1 ###############################################################################
\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
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 --cpu=tiny861 #
\r
8 # -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ #
\r
9 # -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB #
\r
10 # C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ #
\r
11 # --initializers_in_flash -z2 --no_cse --no_inline #
\r
12 # --no_code_motion --no_cross_call --no_clustering #
\r
13 # --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e #
\r
14 # --require_prototypes -I "C:\Program Files\IAR #
\r
15 # Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program #
\r
16 # Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" #
\r
17 # --eeprom_size 512 #
\r
18 # List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ADC.lst #
\r
19 # Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90 #
\r
22 ###############################################################################
\r
24 C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c
\r
25 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
26 2 /*! \file *********************************************************************
\r
29 5 * Functions for use of ADC
\r
31 7 * Contains high level functions for initializing the ADC, interrupt
\r
32 8 * handling, and treatment of samples.\n
\r
33 9 * The ADC is set to free running mode and uses an external reference
\r
35 11 * To make all sampling take at least 25 clock cycles the ADC is stopped
\r
36 12 * and restarted by the ISR.
\r
38 14 * \par Application note:
\r
39 15 * AVR458: Charging Li-Ion Batteries with BC100 \n
\r
40 16 * AVR463: Charging NiMH Batteries with BC100
\r
42 18 * \par Documentation:
\r
43 19 * For comprehensive code documentation, supported compilers, compiler
\r
44 20 * settings and supported devices see readme.html
\r
47 23 * Atmel Corporation: http://www.atmel.com \n
\r
48 24 * Support email: avr@atmel.com \n
\r
49 25 * Original author: \n
\r
52 28 * $Revision: 2299 $
\r
54 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
55 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n
\r
56 32 ******************************************************************************/
\r
58 34 #include <ioavr.h>
\r
60 \ In segment ABSOLUTE, at 0x3b
\r
61 \ <unnamed> volatile __io _A_PORTA
\r
65 \ In segment ABSOLUTE, at 0x3a
\r
66 \ <unnamed> volatile __io _A_DDRA
\r
70 \ In segment ABSOLUTE, at 0x27
\r
71 \ <unnamed> volatile __io _A_ADMUX
\r
75 \ In segment ABSOLUTE, at 0x26
\r
76 \ <unnamed> volatile __io _A_ADCSRA
\r
80 \ In segment ABSOLUTE, at 0x24
\r
81 \ <unnamed> volatile __io _A_ADC
\r
85 \ In segment ABSOLUTE, at 0x23
\r
86 \ <unnamed> volatile __io _A_ADCSRB
\r
89 35 #include <inavr.h>
\r
91 37 #include "structs.h"
\r
93 39 #include "main.h"
\r
97 43 //******************************************************************************
\r
99 45 //******************************************************************************
\r
100 46 // ADC status struct.
\r
101 47 //! \brief Holds sampled data and ADC-status
\r
103 \ In segment NEAR_Z, align 1, keep-with-next
\r
104 \ 00000000 REQUIRE `?<Segment init: NEAR_Z>`
\r
105 48 ADC_Status_t ADCS;
\r
110 51 /*! \brief Indicates maximum battery voltage.
\r
112 53 * This variable is stored in EEPROM and indicates how much the battery voltage
\r
113 54 * is downscaled by HW before it is sampled. The amount of downscaling depends
\r
114 55 * on the maximum battery voltage, and is necessary to avoid saturation of the
\r
115 56 * ADC (reference voltage is 2.5 V).
\r
117 58 * \note Used by the ADC ISR when calling ScaleU() and ScaleI().
\r
119 60 * \note Defaults to 1, which means 10 V max battery voltage.
\r
121 62 * \note Table of settings:
\r
123 64 * VBAT_RANGE | Max battery voltage | Jumper setting
\r
127 68 * 3 | 30V | 1/12
\r
128 69 * 4 | 40V | 1/16
\r
131 72 // Maximum battery voltage (affects scaling of samples).
\r
133 \ In segment EEPROM_I, align 1, keep-with-next
\r
134 73 __eeprom unsigned char VBAT_RANGE = 1;
\r
139 76 //******************************************************************************
\r
141 78 //******************************************************************************
\r
142 79 /*! \brief Interrupt Service routine for ADC.
\r
144 81 * This ISR stores the sampled values in the ADC status-struct, then
\r
145 82 * updates the ADC MUX to the next channel in the scanning-sequence.\n
\r
146 83 * Once the sequence is completed, ADCS.Flag is set and unless
\r
147 84 * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC
\r
148 85 * is disabled.\n
\r
149 86 * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.
\r
151 88 * \note Table of scanning sequence:
\r
153 90 * Seq | MUX | pos I/P | neg I/P | gain | measure | signed
\r
154 91 * ----+--------+----------+----------+------+---------+-------
\r
155 92 * 01 | 000001 | ADC1/PA1 | n/a | 1x | NTC | no
\r
156 93 * 02 | 000010 | ADC2/PA2 | n/a | 1x | RID | no
\r
157 94 * 03 | 000011 | ADC3/PA4 | n/a | 1x | VIN- | no
\r
158 95 * 04 | 000100 | ADC4/PA5 | n/a | 1x | VIN+ | no
\r
159 96 * 05 | 000101 | ADC5/PA6 | n/a | 1x | VBAT- | no
\r
160 97 * 06 | 000110 | ADC6/PA7 | n/a | 1x | VBAT+ | no
\r
161 98 * 07 | 010010 | ADC4/PA5 | ADC3/PA4 | 20x | IIN | no
\r
162 99 * 08 | 010111 | ADC6/PA7 | ADC5/PA6 | 20x | IBAT | yes
\r
165 102 * \todo IIN (#7 in sequence) is never used.
\r
167 104 * \todo Signed is never set. Signed measurements of IBAT will halve the
\r
168 105 * measuring sensitivity, and is therefore not favourable. At the moment,
\r
169 106 * great currents (f.ex. if something happens with the battery) will be
\r
170 107 * interpreted as negative, which might cause unfavourable behaviour during
\r
171 108 * charging (depending on what PWM behaviour is defined), f.ex.
\r
172 109 * ConstantCurrent() will keep increasing the PWM output. This results in an
\r
173 110 * PWM controller error being flagged and the program going into
\r
174 111 * error-state and eventually reinitializing.
\r
176 113 #pragma vector=ADC_vect
\r
178 \ In segment CODE, align 2, keep-with-next
\r
179 114 __interrupt void ADC_ISR(void)
\r
182 \ 00000000 925A ST -Y, R5
\r
183 \ 00000002 924A ST -Y, R4
\r
184 \ 00000004 93BA ST -Y, R27
\r
185 \ 00000006 93AA ST -Y, R26
\r
186 \ 00000008 939A ST -Y, R25
\r
187 \ 0000000A 938A ST -Y, R24
\r
188 \ 0000000C 93FA ST -Y, R31
\r
189 \ 0000000E 93EA ST -Y, R30
\r
190 \ 00000010 923A ST -Y, R3
\r
191 \ 00000012 922A ST -Y, R2
\r
192 \ 00000014 921A ST -Y, R1
\r
193 \ 00000016 920A ST -Y, R0
\r
194 \ 00000018 937A ST -Y, R23
\r
195 \ 0000001A 936A ST -Y, R22
\r
196 \ 0000001C 935A ST -Y, R21
\r
197 \ 0000001E 934A ST -Y, R20
\r
198 \ 00000020 933A ST -Y, R19
\r
199 \ 00000022 932A ST -Y, R18
\r
200 \ 00000024 931A ST -Y, R17
\r
201 \ 00000026 930A ST -Y, R16
\r
202 \ 00000028 B65F IN R5, 0x3F
\r
203 \ 0000002A REQUIRE ?Register_R4_is_cg_reg
\r
204 \ 0000002A REQUIRE ?Register_R5_is_cg_reg
\r
205 116 static unsigned char avgIndex = 0;
\r
206 117 unsigned char i, Next, Signed;
\r
207 118 signed int temp = 0;
\r
208 \ 0000002A E0A0 LDI R26, 0
\r
209 \ 0000002C E0B0 LDI R27, 0
\r
211 120 Signed = FALSE; // Presume next conversion is unipolar.
\r
212 \ 0000002E 2444 CLR R4
\r
213 121 ADCSRA &= ~(1<<ADEN); // Stop conversion before handling. This makes all
\r
214 \ 00000030 9837 CBI 0x06, 0x07
\r
215 122 // conversions take at least 25 ADCCLK. (It is restarted later)
\r
217 124 // Handle the conversion, depending on what channel it is from, then
\r
218 125 // switch to the next channel in the sequence.
\r
219 126 switch (ADCS.MUX){
\r
220 \ 00000032 9100.... LDS R16, ADCS
\r
221 \ 00000036 710F ANDI R16, 0x1F
\r
222 \ 00000038 5001 SUBI R16, 1
\r
223 \ 0000003A F051 BREQ ??ADC_ISR_0
\r
224 \ 0000003C 950A DEC R16
\r
225 \ 0000003E F081 BREQ ??ADC_ISR_1
\r
226 \ 00000040 950A DEC R16
\r
227 \ 00000042 F0B1 BREQ ??ADC_ISR_2
\r
228 \ 00000044 5002 SUBI R16, 2
\r
229 \ 00000046 F189 BREQ ??ADC_ISR_3
\r
230 \ 00000048 5102 SUBI R16, 18
\r
231 \ 0000004A F409 BRNE $+2+2
\r
232 \ 0000004C C040 RJMP ??ADC_ISR_4
\r
233 \ 0000004E C0AF RJMP ??ADC_ISR_5
\r
234 127 // MUX = 0b000001 => ADC1 (PA1) = NTC
\r
236 129 ADCS.rawNTC = ADC;
\r
238 \ 00000050 B104 IN R16, 0x04
\r
239 \ 00000052 B115 IN R17, 0x05
\r
240 \ 00000054 .... LDI R30, LOW(ADCS)
\r
241 \ 00000056 .... LDI R31, (ADCS) >> 8
\r
242 \ 00000058 8304 STD Z+4, R16
\r
243 \ 0000005A 8315 STD Z+5, R17
\r
245 \ 0000005C E092 LDI R25, 2
\r
246 \ 0000005E C0A8 RJMP ??ADC_ISR_6
\r
250 134 // MUX = 0b000010 => ADC2 (PA2) = RID
\r
252 136 ADCS.rawRID = ADC;
\r
254 \ 00000060 B104 IN R16, 0x04
\r
255 \ 00000062 B115 IN R17, 0x05
\r
256 \ 00000064 .... LDI R30, LOW(ADCS)
\r
257 \ 00000066 .... LDI R31, (ADCS) >> 8
\r
258 \ 00000068 8302 STD Z+2, R16
\r
259 \ 0000006A 8313 STD Z+3, R17
\r
261 \ 0000006C E093 LDI R25, 3
\r
262 \ 0000006E C0A0 RJMP ??ADC_ISR_6
\r
266 141 // MUX = 0b000011 => ADC3 (PA4) = VIN-
\r
268 143 // Supply voltage is always divided by 16.
\r
269 144 ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short.
\r
271 \ 00000070 B124 IN R18, 0x04
\r
272 \ 00000072 B135 IN R19, 0x05
\r
273 \ 00000074 E004 LDI R16, 4
\r
274 \ 00000076 .... RCALL ScaleU
\r
275 \ 00000078 .... LDI R30, LOW(ADCS)
\r
276 \ 0000007A .... LDI R31, (ADCS) >> 8
\r
277 \ 0000007C 8700 STD Z+8, R16
\r
278 \ 0000007E 8711 STD Z+9, R17
\r
280 146 // Is mains failing?
\r
281 147 if (ADCS.VIN < VIN_MIN) {
\r
282 \ 00000080 .... LDI R30, LOW(ADCS)
\r
283 \ 00000082 .... LDI R31, (ADCS) >> 8
\r
284 \ 00000084 8500 LDD R16, Z+8
\r
285 \ 00000086 8511 LDD R17, Z+9
\r
286 \ 00000088 3300 CPI R16, 48
\r
287 \ 0000008A E121 LDI R18, 17
\r
288 \ 0000008C 0712 CPC R17, R18
\r
289 \ 0000008E F430 BRCC ??ADC_ISR_7
\r
290 148 ADCS.Mains = FALSE;
\r
291 \ 00000090 .... LDI R30, LOW(ADCS)
\r
292 \ 00000092 .... LDI R31, (ADCS) >> 8
\r
293 \ 00000094 8100 LD R16, Z
\r
294 \ 00000096 7B0F ANDI R16, 0xBF
\r
295 \ 00000098 8300 ST Z, R16
\r
296 \ 0000009A C005 RJMP ??ADC_ISR_8
\r
298 150 ADCS.Mains = TRUE;
\r
300 \ 0000009C .... LDI R30, LOW(ADCS)
\r
301 \ 0000009E .... LDI R31, (ADCS) >> 8
\r
302 \ 000000A0 8100 LD R16, Z
\r
303 \ 000000A2 6400 ORI R16, 0x40
\r
304 \ 000000A4 8300 ST Z, R16
\r
309 \ 000000A6 E095 LDI R25, 5
\r
310 \ 000000A8 C083 RJMP ??ADC_ISR_6
\r
314 157 // MUX = 0b000101 => ADC5 (PA6) = VBAT-
\r
316 159 ADCS.rawVBAT = ADC;
\r
318 \ 000000AA B104 IN R16, 0x04
\r
319 \ 000000AC B115 IN R17, 0x05
\r
320 \ 000000AE .... LDI R30, LOW(ADCS)
\r
321 \ 000000B0 .... LDI R31, (ADCS) >> 8
\r
322 \ 000000B2 8306 STD Z+6, R16
\r
323 \ 000000B4 8317 STD Z+7, R17
\r
325 161 // Scale voltage according to jumper setting.
\r
326 162 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.
\r
327 \ 000000B6 B124 IN R18, 0x04
\r
328 \ 000000B8 B135 IN R19, 0x05
\r
329 \ 000000BA .... LDI R20, LOW(VBAT_RANGE)
\r
330 \ 000000BC .... LDI R21, (VBAT_RANGE) >> 8
\r
331 \ 000000BE .... RCALL __eeget8_16
\r
332 \ 000000C0 .... RCALL ScaleU
\r
333 \ 000000C2 .... LDI R30, LOW(ADCS)
\r
334 \ 000000C4 .... LDI R31, (ADCS) >> 8
\r
335 \ 000000C6 8702 STD Z+10, R16
\r
336 \ 000000C8 8713 STD Z+11, R17
\r
338 \ 000000CA E197 LDI R25, 23
\r
339 \ 000000CC C071 RJMP ??ADC_ISR_6
\r
340 164 // Signed = TRUE; // Next conversion is bipolar. Halves sensitivity!
\r
344 168 case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT
\r
345 169 // If bipolar, from -512 to 0, to 511:
\r
346 170 // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF
\r
348 172 // Scale sample according to jumper setting, handle negative numbers.
\r
349 173 if (ADC > 511) {
\r
351 \ 000000CE B104 IN R16, 0x04
\r
352 \ 000000D0 B115 IN R17, 0x05
\r
353 \ 000000D2 3000 CPI R16, 0
\r
354 \ 000000D4 E022 LDI R18, 2
\r
355 \ 000000D6 0712 CPC R17, R18
\r
356 \ 000000D8 F0C8 BRCS ??ADC_ISR_9
\r
357 174 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,
\r
358 175 (1024 - (ADC-ADCS.ADC5_G20_OS)));
\r
359 \ 000000DA E000 LDI R16, 0
\r
360 \ 000000DC E014 LDI R17, 4
\r
361 \ 000000DE B124 IN R18, 0x04
\r
362 \ 000000E0 B135 IN R19, 0x05
\r
363 \ 000000E2 1B02 SUB R16, R18
\r
364 \ 000000E4 0B13 SBC R17, R19
\r
365 \ 000000E6 9120.... LDS R18, (ADCS + 1)
\r
366 \ 000000EA 9522 SWAP R18
\r
367 \ 000000EC 702F ANDI R18, 0x0F
\r
368 \ 000000EE E030 LDI R19, 0
\r
369 \ 000000F0 0F20 ADD R18, R16
\r
370 \ 000000F2 1F31 ADC R19, R17
\r
371 \ 000000F4 .... LDI R20, LOW(VBAT_RANGE)
\r
372 \ 000000F6 .... LDI R21, (VBAT_RANGE) >> 8
\r
373 \ 000000F8 .... RCALL __eeget8_16
\r
374 \ 000000FA .... RCALL ScaleI
\r
375 \ 000000FC 9511 NEG R17
\r
376 \ 000000FE 9501 NEG R16
\r
377 \ 00000100 4010 SBCI R17, 0
\r
378 \ 00000102 .... LDI R30, LOW(ADCS)
\r
379 \ 00000104 .... LDI R31, (ADCS) >> 8
\r
380 \ 00000106 8704 STD Z+12, R16
\r
381 \ 00000108 8715 STD Z+13, R17
\r
382 \ 0000010A C01C RJMP ??ADC_ISR_10
\r
383 176 } else if (ADC > 0) {
\r
385 \ 0000010C B104 IN R16, 0x04
\r
386 \ 0000010E B115 IN R17, 0x05
\r
387 \ 00000110 2B01 OR R16, R17
\r
388 \ 00000112 F091 BREQ ??ADC_ISR_11
\r
389 177 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));
\r
390 \ 00000114 B124 IN R18, 0x04
\r
391 \ 00000116 B135 IN R19, 0x05
\r
392 \ 00000118 9100.... LDS R16, (ADCS + 1)
\r
393 \ 0000011C 9502 SWAP R16
\r
394 \ 0000011E 700F ANDI R16, 0x0F
\r
395 \ 00000120 E010 LDI R17, 0
\r
396 \ 00000122 1B20 SUB R18, R16
\r
397 \ 00000124 0B31 SBC R19, R17
\r
398 \ 00000126 .... LDI R20, LOW(VBAT_RANGE)
\r
399 \ 00000128 .... LDI R21, (VBAT_RANGE) >> 8
\r
400 \ 0000012A .... RCALL __eeget8_16
\r
401 \ 0000012C .... RCALL ScaleI
\r
402 \ 0000012E .... LDI R30, LOW(ADCS)
\r
403 \ 00000130 .... LDI R31, (ADCS) >> 8
\r
404 \ 00000132 8704 STD Z+12, R16
\r
405 \ 00000134 8715 STD Z+13, R17
\r
406 \ 00000136 C006 RJMP ??ADC_ISR_10
\r
410 \ 00000138 E000 LDI R16, 0
\r
411 \ 0000013A E010 LDI R17, 0
\r
412 \ 0000013C .... LDI R30, LOW(ADCS)
\r
413 \ 0000013E .... LDI R31, (ADCS) >> 8
\r
414 \ 00000140 8704 STD Z+12, R16
\r
415 \ 00000142 8715 STD Z+13, R17
\r
418 182 // Insert sample of battery current into the averaging-array
\r
419 183 // (overwriting the oldest sample), then recalculate and store the
\r
420 184 // average. This is the last conversion in the sequence, so
\r
421 185 // flag a complete ADC-cycle and restart sequence.
\r
422 186 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;
\r
424 \ 00000144 .... LDI R30, LOW(ADCS)
\r
425 \ 00000146 .... LDI R31, (ADCS) >> 8
\r
426 \ 00000148 8524 LDD R18, Z+12
\r
427 \ 0000014A 8535 LDD R19, Z+13
\r
428 \ 0000014C 9100.... LDS R16, ??avgIndex
\r
429 \ 00000150 E010 LDI R17, 0
\r
430 \ 00000152 7003 ANDI R16, 0x03
\r
431 \ 00000154 7010 ANDI R17, 0x00
\r
432 \ 00000156 0F00 LSL R16
\r
433 \ 00000158 1F11 ROL R17
\r
434 \ 0000015A 01F8 MOVW R31:R30, R17:R16
\r
435 \ 0000015C .... SUBI R30, LOW((-(ADCS) & 0xFFFF))
\r
436 \ 0000015E .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8
\r
437 \ 00000160 8726 STD Z+14, R18
\r
438 \ 00000162 8737 STD Z+15, R19
\r
439 \ 00000164 .... LDI R30, LOW(??avgIndex)
\r
440 \ 00000166 .... LDI R31, (??avgIndex) >> 8
\r
441 \ 00000168 8100 LD R16, Z
\r
442 \ 0000016A 9503 INC R16
\r
443 \ 0000016C 8300 ST Z, R16
\r
444 187 for (i = 0; i < 4 ; i++) {
\r
445 \ 0000016E E080 LDI R24, 0
\r
447 \ 00000170 3084 CPI R24, 4
\r
448 \ 00000172 F468 BRCC ??ADC_ISR_13
\r
449 188 temp += ADCS.discIBAT[i];
\r
450 \ 00000174 2F08 MOV R16, R24
\r
451 \ 00000176 E010 LDI R17, 0
\r
452 \ 00000178 0F00 LSL R16
\r
453 \ 0000017A 1F11 ROL R17
\r
454 \ 0000017C 01F8 MOVW R31:R30, R17:R16
\r
455 \ 0000017E .... SUBI R30, LOW((-(ADCS) & 0xFFFF))
\r
456 \ 00000180 .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8
\r
457 \ 00000182 8506 LDD R16, Z+14
\r
458 \ 00000184 8517 LDD R17, Z+15
\r
459 \ 00000186 0FA0 ADD R26, R16
\r
460 \ 00000188 1FB1 ADC R27, R17
\r
462 \ 0000018A 9583 INC R24
\r
463 \ 0000018C CFF1 RJMP ??ADC_ISR_12
\r
465 191 ADCS.avgIBAT = (temp / 4);
\r
467 \ 0000018E 018D MOVW R17:R16, R27:R26
\r
468 \ 00000190 E044 LDI R20, 4
\r
469 \ 00000192 E050 LDI R21, 0
\r
470 \ 00000194 .... RCALL ?SS_DIVMOD_L02
\r
471 \ 00000196 .... LDI R30, LOW(ADCS)
\r
472 \ 00000198 .... LDI R31, (ADCS) >> 8
\r
473 \ 0000019A 8B06 STD Z+22, R16
\r
474 \ 0000019C 8B17 STD Z+23, R17
\r
476 193 ADCS.Flag = TRUE;
\r
477 \ 0000019E .... LDI R30, LOW(ADCS)
\r
478 \ 000001A0 .... LDI R31, (ADCS) >> 8
\r
479 \ 000001A2 8100 LD R16, Z
\r
480 \ 000001A4 6200 ORI R16, 0x20
\r
481 \ 000001A6 8300 ST Z, R16
\r
483 \ 000001A8 E091 LDI R25, 1
\r
484 195 Signed = FALSE; // This is the only bipolar conversion.
\r
485 \ 000001AA 2444 CLR R4
\r
486 \ 000001AC C001 RJMP ??ADC_ISR_6
\r
490 199 default: // Should not happen. (Invalid MUX-channel)
\r
491 200 Next=0x01; // Start at the beginning of sequence.
\r
493 \ 000001AE E091 LDI R25, 1
\r
497 204 // Update MUX to next channel in sequence, set a bipolar conversion if
\r
498 205 // this has been flagged.
\r
499 206 ADCS.MUX = Next;
\r
501 \ 000001B0 9110.... LDS R17, ADCS
\r
502 \ 000001B4 7E10 ANDI R17, 0xE0
\r
503 \ 000001B6 2F09 MOV R16, R25
\r
504 \ 000001B8 710F ANDI R16, 0x1F
\r
505 \ 000001BA 2B01 OR R16, R17
\r
506 \ 000001BC 9300.... STS ADCS, R16
\r
507 207 ADMUX = (1<<REFS0) + ADCS.MUX;
\r
508 \ 000001C0 9100.... LDS R16, ADCS
\r
509 \ 000001C4 710F ANDI R16, 0x1F
\r
510 \ 000001C6 5C00 SUBI R16, 192
\r
511 \ 000001C8 B907 OUT 0x07, R16
\r
514 \ 000001CA 2044 TST R4
\r
515 \ 000001CC F011 BREQ ??ADC_ISR_14
\r
516 210 ADCSRB |= (1<<BIN);
\r
517 \ 000001CE 9A1F SBI 0x03, 0x07
\r
518 \ 000001D0 C001 RJMP ??ADC_ISR_15
\r
520 212 ADCSRB &= ~(1<<BIN);
\r
522 \ 000001D2 981F CBI 0x03, 0x07
\r
525 215 // Re-enable the ADC unless a halt has been flagged and a conversion
\r
526 216 // cycle has completed.
\r
527 217 if (!((ADCS.Halt) && (ADCS.Flag))) {
\r
529 \ 000001D4 9100.... LDS R16, ADCS
\r
530 \ 000001D8 7A00 ANDI R16, 0xA0
\r
531 \ 000001DA 3A00 CPI R16, 160
\r
532 \ 000001DC F019 BREQ ??ADC_ISR_16
\r
533 218 ADCSRA |= (1<<ADEN)|(1<<ADSC);
\r
534 \ 000001DE B106 IN R16, 0x06
\r
535 \ 000001E0 6C00 ORI R16, 0xC0
\r
536 \ 000001E2 B906 OUT 0x06, R16
\r
540 \ 000001E4 BE5F OUT 0x3F, R5
\r
541 \ 000001E6 9109 LD R16, Y+
\r
542 \ 000001E8 9119 LD R17, Y+
\r
543 \ 000001EA 9129 LD R18, Y+
\r
544 \ 000001EC 9139 LD R19, Y+
\r
545 \ 000001EE 9149 LD R20, Y+
\r
546 \ 000001F0 9159 LD R21, Y+
\r
547 \ 000001F2 9169 LD R22, Y+
\r
548 \ 000001F4 9179 LD R23, Y+
\r
549 \ 000001F6 9009 LD R0, Y+
\r
550 \ 000001F8 9019 LD R1, Y+
\r
551 \ 000001FA 9029 LD R2, Y+
\r
552 \ 000001FC 9039 LD R3, Y+
\r
553 \ 000001FE 91E9 LD R30, Y+
\r
554 \ 00000200 91F9 LD R31, Y+
\r
555 \ 00000202 9189 LD R24, Y+
\r
556 \ 00000204 9199 LD R25, Y+
\r
557 \ 00000206 91A9 LD R26, Y+
\r
558 \ 00000208 91B9 LD R27, Y+
\r
559 \ 0000020A 9049 LD R4, Y+
\r
560 \ 0000020C 9059 LD R5, Y+
\r
561 \ 0000020E 9518 RETI
\r
562 \ 00000210 REQUIRE _A_ADMUX
\r
563 \ 00000210 REQUIRE _A_ADCSRA
\r
564 \ 00000210 REQUIRE _A_ADC
\r
565 \ 00000210 REQUIRE _A_ADCSRB
\r
567 \ In segment NEAR_Z, align 1, keep-with-next
\r
568 \ 00000000 REQUIRE `?<Segment init: NEAR_Z>`
\r
573 223 /*! \brief Scales sample to represent "actual voltage" in mV.
\r
575 225 * This function returns the actual sampled voltage, scaled according
\r
576 226 * to the jumper settings.
\r
578 228 * \param setting Indicates what downscaling was used.
\r
579 229 * \param data The sampled value.
\r
581 231 * \note Table for setting-parameter:\n
\r
583 233 * Presume VREF = 2.5V and Gain = 1x.
\r
584 234 * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB
\r
585 235 * setting | source | R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)
\r
586 236 * --------+--------+------+------------+-----------+-------
\r
587 237 * N/A | | - | - | 2.441mV | 2.50V
\r
588 238 * 0 | VBAT | 10k | 1/2 | 4.883mV | 5.00V
\r
589 239 * 1 | VBAT | 30k | 1/4 | 9.766mV | 9.99V
\r
590 240 * 2 | VBAT | 70k | 1/8 | 19.53mV | 19.98V
\r
591 241 * 3 | VBAT | 110k | 1/12 | 29.30mV | 29.97V
\r
592 242 * 4 | VBAT | 150k | 1/16 | 39.06mV | 39.96V
\r
593 243 * 4 | VIN | 150k | 1/16 | 39.06mV | 39.96V
\r
597 \ In segment CODE, align 2, keep-with-next
\r
598 246 unsigned int ScaleU(unsigned char setting, unsigned int data)
\r
601 \ 00000000 .... RCALL ?PROLOGUE6_L09
\r
602 \ 00000002 REQUIRE ?Register_R4_is_cg_reg
\r
603 \ 00000002 REQUIRE ?Register_R5_is_cg_reg
\r
604 \ 00000002 2FA0 MOV R26, R16
\r
605 \ 00000004 01C9 MOVW R25:R24, R19:R18
\r
606 248 // Temporary variable needed.
\r
607 249 unsigned int scaled = 0;
\r
608 \ 00000006 2444 CLR R4
\r
609 \ 00000008 2455 CLR R5
\r
611 251 // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16
\r
612 252 if (setting == 3) {
\r
613 \ 0000000A 30A3 CPI R26, 3
\r
614 \ 0000000C F491 BRNE ??ScaleU_0
\r
615 253 scaled = 29 * data;
\r
616 \ 0000000E 01AC MOVW R21:R20, R25:R24
\r
617 \ 00000010 E10D LDI R16, 29
\r
618 \ 00000012 E010 LDI R17, 0
\r
619 \ 00000014 .... RCALL ?S_MUL_L02
\r
620 \ 00000016 0128 MOVW R5:R4, R17:R16
\r
621 254 scaled += (data >> 2);
\r
622 \ 00000018 018C MOVW R17:R16, R25:R24
\r
623 \ 0000001A 9516 LSR R17
\r
624 \ 0000001C 9507 ROR R16
\r
625 \ 0000001E 9516 LSR R17
\r
626 \ 00000020 9507 ROR R16
\r
627 \ 00000022 0E40 ADD R4, R16
\r
628 \ 00000024 1E51 ADC R5, R17
\r
629 255 scaled += (data >> 4);
\r
630 \ 00000026 018C MOVW R17:R16, R25:R24
\r
631 \ 00000028 E044 LDI R20, 4
\r
632 \ 0000002A .... RCALL ?US_SHR_L02
\r
633 \ 0000002C 0E40 ADD R4, R16
\r
634 \ 0000002E 1E51 ADC R5, R17
\r
635 \ 00000030 C011 RJMP ??ScaleU_1
\r
637 257 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16
\r
638 258 scaled = 39 * data;
\r
640 \ 00000032 01AC MOVW R21:R20, R25:R24
\r
641 \ 00000034 E207 LDI R16, 39
\r
642 \ 00000036 E010 LDI R17, 0
\r
643 \ 00000038 .... RCALL ?S_MUL_L02
\r
644 \ 0000003A 0128 MOVW R5:R4, R17:R16
\r
645 259 scaled += (data >> 4);
\r
646 \ 0000003C 018C MOVW R17:R16, R25:R24
\r
647 \ 0000003E E044 LDI R20, 4
\r
648 \ 00000040 .... RCALL ?US_SHR_L02
\r
649 \ 00000042 0E40 ADD R4, R16
\r
650 \ 00000044 1E51 ADC R5, R17
\r
652 261 if (setting <3) {
\r
653 \ 00000046 30A3 CPI R26, 3
\r
654 \ 00000048 F428 BRCC ??ScaleU_1
\r
655 262 // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8
\r
656 263 // 1: mV/LSB = 9.766 = 39.06 / 4
\r
657 264 // 2: mV/LSB = 19.53 = 39.06 / 2
\r
658 265 scaled = (scaled >> (3-setting));
\r
659 \ 0000004A 0182 MOVW R17:R16, R5:R4
\r
660 \ 0000004C E043 LDI R20, 3
\r
661 \ 0000004E 1B4A SUB R20, R26
\r
662 \ 00000050 .... RCALL ?US_SHR_L02
\r
663 \ 00000052 0128 MOVW R5:R4, R17:R16
\r
667 269 return(scaled);
\r
669 \ 00000054 0182 MOVW R17:R16, R5:R4
\r
670 \ 00000056 E0E6 LDI R30, 6
\r
671 \ 00000058 .... RJMP ?EPILOGUE_B6_L09
\r
675 273 /*! \brief Scales sample to represent "actual current" in mA.
\r
677 275 * This function returns the actual sampled current, scaled according
\r
678 276 * to the jumper settings.
\r
680 278 * \param setting Indicates what downscaling was used.
\r
681 279 * \param data The sampled value.
\r
683 281 * \note Table for setting-parameter:\n
\r
685 283 * Presume VREF = 2.5V and Gain = 1x or 20x.
\r
686 284 * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
\r
687 285 * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
\r
688 286 * Setting | R1 | R2/(R1+R2) | U(LSB) | I(LSB) | I(MAX) | Gain
\r
689 287 * --------+------+------------+----------+----------+--------+-----
\r
690 288 * N/A | - | - | 0.1221mV | 1.744mA | 1.78A | 20x
\r
691 289 * 0 | 10k | 1/2 | 0.2442mV | 3.489mA | 3.57A | 20x
\r
692 290 * 1 | 30k | 1/4 | 0.4884mV | 6.978mA | 7.14A | 20x
\r
693 291 * 2 | 70k | 1/8 | 0.9768mV | 13.955mA | 14.3A | 20x
\r
694 292 * 3 | 110k | 1/12 | 1.4652mV | 20.931mA | 21.4A | 20x
\r
695 293 * 4 | 150k | 1/16 | 1.9536mV | 27.909mA | 28.5A | 20x
\r
696 294 * 5 | 10k | 1/2 | 2.4414mV | 34.877mA | 35.7A | 1x
\r
700 \ In segment CODE, align 2, keep-with-next
\r
701 297 unsigned int ScaleI(unsigned char setting, unsigned int data)
\r
704 \ 00000000 .... RCALL ?PROLOGUE6_L09
\r
705 \ 00000002 REQUIRE ?Register_R4_is_cg_reg
\r
706 \ 00000002 REQUIRE ?Register_R5_is_cg_reg
\r
707 \ 00000002 2FA0 MOV R26, R16
\r
708 \ 00000004 01C9 MOVW R25:R24, R19:R18
\r
709 299 // Temporary variable needed.
\r
710 300 unsigned int scaled = 0;
\r
711 \ 00000006 2444 CLR R4
\r
712 \ 00000008 2455 CLR R5
\r
714 302 // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128
\r
715 303 if (setting == 3) {
\r
716 \ 0000000A 30A3 CPI R26, 3
\r
717 \ 0000000C F499 BRNE ??ScaleI_0
\r
718 304 scaled = 21 * data;
\r
719 \ 0000000E 01AC MOVW R21:R20, R25:R24
\r
720 \ 00000010 E105 LDI R16, 21
\r
721 \ 00000012 E010 LDI R17, 0
\r
722 \ 00000014 .... RCALL ?S_MUL_L02
\r
723 \ 00000016 0128 MOVW R5:R4, R17:R16
\r
724 305 scaled -= (data >> 4);
\r
725 \ 00000018 018C MOVW R17:R16, R25:R24
\r
726 \ 0000001A E044 LDI R20, 4
\r
727 \ 0000001C .... RCALL ?US_SHR_L02
\r
728 \ 0000001E 1A40 SUB R4, R16
\r
729 \ 00000020 0A51 SBC R5, R17
\r
730 306 scaled += (data >> 7);
\r
731 \ 00000022 018C MOVW R17:R16, R25:R24
\r
732 \ 00000024 0F00 LSL R16
\r
733 \ 00000026 2F01 MOV R16, R17
\r
734 \ 00000028 1F00 ROL R16
\r
735 \ 0000002A E010 LDI R17, 0
\r
736 \ 0000002C 1F11 ROL R17
\r
737 \ 0000002E 0E40 ADD R4, R16
\r
738 \ 00000030 1E51 ADC R5, R17
\r
739 \ 00000032 C016 RJMP ??ScaleI_1
\r
740 307 } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32
\r
741 308 scaled = 28 * data;
\r
743 \ 00000034 01AC MOVW R21:R20, R25:R24
\r
744 \ 00000036 E10C LDI R16, 28
\r
745 \ 00000038 E010 LDI R17, 0
\r
746 \ 0000003A .... RCALL ?S_MUL_L02
\r
747 \ 0000003C 0128 MOVW R5:R4, R17:R16
\r
748 309 scaled -= (data >> 3);
\r
749 \ 0000003E 018C MOVW R17:R16, R25:R24
\r
750 \ 00000040 E043 LDI R20, 3
\r
751 \ 00000042 .... RCALL ?US_SHR_L02
\r
752 \ 00000044 1A40 SUB R4, R16
\r
753 \ 00000046 0A51 SBC R5, R17
\r
754 310 scaled += (data >> 5);
\r
755 \ 00000048 018C MOVW R17:R16, R25:R24
\r
756 \ 0000004A E045 LDI R20, 5
\r
757 \ 0000004C .... RCALL ?US_SHR_L02
\r
758 \ 0000004E 0E40 ADD R4, R16
\r
759 \ 00000050 1E51 ADC R5, R17
\r
761 312 if (setting <3) {
\r
762 \ 00000052 30A3 CPI R26, 3
\r
763 \ 00000054 F428 BRCC ??ScaleI_1
\r
764 313 // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8
\r
765 314 // 1: mA/LSB = 6.978mA = 27.909 / 4
\r
766 315 // 2: mA/LSB = 13.955mA = 27.909 / 2
\r
767 316 scaled = (scaled >> (3-setting));
\r
768 \ 00000056 0182 MOVW R17:R16, R5:R4
\r
769 \ 00000058 E043 LDI R20, 3
\r
770 \ 0000005A 1B4A SUB R20, R26
\r
771 \ 0000005C .... RCALL ?US_SHR_L02
\r
772 \ 0000005E 0128 MOVW R5:R4, R17:R16
\r
776 320 return(scaled);
\r
778 \ 00000060 0182 MOVW R17:R16, R5:R4
\r
779 \ 00000062 E0E6 LDI R30, 6
\r
780 \ 00000064 .... RJMP ?EPILOGUE_B6_L09
\r
784 324 /*! \brief Waits for two full cycles of ADC-conversions to occur.
\r
786 326 * This function clears the cycle complete-flag, then waits for it to be set
\r
787 327 * again. This is then repeated once before the function exits.
\r
791 \ In segment CODE, align 2, keep-with-next
\r
792 330 void ADC_Wait(void)
\r
795 332 // Clear ADC flag and wait for cycle to complete.
\r
796 333 ADCS.Flag = FALSE;
\r
797 \ 00000000 .... LDI R30, LOW(ADCS)
\r
798 \ 00000002 .... LDI R31, (ADCS) >> 8
\r
799 \ 00000004 8100 LD R16, Z
\r
800 \ 00000006 7D0F ANDI R16, 0xDF
\r
801 \ 00000008 8300 ST Z, R16
\r
803 335 } while (ADCS.Flag == FALSE);
\r
805 \ 0000000A .... LDI R30, LOW(ADCS)
\r
806 \ 0000000C .... LDI R31, (ADCS) >> 8
\r
807 \ 0000000E 8100 LD R16, Z
\r
808 \ 00000010 FF05 SBRS R16, 5
\r
809 \ 00000012 CFFB RJMP ??ADC_Wait_0
\r
811 337 // Repeat, so we are sure the data beong to the same cycle.
\r
812 338 ADCS.Flag = FALSE;
\r
813 \ 00000014 .... LDI R30, LOW(ADCS)
\r
814 \ 00000016 .... LDI R31, (ADCS) >> 8
\r
815 \ 00000018 8100 LD R16, Z
\r
816 \ 0000001A 7D0F ANDI R16, 0xDF
\r
817 \ 0000001C 8300 ST Z, R16
\r
819 340 } while (ADCS.Flag == FALSE);
\r
821 \ 0000001E .... LDI R30, LOW(ADCS)
\r
822 \ 00000020 .... LDI R31, (ADCS) >> 8
\r
823 \ 00000022 8100 LD R16, Z
\r
824 \ 00000024 FF05 SBRS R16, 5
\r
825 \ 00000026 CFFB RJMP ??ADC_Wait_1
\r
827 \ 00000028 9508 RET
\r
830 344 /*! \brief Initializes ADC and input pins.
\r
832 346 * This function initializes the ADC to free running mode, sampling from
\r
833 347 * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n
\r
834 348 * It also measures and stores calibration data for offset.
\r
836 350 * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.
\r
838 352 * \note Table of MUX settings for offset measurement:
\r
840 354 * Ch | Pin | Gain | MUX
\r
841 355 * ------+-----+---------+-------
\r
842 356 * ADC1 | PA1 | 20x | 001101
\r
843 357 * ADC3 | PA4 | 20x | 010001
\r
844 358 * ADC5 | PA6 | 20x | 010110
\r
845 359 * ADC9 | PB6 | 20x | 011011
\r
846 360 * ADC0 | PA0 | 20x/32x | 111000
\r
847 361 * ADC0 | PA0 | 1x/8x | 111001
\r
848 362 * ADC1 | PA1 | 20x/32x | 111010
\r
849 363 * ADC2 | PA2 | 20x/32x | 111011
\r
850 364 * ADC4 | PA5 | 20x/32x | 111100
\r
851 365 * ADC5 | PA6 | 20x/32x | 111101
\r
852 366 * ADC6 | PA7 | 20x/32x | 111110
\r
856 \ In segment CODE, align 2, keep-with-next
\r
857 369 void ADC_Init(void)
\r
860 \ 00000000 938A ST -Y, R24
\r
861 371 unsigned char i;
\r
863 373 __disable_interrupt();
\r
864 \ 00000002 94F8 CLI
\r
866 375 ADCS.Halt = FALSE; // Enable consecutive runs of ADC.
\r
867 \ 00000004 .... LDI R30, LOW(ADCS)
\r
868 \ 00000006 .... LDI R31, (ADCS) >> 8
\r
869 \ 00000008 8100 LD R16, Z
\r
870 \ 0000000A 770F ANDI R16, 0x7F
\r
871 \ 0000000C 8300 ST Z, R16
\r
873 377 // Configure ADC pins (inputs and disabled pull-ups).
\r
874 378 DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
\r
875 \ 0000000E B30A IN R16, 0x1A
\r
876 \ 00000010 7009 ANDI R16, 0x09
\r
877 \ 00000012 BB0A OUT 0x1A, R16
\r
878 379 PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));
\r
879 \ 00000014 B30B IN R16, 0x1B
\r
880 \ 00000016 7009 ANDI R16, 0x09
\r
881 \ 00000018 BB0B OUT 0x1B, R16
\r
883 381 // Set ADC3 as reference, and MUX to measure the same pin.
\r
884 382 ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);
\r
885 \ 0000001A E403 LDI R16, 67
\r
886 \ 0000001C B907 OUT 0x07, R16
\r
889 \ 0000001E E000 LDI R16, 0
\r
890 \ 00000020 B903 OUT 0x03, R16
\r
892 386 // Start conversion, no interrupt (disable ADC-ISR).
\r
893 387 ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER;
\r
894 \ 00000022 EC07 LDI R16, 199
\r
895 \ 00000024 B906 OUT 0x06, R16
\r
897 389 do { // Wait for conversion to finish.
\r
898 390 } while (!(ADCSRA & (1<<ADIF)));
\r
900 \ 00000026 9B34 SBIS 0x06, 0x04
\r
901 \ 00000028 CFFE RJMP ??ADC_Init_0
\r
903 392 ADCSRA |= (1<<ADIF); // Clear ADC interrupt flag manually.
\r
904 \ 0000002A 9A34 SBI 0x06, 0x04
\r
906 394 ADCS.ADC3_G20_OS = ADC; // Save the sampled offset.
\r
907 \ 0000002C 9120.... LDS R18, (ADCS + 1)
\r
908 \ 00000030 7F20 ANDI R18, 0xF0
\r
909 \ 00000032 B104 IN R16, 0x04
\r
910 \ 00000034 B115 IN R17, 0x05
\r
911 \ 00000036 700F ANDI R16, 0x0F
\r
912 \ 00000038 2B02 OR R16, R18
\r
913 \ 0000003A 9300.... STS (ADCS + 1), R16
\r
915 396 ADMUX = (1<<REFS0) | 0x16; // ADC5/ADC5 (external ref.), 20x
\r
916 \ 0000003E E506 LDI R16, 86
\r
917 \ 00000040 B907 OUT 0x07, R16
\r
919 398 // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.
\r
920 399 ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER;
\r
921 \ 00000042 EC07 LDI R16, 199
\r
922 \ 00000044 B906 OUT 0x06, R16
\r
924 401 do { // Wait for conversion to finish.
\r
925 402 } while (!(ADCSRA & (1<<ADIF)));
\r
927 \ 00000046 9B34 SBIS 0x06, 0x04
\r
928 \ 00000048 CFFE RJMP ??ADC_Init_1
\r
930 404 ADCSRA |= (1<<ADIF); // Clear ADC interrupt flag.
\r
931 \ 0000004A 9A34 SBI 0x06, 0x04
\r
933 406 ADCS.ADC5_G20_OS = ADC; // Save the sampled offset.
\r
934 \ 0000004C 9120.... LDS R18, (ADCS + 1)
\r
935 \ 00000050 702F ANDI R18, 0x0F
\r
936 \ 00000052 B104 IN R16, 0x04
\r
937 \ 00000054 B115 IN R17, 0x05
\r
938 \ 00000056 9502 SWAP R16
\r
939 \ 00000058 7F00 ANDI R16, 0xF0
\r
940 \ 0000005A 2B02 OR R16, R18
\r
941 \ 0000005C 9300.... STS (ADCS + 1), R16
\r
943 408 // Reset the ADC-cycle.
\r
944 409 ADCS.Flag = FALSE;
\r
945 \ 00000060 .... LDI R30, LOW(ADCS)
\r
946 \ 00000062 .... LDI R31, (ADCS) >> 8
\r
947 \ 00000064 8100 LD R16, Z
\r
948 \ 00000066 7D0F ANDI R16, 0xDF
\r
949 \ 00000068 8300 ST Z, R16
\r
950 410 ADCS.MUX = 0x01;
\r
951 \ 0000006A 9100.... LDS R16, ADCS
\r
952 \ 0000006E 7E00 ANDI R16, 0xE0
\r
953 \ 00000070 6001 ORI R16, 0x01
\r
954 \ 00000072 9300.... STS ADCS, R16
\r
955 411 ADMUX = (1<<REFS0) | ADCS.MUX;
\r
956 \ 00000076 9100.... LDS R16, ADCS
\r
957 \ 0000007A 710F ANDI R16, 0x1F
\r
958 \ 0000007C 6400 ORI R16, 0x40
\r
959 \ 0000007E B907 OUT 0x07, R16
\r
961 413 // Clear averaged battery current and the discrete readings.
\r
962 414 ADCS.avgIBAT = 0;
\r
963 \ 00000080 E000 LDI R16, 0
\r
964 \ 00000082 E010 LDI R17, 0
\r
965 \ 00000084 .... LDI R30, LOW(ADCS)
\r
966 \ 00000086 .... LDI R31, (ADCS) >> 8
\r
967 \ 00000088 8B06 STD Z+22, R16
\r
968 \ 0000008A 8B17 STD Z+23, R17
\r
970 416 for (i = 0; i < 4; i++) {
\r
971 \ 0000008C E080 LDI R24, 0
\r
973 \ 0000008E 3084 CPI R24, 4
\r
974 \ 00000090 F468 BRCC ??ADC_Init_3
\r
975 417 ADCS.discIBAT[i] = 0;
\r
976 \ 00000092 E000 LDI R16, 0
\r
977 \ 00000094 E010 LDI R17, 0
\r
978 \ 00000096 2F28 MOV R18, R24
\r
979 \ 00000098 E030 LDI R19, 0
\r
980 \ 0000009A 0F22 LSL R18
\r
981 \ 0000009C 1F33 ROL R19
\r
982 \ 0000009E 01F9 MOVW R31:R30, R19:R18
\r
983 \ 000000A0 .... SUBI R30, LOW((-(ADCS) & 0xFFFF))
\r
984 \ 000000A2 .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8
\r
985 \ 000000A4 8706 STD Z+14, R16
\r
986 \ 000000A6 8717 STD Z+15, R17
\r
988 \ 000000A8 9583 INC R24
\r
989 \ 000000AA CFF1 RJMP ??ADC_Init_2
\r
991 420 // Re-enable the ADC and ISR.
\r
992 421 ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;
\r
994 \ 000000AC EC0F LDI R16, 207
\r
995 \ 000000AE B906 OUT 0x06, R16
\r
997 423 __enable_interrupt();
\r
998 \ 000000B0 9478 SEI
\r
1000 425 // Get a complete cycle of data before returning.
\r
1002 \ 000000B2 .... RCALL ADC_Wait
\r
1004 \ 000000B4 9189 LD R24, Y+
\r
1005 \ 000000B6 9508 RET
\r
1006 \ 000000B8 REQUIRE _A_PORTA
\r
1007 \ 000000B8 REQUIRE _A_DDRA
\r
1008 \ 000000B8 REQUIRE _A_ADMUX
\r
1009 \ 000000B8 REQUIRE _A_ADCSRA
\r
1010 \ 000000B8 REQUIRE _A_ADC
\r
1011 \ 000000B8 REQUIRE _A_ADCSRB
\r
1013 \ In segment INTVEC, offset 0x16, root
\r
1014 \ `??ADC_ISR??INTVEC 22`:
\r
1015 \ 00000016 .... RJMP ADC_ISR
\r
1017 Maximum stack usage in bytes:
\r
1019 Function CSTACK RSTACK
\r
1020 -------- ------ ------
\r
1033 Segment part sizes:
\r
1035 Function/Label Bytes
\r
1036 -------------- -----
\r
1051 ??ADC_ISR??INTVEC 22 2
\r
1055 7 bytes in segment ABSOLUTE
\r
1056 946 bytes in segment CODE
\r
1057 1 byte in segment EEPROM_I
\r
1058 6 bytes in segment INITTAB
\r
1059 2 bytes in segment INTVEC
\r
1060 25 bytes in segment NEAR_Z
\r
1062 946 bytes of CODE memory (+ 8 bytes shared)
\r
1063 25 bytes of DATA memory (+ 7 bytes shared)
\r
1064 1 byte of XDATA memory
\r