Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / Debug / List / statefunc.s90
1 ///////////////////////////////////////////////////////////////////////////////\r
2 //                                                                            /\r
3 // IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
4 // Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
5 //                                                                            /\r
6 //    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c         /\r
7 //    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c         /\r
8 //                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
9 //                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
10 //                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
11 //                    \List\ --initializers_in_flash -z2 --no_cse             /\r
12 //                    --no_inline --no_code_motion --no_cross_call            /\r
13 //                    --no_clustering --no_tbaa --debug                       /\r
14 //                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
15 //                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
16 //                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
17 //                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
18 //                    --eeprom_size 512                                       /\r
19 //    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\statefun /\r
20 //                    c.s90                                                   /\r
21 //                                                                            /\r
22 //                                                                            /\r
23 ///////////////////////////////////////////////////////////////////////////////\r
24 \r
25         NAME statefunc\r
26 \r
27         RSEG CSTACK:DATA:NOROOT(0)\r
28         RSEG RSTACK:DATA:NOROOT(0)\r
29 \r
30         EXTERN ?EPILOGUE_B2_L09\r
31         EXTERN ?EPILOGUE_B3_L09\r
32         EXTERN ?EPILOGUE_B4_L09\r
33         EXTERN ?PROLOGUE2_L09\r
34         EXTERN ?PROLOGUE3_L09\r
35         EXTERN ?PROLOGUE4_L09\r
36         EXTERN ?SS_DIVMOD_L02\r
37         EXTERN ?S_MUL_L02\r
38         EXTERN ?need_segment_init\r
39         EXTERN __eeget8_16\r
40         EXTERN __eeput8_16\r
41 \r
42         PUBWEAK `?<Segment init: NEAR_Z>`\r
43         PUBLIC BatteryControl\r
44         PUBLIC Discharge\r
45         PUBLIC Doze\r
46         PUBLIC Error\r
47         PUBLIC ErrorFlags\r
48         PUBLIC ErrorState\r
49         PUBLIC Initialize\r
50         PUBLIC JumperCheck\r
51         PUBLIC SetErrorFlag\r
52         PUBLIC `Sleep`\r
53         PUBWEAK _A_ADCSRA\r
54         PUBWEAK _A_CLKPR\r
55         PUBWEAK _A_DDRB\r
56         PUBWEAK _A_MCUCR\r
57         PUBWEAK _A_MCUSR\r
58         PUBWEAK _A_WDTCR\r
59         PUBWEAK __?EEARH\r
60         PUBWEAK __?EEARL\r
61         PUBWEAK __?EECR\r
62         PUBWEAK __?EEDR\r
63 \r
64         EXTERN OWI_Init\r
65         EXTERN DisableBatteries\r
66         EXTERN SPI_Init\r
67         EXTERN ADC_Init\r
68         EXTERN Time_Init\r
69         EXTERN EnableBattery\r
70         EXTERN ADC_Wait\r
71         EXTERN BatteryStatusRefresh\r
72         EXTERN BatteryDataRefresh\r
73         EXTERN PWM_Stop\r
74         EXTERN PWM_Start\r
75         EXTERN Time_Set\r
76         EXTERN abs\r
77         EXTERN PWM_IncrementDutyCycle\r
78         EXTERN Time_Left\r
79         EXTERN ADCS\r
80         EXTERN BattActive\r
81         EXTERN BattControl\r
82         EXTERN BattData\r
83         EXTERN BattEEPROM\r
84         EXTERN CurrentState\r
85 \r
86 // C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c\r
87 //    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
88 //    2 /*! \file *********************************************************************\r
89 //    3  *\r
90 //    4  * \brief\r
91 //    5  *      State functions\r
92 //    6  *\r
93 //    7  *      Contains the functions related to the states defined in menu.h.\n\r
94 //    8  *      Also contains related functions, i.e. for checking jumpers, setting\r
95 //    9  *      error flags and "dozing".\r
96 //   10  *\r
97 //   11  *      \note The state function Charge() is in a separate file since it\r
98 //   12  *      should easily be changed with regard to battery type.\r
99 //   13  *\r
100 //   14  * \par Application note:\r
101 //   15  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
102 //   16  *      AVR463: Charging NiMH Batteries with BC100\r
103 //   17  *\r
104 //   18  * \par Documentation\r
105 //   19  *      For comprehensive code documentation, supported compilers, compiler \r
106 //   20  *      settings and supported devices see readme.html\r
107 //   21  *\r
108 //   22  * \author\r
109 //   23  *      Atmel Corporation: http://www.atmel.com \n\r
110 //   24  *      Support email: avr@atmel.com\r
111 //   25  *\r
112 //   26  * \r
113 //   27  * $Name$\r
114 //   28  * $Revision: 2299 $\r
115 //   29  * $RCSfile$\r
116 //   30  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $\r
117 //   31  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
118 //   32  ******************************************************************************/\r
119 //   33 \r
120 //   34 #include <ioavr.h>\r
121 \r
122         ASEGN ABSOLUTE:DATA:NOROOT,055H\r
123 // <unnamed> volatile __io _A_MCUCR\r
124 _A_MCUCR:\r
125         DS 1\r
126 \r
127         ASEGN ABSOLUTE:DATA:NOROOT,054H\r
128 // <unnamed> volatile __io _A_MCUSR\r
129 _A_MCUSR:\r
130         DS 1\r
131 \r
132         ASEGN ABSOLUTE:DATA:NOROOT,048H\r
133 // <unnamed> volatile __io _A_CLKPR\r
134 _A_CLKPR:\r
135         DS 1\r
136 \r
137         ASEGN ABSOLUTE:DATA:NOROOT,041H\r
138 // <unnamed> volatile __io _A_WDTCR\r
139 _A_WDTCR:\r
140         DS 1\r
141 \r
142         ASEGN ABSOLUTE:DATA:NOROOT,037H\r
143 // <unnamed> volatile __io _A_DDRB\r
144 _A_DDRB:\r
145         DS 1\r
146 \r
147         ASEGN ABSOLUTE:DATA:NOROOT,026H\r
148 // <unnamed> volatile __io _A_ADCSRA\r
149 _A_ADCSRA:\r
150         DS 1\r
151 //   35 #include <inavr.h>\r
152 //   36 #include <stdlib.h>\r
153 //   37 \r
154 //   38 #include "structs.h"\r
155 //   39 #include "enums.h"\r
156 //   40 \r
157 //   41 #include "ADC.h"\r
158 //   42 #include "statefunc.h"\r
159 //   43 #include "battery.h"\r
160 //   44 #include "charge.h"\r
161 //   45 #include "main.h"\r
162 //   46 #include "menu.h"\r
163 //   47 #include "OWI.h"\r
164 //   48 #include "PWM.h"\r
165 //   49 #include "time.h"\r
166 //   50 #include "USI.h"\r
167 //   51 \r
168 //   52 \r
169 //   53 //******************************************************************************\r
170 //   54 // Variables\r
171 //   55 //******************************************************************************\r
172 \r
173         RSEG NEAR_Z:DATA:NOROOT(0)\r
174         REQUIRE `?<Segment init: NEAR_Z>`\r
175 //   56 unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
176 ErrorFlags:\r
177         DS 1\r
178 //   57                            //!< \note See statefunc.h for definitions of flags.\r
179 //   58 \r
180 //   59 //! \brief Holds the state in which latest error flag was set.\r
181 //   60 //! \note See menu.h for definitions of states.\r
182 \r
183         RSEG NEAR_Z:DATA:NOROOT(0)\r
184         REQUIRE `?<Segment init: NEAR_Z>`\r
185 //   61 unsigned char ErrorState;\r
186 ErrorState:\r
187         DS 1\r
188 //   62 \r
189 //   63 \r
190 //   64 //******************************************************************************\r
191 //   65 // Functions\r
192 //   66 //******************************************************************************\r
193 //   67 /*! \brief Initialization\r
194 //   68  *\r
195 //   69  * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
196 //   70  * - Initializes the one-wire interface\r
197 //   71  * - Clears on-chip EEPROM\r
198 //   72  * - Sets battery enable pins as outputs, then disables batteries\r
199 //   73  * - Initializes SPI according to \ref SPIMODE\r
200 //   74  * - Initializes ADC\r
201 //   75  * - Initializes timers\r
202 //   76  * - Reads battery data from both battery inputs (via ADC)\r
203 //   77  * - Disables batteries again\r
204 //   78  * - Sets battery A as the current one (\ref BattActive = 0)\r
205 //   79  * - Clears ErrorFlags\r
206 //   80  *\r
207 //   81  * \param inp Not used.\r
208 //   82  *\r
209 //   83  * \retval ST_BATCON Next state in the sequence.\r
210 //   84  */\r
211 \r
212         RSEG CODE:CODE:NOROOT(1)\r
213 //   85 unsigned char Initialize(unsigned char inp)\r
214 Initialize:\r
215 //   86 {\r
216         RCALL   ?PROLOGUE4_L09\r
217         MOV     R27, R16\r
218 //   87         unsigned char i, page;\r
219 //   88 \r
220 //   89         // Disable interrupts while setting prescaler.\r
221 //   90         __disable_interrupt();\r
222         CLI\r
223 //   91         \r
224 //   92         CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
225         LDI     R16, 128\r
226         OUT     0x28, R16\r
227 //   93         CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
228         LDI     R16, 0\r
229         OUT     0x28, R16\r
230 //   94         \r
231 //   95         // Init 1-Wire(R) interface.\r
232 //   96         OWI_Init(OWIBUS);\r
233         LDI     R16, 1\r
234         RCALL   OWI_Init\r
235 //   97         \r
236 //   98         // Clear on-chip EEPROM.\r
237 //   99         for (page = 0; page < 4; page++)        {\r
238         LDI     R25, 0\r
239 ??Initialize_0:\r
240         CPI     R25, 4\r
241         BRCC    ??Initialize_1\r
242 //  100                 for (i = 0; i < 32; i++) {\r
243         LDI     R24, 0\r
244 ??Initialize_2:\r
245         CPI     R24, 32\r
246         BRCC    ??Initialize_3\r
247 //  101                         BattEEPROM[page][i] = 0;\r
248         LDI     R26, 0\r
249         MOV     R20, R25\r
250         LDI     R21, 0\r
251         LDI     R16, 32\r
252         LDI     R17, 0\r
253         RCALL   ?S_MUL_L02\r
254         LDI     R20, LOW(BattEEPROM)\r
255         LDI     R21, (BattEEPROM) >> 8\r
256         ADD     R20, R16\r
257         ADC     R21, R17\r
258         MOV     R16, R24\r
259         LDI     R17, 0\r
260         ADD     R20, R16\r
261         ADC     R21, R17\r
262         MOV     R16, R26\r
263         RCALL   __eeput8_16\r
264 //  102                 }\r
265         INC     R24\r
266         RJMP    ??Initialize_2\r
267 //  103         }\r
268 ??Initialize_3:\r
269         INC     R25\r
270         RJMP    ??Initialize_0\r
271 //  104 \r
272 //  105         DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
273 ??Initialize_1:\r
274         LDI     R16, 48\r
275         OUT     0x17, R16\r
276 //  106         DisableBatteries();\r
277         RCALL   DisableBatteries\r
278 //  107         SPI_Init(SPIMODE);\r
279         LDI     R16, 0\r
280         RCALL   SPI_Init\r
281 //  108         ADC_Init();\r
282         RCALL   ADC_Init\r
283 //  109         Time_Init();\r
284         RCALL   Time_Init\r
285 //  110 \r
286 //  111         // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
287 //  112         for (i = 0; i < 2; i++) {\r
288         LDI     R24, 0\r
289 ??Initialize_4:\r
290         CPI     R24, 2\r
291         BRCC    ??Initialize_5\r
292 //  113                 EnableBattery(i);\r
293         MOV     R16, R24\r
294         RCALL   EnableBattery\r
295 //  114                 ADC_Wait();\r
296         RCALL   ADC_Wait\r
297 //  115                 BatteryStatusRefresh();\r
298         RCALL   BatteryStatusRefresh\r
299 //  116         }\r
300         INC     R24\r
301         RJMP    ??Initialize_4\r
302 //  117     \r
303 //  118         DisableBatteries();\r
304 ??Initialize_5:\r
305         RCALL   DisableBatteries\r
306 //  119         \r
307 //  120         BattActive = 0;               // We have to start somewhere..\r
308         LDI     R16, 0\r
309         STS     BattActive, R16\r
310 //  121         ErrorFlags = 0;\r
311         LDI     R16, 0\r
312         STS     ErrorFlags, R16\r
313 //  122         \r
314 //  123         // Init complete! Go to ST_BATCON next.\r
315 //  124         return(ST_BATCON);\r
316         LDI     R16, 20\r
317         LDI     R30, 4\r
318         RJMP    ?EPILOGUE_B4_L09\r
319         REQUIRE _A_CLKPR\r
320         REQUIRE _A_DDRB\r
321 //  125 }\r
322 //  126 \r
323 //  127 \r
324 //  128 /*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
325 //  129  *\r
326 //  130  * First, JumperCheck() is called. If successful, the function checks if any\r
327 //  131  * valid batteries are connected and attempts to charge these, if necessary.\n\r
328 //  132  * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
329 //  133  * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
330 //  134  * batteries. In this last case, the error is also flagged.\r
331 //  135  *\r
332 //  136  * \param inp Not used.\r
333 //  137  *\r
334 //  138  * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
335 //  139  * no valid batteries.\r
336 //  140  * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
337 //  141  * charged.\r
338 //  142  * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
339 //  143  * charged.\r
340 //  144  */\r
341 \r
342         RSEG CODE:CODE:NOROOT(1)\r
343 //  145 unsigned char BatteryControl(unsigned char inp)\r
344 BatteryControl:\r
345 //  146 {\r
346         RCALL   ?PROLOGUE3_L09\r
347         MOV     R26, R16\r
348 //  147         unsigned char i;\r
349 //  148         \r
350 //  149         // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
351 //  150         if (!JumperCheck()) {\r
352         RCALL   JumperCheck\r
353         TST     R16\r
354         BRNE    ??BatteryControl_0\r
355 //  151                 return(ST_ERROR);           // Error. Exit before damage is done!\r
356         LDI     R16, 90\r
357         RJMP    ??BatteryControl_1\r
358 //  152         }\r
359 //  153         \r
360 //  154         // If neither battery is valid, flag error and go to error state\r
361 //  155         if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
362 ??BatteryControl_0:\r
363         LDI     R20, LOW(BattControl)\r
364         LDI     R21, (BattControl) >> 8\r
365         RCALL   __eeget8_16\r
366         ANDI    R16, 0x01\r
367         TST     R16\r
368         BRNE    ??BatteryControl_2\r
369         LDI     R20, LOW((BattControl + 1))\r
370         LDI     R21, HIGH((BattControl + 1))\r
371         RCALL   __eeget8_16\r
372         ANDI    R16, 0x01\r
373         TST     R16\r
374         BRNE    ??BatteryControl_2\r
375 //  156                 SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
376         LDI     R16, 2\r
377         RCALL   SetErrorFlag\r
378 //  157                 \r
379 //  158                 return(ST_ERROR);\r
380         LDI     R16, 90\r
381         RJMP    ??BatteryControl_1\r
382 //  159         }\r
383 //  160 \r
384 //  161         // Get ADC-readings, try to read EPROM, and start prequalification\r
385 //  162         // of any uncharged battery.\r
386 //  163         for (i = 0; i < 2; i++) {\r
387 ??BatteryControl_2:\r
388         LDI     R24, 0\r
389 ??BatteryControl_3:\r
390         CPI     R24, 2\r
391         BRCC    ??BatteryControl_4\r
392 //  164                 if (BattControl[i].Enabled) {      \r
393         LDI     R25, 0\r
394         LDI     R20, LOW(BattControl)\r
395         LDI     R21, (BattControl) >> 8\r
396         ADD     R20, R24\r
397         ADC     R21, R25\r
398         RCALL   __eeget8_16\r
399         ANDI    R16, 0x01\r
400         TST     R16\r
401         BREQ    ??BatteryControl_5\r
402 //  165                         EnableBattery(i);\r
403         MOV     R16, R24\r
404         RCALL   EnableBattery\r
405 //  166                         ADC_Wait();\r
406         RCALL   ADC_Wait\r
407 //  167 \r
408 //  168                         if (BatteryStatusRefresh()) {\r
409         RCALL   BatteryStatusRefresh\r
410         TST     R16\r
411         BREQ    ??BatteryControl_5\r
412 //  169                                 if (!BattData.Charged) {\r
413         LDI     R30, LOW(BattData)\r
414         LDI     R31, (BattData) >> 8\r
415         LD      R16, Z\r
416         SBRC    R16, 1\r
417         RJMP    ??BatteryControl_5\r
418 //  170                                         BatteryDataRefresh();\r
419         RCALL   BatteryDataRefresh\r
420 //  171 \r
421 //  172                                         return(ST_PREQUAL);       \r
422         LDI     R16, 30\r
423         RJMP    ??BatteryControl_1\r
424 //  173                                 }\r
425 //  174                         }\r
426 //  175                 }\r
427 //  176         }\r
428 ??BatteryControl_5:\r
429         INC     R24\r
430         RJMP    ??BatteryControl_3\r
431 //  177 \r
432 //  178         // If we end up here, one or two batteries are found and fully charged.\r
433 //  179         // Disconnect, so we don't drain them, and go to sleep.\r
434 //  180         DisableBatteries();\r
435 ??BatteryControl_4:\r
436         RCALL   DisableBatteries\r
437 //  181 \r
438 //  182         return(ST_SLEEP);\r
439         LDI     R16, 40\r
440 ??BatteryControl_1:\r
441         LDI     R30, 3\r
442         RJMP    ?EPILOGUE_B3_L09\r
443 //  183 }\r
444 //  184 \r
445 //  185 \r
446 //  186 /*! \brief Start running on batteries\r
447 //  187  *\r
448 //  188  * \todo Run on batteries, if battery voltage high enough.\r
449 //  189  * \todo Jump here when mains voltage drops below threshold\r
450 //  190  *\r
451 //  191  */\r
452 \r
453         RSEG CODE:CODE:NOROOT(1)\r
454 //  192 unsigned char Discharge(unsigned char inp)\r
455 Discharge:\r
456 //  193 {\r
457         MOV     R17, R16\r
458 //  194         return(ST_BATCON);  // Supply voltage restored, start charging\r
459         LDI     R16, 20\r
460         RET\r
461 //  195 }\r
462 //  196 \r
463 //  197 \r
464 //  198 /*! \brief Sleeps until either battery needs charging\r
465 //  199  *\r
466 //  200  * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
467 //  201  * connected batteries are both charged, the function will loop. If not, it's\r
468 //  202  * back to ST_BATCON.\r
469 //  203  *\r
470 //  204  * \param inp Not used.\r
471 //  205  *\r
472 //  206  * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
473 //  207  */\r
474 \r
475         RSEG CODE:CODE:NOROOT(1)\r
476 //  208 unsigned char Sleep(unsigned char inp)\r
477 `Sleep`:\r
478 //  209 {\r
479         RCALL   ?PROLOGUE2_L09\r
480         MOV     R25, R16\r
481 //  210         unsigned char i;\r
482 //  211 \r
483 //  212         do {\r
484 //  213                 Doze();               // Take a nap (~8 seconds).\r
485 ??Sleep_0:\r
486         RCALL   Doze\r
487 //  214 \r
488 //  215                 // If any batteries need charging, go to ST_BATCON.\r
489 //  216                 // Otherwise, keep sleeping.\r
490 //  217                 for (i = 0; i < 2; i++) {\r
491         LDI     R24, 0\r
492 ??Sleep_1:\r
493         CPI     R24, 2\r
494         BRCC    ??Sleep_2\r
495 //  218                         EnableBattery(i);\r
496         MOV     R16, R24\r
497         RCALL   EnableBattery\r
498 //  219                         ADC_Wait();\r
499         RCALL   ADC_Wait\r
500 //  220                         if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
501         RCALL   BatteryStatusRefresh\r
502         TST     R16\r
503         BREQ    ??Sleep_3\r
504         LDI     R30, LOW(BattData)\r
505         LDI     R31, (BattData) >> 8\r
506         LD      R16, Z\r
507         SBRC    R16, 1\r
508         RJMP    ??Sleep_3\r
509 //  221                                 return(ST_BATCON);\r
510         LDI     R16, 20\r
511         RJMP    ??Sleep_4\r
512 ??Sleep_3:\r
513         INC     R24\r
514         RJMP    ??Sleep_1\r
515 //  222                         }\r
516 //  223                 }\r
517 //  224                 \r
518 //  225                 DisableBatteries();  // Disable both batteries before Doze()!\r
519 ??Sleep_2:\r
520         RCALL   DisableBatteries\r
521 //  226         } while (TRUE);\r
522         RJMP    ??Sleep_0\r
523 ??Sleep_4:\r
524         LDI     R30, 2\r
525         RJMP    ?EPILOGUE_B2_L09\r
526 //  227 }\r
527 //  228 \r
528 //  229 \r
529 //  230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
530 //  231  *\r
531 //  232  * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
532 //  233  * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
533 //  234  * On wakeup, ADC is re-enabled.\r
534 //  235  */\r
535 \r
536         RSEG CODE:CODE:NOROOT(1)\r
537 //  236 void Doze(void)\r
538 Doze:\r
539 //  237 {\r
540 //  238         // Wait for this ADC cycle to complete, then halt after the next one.\r
541 //  239         ADC_Wait();\r
542         RCALL   ADC_Wait\r
543 //  240         ADCS.Halt = TRUE;\r
544         LDI     R30, LOW(ADCS)\r
545         LDI     R31, (ADCS) >> 8\r
546         LD      R16, Z\r
547         ORI     R16, 0x80\r
548         ST      Z, R16\r
549 //  241         ADCS.Flag = FALSE;\r
550         LDI     R30, LOW(ADCS)\r
551         LDI     R31, (ADCS) >> 8\r
552         LD      R16, Z\r
553         ANDI    R16, 0xDF\r
554         ST      Z, R16\r
555 //  242         \r
556 //  243         do {\r
557 //  244         } while (ADCS.Flag == FALSE);    \r
558 ??Doze_0:\r
559         LDI     R30, LOW(ADCS)\r
560         LDI     R31, (ADCS) >> 8\r
561         LD      R16, Z\r
562         SBRS    R16, 5\r
563         RJMP    ??Doze_0\r
564 //  245         \r
565 //  246         WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
566         LDI     R16, 33\r
567         OUT     0x21, R16\r
568 //  247         WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
569         IN      R16, 0x21\r
570         ORI     R16, 0xC8\r
571         OUT     0x21, R16\r
572 //  248         MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
573         IN      R16, 0x35\r
574         ORI     R16, 0x38\r
575         OUT     0x35, R16\r
576 //  249         __sleep();                              // Go to sleep, wake up by WDT.\r
577         SLEEP\r
578 //  250         \r
579 //  251         __watchdog_reset();                     // Clear watchdog reset flag.\r
580         WDR\r
581 //  252         MCUSR &= ~(1<<WDRF);          \r
582         IN      R16, 0x34\r
583         ANDI    R16, 0xF7\r
584         OUT     0x34, R16\r
585 //  253         WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
586         IN      R16, 0x21\r
587         ORI     R16, 0x18\r
588         OUT     0x21, R16\r
589 //  254         WDTCR = 0;                              // Turn off watchdog.\r
590         LDI     R16, 0\r
591         OUT     0x21, R16\r
592 //  255         \r
593 //  256         ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
594         LDI     R30, LOW(ADCS)\r
595         LDI     R31, (ADCS) >> 8\r
596         LD      R16, Z\r
597         ANDI    R16, 0x7F\r
598         ST      Z, R16\r
599 //  257         ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
600         IN      R16, 0x06\r
601         ORI     R16, 0xC0\r
602         OUT     0x06, R16\r
603 //  258         \r
604 //  259         // Wait for this cycle to complete.\r
605 //  260         ADC_Wait();                             \r
606         RCALL   ADC_Wait\r
607 //  261 }\r
608         RET\r
609         REQUIRE _A_MCUCR\r
610         REQUIRE _A_MCUSR\r
611         REQUIRE _A_WDTCR\r
612         REQUIRE _A_ADCSRA\r
613 //  262 \r
614 //  263 \r
615 //  264 /*! \brief Handles errors\r
616 //  265  *\r
617 //  266  * Stops PWM output and disables batteries. The function then goes into a loop\r
618 //  267  * that starts with a call to Doze(), then attempts to handle each error. The\r
619 //  268  * loop will reiterate until all flags are cleared.\n\r
620 //  269  * The charger will reinitialize after this.\r
621 //  270  *\r
622 //  271  * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
623 //  272  * If unsuccessful, the error flag will now have been set again.\n\r
624 //  273  *\r
625 //  274  * If there are no valid batteries, the loop will simply reiterate until a\r
626 //  275  * valid battery is found. The error flag will then be cleared.\n\r
627 //  276  *\r
628 //  277  * In the case of PWM controller or battery temperature errors, the error\r
629 //  278  * flag is simply cleared. This is because the problem may have gone away during\r
630 //  279  * Doze(), or after reinitializing.\n\r
631 //  280  *\r
632 //  281  * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
633 //  282  * and change batteries before clearing the error flag.\r
634 //  283  *\r
635 //  284  * \param inp Not used.\r
636 //  285  */\r
637 \r
638         RSEG CODE:CODE:NOROOT(1)\r
639 //  286 unsigned char Error(unsigned char inp)\r
640 Error:\r
641 //  287         {\r
642         RCALL   ?PROLOGUE2_L09\r
643         MOV     R25, R16\r
644 //  288         unsigned char i;\r
645 //  289         \r
646 //  290         PWM_Stop();           // Stop charging.\r
647         RCALL   PWM_Stop\r
648 //  291         DisableBatteries();   // Disable all loads.\r
649         RCALL   DisableBatteries\r
650 //  292         \r
651 //  293         do {\r
652 //  294                 Doze();           // Take a nap.\r
653 ??Error_0:\r
654         RCALL   Doze\r
655 //  295 \r
656 //  296                 // For each bit in ErrorFlags, starting with LSB, handle\r
657 //  297                 // associated error, if the flag is set.\r
658 //  298                 for (i = 0x01; i!=0; i<<=1) {\r
659         LDI     R24, 1\r
660 ??Error_1:\r
661         TST     R24\r
662         BRNE    $+2+2\r
663         RJMP    ??Error_2\r
664 //  299                         if(i & ErrorFlags) {\r
665         LDS     R16, ErrorFlags\r
666         AND     R16, R24\r
667         TST     R16\r
668         BRNE    $+2+2\r
669         RJMP    ??Error_3\r
670 //  300                                 switch (i) {\r
671         MOV     R16, R24\r
672         SUBI    R16, 1\r
673         BREQ    ??Error_4\r
674         DEC     R16\r
675         BREQ    ??Error_5\r
676         SUBI    R16, 2\r
677         BREQ    ??Error_6\r
678         SUBI    R16, 4\r
679         BREQ    ??Error_7\r
680         SUBI    R16, 8\r
681         BREQ    ??Error_8\r
682         RJMP    ??Error_3\r
683 //  301                                 \r
684 //  302                                 case  ERR_JUMPER_MISMATCH:\r
685 //  303                                         // Clear flag & recheck.\r
686 //  304                                         ErrorFlags &= ~i;\r
687 ??Error_4:\r
688         MOV     R16, R24\r
689         COM     R16\r
690         LDI     R30, LOW(ErrorFlags)\r
691         LDI     R31, (ErrorFlags) >> 8\r
692         LD      R17, Z\r
693         AND     R17, R16\r
694         ST      Z, R17\r
695 //  305                                         JumperCheck();\r
696         RCALL   JumperCheck\r
697         RJMP    ??Error_3\r
698 //  306                                 break;\r
699 //  307 \r
700 //  308 \r
701 //  309                                 case  ERR_NO_BATTERIES_ENABLED:\r
702 //  310                                         // Clear if any battery gets enabled.\r
703 //  311                                         if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {\r
704 ??Error_5:\r
705         LDI     R20, LOW(BattControl)\r
706         LDI     R21, (BattControl) >> 8\r
707         RCALL   __eeget8_16\r
708         ANDI    R16, 0x01\r
709         TST     R16\r
710         BRNE    ??Error_9\r
711         LDI     R20, LOW((BattControl + 1))\r
712         LDI     R21, HIGH((BattControl + 1))\r
713         RCALL   __eeget8_16\r
714         ANDI    R16, 0x01\r
715         TST     R16\r
716         BREQ    ??Error_3\r
717 //  312                                                         ErrorFlags &= ~i;\r
718 ??Error_9:\r
719         MOV     R16, R24\r
720         COM     R16\r
721         LDI     R30, LOW(ErrorFlags)\r
722         LDI     R31, (ErrorFlags) >> 8\r
723         LD      R17, Z\r
724         AND     R17, R16\r
725         ST      Z, R17\r
726         RJMP    ??Error_3\r
727 //  313                                         }\r
728 //  314                                 break;\r
729 //  315 \r
730 //  316 \r
731 //  317                                 case  ERR_PWM_CONTROL:\r
732 //  318                                         // Clear flag.\r
733 //  319                                         ErrorFlags &= ~i;\r
734 ??Error_6:\r
735         MOV     R16, R24\r
736         COM     R16\r
737         LDI     R30, LOW(ErrorFlags)\r
738         LDI     R31, (ErrorFlags) >> 8\r
739         LD      R17, Z\r
740         AND     R17, R16\r
741         ST      Z, R17\r
742         RJMP    ??Error_3\r
743 //  320                                 break;\r
744 //  321 \r
745 //  322 \r
746 //  323                                 case  ERR_BATTERY_TEMPERATURE:\r
747 //  324                                         // Clear flag.\r
748 //  325                                         ErrorFlags &= ~i;\r
749 ??Error_7:\r
750         MOV     R16, R24\r
751         COM     R16\r
752         LDI     R30, LOW(ErrorFlags)\r
753         LDI     R31, (ErrorFlags) >> 8\r
754         LD      R17, Z\r
755         AND     R17, R16\r
756         ST      Z, R17\r
757         RJMP    ??Error_3\r
758 //  326                                 break;\r
759 //  327 \r
760 //  328 \r
761 //  329                                 case  ERR_BATTERY_EXHAUSTED:\r
762 //  330                                         // Try the other battery.\r
763 //  331                                         BattData.Exhausted = FALSE;\r
764 ??Error_8:\r
765         LDI     R30, LOW(BattData)\r
766         LDI     R31, (BattData) >> 8\r
767         LD      R16, Z\r
768         ANDI    R16, 0xF7\r
769         ST      Z, R16\r
770 //  332                                         BattActive = (BattActive + 1) % 2;\r
771         LDS     R30, BattActive\r
772         LDI     R31, 0\r
773         ADIW    R31:R30, 1\r
774         MOVW    R17:R16, R31:R30\r
775         LDI     R20, 2\r
776         LDI     R21, 0\r
777         RCALL   ?SS_DIVMOD_L02\r
778         STS     BattActive, R20\r
779 //  333                                         ErrorFlags &= ~i;\r
780         MOV     R16, R24\r
781         COM     R16\r
782         LDI     R30, LOW(ErrorFlags)\r
783         LDI     R31, (ErrorFlags) >> 8\r
784         LD      R17, Z\r
785         AND     R17, R16\r
786         ST      Z, R17\r
787 //  334                                 break;\r
788 //  335 \r
789 //  336                                         \r
790 //  337                                 default:\r
791 //  338                                 break;\r
792 //  339                                 }\r
793 //  340                         }\r
794 //  341                 }\r
795 ??Error_3:\r
796         LSL     R24\r
797         RJMP    ??Error_1\r
798 //  342         } while (ErrorFlags);\r
799 ??Error_2:\r
800         LDS     R16, ErrorFlags\r
801         TST     R16\r
802         BREQ    $+2+2\r
803         RJMP    ??Error_0\r
804 //  343 \r
805 //  344         return(ST_INIT);\r
806         LDI     R16, 10\r
807         LDI     R30, 2\r
808         RJMP    ?EPILOGUE_B2_L09\r
809 //  345 }\r
810 //  346 \r
811 //  347 \r
812 //  348 /*! \brief Sets the specified error-flag and saves the current state\r
813 //  349  *\r
814 //  350  * Updates \ref ErrorFlags and \ref ErrorState.\r
815 //  351  *\r
816 //  352  * \note Error flags are specified in statefunc.h.\r
817 //  353  *\r
818 //  354  * \param Flag Specifies what error to flag.\r
819 //  355  */\r
820 \r
821         RSEG CODE:CODE:NOROOT(1)\r
822 //  356 void SetErrorFlag(unsigned char Flag)\r
823 SetErrorFlag:\r
824 //  357 {\r
825 //  358         ErrorFlags |= Flag;\r
826         LDI     R30, LOW(ErrorFlags)\r
827         LDI     R31, (ErrorFlags) >> 8\r
828         LD      R17, Z\r
829         OR      R17, R16\r
830         ST      Z, R17\r
831 //  359         ErrorState = CurrentState;\r
832         LDS     R17, CurrentState\r
833         STS     ErrorState, R17\r
834 //  360 }\r
835         RET\r
836 //  361 \r
837 //  362 \r
838 //  363 /*! \brief Checks on-board jumpers.\r
839 //  364  *\r
840 //  365  * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
841 //  366  * increasing the duty cycle until conditioned output voltage equals conditioned\r
842 //  367  * input voltage. At low PWM duty and no load buck output should be zero and,\r
843 //  368  * when increasing PWM duty, should quickly jump to steady state output roughly\r
844 //  369  * equal to input voltage. Will disable and leave disabled all batteries.\r
845 //  370  *\r
846 //  371  * \retval FALSE If jumper or load mismatch.\r
847 //  372  * \retval TRUE If everything OK.\r
848 //  373  */\r
849 \r
850         RSEG CODE:CODE:NOROOT(1)\r
851 //  374 unsigned char JumperCheck(void)\r
852 JumperCheck:\r
853 //  375 {\r
854 //  376          DisableBatteries();       // Disconnect, or loads may be destroyed!\r
855         RCALL   DisableBatteries\r
856 //  377          \r
857 //  378          PWM_Start();              // Start PWM (controls the buck charger).\r
858         RCALL   PWM_Start\r
859 //  379         \r
860 //  380          // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
861 //  381          Time_Set(TIMER_GEN,0,1,0);\r
862         LDI     R20, 0\r
863         LDI     R17, 1\r
864         LDI     R18, 0\r
865         LDI     R19, 0\r
866         LDI     R16, 2\r
867         RCALL   Time_Set\r
868 //  382         \r
869 //  383         do {\r
870 //  384                 // If the PWM output voltage saturates the ADC, stop PWM output and\r
871 //  385                 // report a failure.\r
872 //  386                 if (ADCS.rawVBAT == 1023) {\r
873 ??JumperCheck_0:\r
874         LDI     R30, LOW(ADCS)\r
875         LDI     R31, (ADCS) >> 8\r
876         LDD     R16, Z+6\r
877         LDD     R17, Z+7\r
878         CPI     R16, 255\r
879         LDI     R18, 3\r
880         CPC     R17, R18\r
881         BRNE    ??JumperCheck_1\r
882 //  387                         PWM_Stop();\r
883         RCALL   PWM_Stop\r
884 //  388                         return(FALSE);\r
885         LDI     R16, 0\r
886         RET\r
887 //  389                 }\r
888 //  390 \r
889 //  391                 // If the absolute difference between measured (VIN - VBAT) and the\r
890 //  392                 // typical value are below our set maximum, everything is OK.\r
891 //  393                 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
892 //  394                                      VIN_VBAT_DIFF_MAX ) {\r
893 ??JumperCheck_1:\r
894         LDI     R30, LOW(ADCS)\r
895         LDI     R31, (ADCS) >> 8\r
896         LDD     R16, Z+8\r
897         LDD     R17, Z+9\r
898         SUBI    R16, 88\r
899         SBCI    R17, 2\r
900         LDI     R30, LOW(ADCS)\r
901         LDI     R31, (ADCS) >> 8\r
902         LDD     R18, Z+10\r
903         LDD     R19, Z+11\r
904         SUB     R16, R18\r
905         SBC     R17, R19\r
906         RCALL   abs\r
907         CPI     R16, 244\r
908         LDI     R18, 1\r
909         CPC     R17, R18\r
910         BRGE    ??JumperCheck_2\r
911 //  395                                  \r
912 //  396                         PWM_Stop();\r
913         RCALL   PWM_Stop\r
914 //  397                         return(TRUE);\r
915         LDI     R16, 1\r
916         RET\r
917 //  398                 }\r
918 //  399 \r
919 //  400                 // Charge current is too high -> check load and jumper J405 and J406.\r
920 //  401                 if (abs(ADCS.IBAT) > 100) {\r
921 ??JumperCheck_2:\r
922         LDI     R30, LOW(ADCS)\r
923         LDI     R31, (ADCS) >> 8\r
924         LDD     R16, Z+12\r
925         LDD     R17, Z+13\r
926         RCALL   abs\r
927         CPI     R16, 101\r
928         LDI     R18, 0\r
929         CPC     R17, R18\r
930         BRLT    ??JumperCheck_3\r
931 //  402                         PWM_Stop();\r
932         RCALL   PWM_Stop\r
933 //  403                         return(FALSE);\r
934         LDI     R16, 0\r
935         RET\r
936 //  404                 }\r
937 //  405 \r
938 //  406                 // If the PWM output can't be increased high enough -> check jumpers\r
939 //  407                 // J400-J404, J407 and J408.\r
940 //  408                 if (!PWM_IncrementDutyCycle()) {\r
941 ??JumperCheck_3:\r
942         RCALL   PWM_IncrementDutyCycle\r
943         TST     R16\r
944         BRNE    ??JumperCheck_4\r
945 //  409                         PWM_Stop();\r
946         RCALL   PWM_Stop\r
947 //  410                         return(FALSE);\r
948         LDI     R16, 0\r
949         RET\r
950 //  411                 }\r
951 //  412                 \r
952 //  413       // Wait for ADC conversions to complete\r
953 //  414                 ADC_Wait();\r
954 ??JumperCheck_4:\r
955         RCALL   ADC_Wait\r
956 //  415         } while (Time_Left(TIMER_GEN));\r
957         LDI     R16, 2\r
958         RCALL   Time_Left\r
959         TST     R16\r
960         BRNE    ??JumperCheck_0\r
961 //  416         \r
962 //  417 \r
963 //  418         // If we end up here, the measurements took too long.\r
964 //  419         PWM_Stop();\r
965         RCALL   PWM_Stop\r
966 //  420         return(FALSE);\r
967         LDI     R16, 0\r
968         RET\r
969 //  421 }\r
970 \r
971         ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
972 __?EECR:\r
973 \r
974         ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
975 __?EEDR:\r
976 \r
977         ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
978 __?EEARL:\r
979 \r
980         ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
981 __?EEARH:\r
982 \r
983         RSEG INITTAB:CODE:NOROOT(0)\r
984 `?<Segment init: NEAR_Z>`:\r
985         DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
986         DW      SFB(NEAR_Z)\r
987         DW      0\r
988         REQUIRE ?need_segment_init\r
989 \r
990         END\r
991 // \r
992 //   6 bytes in segment ABSOLUTE\r
993 // 734 bytes in segment CODE\r
994 //   6 bytes in segment INITTAB\r
995 //   2 bytes in segment NEAR_Z\r
996 // \r
997 // 734 bytes of CODE memory (+ 6 bytes shared)\r
998 //   2 bytes of DATA memory (+ 6 bytes shared)\r
999 //\r
1000 //Errors: none\r
1001 //Warnings: none\r