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