Initial import
[avr_bc100.git] / BaseTinyFirmware / IAR / Debug / List / ADC.s90
1 ///////////////////////////////////////////////////////////////////////////////\r
2 //                                                                            /\r
3 // IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:38 /\r
4 // Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
5 //                                                                            /\r
6 //    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c               /\r
7 //    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c               /\r
8 //                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
9 //                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
10 //                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
11 //                    \List\ --initializers_in_flash -z2 --no_cse             /\r
12 //                    --no_inline --no_code_motion --no_cross_call            /\r
13 //                    --no_clustering --no_tbaa --debug                       /\r
14 //                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
15 //                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
16 //                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
17 //                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
18 //                    --eeprom_size 512                                       /\r
19 //    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ADC.s90  /\r
20 //                                                                            /\r
21 //                                                                            /\r
22 ///////////////////////////////////////////////////////////////////////////////\r
23 \r
24         NAME `ADC`\r
25 \r
26         RSEG CSTACK:DATA:NOROOT(0)\r
27         RSEG RSTACK:DATA:NOROOT(0)\r
28 \r
29         EXTERN ?EPILOGUE_B6_L09\r
30         EXTERN ?PROLOGUE6_L09\r
31         EXTERN ?Register_R4_is_cg_reg\r
32         EXTERN ?Register_R5_is_cg_reg\r
33         EXTERN ?SS_DIVMOD_L02\r
34         EXTERN ?S_MUL_L02\r
35         EXTERN ?US_SHR_L02\r
36         EXTERN ?need_segment_init\r
37         EXTERN __eeget8_16\r
38 \r
39         PUBWEAK `?<Segment init: NEAR_Z>`\r
40         PUBWEAK `??ADC_ISR??INTVEC 22`\r
41         PUBLIC ADCS\r
42         PUBLIC ADC_ISR\r
43         PUBLIC ADC_Init\r
44         PUBLIC ADC_Wait\r
45         PUBLIC ScaleI\r
46         PUBLIC ScaleU\r
47         PUBLIC VBAT_RANGE\r
48         PUBWEAK _A_ADC\r
49         PUBWEAK _A_ADCSRA\r
50         PUBWEAK _A_ADCSRB\r
51         PUBWEAK _A_ADMUX\r
52         PUBWEAK _A_DDRA\r
53         PUBWEAK _A_PORTA\r
54         PUBWEAK __?EEARH\r
55         PUBWEAK __?EEARL\r
56         PUBWEAK __?EECR\r
57         PUBWEAK __?EEDR\r
58 \r
59 ADC_ISR             SYMBOL "ADC_ISR"\r
60 `??ADC_ISR??INTVEC 22` SYMBOL "??INTVEC 22", ADC_ISR\r
61 \r
62 // C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c\r
63 //    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
64 //    2 /*! \file *********************************************************************\r
65 //    3  *\r
66 //    4  * \brief\r
67 //    5  *      Functions for use of ADC\r
68 //    6  *\r
69 //    7  *      Contains high level functions for initializing the ADC, interrupt\r
70 //    8  *      handling, and treatment of samples.\n\r
71 //    9  *      The ADC is set to free running mode and uses an external reference\r
72 //   10  *      voltage.\n\r
73 //   11  *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
74 //   12  *      and restarted by the ISR.\r
75 //   13  *\r
76 //   14  * \par Application note:\r
77 //   15  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
78 //   16  *      AVR463: Charging NiMH Batteries with BC100\r
79 //   17  *\r
80 //   18  * \par Documentation:\r
81 //   19  *      For comprehensive code documentation, supported compilers, compiler\r
82 //   20  *      settings and supported devices see readme.html\r
83 //   21  *\r
84 //   22  * \author\r
85 //   23  *      Atmel Corporation: http://www.atmel.com \n\r
86 //   24  *      Support email: avr@atmel.com \n\r
87 //   25  *      Original author: \n\r
88 //   26  *\r
89 //   27  * $Name$\r
90 //   28  * $Revision: 2299 $\r
91 //   29  * $RCSfile$\r
92 //   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
93 //   31  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
94 //   32  ******************************************************************************/\r
95 //   33 \r
96 //   34 #include <ioavr.h>\r
97 \r
98         ASEGN ABSOLUTE:DATA:NOROOT,03bH\r
99 // <unnamed> volatile __io _A_PORTA\r
100 _A_PORTA:\r
101         DS 1\r
102 \r
103         ASEGN ABSOLUTE:DATA:NOROOT,03aH\r
104 // <unnamed> volatile __io _A_DDRA\r
105 _A_DDRA:\r
106         DS 1\r
107 \r
108         ASEGN ABSOLUTE:DATA:NOROOT,027H\r
109 // <unnamed> volatile __io _A_ADMUX\r
110 _A_ADMUX:\r
111         DS 1\r
112 \r
113         ASEGN ABSOLUTE:DATA:NOROOT,026H\r
114 // <unnamed> volatile __io _A_ADCSRA\r
115 _A_ADCSRA:\r
116         DS 1\r
117 \r
118         ASEGN ABSOLUTE:DATA:NOROOT,024H\r
119 // <unnamed> volatile __io _A_ADC\r
120 _A_ADC:\r
121         DS 2\r
122 \r
123         ASEGN ABSOLUTE:DATA:NOROOT,023H\r
124 // <unnamed> volatile __io _A_ADCSRB\r
125 _A_ADCSRB:\r
126         DS 1\r
127 //   35 #include <inavr.h>\r
128 //   36 \r
129 //   37 #include "structs.h"\r
130 //   38 \r
131 //   39 #include "main.h"\r
132 //   40 #include "ADC.h"\r
133 //   41 \r
134 //   42 \r
135 //   43 //******************************************************************************\r
136 //   44 // Variables\r
137 //   45 //******************************************************************************\r
138 //   46 // ADC status struct.\r
139 //   47 //! \brief Holds sampled data and ADC-status\r
140 \r
141         RSEG NEAR_Z:DATA:NOROOT(0)\r
142         REQUIRE `?<Segment init: NEAR_Z>`\r
143 //   48 ADC_Status_t ADCS;\r
144 ADCS:\r
145         DS 24\r
146 //   49 \r
147 //   50 \r
148 //   51 /*! \brief Indicates maximum battery voltage.\r
149 //   52  *\r
150 //   53  * This variable is stored in EEPROM and indicates how much the battery voltage\r
151 //   54  * is downscaled by HW before it is sampled. The amount of downscaling depends\r
152 //   55  * on the maximum battery voltage, and is necessary to avoid saturation of the\r
153 //   56  * ADC (reference voltage is 2.5 V).\r
154 //   57  *\r
155 //   58  * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
156 //   59  *\r
157 //   60  * \note Defaults to 1, which means 10 V max battery voltage.\r
158 //   61  *\r
159 //   62  * \note Table of settings:\r
160 //   63  * <pre>\r
161 //   64  * VBAT_RANGE | Max battery voltage | Jumper setting\r
162 //   65  *         0  |             5V      |        1/2\r
163 //   66  *         1  |            10V      |        1/4\r
164 //   67  *         2  |            20V      |        1/8\r
165 //   68  *         3  |            30V      |       1/12\r
166 //   69  *         4  |            40V      |       1/16\r
167 //   70  * </pre>\r
168 //   71  */\r
169 //   72 // Maximum battery voltage (affects scaling of samples).\r
170 \r
171         RSEG EEPROM_I:XDATA:NOROOT(0)\r
172 //   73 __eeprom unsigned char VBAT_RANGE = 1;\r
173 VBAT_RANGE:\r
174         DB 1\r
175 //   74 \r
176 //   75 \r
177 //   76 //******************************************************************************\r
178 //   77 // Functions\r
179 //   78 //******************************************************************************\r
180 //   79 /*! \brief Interrupt Service routine for ADC.\r
181 //   80  *\r
182 //   81  * This ISR stores the sampled values in the ADC status-struct, then\r
183 //   82  * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
184 //   83  * Once the sequence is completed, ADCS.Flag is set and unless\r
185 //   84  * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
186 //   85  * is disabled.\n\r
187 //   86  * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
188 //   87  *\r
189 //   88  * \note Table of scanning sequence:\r
190 //   89  * <pre>\r
191 //   90  * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
192 //   91  * ----+--------+----------+----------+------+---------+-------\r
193 //   92  *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
194 //   93  *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
195 //   94  *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
196 //   95  *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
197 //   96  *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
198 //   97  *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
199 //   98  *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
200 //   99  *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
201 //  100  * </pre>\r
202 //  101  *\r
203 //  102  * \todo IIN (#7 in sequence) is never used.\r
204 //  103  *\r
205 //  104  * \todo Signed is never set. Signed measurements of IBAT will halve the\r
206 //  105  * measuring sensitivity, and is therefore not favourable. At the moment,\r
207 //  106  * great currents (f.ex. if something happens with the battery) will be\r
208 //  107  * interpreted as negative, which might cause unfavourable behaviour during\r
209 //  108  * charging (depending on what PWM behaviour is defined), f.ex.\r
210 //  109  * ConstantCurrent() will keep increasing the PWM output. This results in an\r
211 //  110  * PWM controller error being flagged and the program going into\r
212 //  111  * error-state and eventually reinitializing.\r
213 //  112  */\r
214 //  113 #pragma vector=ADC_vect\r
215 \r
216         RSEG CODE:CODE:NOROOT(1)\r
217 //  114 __interrupt void ADC_ISR(void)\r
218 ADC_ISR:\r
219 //  115 {\r
220         ST      -Y, R5\r
221         ST      -Y, R4\r
222         ST      -Y, R27\r
223         ST      -Y, R26\r
224         ST      -Y, R25\r
225         ST      -Y, R24\r
226         ST      -Y, R31\r
227         ST      -Y, R30\r
228         ST      -Y, R3\r
229         ST      -Y, R2\r
230         ST      -Y, R1\r
231         ST      -Y, R0\r
232         ST      -Y, R23\r
233         ST      -Y, R22\r
234         ST      -Y, R21\r
235         ST      -Y, R20\r
236         ST      -Y, R19\r
237         ST      -Y, R18\r
238         ST      -Y, R17\r
239         ST      -Y, R16\r
240         IN      R5, 0x3F\r
241         REQUIRE ?Register_R4_is_cg_reg\r
242         REQUIRE ?Register_R5_is_cg_reg\r
243 //  116         static unsigned char avgIndex = 0;\r
244 //  117         unsigned char i, Next, Signed;\r
245 //  118         signed int  temp = 0;\r
246         LDI     R26, 0\r
247         LDI     R27, 0\r
248 //  119         \r
249 //  120         Signed = FALSE;  // Presume next conversion is unipolar.\r
250         CLR     R4\r
251 //  121         ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
252         CBI     0x06, 0x07\r
253 //  122           // conversions take at least 25 ADCCLK. (It is restarted later)\r
254 //  123         \r
255 //  124         // Handle the conversion, depending on what channel it is from, then\r
256 //  125         // switch to the next channel in the sequence.\r
257 //  126         switch (ADCS.MUX){\r
258         LDS     R16, ADCS\r
259         ANDI    R16, 0x1F\r
260         SUBI    R16, 1\r
261         BREQ    ??ADC_ISR_0\r
262         DEC     R16\r
263         BREQ    ??ADC_ISR_1\r
264         DEC     R16\r
265         BREQ    ??ADC_ISR_2\r
266         SUBI    R16, 2\r
267         BREQ    ??ADC_ISR_3\r
268         SUBI    R16, 18\r
269         BRNE    $+2+2\r
270         RJMP    ??ADC_ISR_4\r
271         RJMP    ??ADC_ISR_5\r
272 //  127                 // MUX = 0b000001 => ADC1 (PA1) = NTC\r
273 //  128                 case 0x01:\r
274 //  129                         ADCS.rawNTC = ADC;\r
275 ??ADC_ISR_0:\r
276         IN      R16, 0x04\r
277         IN      R17, 0x05\r
278         LDI     R30, LOW(ADCS)\r
279         LDI     R31, (ADCS) >> 8\r
280         STD     Z+4, R16\r
281         STD     Z+5, R17\r
282 //  130                         Next=0x02;\r
283         LDI     R25, 2\r
284         RJMP    ??ADC_ISR_6\r
285 //  131                 break;\r
286 //  132 \r
287 //  133                 \r
288 //  134                 // MUX = 0b000010 => ADC2 (PA2) = RID\r
289 //  135                 case 0x02:\r
290 //  136                         ADCS.rawRID = ADC;\r
291 ??ADC_ISR_1:\r
292         IN      R16, 0x04\r
293         IN      R17, 0x05\r
294         LDI     R30, LOW(ADCS)\r
295         LDI     R31, (ADCS) >> 8\r
296         STD     Z+2, R16\r
297         STD     Z+3, R17\r
298 //  137                         Next=0x03;\r
299         LDI     R25, 3\r
300         RJMP    ??ADC_ISR_6\r
301 //  138                 break;\r
302 //  139 \r
303 //  140                 \r
304 //  141                 // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
305 //  142                 case 0x03:\r
306 //  143                         // Supply voltage is always divided by 16.\r
307 //  144                         ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
308 ??ADC_ISR_2:\r
309         IN      R18, 0x04\r
310         IN      R19, 0x05\r
311         LDI     R16, 4\r
312         RCALL   ScaleU\r
313         LDI     R30, LOW(ADCS)\r
314         LDI     R31, (ADCS) >> 8\r
315         STD     Z+8, R16\r
316         STD     Z+9, R17\r
317 //  145                         \r
318 //  146                         // Is mains failing?\r
319 //  147                         if (ADCS.VIN < VIN_MIN) {\r
320         LDI     R30, LOW(ADCS)\r
321         LDI     R31, (ADCS) >> 8\r
322         LDD     R16, Z+8\r
323         LDD     R17, Z+9\r
324         CPI     R16, 48\r
325         LDI     R18, 17\r
326         CPC     R17, R18\r
327         BRCC    ??ADC_ISR_7\r
328 //  148                                 ADCS.Mains = FALSE;\r
329         LDI     R30, LOW(ADCS)\r
330         LDI     R31, (ADCS) >> 8\r
331         LD      R16, Z\r
332         ANDI    R16, 0xBF\r
333         ST      Z, R16\r
334         RJMP    ??ADC_ISR_8\r
335 //  149                         } else {\r
336 //  150                                 ADCS.Mains = TRUE;\r
337 ??ADC_ISR_7:\r
338         LDI     R30, LOW(ADCS)\r
339         LDI     R31, (ADCS) >> 8\r
340         LD      R16, Z\r
341         ORI     R16, 0x40\r
342         ST      Z, R16\r
343 //  151                         }\r
344 //  152                         \r
345 //  153                         Next=0x05;\r
346 ??ADC_ISR_8:\r
347         LDI     R25, 5\r
348         RJMP    ??ADC_ISR_6\r
349 //  154                 break;\r
350 //  155 \r
351 //  156                 \r
352 //  157                 // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
353 //  158                 case 0x05:\r
354 //  159                         ADCS.rawVBAT = ADC;\r
355 ??ADC_ISR_3:\r
356         IN      R16, 0x04\r
357         IN      R17, 0x05\r
358         LDI     R30, LOW(ADCS)\r
359         LDI     R31, (ADCS) >> 8\r
360         STD     Z+6, R16\r
361         STD     Z+7, R17\r
362 //  160                         \r
363 //  161                         // Scale voltage according to jumper setting.\r
364 //  162                         ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
365         IN      R18, 0x04\r
366         IN      R19, 0x05\r
367         LDI     R20, LOW(VBAT_RANGE)\r
368         LDI     R21, (VBAT_RANGE) >> 8\r
369         RCALL   __eeget8_16\r
370         RCALL   ScaleU\r
371         LDI     R30, LOW(ADCS)\r
372         LDI     R31, (ADCS) >> 8\r
373         STD     Z+10, R16\r
374         STD     Z+11, R17\r
375 //  163                         Next=0x17;\r
376         LDI     R25, 23\r
377         RJMP    ??ADC_ISR_6\r
378 //  164 //                      Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
379 //  165                 break;\r
380 //  166 \r
381 //  167 \r
382 //  168                 case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
383 //  169                         // If bipolar, from -512 to 0, to 511:\r
384 //  170                         // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
385 //  171                 \r
386 //  172                         // Scale sample according to jumper setting, handle negative numbers.\r
387 //  173                         if (ADC > 511) {\r
388 ??ADC_ISR_4:\r
389         IN      R16, 0x04\r
390         IN      R17, 0x05\r
391         CPI     R16, 0\r
392         LDI     R18, 2\r
393         CPC     R17, R18\r
394         BRCS    ??ADC_ISR_9\r
395 //  174                                 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
396 //  175                                              (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
397         LDI     R16, 0\r
398         LDI     R17, 4\r
399         IN      R18, 0x04\r
400         IN      R19, 0x05\r
401         SUB     R16, R18\r
402         SBC     R17, R19\r
403         LDS     R18, (ADCS + 1)\r
404         SWAP    R18\r
405         ANDI    R18, 0x0F\r
406         LDI     R19, 0\r
407         ADD     R18, R16\r
408         ADC     R19, R17\r
409         LDI     R20, LOW(VBAT_RANGE)\r
410         LDI     R21, (VBAT_RANGE) >> 8\r
411         RCALL   __eeget8_16\r
412         RCALL   ScaleI\r
413         NEG     R17\r
414         NEG     R16\r
415         SBCI    R17, 0\r
416         LDI     R30, LOW(ADCS)\r
417         LDI     R31, (ADCS) >> 8\r
418         STD     Z+12, R16\r
419         STD     Z+13, R17\r
420         RJMP    ??ADC_ISR_10\r
421 //  176                         } else if (ADC > 0) {\r
422 ??ADC_ISR_9:\r
423         IN      R16, 0x04\r
424         IN      R17, 0x05\r
425         OR      R16, R17\r
426         BREQ    ??ADC_ISR_11\r
427 //  177                                 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
428         IN      R18, 0x04\r
429         IN      R19, 0x05\r
430         LDS     R16, (ADCS + 1)\r
431         SWAP    R16\r
432         ANDI    R16, 0x0F\r
433         LDI     R17, 0\r
434         SUB     R18, R16\r
435         SBC     R19, R17\r
436         LDI     R20, LOW(VBAT_RANGE)\r
437         LDI     R21, (VBAT_RANGE) >> 8\r
438         RCALL   __eeget8_16\r
439         RCALL   ScaleI\r
440         LDI     R30, LOW(ADCS)\r
441         LDI     R31, (ADCS) >> 8\r
442         STD     Z+12, R16\r
443         STD     Z+13, R17\r
444         RJMP    ??ADC_ISR_10\r
445 //  178                         } else {\r
446 //  179                                 ADCS.IBAT = 0;\r
447 ??ADC_ISR_11:\r
448         LDI     R16, 0\r
449         LDI     R17, 0\r
450         LDI     R30, LOW(ADCS)\r
451         LDI     R31, (ADCS) >> 8\r
452         STD     Z+12, R16\r
453         STD     Z+13, R17\r
454 //  180                         }\r
455 //  181 \r
456 //  182                         // Insert sample of battery current into the averaging-array\r
457 //  183                         // (overwriting the oldest sample), then recalculate and store the\r
458 //  184                         // average. This is the last conversion in the sequence, so\r
459 //  185                         // flag a complete ADC-cycle and restart sequence.\r
460 //  186                         ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
461 ??ADC_ISR_10:\r
462         LDI     R30, LOW(ADCS)\r
463         LDI     R31, (ADCS) >> 8\r
464         LDD     R18, Z+12\r
465         LDD     R19, Z+13\r
466         LDS     R16, ??avgIndex\r
467         LDI     R17, 0\r
468         ANDI    R16, 0x03\r
469         ANDI    R17, 0x00\r
470         LSL     R16\r
471         ROL     R17\r
472         MOVW    R31:R30, R17:R16\r
473         SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
474         SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
475         STD     Z+14, R18\r
476         STD     Z+15, R19\r
477         LDI     R30, LOW(??avgIndex)\r
478         LDI     R31, (??avgIndex) >> 8\r
479         LD      R16, Z\r
480         INC     R16\r
481         ST      Z, R16\r
482 //  187                         for (i = 0; i < 4 ; i++) {\r
483         LDI     R24, 0\r
484 ??ADC_ISR_12:\r
485         CPI     R24, 4\r
486         BRCC    ??ADC_ISR_13\r
487 //  188                                 temp += ADCS.discIBAT[i];\r
488         MOV     R16, R24\r
489         LDI     R17, 0\r
490         LSL     R16\r
491         ROL     R17\r
492         MOVW    R31:R30, R17:R16\r
493         SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
494         SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
495         LDD     R16, Z+14\r
496         LDD     R17, Z+15\r
497         ADD     R26, R16\r
498         ADC     R27, R17\r
499 //  189                         }\r
500         INC     R24\r
501         RJMP    ??ADC_ISR_12\r
502 //  190                         \r
503 //  191                         ADCS.avgIBAT = (temp / 4);\r
504 ??ADC_ISR_13:\r
505         MOVW    R17:R16, R27:R26\r
506         LDI     R20, 4\r
507         LDI     R21, 0\r
508         RCALL   ?SS_DIVMOD_L02\r
509         LDI     R30, LOW(ADCS)\r
510         LDI     R31, (ADCS) >> 8\r
511         STD     Z+22, R16\r
512         STD     Z+23, R17\r
513 //  192                         \r
514 //  193                         ADCS.Flag = TRUE;\r
515         LDI     R30, LOW(ADCS)\r
516         LDI     R31, (ADCS) >> 8\r
517         LD      R16, Z\r
518         ORI     R16, 0x20\r
519         ST      Z, R16\r
520 //  194                         Next=0x01;\r
521         LDI     R25, 1\r
522 //  195                         Signed = FALSE;  // This is the only bipolar conversion.\r
523         CLR     R4\r
524         RJMP    ??ADC_ISR_6\r
525 //  196                 break;\r
526 //  197 \r
527 //  198                 \r
528 //  199                 default:  // Should not happen. (Invalid MUX-channel)\r
529 //  200                         Next=0x01;  // Start at the beginning of sequence.\r
530 ??ADC_ISR_5:\r
531         LDI     R25, 1\r
532 //  201                 break;\r
533 //  202         }\r
534 //  203         \r
535 //  204         // Update MUX to next channel in sequence, set a bipolar conversion if\r
536 //  205         // this has been flagged.\r
537 //  206         ADCS.MUX = Next;                    \r
538 ??ADC_ISR_6:\r
539         LDS     R17, ADCS\r
540         ANDI    R17, 0xE0\r
541         MOV     R16, R25\r
542         ANDI    R16, 0x1F\r
543         OR      R16, R17\r
544         STS     ADCS, R16\r
545 //  207         ADMUX = (1<<REFS0) + ADCS.MUX;      \r
546         LDS     R16, ADCS\r
547         ANDI    R16, 0x1F\r
548         SUBI    R16, 192\r
549         OUT     0x07, R16\r
550 //  208 \r
551 //  209         if (Signed)     {\r
552         TST     R4\r
553         BREQ    ??ADC_ISR_14\r
554 //  210           ADCSRB |= (1<<BIN);               \r
555         SBI     0x03, 0x07\r
556         RJMP    ??ADC_ISR_15\r
557 //  211         } else {\r
558 //  212           ADCSRB &= ~(1<<BIN);              \r
559 ??ADC_ISR_14:\r
560         CBI     0x03, 0x07\r
561 //  213         }\r
562 //  214 \r
563 //  215         // Re-enable the ADC unless a halt has been flagged and a conversion\r
564 //  216         // cycle has completed.\r
565 //  217         if (!((ADCS.Halt) && (ADCS.Flag))) {\r
566 ??ADC_ISR_15:\r
567         LDS     R16, ADCS\r
568         ANDI    R16, 0xA0\r
569         CPI     R16, 160\r
570         BREQ    ??ADC_ISR_16\r
571 //  218           ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
572         IN      R16, 0x06\r
573         ORI     R16, 0xC0\r
574         OUT     0x06, R16\r
575 //  219         }\r
576 //  220 }\r
577 ??ADC_ISR_16:\r
578         OUT     0x3F, R5\r
579         LD      R16, Y+\r
580         LD      R17, Y+\r
581         LD      R18, Y+\r
582         LD      R19, Y+\r
583         LD      R20, Y+\r
584         LD      R21, Y+\r
585         LD      R22, Y+\r
586         LD      R23, Y+\r
587         LD      R0, Y+\r
588         LD      R1, Y+\r
589         LD      R2, Y+\r
590         LD      R3, Y+\r
591         LD      R30, Y+\r
592         LD      R31, Y+\r
593         LD      R24, Y+\r
594         LD      R25, Y+\r
595         LD      R26, Y+\r
596         LD      R27, Y+\r
597         LD      R4, Y+\r
598         LD      R5, Y+\r
599         RETI\r
600         REQUIRE _A_ADMUX\r
601         REQUIRE _A_ADCSRA\r
602         REQUIRE _A_ADC\r
603         REQUIRE _A_ADCSRB\r
604 \r
605         RSEG NEAR_Z:DATA:NOROOT(0)\r
606         REQUIRE `?<Segment init: NEAR_Z>`\r
607 ??avgIndex:\r
608         DS 1\r
609 //  221 \r
610 //  222 \r
611 //  223 /*! \brief Scales sample to represent "actual voltage" in mV.\r
612 //  224  *\r
613 //  225  * This function returns the actual sampled voltage, scaled according\r
614 //  226  * to the jumper settings.\r
615 //  227  *\r
616 //  228  * \param setting Indicates what downscaling was used.\r
617 //  229  * \param data The sampled value.\r
618 //  230  *\r
619 //  231  * \note Table for setting-parameter:\n\r
620 //  232  * <pre>\r
621 //  233  * Presume VREF = 2.5V and Gain = 1x.\r
622 //  234  * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
623 //  235  * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
624 //  236  * --------+--------+------+------------+-----------+-------\r
625 //  237  *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
626 //  238  *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
627 //  239  *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
628 //  240  *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
629 //  241  *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
630 //  242  *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
631 //  243  *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
632 //  244  * </pre>\r
633 //  245  */\r
634 \r
635         RSEG CODE:CODE:NOROOT(1)\r
636 //  246 unsigned int ScaleU(unsigned char setting, unsigned int data)\r
637 ScaleU:\r
638 //  247 {\r
639         RCALL   ?PROLOGUE6_L09\r
640         REQUIRE ?Register_R4_is_cg_reg\r
641         REQUIRE ?Register_R5_is_cg_reg\r
642         MOV     R26, R16\r
643         MOVW    R25:R24, R19:R18\r
644 //  248         // Temporary variable needed.\r
645 //  249         unsigned int scaled = 0;\r
646         CLR     R4\r
647         CLR     R5\r
648 //  250 \r
649 //  251         // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
650 //  252         if (setting == 3)       {\r
651         CPI     R26, 3\r
652         BRNE    ??ScaleU_0\r
653 //  253                 scaled = 29 * data;\r
654         MOVW    R21:R20, R25:R24\r
655         LDI     R16, 29\r
656         LDI     R17, 0\r
657         RCALL   ?S_MUL_L02\r
658         MOVW    R5:R4, R17:R16\r
659 //  254                 scaled += (data >> 2);\r
660         MOVW    R17:R16, R25:R24\r
661         LSR     R17\r
662         ROR     R16\r
663         LSR     R17\r
664         ROR     R16\r
665         ADD     R4, R16\r
666         ADC     R5, R17\r
667 //  255                 scaled += (data >> 4);\r
668         MOVW    R17:R16, R25:R24\r
669         LDI     R20, 4\r
670         RCALL   ?US_SHR_L02\r
671         ADD     R4, R16\r
672         ADC     R5, R17\r
673         RJMP    ??ScaleU_1\r
674 //  256         } else {\r
675 //  257                 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
676 //  258                 scaled = 39 * data;\r
677 ??ScaleU_0:\r
678         MOVW    R21:R20, R25:R24\r
679         LDI     R16, 39\r
680         LDI     R17, 0\r
681         RCALL   ?S_MUL_L02\r
682         MOVW    R5:R4, R17:R16\r
683 //  259                 scaled += (data >> 4);\r
684         MOVW    R17:R16, R25:R24\r
685         LDI     R20, 4\r
686         RCALL   ?US_SHR_L02\r
687         ADD     R4, R16\r
688         ADC     R5, R17\r
689 //  260                 \r
690 //  261                 if (setting <3) {\r
691         CPI     R26, 3\r
692         BRCC    ??ScaleU_1\r
693 //  262                         // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
694 //  263                         //                1: mV/LSB = 9.766 = 39.06 / 4\r
695 //  264                         //                2: mV/LSB = 19.53 = 39.06 / 2\r
696 //  265                         scaled = (scaled >> (3-setting));\r
697         MOVW    R17:R16, R5:R4\r
698         LDI     R20, 3\r
699         SUB     R20, R26\r
700         RCALL   ?US_SHR_L02\r
701         MOVW    R5:R4, R17:R16\r
702 //  266                 }\r
703 //  267         }\r
704 //  268 \r
705 //  269         return(scaled);\r
706 ??ScaleU_1:\r
707         MOVW    R17:R16, R5:R4\r
708         LDI     R30, 6\r
709         RJMP    ?EPILOGUE_B6_L09\r
710 //  270 }\r
711 //  271 \r
712 //  272 \r
713 //  273 /*! \brief Scales sample to represent "actual current" in mA.\r
714 //  274  *\r
715 //  275  * This function returns the actual sampled current, scaled according\r
716 //  276  * to the jumper settings.\r
717 //  277  *\r
718 //  278  * \param setting Indicates what downscaling was used.\r
719 //  279  * \param data The sampled value.\r
720 //  280  *\r
721 //  281  * \note Table for setting-parameter:\n\r
722 //  282  * <pre>\r
723 //  283  * Presume VREF = 2.5V and Gain = 1x or 20x.\r
724 //  284  * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
725 //  285  * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
726 //  286  * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
727 //  287  * --------+------+------------+----------+----------+--------+-----\r
728 //  288  *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
729 //  289  *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
730 //  290  *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
731 //  291  *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
732 //  292  *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
733 //  293  *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
734 //  294  *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
735 //  295  * </pre>\r
736 //  296  */\r
737 \r
738         RSEG CODE:CODE:NOROOT(1)\r
739 //  297 unsigned int ScaleI(unsigned char setting, unsigned int data)\r
740 ScaleI:\r
741 //  298 {\r
742         RCALL   ?PROLOGUE6_L09\r
743         REQUIRE ?Register_R4_is_cg_reg\r
744         REQUIRE ?Register_R5_is_cg_reg\r
745         MOV     R26, R16\r
746         MOVW    R25:R24, R19:R18\r
747 //  299         // Temporary variable needed.\r
748 //  300         unsigned int  scaled = 0;\r
749         CLR     R4\r
750         CLR     R5\r
751 //  301         \r
752 //  302         // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
753 //  303         if (setting == 3) {\r
754         CPI     R26, 3\r
755         BRNE    ??ScaleI_0\r
756 //  304                 scaled = 21 * data;\r
757         MOVW    R21:R20, R25:R24\r
758         LDI     R16, 21\r
759         LDI     R17, 0\r
760         RCALL   ?S_MUL_L02\r
761         MOVW    R5:R4, R17:R16\r
762 //  305                 scaled -= (data >> 4);\r
763         MOVW    R17:R16, R25:R24\r
764         LDI     R20, 4\r
765         RCALL   ?US_SHR_L02\r
766         SUB     R4, R16\r
767         SBC     R5, R17\r
768 //  306                 scaled += (data >> 7);\r
769         MOVW    R17:R16, R25:R24\r
770         LSL     R16\r
771         MOV     R16, R17\r
772         ROL     R16\r
773         LDI     R17, 0\r
774         ROL     R17\r
775         ADD     R4, R16\r
776         ADC     R5, R17\r
777         RJMP    ??ScaleI_1\r
778 //  307         }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
779 //  308                 scaled = 28 * data;\r
780 ??ScaleI_0:\r
781         MOVW    R21:R20, R25:R24\r
782         LDI     R16, 28\r
783         LDI     R17, 0\r
784         RCALL   ?S_MUL_L02\r
785         MOVW    R5:R4, R17:R16\r
786 //  309                 scaled -= (data >> 3);\r
787         MOVW    R17:R16, R25:R24\r
788         LDI     R20, 3\r
789         RCALL   ?US_SHR_L02\r
790         SUB     R4, R16\r
791         SBC     R5, R17\r
792 //  310                 scaled += (data >> 5);\r
793         MOVW    R17:R16, R25:R24\r
794         LDI     R20, 5\r
795         RCALL   ?US_SHR_L02\r
796         ADD     R4, R16\r
797         ADC     R5, R17\r
798 //  311                 \r
799 //  312                 if (setting <3) {\r
800         CPI     R26, 3\r
801         BRCC    ??ScaleI_1\r
802 //  313                         // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
803 //  314                         //                1: mA/LSB = 6.978mA = 27.909 / 4\r
804 //  315                         //                2: mA/LSB = 13.955mA = 27.909 / 2\r
805 //  316                         scaled = (scaled >> (3-setting));\r
806         MOVW    R17:R16, R5:R4\r
807         LDI     R20, 3\r
808         SUB     R20, R26\r
809         RCALL   ?US_SHR_L02\r
810         MOVW    R5:R4, R17:R16\r
811 //  317                 }\r
812 //  318         }\r
813 //  319         \r
814 //  320         return(scaled);\r
815 ??ScaleI_1:\r
816         MOVW    R17:R16, R5:R4\r
817         LDI     R30, 6\r
818         RJMP    ?EPILOGUE_B6_L09\r
819 //  321 }\r
820 //  322 \r
821 //  323 \r
822 //  324 /*! \brief Waits for two full cycles of ADC-conversions to occur.\r
823 //  325  *\r
824 //  326  * This function clears the cycle complete-flag, then waits for it to be set\r
825 //  327  * again. This is then repeated once before the function exits.\r
826 //  328  * \r
827 //  329  */\r
828 \r
829         RSEG CODE:CODE:NOROOT(1)\r
830 //  330 void ADC_Wait(void)\r
831 ADC_Wait:\r
832 //  331 {\r
833 //  332         // Clear ADC flag and wait for cycle to complete.\r
834 //  333         ADCS.Flag = FALSE;              \r
835         LDI     R30, LOW(ADCS)\r
836         LDI     R31, (ADCS) >> 8\r
837         LD      R16, Z\r
838         ANDI    R16, 0xDF\r
839         ST      Z, R16\r
840 //  334         do {\r
841 //  335         } while (ADCS.Flag == FALSE);      \r
842 ??ADC_Wait_0:\r
843         LDI     R30, LOW(ADCS)\r
844         LDI     R31, (ADCS) >> 8\r
845         LD      R16, Z\r
846         SBRS    R16, 5\r
847         RJMP    ??ADC_Wait_0\r
848 //  336         \r
849 //  337         // Repeat, so we are sure the data beong to the same cycle.\r
850 //  338         ADCS.Flag = FALSE;              \r
851         LDI     R30, LOW(ADCS)\r
852         LDI     R31, (ADCS) >> 8\r
853         LD      R16, Z\r
854         ANDI    R16, 0xDF\r
855         ST      Z, R16\r
856 //  339         do {\r
857 //  340         } while (ADCS.Flag == FALSE);      \r
858 ??ADC_Wait_1:\r
859         LDI     R30, LOW(ADCS)\r
860         LDI     R31, (ADCS) >> 8\r
861         LD      R16, Z\r
862         SBRS    R16, 5\r
863         RJMP    ??ADC_Wait_1\r
864 //  341 }\r
865         RET\r
866 //  342 \r
867 //  343 \r
868 //  344 /*! \brief Initializes ADC and input pins.\r
869 //  345  *\r
870 //  346  * This function initializes the ADC to free running mode, sampling from\r
871 //  347  * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
872 //  348  * It also measures and stores calibration data for offset.\r
873 //  349  *\r
874 //  350  * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
875 //  351  *\r
876 //  352  * \note Table of MUX settings for offset measurement:\r
877 //  353  * <pre>\r
878 //  354  *    Ch | Pin |    Gain |    MUX\r
879 //  355  * ------+-----+---------+-------\r
880 //  356  *  ADC1 | PA1 |     20x | 001101\r
881 //  357  *  ADC3 | PA4 |     20x | 010001\r
882 //  358  *  ADC5 | PA6 |     20x | 010110\r
883 //  359  *  ADC9 | PB6 |     20x | 011011\r
884 //  360  *  ADC0 | PA0 | 20x/32x | 111000\r
885 //  361  *  ADC0 | PA0 |   1x/8x | 111001\r
886 //  362  *  ADC1 | PA1 | 20x/32x | 111010\r
887 //  363  *  ADC2 | PA2 | 20x/32x | 111011\r
888 //  364  *  ADC4 | PA5 | 20x/32x | 111100\r
889 //  365  *  ADC5 | PA6 | 20x/32x | 111101\r
890 //  366  *  ADC6 | PA7 | 20x/32x | 111110\r
891 //  367  * </pre>\r
892 //  368  */\r
893 \r
894         RSEG CODE:CODE:NOROOT(1)\r
895 //  369 void ADC_Init(void)\r
896 ADC_Init:\r
897 //  370 {\r
898         ST      -Y, R24\r
899 //  371         unsigned char i;\r
900 //  372 \r
901 //  373         __disable_interrupt();\r
902         CLI\r
903 //  374 \r
904 //  375         ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
905         LDI     R30, LOW(ADCS)\r
906         LDI     R31, (ADCS) >> 8\r
907         LD      R16, Z\r
908         ANDI    R16, 0x7F\r
909         ST      Z, R16\r
910 //  376 \r
911 //  377         // Configure ADC pins (inputs and disabled pull-ups).\r
912 //  378         DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
913         IN      R16, 0x1A\r
914         ANDI    R16, 0x09\r
915         OUT     0x1A, R16\r
916 //  379         PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
917         IN      R16, 0x1B\r
918         ANDI    R16, 0x09\r
919         OUT     0x1B, R16\r
920 //  380 \r
921 //  381         // Set ADC3 as reference, and MUX to measure the same pin.\r
922 //  382         ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
923         LDI     R16, 67\r
924         OUT     0x07, R16\r
925 //  383         \r
926 //  384         ADCSRB = 0;\r
927         LDI     R16, 0\r
928         OUT     0x03, R16\r
929 //  385 \r
930 //  386         // Start conversion, no interrupt (disable ADC-ISR).\r
931 //  387         ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
932         LDI     R16, 199\r
933         OUT     0x06, R16\r
934 //  388 \r
935 //  389         do { // Wait for conversion to finish.\r
936 //  390         } while (!(ADCSRA & (1<<ADIF)));\r
937 ??ADC_Init_0:\r
938         SBIS    0x06, 0x04\r
939         RJMP    ??ADC_Init_0\r
940 //  391 \r
941 //  392         ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
942         SBI     0x06, 0x04\r
943 //  393 \r
944 //  394         ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
945         LDS     R18, (ADCS + 1)\r
946         ANDI    R18, 0xF0\r
947         IN      R16, 0x04\r
948         IN      R17, 0x05\r
949         ANDI    R16, 0x0F\r
950         OR      R16, R18\r
951         STS     (ADCS + 1), R16\r
952 //  395 \r
953 //  396         ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
954         LDI     R16, 86\r
955         OUT     0x07, R16\r
956 //  397         \r
957 //  398         // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
958 //  399         ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
959         LDI     R16, 199\r
960         OUT     0x06, R16\r
961 //  400 \r
962 //  401         do { // Wait for conversion to finish.\r
963 //  402         } while (!(ADCSRA & (1<<ADIF)));\r
964 ??ADC_Init_1:\r
965         SBIS    0x06, 0x04\r
966         RJMP    ??ADC_Init_1\r
967 //  403 \r
968 //  404         ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
969         SBI     0x06, 0x04\r
970 //  405 \r
971 //  406         ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
972         LDS     R18, (ADCS + 1)\r
973         ANDI    R18, 0x0F\r
974         IN      R16, 0x04\r
975         IN      R17, 0x05\r
976         SWAP    R16\r
977         ANDI    R16, 0xF0\r
978         OR      R16, R18\r
979         STS     (ADCS + 1), R16\r
980 //  407 \r
981 //  408         // Reset the ADC-cycle.\r
982 //  409         ADCS.Flag = FALSE;      \r
983         LDI     R30, LOW(ADCS)\r
984         LDI     R31, (ADCS) >> 8\r
985         LD      R16, Z\r
986         ANDI    R16, 0xDF\r
987         ST      Z, R16\r
988 //  410         ADCS.MUX = 0x01;                    \r
989         LDS     R16, ADCS\r
990         ANDI    R16, 0xE0\r
991         ORI     R16, 0x01\r
992         STS     ADCS, R16\r
993 //  411         ADMUX = (1<<REFS0) | ADCS.MUX;      \r
994         LDS     R16, ADCS\r
995         ANDI    R16, 0x1F\r
996         ORI     R16, 0x40\r
997         OUT     0x07, R16\r
998 //  412 \r
999 //  413         // Clear averaged battery current and the discrete readings.\r
1000 //  414         ADCS.avgIBAT = 0;\r
1001         LDI     R16, 0\r
1002         LDI     R17, 0\r
1003         LDI     R30, LOW(ADCS)\r
1004         LDI     R31, (ADCS) >> 8\r
1005         STD     Z+22, R16\r
1006         STD     Z+23, R17\r
1007 //  415         \r
1008 //  416         for (i = 0; i < 4; i++) {\r
1009         LDI     R24, 0\r
1010 ??ADC_Init_2:\r
1011         CPI     R24, 4\r
1012         BRCC    ??ADC_Init_3\r
1013 //  417                 ADCS.discIBAT[i] = 0;             \r
1014         LDI     R16, 0\r
1015         LDI     R17, 0\r
1016         MOV     R18, R24\r
1017         LDI     R19, 0\r
1018         LSL     R18\r
1019         ROL     R19\r
1020         MOVW    R31:R30, R19:R18\r
1021         SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
1022         SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
1023         STD     Z+14, R16\r
1024         STD     Z+15, R17\r
1025 //  418         }\r
1026         INC     R24\r
1027         RJMP    ??ADC_Init_2\r
1028 //  419         \r
1029 //  420         // Re-enable the ADC and ISR.\r
1030 //  421         ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
1031 ??ADC_Init_3:\r
1032         LDI     R16, 207\r
1033         OUT     0x06, R16\r
1034 //  422         \r
1035 //  423         __enable_interrupt();\r
1036         SEI\r
1037 //  424 \r
1038 //  425         // Get a complete cycle of data before returning.\r
1039 //  426         ADC_Wait();\r
1040         RCALL   ADC_Wait\r
1041 //  427 }\r
1042         LD      R24, Y+\r
1043         RET\r
1044         REQUIRE _A_PORTA\r
1045         REQUIRE _A_DDRA\r
1046         REQUIRE _A_ADMUX\r
1047         REQUIRE _A_ADCSRA\r
1048         REQUIRE _A_ADC\r
1049         REQUIRE _A_ADCSRB\r
1050 \r
1051         ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
1052 __?EECR:\r
1053 \r
1054         ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
1055 __?EEDR:\r
1056 \r
1057         ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
1058 __?EEARL:\r
1059 \r
1060         ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
1061 __?EEARH:\r
1062 \r
1063         COMMON INTVEC:CODE:ROOT(1)\r
1064         ORG 22\r
1065 `??ADC_ISR??INTVEC 22`:\r
1066         RJMP    ADC_ISR\r
1067 \r
1068         RSEG INITTAB:CODE:NOROOT(0)\r
1069 `?<Segment init: NEAR_Z>`:\r
1070         DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
1071         DW      SFB(NEAR_Z)\r
1072         DW      0\r
1073         REQUIRE ?need_segment_init\r
1074 \r
1075         END\r
1076 // \r
1077 //   7 bytes in segment ABSOLUTE\r
1078 // 946 bytes in segment CODE\r
1079 //   1 byte  in segment EEPROM_I\r
1080 //   6 bytes in segment INITTAB\r
1081 //   2 bytes in segment INTVEC\r
1082 //  25 bytes in segment NEAR_Z\r
1083 // \r
1084 // 946 bytes of CODE  memory (+ 8 bytes shared)\r
1085 //  25 bytes of DATA  memory (+ 7 bytes shared)\r
1086 //   1 byte  of XDATA memory\r
1087 //\r
1088 //Errors: none\r
1089 //Warnings: none\r