1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 /
\r
4 // Copyright 1996-2007 IAR Systems. All rights reserved. /
\r
6 // Source file = C:\home\kevin\pub\src\bc100\IAR\battery.c /
\r
7 // Command line = C:\home\kevin\pub\src\bc100\IAR\battery.c /
\r
8 // --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /
\r
9 // 00\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\Li /
\r
12 // st\ --initializers_in_flash -s9 /
\r
13 // --no_cross_call --no_tbaa /
\r
14 // -DENABLE_BIT_DEFINITIONS -e -I "C:\Program /
\r
15 // 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 --misrac=5-9,11-12,14,16-17, /
\r
19 // 19-21,24-26,29-32,34-35,38-39,42-43,46,50, /
\r
20 // 52-54,56-59,61-62,64-65,68-80,83-84,87-91, /
\r
21 // 94-95,98-100,103-110,112-126 /
\r
22 // Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, /
\r
23 // 38-39,42-43,46,50,52-54,56-59,61-62,64-65, /
\r
24 // 68-80,83-84,87-91,94-95,98-100,103-110,112-126 /
\r
25 // Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, /
\r
26 // 42,46,50,52-54,56-59,61-62,64,68-69,71-80, /
\r
27 // 83-84,87-89,91,94-95,98,100,104-105,108-109, /
\r
28 // 112-115,118-126 /
\r
29 // Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, /
\r
31 // List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\b /
\r
35 ///////////////////////////////////////////////////////////////////////////////
\r
39 RSEG CSTACK:DATA:NOROOT(0)
\r
40 RSEG RSTACK:DATA:NOROOT(0)
\r
42 EXTERN ?Register_R4_is_cg_reg
\r
43 EXTERN ?Register_R5_is_cg_reg
\r
44 EXTERN ?Register_R6_is_cg_reg
\r
45 EXTERN ?Register_R7_is_cg_reg
\r
46 EXTERN ?Register_R8_is_cg_reg
\r
48 EXTERN ?US_DIVMOD_L02
\r
49 EXTERN ?need_segment_init
\r
52 PUBWEAK `?<Segment init: NEAR_I>`
\r
53 PUBWEAK `?<Segment init: NEAR_Z>`
\r
59 PUBLIC BatteryDataRefresh
\r
60 PUBLIC BatteryStatusRefresh
\r
61 PUBLIC DisableBatteries
\r
62 PUBLIC EnableBattery
\r
74 EXTERN OWI_DetectPresence
\r
76 EXTERN OWI_ReceiveByte
\r
77 EXTERN OWI_ComputeCRC8
\r
82 // C:\home\kevin\pub\src\bc100\IAR\battery.c
\r
83 // 1 /* This file has been prepared for Doxygen automatic documentation generation.*/
\r
84 // 2 /*! \file *********************************************************************
\r
87 // 5 * Functions related to battery control and data acquisition.
\r
89 // 7 * Contains functions for enabling/disabling batteries, and looking up
\r
90 // 8 * their status and specifications using the ADC.
\r
92 // 10 * \par Application note:
\r
93 // 11 * AVR458: Charging Li-Ion Batteries with BC100 \n
\r
94 // 12 * AVR463: Charging NiMH Batteries with BC100
\r
97 // 15 * \par Documentation
\r
98 // 16 * For comprehensive code documentation, supported compilers, compiler
\r
99 // 17 * settings and supported devices see readme.html
\r
102 // 20 * Atmel Corporation: http://www.atmel.com \n
\r
103 // 21 * Support email: avr@atmel.com
\r
107 // 25 * $Revision: 2299 $
\r
109 // 27 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $
\r
110 // 28 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n
\r
111 // 29 ******************************************************************************/
\r
113 // 31 #include <ioavr.h>
\r
115 ASEGN ABSOLUTE:DATA:NOROOT,04cH
\r
116 // <unnamed> volatile __io _A_OCR1B
\r
120 ASEGN ABSOLUTE:DATA:NOROOT,038H
\r
121 // <unnamed> volatile __io _A_PORTB
\r
124 // 32 #include <inavr.h>
\r
126 // 34 #include "structs.h"
\r
127 // 35 #include "enums.h"
\r
129 // 37 #include "ADC.h"
\r
130 // 38 #include "battery.h"
\r
131 // 39 #include "main.h"
\r
132 // 40 #include "OWI.h"
\r
133 // 41 #include "time.h"
\r
136 // 44 #include "NIMHspecs.h"
\r
137 // 45 #endif // NIMH
\r
140 // 48 #include "LIIONspecs.h"
\r
141 // 49 #endif // LIION
\r
145 // 53 //******************************************************************************
\r
147 // 55 //******************************************************************************
\r
148 // 56 /* Control-struct for batteries */
\r
149 // 57 /*! \brief Holds control data for both batteries
\r
150 // 58 * \note Stored in EEPROM.
\r
153 RSEG EEPROM_I:XDATA:NOROOT(0)
\r
154 // 60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},
\r
157 // 61 {TRUE, TRUE, FALSE}};
\r
159 // 63 /* Data-struct for battery */
\r
161 RSEG NEAR_Z:DATA:NOROOT(0)
\r
162 REQUIRE `?<Segment init: NEAR_Z>`
\r
163 // 64 Batteries_t BattData; //!< Holds data for the current battery
\r
168 // 67 /* Storage for battery EPROM */
\r
169 // 68 /*! \brief Storage space for data from the batteries' own EPROMs.
\r
170 // 69 * \note Stored in EEPROM.
\r
173 RSEG EEPROM_I:XDATA:NOROOT(0)
\r
174 // 71 __eeprom unsigned char BattEEPROM[4][32];
\r
176 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
177 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
178 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
179 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
180 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
181 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
182 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
183 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
\r
186 // 74 //! Global that indicates current battery (0 = battery A, 1 = B)
\r
188 RSEG NEAR_Z:DATA:NOROOT(0)
\r
189 REQUIRE `?<Segment init: NEAR_Z>`
\r
190 // 75 unsigned char BattActive;
\r
195 // 78 /*! \brief RID lookup-table
\r
197 // 80 * Contains Resistor ID data specified by manufacturer.
\r
199 // 82 * \note Values have been calculated assuming a +/- 15% tolerance.
\r
202 RSEG NEAR_I:DATA:NOROOT(0)
\r
203 REQUIRE `?<Segment init: NEAR_I>`
\r
204 // 84 const RID_Lookup_t RID[RID_TABLE_SIZE] = {
\r
207 REQUIRE `?<Initializer for RID>`
\r
208 // 85 {558, 659, 3900, 550, 260, 300, 10},
\r
209 // 86 {744, 843, 6800, 750, 360, 300, 14},
\r
210 // 87 {869, 958, 10000, 1000, 475, 300, 19},
\r
211 // 88 {1097, 1153, 24000, 2000, 475, 420, 38}
\r
215 // 92 /*! \brief NTC lookup-table
\r
217 // 94 * The first entry is 0 degrees. For every entry after, temperature increases
\r
218 // 95 * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n
\r
219 // 96 * It must be sorted in descending ADC order.
\r
221 // 98 * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.
\r
223 // 100 * \note NTCLookUp() must be modified if this table is changed so that:
\r
224 // 101 * - first entry is no longer 0 degrees.
\r
225 // 102 * - temperature difference between entries is no longer 4 degrees.
\r
226 // 103 * - ADCsteps no longer specifies ADC steps per half degree.
\r
228 // 105 // FOR VARTA POLYFLEX NTC
\r
230 RSEG NEAR_I:DATA:NOROOT(0)
\r
231 REQUIRE `?<Segment init: NEAR_I>`
\r
232 // 106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {
\r
235 REQUIRE `?<Initializer for NTC>`
\r
236 // 107 {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},
\r
237 // 108 {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},
\r
238 // 109 {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},
\r
239 // 110 {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}
\r
243 // 114 // FOR MITSUBISHI NTC
\r
245 // 116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {
\r
246 // 117 {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},
\r
247 // 118 {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},
\r
248 // 119 {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},
\r
249 // 120 {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}
\r
254 // 125 //******************************************************************************
\r
255 // 126 // Functions
\r
256 // 127 //******************************************************************************
\r
257 // 128 /*! \brief Checks if battery has changed
\r
259 // 130 * Stores current capacity, then attempts to refresh battery status.\n
\r
260 // 131 * If the refresh is successful, old capacity is compared with the new one.
\r
262 // 133 * \retval FALSE Battery is disconnected, or capacity has changed.
\r
263 // 134 * \retval TRUE All OK.
\r
266 RSEG CODE:CODE:NOROOT(1)
\r
267 // 136 unsigned char BatteryCheck(void)
\r
273 // 138 unsigned char success = TRUE;
\r
275 // 139 unsigned int oldCapacity;
\r
277 // 141 // Save to see if battery data has changed.
\r
278 // 142 oldCapacity = BattData.Capacity;
\r
279 LDI R30, LOW(BattData)
\r
280 LDI R31, (BattData) >> 8
\r
284 // 144 if (!BatteryStatusRefresh()) {
\r
285 RCALL BatteryStatusRefresh
\r
287 BRNE ??BatteryCheck_0
\r
288 // 145 success = FALSE; // Battery not present or RID was invalid.
\r
292 // 148 if (oldCapacity != BattData.Capacity) {
\r
294 LDI R30, LOW(BattData)
\r
295 LDI R31, (BattData) >> 8
\r
300 BREQ ??BatteryCheck_1
\r
301 // 149 success = FALSE; // Battery configuration has changed.
\r
305 // 152 return(success);
\r
315 // 156 /*! \brief Refreshes battery status information
\r
317 // 158 * Refreshes battery status information, if it is present, based on
\r
318 // 159 * RID and NTC (read by ADC).\n
\r
319 // 160 * The battery must have been enabled and a complete set of ADC data must have
\r
320 // 161 * been collected before calling.\n
\r
322 // 163 * \retval FALSE No battery present.
\r
323 // 164 * \retval TRUE Battery present, status refreshed.
\r
325 // 166 * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry
\r
326 // 167 * is found in the lookup table. Instead, default battery data will be used.
\r
329 RSEG CODE:CODE:NOROOT(1)
\r
330 // 169 unsigned char BatteryStatusRefresh(void)
\r
331 BatteryStatusRefresh:
\r
337 // 171 // Assume the worst..
\r
338 // 172 unsigned char success = FALSE;
\r
340 // 174 BattData.Present = FALSE;
\r
341 // 175 BattData.Charged = FALSE;
\r
342 // 176 BattData.Low = TRUE;
\r
343 LDI R26, LOW(BattData)
\r
344 LDI R27, (BattData) >> 8
\r
349 // 177 BattData.Circuit = OW_NONE;
\r
351 MOVW R31:R30, R27:R26
\r
353 // 178 BattData.Temperature = 0;
\r
355 // 179 BattData.Capacity = 0;
\r
358 // 180 BattData.MaxCurrent = 0;
\r
361 // 181 BattData.MaxTime = 0;
\r
364 // 182 BattData.MinCurrent = 0;
\r
368 // 184 NTCLookUp();
\r
370 // 185 BattData.HasRID = RIDLookUp();
\r
379 // 187 // Is the battery voltage above minimum safe cell voltage?
\r
380 // 188 if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {
\r
382 LDI R31, (ADCS) >> 8
\r
388 BRCS ??BatteryStatusRefresh_0
\r
389 // 189 BattData.Low = FALSE;
\r
395 // 192 // Is the battery charged?
\r
396 // 193 if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {
\r
397 ??BatteryStatusRefresh_0:
\r
401 BRCS ??BatteryStatusRefresh_1
\r
402 // 194 BattData.Charged = TRUE;
\r
408 // 197 // If we are not charging, yet VBAT is above safe limit, battery is present.
\r
409 // 198 // If we are charging and there's a current flowing, the battery is present.
\r
411 // 200 /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence
\r
412 // 201 * check is redundant since charging will be aborted due to low current at
\r
413 // 202 * max duty cycle. That is preferrable since the charge current reading is
\r
414 // 203 * not 100% proof.
\r
416 // 205 if (((OCR1B == 0) && (!BattData.Low)) ||
\r
417 // 206 ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {
\r
418 ??BatteryStatusRefresh_1:
\r
421 BRNE ??BatteryStatusRefresh_2
\r
424 RJMP ??BatteryStatusRefresh_3
\r
425 ??BatteryStatusRefresh_2:
\r
428 BREQ ??BatteryStatusRefresh_4
\r
433 BRLT ??BatteryStatusRefresh_4
\r
434 // 207 BattData.Present = TRUE;
\r
435 ??BatteryStatusRefresh_3:
\r
439 // 208 success = TRUE;
\r
441 RJMP ??BatteryStatusRefresh_5
\r
443 // 210 BattData.Low = FALSE; // (This is just a technicality..)
\r
444 ??BatteryStatusRefresh_4:
\r
448 // 211 success = FALSE;
\r
452 // 214 #ifndef ALLOW_NO_RID
\r
453 // 215 // Return FALSE if no valid RID entry was found, to stop charging.
\r
454 // 216 if(!BattData.HasRID) {
\r
455 ??BatteryStatusRefresh_5:
\r
458 // 217 success = FALSE;
\r
463 // 221 return(success);
\r
464 ??BatteryStatusRefresh_6:
\r
474 // 225 /*! \brief Refreshes battery data in the EEPROM
\r
476 // 227 * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store
\r
477 // 228 * these data in on-chip EEPROM.\n
\r
478 // 229 * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.
\r
480 // 231 * \todo Updating BattData with these data. Specs needed.
\r
482 // 233 * \retval FALSE Refresh failed.
\r
483 // 234 * \retval TRUE Refresh successful.
\r
486 RSEG CODE:CODE:NOROOT(1)
\r
487 // 236 unsigned char BatteryDataRefresh(void)
\r
488 BatteryDataRefresh:
\r
499 REQUIRE ?Register_R4_is_cg_reg
\r
500 REQUIRE ?Register_R5_is_cg_reg
\r
501 REQUIRE ?Register_R6_is_cg_reg
\r
502 REQUIRE ?Register_R7_is_cg_reg
\r
503 REQUIRE ?Register_R8_is_cg_reg
\r
504 // 238 unsigned char offset;
\r
505 // 239 unsigned char i, crc, family, temp, page;
\r
506 // 240 unsigned char success;
\r
508 // 242 // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.
\r
509 // 243 for (page = 0; page < 4; page++) {
\r
511 LDI R26, LOW(BattEEPROM)
\r
512 LDI R27, (BattEEPROM) >> 8
\r
513 // 244 success = FALSE;
\r
514 ??BatteryDataRefresh_0:
\r
517 // 246 if (OWI_DetectPresence(OWIBUS) == OWIBUS) {
\r
519 RCALL OWI_DetectPresence
\r
522 RJMP ??BatteryDataRefresh_1
\r
524 // 248 // Presence detected, check type and CRC.
\r
525 // 249 OWI_SendByte(OWI_ROM_READ, OWIBUS);
\r
529 // 250 family = OWI_ReceiveByte(OWIBUS);
\r
531 RCALL OWI_ReceiveByte
\r
533 // 251 crc = OWI_ComputeCRC8(family,0);
\r
535 RCALL OWI_ComputeCRC8
\r
538 // 253 for (i = 0; i < 6; i++) {
\r
541 // 254 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);
\r
542 ??BatteryDataRefresh_2:
\r
544 RCALL OWI_ReceiveByte
\r
546 RCALL OWI_ComputeCRC8
\r
550 BRNE ??BatteryDataRefresh_2
\r
552 // 257 // CRC ok, device found.
\r
553 // 258 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
\r
555 RCALL OWI_ReceiveByte
\r
557 RCALL OWI_ComputeCRC8
\r
559 BRNE ??BatteryDataRefresh_1
\r
560 // 259 BattData.Circuit = family;
\r
561 STS (BattData + 1), R5
\r
563 // 261 // For now, we only read data from DS2505 EPROMs.
\r
564 // 262 if (BattData.Circuit == OW_DS2505) {
\r
565 LDS R16, (BattData + 1)
\r
567 BRNE ??BatteryDataRefresh_1
\r
568 // 263 offset = page*32;
\r
574 // 264 OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data.
\r
578 // 265 OWI_SendByte(offset, OWIBUS); // Data: low address.
\r
582 // 266 OWI_SendByte(0, OWIBUS); // Data: high address.
\r
587 // 268 // Calculate checksums.
\r
588 // 269 crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);
\r
591 RCALL OWI_ComputeCRC8
\r
592 // 270 crc = OWI_ComputeCRC8(offset,crc);
\r
595 RCALL OWI_ComputeCRC8
\r
596 // 271 crc = OWI_ComputeCRC8(0,crc);
\r
599 RCALL OWI_ComputeCRC8
\r
602 // 273 // Command received succesfully, now start reading data
\r
603 // 274 // and writing it to EEPROM.
\r
604 // 275 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
\r
606 RCALL OWI_ReceiveByte
\r
608 RCALL OWI_ComputeCRC8
\r
610 BRNE ??BatteryDataRefresh_1
\r
614 // 278 // Fill page with data.
\r
615 // 279 for (i=0; i<32; i++) {
\r
616 MOVW R5:R4, R27:R26
\r
619 // 280 temp = OWI_ReceiveByte(OWIBUS);
\r
620 ??BatteryDataRefresh_3:
\r
622 RCALL OWI_ReceiveByte
\r
624 // 281 crc = OWI_ComputeCRC8(temp, crc);
\r
626 RCALL OWI_ComputeCRC8
\r
628 // 282 BattEEPROM[page][i] = temp;
\r
630 MOVW R21:R20, R5:R4
\r
637 BRNE ??BatteryDataRefresh_3
\r
639 // 285 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {
\r
640 RCALL OWI_ReceiveByte
\r
642 RCALL OWI_ComputeCRC8
\r
644 BRNE ??BatteryDataRefresh_1
\r
645 // 286 success = TRUE; // Data read OK
\r
647 RJMP ??BatteryDataRefresh_4
\r
649 // 288 } else { // Not able to start reading data.
\r
651 // 290 } else { // Wrong device type.
\r
653 // 292 } else { // No device found.
\r
655 // 294 } else { // No presence detected on one-wire bus.
\r
658 // 297 // Erase local EEPROM page if there were any errors during transfer.
\r
659 // 298 if (!success) {
\r
660 // 299 for (i=0; i<32; i++) {
\r
661 ??BatteryDataRefresh_1:
\r
662 MOVW R21:R20, R27:R26
\r
664 // 300 BattEEPROM[page][i] = 0;
\r
665 ??BatteryDataRefresh_5:
\r
672 BRNE ??BatteryDataRefresh_5
\r
675 ??BatteryDataRefresh_4:
\r
680 RJMP ??BatteryDataRefresh_0
\r
682 // 305 return(success);
\r
697 // 309 /*! \brief Enables specified battery
\r
699 // 311 * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears
\r
700 // 312 * PB5/PB4 in PORTB, depending on which battery is specified.\n
\r
701 // 313 * The function takes 100 ms to allow the port switch to settle.
\r
703 // 315 * \param bat Specifies which battery to enable (0 = battery A, 1 = B)
\r
706 RSEG CODE:CODE:NOROOT(1)
\r
707 // 317 void EnableBattery(unsigned char bat)
\r
712 // 319 // Use general timer, set timeout to 100ms.
\r
713 // 320 Time_Set(TIMER_GEN,0,0,100);
\r
721 // 322 // Set specified battery as the active one.
\r
722 // 323 BattActive = bat;
\r
723 STS BattActive, R24
\r
725 // 325 // Enable current battery in hardware, light LED & connect battery.
\r
726 // 326 PORTB |= (1 << (PB4+bat));
\r
736 // 328 // Disconnect other battery.
\r
737 // 329 PORTB &= ~(1<<(PB5-bat));
\r
748 // 331 do { // Let port switch settle.
\r
749 // 332 } while (Time_Left(TIMER_GEN));
\r
754 BRNE ??EnableBattery_0
\r
761 // 336 /*! \brief Disables both batteries
\r
763 // 338 * Clears PB4 and PB5 in PORTB, disabling both batteries.
\r
766 RSEG CODE:CODE:NOROOT(1)
\r
767 // 340 void DisableBatteries(void)
\r
770 // 342 // Turn off LEDs and disconnect batteries.
\r
771 // 343 PORTB &= ~((1<<PB4)|(1<<PB5));
\r
780 // 347 /*! \brief Looks up battery data from RID table
\r
782 // 349 * Attempts to find data for the battery from the RID lookup-table.\n
\r
783 // 350 * If no valid entry is found, default data (defined in battery.h)
\r
786 // 353 * \retval TRUE Entry found, battery data updated.
\r
787 // 354 * \retval FALSE No entry found, using defaults for battery data.
\r
790 RSEG CODE:CODE:NOROOT(1)
\r
791 // 356 unsigned char RIDLookUp (void)
\r
796 // 358 unsigned char i, found = FALSE;
\r
799 // 360 // Lookup in the RID-table. If measured RID is within the limits
\r
800 // 361 // of an entry, those data are used, and TRUE is returned.
\r
801 // 362 for (i = 0 ; i < RID_TABLE_SIZE; i++) {
\r
803 LDI R31, (RID) >> 8
\r
805 LDI R16, LOW(BattData)
\r
806 LDI R17, (BattData) >> 8
\r
807 // 363 if (ADCS.rawRID >= RID[i].Low) {
\r
809 LDI R26, LOW((ADCS + 2))
\r
810 LDI R27, HIGH((ADCS + 2))
\r
818 // 364 if (ADCS.rawRID <= RID[i].High) {
\r
824 // 365 BattData.Capacity = RID[i].Capacity;
\r
827 MOVW R27:R26, R17:R16
\r
831 // 366 BattData.MaxCurrent = RID[i].Icharge;
\r
834 MOVW R27:R26, R17:R16
\r
838 // 367 BattData.MaxTime = RID[i].tCutOff;
\r
841 MOVW R27:R26, R17:R16
\r
845 // 368 BattData.MinCurrent = RID[i].ICutOff;
\r
848 MOVW R27:R26, R17:R16
\r
853 // 370 found = TRUE;
\r
863 // 375 // If no valid entry is found, use defaults and return FALSE.
\r
864 // 376 if (!found) {
\r
867 // 377 BattData.Capacity = DEF_BAT_CAPACITY;
\r
869 MOVW R31:R30, R17:R16
\r
872 // 378 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;
\r
875 // 379 BattData.MaxTime = DEF_BAT_TIME_MAX;
\r
878 // 380 BattData.MinCurrent = DEF_BAT_CURRENT_MIN;
\r
883 // 383 return(found);
\r
892 // 387 /*! \brief Calculates temperature from a lookup table
\r
894 // 389 * Looks up the highest NTC value below or equal to the measured one.\n
\r
895 // 390 * With the current lookup table, temperature is calculated with the formula:\n
\r
896 // 391 * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)
\r
898 // 393 * \note If the NTC-measurement is saturated, with the current lookup table,
\r
899 // 394 * the temperature will be reported as -1 C.
\r
901 // 396 * \note If no valid entry is found, battery temperature is set to 80.
\r
904 RSEG CODE:CODE:NOROOT(1)
\r
905 // 398 void NTCLookUp (void)
\r
911 // 400 unsigned char i;
\r
912 // 401 unsigned char found = FALSE;
\r
915 // 403 // Lookup in the NTC-table. Use the first entry which is equal or below
\r
916 // 404 // sampled NTC. Calculate temperature by using the index number, and the
\r
917 // 405 // difference between the measured NTC value and the one in the entry.
\r
918 // 406 for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) {
\r
920 LDI R26, LOW(BattData)
\r
921 LDI R27, (BattData) >> 8
\r
922 // 407 if (ADCS.rawNTC >= NTC[i].ADC) {
\r
926 MOVW R19:R18, R21:R20
\r
932 LDI R19, (NTC) >> 8
\r
936 LDI R31, (ADCS) >> 8
\r
939 MOVW R31:R30, R19:R18
\r
945 // 408 BattData.Temperature = (i<<2) ;
\r
949 MOVW R31:R30, R27:R26
\r
951 // 409 BattData.ADCSteps = NTC[i].ADCsteps;
\r
952 MOVW R31:R30, R19:R18
\r
954 MOVW R31:R30, R27:R26
\r
956 // 410 BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;
\r
957 LDS R16, (ADCS + 4)
\r
959 MOVW R31:R30, R19:R18
\r
967 RCALL ?US_DIVMOD_L02
\r
968 MOVW R31:R30, R27:R26
\r
973 // 412 found = TRUE; // Could be done with a break, but that violates MISRA.
\r
984 // 416 // For safety, is temperature is greater than the NTC
\r
985 // 417 if (!found) {
\r
989 // 418 BattData.Temperature = 80;
\r
991 STS (BattData + 2), R16
\r
1000 ASEGN ABSOLUTE:DATA:NOROOT,01cH
\r
1003 ASEGN ABSOLUTE:DATA:NOROOT,01dH
\r
1006 ASEGN ABSOLUTE:DATA:NOROOT,01eH
\r
1009 ASEGN ABSOLUTE:DATA:NOROOT,01fH
\r
1012 RSEG INITTAB:CODE:NOROOT(0)
\r
1013 `?<Segment init: NEAR_Z>`:
\r
1014 DW SFE(NEAR_Z) - SFB(NEAR_Z)
\r
1017 REQUIRE ?need_segment_init
\r
1019 RSEG NEAR_ID:CODE:NOROOT(0)
\r
1020 `?<Initializer for RID>`:
\r
1021 DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14
\r
1022 DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475
\r
1025 RSEG INITTAB:CODE:NOROOT(0)
\r
1026 `?<Segment init: NEAR_I>`:
\r
1027 DW SFE(NEAR_I) - SFB(NEAR_I)
\r
1030 REQUIRE ?need_segment_init
\r
1032 RSEG NEAR_ID:CODE:NOROOT(0)
\r
1033 `?<Initializer for NTC>`:
\r
1077 // 2 bytes in segment ABSOLUTE
\r
1078 // 804 bytes in segment CODE
\r
1079 // 130 bytes in segment EEPROM_I
\r
1080 // 12 bytes in segment INITTAB
\r
1081 // 116 bytes in segment NEAR_I
\r
1082 // 116 bytes in segment NEAR_ID
\r
1083 // 13 bytes in segment NEAR_Z
\r
1085 // 920 bytes of CODE memory (+ 12 bytes shared)
\r
1086 // 129 bytes of DATA memory (+ 2 bytes shared)
\r
1087 // 130 bytes of XDATA memory
\r