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