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