Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / Release / List / ADC.lst
1 ###############################################################################\r
2 #                                                                             #\r
3 # IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:49:35 #\r
4 # Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
5 #                                                                             #\r
6 #    Source file           =  C:\home\kevin\pub\src\bc100\IAR\ADC.c           #\r
7 #    Command line          =  C:\home\kevin\pub\src\bc100\IAR\ADC.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\AD #\r
32 #                             C.lst                                           #\r
33 #    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC #\r
34 #                             .r90                                            #\r
35 #                                                                             #\r
36 #                                                                             #\r
37 ###############################################################################\r
38 \r
39 C:\home\kevin\pub\src\bc100\IAR\ADC.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           *      Functions for use of ADC\r
45       6           *\r
46       7           *      Contains high level functions for initializing the ADC, interrupt\r
47       8           *      handling, and treatment of samples.\n\r
48       9           *      The ADC is set to free running mode and uses an external reference\r
49      10           *      voltage.\n\r
50      11           *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
51      12           *      and restarted by the ISR.\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 \n\r
64      25           *      Original author: \n\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/ADC.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 0x3b\r
76    \   <unnamed> volatile __io _A_PORTA\r
77    \                     _A_PORTA:\r
78    \   00000000                      DS 1\r
79 \r
80    \                                 In  segment ABSOLUTE, at 0x3a\r
81    \   <unnamed> volatile __io _A_DDRA\r
82    \                     _A_DDRA:\r
83    \   00000000                      DS 1\r
84 \r
85    \                                 In  segment ABSOLUTE, at 0x27\r
86    \   <unnamed> volatile __io _A_ADMUX\r
87    \                     _A_ADMUX:\r
88    \   00000000                      DS 1\r
89 \r
90    \                                 In  segment ABSOLUTE, at 0x26\r
91    \   <unnamed> volatile __io _A_ADCSRA\r
92    \                     _A_ADCSRA:\r
93    \   00000000                      DS 1\r
94 \r
95    \                                 In  segment ABSOLUTE, at 0x24\r
96    \   <unnamed> volatile __io _A_ADC\r
97    \                     _A_ADC:\r
98    \   00000000                      DS 2\r
99 \r
100    \                                 In  segment ABSOLUTE, at 0x23\r
101    \   <unnamed> volatile __io _A_ADCSRB\r
102    \                     _A_ADCSRB:\r
103    \   00000000                      DS 1\r
104      35          #include <inavr.h>\r
105      36          \r
106      37          #include "structs.h"\r
107      38          \r
108      39          #include "main.h"\r
109      40          #include "ADC.h"\r
110      41          \r
111      42          \r
112      43          //******************************************************************************\r
113      44          // Variables\r
114      45          //******************************************************************************\r
115      46          // ADC status struct.\r
116      47          //! \brief Holds sampled data and ADC-status\r
117      48          ADC_Status_t ADCS;\r
118      49          \r
119      50          \r
120      51          /*! \brief Indicates maximum battery voltage.\r
121      52           *\r
122      53           * This variable is stored in EEPROM and indicates how much the battery voltage\r
123      54           * is downscaled by HW before it is sampled. The amount of downscaling depends\r
124      55           * on the maximum battery voltage, and is necessary to avoid saturation of the\r
125      56           * ADC (reference voltage is 2.5 V).\r
126      57           *\r
127      58           * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
128      59           *\r
129      60           * \note Defaults to 1, which means 10 V max battery voltage.\r
130      61           *\r
131      62           * \note Table of settings:\r
132      63           * <pre>\r
133      64           * VBAT_RANGE | Max battery voltage | Jumper setting\r
134      65           *         0  |             5V      |        1/2\r
135      66           *         1  |            10V      |        1/4\r
136      67           *         2  |            20V      |        1/8\r
137      68           *         3  |            30V      |       1/12\r
138      69           *         4  |            40V      |       1/16\r
139      70           * </pre>\r
140      71           */\r
141      72          // Maximum battery voltage (affects scaling of samples).\r
142 \r
143    \                                 In  segment EEPROM_I, align 1, keep-with-next\r
144      73          __eeprom unsigned char VBAT_RANGE = 1;\r
145    \                     VBAT_RANGE:\r
146    \   00000000   01                 DB 1\r
147      74          \r
148      75          \r
149      76          //******************************************************************************\r
150      77          // Functions\r
151      78          //******************************************************************************\r
152      79          /*! \brief Interrupt Service routine for ADC.\r
153      80           *\r
154      81           * This ISR stores the sampled values in the ADC status-struct, then\r
155      82           * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
156      83           * Once the sequence is completed, ADCS.Flag is set and unless\r
157      84           * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
158      85           * is disabled.\n\r
159      86           * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
160      87           *\r
161      88           * \note Table of scanning sequence:\r
162      89           * <pre>\r
163      90           * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
164      91           * ----+--------+----------+----------+------+---------+-------\r
165      92           *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
166      93           *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
167      94           *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
168      95           *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
169      96           *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
170      97           *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
171      98           *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
172      99           *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
173     100           * </pre>\r
174     101           *\r
175     102           * \todo IIN (#7 in sequence) is never used.\r
176     103           *\r
177     104           * \todo Signed is never set. Signed measurements of IBAT will halve the\r
178     105           * measuring sensitivity, and is therefore not favourable. At the moment,\r
179     106           * great currents (f.ex. if something happens with the battery) will be\r
180     107           * interpreted as negative, which might cause unfavourable behaviour during\r
181     108           * charging (depending on what PWM behaviour is defined), f.ex.\r
182     109           * ConstantCurrent() will keep increasing the PWM output. This results in an\r
183     110           * PWM controller error being flagged and the program going into\r
184     111           * error-state and eventually reinitializing.\r
185     112           */\r
186     113          #pragma vector=ADC_vect\r
187 \r
188    \                                 In  segment CODE, align 2, keep-with-next\r
189     114          __interrupt void ADC_ISR(void)\r
190    \                     ADC_ISR:\r
191     115          {\r
192    \   00000000   924A               ST      -Y, R4\r
193    \   00000002   93BA               ST      -Y, R27\r
194    \   00000004   93AA               ST      -Y, R26\r
195    \   00000006   939A               ST      -Y, R25\r
196    \   00000008   938A               ST      -Y, R24\r
197    \   0000000A   93FA               ST      -Y, R31\r
198    \   0000000C   93EA               ST      -Y, R30\r
199    \   0000000E   923A               ST      -Y, R3\r
200    \   00000010   922A               ST      -Y, R2\r
201    \   00000012   921A               ST      -Y, R1\r
202    \   00000014   920A               ST      -Y, R0\r
203    \   00000016   937A               ST      -Y, R23\r
204    \   00000018   936A               ST      -Y, R22\r
205    \   0000001A   935A               ST      -Y, R21\r
206    \   0000001C   934A               ST      -Y, R20\r
207    \   0000001E   933A               ST      -Y, R19\r
208    \   00000020   932A               ST      -Y, R18\r
209    \   00000022   931A               ST      -Y, R17\r
210    \   00000024   930A               ST      -Y, R16\r
211    \   00000026   B64F               IN      R4, 0x3F\r
212    \   00000028                      REQUIRE ?Register_R4_is_cg_reg\r
213     116                 static unsigned char avgIndex = 0;\r
214     117                 unsigned char i, Next, Signed;\r
215     118                 signed int  temp = 0;\r
216    \   00000028   E080               LDI     R24, 0\r
217    \   0000002A   E090               LDI     R25, 0\r
218     119                 \r
219     120                 Signed = FALSE;  // Presume next conversion is unipolar.\r
220     121                 ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
221    \   0000002C   9837               CBI     0x06, 0x07\r
222     122                   // conversions take at least 25 ADCCLK. (It is restarted later)\r
223     123                 \r
224     124                 // Handle the conversion, depending on what channel it is from, then\r
225     125                 // switch to the next channel in the sequence.\r
226     126                 switch (ADCS.MUX){\r
227    \   0000002E   ....               LDI     R26, LOW(ADCS)\r
228    \   00000030   ....               LDI     R27, (ADCS) >> 8\r
229    \   00000032   910C               LD      R16, X\r
230    \   00000034   710F               ANDI    R16, 0x1F\r
231    \   00000036   950A               DEC     R16\r
232    \   00000038   F049               BREQ    ??ADC_ISR_0\r
233    \   0000003A   950A               DEC     R16\r
234    \   0000003C   F071               BREQ    ??ADC_ISR_1\r
235    \   0000003E   950A               DEC     R16\r
236    \   00000040   F099               BREQ    ??ADC_ISR_2\r
237    \   00000042   5002               SUBI    R16, 2\r
238    \   00000044   F111               BREQ    ??ADC_ISR_3\r
239    \   00000046   5102               SUBI    R16, 18\r
240    \   00000048   F181               BREQ    ??ADC_ISR_4\r
241    \   0000004A   C07E               RJMP    ??ADC_ISR_5\r
242     127                         // MUX = 0b000001 => ADC1 (PA1) = NTC\r
243     128                         case 0x01:\r
244     129                                 ADCS.rawNTC = ADC;\r
245    \                     ??ADC_ISR_0:\r
246    \   0000004C   B104               IN      R16, 0x04\r
247    \   0000004E   B115               IN      R17, 0x05\r
248    \   00000050   01FD               MOVW    R31:R30, R27:R26\r
249    \   00000052   8304               STD     Z+4, R16\r
250    \   00000054   8315               STD     Z+5, R17\r
251     130                                 Next=0x02;\r
252    \   00000056   E002               LDI     R16, 2\r
253    \   00000058   C078               RJMP    ??ADC_ISR_6\r
254     131                         break;\r
255     132          \r
256     133                         \r
257     134                         // MUX = 0b000010 => ADC2 (PA2) = RID\r
258     135                         case 0x02:\r
259     136                                 ADCS.rawRID = ADC;\r
260    \                     ??ADC_ISR_1:\r
261    \   0000005A   B104               IN      R16, 0x04\r
262    \   0000005C   B115               IN      R17, 0x05\r
263    \   0000005E   01FD               MOVW    R31:R30, R27:R26\r
264    \   00000060   8302               STD     Z+2, R16\r
265    \   00000062   8313               STD     Z+3, R17\r
266     137                                 Next=0x03;\r
267    \   00000064   E003               LDI     R16, 3\r
268    \   00000066   C071               RJMP    ??ADC_ISR_6\r
269     138                         break;\r
270     139          \r
271     140                         \r
272     141                         // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
273     142                         case 0x03:\r
274     143                                 // Supply voltage is always divided by 16.\r
275     144                                 ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
276    \                     ??ADC_ISR_2:\r
277    \   00000068   B124               IN      R18, 0x04\r
278    \   0000006A   B135               IN      R19, 0x05\r
279    \   0000006C   E004               LDI     R16, 4\r
280    \   0000006E   ....               RCALL   ScaleU\r
281    \   00000070   01FD               MOVW    R31:R30, R27:R26\r
282    \   00000072   8700               STD     Z+8, R16\r
283    \   00000074   8711               STD     Z+9, R17\r
284     145                                 \r
285     146                                 // Is mains failing?\r
286     147                                 if (ADCS.VIN < VIN_MIN) {\r
287    \   00000076   3300               CPI     R16, 48\r
288    \   00000078   4111               SBCI    R17, 17\r
289    \   0000007A   910C               LD      R16, X\r
290    \   0000007C   F410               BRCC    ??ADC_ISR_7\r
291     148                                         ADCS.Mains = FALSE;\r
292    \   0000007E   7B0F               ANDI    R16, 0xBF\r
293    \   00000080   C001               RJMP    ??ADC_ISR_8\r
294     149                                 } else {\r
295     150                                         ADCS.Mains = TRUE;\r
296    \                     ??ADC_ISR_7:\r
297    \   00000082   6400               ORI     R16, 0x40\r
298    \                     ??ADC_ISR_8:\r
299    \   00000084   930C               ST      X, R16\r
300     151                                 }\r
301     152                                 \r
302     153                                 Next=0x05;\r
303    \   00000086   E005               LDI     R16, 5\r
304    \   00000088   C060               RJMP    ??ADC_ISR_6\r
305     154                         break;\r
306     155          \r
307     156                         \r
308     157                         // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
309     158                         case 0x05:\r
310     159                                 ADCS.rawVBAT = ADC;\r
311    \                     ??ADC_ISR_3:\r
312    \   0000008A   B104               IN      R16, 0x04\r
313    \   0000008C   B115               IN      R17, 0x05\r
314    \   0000008E   01FD               MOVW    R31:R30, R27:R26\r
315    \   00000090   8306               STD     Z+6, R16\r
316    \   00000092   8317               STD     Z+7, R17\r
317     160                                 \r
318     161                                 // Scale voltage according to jumper setting.\r
319     162                                 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
320    \   00000094   B124               IN      R18, 0x04\r
321    \   00000096   B135               IN      R19, 0x05\r
322    \   00000098   ....               LDI     R20, LOW(VBAT_RANGE)\r
323    \   0000009A   ....               LDI     R21, (VBAT_RANGE) >> 8\r
324    \   0000009C   ....               RCALL   __eeget8_16\r
325    \   0000009E   ....               RCALL   ScaleU\r
326    \   000000A0   01FD               MOVW    R31:R30, R27:R26\r
327    \   000000A2   8702               STD     Z+10, R16\r
328    \   000000A4   8713               STD     Z+11, R17\r
329     163                                 Next=0x17;\r
330    \   000000A6   E107               LDI     R16, 23\r
331    \   000000A8   C050               RJMP    ??ADC_ISR_6\r
332     164          //                     Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
333     165                         break;\r
334     166          \r
335     167          \r
336     168                         case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
337     169                                 // If bipolar, from -512 to 0, to 511:\r
338     170                                 // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
339     171                         \r
340     172                                 // Scale sample according to jumper setting, handle negative numbers.\r
341     173                                 if (ADC > 511) {\r
342    \                     ??ADC_ISR_4:\r
343    \   000000AA   B104               IN      R16, 0x04\r
344    \   000000AC   B115               IN      R17, 0x05\r
345    \   000000AE   3012               CPI     R17, 2\r
346    \   000000B0   F0C0               BRCS    ??ADC_ISR_9\r
347     174                                         ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
348     175                                                      (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
349    \   000000B2   E000               LDI     R16, 0\r
350    \   000000B4   E014               LDI     R17, 4\r
351    \   000000B6   B124               IN      R18, 0x04\r
352    \   000000B8   B135               IN      R19, 0x05\r
353    \   000000BA   1B02               SUB     R16, R18\r
354    \   000000BC   0B13               SBC     R17, R19\r
355    \   000000BE   01FD               MOVW    R31:R30, R27:R26\r
356    \   000000C0   8121               LDD     R18, Z+1\r
357    \   000000C2   9522               SWAP    R18\r
358    \   000000C4   702F               ANDI    R18, 0x0F\r
359    \   000000C6   E030               LDI     R19, 0\r
360    \   000000C8   0F20               ADD     R18, R16\r
361    \   000000CA   1F31               ADC     R19, R17\r
362    \   000000CC   ....               LDI     R20, LOW(VBAT_RANGE)\r
363    \   000000CE   ....               LDI     R21, (VBAT_RANGE) >> 8\r
364    \   000000D0   ....               RCALL   __eeget8_16\r
365    \   000000D2   ....               RCALL   ScaleI\r
366    \   000000D4   9511               NEG     R17\r
367    \   000000D6   9501               NEG     R16\r
368    \   000000D8   4010               SBCI    R17, 0\r
369    \                     ??ADC_ISR_10:\r
370    \   000000DA   01FD               MOVW    R31:R30, R27:R26\r
371    \   000000DC   8704               STD     Z+12, R16\r
372    \   000000DE   8715               STD     Z+13, R17\r
373    \   000000E0   C014               RJMP    ??ADC_ISR_11\r
374     176                                 } else if (ADC > 0) {\r
375    \                     ??ADC_ISR_9:\r
376    \   000000E2   B104               IN      R16, 0x04\r
377    \   000000E4   B115               IN      R17, 0x05\r
378    \   000000E6   2B01               OR      R16, R17\r
379    \   000000E8   F069               BREQ    ??ADC_ISR_12\r
380     177                                         ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
381    \   000000EA   B124               IN      R18, 0x04\r
382    \   000000EC   B135               IN      R19, 0x05\r
383    \   000000EE   01FD               MOVW    R31:R30, R27:R26\r
384    \   000000F0   8101               LDD     R16, Z+1\r
385    \   000000F2   9502               SWAP    R16\r
386    \   000000F4   700F               ANDI    R16, 0x0F\r
387    \   000000F6   1B20               SUB     R18, R16\r
388    \   000000F8   4030               SBCI    R19, 0\r
389    \   000000FA   ....               LDI     R20, LOW(VBAT_RANGE)\r
390    \   000000FC   ....               LDI     R21, (VBAT_RANGE) >> 8\r
391    \   000000FE   ....               RCALL   __eeget8_16\r
392    \   00000100   ....               RCALL   ScaleI\r
393    \   00000102   CFEB               RJMP    ??ADC_ISR_10\r
394     178                                 } else {\r
395     179                                         ADCS.IBAT = 0;\r
396    \                     ??ADC_ISR_12:\r
397    \   00000104   01FD               MOVW    R31:R30, R27:R26\r
398    \   00000106   8784               STD     Z+12, R24\r
399    \   00000108   8785               STD     Z+13, R24\r
400     180                                 }\r
401     181          \r
402     182                                 // Insert sample of battery current into the averaging-array\r
403     183                                 // (overwriting the oldest sample), then recalculate and store the\r
404     184                                 // average. This is the last conversion in the sequence, so\r
405     185                                 // flag a complete ADC-cycle and restart sequence.\r
406     186                                 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
407    \                     ??ADC_ISR_11:\r
408    \   0000010A   8524               LDD     R18, Z+12\r
409    \   0000010C   8535               LDD     R19, Z+13\r
410    \   0000010E   8D00               LDD     R16, Z+24\r
411    \   00000110   7003               ANDI    R16, 0x03\r
412    \   00000112   0F00               LSL     R16\r
413    \   00000114   0FE0               ADD     R30, R16\r
414    \   00000116   1FF8               ADC     R31, R24\r
415    \   00000118   8726               STD     Z+14, R18\r
416    \   0000011A   8737               STD     Z+15, R19\r
417    \   0000011C   01FD               MOVW    R31:R30, R27:R26\r
418    \   0000011E   8D00               LDD     R16, Z+24\r
419    \   00000120   9503               INC     R16\r
420    \   00000122   8F00               STD     Z+24, R16\r
421     187                                 for (i = 0; i < 4 ; i++) {\r
422    \   00000124   963E               ADIW    R31:R30, 14\r
423    \   00000126   E004               LDI     R16, 4\r
424     188                                         temp += ADCS.discIBAT[i];\r
425    \                     ??ADC_ISR_13:\r
426    \   00000128   9121               LD      R18, Z+\r
427    \   0000012A   9131               LD      R19, Z+\r
428    \   0000012C   0F82               ADD     R24, R18\r
429    \   0000012E   1F93               ADC     R25, R19\r
430     189                                 }\r
431    \   00000130   950A               DEC     R16\r
432    \   00000132   F7D1               BRNE    ??ADC_ISR_13\r
433     190                                 \r
434     191                                 ADCS.avgIBAT = (temp / 4);\r
435    \   00000134   018C               MOVW    R17:R16, R25:R24\r
436    \   00000136   E044               LDI     R20, 4\r
437    \   00000138   E050               LDI     R21, 0\r
438    \   0000013A   ....               RCALL   ?SS_DIVMOD_L02\r
439    \   0000013C   01FD               MOVW    R31:R30, R27:R26\r
440    \   0000013E   8B06               STD     Z+22, R16\r
441    \   00000140   8B17               STD     Z+23, R17\r
442     192                                 \r
443     193                                 ADCS.Flag = TRUE;\r
444    \   00000142   910C               LD      R16, X\r
445    \   00000144   6200               ORI     R16, 0x20\r
446    \   00000146   930C               ST      X, R16\r
447     194                                 Next=0x01;\r
448     195                                 Signed = FALSE;  // This is the only bipolar conversion.\r
449     196                         break;\r
450     197          \r
451     198                         \r
452     199                         default:  // Should not happen. (Invalid MUX-channel)\r
453     200                                 Next=0x01;  // Start at the beginning of sequence.\r
454    \                     ??ADC_ISR_5:\r
455    \   00000148   E001               LDI     R16, 1\r
456     201                         break;\r
457     202                 }\r
458     203                 \r
459     204                 // Update MUX to next channel in sequence, set a bipolar conversion if\r
460     205                 // this has been flagged.\r
461     206                 ADCS.MUX = Next;                    \r
462    \                     ??ADC_ISR_6:\r
463    \   0000014A   911C               LD      R17, X\r
464    \   0000014C   7E10               ANDI    R17, 0xE0\r
465    \   0000014E   710F               ANDI    R16, 0x1F\r
466    \   00000150   2B01               OR      R16, R17\r
467    \   00000152   930C               ST      X, R16\r
468     207                 ADMUX = (1<<REFS0) + ADCS.MUX;      \r
469    \   00000154   710F               ANDI    R16, 0x1F\r
470    \   00000156   5C00               SUBI    R16, 192\r
471    \   00000158   B907               OUT     0x07, R16\r
472     208          \r
473     209                 if (Signed)     {\r
474     210                   ADCSRB |= (1<<BIN);               \r
475     211                 } else {\r
476     212                   ADCSRB &= ~(1<<BIN);              \r
477    \   0000015A   981F               CBI     0x03, 0x07\r
478     213                 }\r
479     214          \r
480     215                 // Re-enable the ADC unless a halt has been flagged and a conversion\r
481     216                 // cycle has completed.\r
482     217                 if (!((ADCS.Halt) && (ADCS.Flag))) {\r
483    \   0000015C   910C               LD      R16, X\r
484    \   0000015E   7A00               ANDI    R16, 0xA0\r
485    \   00000160   3A00               CPI     R16, 160\r
486    \   00000162   F019               BREQ    ??ADC_ISR_14\r
487     218                   ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
488    \   00000164   B106               IN      R16, 0x06\r
489    \   00000166   6C00               ORI     R16, 0xC0\r
490    \   00000168   B906               OUT     0x06, R16\r
491     219                 }\r
492     220          }\r
493    \                     ??ADC_ISR_14:\r
494    \   0000016A   BE4F               OUT     0x3F, R4\r
495    \   0000016C   9109               LD      R16, Y+\r
496    \   0000016E   9119               LD      R17, Y+\r
497    \   00000170   9129               LD      R18, Y+\r
498    \   00000172   9139               LD      R19, Y+\r
499    \   00000174   9149               LD      R20, Y+\r
500    \   00000176   9159               LD      R21, Y+\r
501    \   00000178   9169               LD      R22, Y+\r
502    \   0000017A   9179               LD      R23, Y+\r
503    \   0000017C   9009               LD      R0, Y+\r
504    \   0000017E   9019               LD      R1, Y+\r
505    \   00000180   9029               LD      R2, Y+\r
506    \   00000182   9039               LD      R3, Y+\r
507    \   00000184   91E9               LD      R30, Y+\r
508    \   00000186   91F9               LD      R31, Y+\r
509    \   00000188   9189               LD      R24, Y+\r
510    \   0000018A   9199               LD      R25, Y+\r
511    \   0000018C   91A9               LD      R26, Y+\r
512    \   0000018E   91B9               LD      R27, Y+\r
513    \   00000190   9049               LD      R4, Y+\r
514    \   00000192   9518               RETI\r
515    \   00000194                      REQUIRE _A_ADMUX\r
516    \   00000194                      REQUIRE _A_ADCSRA\r
517    \   00000194                      REQUIRE _A_ADC\r
518    \   00000194                      REQUIRE _A_ADCSRB\r
519 \r
520    \                                 In  segment NEAR_Z, align 1, keep-with-next\r
521    \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
522    \                     ADCS:\r
523    \   00000000                      DS 24\r
524    \   00000018                      DS 1\r
525     221          \r
526     222          \r
527     223          /*! \brief Scales sample to represent "actual voltage" in mV.\r
528     224           *\r
529     225           * This function returns the actual sampled voltage, scaled according\r
530     226           * to the jumper settings.\r
531     227           *\r
532     228           * \param setting Indicates what downscaling was used.\r
533     229           * \param data The sampled value.\r
534     230           *\r
535     231           * \note Table for setting-parameter:\n\r
536     232           * <pre>\r
537     233           * Presume VREF = 2.5V and Gain = 1x.\r
538     234           * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
539     235           * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
540     236           * --------+--------+------+------------+-----------+-------\r
541     237           *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
542     238           *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
543     239           *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
544     240           *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
545     241           *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
546     242           *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
547     243           *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
548     244           * </pre>\r
549     245           */\r
550 \r
551    \                                 In  segment CODE, align 2, keep-with-next\r
552     246          unsigned int ScaleU(unsigned char setting, unsigned int data)\r
553    \                     ScaleU:\r
554     247          {\r
555    \   00000000   2E2A               MOV     R2, R26\r
556    \   00000002   01BC               MOVW    R23:R22, R25:R24\r
557    \   00000004   2FA0               MOV     R26, R16\r
558    \   00000006   01C9               MOVW    R25:R24, R19:R18\r
559     248                 // Temporary variable needed.\r
560     249                 unsigned int scaled = 0;\r
561     250          \r
562     251                 // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
563     252                 if (setting == 3)       {\r
564    \   00000008   3003               CPI     R16, 3\r
565    \   0000000A   01A9               MOVW    R21:R20, R19:R18\r
566    \   0000000C   F4A1               BRNE    ??ScaleU_0\r
567     253                         scaled = 29 * data;\r
568     254                         scaled += (data >> 2);\r
569     255                         scaled += (data >> 4);\r
570    \   0000000E   E10D               LDI     R16, 29\r
571    \   00000010   E010               LDI     R17, 0\r
572    \   00000012   ....               RCALL   ?S_MUL_L02\r
573    \   00000014   9536               LSR     R19\r
574    \   00000016   9527               ROR     R18\r
575    \   00000018   9536               LSR     R19\r
576    \   0000001A   9527               ROR     R18\r
577    \   0000001C   0D20               ADD     R18, R0\r
578    \   0000001E   1D31               ADC     R19, R1\r
579    \   00000020   9596               LSR     R25\r
580    \   00000022   9587               ROR     R24\r
581    \   00000024   9596               LSR     R25\r
582    \   00000026   9587               ROR     R24\r
583    \   00000028   9596               LSR     R25\r
584    \   0000002A   9587               ROR     R24\r
585    \   0000002C   9596               LSR     R25\r
586    \   0000002E   9587               ROR     R24\r
587    \   00000030   0F82               ADD     R24, R18\r
588    \   00000032   1F93               ADC     R25, R19\r
589    \   00000034   C014               RJMP    ??ScaleU_1\r
590     256                 } else {\r
591     257                         // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
592     258                         scaled = 39 * data;\r
593     259                         scaled += (data >> 4);\r
594    \                     ??ScaleU_0:\r
595    \   00000036   E207               LDI     R16, 39\r
596    \   00000038   E010               LDI     R17, 0\r
597    \   0000003A   ....               RCALL   ?S_MUL_L02\r
598    \   0000003C   9596               LSR     R25\r
599    \   0000003E   9587               ROR     R24\r
600    \   00000040   9596               LSR     R25\r
601    \   00000042   9587               ROR     R24\r
602    \   00000044   9596               LSR     R25\r
603    \   00000046   9587               ROR     R24\r
604    \   00000048   9596               LSR     R25\r
605    \   0000004A   9587               ROR     R24\r
606    \   0000004C   0D80               ADD     R24, R0\r
607    \   0000004E   1D91               ADC     R25, R1\r
608     260                         \r
609     261                         if (setting <3) {\r
610    \   00000050   30A3               CPI     R26, 3\r
611    \   00000052   F428               BRCC    ??ScaleU_1\r
612     262                                 // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
613     263                                 //                1: mV/LSB = 9.766 = 39.06 / 4\r
614     264                                 //                2: mV/LSB = 19.53 = 39.06 / 2\r
615     265                                 scaled = (scaled >> (3-setting));\r
616    \   00000054   018C               MOVW    R17:R16, R25:R24\r
617    \   00000056   E043               LDI     R20, 3\r
618    \   00000058   1B4A               SUB     R20, R26\r
619    \   0000005A   ....               RCALL   ?US_SHR_L02\r
620    \   0000005C   01C8               MOVW    R25:R24, R17:R16\r
621     266                         }\r
622     267                 }\r
623     268          \r
624     269                 return(scaled);\r
625    \                     ??ScaleU_1:\r
626    \   0000005E   018C               MOVW    R17:R16, R25:R24\r
627    \   00000060   01CB               MOVW    R25:R24, R23:R22\r
628    \   00000062   2DA2               MOV     R26, R2\r
629    \   00000064   9508               RET\r
630     270          }\r
631     271          \r
632     272          \r
633     273          /*! \brief Scales sample to represent "actual current" in mA.\r
634     274           *\r
635     275           * This function returns the actual sampled current, scaled according\r
636     276           * to the jumper settings.\r
637     277           *\r
638     278           * \param setting Indicates what downscaling was used.\r
639     279           * \param data The sampled value.\r
640     280           *\r
641     281           * \note Table for setting-parameter:\n\r
642     282           * <pre>\r
643     283           * Presume VREF = 2.5V and Gain = 1x or 20x.\r
644     284           * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
645     285           * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
646     286           * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
647     287           * --------+------+------------+----------+----------+--------+-----\r
648     288           *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
649     289           *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
650     290           *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
651     291           *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
652     292           *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
653     293           *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
654     294           *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
655     295           * </pre>\r
656     296           */\r
657 \r
658    \                                 In  segment CODE, align 2, keep-with-next\r
659     297          unsigned int ScaleI(unsigned char setting, unsigned int data)\r
660    \                     ScaleI:\r
661     298          {\r
662    \   00000000   2E2A               MOV     R2, R26\r
663    \   00000002   01BC               MOVW    R23:R22, R25:R24\r
664    \   00000004   2FA0               MOV     R26, R16\r
665    \   00000006   01C9               MOVW    R25:R24, R19:R18\r
666     299                 // Temporary variable needed.\r
667     300                 unsigned int  scaled = 0;\r
668     301                 \r
669     302                 // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
670     303                 if (setting == 3) {\r
671    \   00000008   3003               CPI     R16, 3\r
672    \   0000000A   01A9               MOVW    R21:R20, R19:R18\r
673    \   0000000C   F4A9               BRNE    ??ScaleI_0\r
674     304                         scaled = 21 * data;\r
675     305                         scaled -= (data >> 4);\r
676     306                         scaled += (data >> 7);\r
677    \   0000000E   E105               LDI     R16, 21\r
678    \   00000010   E010               LDI     R17, 0\r
679    \   00000012   ....               RCALL   ?S_MUL_L02\r
680    \   00000014   9536               LSR     R19\r
681    \   00000016   9527               ROR     R18\r
682    \   00000018   9536               LSR     R19\r
683    \   0000001A   9527               ROR     R18\r
684    \   0000001C   9536               LSR     R19\r
685    \   0000001E   9527               ROR     R18\r
686    \   00000020   9536               LSR     R19\r
687    \   00000022   9527               ROR     R18\r
688    \   00000024   1B02               SUB     R16, R18\r
689    \   00000026   0B13               SBC     R17, R19\r
690    \   00000028   0F88               LSL     R24\r
691    \   0000002A   2F89               MOV     R24, R25\r
692    \   0000002C   1F88               ROL     R24\r
693    \   0000002E   E090               LDI     R25, 0\r
694    \   00000030   1F99               ROL     R25\r
695    \   00000032   0F80               ADD     R24, R16\r
696    \   00000034   1F91               ADC     R25, R17\r
697    \   00000036   C01A               RJMP    ??ScaleI_1\r
698     307                 }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
699     308                         scaled = 28 * data;\r
700     309                         scaled -= (data >> 3);\r
701     310                         scaled += (data >> 5);\r
702    \                     ??ScaleI_0:\r
703    \   00000038   E10C               LDI     R16, 28\r
704    \   0000003A   E010               LDI     R17, 0\r
705    \   0000003C   ....               RCALL   ?S_MUL_L02\r
706    \   0000003E   0198               MOVW    R19:R18, R17:R16\r
707    \   00000040   018C               MOVW    R17:R16, R25:R24\r
708    \   00000042   9516               LSR     R17\r
709    \   00000044   9507               ROR     R16\r
710    \   00000046   9516               LSR     R17\r
711    \   00000048   9507               ROR     R16\r
712    \   0000004A   9516               LSR     R17\r
713    \   0000004C   9507               ROR     R16\r
714    \   0000004E   1B20               SUB     R18, R16\r
715    \   00000050   0B31               SBC     R19, R17\r
716    \   00000052   018C               MOVW    R17:R16, R25:R24\r
717    \   00000054   E045               LDI     R20, 5\r
718    \   00000056   ....               RCALL   ?US_SHR_L02\r
719    \   00000058   01C8               MOVW    R25:R24, R17:R16\r
720    \   0000005A   0F82               ADD     R24, R18\r
721    \   0000005C   1F93               ADC     R25, R19\r
722     311                         \r
723     312                         if (setting <3) {\r
724    \   0000005E   30A3               CPI     R26, 3\r
725    \   00000060   F428               BRCC    ??ScaleI_1\r
726     313                                 // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
727     314                                 //                1: mA/LSB = 6.978mA = 27.909 / 4\r
728     315                                 //                2: mA/LSB = 13.955mA = 27.909 / 2\r
729     316                                 scaled = (scaled >> (3-setting));\r
730    \   00000062   018C               MOVW    R17:R16, R25:R24\r
731    \   00000064   E043               LDI     R20, 3\r
732    \   00000066   1B4A               SUB     R20, R26\r
733    \   00000068   ....               RCALL   ?US_SHR_L02\r
734    \   0000006A   01C8               MOVW    R25:R24, R17:R16\r
735     317                         }\r
736     318                 }\r
737     319                 \r
738     320                 return(scaled);\r
739    \                     ??ScaleI_1:\r
740    \   0000006C   018C               MOVW    R17:R16, R25:R24\r
741    \   0000006E   01CB               MOVW    R25:R24, R23:R22\r
742    \   00000070   2DA2               MOV     R26, R2\r
743    \   00000072   9508               RET\r
744     321          }\r
745     322          \r
746     323          \r
747     324          /*! \brief Waits for two full cycles of ADC-conversions to occur.\r
748     325           *\r
749     326           * This function clears the cycle complete-flag, then waits for it to be set\r
750     327           * again. This is then repeated once before the function exits.\r
751     328           * \r
752     329           */\r
753 \r
754    \                                 In  segment CODE, align 2, keep-with-next\r
755     330          void ADC_Wait(void)\r
756    \                     ADC_Wait:\r
757    \                     ??ADC_Wait_0:\r
758     331          {\r
759     332                 // Clear ADC flag and wait for cycle to complete.\r
760     333                 ADCS.Flag = FALSE;              \r
761     334                 do {\r
762     335                 } while (ADCS.Flag == FALSE);      \r
763    \   00000000   CFFF               RJMP    ??ADC_Wait_0\r
764     336                 \r
765     337                 // Repeat, so we are sure the data beong to the same cycle.\r
766     338                 ADCS.Flag = FALSE;              \r
767     339                 do {\r
768     340                 } while (ADCS.Flag == FALSE);      \r
769     341          }\r
770     342          \r
771     343          \r
772     344          /*! \brief Initializes ADC and input pins.\r
773     345           *\r
774     346           * This function initializes the ADC to free running mode, sampling from\r
775     347           * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
776     348           * It also measures and stores calibration data for offset.\r
777     349           *\r
778     350           * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
779     351           *\r
780     352           * \note Table of MUX settings for offset measurement:\r
781     353           * <pre>\r
782     354           *    Ch | Pin |    Gain |    MUX\r
783     355           * ------+-----+---------+-------\r
784     356           *  ADC1 | PA1 |     20x | 001101\r
785     357           *  ADC3 | PA4 |     20x | 010001\r
786     358           *  ADC5 | PA6 |     20x | 010110\r
787     359           *  ADC9 | PB6 |     20x | 011011\r
788     360           *  ADC0 | PA0 | 20x/32x | 111000\r
789     361           *  ADC0 | PA0 |   1x/8x | 111001\r
790     362           *  ADC1 | PA1 | 20x/32x | 111010\r
791     363           *  ADC2 | PA2 | 20x/32x | 111011\r
792     364           *  ADC4 | PA5 | 20x/32x | 111100\r
793     365           *  ADC5 | PA6 | 20x/32x | 111101\r
794     366           *  ADC6 | PA7 | 20x/32x | 111110\r
795     367           * </pre>\r
796     368           */\r
797 \r
798    \                                 In  segment CODE, align 2, keep-with-next\r
799     369          void ADC_Init(void)\r
800    \                     ADC_Init:\r
801     370          {\r
802     371                 unsigned char i;\r
803     372          \r
804     373                 __disable_interrupt();\r
805    \   00000000   94F8               CLI\r
806     374          \r
807     375                 ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
808    \   00000002   ....               LDI     R30, LOW(ADCS)\r
809    \   00000004   ....               LDI     R31, (ADCS) >> 8\r
810    \   00000006   8100               LD      R16, Z\r
811    \   00000008   770F               ANDI    R16, 0x7F\r
812    \   0000000A   8300               ST      Z, R16\r
813     376          \r
814     377                 // Configure ADC pins (inputs and disabled pull-ups).\r
815     378                 DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
816    \   0000000C   B30A               IN      R16, 0x1A\r
817    \   0000000E   7009               ANDI    R16, 0x09\r
818    \   00000010   BB0A               OUT     0x1A, R16\r
819     379                 PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
820    \   00000012   B30B               IN      R16, 0x1B\r
821    \   00000014   7009               ANDI    R16, 0x09\r
822    \   00000016   BB0B               OUT     0x1B, R16\r
823     380          \r
824     381                 // Set ADC3 as reference, and MUX to measure the same pin.\r
825     382                 ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
826    \   00000018   E403               LDI     R16, 67\r
827    \   0000001A   B907               OUT     0x07, R16\r
828     383                 \r
829     384                 ADCSRB = 0;\r
830    \   0000001C   E000               LDI     R16, 0\r
831    \   0000001E   B903               OUT     0x03, R16\r
832     385          \r
833     386                 // Start conversion, no interrupt (disable ADC-ISR).\r
834     387                 ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
835    \   00000020   EC07               LDI     R16, 199\r
836    \   00000022   B906               OUT     0x06, R16\r
837     388          \r
838     389                 do { // Wait for conversion to finish.\r
839     390                 } while (!(ADCSRA & (1<<ADIF)));\r
840    \                     ??ADC_Init_0:\r
841    \   00000024   9B34               SBIS    0x06, 0x04\r
842    \   00000026   CFFE               RJMP    ??ADC_Init_0\r
843     391          \r
844     392                 ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
845    \   00000028   9A34               SBI     0x06, 0x04\r
846     393          \r
847     394                 ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
848    \   0000002A   8121               LDD     R18, Z+1\r
849    \   0000002C   7F20               ANDI    R18, 0xF0\r
850    \   0000002E   B104               IN      R16, 0x04\r
851    \   00000030   B115               IN      R17, 0x05\r
852    \   00000032   700F               ANDI    R16, 0x0F\r
853    \   00000034   2B02               OR      R16, R18\r
854    \   00000036   8301               STD     Z+1, R16\r
855     395          \r
856     396                 ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
857    \   00000038   E516               LDI     R17, 86\r
858    \   0000003A   B917               OUT     0x07, R17\r
859     397                 \r
860     398                 // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
861     399                 ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
862    \   0000003C   EC17               LDI     R17, 199\r
863    \   0000003E   B916               OUT     0x06, R17\r
864     400          \r
865     401                 do { // Wait for conversion to finish.\r
866     402                 } while (!(ADCSRA & (1<<ADIF)));\r
867    \                     ??ADC_Init_1:\r
868    \   00000040   9B34               SBIS    0x06, 0x04\r
869    \   00000042   CFFE               RJMP    ??ADC_Init_1\r
870     403          \r
871     404                 ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
872    \   00000044   9A34               SBI     0x06, 0x04\r
873     405          \r
874     406                 ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
875    \   00000046   700F               ANDI    R16, 0x0F\r
876    \   00000048   B124               IN      R18, 0x04\r
877    \   0000004A   B135               IN      R19, 0x05\r
878    \   0000004C   9522               SWAP    R18\r
879    \   0000004E   7F20               ANDI    R18, 0xF0\r
880    \   00000050   2B20               OR      R18, R16\r
881    \   00000052   8321               STD     Z+1, R18\r
882     407          \r
883     408                 // Reset the ADC-cycle.\r
884     409                 ADCS.Flag = FALSE;      \r
885     410                 ADCS.MUX = 0x01;                    \r
886    \   00000054   8100               LD      R16, Z\r
887    \   00000056   7C00               ANDI    R16, 0xC0\r
888    \   00000058   6001               ORI     R16, 0x01\r
889    \   0000005A   8300               ST      Z, R16\r
890     411                 ADMUX = (1<<REFS0) | ADCS.MUX;      \r
891    \   0000005C   E401               LDI     R16, 65\r
892    \   0000005E   B907               OUT     0x07, R16\r
893     412          \r
894     413                 // Clear averaged battery current and the discrete readings.\r
895     414                 ADCS.avgIBAT = 0;\r
896    \   00000060   E000               LDI     R16, 0\r
897    \   00000062   8B06               STD     Z+22, R16\r
898    \   00000064   8B07               STD     Z+23, R16\r
899     415                 \r
900     416                 for (i = 0; i < 4; i++) {\r
901    \   00000066   963E               ADIW    R31:R30, 14\r
902    \   00000068   E024               LDI     R18, 4\r
903     417                         ADCS.discIBAT[i] = 0;             \r
904    \                     ??ADC_Init_2:\r
905    \   0000006A   9301               ST      Z+, R16\r
906    \   0000006C   9301               ST      Z+, R16\r
907     418                 }\r
908    \   0000006E   952A               DEC     R18\r
909    \   00000070   F7E1               BRNE    ??ADC_Init_2\r
910     419                 \r
911     420                 // Re-enable the ADC and ISR.\r
912     421                 ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
913    \   00000072   EC0F               LDI     R16, 207\r
914    \   00000074   B906               OUT     0x06, R16\r
915     422                 \r
916     423                 __enable_interrupt();\r
917    \   00000076   9478               SEI\r
918     424          \r
919     425                 // Get a complete cycle of data before returning.\r
920     426                 ADC_Wait();\r
921    \                     ??ADC_Init_3:\r
922    \   00000078   CFFF               RJMP    ??ADC_Init_3\r
923    \   0000007A                      REQUIRE _A_PORTA\r
924    \   0000007A                      REQUIRE _A_DDRA\r
925    \   0000007A                      REQUIRE _A_ADMUX\r
926    \   0000007A                      REQUIRE _A_ADCSRA\r
927    \   0000007A                      REQUIRE _A_ADC\r
928    \   0000007A                      REQUIRE _A_ADCSRB\r
929     427          }\r
930 \r
931    \                                 In  segment INTVEC, offset 0x16, root\r
932    \                     `??ADC_ISR??INTVEC 22`:\r
933    \   00000016   ....               RJMP    ADC_ISR\r
934 \r
935    Maximum stack usage in bytes:\r
936 \r
937      Function    CSTACK RSTACK\r
938      --------    ------ ------\r
939      ADC_ISR        19      4\r
940        -> ScaleU    19      2\r
941        -> ScaleU    19      2\r
942        -> ScaleI    19      2\r
943        -> ScaleI    19      2\r
944      ADC_Init        0      2\r
945      ADC_Wait        0      2\r
946      ScaleI          3      4\r
947      ScaleU          3      4\r
948 \r
949 \r
950    Segment part sizes:\r
951 \r
952      Function/Label       Bytes\r
953      --------------       -----\r
954      _A_PORTA                1\r
955      _A_DDRA                 1\r
956      _A_ADMUX                1\r
957      _A_ADCSRA               1\r
958      _A_ADC                  2\r
959      _A_ADCSRB               1\r
960      VBAT_RANGE              1\r
961      ADC_ISR               404\r
962      ADCS                   25\r
963      ScaleU                102\r
964      ScaleI                116\r
965      ??ADC_Wait_0            2\r
966      ADC_Init              122\r
967      ??ADC_ISR??INTVEC 22    2\r
968       Others                 6\r
969 \r
970  \r
971    7 bytes in segment ABSOLUTE\r
972  746 bytes in segment CODE\r
973    1 byte  in segment EEPROM_I\r
974    6 bytes in segment INITTAB\r
975    2 bytes in segment INTVEC\r
976   25 bytes in segment NEAR_Z\r
977  \r
978  746 bytes of CODE  memory (+ 8 bytes shared)\r
979   25 bytes of DATA  memory (+ 7 bytes shared)\r
980    1 byte  of XDATA memory\r
981 \r
982 Errors: none\r
983 Warnings: none\r