Initial import
authorKevin Rosenberg <kevin@rosenberg.net>
Fri, 14 Mar 2008 15:39:54 +0000 (09:39 -0600)
committerKevin Rosenberg <kevin@rosenberg.net>
Fri, 14 Mar 2008 15:39:54 +0000 (09:39 -0600)
159 files changed:
BaseTinyFirmware/GCC/ADC.c [new file with mode: 0644]
BaseTinyFirmware/GCC/ADC.h [new file with mode: 0644]
BaseTinyFirmware/GCC/ChangeLog [new file with mode: 0644]
BaseTinyFirmware/GCC/LIIONspecs.h [new file with mode: 0644]
BaseTinyFirmware/GCC/NIMHspecs.h [new file with mode: 0644]
BaseTinyFirmware/GCC/OWI.c [new file with mode: 0644]
BaseTinyFirmware/GCC/OWI.h [new file with mode: 0644]
BaseTinyFirmware/GCC/PWM.c [new file with mode: 0644]
BaseTinyFirmware/GCC/PWM.h [new file with mode: 0644]
BaseTinyFirmware/GCC/USI.c [new file with mode: 0644]
BaseTinyFirmware/GCC/USI.h [new file with mode: 0644]
BaseTinyFirmware/GCC/atmel.jpg [new file with mode: 0644]
BaseTinyFirmware/GCC/avr458.aps [new file with mode: 0644]
BaseTinyFirmware/GCC/avr458.aws [new file with mode: 0644]
BaseTinyFirmware/GCC/avr463.aps [new file with mode: 0644]
BaseTinyFirmware/GCC/avr463.aws [new file with mode: 0644]
BaseTinyFirmware/GCC/battery.c [new file with mode: 0644]
BaseTinyFirmware/GCC/battery.h [new file with mode: 0644]
BaseTinyFirmware/GCC/blue.GIF [new file with mode: 0644]
BaseTinyFirmware/GCC/charge.h [new file with mode: 0644]
BaseTinyFirmware/GCC/chargefunc.c [new file with mode: 0644]
BaseTinyFirmware/GCC/chargefunc.h [new file with mode: 0644]
BaseTinyFirmware/GCC/config_AVR458.doxygen [new file with mode: 0644]
BaseTinyFirmware/GCC/config_AVR463.doxygen [new file with mode: 0644]
BaseTinyFirmware/GCC/delay_x_gcc.h [new file with mode: 0644]
BaseTinyFirmware/GCC/doxygen.png [new file with mode: 0644]
BaseTinyFirmware/GCC/enums.h [new file with mode: 0644]
BaseTinyFirmware/GCC/liioncharge.c [new file with mode: 0644]
BaseTinyFirmware/GCC/main.c [new file with mode: 0644]
BaseTinyFirmware/GCC/main.h [new file with mode: 0644]
BaseTinyFirmware/GCC/menu.c [new file with mode: 0644]
BaseTinyFirmware/GCC/menu.h [new file with mode: 0644]
BaseTinyFirmware/GCC/nimhcharge.c [new file with mode: 0644]
BaseTinyFirmware/GCC/readme_AVR458.html [new file with mode: 0644]
BaseTinyFirmware/GCC/readme_AVR463.html [new file with mode: 0644]
BaseTinyFirmware/GCC/statefunc.c [new file with mode: 0644]
BaseTinyFirmware/GCC/statefunc.h [new file with mode: 0644]
BaseTinyFirmware/GCC/structs.h [new file with mode: 0644]
BaseTinyFirmware/GCC/time.c [new file with mode: 0644]
BaseTinyFirmware/GCC/time.h [new file with mode: 0644]
BaseTinyFirmware/IAR/ADC.c [new file with mode: 0644]
BaseTinyFirmware/IAR/ADC.h [new file with mode: 0644]
BaseTinyFirmware/IAR/BC100_tiny.dep [new file with mode: 0644]
BaseTinyFirmware/IAR/BC100_tiny.ewd [new file with mode: 0644]
BaseTinyFirmware/IAR/BC100_tiny.ewp [new file with mode: 0644]
BaseTinyFirmware/IAR/BC100_tiny.eww [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Exe/BC100_tiny.d90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/ADC.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/ADC.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/BC100_tiny.html [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/NIMHcharge.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/NIMHcharge.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/OWI.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/OWI.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/PWM.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/PWM.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/USI.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/USI.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/battery.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/battery.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/chargefunc.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/chargefunc.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/main.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/main.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/menu.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/menu.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/statefunc.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/statefunc.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/time.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/List/time.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/ADC.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/BC100_tiny.pbd [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/NIMHcharge.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/OWI.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/PWM.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/USI.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/battery.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/chargefunc.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/main.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/menu.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/statefunc.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Debug/Obj/time.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/LIIONcharge.c [new file with mode: 0644]
BaseTinyFirmware/IAR/LIIONspecs.h [new file with mode: 0644]
BaseTinyFirmware/IAR/NIMHcharge.c [new file with mode: 0644]
BaseTinyFirmware/IAR/NIMHspecs.h [new file with mode: 0644]
BaseTinyFirmware/IAR/OWI.c [new file with mode: 0644]
BaseTinyFirmware/IAR/OWI.h [new file with mode: 0644]
BaseTinyFirmware/IAR/PWM.c [new file with mode: 0644]
BaseTinyFirmware/IAR/PWM.h [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Exe/BC100_tiny.hex [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_data.hex [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_eeprom.hex [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/ADC.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/ADC.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/BC100_tiny.map [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/NIMHcharge.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/NIMHcharge.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/OWI.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/OWI.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/PWM.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/PWM.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/USI.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/USI.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/battery.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/battery.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/chargefunc.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/chargefunc.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/main.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/main.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/menu.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/menu.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/statefunc.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/statefunc.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/time.lst [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/List/time.s90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/ADC.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/BC100_tiny.pbd [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/NIMHcharge.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/OWI.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/PWM.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/USI.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/battery.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/chargefunc.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/main.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/menu.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/statefunc.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/Release/Obj/time.r90 [new file with mode: 0644]
BaseTinyFirmware/IAR/USI.c [new file with mode: 0644]
BaseTinyFirmware/IAR/USI.h [new file with mode: 0644]
BaseTinyFirmware/IAR/atmel.jpg [new file with mode: 0644]
BaseTinyFirmware/IAR/battery.c [new file with mode: 0644]
BaseTinyFirmware/IAR/battery.h [new file with mode: 0644]
BaseTinyFirmware/IAR/blue.GIF [new file with mode: 0644]
BaseTinyFirmware/IAR/charge.h [new file with mode: 0644]
BaseTinyFirmware/IAR/chargefunc.c [new file with mode: 0644]
BaseTinyFirmware/IAR/chargefunc.h [new file with mode: 0644]
BaseTinyFirmware/IAR/config_AVR458.doxygen [new file with mode: 0644]
BaseTinyFirmware/IAR/config_AVR463.doxygen [new file with mode: 0644]
BaseTinyFirmware/IAR/doxygen.png [new file with mode: 0644]
BaseTinyFirmware/IAR/enums.h [new file with mode: 0644]
BaseTinyFirmware/IAR/main.c [new file with mode: 0644]
BaseTinyFirmware/IAR/main.h [new file with mode: 0644]
BaseTinyFirmware/IAR/menu.c [new file with mode: 0644]
BaseTinyFirmware/IAR/menu.h [new file with mode: 0644]
BaseTinyFirmware/IAR/readme_AVR458.html [new file with mode: 0644]
BaseTinyFirmware/IAR/readme_AVR463.html [new file with mode: 0644]
BaseTinyFirmware/IAR/settings/BC100_tiny.cspy.bat [new file with mode: 0644]
BaseTinyFirmware/IAR/settings/BC100_tiny.dbgdt [new file with mode: 0644]
BaseTinyFirmware/IAR/settings/BC100_tiny.dni [new file with mode: 0644]
BaseTinyFirmware/IAR/settings/BC100_tiny.wsdt [new file with mode: 0644]
BaseTinyFirmware/IAR/statefunc.c [new file with mode: 0644]
BaseTinyFirmware/IAR/statefunc.h [new file with mode: 0644]
BaseTinyFirmware/IAR/structs.h [new file with mode: 0644]
BaseTinyFirmware/IAR/time.c [new file with mode: 0644]
BaseTinyFirmware/IAR/time.h [new file with mode: 0644]
BaseTinyFirmware/README [new file with mode: 0644]
BaseTinyFirmware/README.GCC [new file with mode: 0644]
README [new file with mode: 0644]

diff --git a/BaseTinyFirmware/GCC/ADC.c b/BaseTinyFirmware/GCC/ADC.c
new file mode 100644 (file)
index 0000000..004ba8d
--- /dev/null
@@ -0,0 +1,426 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for use of ADC\r
+ *\r
+ *      Contains high level functions for initializing the ADC, interrupt\r
+ *      handling, and treatment of samples.\n\r
+ *      The ADC is set to free running mode and uses an external reference\r
+ *      voltage.\n\r
+ *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
+ *      and restarted by the ISR.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+\r
+#include "structs.h"\r
+\r
+#include "main.h"\r
+#include "ADC.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+// ADC status struct.\r
+//! \brief Holds sampled data and ADC-status\r
+ADC_Status_t ADCS;\r
+\r
+\r
+/*! \brief Indicates maximum battery voltage.\r
+ *\r
+ * This variable is stored in EEPROM and indicates how much the battery voltage\r
+ * is downscaled by HW before it is sampled. The amount of downscaling depends\r
+ * on the maximum battery voltage, and is necessary to avoid saturation of the\r
+ * ADC (reference voltage is 2.5 V).\r
+ *\r
+ * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
+ *\r
+ * \note Defaults to 1, which means 10 V max battery voltage.\r
+ *\r
+ * \note Table of settings:\r
+ * <pre>\r
+ * VBAT_RANGE | Max battery voltage | Jumper setting\r
+ *         0  |             5V      |        1/2\r
+ *         1  |            10V      |        1/4\r
+ *         2  |            20V      |        1/8\r
+ *         3  |            30V      |       1/12\r
+ *         4  |            40V      |       1/16\r
+ * </pre>\r
+ */\r
+// Maximum battery voltage (affects scaling of samples).\r
+unsigned char EEMEM VBAT_RANGE = 1;\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Interrupt Service routine for ADC.\r
+ *\r
+ * This ISR stores the sampled values in the ADC status-struct, then\r
+ * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
+ * Once the sequence is completed, ADCS.Flag is set and unless\r
+ * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC\r
+ * is disabled.\n\r
+ * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
+ *\r
+ * \note Table of scanning sequence:\r
+ * <pre>\r
+ * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
+ * ----+--------+----------+----------+------+---------+-------\r
+ *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
+ *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
+ *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
+ *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
+ *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
+ *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
+ *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
+ *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
+ * </pre>\r
+ *\r
+ * \todo IIN (#7 in sequence) is never used.\r
+ *\r
+ * \todo Signed is never set. Signed measurements of IBAT will halve the\r
+ * measuring sensitivity, and is therefore not favourable. At the moment,\r
+ * great currents (f.ex. if something happens with the battery) will be\r
+ * interpreted as negative, which might cause unfavourable behaviour during\r
+ * charging (depending on what PWM behaviour is defined), f.ex.\r
+ * ConstantCurrent() will keep increasing the PWM output. This results in an\r
+ * PWM controller error being flagged and the program going into\r
+ * error-state and eventually reinitializing.\r
+ */\r
+ISR(ADC_vect)\r
+{\r
+       static unsigned char avgIndex = 0;\r
+       unsigned char i, Next, Signed;\r
+       signed int  temp = 0;\r
+\r
+       Signed = FALSE;  // Presume next conversion is unipolar.\r
+       ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
+         // conversions take at least 25 ADCCLK. (It is restarted later)\r
+\r
+       // Handle the conversion, depending on what channel it is from, then\r
+       // switch to the next channel in the sequence.\r
+       switch (ADCS.MUX){\r
+               // MUX = 0b000001 => ADC1 (PA1) = NTC\r
+               case 0x01:\r
+                       ADCS.rawNTC = ADC;\r
+                       Next=0x02;\r
+               break;\r
+\r
+\r
+               // MUX = 0b000010 => ADC2 (PA2) = RID\r
+               case 0x02:\r
+                       ADCS.rawRID = ADC;\r
+                       Next=0x03;\r
+               break;\r
+\r
+\r
+               // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
+               case 0x03:\r
+                       // Supply voltage is always divided by 16.\r
+                       ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
+\r
+                       // Is mains failing?\r
+                       if (ADCS.VIN < VIN_MIN) {\r
+                               ADCS.Mains = FALSE;\r
+                       } else {\r
+                               ADCS.Mains = TRUE;\r
+                       }\r
+\r
+                       Next=0x05;\r
+               break;\r
+\r
+\r
+               // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
+               case 0x05:\r
+                       ADCS.rawVBAT = ADC;\r
+\r
+                       // Scale voltage according to jumper setting.\r
+                       ADCS.VBAT = ScaleU(eeprom_read_byte(&VBAT_RANGE), (unsigned int)ADC); // ADC is a short.\r
+                       Next=0x17;\r
+//                     Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
+               break;\r
+\r
+\r
+               case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
+                       // If bipolar, from -512 to 0, to 511:\r
+                       // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
+\r
+                       // Scale sample according to jumper setting, handle negative numbers.\r
+                       if (ADC > 511) {\r
+                          ADCS.IBAT = -(signed int)ScaleI(eeprom_read_byte(&VBAT_RANGE),\r
+                                            (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+                       } else if (ADC > 0) {\r
+                          ADCS.IBAT = ScaleI(eeprom_read_byte(&VBAT_RANGE), (ADC-ADCS.ADC5_G20_OS));\r
+                       } else {\r
+                               ADCS.IBAT = 0;\r
+                       }\r
+\r
+                       // Insert sample of battery current into the averaging-array\r
+                       // (overwriting the oldest sample), then recalculate and store the\r
+                       // average. This is the last conversion in the sequence, so\r
+                       // flag a complete ADC-cycle and restart sequence.\r
+                       ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
+                       for (i = 0; i < 4 ; i++) {\r
+                               temp += ADCS.discIBAT[i];\r
+                       }\r
+\r
+                       ADCS.avgIBAT = (temp / 4);\r
+\r
+                       ADCS.Flag = TRUE;\r
+                       Next=0x01;\r
+                       Signed = FALSE;  // This is the only bipolar conversion.\r
+               break;\r
+\r
+\r
+               default:  // Should not happen. (Invalid MUX-channel)\r
+                       Next=0x01;  // Start at the beginning of sequence.\r
+               break;\r
+       }\r
+\r
+       // Update MUX to next channel in sequence, set a bipolar conversion if\r
+       // this has been flagged.\r
+       ADCS.MUX = Next;\r
+       ADMUX = (1<<REFS0) + ADCS.MUX;\r
+\r
+       if (Signed)     {\r
+         ADCSRB |= (1<<BIN);\r
+       } else {\r
+         ADCSRB &= ~(1<<BIN);\r
+       }\r
+\r
+       // Re-enable the ADC unless a halt has been flagged and a conversion\r
+       // cycle has completed.\r
+       if (!((ADCS.Halt) && (ADCS.Flag))) {\r
+         ADCSRA |= (1<<ADEN)|(1<<ADSC);\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Scales sample to represent "actual voltage" in mV.\r
+ *\r
+ * This function returns the actual sampled voltage, scaled according\r
+ * to the jumper settings.\r
+ *\r
+ * \param setting Indicates what downscaling was used.\r
+ * \param data The sampled value.\r
+ *\r
+ * \note Table for setting-parameter:\n\r
+ * <pre>\r
+ * Presume VREF = 2.5V and Gain = 1x.\r
+ * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
+ * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
+ * --------+--------+------+------------+-----------+-------\r
+ *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
+ *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
+ *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
+ *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
+ *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
+ *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
+ *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
+ * </pre>\r
+ */\r
+unsigned int ScaleU(unsigned char setting, unsigned int data)\r
+{\r
+       // Temporary variable needed.\r
+       unsigned int scaled = 0;\r
+\r
+       // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
+       if (setting == 3)       {\r
+               scaled = 29 * data;\r
+               scaled += (data >> 2);\r
+               scaled += (data >> 4);\r
+       } else {\r
+               // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
+               scaled = 39 * data;\r
+               scaled += (data >> 4);\r
+\r
+               if (setting <3) {\r
+                       // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
+                       //                1: mV/LSB = 9.766 = 39.06 / 4\r
+                       //                2: mV/LSB = 19.53 = 39.06 / 2\r
+                       scaled = (scaled >> (3-setting));\r
+               }\r
+       }\r
+\r
+       return(scaled);\r
+}\r
+\r
+\r
+/*! \brief Scales sample to represent "actual current" in mA.\r
+ *\r
+ * This function returns the actual sampled current, scaled according\r
+ * to the jumper settings.\r
+ *\r
+ * \param setting Indicates what downscaling was used.\r
+ * \param data The sampled value.\r
+ *\r
+ * \note Table for setting-parameter:\n\r
+ * <pre>\r
+ * Presume VREF = 2.5V and Gain = 1x or 20x.\r
+ * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
+ * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
+ * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
+ * --------+------+------------+----------+----------+--------+-----\r
+ *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
+ *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
+ *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
+ *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
+ *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
+ *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
+ *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
+ * </pre>\r
+ */\r
+unsigned int ScaleI(unsigned char setting, unsigned int data)\r
+{\r
+       // Temporary variable needed.\r
+       unsigned int  scaled = 0;\r
+\r
+       // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
+       if (setting == 3) {\r
+               scaled = 21 * data;\r
+               scaled -= (data >> 4);\r
+               scaled += (data >> 7);\r
+       }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
+               scaled = 28 * data;\r
+               scaled -= (data >> 3);\r
+               scaled += (data >> 5);\r
+\r
+               if (setting <3) {\r
+                       // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
+                       //                1: mA/LSB = 6.978mA = 27.909 / 4\r
+                       //                2: mA/LSB = 13.955mA = 27.909 / 2\r
+                       scaled = (scaled >> (3-setting));\r
+               }\r
+       }\r
+\r
+       return(scaled);\r
+}\r
+\r
+\r
+/*! \brief Waits for two full cycles of ADC-conversions to occur.\r
+ *\r
+ * This function clears the cycle complete-flag, then waits for it to be set\r
+ * again. This is then repeated once before the function exits.\r
+ *\r
+ */\r
+void ADC_Wait(void)\r
+{\r
+       // Clear ADC flag and wait for cycle to complete.\r
+       ADCS.Flag = FALSE;\r
+       do {\r
+       } while (ADCS.Flag == FALSE);\r
+\r
+       // Repeat, so we are sure the data beong to the same cycle.\r
+       ADCS.Flag = FALSE;\r
+       do {\r
+       } while (ADCS.Flag == FALSE);\r
+}\r
+\r
+\r
+/*! \brief Initializes ADC and input pins.\r
+ *\r
+ * This function initializes the ADC to free running mode, sampling from\r
+ * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
+ * It also measures and stores calibration data for offset.\r
+ *\r
+ * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
+ *\r
+ * \note Table of MUX settings for offset measurement:\r
+ * <pre>\r
+ *    Ch | Pin |    Gain |    MUX\r
+ * ------+-----+---------+-------\r
+ *  ADC1 | PA1 |     20x | 001101\r
+ *  ADC3 | PA4 |     20x | 010001\r
+ *  ADC5 | PA6 |     20x | 010110\r
+ *  ADC9 | PB6 |     20x | 011011\r
+ *  ADC0 | PA0 | 20x/32x | 111000\r
+ *  ADC0 | PA0 |   1x/8x | 111001\r
+ *  ADC1 | PA1 | 20x/32x | 111010\r
+ *  ADC2 | PA2 | 20x/32x | 111011\r
+ *  ADC4 | PA5 | 20x/32x | 111100\r
+ *  ADC5 | PA6 | 20x/32x | 111101\r
+ *  ADC6 | PA7 | 20x/32x | 111110\r
+ * </pre>\r
+ */\r
+void ADC_Init(void)\r
+{\r
+       unsigned char i;\r
+\r
+       cli();\r
+\r
+       ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
+\r
+       // Configure ADC pins (inputs and disabled pull-ups).\r
+       DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+       PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+\r
+       // Set ADC3 as reference, and MUX to measure the same pin.\r
+       ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
+\r
+       ADCSRB = 0;\r
+\r
+       // Start conversion, no interrupt (disable ADC-ISR).\r
+       ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER;\r
+\r
+       do { // Wait for conversion to finish.\r
+       } while (!(ADCSRA & (1<<ADIF)));\r
+\r
+       ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
+\r
+       ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
+\r
+       ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
+\r
+       // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
+       ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER;\r
+\r
+       do { // Wait for conversion to finish.\r
+       } while (!(ADCSRA & (1<<ADIF)));\r
+\r
+       ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
+\r
+       ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
+\r
+       // Reset the ADC-cycle.\r
+       ADCS.Flag = FALSE;\r
+       ADCS.MUX = 0x01;\r
+       ADMUX = (1<<REFS0) | ADCS.MUX;\r
+\r
+       // Clear averaged battery current and the discrete readings.\r
+       ADCS.avgIBAT = 0;\r
+\r
+       for (i = 0; i < 4; i++) {\r
+               ADCS.discIBAT[i] = 0;\r
+       }\r
+\r
+       // Re-enable the ADC and ISR.\r
+       ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
+\r
+       sei();\r
+\r
+       // Get a complete cycle of data before returning.\r
+       ADC_Wait();\r
+}\r
diff --git a/BaseTinyFirmware/GCC/ADC.h b/BaseTinyFirmware/GCC/ADC.h
new file mode 100644 (file)
index 0000000..461dbda
--- /dev/null
@@ -0,0 +1,69 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for ADC.c\r
+ *\r
+ *      Contains definitions for ADC setup, and minimum supply voltage.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef ADC_H\r
+#define ADC_H\r
+\r
+#include <avr/eeprom.h>\r
+\r
+//******************************************************************************\r
+// ADC setup\r
+//******************************************************************************\r
+// 8MHz / (25x128) = 2500 samples/s/ch\r
+#define ADC_PRESCALER     0x07\r
+/*!< \brief Prescaling of ADC clock.\r
+ *\r
+ * The ADC will run at 8 MHz (system clock) divided by 128\r
+ * (prescaler), and every sample will takes approximately 25 ticks:\r
+ * Sample rate = 8 MHz / (128 * 25 cycles/sample) = 2.5 k samples/sec\r
+ */\r
+\r
+\r
+//******************************************************************************\r
+// Minimum supply voltage\r
+//******************************************************************************\r
+//! Minimum supply voltage (at TP101 = VIN+), in mV.\r
+#define VIN_MIN               4400\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern unsigned char EEMEM VBAT_RANGE;\r
+extern ADC_Status_t ADCS;\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned int ScaleU(unsigned char setting, unsigned int data);\r
+unsigned int ScaleI(unsigned char setting, unsigned int data);\r
+void ADC_Wait(void);\r
+void ADC_Init(void);\r
+\r
+#endif // ADC_H\r
+\r
diff --git a/BaseTinyFirmware/GCC/ChangeLog b/BaseTinyFirmware/GCC/ChangeLog
new file mode 100644 (file)
index 0000000..93703b7
--- /dev/null
@@ -0,0 +1,3 @@
+2008-03-12 Kevin Rosenberg <kevin@rosenberg.net>\r
+       * Initial GCC port performed and compiles without error\r
+       * Warning: Not yet tested on BC100 hardware!\r
diff --git a/BaseTinyFirmware/GCC/LIIONspecs.h b/BaseTinyFirmware/GCC/LIIONspecs.h
new file mode 100644 (file)
index 0000000..e662b1e
--- /dev/null
@@ -0,0 +1,102 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Li-Ion specifications\r
+ *\r
+ *      Contains example definitions of Li-Ion battery specifications.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONspecs.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef LIIONSPECS_H\r
+#define LIIONSPECS_H\r
+\r
+\r
+//******************************************************************************\r
+// Cell limits\r
+//******************************************************************************\r
+// This is for common NiMH batteries.\r
+#define        CELL_VOLTAGE_SAFETY     0  /*!< \brief Buffer for unmatched batteries.\r
+ * \r
+ * If we are charging a multicell battery and the cells aren't matched, we\r
+ * may risk overcharging at least one. Therefore, we may subtract this constant\r
+ * per additional cell in battery to allow for a "buffer".\r
+ *\r
+ * \note Set to 0 if batteries are properly matched.\r
+ *\r
+ * \note If this is changed to something higher than (CELL_VOLTAGE_MAX -\r
+ * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit\r
+ * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause\r
+ * the charger to keep trying to charge, but instantly finishing because\r
+ * the battery voltage is already at max.\r
+ */\r
+//! Maximum charge voltage for cell, in mV.\r
+#define        CELL_VOLTAGE_MAX     4200\r
+\r
+//! Minimum voltage to consider cell charged at, in mV.\r
+#define        CELL_VOLTAGE_LOW     4050\r
+\r
+//! Minimum voltage to start charging at, in mV.\r
+#define        CELL_VOLTAGE_MIN     2750\r
+\r
+//! Target voltage during prequalification, in mV.\r
+#define        CELL_VOLTAGE_PREQUAL 3000\r
+\r
+\r
+//******************************************************************************\r
+// Battery limits\r
+//******************************************************************************\r
+// Battery-definitions.\r
+//! Number of cells in battery.\r
+#define        BAT_CELL_NUMBER      1\r
+\r
+//! Maximum cell temperature (Celsius).\r
+#define        BAT_TEMPERATURE_MAX  45\r
+\r
+//! Minimum Cell temperature (Celsius).\r
+#define BAT_TEMPERATURE_MIN   0\r
+\r
+//! Maximum time for prequalification, in minutes.\r
+#define        BAT_TIME_PREQUAL     9\r
+\r
+//! \brief Constant charge current, in mA, during prequalification mode.\r
+//! \note This is typically lower than the main charge current.\r
+#define        BAT_CURRENT_PREQUAL  150\r
+\r
+//! Charge current hysteresis, in mA.\r
+#define        BAT_CURRENT_HYST     5\r
+\r
+//! Charge voltage hysteresis, in mV.\r
+#define        BAT_VOLTAGE_HYST     10\r
+\r
+//! Maximum battery voltage, in mV. \r
+#define        BAT_VOLTAGE_MAX      (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \\r
+                              ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY)\r
+\r
+//! Minimum voltage, in mV, to consider battery charged.\r
+#define        BAT_VOLTAGE_LOW      (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER)\r
+\r
+//! Minimum voltage, in mV, to consider battery safe to charge.\r
+#define        BAT_VOLTAGE_MIN      (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER)\r
+\r
+//! Charge voltage to achieve, in mV, during prequalification mode.\r
+#define BAT_VOLTAGE_PREQUAL    (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER)\r
+\r
+#endif // LIIONSPECS_H\r
diff --git a/BaseTinyFirmware/GCC/NIMHspecs.h b/BaseTinyFirmware/GCC/NIMHspecs.h
new file mode 100644 (file)
index 0000000..cd27677
--- /dev/null
@@ -0,0 +1,108 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      NiMH specifications\r
+ *\r
+ *      Contains example definitions of NiMH battery specifications.\r
+ *\r
+ * \par Application note:\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2255 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHspecs.h $\r
+ * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef NIMHSPECS_H\r
+#define NIMHSPECS_H\r
+\r
+\r
+//******************************************************************************\r
+// Cell limits\r
+//******************************************************************************\r
+// This is for common NiMH batteries.\r
+#define        CELL_VOLTAGE_SAFETY     0  /*!< \brief Buffer for unmatched batteries.\r
+ * \r
+ * If we are charging a multicell battery and the cells aren't matched, we\r
+ * may risk overcharging at least one. Therefore, we may subtract this constant\r
+ * per additional cell in battery to allow for a "buffer".\r
+ *\r
+ * \note Set to 0 if batteries are properly matched.\r
+ *\r
+ * \note If this is changed to something higher than (CELL_VOLTAGE_MAX -\r
+ * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit\r
+ * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause\r
+ * the charger to keep trying to charge, but instantly finishing because\r
+ * the battery voltage is already at max.\r
+ */\r
+//! Maximum charge voltage for cell, in mV.\r
+#define        CELL_VOLTAGE_MAX     1600\r
+\r
+//! Minimum voltage to consider cell charged at, in mV.\r
+#define        CELL_VOLTAGE_LOW     1350\r
+\r
+//! Minimum voltage to start charging at, in mV.\r
+#define        CELL_VOLTAGE_MIN     800\r
+\r
+//! Target voltage during prequalification, in mV.\r
+#define        CELL_VOLTAGE_PREQUAL 1000\r
+\r
+//! Cell voltage drop when full charge is achieved.\r
+#define CELL_VOLTAGE_DROP     15\r
+\r
+\r
+//******************************************************************************\r
+// Battery limits\r
+//******************************************************************************\r
+// Battery-definitions.\r
+//! Number of cells in battery.\r
+#define        BAT_CELL_NUMBER      3\r
+\r
+//! Maximum cell temperature (Celsius).\r
+#define        BAT_TEMPERATURE_MAX  50\r
+\r
+//! Minimum Cell temperature (Celsius).\r
+#define BAT_TEMPERATURE_MIN   5\r
+\r
+//! Maximum time for prequalification, in minutes.\r
+#define        BAT_TIME_PREQUAL     2\r
+\r
+//! \brief Constant charge current, in mA, during prequalification mode.\r
+//! \note This is typically lower than the main charge current.\r
+#define        BAT_CURRENT_PREQUAL  150\r
+\r
+//! Charge current hysteresis, in mA.\r
+#define        BAT_CURRENT_HYST     3\r
+\r
+//! Charge voltage hysteresis, in mV.\r
+#define        BAT_VOLTAGE_HYST     10\r
+\r
+//! Maximum battery voltage, in mV. \r
+#define        BAT_VOLTAGE_MAX      (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \\r
+                              ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY)\r
+\r
+//! Minimum voltage, in mV, to consider battery charged.\r
+#define        BAT_VOLTAGE_LOW      (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER)\r
+\r
+//! Minimum voltage, in mV, to consider battery safe to charge.\r
+#define        BAT_VOLTAGE_MIN      (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER)\r
+\r
+//! Voltage drop, in mV, when full charge is achieved.\r
+#define BAT_VOLTAGE_DROP      (CELL_VOLTAGE_DROP * BAT_CELL_NUMBER)\r
+\r
+//! Charge voltage to achieve, in mV, during prequalification mode.\r
+#define BAT_VOLTAGE_PREQUAL    (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER)\r
+\r
+#endif // NIMHSPECS_H\r
diff --git a/BaseTinyFirmware/GCC/OWI.c b/BaseTinyFirmware/GCC/OWI.c
new file mode 100644 (file)
index 0000000..ef741b9
--- /dev/null
@@ -0,0 +1,524 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file ********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for 1-Wire(R) bus communication\r
+ *\r
+ *      High level functions for transmission of full bytes on the 1-Wire(R)\r
+ *      bus and implementations of ROM commands.\n\r
+ *      Polled software only implementation of the basic bit-level signalling\r
+ *      in the 1-Wire(R) protocol.\n\r
+ *      Includes functions for computing and checking CRC8 & 16 values of data\r
+ *      sets, and of 64 bit ROM identifiers.\r
+ *      Supported devices:  All AVRs.\r
+ *\r
+ * \par Application Note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+ *      AVR463: Charging NiMH Batteries with BC100\n\r
+ *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+****************************************************************************/\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+\r
+// define F_CPU for delay_x_cyles\r
+#define F_CPU ((CPU_FREQUENCY) * 1000000)\r
+#include "delay_x_gcc.h"\r
+\r
+#include "OWI.h"\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Initialization of the one wire bus(es). (Software only driver)\r
+ *  \r
+ *  This function initializes the 1-Wire bus(es) by releasing it and\r
+ *  waiting until any presence signals are finished.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to initialize.\r
+ */\r
+void OWI_Init(unsigned char pins){\r
+       OWI_RELEASE_BUS(pins);\r
+       // The first rising edge can be interpreted by a slave as the end of a\r
+       // Reset-pulse. Delay for the required reset recovery time (H) to be \r
+       // sure that the real reset is interpreted correctly.\r
+       _delay_cycles(OWI_DELAY_H_STD_MODE);\r
+}\r
+\r
+\r
+/*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
+ *\r
+ *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
+ *  bus.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to write to.\r
+ */\r
+void OWI_WriteBit1(unsigned char pins){\r
+       unsigned char intState;\r
+       \r
+       // Disable interrupts.\r
+       intState = SREG & SREG_I;\r
+       cli();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       _delay_cycles(OWI_DELAY_A_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       _delay_cycles(OWI_DELAY_B_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       if (intState)\r
+               sei();\r
+}\r
+\r
+/*! \brief  Write a '0' to the bus(es). (Software only driver)\r
+ *\r
+ *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
+ *  bus.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to write to.\r
+ */\r
+void OWI_WriteBit0(unsigned char pins)\r
+{\r
+       unsigned char intState;\r
+       \r
+       // Disable interrupts.\r
+       intState = SREG & SREG_I;\r
+       cli();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       _delay_cycles(OWI_DELAY_C_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       _delay_cycles(OWI_DELAY_D_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       if (intState)\r
+               sei();\r
+}\r
+\r
+/*! \brief  Read a bit from the bus(es). (Software only driver)\r
+ *\r
+ *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
+ *\r
+ *  \param  pins    A bitmask of the bus(es) to read from.\r
+ *\r
+ *  \return A bitmask of the buses where a '1' was read.\r
+ */\r
+unsigned char OWI_ReadBit(unsigned char pins)\r
+{\r
+       unsigned char intState;\r
+       unsigned char bitsRead;\r
+       \r
+       // Disable interrupts.\r
+       intState = SREG & SREG_I;\r
+       cli();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       _delay_cycles(OWI_DELAY_A_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       _delay_cycles(OWI_DELAY_E_STD_MODE);\r
+       \r
+       // Sample bus and delay.\r
+       bitsRead = OWI_PIN & pins;\r
+       _delay_cycles(OWI_DELAY_F_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       if (intState)\r
+               sei();\r
+       \r
+       return bitsRead;\r
+}\r
+\r
+\r
+/*! \brief  Send a Reset signal and listen for Presence signal. (software\r
+ *  only driver)\r
+ *\r
+ *  Generates the waveform for transmission of a Reset pulse on the \r
+ *  1-Wire(R) bus and listens for presence signals.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
+ *\r
+ *  \return A bitmask of the buses where a presence signal was detected.\r
+ */\r
+unsigned char OWI_DetectPresence(unsigned char pins)\r
+{\r
+       unsigned char intState;\r
+       unsigned char presenceDetected;\r
+       \r
+       // Disable interrupts.\r
+       intState = SREG & SREG_I;\r
+       cli();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       _delay_cycles(OWI_DELAY_H_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       _delay_cycles(OWI_DELAY_I_STD_MODE);\r
+       \r
+       // Sample bus to detect presence signal and delay.\r
+       presenceDetected = ((~OWI_PIN) & pins);\r
+       _delay_cycles(OWI_DELAY_J_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       if (intState)\r
+               sei();\r
+       \r
+       return presenceDetected;\r
+}\r
+\r
+\r
+/*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
+ *  \r
+ *  This function automates the task of sending a complete byte\r
+ *  of data on the 1-Wire bus(es).\r
+ *\r
+ *  \param  data    The data to send on the bus(es).\r
+ *  \r
+ *  \param  pins    A bitmask of the buses to send the data to.\r
+ */\r
+void OWI_SendByte(unsigned char data, unsigned char pins)\r
+{\r
+       unsigned char temp;\r
+       unsigned char i;\r
+       \r
+       // Do once for each bit\r
+       for (i = 0; i < 8; i++) {\r
+               // Determine if LSB is '0' or '1' and transmit corresponding\r
+               // waveform on the bus.\r
+               temp = data & 0x01;\r
+               \r
+               if (temp) {\r
+                       OWI_WriteBit1(pins);\r
+               } else {\r
+                       OWI_WriteBit0(pins);\r
+               }\r
+       \r
+               data >>= 1;  // Right shift the data to get next bit.\r
+       }\r
+}\r
+\r
+\r
+/*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
+ *\r
+ *  This function automates the task of receiving a complete byte \r
+ *  of data from the 1-Wire bus.\r
+ *\r
+ *  \param  pin     A bitmask of the bus to read from.\r
+ *  \r
+ *  \return     The byte read from the bus.\r
+ */\r
+unsigned char OWI_ReceiveByte(unsigned char pin)\r
+{\r
+       unsigned char data;\r
+       unsigned char i;\r
+       \r
+       // Clear the temporary input variable.\r
+       data = 0x00;\r
+       \r
+       // Do once for each bit\r
+       for (i = 0; i < 8; i++) {\r
+               // Shift temporary input variable right.\r
+               data >>= 1;\r
+               \r
+               // Set the MSB if a '1' value is read from the bus.\r
+               // Leave as it is ('0') else.\r
+               if (OWI_ReadBit(pin)) {\r
+                       data |= 0x80;\r
+               }\r
+       }\r
+       \r
+       return data;\r
+}\r
+\r
+\r
+/*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
+ *\r
+ *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
+ */\r
+void OWI_SkipRom(unsigned char pins)\r
+{\r
+       // Send the SKIP ROM command on the bus.\r
+       OWI_SendByte(OWI_ROM_SKIP, pins);\r
+}\r
+\r
+\r
+/*! \brief  Sends the READ ROM command and reads back the ROM id.\r
+ *\r
+ *  \param  romValue    A pointer where the id will be placed.\r
+ *\r
+ *  \param  pin     A bitmask of the bus to read from.\r
+ */\r
+void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
+{\r
+       unsigned char bytesLeft = 8;\r
+       \r
+       // Send the READ ROM command on the bus.\r
+       OWI_SendByte(OWI_ROM_READ, pin);\r
+       \r
+       // Do 8 times.\r
+       while (bytesLeft > 0) {\r
+               // Place the received data in memory.\r
+               *romValue++ = OWI_ReceiveByte(pin);\r
+               bytesLeft--;\r
+       }\r
+}\r
+\r
+\r
+/*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
+ *\r
+ *  \param  romValue    A pointer to the ID to match against.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
+ */\r
+void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
+{\r
+       unsigned char bytesLeft = 8;   \r
+       \r
+       // Send the MATCH ROM command.\r
+       OWI_SendByte(OWI_ROM_MATCH, pins);\r
+       \r
+       // Do once for each byte.\r
+       while (bytesLeft > 0) {\r
+               // Transmit 1 byte of the ID to match.\r
+               OWI_SendByte(*romValue++, pins);\r
+               bytesLeft--;\r
+       }\r
+}\r
+\r
+\r
+/*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
+ *          1-Wire(R) bus.\r
+ *\r
+ *  \param  bitPattern      A pointer to an 8 byte char array where the \r
+ *                          discovered identifier will be placed. When \r
+ *                          searching for several slaves, a copy of the \r
+ *                          last found identifier should be supplied in \r
+ *                          the array, or the search will fail.\r
+ *\r
+ *  \param  lastDeviation   The bit position where the algorithm made a \r
+ *                          choice the last time it was run. This argument \r
+ *                          should be 0 when a search is initiated. Supplying \r
+ *                          the return argument of this function when calling \r
+ *                          repeatedly will go through the complete slave \r
+ *                          search.\r
+ *\r
+ *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
+ *\r
+ *  \return The last bit position where there was a discrepancy between slave\r
+ *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
+ *  if an error was detected (e.g. a device was connected to the bus during the\r
+ *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
+ *  discovered.\r
+ *\r
+ *  \note   See main.c for an example of how to utilize this function.\r
+ */\r
+unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+                                               unsigned char lastDeviation, unsigned char pin)\r
+{\r
+       unsigned char currentBit = 1;\r
+       unsigned char newDeviation = 0;\r
+       unsigned char bitMask = 0x01;\r
+       unsigned char bitA;\r
+       unsigned char bitB;\r
+       \r
+       // Send SEARCH ROM command on the bus.\r
+       OWI_SendByte(OWI_ROM_SEARCH, pin);\r
+       \r
+       // Walk through all 64 bits.\r
+       while (currentBit <= 64) {\r
+               // Read bit from bus twice.\r
+               bitA = OWI_ReadBit(pin);\r
+               bitB = OWI_ReadBit(pin);\r
+               \r
+               if (bitA && bitB) {\r
+                       // Both bits 1 (Error).\r
+                       newDeviation = OWI_ROM_SEARCH_FAILED;\r
+                       return newDeviation;\r
+               } else if (bitA ^ bitB) {\r
+                       // Bits A and B are different. All devices have the same bit here.\r
+                       // Set the bit in bitPattern to this value.\r
+                       if (bitA) {\r
+                               (*bitPattern) |= bitMask;\r
+                       } else {\r
+                               (*bitPattern) &= ~bitMask;\r
+                       }\r
+               } else {\r
+                       // If this is where a choice was made the last time,\r
+                       // a '1' bit is selected this time.\r
+                       if (currentBit == lastDeviation) {\r
+                               (*bitPattern) |= bitMask;\r
+                       }\r
+                       \r
+                       // For the rest of the id, '0' bits are selected when\r
+                       // discrepancies occur.\r
+                       else if (currentBit > lastDeviation) {\r
+                               (*bitPattern) &= ~bitMask;\r
+                               newDeviation = currentBit;\r
+                       }\r
+                       \r
+                       // If current bit in bit pattern = 0, then this is\r
+                       // out new deviation.\r
+                       else if ( !(*bitPattern & bitMask)) {\r
+                               newDeviation = currentBit;\r
+                       }\r
+                       \r
+               // IF the bit is already 1, do nothing.\r
+                       else {\r
+                       }\r
+               }\r
+               \r
+               // Send the selected bit to the bus.\r
+               if ((*bitPattern) & bitMask) {\r
+                       OWI_WriteBit1(pin);\r
+               } else {\r
+                       OWI_WriteBit0(pin);\r
+               }\r
+               \r
+               // Increment current bit.    \r
+               currentBit++;\r
+               \r
+               // Adjust bitMask and bitPattern pointer.    \r
+               bitMask <<= 1;\r
+               if (!bitMask) {\r
+                       bitMask = 0x01;\r
+                       bitPattern++;\r
+               }\r
+       }\r
+       \r
+       return newDeviation;\r
+}\r
+\r
+\r
+/* Functions for handling CRC */\r
+/*! \brief  Compute the CRC8 value of a data set.\r
+ *\r
+ *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
+ *  as inital value for the CRC.\r
+ *\r
+ *  \param  inData  One byte of data to compute CRC from.\r
+ *\r
+ *  \param  seed    The starting value of the CRC.\r
+ *\r
+ *  \return The CRC8 of inData with seed as initial value.\r
+ *\r
+ *  \note   Setting seed to 0 computes the crc8 of the inData.\r
+ *\r
+ *  \note   Constantly passing the return value of this function \r
+ *          As the seed argument computes the CRC8 value of a\r
+ *          longer string of data.\r
+ */\r
+unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
+{\r
+       unsigned char bitsLeft;\r
+       unsigned char temp;\r
+       \r
+       for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+               temp = ((seed ^ inData) & 0x01);\r
+               \r
+               if (temp == 0) {\r
+               seed >>= 1;\r
+               } else {\r
+                       seed ^= 0x18;\r
+                       seed >>= 1;\r
+                       seed |= 0x80;\r
+               }\r
+               \r
+               inData >>= 1;\r
+       }\r
+       return seed;    \r
+}\r
+\r
+\r
+/*! \brief  Compute the CRC16 value of a data set.\r
+ *\r
+ *  This function will compute the CRC16 of inData using seed\r
+ *  as inital value for the CRC.\r
+ *\r
+ *  \param  inData  One byte of data to compute CRC from.\r
+ *\r
+ *  \param  seed    The starting value of the CRC.\r
+ *\r
+ *  \return The CRC16 of inData with seed as initial value.\r
+ *\r
+ *  \note   Setting seed to 0 computes the crc16 of the inData.\r
+ *\r
+ *  \note   Constantly passing the return value of this function \r
+ *          As the seed argument computes the CRC16 value of a\r
+ *          longer string of data.\r
+ */\r
+unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
+{\r
+       unsigned char bitsLeft;\r
+       unsigned char temp;\r
+       \r
+       for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+               temp = ((seed ^ inData) & 0x01);\r
+               \r
+               if (temp == 0) {\r
+                       seed >>= 1;\r
+         } else {\r
+                       seed ^= 0x4002;\r
+                       seed >>= 1;\r
+                       seed |= 0x8000;\r
+               }\r
+\r
+               inData >>= 1;\r
+       }\r
+       \r
+       return seed;    \r
+}\r
+\r
+\r
+/*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
+ *  \r
+ *  This function computes the CRC8 value of the first 56 bits of a\r
+ *  64 bit identifier. It then checks the calculated value against the\r
+ *  CRC value stored in ROM.\r
+ *\r
+ *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
+ *\r
+ *  \retval OWI_CRC_OK      The CRC's matched.\r
+ *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
+ */\r
+unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
+{\r
+       unsigned char i;\r
+       unsigned char crc8 = 0;\r
+       \r
+       for (i = 0; i < 7; i++) {\r
+               crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
+               romValue++;\r
+       }\r
+       \r
+       if (crc8 == (*romValue)) {\r
+               return OWI_CRC_OK;\r
+       }\r
+       \r
+       return OWI_CRC_ERROR;\r
+}\r
diff --git a/BaseTinyFirmware/GCC/OWI.h b/BaseTinyFirmware/GCC/OWI.h
new file mode 100644 (file)
index 0000000..86ffba7
--- /dev/null
@@ -0,0 +1,178 @@
+// This file has been prepared for Doxygen automatic documentation generation.\r
+/*! \file ********************************************************************\r
+ *\r
+ * \brief\r
+ *      Header file for OWI.c\r
+ *\r
+ *      Contains definitions used in the polled 1-Wire(R) driver.\r
+ *\r
+ * \par Application Note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+ *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+****************************************************************************/\r
+\r
+#ifndef OWI_H\r
+#define OWI_H\r
+\r
+#include <avr/io.h>\r
+\r
+\r
+//******************************************************************************\r
+// Defines for CRC-functions\r
+//******************************************************************************\r
+#define     OWI_CRC_OK      0x00    //!< CRC check succeded\r
+#define     OWI_CRC_ERROR   0x01    //!< CRC check failed\r
+\r
+\r
+//******************************************************************************\r
+// Defines for OWI-functions\r
+//******************************************************************************\r
+/*! \brief  CPU clock frequency. \r
+ *  \r
+ *  This define is used to calculate delays when the software only driver\r
+ *  is used. The CPU frequency must be at least 2.170 MHz to be able to\r
+ *  generate the shortest delays.\r
+ */\r
+#define     CPU_FREQUENCY   8.000\r
+\r
+\r
+/*! \brief  Use internal pull-up resistor on 1-Wire buses.\r
+ *\r
+ *  If this symbol is defined, the internal pull-up resister on the GPIO pins \r
+ *  of the AVR will be used to generate the necessary pull-up on the bus. If \r
+ *  an external pull-up resistor is used, uncomment this define.\r
+ */\r
+//#define     OWI_USE_INTERNAL_PULLUP\r
+\r
+\r
+// Port configuration registers for 1-Wire buses.\r
+// Make sure that all three registers belong to the same port.\r
+#define     OWI_PORT        PORTA   //!< 1-Wire PORT Data register.\r
+#define     OWI_PIN         PINA    //!< 1-Wire Input pin register.\r
+#define     OWI_DDR         DDRA    //!< 1-Wire Data direction register.\r
+\r
+\r
+//******************************************************************************\r
+// Pin bitmasks\r
+//******************************************************************************\r
+#define     OWI_PIN_0       0x01\r
+#define     OWI_PIN_1       0x02\r
+#define     OWI_PIN_2       0x04\r
+#define     OWI_PIN_3       0x08\r
+#define     OWI_PIN_4       0x10\r
+#define     OWI_PIN_5       0x20\r
+#define     OWI_PIN_6       0x40\r
+#define     OWI_PIN_7       0x80\r
+\r
+\r
+//******************************************************************************\r
+// Timing parameters\r
+//******************************************************************************\r
+//! Timing delay when pulling bus low and releasing bus.\r
+#define     OWI_DELAY_OFFSET_CYCLES    13   \r
+\r
+// Bit timing delays in clock cycles (= us*clock freq in MHz).\r
+#define     OWI_DELAY_A_STD_MODE    (unsigned long)((6   * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_B_STD_MODE    (unsigned long)((64  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_C_STD_MODE    (unsigned long)((60  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_D_STD_MODE    (unsigned long)((10  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_E_STD_MODE    (unsigned long)((9   * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_F_STD_MODE    (unsigned long)((55  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+//#define     OWI_DELAY_G_STD_MODE  (unsigned long)((0   * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_H_STD_MODE    (unsigned long)((480 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_I_STD_MODE    (unsigned long)((70  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_J_STD_MODE    (unsigned long)((410 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+\r
+\r
+//******************************************************************************\r
+// ROM commands\r
+//******************************************************************************\r
+#define     OWI_ROM_READ    0x33    //!< READ ROM command code.\r
+#define     OWI_ROM_SKIP    0xcc    //!< SKIP ROM command code.\r
+#define     OWI_ROM_MATCH   0x55    //!< MATCH ROM command code.\r
+#define     OWI_ROM_SEARCH  0xf0    //!< SEARCH ROM command code.\r
+\r
+\r
+//******************************************************************************\r
+// Return codes\r
+//******************************************************************************\r
+#define     OWI_ROM_SEARCH_FINISHED     0x00   //!< Search finished return code.\r
+#define     OWI_ROM_SEARCH_FAILED       0xff   //!< Search failed return code.\r
+\r
+\r
+//******************************************************************************\r
+// Macros\r
+//******************************************************************************\r
+/*! \brief Pull 1-Wire bus low.\r
+ *\r
+ *  This macro sets the direction of the 1-Wire pin(s) to output and \r
+ *  pull the line(s) low.\r
+ *  \r
+ *  \param bitMask  A bitmask of the buses to pull low.\r
+ */\r
+#define OWI_PULL_BUS_LOW(bitMask) \\r
+                       OWI_DDR |= (bitMask); \\r
+                       OWI_PORT &= ~(bitMask)\r
+\r
+\r
+/*! \def OWI_RELEASE_BUS(bitMask)\r
+ *\r
+ * \brief  Release the bus. \r
+ *\r
+ * This macro releases the bus and enables the internal pull-up if\r
+ * it is used.\r
+ *\r
+ * \param  bitMask A bitmask of the buses to release.\r
+ */\r
+#ifdef OWI_USE_INTERNAL_PULLUP            \r
+       // Set 1-Wire pin(s) to input and enable internal pull-up resistor.\r
+#define OWI_RELEASE_BUS(bitMask) \\r
+                       OWI_DDR &= ~(bitMask); \\r
+                       OWI_PORT |= (bitMask)\r
+\r
+#else\r
+       // Set 1-Wire pin(s) to input mode. No internal pull-up enabled.\r
+#define OWI_RELEASE_BUS(bitMask) \\r
+                       OWI_DDR &= ~(bitMask); \\r
+                       OWI_PORT &= ~(bitMask)\r
+\r
+#endif\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+void OWI_SendByte(unsigned char data, unsigned char pins);\r
+unsigned char OWI_ReceiveByte(unsigned char pin);\r
+void OWI_SkipRom(unsigned char pins);\r
+void OWI_ReadRom(unsigned char * romValue, unsigned char pin);\r
+void OWI_MatchRom(unsigned char * romValue, unsigned char pins);\r
+unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+                                                                        unsigned char lastDeviation, unsigned char pin);\r
+void OWI_Init(unsigned char pins);\r
+void OWI_WriteBit1(unsigned char pins);\r
+void OWI_WriteBit0(unsigned char pins);\r
+unsigned char OWI_ReadBit(unsigned char pins);\r
+unsigned char OWI_DetectPresence(unsigned char pins);\r
+\r
+unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed);\r
+unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed);\r
+unsigned char OWI_CheckRomCRC(unsigned char *romValue);\r
+\r
+#endif // OWI_H\r
+\r
diff --git a/BaseTinyFirmware/GCC/PWM.c b/BaseTinyFirmware/GCC/PWM.c
new file mode 100644 (file)
index 0000000..9d205fc
--- /dev/null
@@ -0,0 +1,150 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for use of PWM\r
+ *\r
+ *      Contains functions for initializing and controlling PWM output.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+\r
+#include "enums.h"\r
+\r
+#include "main.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Stops PWM output\r
+ *\r
+ */\r
+void PWM_Stop(void)\r
+{\r
+       OCR1B = 0;  // Reset compare level.\r
+       PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
+       TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
+       TCCR1B = 0; // Stop timer/counter1.\r
+       TCCR1C = 0; // Set normal port operation.\r
+       TCCR1D = 0; // No fault protection, normal waveform.\r
+       OCR1C = 0;  // Reset compare.\r
+       OCR1D = 0;  // Reset compare.\r
+       DT1 = 0;    // No dead time values.\r
+}\r
+\r
+\r
+/*! \brief Initializes and starts PWM output\r
+ *\r
+ * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
+ * Its comparator is connected to PB3 and will output high until timer1 reaches\r
+ * the value of OCR1B. It is then dropped to 0.\n\r
+ * The comparator outputs high again when the counter overflows, which will\r
+ * happen at a rate of 250 kHz.\r
+ */\r
+void PWM_Start(void)\r
+{\r
+       // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
+       TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
+       \r
+       // Non-inverted PWM, T/C stopped.\r
+       TCCR1B = 0;\r
+       \r
+       // Copy shadow bits, disconnect OC1D.\r
+       TCCR1C = (TCCR1A & 0xF0);\r
+       \r
+       // No fault protection, use phase & frequency correct PWM.\r
+       TCCR1D = (0<<WGM11)|(1<WGM10);\r
+       \r
+       // Does not matter -- PWM6 mode not used.\r
+       TCCR1E = 0;\r
+       \r
+       // Does not matter -- OC1A is disabled.\r
+       OCR1A = 0;\r
+       \r
+       // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
+       OCR1B = PWM_OFFSET;\r
+       \r
+       // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
+       OCR1C = 0xFF;\r
+       \r
+       // Does not matter -- OC1D is disabled.\r
+       OCR1D = 0;\r
+       \r
+       // No dead time values.\r
+       DT1 = 0;\r
+       \r
+       // Set PWM port pin to output.\r
+       DDRB |= (1<<PB3);\r
+       \r
+       // Enable PLL, use full speed mode.\r
+       PLLCSR = (0<<LSM) | (1<<PLLE);\r
+       \r
+       // Use general timer and wait 1 ms for PLL lock to settle.\r
+       Time_Set(TIMER_GEN,0,0,1);\r
+       do{ \r
+       }while(Time_Left(TIMER_GEN));\r
+       \r
+       // Now wait for PLL to lock.\r
+       do{ \r
+       }while((PLLCSR & (1<<PLOCK)) == 0);\r
+\r
+       // Use PLL as clock source.\r
+       PLLCSR |= (1<<PCKE);\r
+       \r
+       // CLK PCK = 64MHz / 1 = 64MHz.\r
+       TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
+}\r
+\r
+\r
+/*! \brief Increments the PWM duty cycle, if not already at max\r
+ *\r
+ * \retval TRUE Success, duty cycle could be incremented.\r
+ * \retval FALSE Failure, duty cycle already at maximum.\r
+ */\r
+unsigned char PWM_IncrementDutyCycle(void){\r
+\r
+       if (OCR1B < PWM_MAX) {\r
+               OCR1B += 1;\r
+               return(TRUE);\r
+       } else {\r
+               return(FALSE);\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Decrements the PWM duty cycle, if not already at zero.\r
+ *\r
+ * \retval TRUE Success, duty cycle could be decremented.\r
+ * \retval FALSE Failure, duty cycle already at zero.\r
+ */\r
+unsigned char PWM_DecrementDutyCycle(void){\r
+       \r
+       if (OCR1B > 0)  {\r
+               OCR1B -= 1;\r
+               return(TRUE);\r
+       } else {\r
+               return(FALSE);\r
+       }\r
+}\r
diff --git a/BaseTinyFirmware/GCC/PWM.h b/BaseTinyFirmware/GCC/PWM.h
new file mode 100644 (file)
index 0000000..bda3a88
--- /dev/null
@@ -0,0 +1,50 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Header file for PWM.c\r
+ *\r
+ *      Contains definitions to control PWM behaviour.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef PWM_H\r
+#define PWM_H\r
+\r
+//******************************************************************************\r
+// Constants for PWM\r
+//******************************************************************************\r
+//! Needed for JumperCheck() to succeed. ADC is saturated otherwise!\r
+#define PWM_OFFSET     12\r
+\r
+//! PWM duty cycle limit (must be less than 256).\r
+#define PWM_MAX        255\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+void PWM_Start(void);\r
+void PWM_Stop(void);\r
+unsigned char PWM_IncrementDutyCycle(void);\r
+unsigned char PWM_DecrementDutyCycle(void);\r
+\r
+#endif // PWM_H\r
+\r
diff --git a/BaseTinyFirmware/GCC/USI.c b/BaseTinyFirmware/GCC/USI.c
new file mode 100644 (file)
index 0000000..efc004f
--- /dev/null
@@ -0,0 +1,310 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for use of the Universal Serial Interface\r
+ *\r
+ *      Contains high level functions for initializing the USI as an SPI slave,\r
+ *      interrupt handling, sending and receiving single bytes.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "main.h"\r
+#include "ADC.h"\r
+#include "battery.h"\r
+#include "time.h"\r
+#include "USI.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+//! SPI status struct\r
+SPI_Status_t SPI;\r
+\r
+\r
+//******************************************************************************\r
+//Functions\r
+//*****************************************************************************\r
+/*! \brief USI Counter Overflow Interrupt Service Routine\r
+ *\r
+ * When the USI counter overflows, a byte has been transferred.\n\r
+ * The USIDR contents are stored and flags are updated.\r
+ *\r
+ * The protocol is quite simple and has three sequential states: command,\r
+ * address and data.\r
+ * (Keep in mind that the Master is in charge of data clocking, which means\r
+ * there is a one byte "delay" from when the Slave puts something to SPI till\r
+ * the Master can read it.)\r
+ *\r
+ * 1. If a non-zero byte is received in the command state, the ISR will\r
+ * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
+ * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
+ * If a zero byte (0x00) is received in the command state, it is simply ignored\r
+ * because it is an invalid command.\r
+ *\r
+ * 2. When a byte is received in the address state, it is stored to the SPI\r
+ * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
+ * \r
+ * 3. In the data state, variables are read/written "from back to front" until\r
+ * the byte counter reaches zero. Since the Master is in charge of the data\r
+ * clocking, the Slave will go to command state before the last byte is\r
+ * transferred during reading. This means that the Master should send an \r
+ * invalid command when getting each byte, ie 0x00.\r
+ *\r
+ * If the time between two transfers is 1 second or more, the Slave\r
+ * automatically reverts to command state.\r
+ *\r
+ * \note Battery charging is not automatically halted during SPI communication.\r
+ * This means that the current charge state (current and voltage) will\r
+ * remain constant during heavy and prolonged serial traffic.\r
+ *\r
+ * \todo Variable writing not implemented yet.\r
+ * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
+ */\r
+ISR(USI_OVF_vect)\r
+{\r
+       // If the communication timed out, set ST_CMD as current state.\r
+       if (!Time_Left(TIMER_USI)) {\r
+               SPI.State = ST_CMD;\r
+       }\r
+\r
+       // Start communication timer. If further communication doesn't happen\r
+       // within 1 second, the SPI communication state is reset to CMD.\r
+       Time_Set(TIMER_USI, 0, 1, 0);\r
+       \r
+       // Clear USI counter and flag completed transfer.\r
+       USISR = (1<<USIOIF);\r
+       SPI.XferComplete = TRUE;\r
+       \r
+       // Process incoming data.\r
+       switch(SPI.State)       {\r
+       // A valid SPI transfer starts with a Command Byte sent by the Master.\r
+       case ST_CMD:   \r
+               SPI.Data = USIDR;  // Store the transferred byte.\r
+               \r
+               // If the master sent 0, it is trying to get data. Ignore in this state.\r
+               if (SPI.Data != 0) {\r
+                       // Does the master want to read or write?\r
+                       if (SPI.Data & 0x40) {\r
+                               SPI.Read = FALSE;\r
+                       } else {\r
+                               SPI.Read = TRUE;\r
+                       }\r
+\r
+                               // From/to EEPROM or SRAM?\r
+                       if (SPI.Data &0x80) {\r
+                               SPI.EEPROM = TRUE;\r
+                       } else {\r
+                               SPI.EEPROM = FALSE;\r
+                       }\r
+\r
+                       SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
+                       SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
+\r
+                       SPI_Put(0xCC);  // Signal that command was received.\r
+               }\r
+       break;\r
+\r
+                       \r
+       case ST_ADDR:  \r
+               SPI.Data = USIDR;  // Store the address.\r
+               SPI.Address = SPI.Data;\r
+               SPI.State = ST_DATA;  // The master will send/wait for data next.\r
+\r
+               SPI_Put(0xBB);  // Signal that address was received.\r
+       break;\r
+\r
+\r
+       // Note well: this will process at least one byte, regardless of Count.\r
+       case ST_DATA:\r
+               if (SPI.Count-- > 0) {\r
+                       // Write specified variable to SPI, "back to front".\r
+                       if (SPI.Read) {\r
+                               switch (SPI.Address) {\r
+                               case ADR_ADCS:\r
+                                       SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               \r
+                               case ADR_BATTACTIVE:\r
+                                       SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               \r
+                               case ADR_BATTDATA:\r
+                                       SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               \r
+                               case ADR_BATTCTRL:\r
+                                  SPI_Put(eeprom_read_byte((unsigned char*)&BattControl + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               case ADR_TIMERS:\r
+                                       SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
+                               break;\r
+\r
+                               \r
+                               default:\r
+                                       SPI_Put(0);\r
+                               break;\r
+                               }\r
+                       } else {\r
+                               // Read byte from SPI\r
+                               SPI.Data = USIDR;\r
+\r
+                               // ********************************************\r
+                               // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
+                               // ********************************************\r
+                                                               \r
+                               // Save byte to specified variable.\r
+                               switch (SPI.Address) {\r
+                               case ADR_BATTCTRL:\r
+                                       eeprom_write_byte((unsigned char*)&BattControl + SPI.Count, SPI.Data);\r
+                               break;\r
+\r
+                               \r
+                               default:\r
+                               break;\r
+                               }\r
+                       }\r
+                       \r
+\r
+               } else {\r
+                       SPI.State = ST_CMD;\r
+               }\r
+       break;\r
+\r
+       default:  // Shouldn't end up here. (Unknown SPI-state)\r
+       break;\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Initializes USI as an SPI slave\r
+ *\r
+ * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
+ * I/O and clock, and USI counter overflow interrupts enabled.\n\r
+ * Also initializes the SPI status struct.\r
+ * \r
+ * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
+ * (1) edge of clock signal\r
+ *\r
+ * \note Clears the stored data\r
+ *\r
+ * \todo Timer should reset SPI protocol on timeout\r
+ */\r
+void SPI_Init(unsigned char spi_mode)\r
+{\r
+       cli();\r
+       \r
+       // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
+       USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
+       USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
+       USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
+       \r
+       // Configure USI to 3-wire slave mode with overflow interrupt\r
+       USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
+\r
+       // Initialize the SPI struct\r
+       SPI.Data = 0;                 // Clear data.\r
+       SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
+       SPI.Read = FALSE;             // Doesn't matter right now.\r
+       SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
+       SPI.Count = 0;                // Doesn't matter right now.\r
+       SPI.Address = 0;              // Doesn't matter right now.\r
+       SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
+       SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
+\r
+       sei();\r
+}\r
+\r
+\r
+// Put one byte on bus. Use this function like you would write to the SPDR\r
+// register in the native SPI module. Calling this function will prepare a\r
+// byte for the next transfer initiated by the master device. If a transfer\r
+// is in progress, this function will set the write collision flag and return\r
+// without altering the data registers.\r
+//\r
+// Returns 0 if a write collision occurred, 1 otherwise.\r
+/*! \brief Write a byte to SPI bus\r
+ *\r
+ * This function first checks if a transmission is in progress, and if so, flags\r
+ * a write collision, and returns FALSE.\n\r
+ * If a transmission is not in progress, the flags for write collision and\r
+ * transfer complete are cleared, and the input byte is written to SPDR.\n\r
+ *\r
+ * \param val The byte to send.\r
+ *\r
+ * \retval FALSE A write collision happened.\r
+ * \retval TRUE Byte written to SPDR.\r
+ */\r
+unsigned char SPI_Put(unsigned char val)\r
+{\r
+       // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
+       // If this fails, flag a write collision and return.\r
+       if((USISR & 0x0F) != 0) {\r
+               SPI.WriteCollision = TRUE;\r
+               return(FALSE);\r
+       }\r
+\r
+       // Reinitialize flags.\r
+       SPI.XferComplete = FALSE;\r
+       SPI.WriteCollision = FALSE;\r
+\r
+       USIDR = val;  // Put data in USI data register.\r
+\r
+       return (TRUE);\r
+}\r
+\r
+\r
+// Get one byte from bus. This function only returns the previous stored\r
+// USIDR value. The transfer complete flag is not checked. Use this function\r
+// like you would read from the SPDR register in the native SPI module.\r
+/*! \brief Get the last byte received from SPI bus\r
+ *\r
+ * This function simply returns the last byte stored to the SPI status struct,\r
+ * without checking if a completed transfer is flagged.\r
+ *\r
+ * \retval SPI.Data The last byte read from SPI.\r
+ */\r
+unsigned char SPI_Get(void)\r
+{\r
+       return SPI.Data;\r
+}\r
+\r
+\r
+/*! \brief Wait for SPI transfer to complete\r
+ *\r
+ * This function waits for a transfer complete to be flagged.\r
+ */\r
+void SPI_Wait(void)\r
+{\r
+       do {  // Wait for transfer complete.\r
+       } while (SPI.XferComplete == FALSE);\r
+}\r
diff --git a/BaseTinyFirmware/GCC/USI.h b/BaseTinyFirmware/GCC/USI.h
new file mode 100644 (file)
index 0000000..726291d
--- /dev/null
@@ -0,0 +1,88 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for USI.c\r
+ *\r
+ *      Contains definitions of which I/O-register and pins to use,\r
+ *      communication states, and a declaration of the SPI status struct.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef USI_H\r
+#define USI_H\r
+\r
+//******************************************************************************\r
+// USI port and pin definitions\r
+//******************************************************************************\r
+#define USI_OUT_REG       PORTB   //!< USI port output register.\r
+#define USI_IN_REG        PINB    //!< USI port input register.\r
+#define USI_DIR_REG       DDRB    //!< USI port direction register.\r
+#define USI_CLOCK_PIN     PB2     //!< USI clock I/O pin.\r
+#define USI_DATAIN_PIN    PB0     //!< USI data input pin.\r
+#define USI_DATAOUT_PIN   PB1     //!< USI data output pin.\r
+\r
+\r
+//******************************************************************************\r
+// USI/SPI states\r
+//******************************************************************************\r
+enum {\r
+       ST_CMD = 1,  //!< USI/SPI command state.\r
+       ST_ADDR,     //!< USI/SPI address state.\r
+       ST_DATA      //!< USI/SPI data state.\r
+};\r
+\r
+\r
+//******************************************************************************\r
+// Struct declarations\r
+//******************************************************************************\r
+//! \brief Holds SPI status and data\r
+struct SPI_Status_struct\r
+{\r
+       unsigned char Data           : 8;  //!< The last received byte.\r
+       unsigned char Address        : 8;  //!< Specifies variable to read/write.\r
+       unsigned char Count          : 6;  //!< The number of bytes to read/write.\r
+       unsigned char State          : 2;  //!< \brief Communication state.\r
+       //!< \note The states are enumerated in USI.h.\r
+               \r
+       \r
+       //! Master wants to read or write? (TRUE/FALSE)\r
+       unsigned char Read           : 1;\r
+       \r
+       //! Read/write from/to EEPROM? (TRUE/FALSE)\r
+       unsigned char EEPROM         : 1;\r
+       \r
+       //! Used by SPI_Put() to determine if last byte was transferred.(TRUE/FALSE)\r
+       unsigned char XferComplete   : 1;\r
+       \r
+       //! Set if SPI_Put() is called before last byte was transferred.(TRUE/FALSE)\r
+       unsigned char WriteCollision : 1; \r
+};\r
+typedef struct SPI_Status_struct SPI_Status_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+void SPI_Init(unsigned char spi_mode);\r
+unsigned char SPI_Put(unsigned char val);\r
+unsigned char SPI_Get(void);\r
+void SPI_Wait(void);\r
+\r
+#endif // USI_H\r
diff --git a/BaseTinyFirmware/GCC/atmel.jpg b/BaseTinyFirmware/GCC/atmel.jpg
new file mode 100644 (file)
index 0000000..f163a72
Binary files /dev/null and b/BaseTinyFirmware/GCC/atmel.jpg differ
diff --git a/BaseTinyFirmware/GCC/avr458.aps b/BaseTinyFirmware/GCC/avr458.aps
new file mode 100644 (file)
index 0000000..1b7c850
--- /dev/null
@@ -0,0 +1 @@
+<AVRStudio><MANAGEMENT><ProjectName>avr458</ProjectName><Created>13-Mar-2008 01:43:55</Created><LastEdit>13-Mar-2008 04:56:33</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>13-Mar-2008 01:43:55</Created><Version>4</Version><Build>4, 14, 0, 580</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>avr458\avr458.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>C:\Users\kevin\pub\src\bc100\GCC\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>AVR Simulator</CURRENT_TARGET><CURRENT_PART>ATtiny861.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>ADC.c</SOURCEFILE><SOURCEFILE>battery.c</SOURCEFILE><SOURCEFILE>chargefunc.c</SOURCEFILE><SOURCEFILE>LIIONcharge.c</SOURCEFILE><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>menu.c</SOURCEFILE><SOURCEFILE>OWI.c</SOURCEFILE><SOURCEFILE>PWM.c</SOURCEFILE><SOURCEFILE>statefunc.c</SOURCEFILE><SOURCEFILE>time.c</SOURCEFILE><SOURCEFILE>USI.c</SOURCEFILE><OTHERFILE>avr458\avr458.lss</OTHERFILE><OTHERFILE>avr458\avr458.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>avr458</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>attiny861</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>avr458.elf</OUTPUTFILENAME><OUTPUTDIR>avr458\</OUTPUTDIR><ISDIRTY>0</ISDIRTY><OPTIONS><OPTION><FILE>ADC.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>LIIONcharge.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>OWI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>PWM.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>USI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>battery.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>chargefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>main.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>menu.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>statefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>time.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DLIION -Wall </OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>avr458</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>\r
diff --git a/BaseTinyFirmware/GCC/avr458.aws b/BaseTinyFirmware/GCC/avr458.aws
new file mode 100644 (file)
index 0000000..2773bff
--- /dev/null
@@ -0,0 +1 @@
+<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name="ATTINY861"/><Files/></AVRWorkspace>\r
diff --git a/BaseTinyFirmware/GCC/avr463.aps b/BaseTinyFirmware/GCC/avr463.aps
new file mode 100644 (file)
index 0000000..0e89be1
--- /dev/null
@@ -0,0 +1 @@
+<AVRStudio><MANAGEMENT><ProjectName>avr463</ProjectName><Created>13-Mar-2008 01:54:24</Created><LastEdit>13-Mar-2008 03:07:11</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>13-Mar-2008 01:54:24</Created><Version>4</Version><Build>4, 14, 0, 580</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>avr463\avr463.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>C:\Users\kevin\pub\src\bc100\GCC\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>AVR Simulator</CURRENT_TARGET><CURRENT_PART>ATtiny861.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>ADC.c</SOURCEFILE><SOURCEFILE>battery.c</SOURCEFILE><SOURCEFILE>chargefunc.c</SOURCEFILE><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>menu.c</SOURCEFILE><SOURCEFILE>NIMHcharge.c</SOURCEFILE><SOURCEFILE>OWI.c</SOURCEFILE><SOURCEFILE>PWM.c</SOURCEFILE><SOURCEFILE>statefunc.c</SOURCEFILE><SOURCEFILE>time.c</SOURCEFILE><SOURCEFILE>USI.c</SOURCEFILE><OTHERFILE>avr463\avr463.lss</OTHERFILE><OTHERFILE>avr463\avr463.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>avr463</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>attiny861</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>avr463.elf</OUTPUTFILENAME><OUTPUTDIR>avr463\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS><OPTION><FILE>ADC.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>NIMHcharge.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>OWI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>PWM.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>USI.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>battery.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>chargefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>main.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>menu.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>statefunc.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>time.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DNIMH </OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>avr463</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><ProjectFiles><Files><Name>C:\Users\kevin\pub\src\bc100\GCC\ADC.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\battery.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\chargefunc.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\main.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\menu.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\NIMHcharge.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\OWI.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\PWM.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\statefunc.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\time.c</Name><Name>C:\Users\kevin\pub\src\bc100\GCC\USI.c</Name></Files></ProjectFiles><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files><File00000><FileId>00000</FileId><FileName>battery.c</FileName><Status>1</Status></File00000><File00001><FileId>00001</FileId><FileName>chargefunc.c</FileName><Status>1</Status></File00001><File00002><FileId>00002</FileId><FileName>nimhcharge.c</FileName><Status>1</Status></File00002><File00003><FileId>00003</FileId><FileName>statefunc.c</FileName><Status>1</Status></File00003></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>\r
diff --git a/BaseTinyFirmware/GCC/avr463.aws b/BaseTinyFirmware/GCC/avr463.aws
new file mode 100644 (file)
index 0000000..2773bff
--- /dev/null
@@ -0,0 +1 @@
+<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name="ATTINY861"/><Files/></AVRWorkspace>\r
diff --git a/BaseTinyFirmware/GCC/battery.c b/BaseTinyFirmware/GCC/battery.c
new file mode 100644 (file)
index 0000000..e6cacd8
--- /dev/null
@@ -0,0 +1,422 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions related to battery control and data acquisition.\r
+ *\r
+ *      Contains functions for enabling/disabling batteries, and looking up\r
+ *      their status and specifications using the ADC.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+#include <avr/eeprom.h>\r
+\r
+#include "structs.h"\r
+#include "enums.h"\r
+\r
+#include "ADC.h"\r
+#include "battery.h"\r
+#include "main.h"\r
+#include "OWI.h"\r
+#include "time.h"\r
+\r
+#ifdef NIMH\r
+#include "NIMHspecs.h"\r
+#endif // NIMH\r
+\r
+#ifdef LIION\r
+#include "LIIONspecs.h"\r
+#endif // LIION\r
+\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+/* Control-struct for batteries */\r
+/*! \brief Holds control data for both batteries\r
+ * \note Stored in EEPROM.\r
+ */\r
+\r
+Battery_t EEMEM BattControl[2] = {(BIT_BATTERY_ENABLED | BIT_BATTERY_DISCONNECT_ALLOWED | BIT_BATTERY_CHARGE_INHIBIT),\r
+                                  (BIT_BATTERY_ENABLED | BIT_BATTERY_DISCONNECT_ALLOWED | BIT_BATTERY_CHARGE_INHIBIT),\r
+};\r
+\r
+/* Data-struct for battery */\r
+Batteries_t BattData; //!< Holds data for the current battery\r
+\r
+\r
+/* Storage for battery EPROM */\r
+/*! \brief Storage space for data from the batteries' own EPROMs.\r
+ * \note Stored in EEPROM.\r
+ */\r
+unsigned char EEMEM BattEEPROM[4][32];\r
+\r
+\r
+//! Global that indicates current battery (0 = battery A, 1 = B)\r
+unsigned char BattActive;\r
+\r
+\r
+/*! \brief RID lookup-table\r
+ *\r
+ * Contains Resistor ID data specified by manufacturer.\r
+ *\r
+ * \note Values have been calculated assuming a +/- 15% tolerance.\r
+ */\r
+const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
+  {558, 659, 3900, 550, 260, 300, 10},\r
+  {744, 843, 6800, 750, 360, 300, 14},\r
+  {869, 958, 10000, 1000, 475, 300, 19},\r
+  {1097, 1153, 24000, 2000, 475, 420, 38}\r
+};\r
+\r
+\r
+/*! \brief NTC lookup-table\r
+ *\r
+ * The first entry is 0 degrees. For every entry after, temperature increases\r
+ * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
+ * It must be sorted in descending ADC order.\r
+ *\r
+ * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
+ *\r
+ * \note NTCLookUp() must be modified if this table is changed so that:\r
+ * - first entry is no longer 0 degrees.\r
+ * - temperature difference between entries is no longer 4 degrees.\r
+ * - ADCsteps no longer specifies ADC steps per half degree.\r
+ */\r
+// FOR VARTA POLYFLEX NTC\r
+const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+       {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
+       {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
+       {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
+       {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
+};\r
+\r
+\r
+// FOR MITSUBISHI NTC\r
+/*\r
+const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+  {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
+  {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
+  {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
+  {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
+};\r
+*/\r
+\r
\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Checks if battery has changed\r
+ *\r
+ * Stores current capacity, then attempts to refresh battery status.\n\r
+ * If the refresh is successful, old capacity is compared with the new one.\r
+ * \r
+ * \retval FALSE Battery is disconnected, or capacity has changed.\r
+ * \retval TRUE All OK.\r
+ */\r
+unsigned char BatteryCheck(void)\r
+{\r
+       unsigned char success = TRUE;\r
+       unsigned int  oldCapacity;\r
+       \r
+       // Save to see if battery data has changed.\r
+       oldCapacity = BattData.Capacity;  \r
+       \r
+       if (!BatteryStatusRefresh()) {\r
+               success = FALSE;              // Battery not present or RID was invalid.\r
+       }\r
+       \r
+       if (oldCapacity != BattData.Capacity) {\r
+               success = FALSE;              // Battery configuration has changed.\r
+       }\r
+\r
+       return(success);\r
+}\r
+\r
+\r
+/*! \brief Refreshes battery status information\r
+ *\r
+ * Refreshes battery status information, if it is present, based on\r
+ * RID and NTC (read by ADC).\n\r
+ * The battery must have been enabled and a complete set of ADC data must have\r
+ * been collected before calling.\n\r
+ *\r
+ * \retval FALSE No battery present.\r
+ * \retval TRUE Battery present, status refreshed.\r
+ *\r
+ * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
+ * is found in the lookup table. Instead, default battery data will be used.\r
+ */\r
+unsigned char BatteryStatusRefresh(void)\r
+{\r
+       // Assume the worst..\r
+       unsigned char success = FALSE;\r
+       \r
+       BattData.Present = FALSE;\r
+       BattData.Charged = FALSE;\r
+       BattData.Low = TRUE;\r
+       BattData.Circuit = OW_NONE;\r
+       BattData.Temperature = 0;\r
+       BattData.Capacity = 0;\r
+       BattData.MaxCurrent = 0;\r
+       BattData.MaxTime = 0;\r
+       BattData.MinCurrent = 0;\r
+\r
+       NTCLookUp();\r
+       BattData.HasRID = RIDLookUp();\r
+\r
+       // Is the battery voltage above minimum safe cell voltage?\r
+       if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+               BattData.Low = FALSE;\r
+       }\r
+\r
+       // Is the battery charged?\r
+       if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+               BattData.Charged = TRUE;\r
+       }\r
+\r
+       // If we are not charging, yet VBAT is above safe limit, battery is present.\r
+       // If we are charging and there's a current flowing, the battery is present.\r
+       \r
+       /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
+       * check is redundant since charging will be aborted due to low current at\r
+       * max duty cycle. That is preferrable since the charge current reading is\r
+       * not 100% proof.\r
+       */\r
+       if (((OCR1B == 0) && (!BattData.Low)) ||\r
+           ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+               BattData.Present = TRUE;\r
+               success = TRUE;\r
+       } else {\r
+               BattData.Low = FALSE;  // (This is just a technicality..)\r
+               success = FALSE;\r
+       }\r
+\r
+#ifndef ALLOW_NO_RID\r
+       // Return FALSE if no valid RID entry was found, to stop charging.\r
+       if(!BattData.HasRID) {\r
+               success = FALSE;\r
+       }\r
+#endif\r
+\r
+       return(success);\r
+}\r
+\r
+\r
+/*! \brief Refreshes battery data in the EEPROM\r
+ *\r
+ * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
+ * these data in on-chip EEPROM.\n\r
+ * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
+ *\r
+ * \todo Updating BattData with these data. Specs needed.\r
+ *\r
+ * \retval FALSE Refresh failed.\r
+ * \retval TRUE Refresh successful.\r
+ */\r
+unsigned char BatteryDataRefresh(void)\r
+{\r
+       unsigned char offset;\r
+       unsigned char i, crc, family, temp, page;\r
+       unsigned char success;\r
+       \r
+       // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
+       for (page = 0; page < 4; page++)        {\r
+               success = FALSE;\r
+       \r
+               if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
+                       \r
+                       // Presence detected, check type and CRC.\r
+                       OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
+                       family = OWI_ReceiveByte(OWIBUS);\r
+                       crc = OWI_ComputeCRC8(family,0);\r
+\r
+                       for (i = 0; i < 6; i++) {\r
+                               crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
+                       }\r
+\r
+                       // CRC ok, device found.\r
+                       if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+                               BattData.Circuit = family;\r
+\r
+                               // For now, we only read data from DS2505 EPROMs.\r
+                               if (BattData.Circuit == OW_DS2505) {\r
+                                       offset = page*32;\r
+                                       OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
+                                       OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
+                                       OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
+\r
+                                       // Calculate checksums.\r
+                                       crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
+                                       crc = OWI_ComputeCRC8(offset,crc);\r
+                                       crc = OWI_ComputeCRC8(0,crc);\r
+\r
+                                       // Command received succesfully, now start reading data\r
+                                       // and writing it to EEPROM.\r
+                                       if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+                                               crc = 0;\r
+                                               \r
+                                               // Fill page with data.\r
+                                               for (i=0; i<32; i++) {\r
+                                                       temp = OWI_ReceiveByte(OWIBUS);\r
+                                                       crc = OWI_ComputeCRC8(temp, crc);\r
+                                                       eeprom_write_byte(&BattEEPROM[page][i], temp);\r
+                                               }\r
+                                               \r
+                                               if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+                                                               success = TRUE;  // Data read OK\r
+                                               }\r
+                                       } else { // Not able to start reading data.\r
+                                       }\r
+                               } else { // Wrong device type.\r
+                               }\r
+                       } else { // No device found.             \r
+                       }\r
+               } else { // No presence detected on one-wire bus.\r
+               }\r
+\r
+         // Erase local EEPROM page if there were any errors during transfer.\r
+               if (!success) {\r
+                       for (i=0; i<32; i++) {\r
+                          eeprom_write_byte(&BattEEPROM[page][i], 0);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return(success);\r
+}\r
+\r
+\r
+/*! \brief Enables specified battery\r
+ *\r
+ * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
+ * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
+ * The function takes 100 ms to allow the port switch to settle.\r
+ *\r
+ * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
+ */\r
+void EnableBattery(unsigned char bat)\r
+{\r
+       // Use general timer, set timeout to 100ms.\r
+       Time_Set(TIMER_GEN,0,0,100);\r
+\r
+       // Set specified battery as the active one.\r
+       BattActive = bat;\r
+\r
+       // Enable current battery in hardware, light LED & connect battery.\r
+       PORTB |= (1 << (PB4+bat));\r
+\r
+       // Disconnect other battery.\r
+       PORTB &= ~(1<<(PB5-bat));     \r
+\r
+       do { // Let port switch settle.\r
+       } while (Time_Left(TIMER_GEN));  \r
+}\r
+\r
+\r
+/*! \brief Disables both batteries\r
+ *\r
+ * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
+ */\r
+void DisableBatteries(void)\r
+{\r
+       // Turn off LEDs and disconnect batteries.\r
+       PORTB &= ~((1<<PB4)|(1<<PB5));  \r
+}\r
+\r
+\r
+/*! \brief Looks up battery data from RID table\r
+ *\r
+ * Attempts to find data for the battery from the RID lookup-table.\n\r
+ * If no valid entry is found, default data (defined in battery.h)\r
+ * are used.\r
+ *\r
+ * \retval TRUE Entry found, battery data updated.\r
+ * \retval FALSE No entry found, using defaults for battery data.\r
+ */\r
+unsigned char RIDLookUp (void)\r
+{\r
+       unsigned char i, found = FALSE;\r
+               \r
+       // Lookup in the RID-table. If measured RID is within the limits\r
+       // of an entry, those data are used, and TRUE is returned.\r
+       for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
+               if (ADCS.rawRID >= RID[i].Low) {\r
+                       if (ADCS.rawRID <= RID[i].High) {\r
+                               BattData.Capacity = RID[i].Capacity;\r
+                               BattData.MaxCurrent = RID[i].Icharge;\r
+                               BattData.MaxTime = RID[i].tCutOff;\r
+                               BattData.MinCurrent = RID[i].ICutOff;\r
+                               \r
+                               found = TRUE;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       // If no valid entry is found, use defaults and return FALSE.\r
+       if (!found) {\r
+               BattData.Capacity = DEF_BAT_CAPACITY;\r
+               BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
+               BattData.MaxTime = DEF_BAT_TIME_MAX;\r
+               BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
+       }\r
+       \r
+       return(found);\r
+}\r
+\r
+\r
+/*! \brief Calculates temperature from a lookup table\r
+ *\r
+ * Looks up the highest NTC value below or equal to the measured one.\n\r
+ * With the current lookup table, temperature is calculated with the formula:\n\r
+ * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
+ *\r
+ * \note If the NTC-measurement is saturated, with the current lookup table,\r
+ * the temperature will be reported as -1 C.\r
+ *\r
+ * \note If no valid entry is found, battery temperature is set to 80.\r
+ */\r
+void NTCLookUp (void)\r
+{\r
+       unsigned char i;\r
+       unsigned char found = FALSE;\r
+       \r
+       // Lookup in the NTC-table. Use the first entry which is equal or below\r
+       // sampled NTC. Calculate temperature by using the index number, and the\r
+       // difference between the measured NTC value and the one in the entry.\r
+       for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
+               if (ADCS.rawNTC >= NTC[i].ADCV) {\r
+                       BattData.Temperature = (i<<2) ;\r
+                       BattData.ADCSteps = NTC[i].ADCsteps;  \r
+                       BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADCV)<<1) / BattData.ADCSteps;\r
+                       \r
+                       found = TRUE;  // Could be done with a break, but that violates MISRA.\r
+               }\r
+       }\r
+       \r
+       // For safety, is temperature is greater than the NTC \r
+       if (!found) {\r
+               BattData.Temperature = 80;\r
+       }\r
+}\r
diff --git a/BaseTinyFirmware/GCC/battery.h b/BaseTinyFirmware/GCC/battery.h
new file mode 100644 (file)
index 0000000..bb76eaf
--- /dev/null
@@ -0,0 +1,115 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for battery.c\r
+ *\r
+ *      Contains definitions for the setup of 1-Wire(R) and behaviour of the\r
+ *      battery data and status refreshing functions.\n\r
+ *      Also contains definitions of default battery data, and declarations\r
+ *      for the RID and NTC lookup tables.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+\r
+#ifndef BATTERY_H\r
+#define BATTERY_H\r
+\r
+#include <avr/eeprom.h>\r
+\r
+\r
+//******************************************************************************\r
+// Defines for EEPROM reading\r
+//******************************************************************************\r
+#define OWIBUS  OWI_PIN_0         //!< One-wire bus (pin).\r
+\r
+#define OW_NONE           0x00    //!< One-wire device family code.\r
+#define OW_DS2505         0x09    //!< One-wire device family code.\r
+\r
+#define DS2505_MEM_READ     0xF0  //!< One-wire device command.\r
+#define DS2505_STATUS_READ  0xAA  //!< One-wire device command.\r
+#define DS2505_DATA_READ    0xC3  //!< One-wire device command.\r
+\r
+\r
+//******************************************************************************\r
+// RID-less charging (for BatteryStatusRefresh())\r
+//******************************************************************************\r
+//#define ALLOW_NO_RID  //!< Use default battery data if no matching entry found.\r
+\r
+#define DEF_BAT_CAPACITY               0  //!< Default battery capacity, in mAh.\r
+#define DEF_BAT_CURRENT_MAX    0  //!< Default maximum charge current, in mA.\r
+#define DEF_BAT_TIME_MAX               0  //!< Default maximum charge time, in minutes.\r
+//! Default minimum current to stop charge, in mA.\r
+#define DEF_BAT_CURRENT_MIN    0\r
+\r
+\r
+\r
+//******************************************************************************\r
+// RID and NTC defines and struct declarations\r
+//******************************************************************************\r
+#define RID_TABLE_SIZE        4     //!< Number of entries in RID table.\r
+#define NTC_TABLE_SIZE        20    //!< Number of entries in NTC table.\r
+\r
+//! \brief Struct for an entry in the resistor ID lookup-table\r
+struct RID_Lookup_struct {\r
+  unsigned int  Low;              //!< Lowest acceptable ADC value.\r
+  unsigned int  High;             //!< Highest acceptable ADC value.\r
+  unsigned int  Resistance;       //!< RID resistance, in Ohms.\r
+  unsigned int  Capacity;         //!< Associated battery capacity, in mAh.\r
+  unsigned int  Icharge;          //!< Associated initial charge current, in mA.\r
+  unsigned int  tCutOff;          //!< Associated cut-off time, in minutes.\r
+  unsigned int  ICutOff;          //!< Associated cut-off current, in mA.\r
+};\r
+typedef struct RID_Lookup_struct RID_Lookup_t; //!< For convenience.\r
+\r
+/*! \brief Struct for an entry in the NTC lookup-table\r
+ *\r
+ * \note Must be sorted in descending ADC order.\r
+ */\r
+struct NTC_Lookup_struct\r
+{\r
+  unsigned int  ADCV;  //!< Measured NTC.\r
+  unsigned char ADCsteps;  //!< ADC steps per half degree at this temperature.\r
+};\r
+typedef struct NTC_Lookup_struct NTC_Lookup_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern Battery_t EEMEM BattControl[];\r
+extern Batteries_t BattData;\r
+extern unsigned char EEMEM BattEEPROM[][32];\r
+extern unsigned char BattActive;\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char BatteryCheck(void);\r
+unsigned char BatteryStatusRefresh(void);\r
+unsigned char BatteryDataRefresh(void);\r
+void EnableBattery(unsigned char);\r
+void DisableBatteries(void);\r
+unsigned char RIDLookUp(void);\r
+void NTCLookUp(void);\r
+\r
+\r
+#endif // BATTERY_H\r
diff --git a/BaseTinyFirmware/GCC/blue.GIF b/BaseTinyFirmware/GCC/blue.GIF
new file mode 100644 (file)
index 0000000..ddb3000
Binary files /dev/null and b/BaseTinyFirmware/GCC/blue.GIF differ
diff --git a/BaseTinyFirmware/GCC/charge.h b/BaseTinyFirmware/GCC/charge.h
new file mode 100644 (file)
index 0000000..3d387a5
--- /dev/null
@@ -0,0 +1,38 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for NIMHcharge.c and LIIONcharge.c\r
+ *\r
+ *      Contains definitions and declarations related to the charge state.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/charge.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef CHARGE_H\r
+#define CHARGE_H\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char Charge(unsigned char inp);\r
+\r
+\r
+#endif // CHARGE_H\r
diff --git a/BaseTinyFirmware/GCC/chargefunc.c b/BaseTinyFirmware/GCC/chargefunc.c
new file mode 100644 (file)
index 0000000..2194e56
--- /dev/null
@@ -0,0 +1,363 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Charge functions\r
+ *\r
+ *      Contains the functions for charging with constant current and voltage,\r
+ *      and for deciding when to halt.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "ADC.h"\r
+#include "battery.h"\r
+#include "chargefunc.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "PWM.h"\r
+#include "statefunc.h"\r
+#include "time.h"\r
+\r
+#ifdef NIMH\r
+#include "NIMHspecs.h"\r
+#endif // NIMH\r
+\r
+#ifdef LIION\r
+#include "LIIONspecs.h"\r
+#endif // LIION\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+//! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().\r
+ChargeParameters_t ChargeParameters;\r
+\r
+//! Struct that holds parameters for HaltNow().\r
+HaltParameters_t HaltParameters;\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Charges battery with a constant current.\r
+ *\r
+ * This function applies a constant current (set in ChargeParameters.Current)\r
+ * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+ * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+ * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n\r
+ * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+ * Once the battery is no longer flagged for charge inhibit, timers are\r
+ * started again and charging resumed.\r
+ *\r
+ * \retval ChargeParameters.NextState Next state once this stage is done.\r
+ * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+ * HaltNow() will have set a new next state.\r
+ */\r
+unsigned char ConstantCurrent(void)\r
+{\r
+       unsigned char error = FALSE,\r
+                     wasStopped = FALSE;\r
+       \r
+       do      {\r
+      // Wait for ADC conversions to complete.\r
+               ADC_Wait();\r
+\r
+               // If Master has flagged for a charge inhibit, pause charging.\r
+               // (This is to prevent damage during prolonged serial communication.)\r
+               if (eeprom_read_byte(&BattControl[BattActive]) & BIT_BATTERY_CHARGE_INHIBIT) {\r
+                       wasStopped = TRUE;\r
+                       Time_Stop();\r
+                       OCR1B = 0;\r
+               } else {\r
+                       // Continue charging!\r
+                       if (wasStopped) {\r
+                               wasStopped = FALSE;\r
+                               \r
+                               // Timer variables are not reset by this.\r
+                               Time_Start();\r
+                       }\r
+         \r
+                       // Adjust the charge current to within ChargeParameters.Current\r
+                       // +/- BAT_CURRENT_HYST.\r
+                       if ((ADCS.avgIBAT < 0) ||\r
+                           (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+                                        \r
+                               if(!PWM_IncrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MAX\r
+                               // If the duty cycle cannot be incremented, flag error and\r
+                               // go to error state.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       } else if ((ADCS.avgIBAT >= 0) &&\r
+                                (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+                                        \r
+                               if(!PWM_DecrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MIN\r
+                                       // If the duty cycle cannot be decremented, flag error and\r
+                                       // go to error state.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       }\r
+               }\r
+       } while (!HaltNow() && !error);\r
+\r
+       // Return the next state to Charge(). If an error has occured, this will\r
+       // point to some other state than the next state of charging.\r
+       return(ChargeParameters.NextState);\r
+}\r
+\r
+\r
+/*! \brief Charges battery with a constant voltage\r
+ *\r
+ * This function applies a constant voltage (set in ChargeParameters.Voltage)\r
+ * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+ * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+ * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n\r
+ * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+ * Once the battery is no longer flagged for charge inhibit, timers are\r
+ * started again and charging resumed.\r
+ *\r
+ * \retval ChargeParameters.NextState Next state once this stage is done.\r
+ * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+ * HaltNow() will have set a new next state.\r
+ */\r
+unsigned char ConstantVoltage(void)\r
+{\r
+       unsigned char error = FALSE,\r
+                     wasStopped = FALSE;\r
+       \r
+       do{\r
+               \r
+               // Wait for ADC conversions to complete.\r
+               ADC_Wait();\r
+               \r
+               // If Master has flagged for a charge inhibit, pause charging.\r
+               // (This is to prevent damage during prolonged serial communication.)\r
+               if (eeprom_read_byte(&BattControl[BattActive]) & BIT_BATTERY_CHARGE_INHIBIT) {\r
+                       wasStopped = TRUE;\r
+                       Time_Stop();\r
+                       OCR1B = 0;\r
+               }\r
+               \r
+               else {\r
+                       // Continue charging!\r
+                       if (wasStopped) {\r
+                               wasStopped = FALSE;\r
+                               \r
+                               // Timer variables aren't reset by this.\r
+                               Time_Start();\r
+                       }\r
+                       \r
+                       // Adjust the charge voltage to within ChargeParameters.Voltage\r
+                       // +/- BAT_VOLTAGE_HYST.\r
+                       if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+\r
+                               if(!PWM_IncrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MAX\r
+                               // Flag PWM control error and go to error-state if the duty\r
+                               // cycle cannot be incremented.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+\r
+                               if(!PWM_DecrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MIN\r
+                                       // Flag PWM control error and go to error-state if duty\r
+                                       // cycle cannot be decremented.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       }\r
+               }\r
+\r
+       } while (!HaltNow() && !error);\r
+\r
+       // Return the next state to Charge(). If an error has occured, this will\r
+       // point to some other state than the next state of charging.\r
+       return(ChargeParameters.NextState);\r
+}\r
+\r
+\r
+/*! \brief Determines when to halt charging.\r
+ *\r
+ * This function evaluates parameters depending on what has been flagged in\r
+ * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should\r
+ * halt or not.\n\r
+ * In addition, error flagging on timeout (battery exhaustion) can be set.\n\r
+ *\r
+ * The function also checks if the battery temperature is within limits,\r
+ * if mains is OK, and if BatteryCheck() returns TRUE.\r
+ * If an error is detected, the associated errorflag is set and \r
+ * ChargeParameters.NextState is changed to an appropriate state.\r
+ *\r
+ * \retval TRUE Halt now.\r
+ * \retval FALSE Don't halt now.\r
+ *\r
+ * \note See chargefunc.h for definitions of halt flags.\r
+ * \note It is generally a bad idea not to halt on a timeout.\r
+ * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be\r
+ * reset in Charge() before calling a charging-function.\r
+ *\r
+ * \todo "Priorities" of standard error checks OK?\r
+ */\r
+unsigned char HaltNow(void)\r
+{\r
+       unsigned char i, halt = FALSE;\r
+       \r
+       // Wait for a full ADC-cycle to finish.\r
+       ADC_Wait();\r
+\r
+       // Evaluate ADC readings according to HaltFlags. Flag errors if selected.\r
+       // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.\r
+       // (Gets overridden if either mains is failing, or the battery changes.)\r
+       for (i = 0x01; i != 0; i <<= 1) {\r
+               if (HaltParameters.HaltFlags & i) {\r
+                       switch (i) {\r
+                       // Is VBAT less than the recorded maximum?\r
+                       case HALT_VOLTAGE_DROP:\r
+\r
+                               // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
+                               if (ADCS.VBAT > HaltParameters.VBATMax) {\r
+                                       HaltParameters.VBATMax = ADCS.VBAT;\r
+                               } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+                                         HaltParameters.VoltageDrop) {\r
+                                       halt = TRUE;\r
+                               }\r
+                       break;\r
+\r
+                       \r
+                       // Has VBAT reached the maximum limit?\r
+                       case HALT_VOLTAGE_MAX:  \r
+                               \r
+                               if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+                                       halt = TRUE;\r
+                               }\r
+                               break;\r
+\r
+\r
+                       // Has IBAT reached the minimum limit?\r
+                       case HALT_CURRENT_MIN:\r
+                               \r
+                               if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+                                       halt = TRUE;\r
+                               }\r
+                               break;\r
+       \r
+                               \r
+                       // Is the temperature rising too fast?\r
+                       case HALT_TEMPERATURE_RISE:\r
+\r
+                               // If rawNTC has increased, the temperature has dropped.\r
+                               // We can store this value for now, and start the timer.\r
+                               // Otherwise, check if NTC has changed too fast.\r
+                               if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
+                                       HaltParameters.LastNTC = ADCS.rawNTC;\r
+                                       Time_Set(TIMER_TEMP,0,30,0);\r
+                                       \r
+                               // Is the increase in temperature greater than the set threshold?\r
+                               } else  if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+                                 (BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
+                                       \r
+                                       // If this happened within a timeframe of 30 seconds, the \r
+                                       // temperature is rising faster than we want.\r
+                                       // If not, update LastNTC and reset timer.\r
+                                       if (Time_Left(TIMER_TEMP))  {\r
+                                               halt = TRUE;\r
+                                       } else {\r
+                                               HaltParameters.LastNTC = ADCS.rawNTC;\r
+                                               Time_Set(TIMER_TEMP,0,30,0);\r
+                                       }\r
+                               }\r
+                       break;\r
+       \r
+                       \r
+                       // Is there any time left?\r
+                       case HALT_TIME:  \r
+                               \r
+                               if (!Time_Left(TIMER_CHG)) {\r
+                                       halt = TRUE;\r
+                                       \r
+                                       // If exhaustion flagging is selected, stop the PWM, disable the \r
+                                       // battery and flag it as exhausted. Make ST_ERROR next state.\r
+                                       if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
+                                                       PWM_Stop();\r
+                                                       Battery_t tmp = eeprom_read_byte(&BattControl[BattActive]);\r
+                                                        tmp &= ~BIT_BATTERY_ENABLED; // Enabled = FALSE;\r
+                                                        eeprom_write_byte(&BattControl[BattActive], tmp);\r
+                                                       BattData.Exhausted = TRUE;\r
+                                                       SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
+                                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       }\r
+                               }\r
+                       break;\r
+                       \r
+                       \r
+                       default:  // Shouldn't end up here, but is needed for MISRA compliance.\r
+                       break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Standard checks:\r
+\r
+       // Battery too cold or hot?\r
+       if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||\r
+           (BattData.Temperature >= HaltParameters.TemperatureMax)) {\r
+                       \r
+               PWM_Stop();\r
+               SetErrorFlag(ERR_BATTERY_TEMPERATURE);\r
+               ChargeParameters.NextState = ST_ERROR;\r
+               halt = TRUE;\r
+       }\r
+\r
+       // Battery not OK?\r
+       if (!BatteryCheck()) {\r
+               PWM_Stop();\r
+               ChargeParameters.NextState = ST_INIT;\r
+               halt = TRUE;\r
+       }\r
+\r
+       // Is mains voltage OK?\r
+       if (!ADCS.Mains) {\r
+               PWM_Stop();\r
+               ChargeParameters.NextState = ST_SLEEP;\r
+               halt = TRUE;\r
+       }\r
+\r
+       return(halt);\r
+}\r
diff --git a/BaseTinyFirmware/GCC/chargefunc.h b/BaseTinyFirmware/GCC/chargefunc.h
new file mode 100644 (file)
index 0000000..88ac473
--- /dev/null
@@ -0,0 +1,134 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for chargefunc.c\r
+ *\r
+ *      Contains definitions to decide PWM error handling and of halt flags,\r
+ *      and declarations of parameter structs for charging.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef CHARGEFUNC_H\r
+#define CHARGEFUNC_H\r
+\r
+\r
+//******************************************************************************\r
+// PWM error handling\r
+//******************************************************************************\r
+//! Report error if maximum duty cycle doesn't give a sufficient charge current.\r
+#define ABORT_IF_PWM_MAX\r
+\r
+//! Report error if minimum duty cycle gives a too great charge current.\r
+#define ABORT_IF_PWM_MIN\r
+\r
+\r
+//******************************************************************************\r
+// Definitions for HaltFlags\r
+//******************************************************************************\r
+//! Halt if VBAT drops more than the set limit.\r
+#define HALT_VOLTAGE_DROP              0x01  \r
+\r
+//! Halt if VBAT reaches the set maximum.\r
+#define HALT_VOLTAGE_MAX               0x02  \r
+\r
+//! Halt if avgIBAT goes below the set minimum.\r
+#define HALT_CURRENT_MIN               0x04  \r
+\r
+//! Halt if BattData.Temperature rises quicker than the set maximum.\r
+#define HALT_TEMPERATURE_RISE  0x08\r
+\r
+//! Halt if TIMER_CHG runs out.\r
+#define HALT_TIME                                      0x10  \r
+\r
+//! Flag battery as exhausted if timeout occurs.\r
+#define HALT_FLAG_EXHAUSTION   0x20\r
+\r
+\r
+//******************************************************************************\r
+// Parameter struct for charging\r
+//******************************************************************************\r
+/*! \brief Holds the parameters for ConstantCurrent() and ConstantVoltage().\r
+ *\r
+ */\r
+struct ChargeParameters_struct {\r
+       unsigned int Voltage;  //!< Voltage to charge with.\r
+       unsigned int Current;  //!< Current to charge with.\r
+       unsigned char NextState;  //!< \brief Next state once charge stage finishes.\r
+                                //!< \note Set in Charge(), but may be changed by\r
+                                //!< HaltNow() if an error occurs!\r
+};\r
+typedef struct ChargeParameters_struct ChargeParameters_t;\r
+\r
+\r
+//******************************************************************************\r
+// Parameter struct for HaltNow()\r
+//******************************************************************************\r
+/*! \brief Holds the parameters for HaltNow();\r
+ *\r
+ */\r
+struct HaltParameters_struct {\r
+       //! \brief Contains flags for what to evaluate. \r
+       //! \note See chargefunc.h for definitions of flags.\r
+       unsigned char HaltFlags;\r
+       \r
+       //! Maximum drop in voltage before halting, in mV.\r
+       unsigned int VoltageDrop;  \r
+       \r
+       //! Maximum limit for output voltage, in mV.\r
+       unsigned int VoltageMax;  \r
+       \r
+       //! Minimum limit for output current, in mA.\r
+       unsigned int CurrentMin;\r
+       \r
+       //! Maximum limit for battery temperature, in degrees centigrade.\r
+       unsigned int TemperatureMax;\r
+       \r
+       //! Minimum limit for battery temperature, in degrees centigrade.\r
+       signed int TemperatureMin;\r
+\r
+       //! Maximum limit for temperature to rise, in degrees centigrade per minute.\r
+       unsigned int TemperatureRise;\r
+\r
+       //! \brief Contains highest VBAT measured, used to calculate voltage drop.\r
+       //! \note Must be manually reset.\r
+       unsigned int VBATMax;\r
+\r
+       //! Used to detect temperature rise.\r
+       unsigned int LastNTC;  \r
+};\r
+typedef struct HaltParameters_struct HaltParameters_t;\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern ChargeParameters_t ChargeParameters;\r
+extern HaltParameters_t HaltParameters;\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char ConstantCurrent(void);\r
+unsigned char ConstantVoltage(void);\r
+unsigned char HaltNow(void);\r
+\r
+#endif // CHARGEFUNC_H\r
diff --git a/BaseTinyFirmware/GCC/config_AVR458.doxygen b/BaseTinyFirmware/GCC/config_AVR458.doxygen
new file mode 100644 (file)
index 0000000..2e5419c
--- /dev/null
@@ -0,0 +1,229 @@
+# Doxyfile 1.5.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "AVR458 Charging Li-Ion Batteries with ATAVRBC100"
+PROJECT_NUMBER         = "<A href=http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 >Atmel AVR Application Notes</A>"
+OUTPUT_DIRECTORY       = doxygen_avr458
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = YES
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+DISTRIBUTE_GROUP_DOC   = YES
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = YES
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = NO
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = 
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.h \
+                         *.cpp
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = NIMH*
+EXCLUDE_SYMBOLS        = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = YES
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = doxygen
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = RTF
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = YES
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/BaseTinyFirmware/GCC/config_AVR463.doxygen b/BaseTinyFirmware/GCC/config_AVR463.doxygen
new file mode 100644 (file)
index 0000000..5ab35da
--- /dev/null
@@ -0,0 +1,229 @@
+# Doxyfile 1.5.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "AVR463 Charging NiMH Batteries with ATAVRBC100"
+PROJECT_NUMBER         = "<A href=http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 >Atmel AVR Application Notes</A>"
+OUTPUT_DIRECTORY       = doxygen_avr463
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = YES
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+DISTRIBUTE_GROUP_DOC   = YES
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = YES
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = NO
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = 
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.h \
+                         *.cpp
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = LIION*
+EXCLUDE_SYMBOLS        = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = YES
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = doxygen
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = RTF
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = YES
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/BaseTinyFirmware/GCC/delay_x_gcc.h b/BaseTinyFirmware/GCC/delay_x_gcc.h
new file mode 100644 (file)
index 0000000..8a1abfa
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+   Copyright (c) 2005, Hans-Juergen Heinrichs
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are met:
+
+   * Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+
+   * Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+
+   * Neither the name of the copyright holders nor the names of
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+/*
+ *  delay_x.h
+ *
+ *  Accurate delays ranging from a single CPU cycle up to
+ *  more than 500 second (e.g. with 8MHz device):
+ *
+ *  The idea for the functions below was heavily inspired by the
+ *  file <avr/delay.h> which is part of the excellent WinAVR
+ *  distribution. Therefore, thanks to Marek Michalkiewicz and
+ *  Joerg Wunsch.
+ *
+ *  The idea is to have the GCC preprocessor handle all calculations
+ *  necessary for determining the exact implementation of a delay
+ *  algorithm. The implementation itself is then inlined into the
+ *  user code.
+ *  In this way it is possible to always get the code size optimized
+ *  delay implementation.
+ *
+ */
+
+#ifndef _AVR_DELAY_X_H_
+#define _AVR_DELAY_X_H_ 1
+
+#include <stdint.h>
+
+#ifndef F_CPU
+# warning "Macro F_CPU must be defined"
+#endif
+
+/*
+ * Forward declaration for all functions with attribute
+ * 'always_inline' enforces GCC to inline the code (even
+ * if it would be better not to do so from optimization
+ * perspective).
+ * Without this attribute GCC is free to implement
+ * inline code or not (using the keyword 'inline'
+ * alone is not sufficient).
+ *
+ */
+static __inline__ void _NOP1( void) __attribute__((always_inline));
+static __inline__ void _NOP2( void) __attribute__((always_inline));
+static __inline__ void _NOP3( void) __attribute__((always_inline));
+static __inline__ void _NOP4( void) __attribute__((always_inline));
+static __inline__ void _NOP5( void) __attribute__((always_inline));
+static __inline__ void _NOP6( void) __attribute__((always_inline));
+static __inline__ void _NOP7( void) __attribute__((always_inline));
+static __inline__ void _NOP8( void) __attribute__((always_inline));
+static __inline__ void _NOP9( void) __attribute__((always_inline));
+static __inline__ void _NOP10(void) __attribute__((always_inline));
+static __inline__ void _NOP11(void) __attribute__((always_inline));
+static __inline__ void _NOP12(void) __attribute__((always_inline));
+
+static __inline__ void _delay_loop_3(  uint32_t) __attribute__((always_inline));
+static __inline__ void _delay_loop_1_x( uint8_t) __attribute__((always_inline));
+static __inline__ void _delay_loop_2_x(uint16_t) __attribute__((always_inline));
+static __inline__ void _delay_loop_3_x(uint32_t) __attribute__((always_inline));
+
+static __inline__ void _delay_cycles(const double) __attribute__((always_inline));
+
+
+/*
+ * _ N O P x ( void )
+ *
+ * Code sized optimized NOPs - not using any registers
+ *
+ * These NOPs will be used for very short delays where
+ * it is more code efficient than executing loops.
+ *
+ */
+static __inline__ void _NOP1 (void) { __asm__ volatile ( "nop    " "\n\t" ); }
+static __inline__ void _NOP2 (void) { __asm__ volatile ( "rjmp 1f" "\n\t"  "1:" "\n\t" ); }
+static __inline__ void _NOP3 (void) { __asm__ volatile ( "lpm    " "\n\t" ); }
+static __inline__ void _NOP4 (void) { _NOP3(); _NOP1(); }
+static __inline__ void _NOP5 (void) { _NOP3(); _NOP2(); }
+static __inline__ void _NOP6 (void) { _NOP3(); _NOP3(); }
+static __inline__ void _NOP7 (void) { _NOP3(); _NOP3(); _NOP1(); }
+static __inline__ void _NOP8 (void) { _NOP3(); _NOP3(); _NOP2(); }
+static __inline__ void _NOP9 (void) { _NOP3(); _NOP3(); _NOP3(); }
+static __inline__ void _NOP10(void) { _NOP3(); _NOP3(); _NOP3(); _NOP1(); }
+static __inline__ void _NOP11(void) { _NOP3(); _NOP3(); _NOP3(); _NOP2(); }
+static __inline__ void _NOP12(void) { _NOP3(); _NOP3(); _NOP3(); _NOP3(); }
+
+
+
+/*
+ *  _ d e l a y _ l o o p _ 3( uint32_t __count )
+ *
+ * This delay loop is not used in the code below: It is
+ * a supplement to the _delay_loop_1() and _delay_loop_2()
+ * within standard WinAVR <arv/delay.h> giving a wider
+ * (32 bit) delay range.
+ *
+ */
+static __inline__ void
+_delay_loop_3( uint32_t __count )
+{
+    __asm__ volatile (
+        "1: sbiw %A0,1" "\n\t"
+        "sbc %C0,__zero_reg__" "\n\t"
+        "sbc %D0,__zero_reg__" "\n\t"
+        "brne 1b"
+        : "=w" (__count)
+        : "0" (__count)
+    );
+}
+
+
+/*
+ *  _ d e l a y _ l o o p _ 1 _ x( uint8_t __count )
+ *  _ d e l a y _ l o o p _ 2 _ x( uint16_t  __count )
+ *  _ d e l a y _ l o o p _ 4 _ x( uint32_t __count )
+ *
+ *  These delay loops always have exactly 4(8) cycles per loop.
+ *  They use a 8/16/32 bit register counter respectively.
+ *
+ */
+static __inline__ void      /* exactly 4 cycles/loop, max 2**8 loops */
+_delay_loop_1_x( uint8_t __n )
+{                                               /* cycles per loop      */
+    __asm__ volatile (                          /* __n..one        zero */
+        "1: dec  %0"   "\n\t"                   /*    1             1   */
+        "   breq 2f"   "\n\t"                   /*    1             2   */
+        "2: brne 1b"   "\n\t"                   /*    2             1   */
+        : "=r" (__n)                            /*  -----         ----- */
+        : "0" (__n)                             /*    4             4   */
+    );
+}
+
+static __inline__ void      /* exactly 4 cycles/loop, max 2**16 loops */
+_delay_loop_2_x( uint16_t __n )
+{                                               /* cycles per loop      */
+    __asm__ volatile (                          /* __n..one        zero */
+        "1: sbiw %0,1"   "\n\t"                 /*    2             2   */
+        "   brne 1b  "   "\n\t"                 /*    2             1   */
+        "   nop      "   "\n\t"                 /*                  1   */
+        : "=w" (__n)                            /*  -----         ----- */
+        : "0" (__n)                             /*    4             4   */
+    );
+}
+
+static __inline__ void      /* exactly 8 cycles/loop, max 2**32 loops */
+_delay_loop_3_x( uint32_t __n )
+{                                               /* cycles per loop      */
+    __asm__ volatile (                          /* __n..one        zero */
+        "1: sbiw %A0,1           "  "\n\t"      /*    2             2   */
+        "   sbc  %C0,__zero_reg__"  "\n\t"      /*    1             1   */
+        "   sbc  %D0,__zero_reg__"  "\n\t"      /*    1             1   */
+        "   nop                  "  "\n\t"      /*    1             1   */
+        "   breq 2f              "  "\n\t"      /*    1             2   */
+        "2: brne 1b              "  "\n\t"      /*    2             1   */
+        : "=w" (__n)                            /*  -----         ----- */
+        : "0" (__n)                             /*    8             8   */
+    );
+}
+
+
+/*
+ *
+ *  _ d e l a y _ c y c l e s (double __ticks_d)
+ *
+ *  Perform an accurate delay of a given number of processor cycles.
+ *
+ *  All the floating point arithmetic will be handled by the
+ *  GCC Preprocessor and no floating point code will be generated.
+ *  Allthough the parameter __ticks_d is of type 'double' this
+ *  function can be called with any constant integer value, too.
+ *  GCC will handle the casting appropriately.
+ *
+ *  With an 8 MHz clock e.g., delays ranging from 125 nanoseconds
+ *  up to (2**32-1) * 125ns ~= 536,87 seconds are feasible.
+ *
+ */
+static __inline__ void
+_delay_cycles(const double __ticks_d)
+{
+    uint32_t __ticks = (uint32_t)(__ticks_d);
+    uint32_t __padding;
+    uint32_t __loops;
+
+    /*
+     * Special optimization for very
+     * small delays - not using any register.
+     */
+    if( __ticks <= 12 )  {              /* this can be done with 4 opcodes      */
+        __padding = __ticks;
+
+    /* create a single byte counter */
+    } else if( __ticks <= 0x400 )  {
+        __ticks -= 1;                   /* caller needs 1 cycle to init counter */
+        __loops = __ticks / 4;
+        __padding = __ticks % 4;
+        if( __loops != 0 )
+            _delay_loop_1_x( (uint8_t)__loops );
+
+    /* create a two byte counter */
+    } else if( __ticks <= 0x40001 )  {
+        __ticks -= 2;                   /* caller needs 2 cycles to init counter */
+        __loops = __ticks / 4;
+        __padding = __ticks % 4;
+        if( __loops != 0 )
+            _delay_loop_2_x( (uint16_t)__loops );
+
+    /* create a four byte counter */
+    } else  {
+        __ticks -= 4;                   /* caller needs 4 cycles to init counter */
+        __loops = __ticks / 8;
+        __padding = __ticks % 8;
+        if( __loops != 0 )
+            _delay_loop_3_x( (uint32_t)__loops );
+    }
+
+    if( __padding ==  1 )  _NOP1();
+    if( __padding ==  2 )  _NOP2();
+    if( __padding ==  3 )  _NOP3();
+    if( __padding ==  4 )  _NOP4();
+    if( __padding ==  5 )  _NOP5();
+    if( __padding ==  6 )  _NOP6();
+    if( __padding ==  7 )  _NOP7();
+    if( __padding ==  8 )  _NOP8();
+    if( __padding ==  9 )  _NOP9();
+    if( __padding == 10 ) _NOP10();
+    if( __padding == 11 ) _NOP11();
+    if( __padding == 12 ) _NOP12();
+}
+
+
+/*
+ *
+ *   _ d e l a y _ n s (double __ns)
+ *   _ d e l a y _ u s (double __us)
+ *   _ d e l a y _ m s (double __ms)
+ *   _ d e l a y _ s   (double __s)
+ *
+ *   Perform a very exact delay with a resolution as accurate as a
+ *   single CPU clock (the macro F_CPU is supposed to be defined to a
+ *   constant defining the CPU clock frequency in Hertz).
+ *
+ */
+#define _delay_ns(__ns)     _delay_cycles( (double)(F_CPU)*((double)__ns)/1.0e9 + 0.5 )
+#define _delay_us(__us)     _delay_cycles( (double)(F_CPU)*((double)__us)/1.0e6 + 0.5 )
+#define _delay_ms(__ms)     _delay_cycles( (double)(F_CPU)*((double)__ms)/1.0e3 + 0.5 )
+#define _delay_s(  __s)     _delay_cycles( (double)(F_CPU)*((double)__s )/1.0e0 + 0.5 )
+
+#endif /* _AVR_DELAY_X_H_ */
diff --git a/BaseTinyFirmware/GCC/doxygen.png b/BaseTinyFirmware/GCC/doxygen.png
new file mode 100644 (file)
index 0000000..ccabc50
Binary files /dev/null and b/BaseTinyFirmware/GCC/doxygen.png differ
diff --git a/BaseTinyFirmware/GCC/enums.h b/BaseTinyFirmware/GCC/enums.h
new file mode 100644 (file)
index 0000000..b8c92c5
--- /dev/null
@@ -0,0 +1,56 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Enums in common for Slave and Master\r
+ *\r
+ *      Contains enumerations of timers and variable specifiers for\r
+ *      time.c and USI.c.\n\r
+ *      These are also used in the Master, and have therefore been\r
+ *      put in a separate file for convenience.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/enums.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef ENUMS_H\r
+#define ENUMS_H\r
+\r
+//******************************************************************************\r
+// Variable specifiers (for Master-Slave communication)\r
+//******************************************************************************\r
+enum {\r
+       ADR_ADCS = 1,          //!< Indicates that ADCS is read/write target.\r
+       ADR_BATTACTIVE,        //!< Indicates that BattActive is read/write target.\r
+       ADR_BATTDATA,          //!< Indicates that BattData is read/write target.\r
+       ADR_BATTCTRL,          //!< Indicates that BattControl is read/write target.\r
+       ADR_TIMERS             //!< Indicates that timeval is read/write target.\r
+};\r
+\r
+\r
+//******************************************************************************\r
+// Timers\r
+//******************************************************************************\r
+enum {\r
+       TIMER_USI = 0,          //!< Timer meant for USI.\r
+       TIMER_CHG,              //!< Timer meant for charging.\r
+       TIMER_GEN,              //!< Timer meant for general use.\r
+       TIMER_TEMP,             //!< Timer meant for timing of temperature rise.\r
+       TIMERS                  //!< Number of timers used.\r
+};\r
+\r
+#endif // ENUMS_H\r
diff --git a/BaseTinyFirmware/GCC/liioncharge.c b/BaseTinyFirmware/GCC/liioncharge.c
new file mode 100644 (file)
index 0000000..0ce5427
--- /dev/null
@@ -0,0 +1,156 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Charge state function for Li-Ion batteries\r
+ *\r
+ *      Contains the charge state function, in which the Li-Ion charging\r
+ *      algorithm is, plus the associated functions.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONcharge.c $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "battery.h"\r
+#include "charge.h"\r
+#include "chargefunc.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "LIIONspecs.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+\r
+#ifndef LIION\r
+#error LIION not defined in main.h!\r
+#endif // LIION\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Controls the charging.\r
+ *\r
+ * This function contains the charging algorithm itself, divided into stages.\n\r
+ * For each stage the PWM may be started/stopped, and the timer, \r
+ * halt-requirements and charge parameters may be set.\n\r
+ * The charging functions return whatever state is next, and as long as no\r
+ * errors occur this is the next charging stage.\r
+ *\r
+ * \note If more stages are needed simply define more states in menu.h, include\r
+ * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+ *\r
+ * \note This algorithm is for Li-Ion batteries.\r
+ */\r
+unsigned char Charge(unsigned char inp)\r
+{\r
+       unsigned char NextState;\r
+\r
+       switch (CurrentState)   {\r
+       case ST_PREQUAL:  // First step is prequalification.\r
+               \r
+               // Charge with the defined prequalifiction-current, and if no errors\r
+               // occur return ST_CCURRENT as the next state.\r
+               ChargeParameters.Current = BAT_CURRENT_PREQUAL;\r
+               ChargeParameters.NextState = ST_CCURRENT;\r
+               \r
+               // We want charging to halt if voltage reaches a limit or time runs out.\r
+               // In case of timeout the battery will be flagged as exhausted, and an\r
+               // error will be flagged.\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | \r
+                                           HALT_FLAG_EXHAUSTION);\r
+               \r
+               // Set the maximum temperature and charge voltage limit.\r
+               HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+               HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+\r
+               // Start PWM output and charging timer first.\r
+               PWM_Start();\r
+               Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+\r
+               // Call the constant current charging-function.\r
+               // If all goes well, we will get ST_CCURRENT in return.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+       \r
+\r
+       case ST_CCURRENT:  // Second step is constant current charging.\r
+               \r
+               // Set charging timer to the battery's maximum charge time.\r
+               Time_Set(TIMER_CHG,BattData.MaxTime,0,0);\r
+\r
+               // Charge at the battery's maximum current, go to ST_CVOLTAGE next.\r
+               ChargeParameters.Current = BattData.MaxCurrent;\r
+               ChargeParameters.NextState = ST_CVOLTAGE;\r
+\r
+\r
+               // Charge until the defined BatChargeVoltage is reached.\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+               \r
+               // Start charging using constant current.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       case ST_CVOLTAGE:  // Third step is constant voltage charging.\r
+               \r
+               // Charge with the defined charge-voltage, go to ST_ENDCHARGE next.\r
+               ChargeParameters.Voltage = BAT_VOLTAGE_MAX;\r
+               ChargeParameters.NextState = ST_ENDCHARGE;\r
+               \r
+               // We want charging to halt if temperature rises too high, if current\r
+               // sinks below limit, or time runs out. Also, flag error if temperature\r
+               // limit is reached. Timeout doesn't mean anything is wrong at this point.\r
+               HaltParameters.HaltFlags = (HALT_CURRENT_MIN | HALT_TIME);\r
+               \r
+               HaltParameters.CurrentMin = BattData.MinCurrent;\r
+               \r
+               // Start charging using constant voltage. We will continue on the \r
+               // timer started in ST_CCURRENT.\r
+               NextState = ConstantVoltage(); \r
+       break;\r
+\r
+\r
+       case ST_ENDCHARGE:  // Charging is done!\r
+\r
+               PWM_Stop();\r
+               BattData.Charged = TRUE;\r
+               \r
+               // If the other battery is enabled go to ST_BATCON, otherwise\r
+               // go to ST_SLEEP.\r
+               if (eeprom_read_byte(&BattControl[(BattActive+1)%2]) & BIT_BATTERY_ENABLED) {\r
+                       NextState = ST_BATCON;\r
+               } else {\r
+                       NextState = ST_SLEEP;\r
+               }               \r
+       break;\r
+\r
+\r
+       default:  // Shouldn't end up here. Reinitialize for safety.\r
+               NextState = ST_INIT;\r
+               break;\r
+       }\r
+\r
+       // Return the next state.\r
+       return(NextState);\r
+}\r
diff --git a/BaseTinyFirmware/GCC/main.c b/BaseTinyFirmware/GCC/main.c
new file mode 100644 (file)
index 0000000..62f46d3
--- /dev/null
@@ -0,0 +1,213 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Main program file\r
+ *\r
+ *      Contains the main program, which is a basic state machine.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2302 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $\r
+ * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+/*! \page License\r
+ * Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <avr/io.h>\r
+#include <avr/pgmspace.h>\r
+\r
+#include <stdlib.h>\r
+\r
+#include "structs.h"\r
+\r
+#include "main.h"\r
+#include "ADC.h"\r
+#include "statefunc.h"\r
+#include "battery.h"\r
+#include "menu.h"\r
+#include "OWI.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+#include "USI.h"\r
+\r
+\r
+\r
+//******************************************************************************\r
+// Globals\r
+//******************************************************************************\r
+unsigned char CurrentState;     //!< \brief Global that indicates current state\r
+                                //!<\r
+                                //!< Updated by main().\r
+                                //!< \note See menu.h for definition of states.\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Main program\r
+ *\r
+ * The main function goes into an infinite loop, keeping track of the current\r
+ * state and the next one. If the next state is different from the current, it\r
+ * looks up the address to the next state function, in \ref menu_state[], and \r
+ * updates \ref CurrentState. The state function is then called and will\r
+ * eventually return a new state, and so the loop reiterates.\r
+ *\r
+ * \todo The variable inp is passed to all state functions, but is not used\r
+ * for anything yet. Remove?\r
+ */\r
+int main( void )\r
+{\r
+       unsigned char nextstate, inp, i;\r
+       unsigned char (*pStateFunc)(unsigned char);   // Function pointer.\r
+       \r
+       // Initialize local state variables.\r
+       inp = ZERO;\r
+       CurrentState = nextstate = ST_INIT;\r
+       pStateFunc = NULL;\r
+       \r
+       // Look for function associated with current state, get its address.\r
+       for (i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) {\r
+          if (pgm_read_byte(&menu_state[i].state) == CurrentState) {\r
+            pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc);\r
+               }\r
+       }\r
+\r
+       while (TRUE) {\r
+               // Run function associated with current state, get next state in return.\r
+               if (pStateFunc != NULL){\r
+                       nextstate = pStateFunc(inp);\r
+               }\r
+\r
+               // Look up function for next state, if it differs from the current.\r
+               if (nextstate != CurrentState) {\r
+                       CurrentState = nextstate;\r
+                       for ( i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) {\r
+                          if (pgm_read_byte(&menu_state[i].state) == CurrentState) {\r
+                            pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/* Doxygen documentation mainpage ********************************************/\r
+/*! \mainpage\r
+ * \section intro Introduction\r
+ * This documents the software for application note AVR458. This is a charger\r
+ * for Li-Ion batteries, based on ATAVRBC100.\r
+ *\r
+ * \section compinfo Compilation Info\r
+ * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC \r
+ * the source have to be modified.\n\r
+ * \n\r
+ * To make project on IAR EWAVR:\n\r
+ * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,\r
+ * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,\r
+ * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate\r
+ * battery data if needed.\n\r
+ * \n\r
+ * Use device --cpu=tiny861, enable bit definitions in I/O include files,\r
+ * optimization low for debug target and high for release, output format: ubrof8\r
+ * for Debug and intel_extended for Release. \n\r
+ *\r
+ * \section deviceinfo Device Info\r
+ * This application is based on the ATtiny 861, but it is possible to migrate \r
+ * the design to other AVR microcontrollers, such as pin-compatible devices\r
+ * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be\r
+ * used, but with reduced functionality.\r
+ * \r
+ * Required fuse bit settings:\r
+ *    <pre>\r
+ *    FUSE BIT  | SETTING\r
+ *    ----------+--------------------\r
+ *    CKDIV8    | 1 (unprogrammed)\r
+ *    CKSEL3..0 | 0010 (internal osc)\r
+ *    </pre>\r
+ *\r
+ *\r
+ * \section todo To Do-list\r
+ * \todo\r
+ * - Finalize master-slave communication protocol\r
+ * - Implement discharge mode\r
+ *\r
+ * \section contactinfo Contact Info\r
+ * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n\r
+ * For application notes visit \r
+ * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n\r
+ * Support mail: avr@atmel.com\r
+ */\r
+\r
+\r
+/*! \page misra MISRA C rule violations\r
+ *\r
+ * \par Rule 1\r
+ * <i>"All code shall conform to ISO 9899 standard C, with no extensions\r
+ * permitted."</i>\r
+ *\r
+ * Extensions are necessary because ISO C has no way of specifying that a\r
+ * function should be an interrupt service routine, or that we would like data\r
+ * members to be stored in f.ex. EEPROM.\r
+ *\r
+ *\r
+ * \par Rule 37\r
+ * <i>"Bitwise operations shall not be performed on signed integer types."</i>\r
+ *\r
+ * The compiler assumes all the 1's we shift around to make bitmasks are signed\r
+ * integers. Specifying them all to be (unsigned int), either directly or via a\r
+ * definition, would fix the rule violations, but also reduce code readability.\r
+ *\r
+ *\r
+ * \par Rule 45\r
+ * <i>"Type casting from any type to or from pointers shall not be used."</i>\r
+ *\r
+ * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..\r
+ *\r
+ *\r
+ * \par Rule 96\r
+ * <i>"In the definition of a function-like macro the whole definition, and each\r
+ * instance of a parameter, shall be enclosed in parentheses."</i>\r
+ * \r
+ * It is difficult to use parentheses with void function-like macros.\r
+ */\r
diff --git a/BaseTinyFirmware/GCC/main.h b/BaseTinyFirmware/GCC/main.h
new file mode 100644 (file)
index 0000000..545f1ff
--- /dev/null
@@ -0,0 +1,65 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for main.c\r
+ *\r
+ *      Contains some basic definitions (FALSE, TRUE, ZERO) as well as\r
+ *      what battery type (NiMh or Li-Ion) the charger is for.\r
+ * \r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ *\r
+ * $Name$\r
+ * $Revision: 2302 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.h $\r
+ * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef _MAIN_H\r
+#define _MAIN_H\r
+\r
+\r
+//******************************************************************************\r
+// Firmware revision\r
+//******************************************************************************\r
+#define SWHIGH  1\r
+#define SWLOW   0\r
+\r
+\r
+//******************************************************************************\r
+// Battery type (add appropriate *charge.c to project!)\r
+//******************************************************************************\r
+// One or the other needs to be defined in the AVR Studio Project file\r
+//#define NIMH  //!< Use specs and state menu for NIMH.\r
+//#define LIION  //!< Use specs and state menu for LIION.\r
+#if !defined(NIMH) && !defined(LIION)\r
+#error Need to define NIMH or LIION to select charging scheme\r
+#endif\r
+\r
+\r
+//******************************************************************************\r
+// Basic definitions\r
+//******************************************************************************\r
+#define FALSE   0  //!< We have to define this ourselves.\r
+#define TRUE    (!FALSE)  //!< We have to define this ourselves.\r
+#define ZERO    0  //!< We have to define this ourselves.\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern unsigned char CurrentState;\r
+\r
+\r
+#endif //_MAIN_H\r
diff --git a/BaseTinyFirmware/GCC/menu.c b/BaseTinyFirmware/GCC/menu.c
new file mode 100644 (file)
index 0000000..824bf20
--- /dev/null
@@ -0,0 +1,79 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      State menu definition\r
+ * \r
+ *      Contains the definition of the state menu.\n\r
+ *      The state menu contains all states and adresses to associated functions.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <stdlib.h>\r
+\r
+#include "statefunc.h"\r
+#include "charge.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+\r
+\r
+//******************************************************************************\r
+// State menu (relies on the proper battery type to be defined in main.h!)\r
+//******************************************************************************\r
+#ifdef NIMH\r
+/*! \brief The state menu\r
+ *\r
+ * Contains all the defined states and addresses to their associated functions.\r
+ */\r
+const MENU_STATE_t PROGMEM menu_state[] = {\r
+//  State                                      State function\r
+  { ST_INIT,            Initialize},\r
+  { ST_BATCON,          BatteryControl},\r
+  { ST_PREQUAL,         Charge},\r
+  { ST_SLEEP,           Sleep},\r
+  { ST_FASTCHARGE,      Charge},\r
+  { ST_LOWRATECHARGE,   Charge},\r
+  { ST_ENDCHARGE,       Charge},       \r
+  { ST_DISCHARGE,       Discharge},\r
+  { ST_ERROR,           Error},\r
+  { 0,                  NULL},\r
+};\r
+#endif // NIMH\r
+\r
+#ifdef LIION\r
+/*! \brief The state menu\r
+ *\r
+ * Contains all the defined states and addresses to their associated functions.\r
+ */\r
+const MENU_STATE_t PROGMEM menu_state[] = {\r
+//  State                                      State function\r
+  { ST_INIT,            Initialize},\r
+  { ST_BATCON,          BatteryControl},\r
+  { ST_PREQUAL,         Charge},\r
+  { ST_SLEEP,           Sleep},\r
+  { ST_CCURRENT,        Charge},\r
+  { ST_CVOLTAGE,        Charge},\r
+  { ST_ENDCHARGE,       Charge},       \r
+  { ST_DISCHARGE,       Discharge},\r
+  { ST_ERROR,           Error},\r
+  { 0,                  NULL},\r
+};\r
+#endif // LIION\r
diff --git a/BaseTinyFirmware/GCC/menu.h b/BaseTinyFirmware/GCC/menu.h
new file mode 100644 (file)
index 0000000..d07857c
--- /dev/null
@@ -0,0 +1,73 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for menu.c\r
+ * \r
+ *      Contains definitions of each state and declaration of the state\r
+ *      menu entry struct.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef MENU_H\r
+#define MENU_H\r
+\r
+#include <avr/pgmspace.h>\r
+\r
+\r
+//******************************************************************************\r
+// State machine states\r
+//******************************************************************************\r
+// State machine states -- max size and number of states is 255.\r
+// State values must be larger than zero\r
+#define ST_INIT           (10)  //!< Identifies initialization state.\r
+#define ST_BATCON         (20)  //!< Identifies battery control state.\r
+#define ST_PREQUAL        (30)  //!< Identifies prequalification state.\r
+#define ST_SLEEP          (40)  //!< Identifies sleep state.\r
+#define ST_FASTCHARGE     (50)  //!< Identifies fast charge state.\r
+#define ST_LOWRATECHARGE  (60)  //!< Identifies trickle charge state.\r
+#define ST_ENDCHARGE             (70)  //!< Identifies end of charge.\r
+#define ST_DISCHARGE      (80)  //!< Identifies discharge state.\r
+#define ST_ERROR          (90)  //!< Identifies error state.\r
+#define ST_CCURRENT       (100)  //!< Identifies constant current charge state.\r
+#define ST_CVOLTAGE       (110)  //!< Identifies constant voltage charge state.\r
+\r
+\r
+//******************************************************************************\r
+// Struct declarations\r
+//******************************************************************************\r
+/*! \brief Holds an entry in the state menu\r
+ *\r
+ * Contains the ID number of a state, and a pointer to its associated function\r
+ */\r
+struct MENU_STATE_struct\r
+{\r
+  unsigned char state; //!< ID number of state.\r
+  unsigned char (*pFunc)(unsigned char inp);  //!< Associated function.\r
+};\r
+typedef struct MENU_STATE_struct MENU_STATE_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern const MENU_STATE_t PROGMEM menu_state[];\r
+\r
+#endif // MENU_H\r
diff --git a/BaseTinyFirmware/GCC/nimhcharge.c b/BaseTinyFirmware/GCC/nimhcharge.c
new file mode 100644 (file)
index 0000000..1a436cd
--- /dev/null
@@ -0,0 +1,179 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Charge state function for NiMH batteries\r
+ *\r
+ *      Contains the charge state function, in which the NiMH charging\r
+ *      algorithm is, plus the associated functions.\r
+ *\r
+ * \par Application note:\r
+ *      AVR463: Charging NiMH Batteries with BC100 \n\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2255 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $\r
+ * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "battery.h"\r
+#include "charge.h"\r
+#include "chargefunc.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "NIMHspecs.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+\r
+#ifndef NIMH\r
+#error NIMH not defined in main.h!\r
+#endif // NIMH\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Controls the charging.\r
+ *\r
+ * This function contains the charging algorithm itself, divided into stages.\n\r
+ * For each stage the PWM may be started/stopped, and the timer, \r
+ * halt-requirements and charge parameters may be set.\n\r
+ * The charging functions return whatever state is next, and as long as no\r
+ * errors occur this is the next charging stage.\r
+ *\r
+ * \note If more stages are needed simply define more states in menu.h, include\r
+ * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+ *\r
+ * \note This algorithm is for NiMH batteries.\r
+ */\r
+unsigned char Charge(unsigned char inp)\r
+{\r
+       unsigned char NextState;\r
+\r
+       switch (CurrentState) {\r
+       // First stage is a prequalification. Attempt to charge battery to 1 V,\r
+       // using a 0.1 C current, within 2 minutes.\r
+       // If this fails, the battery is likely damaged.\r
+       // If it succeeds, start a fast charge.\r
+       case ST_PREQUAL:\r
+               \r
+               // Set up charge current and next state.\r
+               ChargeParameters.Current = BattData.Capacity / 10;\r
+               ChargeParameters.NextState = ST_FASTCHARGE;\r
+               \r
+               // Halt charge on voltage limit or timeout.\r
+               // Timeout means battery exhaustion.\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+                                           HALT_FLAG_EXHAUSTION);\r
+               \r
+               // Set up voltage limit and temperature limits.\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+               HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+               HaltParameters.TemperatureMax = 35;\r
+               \r
+               // Reset temperature measurement for HaltNow().\r
+               HaltParameters.LastNTC = 0;\r
+               \r
+               // Start PWM and charge timer before calling the charge function.\r
+               PWM_Start();\r
+               Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+               \r
+               // Call charge function, get next state.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,\r
+       // until either rate of temperature increase or voltage reaches limit, or\r
+       // the voltage drops sufficiently.\r
+       // Timeout doesn't mean battery exhaustion now.\r
+       case ST_FASTCHARGE:\r
+\r
+               // Set up charge current and next state.\r
+               ChargeParameters.Current = BattData.Capacity;\r
+               ChargeParameters.NextState = ST_LOWRATECHARGE;\r
+               \r
+               // Halt charge on voltage limit, timeout, voltage drop or rate of \r
+               // temperature increase.\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+                                           HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);\r
+               \r
+               // Set up limits for voltage, voltage drop, temperature and rate of \r
+               // temperature increase (1 degree C per minute).\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+               HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;\r
+               HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+               HaltParameters.TemperatureRise = 1;\r
+               \r
+               // Reset maximum voltage measurement for HaltNow().\r
+               HaltParameters.VBATMax = 0;\r
+\r
+               // Start timer, PWM should still be running.\r
+               Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);\r
+\r
+               // Call charge function, get next state.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,\r
+       // until either rate of temperature increase or voltage reaches limit.\r
+       case ST_LOWRATECHARGE:\r
+               \r
+               // Set up charge current and next state.\r
+               ChargeParameters.Current = BattData.Capacity / 10;\r
+               ChargeParameters.NextState = ST_ENDCHARGE;\r
+               \r
+               // Halt charge on voltage limit, timeout or temperature rise.\r
+               // Use the same requirements as during the last stage (ST_FASTCHARGE).\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+                                           HALT_TEMPERATURE_RISE);\r
+\r
+               // Start timer, 30 minutes.\r
+               Time_Set(TIMER_CHG, 30, 0, 0);\r
+               \r
+               // Call charge function, get next state.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       // Charging is done!\r
+       case ST_ENDCHARGE:\r
+\r
+               // Stop the PWM output and flag battery as charged.\r
+               PWM_Stop();\r
+               BattData.Charged = TRUE;\r
+               \r
+               // If the other battery is enabled go to ST_BATCON, otherwise\r
+               // go to ST_SLEEP.\r
+               if (eeprom_read_byte(&BattControl[(BattActive+1)%2]) & BIT_BATTERY_ENABLED) {\r
+                       NextState = ST_BATCON;\r
+               } else {\r
+                       NextState = ST_SLEEP;\r
+               }               \r
+       break;\r
+\r
+\r
+       default:  // Shouldn't end up here. Reinitialize for safety.\r
+               NextState = ST_INIT;\r
+               break;\r
+       }\r
+\r
+       // Return the next state to main().\r
+       return(NextState);\r
+}\r
diff --git a/BaseTinyFirmware/GCC/readme_AVR458.html b/BaseTinyFirmware/GCC/readme_AVR458.html
new file mode 100644 (file)
index 0000000..7e82c9e
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<title>ATMEL AVR Doxygen Documentation</title>\r
+<style type="text/css">\r
+<!--\r
+h3 {font-family: Arial, Helvetica, sans-serif}\r
+h5 {font-family: Arial, Helvetica, sans-serif}\r
+.legaltext {font-family: Arial, Helvetica, sans-serif; font-size: 10px; color: #999999;}\r
+p {font-family: Arial, Helvetica, sans-serif; font-size: 12px;}\r
+a:link {text-decoration: none; color:#036ab5}\r
+a:visited {text-decoration: none; color:#036ab5}\r
+a:hover {text-decoration: none; color:#036ab5}\r
+a:active {text-decoration: none; color:#036ab5}\r
+-->\r
+</style>\r
+</head>\r
+<body>\r
+<table width="80%" border="0" cellpadding="0" cellspacing="0">\r
+  <tr>\r
+    <td colspan="2"><p><img src="atmel.jpg" /></p><br /></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="2" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+       <td width="5"></td>\r
+    <td><br />\r
+               <h3><span class="h1">\r
+<!-- START INSERT DOCUMENT TITLE HERE -->\r
+               AVR458: Charging Li-Ion Batteries with BC100\r
+<!-- END INSERT DOCUMENT TITLE HERE -->\r
+               </span></h3>\r
+               <h5><span class="h1">\r
+<!-- START INSERT OPTIONAL DESCRIPTION HERE -->\r
+               This application note is based on the ATAVRBC100 Battery Charger reference design (BC100) and focuses on how to use the reference design to charge Lithium-Ion (Li-Ion) batteries. The firmware is written entirely in C language (using IAR® Systems Embedded Workbench) and is easy to port to other AVR® microcontrollers.\r
+This application is based on the ATtiny861 microcontroller but it is possible to migrate the design to other AVR microcontrollers, such as pin-compatible devices ATtiny261 and ATtiny461. Low pin count devices such as ATtiny25/45/85 can also be used, but with reduced functionality.\r
+<!-- END INSERT OPTIONAL DESCRIPTION HERE -->\r
+               </span></h5>            \r
+<!-- START INSERT DOXYGEN LINKS HERE -->\r
+               <p><a href="doxygen_avr458/doxygen/index.html">Code documentation</a> </p>\r
+<!-- END INSERT DOXYGEN LINKS HERE -->\r
+       <br />\r
+       </td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="1" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2">\r
+               <span class="legaltext"><strong>Disclaimer:</strong> The information in this document is provided in connection with Atmel products. No license, express or implied, by estoppel or otherwise, to any intellectual property right is granted by this document or in connection with the sale of Atmel products. <strong>EXCEPT AS SET FORTH IN ATMEL\92S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL\92S WEB SITE, ATMEL ASSUMES NO LIABILITY WHATSOEVER AND DISCLAIMS ANY EXPRESS, IMPLIED OR STATUTORY WARRANTY RELATING TO ITS PRODUCTS INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THIS DOCUMENT, EVEN IF ATMEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</strong> Atmel makes no representations or warranties with respect to the accuracy or completeness of the contents of this document and reserves the right to make changes to specifications and product descriptions at any time without notice. Atmel does not make any commitment to update the information contained herein. Unless specifically provided otherwise, Atmel products are not suitable for, and shall not be used in, automotive applications. Atmel\92s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.<br />\r
+           <br />\r
+               <strong>© 2006 Atmel Corporation. All rights reserved.</strong> ATMEL®, logo and combinations thereof, Everywhere You Are®, AVR®, and others, are registered trademarks or trademarks of Atmel Corporation or its subsidiaries. Other terms and product names may be trademarks of others.</span></td>\r
+  </tr>  \r
+</table>\r
+</body>\r
+</html>\r
diff --git a/BaseTinyFirmware/GCC/readme_AVR463.html b/BaseTinyFirmware/GCC/readme_AVR463.html
new file mode 100644 (file)
index 0000000..523775a
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<title>ATMEL AVR Doxygen Documentation</title>\r
+<style type="text/css">\r
+<!--\r
+h3 {font-family: Arial, Helvetica, sans-serif}\r
+h5 {font-family: Arial, Helvetica, sans-serif}\r
+.legaltext {font-family: Arial, Helvetica, sans-serif; font-size: 10px; color: #999999;}\r
+p {font-family: Arial, Helvetica, sans-serif; font-size: 12px;}\r
+a:link {text-decoration: none; color:#036ab5}\r
+a:visited {text-decoration: none; color:#036ab5}\r
+a:hover {text-decoration: none; color:#036ab5}\r
+a:active {text-decoration: none; color:#036ab5}\r
+-->\r
+</style>\r
+</head>\r
+<body>\r
+<table width="80%" border="0" cellpadding="0" cellspacing="0">\r
+  <tr>\r
+    <td colspan="2"><p><img src="atmel.jpg" /></p><br /></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="2" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+       <td width="5"></td>\r
+    <td><br />\r
+               <h3><span class="h1">\r
+<!-- START INSERT DOCUMENT TITLE HERE -->\r
+               AVR458: Charging Li-Ion Batteries with BC100\r
+<!-- END INSERT DOCUMENT TITLE HERE -->\r
+               </span></h3>\r
+               <h5><span class="h1">\r
+<!-- START INSERT OPTIONAL DESCRIPTION HERE -->\r
+This application note is based on the ATAVRBC100 Battery Charger reference design (BC100) and focuses on how to use the reference design to charge Nickel-Metal Hydride (NiMH) batteries. The firmware is written entirely in C language (using IAR Systems Embedded Workbench) and is easy to port to other AVR microcontrollers.\r
+This application is based on the ATtiny861 microcontroller but it is possible to migrate the design to other AVR microcontrollers, such as pin-compatible devices ATtiny261 and ATtiny461. Low pin count devices such as ATtiny25/45/85 can also be used, but with reduced functionality.\r
+<!-- END INSERT OPTIONAL DESCRIPTION HERE -->\r
+               </span></h5>            \r
+<!-- START INSERT DOXYGEN LINKS HERE -->\r
+               <p><a href="doxygen_avr463/doxygen/index.html">Code documentation</a> </p>\r
+<!-- END INSERT DOXYGEN LINKS HERE -->\r
+       <br />\r
+       </td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="1" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2">\r
+               <span class="legaltext"><strong>Disclaimer:</strong> The information in this document is provided in connection with Atmel products. No license, express or implied, by estoppel or otherwise, to any intellectual property right is granted by this document or in connection with the sale of Atmel products. <strong>EXCEPT AS SET FORTH IN ATMEL\92S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL\92S WEB SITE, ATMEL ASSUMES NO LIABILITY WHATSOEVER AND DISCLAIMS ANY EXPRESS, IMPLIED OR STATUTORY WARRANTY RELATING TO ITS PRODUCTS INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THIS DOCUMENT, EVEN IF ATMEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</strong> Atmel makes no representations or warranties with respect to the accuracy or completeness of the contents of this document and reserves the right to make changes to specifications and product descriptions at any time without notice. Atmel does not make any commitment to update the information contained herein. Unless specifically provided otherwise, Atmel products are not suitable for, and shall not be used in, automotive applications. Atmel\92s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.<br />\r
+           <br />\r
+               <strong>© 2006 Atmel Corporation. All rights reserved.</strong> ATMEL®, logo and combinations thereof, Everywhere You Are®, AVR®, and others, are registered trademarks or trademarks of Atmel Corporation or its subsidiaries. Other terms and product names may be trademarks of others.</span></td>\r
+  </tr>  \r
+</table>\r
+</body>\r
+</html>\r
diff --git a/BaseTinyFirmware/GCC/statefunc.c b/BaseTinyFirmware/GCC/statefunc.c
new file mode 100644 (file)
index 0000000..9df2b5c
--- /dev/null
@@ -0,0 +1,426 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      State functions\r
+ *\r
+ *      Contains the functions related to the states defined in menu.h.\n\r
+ *      Also contains related functions, i.e. for checking jumpers, setting\r
+ *      error flags and "dozing".\r
+ *\r
+ *      \note The state function Charge() is in a separate file since it\r
+ *      should easily be changed with regard to battery type.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include <avr/wdt.h>\r
+#include <avr/wdt.h>\r
+#include <avr/sleep.h>\r
+#include <avr/eeprom.h>\r
+\r
+#include <stdlib.h>\r
+\r
+#include "structs.h"\r
+#include "enums.h"\r
+\r
+#include "ADC.h"\r
+#include "statefunc.h"\r
+#include "battery.h"\r
+#include "charge.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "OWI.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+#include "USI.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
+                           //!< \note See statefunc.h for definitions of flags.\r
+\r
+//! \brief Holds the state in which latest error flag was set.\r
+//! \note See menu.h for definitions of states.\r
+unsigned char ErrorState;\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Initialization\r
+ *\r
+ * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
+ * - Initializes the one-wire interface\r
+ * - Clears on-chip EEPROM\r
+ * - Sets battery enable pins as outputs, then disables batteries\r
+ * - Initializes SPI according to \ref SPIMODE\r
+ * - Initializes ADC\r
+ * - Initializes timers\r
+ * - Reads battery data from both battery inputs (via ADC)\r
+ * - Disables batteries again\r
+ * - Sets battery A as the current one (\ref BattActive = 0)\r
+ * - Clears ErrorFlags\r
+ *\r
+ * \param inp Not used.\r
+ *\r
+ * \retval ST_BATCON Next state in the sequence.\r
+ */\r
+unsigned char Initialize(unsigned char inp)\r
+{\r
+       unsigned char i, page;\r
+\r
+       // Disable interrupts while setting prescaler.\r
+       cli();\r
+       \r
+       CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
+       CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
+       \r
+       // Init 1-Wire(R) interface.\r
+       OWI_Init(OWIBUS);\r
+       \r
+       // Clear on-chip EEPROM.\r
+       for (page = 0; page < 4; page++)        {\r
+               for (i = 0; i < 32; i++) {\r
+                  eeprom_write_byte(&BattEEPROM[page][i], 0);\r
+               }\r
+       }\r
+\r
+       DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
+       DisableBatteries();\r
+       SPI_Init(SPIMODE);\r
+       ADC_Init();\r
+       Time_Init();\r
+\r
+       // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
+       for (i = 0; i < 2; i++) {\r
+               EnableBattery(i);\r
+               ADC_Wait();\r
+               BatteryStatusRefresh();\r
+       }\r
+    \r
+       DisableBatteries();\r
+       \r
+       BattActive = 0;               // We have to start somewhere..\r
+       ErrorFlags = 0;\r
+       \r
+       // Init complete! Go to ST_BATCON next.\r
+       return(ST_BATCON);\r
+}\r
+\r
+\r
+/*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
+ *\r
+ * First, JumperCheck() is called. If successful, the function checks if any\r
+ * valid batteries are connected and attempts to charge these, if necessary.\n\r
+ * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
+ * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
+ * batteries. In this last case, the error is also flagged.\r
+ *\r
+ * \param inp Not used.\r
+ *\r
+ * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
+ * no valid batteries.\r
+ * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
+ * charged.\r
+ * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
+ * charged.\r
+ */\r
+unsigned char BatteryControl(unsigned char inp)\r
+{\r
+       unsigned char i;\r
+       \r
+       // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
+       if (!JumperCheck()) {\r
+               return(ST_ERROR);           // Error. Exit before damage is done!\r
+       }\r
+       \r
+       // If neither battery is valid, flag error and go to error state\r
+       if (!(eeprom_read_byte(&BattControl[0]) & BIT_BATTERY_ENABLED) && (!eeprom_read_byte(&BattControl[1]) & BIT_BATTERY_ENABLED)) {\r
+               SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
+               \r
+               return(ST_ERROR);\r
+       }\r
+\r
+       // Get ADC-readings, try to read EPROM, and start prequalification\r
+       // of any uncharged battery.\r
+       for (i = 0; i < 2; i++) {\r
+          if (eeprom_read_byte(&BattControl[i]) & BIT_BATTERY_ENABLED) {      \r
+                       EnableBattery(i);\r
+                       ADC_Wait();\r
+\r
+                       if (BatteryStatusRefresh()) {\r
+                               if (!BattData.Charged) {\r
+                                       BatteryDataRefresh();\r
+\r
+                                       return(ST_PREQUAL);       \r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       // If we end up here, one or two batteries are found and fully charged.\r
+       // Disconnect, so we don't drain them, and go to sleep.\r
+       DisableBatteries();\r
+\r
+       return(ST_SLEEP);\r
+}\r
+\r
+\r
+/*! \brief Start running on batteries\r
+ *\r
+ * \todo Run on batteries, if battery voltage high enough.\r
+ * \todo Jump here when mains voltage drops below threshold\r
+ *\r
+ */\r
+unsigned char Discharge(unsigned char inp)\r
+{\r
+       return(ST_BATCON);  // Supply voltage restored, start charging\r
+}\r
+\r
+\r
+/*! \brief Sleeps until either battery needs charging\r
+ *\r
+ * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
+ * connected batteries are both charged, the function will loop. If not, it's\r
+ * back to ST_BATCON.\r
+ *\r
+ * \param inp Not used.\r
+ *\r
+ * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
+ */\r
+unsigned char Sleep(unsigned char inp)\r
+{\r
+       unsigned char i;\r
+\r
+       do {\r
+               Doze();               // Take a nap (~8 seconds).\r
+\r
+               // If any batteries need charging, go to ST_BATCON.\r
+               // Otherwise, keep sleeping.\r
+               for (i = 0; i < 2; i++) {\r
+                       EnableBattery(i);\r
+                       ADC_Wait();\r
+                       if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
+                               return(ST_BATCON);\r
+                       }\r
+               }\r
+               \r
+               DisableBatteries();  // Disable both batteries before Doze()!\r
+       } while (TRUE);\r
+}\r
+\r
+\r
+/*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
+ *\r
+ * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
+ * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
+ * On wakeup, ADC is re-enabled.\r
+ */\r
+void Doze(void)\r
+{\r
+       // Wait for this ADC cycle to complete, then halt after the next one.\r
+       ADC_Wait();\r
+       ADCS.Halt = TRUE;\r
+       ADCS.Flag = FALSE;\r
+       \r
+       do {\r
+       } while (ADCS.Flag == FALSE);    \r
+       \r
+       WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
+       WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
+       MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
+       sleep_cpu();                            // Go to sleep, wake up by WDT.\r
+       \r
+       wdt_reset();                            // Clear watchdog reset flag.\r
+       MCUSR &= ~(1<<WDRF);          \r
+       WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
+       WDTCR = 0;                              // Turn off watchdog.\r
+       \r
+       ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
+       ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
+       \r
+       // Wait for this cycle to complete.\r
+       ADC_Wait();                             \r
+}\r
+\r
+\r
+/*! \brief Handles errors\r
+ *\r
+ * Stops PWM output and disables batteries. The function then goes into a loop\r
+ * that starts with a call to Doze(), then attempts to handle each error. The\r
+ * loop will reiterate until all flags are cleared.\n\r
+ * The charger will reinitialize after this.\r
+ *\r
+ * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
+ * If unsuccessful, the error flag will now have been set again.\n\r
+ *\r
+ * If there are no valid batteries, the loop will simply reiterate until a\r
+ * valid battery is found. The error flag will then be cleared.\n\r
+ *\r
+ * In the case of PWM controller or battery temperature errors, the error\r
+ * flag is simply cleared. This is because the problem may have gone away during\r
+ * Doze(), or after reinitializing.\n\r
+ *\r
+ * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
+ * and change batteries before clearing the error flag.\r
+ *\r
+ * \param inp Not used.\r
+ */\r
+unsigned char Error(unsigned char inp)\r
+       {\r
+       unsigned char i;\r
+       \r
+       PWM_Stop();           // Stop charging.\r
+       DisableBatteries();   // Disable all loads.\r
+       \r
+       do {\r
+               Doze();           // Take a nap.\r
+\r
+               // For each bit in ErrorFlags, starting with LSB, handle\r
+               // associated error, if the flag is set.\r
+               for (i = 0x01; i!=0; i<<=1) {\r
+                       if(i & ErrorFlags) {\r
+                               switch (i) {\r
+                               \r
+                               case  ERR_JUMPER_MISMATCH:\r
+                                       // Clear flag & recheck.\r
+                                       ErrorFlags &= ~i;\r
+                                       JumperCheck();\r
+                               break;\r
+\r
+\r
+                               case  ERR_NO_BATTERIES_ENABLED:\r
+                                       // Clear if any battery gets enabled.\r
+                                  if ((eeprom_read_byte(&BattControl[0]) & BIT_BATTERY_ENABLED) || (eeprom_read_byte(&BattControl[1]) & BIT_BATTERY_ENABLED)) {\r
+                                                       ErrorFlags &= ~i;\r
+                                       }\r
+                               break;\r
+\r
+\r
+                               case  ERR_PWM_CONTROL:\r
+                                       // Clear flag.\r
+                                       ErrorFlags &= ~i;\r
+                               break;\r
+\r
+\r
+                               case  ERR_BATTERY_TEMPERATURE:\r
+                                       // Clear flag.\r
+                                       ErrorFlags &= ~i;\r
+                               break;\r
+\r
+\r
+                               case  ERR_BATTERY_EXHAUSTED:\r
+                                       // Try the other battery.\r
+                                       BattData.Exhausted = FALSE;\r
+                                       BattActive = (BattActive + 1) % 2;\r
+                                       ErrorFlags &= ~i;\r
+                               break;\r
+\r
+                                       \r
+                               default:\r
+                               break;\r
+                               }\r
+                       }\r
+               }\r
+       } while (ErrorFlags);\r
+\r
+       return(ST_INIT);\r
+}\r
+\r
+\r
+/*! \brief Sets the specified error-flag and saves the current state\r
+ *\r
+ * Updates \ref ErrorFlags and \ref ErrorState.\r
+ *\r
+ * \note Error flags are specified in statefunc.h.\r
+ *\r
+ * \param Flag Specifies what error to flag.\r
+ */\r
+void SetErrorFlag(unsigned char Flag)\r
+{\r
+       ErrorFlags |= Flag;\r
+       ErrorState = CurrentState;\r
+}\r
+\r
+\r
+/*! \brief Checks on-board jumpers.\r
+ *\r
+ * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
+ * increasing the duty cycle until conditioned output voltage equals conditioned\r
+ * input voltage. At low PWM duty and no load buck output should be zero and,\r
+ * when increasing PWM duty, should quickly jump to steady state output roughly\r
+ * equal to input voltage. Will disable and leave disabled all batteries.\r
+ *\r
+ * \retval FALSE If jumper or load mismatch.\r
+ * \retval TRUE If everything OK.\r
+ */\r
+unsigned char JumperCheck(void)\r
+{\r
+        DisableBatteries();       // Disconnect, or loads may be destroyed!\r
+        \r
+        PWM_Start();              // Start PWM (controls the buck charger).\r
+       \r
+        // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
+        Time_Set(TIMER_GEN,0,1,0);\r
+       \r
+       do {\r
+               // If the PWM output voltage saturates the ADC, stop PWM output and\r
+               // report a failure.\r
+               if (ADCS.rawVBAT == 1023) {\r
+                       PWM_Stop();\r
+                       return(FALSE);\r
+               }\r
+\r
+               // If the absolute difference between measured (VIN - VBAT) and the\r
+               // typical value are below our set maximum, everything is OK.\r
+               if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+                                    VIN_VBAT_DIFF_MAX ) {\r
+                                \r
+                       PWM_Stop();\r
+                       return(TRUE);\r
+               }\r
+\r
+               // Charge current is too high -> check load and jumper J405 and J406.\r
+               if (abs(ADCS.IBAT) > 100) {\r
+                       PWM_Stop();\r
+                       return(FALSE);\r
+               }\r
+\r
+               // If the PWM output can't be increased high enough -> check jumpers\r
+               // J400-J404, J407 and J408.\r
+               if (!PWM_IncrementDutyCycle()) {\r
+                       PWM_Stop();\r
+                       return(FALSE);\r
+               }\r
+               \r
+      // Wait for ADC conversions to complete\r
+               ADC_Wait();\r
+       } while (Time_Left(TIMER_GEN));\r
+       \r
+\r
+       // If we end up here, the measurements took too long.\r
+       PWM_Stop();\r
+       return(FALSE);\r
+}\r
diff --git a/BaseTinyFirmware/GCC/statefunc.h b/BaseTinyFirmware/GCC/statefunc.h
new file mode 100644 (file)
index 0000000..9594f44
--- /dev/null
@@ -0,0 +1,83 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for statefunc.c\r
+ *\r
+ *      Contains definitions for SPI mode and error identifiers.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef STATEFUNC_H\r
+#define STATEFUNC_H\r
+\r
+\r
+//******************************************************************************\r
+// Wanted SPI-mode\r
+//******************************************************************************\r
+//! Sample on leading _rising_ edge, setup on trailing _falling_ edge.\r
+#define SPIMODE 0\r
+\r
+//! Sample on leading _falling_ edge, setup on trailing _rising_ edge.\r
+//#define SPIMODE 1    \r
+\r
+\r
+//******************************************************************************\r
+// Typical and maximum voltage difference between supply and battery\r
+//******************************************************************************\r
+//! Typical difference between VIN and VBAT, in mV.\r
+#define VIN_VBAT_DIFF_TYP     600\r
+\r
+//! Maximum allowed difference between VIN - VIN_VBAT_DIFF_TYP and VBAT, in mV.\r
+#define VIN_VBAT_DIFF_MAX     500\r
+\r
+\r
+//******************************************************************************\r
+// Error-flag bit identifiers\r
+//******************************************************************************\r
+//! Wrong jumper settings.\r
+#define   ERR_JUMPER_MISMATCH                          0x01  \r
+\r
+//! Both batteries disabled.\r
+#define   ERR_NO_BATTERIES_ENABLED             0x02  \r
+\r
+//! PWM output too much/little.\r
+#define   ERR_PWM_CONTROL                                      0x04  \r
+\r
+//! Battery temperature out of limits.\r
+#define   ERR_BATTERY_TEMPERATURE              0x08  \r
+\r
+//! Battery couldn't be charged.\r
+#define   ERR_BATTERY_EXHAUSTED                        0x10  \r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char Initialize(unsigned char);\r
+unsigned char BatteryControl(unsigned char);\r
+unsigned char Discharge(unsigned char);\r
+unsigned char Sleep(unsigned char);\r
+void Doze(void);\r
+unsigned char Error(unsigned char);\r
+void SetErrorFlag(unsigned char);\r
+unsigned char JumperCheck(void);\r
+\r
+#endif // STATEFUNC_H\r
diff --git a/BaseTinyFirmware/GCC/structs.h b/BaseTinyFirmware/GCC/structs.h
new file mode 100644 (file)
index 0000000..a78b9c1
--- /dev/null
@@ -0,0 +1,100 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Structs in common for Slave and Master\r
+ *\r
+ *      Contains struct declarations for ADC.c and battery.c.\n\r
+ *      These are also used in the Master, and have therefore been\r
+ *      put in a separate file for convenience.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/structs.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+\r
+#ifndef STRUCTS_H\r
+#define STRUCTS_H\r
+\r
+\r
+//******************************************************************************\r
+// Battery struct declarations\r
+//******************************************************************************\r
+/*! \brief Holds status and various data for a battery\r
+ *\r
+ * These data are updated by BatteryStatusRefresh(), RIDLookUp(),\r
+ * NTCLookUp() and BatteryDataRefresh().\r
+ */\r
+struct Batteries_struct\r
+{\r
+       unsigned char Present   : 1; //!< Battery found. (TRUE/FALSE)\r
+       unsigned char Charged   : 1; //!< Battery fully charged. (TRUE/FALSE)\r
+       unsigned char Low       : 1; //!< Battery low voltage. (TRUE/FALSE)\r
+       unsigned char Exhausted : 1; //!< Battery exhausted. (TRUE/FALSE)\r
+       unsigned char HasRID            : 1; //!< Battery has resistor ID. (TRUE/FALSE)\r
+       unsigned char Circuit;       //!< Battery safety circuit (family id).\r
+       signed char Temperature;     //!< Battery temperature, in centigrade.\r
+       unsigned char ADCSteps;      //!< ADC steps per half degree.\r
+       unsigned int  Capacity;      //!< Capacity, in mAh.\r
+       unsigned int  MaxCurrent;    //!< Charge current, in mA.\r
+       unsigned int  MaxTime;       //!< Charge cut-off time, in minutes.\r
+       unsigned int  MinCurrent;    //!< Cut-off current, in mA.\r
+};\r
+typedef struct Batteries_struct Batteries_t; //!< For convenience.\r
+\r
+\r
+// KMR: These definitions are in structs.h because they are a conversion\r
+// of Atmel's original IAR code which used a bitfield structs for the\r
+// type Battery_t. However, porting to GCC/avr-libc makes the use of a\r
+// bitfield struct for acceessing an EEPROM value cumbersome.\r
+// So, bitmasks on a uint8_t are now used insteads of a bitfield struct.\r
+// These bitmasks could be moved to battery.h, but are left here for easier\r
+// comparison to changes in Atmel's IAR code.\r
+#define BIT_BATTERY_ENABLED            0x01    //! Battery valid, enabling allowed.\r
+#define BIT_BATTERY_DISCONNECT_ALLOWED 0x02    //! Disconnect allowed.\r
+#define BIT_BATTERY_CHARGE_INHIBIT     0x04    //! Inhibit charging. \todo Changed by master?\r
+typedef uint8_t Battery_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// ADC status struct declaration\r
+//******************************************************************************\r
+/*! \brief Holds ADC-status and samples\r
+ *\r
+ * Is updated by ADC_ISR().\r
+ */\r
+struct ADC_Status_struct\r
+{\r
+       unsigned char MUX : 5;  //!< Corresponds to ADMUX low bits MUX4..0.\r
+       unsigned char Flag : 1;  //!< ADC cycle complete (TRUE/FALSE).\r
+       unsigned char Mains : 1;  //!< Mains OK? (TRUE/FALSE).\r
+       unsigned char Halt : 1;  //!< Stop A/D-conversions (TRUE/FALSE).\r
+       unsigned char ADC3_G20_OS : 4;  //!< Offset on ADC3 at 20x gain.\r
+       unsigned char ADC5_G20_OS : 4;  //!< Offset on ADC5 at 20x gain.\r
+       unsigned int rawRID;  //!< Raw, unconditioned resistor ID data.\r
+       unsigned int rawNTC;  //!< Raw, unconditioned thermistor data.\r
+       unsigned int rawVBAT;  //!< Raw, unconditioned battery voltage.\r
+       unsigned int VIN;  //!< Supply voltage, in mV.\r
+       unsigned int VBAT;  //!< Battery voltage, in mV.\r
+       signed int IBAT;  //!< Battery current, in mA.\r
+       signed int discIBAT[4];  //!< Discrete battery current readings, in mA.\r
+       signed int avgIBAT;  //!< Average of the last four IBAT readings, in mA.\r
+};\r
+typedef struct ADC_Status_struct ADC_Status_t; //!< For convenience.\r
+\r
+\r
+#endif // STRUCTS_H\r
diff --git a/BaseTinyFirmware/GCC/time.c b/BaseTinyFirmware/GCC/time.c
new file mode 100644 (file)
index 0000000..ee738bd
--- /dev/null
@@ -0,0 +1,161 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for timing\r
+ *\r
+ *      Contains functions to initialize, set, poll and stop timers.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+\r
+#include "enums.h"\r
+\r
+#include "main.h"\r
+#include "time.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+unsigned long timeval[TIMERS];  //!< Contains the values for each timer.\r
+\r
+// timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
+//#pragma vector = TIM0_OVF_vect\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Interrupt service routine for timer 0 overflow\r
+ *\r
+ * Timer 0 runs at 125 kHz and compare match will occur every millisecond\r
+ * (125 / 125 kHz = 1.0 ms), which will result in a call to this function.\r
+ * When called, this function will decrement the time left for each timer,\r
+ * unless they are already at zero.\r
+ */\r
+ISR(TIMER0_COMPA_vect)\r
+{\r
+       unsigned char i;\r
+\r
+       // 1 ms has passed, decrement all non-zero timers.\r
+       for (i = 0; i < TIMERS; i++) {\r
+               if(timeval[i] > 0) {\r
+                       timeval[i]--;\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Checks if a specified timer has expired\r
+ *\r
+ * \param timer Specifies timer\r
+ *\r
+ * \retval TRUE Timer still going.\r
+ * \retval FALSE Timer has expired.\r
+ */ \r
+unsigned char Time_Left(unsigned char timer)\r
+{\r
+       if(timeval[timer] > 0) {\r
+               return(TRUE);\r
+       } else {\r
+               return(FALSE);\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Sets the specified timer\r
+ *\r
+ * \param timer Specifies timer\r
+ * \param min Minutes for timer to count down\r
+ * \param sec Seconds for timer to count down\r
+ * \param ms Milliseconds for timer to count down\r
+ */\r
+void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+                                 unsigned char ms)\r
+{\r
+//     timeval[i] = 4 * (1000*(sec + 60*min) + ms);   // about 4000 ticks per second\r
+//     timeval[i] = 240000 * (unsigned long)min;\r
+//     timeval[i] += 4000 * (unsigned long)sec;\r
+//     timeval[i] += 4 * (unsigned long)ms;\r
+\r
+       timeval[timer] = 60000 * (unsigned long)min;\r
+       timeval[timer] += 1000 * (unsigned long)sec;\r
+       timeval[timer] += 1 * (unsigned long)ms;\r
+}\r
+\r
+\r
+/*! \brief Stops timers\r
+ *\r
+ * Sets timer0's clock source to none.\r
+ */\r
+void Time_Stop(void)\r
+{\r
+       TCCR0B = 0;\r
+}\r
+\r
+\r
+/*! \brief Starts timers\r
+ *\r
+ * Sets timer0's clock source to system clock divided by 64.\r
+ */\r
+void Time_Start(void)\r
+{\r
+       TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+}\r
+\r
+\r
+/*! \brief Initializes timers\r
+ *\r
+ * Resets all the timer values to 0, then sets up timer 0 for a compare match\r
+ * every millisecond.\r
+ */\r
+void Time_Init(void)\r
+{\r
+       unsigned char i;\r
+       \r
+       for (i = 0; i<<TIMERS; i++)     {\r
+               timeval[i] = 0;\r
+       }\r
+\r
+       //    OCR0A = 0;  // Doesn't matter, will run in normal mode.\r
+       \r
+       OCR0A = 125;  // Will give a compare match every ms.\r
+       \r
+       OCR0B = 0;  // Doesn't matter, will run in normal mode.\r
+\r
+               //    TCCR0A = 0;  // Normal 8-bit mode, no input capture.\r
+\r
+       TCCR0A = (1<<WGM00);  // 8-bit CTC mode.\r
+       \r
+       //    TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00);  // CLKT0 = CLK/8 = 1 MHz.\r
+       \r
+       TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+\r
+       //    TIMSK |= (1<<TOIE0);      // Overflow interrupt enabled.\r
+\r
+       TIMSK |= (1<<OCIE0A);  // Timer 0, Compare match A interrupt enabled.\r
+\r
+       // Enable interrupts, just in case they weren't already.\r
+       sei();       \r
+}\r
diff --git a/BaseTinyFirmware/GCC/time.h b/BaseTinyFirmware/GCC/time.h
new file mode 100644 (file)
index 0000000..5dc4f0e
--- /dev/null
@@ -0,0 +1,49 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Header file for time.c\r
+ *\r
+ *      Contains definitions of the number of timers used and their names.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef TIME_H\r
+#define TIME_H\r
+\r
+\r
+//******************************************************************************\r
+// Globals\r
+//******************************************************************************\r
+extern unsigned long timeval[];  // Needed for SPI transfer.\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+\r
+unsigned char Time_Left(unsigned char i);\r
+void Time_Set(unsigned char i, unsigned int min, unsigned char sec,\r
+                                 unsigned char ms);\r
+void Time_Stop(void);\r
+void Time_Start(void);\r
+void Time_Init(void);\r
+\r
+#endif // TIME_H\r
diff --git a/BaseTinyFirmware/IAR/ADC.c b/BaseTinyFirmware/IAR/ADC.c
new file mode 100644 (file)
index 0000000..b1229a2
--- /dev/null
@@ -0,0 +1,427 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for use of ADC\r
+ *\r
+ *      Contains high level functions for initializing the ADC, interrupt\r
+ *      handling, and treatment of samples.\n\r
+ *      The ADC is set to free running mode and uses an external reference\r
+ *      voltage.\n\r
+ *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
+ *      and restarted by the ISR.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+\r
+#include "structs.h"\r
+\r
+#include "main.h"\r
+#include "ADC.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+// ADC status struct.\r
+//! \brief Holds sampled data and ADC-status\r
+ADC_Status_t ADCS;\r
+\r
+\r
+/*! \brief Indicates maximum battery voltage.\r
+ *\r
+ * This variable is stored in EEPROM and indicates how much the battery voltage\r
+ * is downscaled by HW before it is sampled. The amount of downscaling depends\r
+ * on the maximum battery voltage, and is necessary to avoid saturation of the\r
+ * ADC (reference voltage is 2.5 V).\r
+ *\r
+ * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
+ *\r
+ * \note Defaults to 1, which means 10 V max battery voltage.\r
+ *\r
+ * \note Table of settings:\r
+ * <pre>\r
+ * VBAT_RANGE | Max battery voltage | Jumper setting\r
+ *         0  |             5V      |        1/2\r
+ *         1  |            10V      |        1/4\r
+ *         2  |            20V      |        1/8\r
+ *         3  |            30V      |       1/12\r
+ *         4  |            40V      |       1/16\r
+ * </pre>\r
+ */\r
+// Maximum battery voltage (affects scaling of samples).\r
+__eeprom unsigned char VBAT_RANGE = 1;\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Interrupt Service routine for ADC.\r
+ *\r
+ * This ISR stores the sampled values in the ADC status-struct, then\r
+ * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
+ * Once the sequence is completed, ADCS.Flag is set and unless\r
+ * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
+ * is disabled.\n\r
+ * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
+ *\r
+ * \note Table of scanning sequence:\r
+ * <pre>\r
+ * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
+ * ----+--------+----------+----------+------+---------+-------\r
+ *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
+ *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
+ *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
+ *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
+ *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
+ *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
+ *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
+ *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
+ * </pre>\r
+ *\r
+ * \todo IIN (#7 in sequence) is never used.\r
+ *\r
+ * \todo Signed is never set. Signed measurements of IBAT will halve the\r
+ * measuring sensitivity, and is therefore not favourable. At the moment,\r
+ * great currents (f.ex. if something happens with the battery) will be\r
+ * interpreted as negative, which might cause unfavourable behaviour during\r
+ * charging (depending on what PWM behaviour is defined), f.ex.\r
+ * ConstantCurrent() will keep increasing the PWM output. This results in an\r
+ * PWM controller error being flagged and the program going into\r
+ * error-state and eventually reinitializing.\r
+ */\r
+#pragma vector=ADC_vect\r
+__interrupt void ADC_ISR(void)\r
+{\r
+       static unsigned char avgIndex = 0;\r
+       unsigned char i, Next, Signed;\r
+       signed int  temp = 0;\r
+       \r
+       Signed = FALSE;  // Presume next conversion is unipolar.\r
+       ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
+         // conversions take at least 25 ADCCLK. (It is restarted later)\r
+       \r
+       // Handle the conversion, depending on what channel it is from, then\r
+       // switch to the next channel in the sequence.\r
+       switch (ADCS.MUX){\r
+               // MUX = 0b000001 => ADC1 (PA1) = NTC\r
+               case 0x01:\r
+                       ADCS.rawNTC = ADC;\r
+                       Next=0x02;\r
+               break;\r
+\r
+               \r
+               // MUX = 0b000010 => ADC2 (PA2) = RID\r
+               case 0x02:\r
+                       ADCS.rawRID = ADC;\r
+                       Next=0x03;\r
+               break;\r
+\r
+               \r
+               // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
+               case 0x03:\r
+                       // Supply voltage is always divided by 16.\r
+                       ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
+                       \r
+                       // Is mains failing?\r
+                       if (ADCS.VIN < VIN_MIN) {\r
+                               ADCS.Mains = FALSE;\r
+                       } else {\r
+                               ADCS.Mains = TRUE;\r
+                       }\r
+                       \r
+                       Next=0x05;\r
+               break;\r
+\r
+               \r
+               // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
+               case 0x05:\r
+                       ADCS.rawVBAT = ADC;\r
+                       \r
+                       // Scale voltage according to jumper setting.\r
+                       ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
+                       Next=0x17;\r
+//                     Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
+               break;\r
+\r
+\r
+               case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
+                       // If bipolar, from -512 to 0, to 511:\r
+                       // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
+               \r
+                       // Scale sample according to jumper setting, handle negative numbers.\r
+                       if (ADC > 511) {\r
+                               ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
+                                            (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+                       } else if (ADC > 0) {\r
+                               ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
+                       } else {\r
+                               ADCS.IBAT = 0;\r
+                       }\r
+\r
+                       // Insert sample of battery current into the averaging-array\r
+                       // (overwriting the oldest sample), then recalculate and store the\r
+                       // average. This is the last conversion in the sequence, so\r
+                       // flag a complete ADC-cycle and restart sequence.\r
+                       ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
+                       for (i = 0; i < 4 ; i++) {\r
+                               temp += ADCS.discIBAT[i];\r
+                       }\r
+                       \r
+                       ADCS.avgIBAT = (temp / 4);\r
+                       \r
+                       ADCS.Flag = TRUE;\r
+                       Next=0x01;\r
+                       Signed = FALSE;  // This is the only bipolar conversion.\r
+               break;\r
+\r
+               \r
+               default:  // Should not happen. (Invalid MUX-channel)\r
+                       Next=0x01;  // Start at the beginning of sequence.\r
+               break;\r
+       }\r
+       \r
+       // Update MUX to next channel in sequence, set a bipolar conversion if\r
+       // this has been flagged.\r
+       ADCS.MUX = Next;                    \r
+       ADMUX = (1<<REFS0) + ADCS.MUX;      \r
+\r
+       if (Signed)     {\r
+         ADCSRB |= (1<<BIN);               \r
+       } else {\r
+         ADCSRB &= ~(1<<BIN);              \r
+       }\r
+\r
+       // Re-enable the ADC unless a halt has been flagged and a conversion\r
+       // cycle has completed.\r
+       if (!((ADCS.Halt) && (ADCS.Flag))) {\r
+         ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
+       }\r
+}\r
+\r
+\r
+/*! \brief Scales sample to represent "actual voltage" in mV.\r
+ *\r
+ * This function returns the actual sampled voltage, scaled according\r
+ * to the jumper settings.\r
+ *\r
+ * \param setting Indicates what downscaling was used.\r
+ * \param data The sampled value.\r
+ *\r
+ * \note Table for setting-parameter:\n\r
+ * <pre>\r
+ * Presume VREF = 2.5V and Gain = 1x.\r
+ * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
+ * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
+ * --------+--------+------+------------+-----------+-------\r
+ *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
+ *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
+ *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
+ *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
+ *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
+ *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
+ *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
+ * </pre>\r
+ */\r
+unsigned int ScaleU(unsigned char setting, unsigned int data)\r
+{\r
+       // Temporary variable needed.\r
+       unsigned int scaled = 0;\r
+\r
+       // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
+       if (setting == 3)       {\r
+               scaled = 29 * data;\r
+               scaled += (data >> 2);\r
+               scaled += (data >> 4);\r
+       } else {\r
+               // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
+               scaled = 39 * data;\r
+               scaled += (data >> 4);\r
+               \r
+               if (setting <3) {\r
+                       // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
+                       //                1: mV/LSB = 9.766 = 39.06 / 4\r
+                       //                2: mV/LSB = 19.53 = 39.06 / 2\r
+                       scaled = (scaled >> (3-setting));\r
+               }\r
+       }\r
+\r
+       return(scaled);\r
+}\r
+\r
+\r
+/*! \brief Scales sample to represent "actual current" in mA.\r
+ *\r
+ * This function returns the actual sampled current, scaled according\r
+ * to the jumper settings.\r
+ *\r
+ * \param setting Indicates what downscaling was used.\r
+ * \param data The sampled value.\r
+ *\r
+ * \note Table for setting-parameter:\n\r
+ * <pre>\r
+ * Presume VREF = 2.5V and Gain = 1x or 20x.\r
+ * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
+ * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
+ * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
+ * --------+------+------------+----------+----------+--------+-----\r
+ *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
+ *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
+ *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
+ *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
+ *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
+ *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
+ *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
+ * </pre>\r
+ */\r
+unsigned int ScaleI(unsigned char setting, unsigned int data)\r
+{\r
+       // Temporary variable needed.\r
+       unsigned int  scaled = 0;\r
+       \r
+       // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
+       if (setting == 3) {\r
+               scaled = 21 * data;\r
+               scaled -= (data >> 4);\r
+               scaled += (data >> 7);\r
+       }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
+               scaled = 28 * data;\r
+               scaled -= (data >> 3);\r
+               scaled += (data >> 5);\r
+               \r
+               if (setting <3) {\r
+                       // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
+                       //                1: mA/LSB = 6.978mA = 27.909 / 4\r
+                       //                2: mA/LSB = 13.955mA = 27.909 / 2\r
+                       scaled = (scaled >> (3-setting));\r
+               }\r
+       }\r
+       \r
+       return(scaled);\r
+}\r
+\r
+\r
+/*! \brief Waits for two full cycles of ADC-conversions to occur.\r
+ *\r
+ * This function clears the cycle complete-flag, then waits for it to be set\r
+ * again. This is then repeated once before the function exits.\r
+ * \r
+ */\r
+void ADC_Wait(void)\r
+{\r
+       // Clear ADC flag and wait for cycle to complete.\r
+       ADCS.Flag = FALSE;              \r
+       do {\r
+       } while (ADCS.Flag == FALSE);      \r
+       \r
+       // Repeat, so we are sure the data beong to the same cycle.\r
+       ADCS.Flag = FALSE;              \r
+       do {\r
+       } while (ADCS.Flag == FALSE);      \r
+}\r
+\r
+\r
+/*! \brief Initializes ADC and input pins.\r
+ *\r
+ * This function initializes the ADC to free running mode, sampling from\r
+ * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
+ * It also measures and stores calibration data for offset.\r
+ *\r
+ * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
+ *\r
+ * \note Table of MUX settings for offset measurement:\r
+ * <pre>\r
+ *    Ch | Pin |    Gain |    MUX\r
+ * ------+-----+---------+-------\r
+ *  ADC1 | PA1 |     20x | 001101\r
+ *  ADC3 | PA4 |     20x | 010001\r
+ *  ADC5 | PA6 |     20x | 010110\r
+ *  ADC9 | PB6 |     20x | 011011\r
+ *  ADC0 | PA0 | 20x/32x | 111000\r
+ *  ADC0 | PA0 |   1x/8x | 111001\r
+ *  ADC1 | PA1 | 20x/32x | 111010\r
+ *  ADC2 | PA2 | 20x/32x | 111011\r
+ *  ADC4 | PA5 | 20x/32x | 111100\r
+ *  ADC5 | PA6 | 20x/32x | 111101\r
+ *  ADC6 | PA7 | 20x/32x | 111110\r
+ * </pre>\r
+ */\r
+void ADC_Init(void)\r
+{\r
+       unsigned char i;\r
+\r
+       __disable_interrupt();\r
+\r
+       ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
+\r
+       // Configure ADC pins (inputs and disabled pull-ups).\r
+       DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+       PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+\r
+       // Set ADC3 as reference, and MUX to measure the same pin.\r
+       ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
+       \r
+       ADCSRB = 0;\r
+\r
+       // Start conversion, no interrupt (disable ADC-ISR).\r
+       ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+\r
+       do { // Wait for conversion to finish.\r
+       } while (!(ADCSRA & (1<<ADIF)));\r
+\r
+       ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
+\r
+       ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
+\r
+       ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
+       \r
+       // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
+       ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+\r
+       do { // Wait for conversion to finish.\r
+       } while (!(ADCSRA & (1<<ADIF)));\r
+\r
+       ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
+\r
+       ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
+\r
+       // Reset the ADC-cycle.\r
+       ADCS.Flag = FALSE;      \r
+       ADCS.MUX = 0x01;                    \r
+       ADMUX = (1<<REFS0) | ADCS.MUX;      \r
+\r
+       // Clear averaged battery current and the discrete readings.\r
+       ADCS.avgIBAT = 0;\r
+       \r
+       for (i = 0; i < 4; i++) {\r
+               ADCS.discIBAT[i] = 0;             \r
+       }\r
+       \r
+       // Re-enable the ADC and ISR.\r
+       ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
+       \r
+       __enable_interrupt();\r
+\r
+       // Get a complete cycle of data before returning.\r
+       ADC_Wait();\r
+}\r
diff --git a/BaseTinyFirmware/IAR/ADC.h b/BaseTinyFirmware/IAR/ADC.h
new file mode 100644 (file)
index 0000000..ff67fbd
--- /dev/null
@@ -0,0 +1,70 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for ADC.c\r
+ *\r
+ *      Contains definitions for ADC setup, and minimum supply voltage.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef ADC_H\r
+#define ADC_H\r
+\r
+//******************************************************************************\r
+// ADC setup\r
+//******************************************************************************\r
+// 8MHz / (25x128) = 2500 samples/s/ch\r
+#define ADC_PRESCALER     0x07\r
+/*!< \brief Prescaling of ADC clock.\r
+ *\r
+ * The ADC will run at 8 MHz (system clock) divided by 128\r
+ * (prescaler), and every sample will takes approximately 25 ticks:\r
+ * Sample rate = 8 MHz / (128 * 25 cycles/sample) = 2.5 k samples/sec\r
+ */\r
+\r
+\r
+//******************************************************************************\r
+// Minimum supply voltage\r
+//******************************************************************************\r
+//! Minimum supply voltage (at TP101 = VIN+), in mV.\r
+#define VIN_MIN               4400\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern __eeprom unsigned char VBAT_RANGE;   \r
+extern ADC_Status_t ADCS;\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+#pragma vector=ADC_vect\r
+__interrupt void ADC_ISR(void);\r
+\r
+unsigned int ScaleU(unsigned char setting, unsigned int data);\r
+unsigned int ScaleI(unsigned char setting, unsigned int data);\r
+void ADC_Wait(void);\r
+void ADC_Init(void);\r
+\r
+#endif // ADC_H\r
+\r
diff --git a/BaseTinyFirmware/IAR/BC100_tiny.dep b/BaseTinyFirmware/IAR/BC100_tiny.dep
new file mode 100644 (file)
index 0000000..8cf3c86
--- /dev/null
@@ -0,0 +1,983 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+\r
+<project>\r
+  <fileVersion>2</fileVersion>\r
+  <fileChecksum>373717447</fileChecksum>\r
+  <configuration>\r
+    <name>Debug</name>\r
+    <outputs>\r
+      <file>$PROJ_DIR$\Debug\Obj\USI.r90</file>\r
+      <file>$PROJ_DIR$\Debug\List\NIMHcharge.lst</file>\r
+      <file>$PROJ_DIR$\Debug\List\OWIcrc.lst</file>\r
+      <file>$PROJ_DIR$\time.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\LIIONcharge.pbi</file>\r
+      <file>$PROJ_DIR$\main.h</file>\r
+      <file>$PROJ_DIR$\AVR458.c</file>\r
+      <file>$PROJ_DIR$\Debug\List\BC100_tiny.html</file>\r
+      <file>$PROJ_DIR$\Debug\List\battery.s90</file>\r
+      <file>$PROJ_DIR$\chargefunc.c</file>\r
+      <file>$PROJ_DIR$\charge.c</file>\r
+      <file>$PROJ_DIR$\ADC.c</file>\r
+      <file>$PROJ_DIR$\battery.c</file>\r
+      <file>$PROJ_DIR$\LIIONcharge.c</file>\r
+      <file>$PROJ_DIR$\main.c</file>\r
+      <file>$PROJ_DIR$\menu.c</file>\r
+      <file>$PROJ_DIR$\NIMHcharge.c</file>\r
+      <file>$PROJ_DIR$\OWI.c</file>\r
+      <file>$PROJ_DIR$\PWM.c</file>\r
+      <file>$PROJ_DIR$\statefunc.c</file>\r
+      <file>$PROJ_DIR$\time.c</file>\r
+      <file>$PROJ_DIR$\USI.c</file>\r
+      <file>$PROJ_DIR$\Debug\List\PWM.s90</file>\r
+      <file>$PROJ_DIR$\LIIONspecs.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\statefunc.r90</file>\r
+      <file>$TOOLKIT_DIR$\src\template\cfg1soim.xcl</file>\r
+      <file>$PROJ_DIR$\Debug\List\USI.s90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\charge.r90</file>\r
+      <file>$PROJ_DIR$\structs.h</file>\r
+      <file>$PROJ_DIR$\Debug\List\charge.lst</file>\r
+      <file>$PROJ_DIR$\Debug\Exe\BC100_tiny.d90</file>\r
+      <file>$TOOLKIT_DIR$\inc\clib\stdlib.h</file>\r
+      <file>$PROJ_DIR$\NIMHspecs.h</file>\r
+      <file>$TOOLKIT_DIR$\src\template\cfgtiny861.xcl</file>\r
+      <file>$PROJ_DIR$\PWM.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\ADC.r90</file>\r
+      <file>$PROJ_DIR$\AVR463.c</file>\r
+      <file>$PROJ_DIR$\Debug\List\OWI.s90</file>\r
+      <file>$PROJ_DIR$\Debug\List\main.lst</file>\r
+      <file>$PROJ_DIR$\Debug\List\USI.lst</file>\r
+      <file>$PROJ_DIR$\AVR463.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\BC100_tiny.pbd</file>\r
+      <file>$PROJ_DIR$\Debug\List\main.s90</file>\r
+      <file>$TOOLKIT_DIR$\inc\clib\sysmac.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\battery.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\NIMHcharge.pbi</file>\r
+      <file>$TOOLKIT_DIR$\inc\iomacro.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\ADC.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\charge.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\OWI.r90</file>\r
+      <file>$PROJ_DIR$\Debug\List\chargefunc.s90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\time.r90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\statefunc.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\List\menu.s90</file>\r
+      <file>$PROJ_DIR$\OWIcrc.h</file>\r
+      <file>$PROJ_DIR$\Debug\List\time.lst</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\NIMHcharge.r90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\OWIcrc.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\AVR463.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\List\battery.lst</file>\r
+      <file>$PROJ_DIR$\battery.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\main.r90</file>\r
+      <file>$PROJ_DIR$\Debug\List\statefunc.s90</file>\r
+      <file>$TOOLKIT_DIR$\inc\iotiny861.h</file>\r
+      <file>$PROJ_DIR$\USI.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\time.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\OWI.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\List\PWM.lst</file>\r
+      <file>$PROJ_DIR$\Debug\List\AVR458.lst</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\menu.r90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\PWM.pbi</file>\r
+      <file>$PROJ_DIR$\ADC.h</file>\r
+      <file>$PROJ_DIR$\Debug\List\AVR458.s90</file>\r
+      <file>$PROJ_DIR$\Debug\List\menu.lst</file>\r
+      <file>$PROJ_DIR$\statefunc.h</file>\r
+      <file>$PROJ_DIR$\Debug\List\NIMHcharge.s90</file>\r
+      <file>$TOOLKIT_DIR$\inc\inavr.h</file>\r
+      <file>$PROJ_DIR$\Debug\List\ADC.lst</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\LIIONcharge.r90</file>\r
+      <file>$PROJ_DIR$\Debug\List\OWIcrc.s90</file>\r
+      <file>$PROJ_DIR$\OWIcrc.c</file>\r
+      <file>$PROJ_DIR$\menu.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\AVR463.r90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\OWIcrc.r90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\chargefunc.r90</file>\r
+      <file>$PROJ_DIR$\charge.h</file>\r
+      <file>$TOOLKIT_DIR$\inc\ioavr.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\PWM.r90</file>\r
+      <file>$PROJ_DIR$\Debug\List\OWI.lst</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\battery.r90</file>\r
+      <file>$TOOLKIT_DIR$\inc\intrinsics.h</file>\r
+      <file>$PROJ_DIR$\Debug\List\ADC.s90</file>\r
+      <file>$PROJ_DIR$\Debug\List\chargefunc.lst</file>\r
+      <file>$PROJ_DIR$\enums.h</file>\r
+      <file>$PROJ_DIR$\AVR458.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\AVR458.r90</file>\r
+      <file>$PROJ_DIR$\Debug\List\time.s90</file>\r
+      <file>$PROJ_DIR$\OWI.h</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\chargefunc.pbi</file>\r
+      <file>$PROJ_DIR$\chargefunc.h</file>\r
+      <file>$TOOLKIT_DIR$\lib\clib\cl1s-ec_nomul.r90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\menu.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\List\statefunc.lst</file>\r
+      <file>$PROJ_DIR$\Debug\List\charge.s90</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\AVR458.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\USI.pbi</file>\r
+      <file>$PROJ_DIR$\Debug\Obj\main.pbi</file>\r
+    </outputs>\r
+    <file>\r
+      <name>$PROJ_DIR$\AVR458.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 95 72 68</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 104</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 31 43 28 93 71 94 60 5 81 97 34 3 64</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 31 43 28 93 71 94 60 5 81 97 34 3 64</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\chargefunc.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 84 50 92</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 98</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 93 28 71 60 99 5 81 34 74 3 32</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 93 28 71 60 99 5 81 34 74 3 32</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\charge.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 27 103 29</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 48</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 93 28 71 74 85 60 5 81 34 3</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 93 28 71 74 85 60 5 81 34 3</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\ADC.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 35 91 77</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 47</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 28 5 71</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 28 5 71</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\battery.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 89 8 59</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 44</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 28 93 71 60 5 97 3 32</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 28 93 71 60 5 97 3 32</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\LIIONcharge.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 78</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 4</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 93 28 60 85 99 5 81 23 34 3</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 93 28 60 85 99 5 81 23 34 3</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\main.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 61 42 38</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 106</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 31 43 28 5 71 74 60 81 97 34 3 64</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 31 43 28 5 71 74 60 81 97 34 3 64</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\menu.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 69 53 73</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 101</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 31 43 74 85 5 81</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 31 43 74 85 5 81</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\NIMHcharge.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 56 75 1</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 45</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 93 28 60 85 99 5 81 32 34 3</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 93 28 60 85 99 5 81 32 34 3</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\OWI.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 49 37 88</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 66</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 97</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 97</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\PWM.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 87 22 67</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 70</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 93 5 34 3</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 93 5 34 3</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\statefunc.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 24 62 102</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 52</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 31 43 28 93 71 74 60 85 5 81 97 34 3 64</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 31 43 28 93 71 74 60 85 5 81 97 34 3 64</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\time.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 51 96 55</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 65</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 93 5 3</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 93 5 3</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\USI.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 0 26 39</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 105</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 86 63 46 76 90 93 28 5 71 60 3 64</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 93 28 5 71 60 3 64</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>[ROOT_NODE]</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>XLINK</name>\r
+          <file> 30 7</file>\r
+        </tool>\r
+      </outputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\Debug\Exe\BC100_tiny.d90</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>XLINK</name>\r
+          <file> 7</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>XLINK</name>\r
+          <file> 33 25 35 56 49 87 0 89 84 61 69 24 51 100</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\AVR463.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 82</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 58</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 86 63 46 76 90 31 43 28 93 71 40 60 85 5 81 97 34 3 64</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\Debug\Obj\BC100_tiny.pbd</name>\r
+      <inputs>\r
+        <tool>\r
+          <name>BILINK</name>\r
+          <file> 47 45 66 70 105 44 98 106 101 52 65</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\OWIcrc.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 83 79 2</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 57</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 54 97 86 63 46</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 54 97 86 63 46</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <forcedrebuild>\r
+      <name>[MULTI_TOOL]</name>\r
+      <tool>XLINK</tool>\r
+    </forcedrebuild>\r
+  </configuration>\r
+  <configuration>\r
+    <name>Release</name>\r
+    <outputs>\r
+      <file>$PROJ_DIR$\Release\List\main.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\menu.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\time.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\statefunc.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\statefunc.lst</file>\r
+      <file>$PROJ_DIR$\Release\List\chargefunc.s90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\chargefunc.pbi</file>\r
+      <file>$PROJ_DIR$\Release\List\OWI.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\ADC.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\PWM.s90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\LIIONcharge.pbi</file>\r
+      <file>$PROJ_DIR$\Release\List\NIMHcharge.s90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\LIIONcharge.r90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\chargefunc.r90</file>\r
+      <file>$PROJ_DIR$\time.h</file>\r
+      <file>$PROJ_DIR$\main.h</file>\r
+      <file>$PROJ_DIR$\AVR458.c</file>\r
+      <file>$PROJ_DIR$\Release\Obj\main.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Exe\BC100_tiny_data.hex</file>\r
+      <file>$PROJ_DIR$\Release\Obj\AVR458.r90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\NIMHcharge.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\time.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\OWIcrc.r90</file>\r
+      <file>$PROJ_DIR$\Release\List\OWI.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\NIMHcharge.r90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\battery.r90</file>\r
+      <file>$PROJ_DIR$\chargefunc.c</file>\r
+      <file>$PROJ_DIR$\ADC.c</file>\r
+      <file>$PROJ_DIR$\battery.c</file>\r
+      <file>$PROJ_DIR$\LIIONcharge.c</file>\r
+      <file>$PROJ_DIR$\main.c</file>\r
+      <file>$PROJ_DIR$\menu.c</file>\r
+      <file>$PROJ_DIR$\NIMHcharge.c</file>\r
+      <file>$PROJ_DIR$\OWI.c</file>\r
+      <file>$PROJ_DIR$\PWM.c</file>\r
+      <file>$PROJ_DIR$\statefunc.c</file>\r
+      <file>$PROJ_DIR$\time.c</file>\r
+      <file>$PROJ_DIR$\USI.c</file>\r
+      <file>$PROJ_DIR$\Release\List\NIMHcharge.lst</file>\r
+      <file>$PROJ_DIR$\Release\List\USI.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\battery.s90</file>\r
+      <file>$PROJ_DIR$\Release\List\chargefunc.lst</file>\r
+      <file>$PROJ_DIR$\LIIONspecs.h</file>\r
+      <file>$TOOLKIT_DIR$\src\template\cfg1soim.xcl</file>\r
+      <file>$PROJ_DIR$\structs.h</file>\r
+      <file>$TOOLKIT_DIR$\inc\clib\stdlib.h</file>\r
+      <file>$PROJ_DIR$\NIMHspecs.h</file>\r
+      <file>$TOOLKIT_DIR$\src\template\cfgtiny861.xcl</file>\r
+      <file>$PROJ_DIR$\PWM.h</file>\r
+      <file>$PROJ_DIR$\Release\Obj\PWM.r90</file>\r
+      <file>$PROJ_DIR$\Release\List\OWIcrc.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\ADC.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\OWI.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\time.r90</file>\r
+      <file>$PROJ_DIR$\Release\Exe\BC100_tiny_eeprom.hex</file>\r
+      <file>$PROJ_DIR$\Release\Obj\statefunc.r90</file>\r
+      <file>$PROJ_DIR$\Release\List\USI.lst</file>\r
+      <file>$PROJ_DIR$\Release\List\menu.lst</file>\r
+      <file>$PROJ_DIR$\Release\List\BC100_tiny.map</file>\r
+      <file>$PROJ_DIR$\Release\Obj\ADC.r90</file>\r
+      <file>$PROJ_DIR$\Release\List\time.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\main.r90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\AVR458.pbi</file>\r
+      <file>$PROJ_DIR$\Release\List\PWM.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\OWI.r90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\battery.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\PWM.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\menu.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\USI.pbi</file>\r
+      <file>$PROJ_DIR$\Release\Obj\statefunc.pbi</file>\r
+      <file>$PROJ_DIR$\Release\List\ADC.lst</file>\r
+      <file>$TOOLKIT_DIR$\inc\clib\sysmac.h</file>\r
+      <file>$PROJ_DIR$\Release\List\AVR458.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\menu.r90</file>\r
+      <file>$TOOLKIT_DIR$\inc\iomacro.h</file>\r
+      <file>$PROJ_DIR$\OWIcrc.h</file>\r
+      <file>$PROJ_DIR$\battery.h</file>\r
+      <file>$TOOLKIT_DIR$\inc\iotiny861.h</file>\r
+      <file>$PROJ_DIR$\USI.h</file>\r
+      <file>$PROJ_DIR$\ADC.h</file>\r
+      <file>$PROJ_DIR$\statefunc.h</file>\r
+      <file>$TOOLKIT_DIR$\inc\inavr.h</file>\r
+      <file>$PROJ_DIR$\OWIcrc.c</file>\r
+      <file>$PROJ_DIR$\menu.h</file>\r
+      <file>$PROJ_DIR$\charge.h</file>\r
+      <file>$TOOLKIT_DIR$\inc\ioavr.h</file>\r
+      <file>$TOOLKIT_DIR$\inc\intrinsics.h</file>\r
+      <file>$PROJ_DIR$\enums.h</file>\r
+      <file>$PROJ_DIR$\AVR458.h</file>\r
+      <file>$PROJ_DIR$\OWI.h</file>\r
+      <file>$PROJ_DIR$\chargefunc.h</file>\r
+      <file>$TOOLKIT_DIR$\lib\clib\cl1s-ec_nomul.r90</file>\r
+      <file>$PROJ_DIR$\Release\Obj\OWIcrc.pbi</file>\r
+      <file>$PROJ_DIR$\Release\List\battery.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\USI.r90</file>\r
+      <file>$PROJ_DIR$\Release\Exe\BC100_tiny.hex</file>\r
+      <file>$PROJ_DIR$\Release\List\main.lst</file>\r
+      <file>$PROJ_DIR$\Release\Obj\BC100_tiny.pbd</file>\r
+    </outputs>\r
+    <file>\r
+      <name>$PROJ_DIR$\AVR458.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 19 72</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 62</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 45 71 79 88 76 15 83 89 48 14 78</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 45 71 79 88 76 15 83 89 48 14 78</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\chargefunc.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 13 5 41</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 6</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 87 44 79 76 90 15 83 48 80 14 46</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 87 44 79 76 90 15 83 48 80 14 46</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\ADC.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 59 8 70</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 51</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 44 15 79</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 44 15 79</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\battery.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 25 40 93</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 65</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 44 87 79 76 15 89 14 46</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 44 87 79 76 15 89 14 46</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\LIIONcharge.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 12</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 10</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 87 44 76 84 90 15 83 42 48 14</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 87 44 76 84 90 15 83 42 48 14</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\main.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 61 0 96</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 17</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 45 71 44 15 79 80 76 83 89 48 14 78</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 45 71 44 15 79 80 76 83 89 48 14 78</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\menu.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 73 1 57</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 67</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 45 71 80 84 15 83</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 45 71 80 84 15 83</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\NIMHcharge.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 24 11 38</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 20</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 87 44 76 84 90 15 83 46 48 14</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 87 44 76 84 90 15 83 46 48 14</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\OWI.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 64 7 23</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 52</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 89</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 89</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\PWM.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 49 9 63</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 66</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 87 15 48 14</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 87 15 48 14</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\statefunc.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 55 3 4</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 69</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 45 71 44 87 79 80 76 84 15 83 89 48 14 78</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 45 71 44 87 79 80 76 84 15 83 89 48 14 78</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\time.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 53 2 60</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 21</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 87 15 14</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 87 15 14</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\USI.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 94 39 56</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 68</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 85 77 74 81 86 87 44 15 79 76 14 78</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 85 77 74 81 86 87 44 15 79 76 14 78</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>[ROOT_NODE]</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>XLINK</name>\r
+          <file> 95 58 18 54</file>\r
+        </tool>\r
+      </outputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\OWIcrc.c</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 22 50</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 92</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>ICCAVR</name>\r
+          <file> 75 89 85 77 74</file>\r
+        </tool>\r
+        <tool>\r
+          <name>BICOMP</name>\r
+          <file> 75 89 85 77 74</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\Release\Exe\BC100_tiny.hex</name>\r
+      <outputs>\r
+        <tool>\r
+          <name>XLINK</name>\r
+          <file> 58 18 54</file>\r
+        </tool>\r
+      </outputs>\r
+      <inputs>\r
+        <tool>\r
+          <name>XLINK</name>\r
+          <file> 47 43 59 24 64 49 94 25 13 61 73 55 53 91</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <file>\r
+      <name>$PROJ_DIR$\Release\Obj\BC100_tiny.pbd</name>\r
+      <inputs>\r
+        <tool>\r
+          <name>BILINK</name>\r
+          <file> 51 20 52 66 68 65 6 17 67 69 21</file>\r
+        </tool>\r
+      </inputs>\r
+    </file>\r
+    <forcedrebuild>\r
+      <name>$PROJ_DIR$\LIIONcharge.c</name>\r
+      <tool>ICCAVR</tool>\r
+    </forcedrebuild>\r
+  </configuration>\r
+</project>\r
+\r
+\r
diff --git a/BaseTinyFirmware/IAR/BC100_tiny.ewd b/BaseTinyFirmware/IAR/BC100_tiny.ewd
new file mode 100644 (file)
index 0000000..8989609
--- /dev/null
@@ -0,0 +1,1291 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+\r
+<project>\r
+  <fileVersion>1</fileVersion>\r
+  <configuration>\r
+    <name>Debug</name>\r
+    <toolchain>\r
+      <name>AVR</name>\r
+    </toolchain>\r
+    <debug>1</debug>\r
+    <settings>\r
+      <name>C-SPY</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <version>12</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>CSVariantProcessor</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacFile</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>DDFile</name>\r
+          <state>$TOOLKIT_DIR$\Config\iotiny861.ddf</state>\r
+        </option>\r
+        <option>\r
+          <name>CInput</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCEnhancedCore</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OC64BitDoubles</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>DdfFileSlave</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RunToEnable</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>RunToName</name>\r
+          <state>main</state>\r
+        </option>\r
+        <option>\r
+          <name>newDDFileOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CSVariantEepromSize</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CSVariant64KFlash</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CdDllSlave</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CDynDriver</name>\r
+          <state>SIMAVR</state>\r
+        </option>\r
+        <option>\r
+          <name>DebuggerUseUbrofResetVector</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>CCRAVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>OCCRAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRSuppressLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRFastDownload</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRTargetCCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRdownloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>ICE200AVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>OICE200AVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRHighSpeed</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRSingleStepTimers</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRRestoreEEPROM</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRComPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRSuppLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRConsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRIce200ResetDelayList</name>\r
+          <version>8</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRIce200downloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>JTAGICEAVR</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <version>2</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>OJTAGICEAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceDefaultCom</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceComPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceSuppLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceConsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagFreqRadio</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagFreqManually</name>\r
+          <state>100000</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagFreq</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagDeviceBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagDeviceAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagInstrBitsBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagInstrBitsAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceDaisyChain</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugTimers</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugEeprom</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugReset</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugFuses</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIcedownloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ExitBreakpointP7</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PutcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GetcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>JTAGICEMKIIAVR</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <version>5</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceDefaultCom</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceComPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceSuppLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceConsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagFreqRadio</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagFreqManually</name>\r
+          <state>100000</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagFreq</name>\r
+          <version>0</version>\r
+          <state>8</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagDeviceBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagDeviceAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagInstrBitsBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagInstrBitsAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceDaisyChain</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugTimers</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugEeprom</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugReset</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugFuses</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIcedownloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagSoftwareBreak</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ExitBreakpointP7</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PutcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GetcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRCommunicationNew</name>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRCommunicationUsbEditId</name>\r
+          <state></state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>SIMAVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>OSIMAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OSIMAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OSIMAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>THIRDPARTYAVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRDriverDll</name>\r
+          <state>Browse to your Third party driver</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRSuppress</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRVerify</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRLogFileCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRLogFileEditB</name>\r
+          <state>$TOOLKIT_DIR$\cspycomm.log</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <debuggerPlugins>\r
+      <plugin>\r
+        <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin</file>\r
+        <loadFlag>0</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin</file>\r
+        <loadFlag>1</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>\r
+        <loadFlag>0</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\Profiling\Profiling.ENU.ewplugin</file>\r
+        <loadFlag>1</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\Stack\Stack.ENU.ewplugin</file>\r
+        <loadFlag>1</loadFlag>\r
+      </plugin>\r
+    </debuggerPlugins>\r
+  </configuration>\r
+  <configuration>\r
+    <name>Release</name>\r
+    <toolchain>\r
+      <name>AVR</name>\r
+    </toolchain>\r
+    <debug>0</debug>\r
+    <settings>\r
+      <name>C-SPY</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <version>12</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>CSVariantProcessor</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacFile</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>DDFile</name>\r
+          <state>$TOOLKIT_DIR$\Config\iotiny861.ddf</state>\r
+        </option>\r
+        <option>\r
+          <name>CInput</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCEnhancedCore</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OC64BitDoubles</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>DdfFileSlave</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RunToEnable</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>RunToName</name>\r
+          <state>main</state>\r
+        </option>\r
+        <option>\r
+          <name>newDDFileOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CSVariantEepromSize</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CSVariant64KFlash</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CdDllSlave</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CDynDriver</name>\r
+          <state>SIMAVR</state>\r
+        </option>\r
+        <option>\r
+          <name>DebuggerUseUbrofResetVector</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>CCRAVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>OCCRAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRSuppressLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRFastDownload</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRTargetCCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCRAVRdownloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>ICE200AVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>OICE200AVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRHighSpeed</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRSingleStepTimers</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRRestoreEEPROM</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRComPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRSuppLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRConsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRIce200ResetDelayList</name>\r
+          <version>8</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OICE200AVRIce200downloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>JTAGICEAVR</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <version>2</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>OJTAGICEAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceDefaultCom</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceComPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceSuppLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceConsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagFreqRadio</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagFreqManually</name>\r
+          <state>100000</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagFreq</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagDeviceBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagDeviceAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagInstrBitsBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceJtagInstrBitsAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIceDaisyChain</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugTimers</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugEeprom</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugReset</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagDebugFuses</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEAVRJtagIcedownloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ExitBreakpointP7</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PutcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GetcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>JTAGICEMKIIAVR</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <version>5</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRBaud</name>\r
+          <version>0</version>\r
+          <state>5</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRParity</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRDataBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRStopBits</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRHandshake</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRAllComm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRDoLogfile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRLogFile</name>\r
+          <state>cspycomm.log</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceDefaultCom</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceComPort</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceSuppLoad</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceConsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagFreqRadio</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagFreqManually</name>\r
+          <state>100000</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagFreq</name>\r
+          <version>0</version>\r
+          <state>8</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagDeviceBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagDeviceAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagInstrBitsBefore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceJtagInstrBitsAfter</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIceDaisyChain</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugTimers</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugEeprom</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugReset</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagDebugFuses</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagIcedownloadToData</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRJtagSoftwareBreak</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ExitBreakpointP7</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PutcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GetcharBreakpointP7</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRCommunicationNew</name>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>OJTAGICEMKIIAVRCommunicationUsbEditId</name>\r
+          <state></state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>SIMAVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>OSIMAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OSIMAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OSIMAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>THIRDPARTYAVR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>1</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRDriver</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRDriverDll</name>\r
+          <state>Browse to your Third party driver</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRSuppress</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRVerify</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRLogFileCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OTHIRDPARTYAVRLogFileEditB</name>\r
+          <state>$TOOLKIT_DIR$\cspycomm.log</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <debuggerPlugins>\r
+      <plugin>\r
+        <file>$TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin</file>\r
+        <loadFlag>0</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin</file>\r
+        <loadFlag>1</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin</file>\r
+        <loadFlag>0</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\Profiling\Profiling.ENU.ewplugin</file>\r
+        <loadFlag>1</loadFlag>\r
+      </plugin>\r
+      <plugin>\r
+        <file>$EW_DIR$\common\plugins\Stack\Stack.ENU.ewplugin</file>\r
+        <loadFlag>1</loadFlag>\r
+      </plugin>\r
+    </debuggerPlugins>\r
+  </configuration>\r
+</project>\r
+\r
+\r
diff --git a/BaseTinyFirmware/IAR/BC100_tiny.ewp b/BaseTinyFirmware/IAR/BC100_tiny.ewp
new file mode 100644 (file)
index 0000000..1e84451
--- /dev/null
@@ -0,0 +1,1966 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+\r
+<project>\r
+  <fileVersion>1</fileVersion>\r
+  <configuration>\r
+    <name>Debug</name>\r
+    <toolchain>\r
+      <name>AVR</name>\r
+    </toolchain>\r
+    <debug>1</debug>\r
+    <settings>\r
+      <name>General</name>\r
+      <archiveVersion>4</archiveVersion>\r
+      <data>\r
+        <version>7</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>GGEnhancedCore</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>Variant Memory</name>\r
+          <version>0</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ExePath</name>\r
+          <state>Debug\Exe</state>\r
+        </option>\r
+        <option>\r
+          <name>ObjPath</name>\r
+          <state>Debug\Obj</state>\r
+        </option>\r
+        <option>\r
+          <name>ListPath</name>\r
+          <state>Debug\List</state>\r
+        </option>\r
+        <option>\r
+          <name>GGEnableConfig</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GG64KFlash</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GG64BitDoubles</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GGFPSLICCOnfig</name>\r
+          <version>0</version>\r
+          <state>3</state>\r
+        </option>\r
+        <option>\r
+          <name>LCEnableBitDefs</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>LCHeapSize</name>\r
+          <state>0x10</state>\r
+        </option>\r
+        <option>\r
+          <name>SCCStackSize</name>\r
+          <state>0x40</state>\r
+        </option>\r
+        <option>\r
+          <name>SCExtCStack</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRStackSize</name>\r
+          <state>24</state>\r
+        </option>\r
+        <option>\r
+          <name>SCExtRStack</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCEnableBus</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCAddWaitstate</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRamBase</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRamSize</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRomBase</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRomSize</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCNVBase</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCNVSize</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCInitWithReti</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GOutputBinary</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GGEepromUtil</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GGEepromUtilSize</name>\r
+          <state>512</state>\r
+        </option>\r
+        <option>\r
+          <name>New Variant Processor</name>\r
+          <version>23</version>\r
+          <state>107</state>\r
+        </option>\r
+        <option>\r
+          <name>GRuntimeLibSelect</name>\r
+          <version>0</version>\r
+          <state>4</state>\r
+        </option>\r
+        <option>\r
+          <name>RTDescription</name>\r
+          <state>Use the legacy C runtime library.</state>\r
+        </option>\r
+        <option>\r
+          <name>RTConfigPath</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RTLibraryPath</name>\r
+          <state>$TOOLKIT_DIR$\LIB\CLIB\cl1s-ec_nomul.r90</state>\r
+        </option>\r
+        <option>\r
+          <name>Input variant</name>\r
+          <version>0</version>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>Input description</name>\r
+          <state>No float.</state>\r
+        </option>\r
+        <option>\r
+          <name>Output variant</name>\r
+          <version>0</version>\r
+          <state>3</state>\r
+        </option>\r
+        <option>\r
+          <name>Output description</name>\r
+          <state>No float, no field width, no precision.</state>\r
+        </option>\r
+        <option>\r
+          <name>GRuntimeLibSelectSlave</name>\r
+          <version>0</version>\r
+          <state>4</state>\r
+        </option>\r
+        <option>\r
+          <name>GeneralMisraRules</name>\r
+          <version>0</version>\r
+          <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>\r
+        </option>\r
+        <option>\r
+          <name>GeneralEnableMisra</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GeneralMisraVerbose</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>LCTinyHeapSize</name>\r
+          <state>0x10</state>\r
+        </option>\r
+        <option>\r
+          <name>LCNearHeapSize</name>\r
+          <state>0x20</state>\r
+        </option>\r
+        <option>\r
+          <name>LCFarHeapSize</name>\r
+          <state>0x1000</state>\r
+        </option>\r
+        <option>\r
+          <name>LCHugeHeapSize</name>\r
+          <state>0x1000</state>\r
+        </option>\r
+        <option>\r
+          <name>LCsHeapConfigText</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GGNoMULInstruction</name>\r
+          <state>1</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>ICCAVR</name>\r
+      <archiveVersion>4</archiveVersion>\r
+      <data>\r
+        <version>13</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>CCVariantProcessor</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnhancedCore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCVariantMemory</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCObjPrefix</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCDefines</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCPreprocFile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCPreprocComments</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCPreprocLine</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListCFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListCMnemonics</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListCMessages</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListAssFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListAssSource</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnableRemarks</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagSuppress</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagRemark</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagWarning</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagError</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCWarnAsError</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCConstInRAM</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCInitInFlash</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCForceVariables</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOldCallConv</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLockRegs</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptSizeSpeed</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptimization</name>\r
+          <version>1</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCAllowList</name>\r
+          <version>3</version>\r
+          <state>000000</state>\r
+        </option>\r
+        <option>\r
+          <name>CCCrossCallPassesList</name>\r
+          <version>8</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCObjUseModuleName</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCObjModuleName</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDebugInfo</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCNoErrorMsg</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CC64BitDoubles</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CC64KFlash</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnableExtBus</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnableBitDefs</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptForceCrossCall</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCCharIs</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCExt</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>IExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>IExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCMultibyteSupport</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCRequirePrototypes</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCCompilerRuntimeInfo</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>newCCIncludePaths</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCStdIncCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCStdIncludePaths</name>\r
+          <state>$TOOLKIT_DIR$\INC\</state>\r
+          <state>$TOOLKIT_DIR$\INC\CLIB\</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEepromSize</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLockRegsSlave</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptSizeSpeedSlave</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptimizationSlave</name>\r
+          <version>1</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOutputFile</name>\r
+          <state>$FILE_BNAME$.r90</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLangSelect</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CompilerMisraRules</name>\r
+          <version>0</version>\r
+          <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>\r
+        </option>\r
+        <option>\r
+          <name>CompilerMisraOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLibConfigHeader</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>PreInclude</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCOverrideModuleTypeDefault</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCRadioModuleType</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCRadioModuleTypeSlave</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCAdditionalCommandLineOptionsSlave</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>AAVR</name>\r
+      <archiveVersion>4</archiveVersion>\r
+      <data>\r
+        <version>10</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>IProcessor</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AObjPrefix</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ACaseSensitivity</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnEnable</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnWhat</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnOne</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnRange1</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnRange2</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CDebug</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ADefines</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>MacroChars</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefAsm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefLine</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefTime</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefDate</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefTid</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AList</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AListHeader</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AListing</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>Includes</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacDefs</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacExps</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>MacExec</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OnlyAssed</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MultiLine</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLengthCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLength</name>\r
+          <state>80</state>\r
+        </option>\r
+        <option>\r
+          <name>TabSpacing</name>\r
+          <state>8</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRef</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRefDefines</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRefInternal</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRefDual</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OAEnhancedCore</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AMaxErrOn</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AMaxErrNum</name>\r
+          <state>100</state>\r
+        </option>\r
+        <option>\r
+          <name>ANewIncludes</name>\r
+          <state>$TOOLKIT_DIR$\INC\</state>\r
+        </option>\r
+        <option>\r
+          <name>AsmMultiByteSupport</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AavrVariantMemory</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AsmHasElpm</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AsmOutputFile</name>\r
+          <state>$FILE_BNAME$.r90</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>CUSTOM</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <extensions></extensions>\r
+        <cmdline></cmdline>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>BICOMP</name>\r
+      <archiveVersion>0</archiveVersion>\r
+      <data/>\r
+    </settings>\r
+    <settings>\r
+      <name>BUILDACTION</name>\r
+      <archiveVersion>1</archiveVersion>\r
+      <data>\r
+        <prebuild></prebuild>\r
+        <postbuild></postbuild>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>XLINK</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>13</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>XOutOverride</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OutputFile</name>\r
+          <state>$PROJ_FNAME$.d90</state>\r
+        </option>\r
+        <option>\r
+          <name>OutputFormat</name>\r
+          <version>11</version>\r
+          <state>70</state>\r
+        </option>\r
+        <option>\r
+          <name>FormatVariant</name>\r
+          <version>8</version>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>SecondaryOutputFile</name>\r
+          <state>(None for the selected format)</state>\r
+        </option>\r
+        <option>\r
+          <name>XDefines</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>AlwaysOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OverlapWarnings</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>NoGlobalCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XList</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>SegmentMap</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ListSymbols</name>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLengthCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLength</name>\r
+          <state>80</state>\r
+        </option>\r
+        <option>\r
+          <name>XIncludes</name>\r
+          <state>$TOOLKIT_DIR$\LIB\</state>\r
+        </option>\r
+        <option>\r
+          <name>ModuleStatus</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XclOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XclFile</name>\r
+          <state>$TOOLKIT_DIR$\src\template\cfgtiny861.xcl</state>\r
+        </option>\r
+        <option>\r
+          <name>XclFileSlave</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>DoFill</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>FillerByte</name>\r
+          <state>0xFF</state>\r
+        </option>\r
+        <option>\r
+          <name>DoCrc</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcSize</name>\r
+          <version>0</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcAlgo</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcPoly</name>\r
+          <state>0x11021</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcCompl</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>RangeCheckAlternatives</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SuppressAllWarn</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SuppressDiags</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>TreatAsWarn</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>TreatAsErr</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>ModuleLocalSym</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcBitOrder</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OXSysConfig</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>XExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>IncludeSuppressed</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ModuleSummary</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>xcProgramEntryLabel</name>\r
+          <state>__program_start</state>\r
+        </option>\r
+        <option>\r
+          <name>DebugInformation</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>RuntimeControl</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>IoEmulation</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AllowExtraOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GenerateExtraOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XExtraOutOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ExtraOutputFile</name>\r
+          <state>BC100_tiny.a90</state>\r
+        </option>\r
+        <option>\r
+          <name>ExtraOutputFormat</name>\r
+          <version>11</version>\r
+          <state>25</state>\r
+        </option>\r
+        <option>\r
+          <name>ExtraFormatVariant</name>\r
+          <version>8</version>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>xcOverrideProgramEntryLabel</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>xcProgramEntryLabelSelect</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ListOutputFormat</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>BufferedTermOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XcRTLibraryFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OXLibIOConfig</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>XLinkMisraHandler</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OverlaySystemMap</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinaryFile</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinarySymbol</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinarySegment</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinaryAlign</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CrcAlign</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcInitialValue</name>\r
+          <state>0x00</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>XAR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>0</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>1</debug>\r
+        <option>\r
+          <name>XAROutOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XARInputs</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OutputFile</name>\r
+          <state></state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>BILINK</name>\r
+      <archiveVersion>0</archiveVersion>\r
+      <data/>\r
+    </settings>\r
+  </configuration>\r
+  <configuration>\r
+    <name>Release</name>\r
+    <toolchain>\r
+      <name>AVR</name>\r
+    </toolchain>\r
+    <debug>0</debug>\r
+    <settings>\r
+      <name>General</name>\r
+      <archiveVersion>4</archiveVersion>\r
+      <data>\r
+        <version>7</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>GGEnhancedCore</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>Variant Memory</name>\r
+          <version>0</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ExePath</name>\r
+          <state>Release\Exe</state>\r
+        </option>\r
+        <option>\r
+          <name>ObjPath</name>\r
+          <state>Release\Obj</state>\r
+        </option>\r
+        <option>\r
+          <name>ListPath</name>\r
+          <state>Release\List</state>\r
+        </option>\r
+        <option>\r
+          <name>GGEnableConfig</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GG64KFlash</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GG64BitDoubles</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GGFPSLICCOnfig</name>\r
+          <version>0</version>\r
+          <state>3</state>\r
+        </option>\r
+        <option>\r
+          <name>LCEnableBitDefs</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>LCHeapSize</name>\r
+          <state>0x10</state>\r
+        </option>\r
+        <option>\r
+          <name>SCCStackSize</name>\r
+          <state>0x40</state>\r
+        </option>\r
+        <option>\r
+          <name>SCExtCStack</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRStackSize</name>\r
+          <state>24</state>\r
+        </option>\r
+        <option>\r
+          <name>SCExtRStack</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCEnableBus</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCAddWaitstate</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRamBase</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRamSize</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRomBase</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCRomSize</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCNVBase</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCNVSize</name>\r
+          <state>0x0</state>\r
+        </option>\r
+        <option>\r
+          <name>SCInitWithReti</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GOutputBinary</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GGEepromUtil</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GGEepromUtilSize</name>\r
+          <state>512</state>\r
+        </option>\r
+        <option>\r
+          <name>New Variant Processor</name>\r
+          <version>23</version>\r
+          <state>107</state>\r
+        </option>\r
+        <option>\r
+          <name>GRuntimeLibSelect</name>\r
+          <version>0</version>\r
+          <state>4</state>\r
+        </option>\r
+        <option>\r
+          <name>RTDescription</name>\r
+          <state>Use the legacy C runtime library.</state>\r
+        </option>\r
+        <option>\r
+          <name>RTConfigPath</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RTLibraryPath</name>\r
+          <state>$TOOLKIT_DIR$\LIB\CLIB\cl1s-ec_nomul.r90</state>\r
+        </option>\r
+        <option>\r
+          <name>Input variant</name>\r
+          <version>0</version>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>Input description</name>\r
+          <state>No float.</state>\r
+        </option>\r
+        <option>\r
+          <name>Output variant</name>\r
+          <version>0</version>\r
+          <state>3</state>\r
+        </option>\r
+        <option>\r
+          <name>Output description</name>\r
+          <state>No float, no field width, no precision.</state>\r
+        </option>\r
+        <option>\r
+          <name>GRuntimeLibSelectSlave</name>\r
+          <version>0</version>\r
+          <state>4</state>\r
+        </option>\r
+        <option>\r
+          <name>GeneralMisraRules</name>\r
+          <version>0</version>\r
+          <state>0000111110110101101110011100111101100110011001000101110111101101100111111111111100110011111001100111001111111101111111111111110</state>\r
+        </option>\r
+        <option>\r
+          <name>GeneralEnableMisra</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GeneralMisraVerbose</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>LCTinyHeapSize</name>\r
+          <state>0x10</state>\r
+        </option>\r
+        <option>\r
+          <name>LCNearHeapSize</name>\r
+          <state>0x20</state>\r
+        </option>\r
+        <option>\r
+          <name>LCFarHeapSize</name>\r
+          <state>0x1000</state>\r
+        </option>\r
+        <option>\r
+          <name>LCHugeHeapSize</name>\r
+          <state>0x1000</state>\r
+        </option>\r
+        <option>\r
+          <name>LCsHeapConfigText</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>GGNoMULInstruction</name>\r
+          <state>1</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>ICCAVR</name>\r
+      <archiveVersion>4</archiveVersion>\r
+      <data>\r
+        <version>13</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>CCVariantProcessor</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnhancedCore</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCVariantMemory</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCObjPrefix</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCDefines</name>\r
+          <state>NDEBUG</state>\r
+        </option>\r
+        <option>\r
+          <name>CCPreprocFile</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCPreprocComments</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCPreprocLine</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListCFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListCMnemonics</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListCMessages</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListAssFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCListAssSource</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnableRemarks</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagSuppress</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagRemark</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagWarning</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDiagError</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCWarnAsError</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCConstInRAM</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCInitInFlash</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCForceVariables</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOldCallConv</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLockRegs</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptSizeSpeed</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptimization</name>\r
+          <version>1</version>\r
+          <state>4</state>\r
+        </option>\r
+        <option>\r
+          <name>CCAllowList</name>\r
+          <version>3</version>\r
+          <state>111010</state>\r
+        </option>\r
+        <option>\r
+          <name>CCCrossCallPassesList</name>\r
+          <version>8</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCObjUseModuleName</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCObjModuleName</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCDebugInfo</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCNoErrorMsg</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CC64BitDoubles</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CC64KFlash</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnableExtBus</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEnableBitDefs</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptForceCrossCall</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCCharIs</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCExt</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>IExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>IExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCMultibyteSupport</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCRequirePrototypes</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCCompilerRuntimeInfo</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>newCCIncludePaths</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCStdIncCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCStdIncludePaths</name>\r
+          <state>$TOOLKIT_DIR$\INC\</state>\r
+          <state>$TOOLKIT_DIR$\INC\CLIB\</state>\r
+        </option>\r
+        <option>\r
+          <name>CCEepromSize</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLockRegsSlave</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptSizeSpeedSlave</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOptimizationSlave</name>\r
+          <version>1</version>\r
+          <state>4</state>\r
+        </option>\r
+        <option>\r
+          <name>CCOutputFile</name>\r
+          <state>$FILE_BNAME$.r90</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLangSelect</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CompilerMisraRules</name>\r
+          <version>0</version>\r
+          <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state>\r
+        </option>\r
+        <option>\r
+          <name>CompilerMisraOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCLibConfigHeader</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>PreInclude</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CCOverrideModuleTypeDefault</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCRadioModuleType</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CCRadioModuleTypeSlave</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OCCAdditionalCommandLineOptionsSlave</name>\r
+          <state>0</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>AAVR</name>\r
+      <archiveVersion>4</archiveVersion>\r
+      <data>\r
+        <version>10</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>IProcessor</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AObjPrefix</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ACaseSensitivity</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnEnable</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnWhat</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnOne</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnRange1</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>AWarnRange2</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CDebug</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ADefines</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>MacroChars</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefAsm</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefLine</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefTime</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefDate</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>UndefTid</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AList</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AListHeader</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AListing</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>Includes</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacDefs</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MacExps</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>MacExec</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OnlyAssed</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>MultiLine</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLengthCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLength</name>\r
+          <state>80</state>\r
+        </option>\r
+        <option>\r
+          <name>TabSpacing</name>\r
+          <state>8</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRef</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRefDefines</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRefInternal</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AXRefDual</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AExtraOptions</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OAEnhancedCore</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AExtraOptionsCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AMaxErrOn</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AMaxErrNum</name>\r
+          <state>100</state>\r
+        </option>\r
+        <option>\r
+          <name>ANewIncludes</name>\r
+          <state>$TOOLKIT_DIR$\INC\</state>\r
+        </option>\r
+        <option>\r
+          <name>AsmMultiByteSupport</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AavrVariantMemory</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AsmHasElpm</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>AsmOutputFile</name>\r
+          <state>$FILE_BNAME$.r90</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>CUSTOM</name>\r
+      <archiveVersion>3</archiveVersion>\r
+      <data>\r
+        <extensions></extensions>\r
+        <cmdline></cmdline>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>BICOMP</name>\r
+      <archiveVersion>0</archiveVersion>\r
+      <data/>\r
+    </settings>\r
+    <settings>\r
+      <name>BUILDACTION</name>\r
+      <archiveVersion>1</archiveVersion>\r
+      <data>\r
+        <prebuild></prebuild>\r
+        <postbuild></postbuild>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>XLINK</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>13</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>XOutOverride</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OutputFile</name>\r
+          <state>$PROJ_FNAME$.hex</state>\r
+        </option>\r
+        <option>\r
+          <name>OutputFormat</name>\r
+          <version>11</version>\r
+          <state>23</state>\r
+        </option>\r
+        <option>\r
+          <name>FormatVariant</name>\r
+          <version>8</version>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>SecondaryOutputFile</name>\r
+          <state>(None for the selected format)</state>\r
+        </option>\r
+        <option>\r
+          <name>XDefines</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>AlwaysOutput</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OverlapWarnings</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>NoGlobalCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XList</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>SegmentMap</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>ListSymbols</name>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLengthCheck</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>PageLength</name>\r
+          <state>80</state>\r
+        </option>\r
+        <option>\r
+          <name>XIncludes</name>\r
+          <state>$TOOLKIT_DIR$\LIB\</state>\r
+        </option>\r
+        <option>\r
+          <name>ModuleStatus</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XclOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XclFile</name>\r
+          <state>$TOOLKIT_DIR$\src\template\cfgtiny861.xcl</state>\r
+        </option>\r
+        <option>\r
+          <name>XclFileSlave</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>DoFill</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>FillerByte</name>\r
+          <state>0xFF</state>\r
+        </option>\r
+        <option>\r
+          <name>DoCrc</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcSize</name>\r
+          <version>0</version>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcAlgo</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcPoly</name>\r
+          <state>0x11021</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcCompl</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>RangeCheckAlternatives</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SuppressAllWarn</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>SuppressDiags</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>TreatAsWarn</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>TreatAsErr</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>ModuleLocalSym</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcBitOrder</name>\r
+          <version>0</version>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OXSysConfig</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>XExtraOptionsCheck</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>XExtraOptions</name>\r
+          <state>-y(CODE)</state>\r
+          <state>-Ointel-extended,(DATA)=$EXE_DIR$\$PROJ_FNAME$_data.hex</state>\r
+          <state>-Ointel-extended,(XDATA)=$EXE_DIR$\$PROJ_FNAME$_eeprom.hex</state>\r
+        </option>\r
+        <option>\r
+          <name>IncludeSuppressed</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ModuleSummary</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>xcProgramEntryLabel</name>\r
+          <state>__program_start</state>\r
+        </option>\r
+        <option>\r
+          <name>DebugInformation</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>RuntimeControl</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>IoEmulation</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>AllowExtraOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>GenerateExtraOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XExtraOutOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ExtraOutputFile</name>\r
+          <state>BC100_tiny.a90</state>\r
+        </option>\r
+        <option>\r
+          <name>ExtraOutputFormat</name>\r
+          <version>11</version>\r
+          <state>25</state>\r
+        </option>\r
+        <option>\r
+          <name>ExtraFormatVariant</name>\r
+          <version>8</version>\r
+          <state>2</state>\r
+        </option>\r
+        <option>\r
+          <name>xcOverrideProgramEntryLabel</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>xcProgramEntryLabelSelect</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>ListOutputFormat</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>BufferedTermOutput</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XcRTLibraryFile</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>OXLibIOConfig</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>XLinkMisraHandler</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>OverlaySystemMap</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinaryFile</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinarySymbol</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinarySegment</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>RawBinaryAlign</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>CrcAlign</name>\r
+          <state>1</state>\r
+        </option>\r
+        <option>\r
+          <name>CrcInitialValue</name>\r
+          <state>0x00</state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>XAR</name>\r
+      <archiveVersion>2</archiveVersion>\r
+      <data>\r
+        <version>0</version>\r
+        <wantNonLocal>1</wantNonLocal>\r
+        <debug>0</debug>\r
+        <option>\r
+          <name>XAROutOverride</name>\r
+          <state>0</state>\r
+        </option>\r
+        <option>\r
+          <name>XARInputs</name>\r
+          <state></state>\r
+        </option>\r
+        <option>\r
+          <name>OutputFile</name>\r
+          <state></state>\r
+        </option>\r
+      </data>\r
+    </settings>\r
+    <settings>\r
+      <name>BILINK</name>\r
+      <archiveVersion>0</archiveVersion>\r
+      <data/>\r
+    </settings>\r
+  </configuration>\r
+  <file>\r
+    <name>$PROJ_DIR$\ADC.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\battery.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\chargefunc.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\main.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\menu.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\NIMHcharge.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\OWI.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\PWM.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\statefunc.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\time.c</name>\r
+  </file>\r
+  <file>\r
+    <name>$PROJ_DIR$\USI.c</name>\r
+  </file>\r
+</project>\r
+\r
+\r
diff --git a/BaseTinyFirmware/IAR/BC100_tiny.eww b/BaseTinyFirmware/IAR/BC100_tiny.eww
new file mode 100644 (file)
index 0000000..8ea13f5
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+\r
+<workspace>\r
+  <project>\r
+    <path>$WS_DIR$\BC100_tiny.ewp</path>\r
+  </project>\r
+  <batchBuild/>\r
+</workspace>\r
+\r
+\r
diff --git a/BaseTinyFirmware/IAR/Debug/Exe/BC100_tiny.d90 b/BaseTinyFirmware/IAR/Debug/Exe/BC100_tiny.d90
new file mode 100644 (file)
index 0000000..65633bf
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Exe/BC100_tiny.d90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/List/ADC.lst b/BaseTinyFirmware/IAR/Debug/List/ADC.lst
new file mode 100644 (file)
index 0000000..ffe51c1
--- /dev/null
@@ -0,0 +1,1067 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:38 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c                #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c --cpu=tiny861  #\r
+#                    -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\    #\r
+#                    -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB  #\r
+#                    C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\          #\r
+#                    --initializers_in_flash -z2 --no_cse --no_inline         #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ADC.lst   #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90    #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for use of ADC\r
+      6           *\r
+      7           *      Contains high level functions for initializing the ADC, interrupt\r
+      8           *      handling, and treatment of samples.\n\r
+      9           *      The ADC is set to free running mode and uses an external reference\r
+     10           *      voltage.\n\r
+     11           *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
+     12           *      and restarted by the ISR.\r
+     13           *\r
+     14           * \par Application note:\r
+     15           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     16           *      AVR463: Charging NiMH Batteries with BC100\r
+     17           *\r
+     18           * \par Documentation:\r
+     19           *      For comprehensive code documentation, supported compilers, compiler\r
+     20           *      settings and supported devices see readme.html\r
+     21           *\r
+     22           * \author\r
+     23           *      Atmel Corporation: http://www.atmel.com \n\r
+     24           *      Support email: avr@atmel.com \n\r
+     25           *      Original author: \n\r
+     26           *\r
+     27           * $Name$\r
+     28           * $Revision: 2299 $\r
+     29           * $RCSfile$\r
+     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
+     31           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     32           ******************************************************************************/\r
+     33          \r
+     34          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3b\r
+   \   <unnamed> volatile __io _A_PORTA\r
+   \                     _A_PORTA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3a\r
+   \   <unnamed> volatile __io _A_DDRA\r
+   \                     _A_DDRA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x27\r
+   \   <unnamed> volatile __io _A_ADMUX\r
+   \                     _A_ADMUX:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x26\r
+   \   <unnamed> volatile __io _A_ADCSRA\r
+   \                     _A_ADCSRA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x24\r
+   \   <unnamed> volatile __io _A_ADC\r
+   \                     _A_ADC:\r
+   \   00000000                      DS 2\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x23\r
+   \   <unnamed> volatile __io _A_ADCSRB\r
+   \                     _A_ADCSRB:\r
+   \   00000000                      DS 1\r
+     35          #include <inavr.h>\r
+     36          \r
+     37          #include "structs.h"\r
+     38          \r
+     39          #include "main.h"\r
+     40          #include "ADC.h"\r
+     41          \r
+     42          \r
+     43          //******************************************************************************\r
+     44          // Variables\r
+     45          //******************************************************************************\r
+     46          // ADC status struct.\r
+     47          //! \brief Holds sampled data and ADC-status\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     48          ADC_Status_t ADCS;\r
+   \                     ADCS:\r
+   \   00000000                      DS 24\r
+     49          \r
+     50          \r
+     51          /*! \brief Indicates maximum battery voltage.\r
+     52           *\r
+     53           * This variable is stored in EEPROM and indicates how much the battery voltage\r
+     54           * is downscaled by HW before it is sampled. The amount of downscaling depends\r
+     55           * on the maximum battery voltage, and is necessary to avoid saturation of the\r
+     56           * ADC (reference voltage is 2.5 V).\r
+     57           *\r
+     58           * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
+     59           *\r
+     60           * \note Defaults to 1, which means 10 V max battery voltage.\r
+     61           *\r
+     62           * \note Table of settings:\r
+     63           * <pre>\r
+     64           * VBAT_RANGE | Max battery voltage | Jumper setting\r
+     65           *         0  |             5V      |        1/2\r
+     66           *         1  |            10V      |        1/4\r
+     67           *         2  |            20V      |        1/8\r
+     68           *         3  |            30V      |       1/12\r
+     69           *         4  |            40V      |       1/16\r
+     70           * </pre>\r
+     71           */\r
+     72          // Maximum battery voltage (affects scaling of samples).\r
+\r
+   \                                 In  segment EEPROM_I, align 1, keep-with-next\r
+     73          __eeprom unsigned char VBAT_RANGE = 1;\r
+   \                     VBAT_RANGE:\r
+   \   00000000   01                 DB 1\r
+     74          \r
+     75          \r
+     76          //******************************************************************************\r
+     77          // Functions\r
+     78          //******************************************************************************\r
+     79          /*! \brief Interrupt Service routine for ADC.\r
+     80           *\r
+     81           * This ISR stores the sampled values in the ADC status-struct, then\r
+     82           * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
+     83           * Once the sequence is completed, ADCS.Flag is set and unless\r
+     84           * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
+     85           * is disabled.\n\r
+     86           * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
+     87           *\r
+     88           * \note Table of scanning sequence:\r
+     89           * <pre>\r
+     90           * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
+     91           * ----+--------+----------+----------+------+---------+-------\r
+     92           *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
+     93           *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
+     94           *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
+     95           *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
+     96           *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
+     97           *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
+     98           *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
+     99           *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
+    100           * </pre>\r
+    101           *\r
+    102           * \todo IIN (#7 in sequence) is never used.\r
+    103           *\r
+    104           * \todo Signed is never set. Signed measurements of IBAT will halve the\r
+    105           * measuring sensitivity, and is therefore not favourable. At the moment,\r
+    106           * great currents (f.ex. if something happens with the battery) will be\r
+    107           * interpreted as negative, which might cause unfavourable behaviour during\r
+    108           * charging (depending on what PWM behaviour is defined), f.ex.\r
+    109           * ConstantCurrent() will keep increasing the PWM output. This results in an\r
+    110           * PWM controller error being flagged and the program going into\r
+    111           * error-state and eventually reinitializing.\r
+    112           */\r
+    113          #pragma vector=ADC_vect\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    114          __interrupt void ADC_ISR(void)\r
+   \                     ADC_ISR:\r
+    115          {\r
+   \   00000000   925A               ST      -Y, R5\r
+   \   00000002   924A               ST      -Y, R4\r
+   \   00000004   93BA               ST      -Y, R27\r
+   \   00000006   93AA               ST      -Y, R26\r
+   \   00000008   939A               ST      -Y, R25\r
+   \   0000000A   938A               ST      -Y, R24\r
+   \   0000000C   93FA               ST      -Y, R31\r
+   \   0000000E   93EA               ST      -Y, R30\r
+   \   00000010   923A               ST      -Y, R3\r
+   \   00000012   922A               ST      -Y, R2\r
+   \   00000014   921A               ST      -Y, R1\r
+   \   00000016   920A               ST      -Y, R0\r
+   \   00000018   937A               ST      -Y, R23\r
+   \   0000001A   936A               ST      -Y, R22\r
+   \   0000001C   935A               ST      -Y, R21\r
+   \   0000001E   934A               ST      -Y, R20\r
+   \   00000020   933A               ST      -Y, R19\r
+   \   00000022   932A               ST      -Y, R18\r
+   \   00000024   931A               ST      -Y, R17\r
+   \   00000026   930A               ST      -Y, R16\r
+   \   00000028   B65F               IN      R5, 0x3F\r
+   \   0000002A                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   0000002A                      REQUIRE ?Register_R5_is_cg_reg\r
+    116                static unsigned char avgIndex = 0;\r
+    117                unsigned char i, Next, Signed;\r
+    118                signed int  temp = 0;\r
+   \   0000002A   E0A0               LDI     R26, 0\r
+   \   0000002C   E0B0               LDI     R27, 0\r
+    119                \r
+    120                Signed = FALSE;  // Presume next conversion is unipolar.\r
+   \   0000002E   2444               CLR     R4\r
+    121                ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
+   \   00000030   9837               CBI     0x06, 0x07\r
+    122                  // conversions take at least 25 ADCCLK. (It is restarted later)\r
+    123                \r
+    124                // Handle the conversion, depending on what channel it is from, then\r
+    125                // switch to the next channel in the sequence.\r
+    126                switch (ADCS.MUX){\r
+   \   00000032   9100....           LDS     R16, ADCS\r
+   \   00000036   710F               ANDI    R16, 0x1F\r
+   \   00000038   5001               SUBI    R16, 1\r
+   \   0000003A   F051               BREQ    ??ADC_ISR_0\r
+   \   0000003C   950A               DEC     R16\r
+   \   0000003E   F081               BREQ    ??ADC_ISR_1\r
+   \   00000040   950A               DEC     R16\r
+   \   00000042   F0B1               BREQ    ??ADC_ISR_2\r
+   \   00000044   5002               SUBI    R16, 2\r
+   \   00000046   F189               BREQ    ??ADC_ISR_3\r
+   \   00000048   5102               SUBI    R16, 18\r
+   \   0000004A   F409               BRNE    $+2+2\r
+   \   0000004C   C040               RJMP    ??ADC_ISR_4\r
+   \   0000004E   C0AF               RJMP    ??ADC_ISR_5\r
+    127                        // MUX = 0b000001 => ADC1 (PA1) = NTC\r
+    128                        case 0x01:\r
+    129                                ADCS.rawNTC = ADC;\r
+   \                     ??ADC_ISR_0:\r
+   \   00000050   B104               IN      R16, 0x04\r
+   \   00000052   B115               IN      R17, 0x05\r
+   \   00000054   ....               LDI     R30, LOW(ADCS)\r
+   \   00000056   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000058   8304               STD     Z+4, R16\r
+   \   0000005A   8315               STD     Z+5, R17\r
+    130                                Next=0x02;\r
+   \   0000005C   E092               LDI     R25, 2\r
+   \   0000005E   C0A8               RJMP    ??ADC_ISR_6\r
+    131                        break;\r
+    132          \r
+    133                        \r
+    134                        // MUX = 0b000010 => ADC2 (PA2) = RID\r
+    135                        case 0x02:\r
+    136                                ADCS.rawRID = ADC;\r
+   \                     ??ADC_ISR_1:\r
+   \   00000060   B104               IN      R16, 0x04\r
+   \   00000062   B115               IN      R17, 0x05\r
+   \   00000064   ....               LDI     R30, LOW(ADCS)\r
+   \   00000066   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000068   8302               STD     Z+2, R16\r
+   \   0000006A   8313               STD     Z+3, R17\r
+    137                                Next=0x03;\r
+   \   0000006C   E093               LDI     R25, 3\r
+   \   0000006E   C0A0               RJMP    ??ADC_ISR_6\r
+    138                        break;\r
+    139          \r
+    140                        \r
+    141                        // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
+    142                        case 0x03:\r
+    143                                // Supply voltage is always divided by 16.\r
+    144                                ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
+   \                     ??ADC_ISR_2:\r
+   \   00000070   B124               IN      R18, 0x04\r
+   \   00000072   B135               IN      R19, 0x05\r
+   \   00000074   E004               LDI     R16, 4\r
+   \   00000076   ....               RCALL   ScaleU\r
+   \   00000078   ....               LDI     R30, LOW(ADCS)\r
+   \   0000007A   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000007C   8700               STD     Z+8, R16\r
+   \   0000007E   8711               STD     Z+9, R17\r
+    145                                \r
+    146                                // Is mains failing?\r
+    147                                if (ADCS.VIN < VIN_MIN) {\r
+   \   00000080   ....               LDI     R30, LOW(ADCS)\r
+   \   00000082   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000084   8500               LDD     R16, Z+8\r
+   \   00000086   8511               LDD     R17, Z+9\r
+   \   00000088   3300               CPI     R16, 48\r
+   \   0000008A   E121               LDI     R18, 17\r
+   \   0000008C   0712               CPC     R17, R18\r
+   \   0000008E   F430               BRCC    ??ADC_ISR_7\r
+    148                                        ADCS.Mains = FALSE;\r
+   \   00000090   ....               LDI     R30, LOW(ADCS)\r
+   \   00000092   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000094   8100               LD      R16, Z\r
+   \   00000096   7B0F               ANDI    R16, 0xBF\r
+   \   00000098   8300               ST      Z, R16\r
+   \   0000009A   C005               RJMP    ??ADC_ISR_8\r
+    149                                } else {\r
+    150                                        ADCS.Mains = TRUE;\r
+   \                     ??ADC_ISR_7:\r
+   \   0000009C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000009E   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000A0   8100               LD      R16, Z\r
+   \   000000A2   6400               ORI     R16, 0x40\r
+   \   000000A4   8300               ST      Z, R16\r
+    151                                }\r
+    152                                \r
+    153                                Next=0x05;\r
+   \                     ??ADC_ISR_8:\r
+   \   000000A6   E095               LDI     R25, 5\r
+   \   000000A8   C083               RJMP    ??ADC_ISR_6\r
+    154                        break;\r
+    155          \r
+    156                        \r
+    157                        // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
+    158                        case 0x05:\r
+    159                                ADCS.rawVBAT = ADC;\r
+   \                     ??ADC_ISR_3:\r
+   \   000000AA   B104               IN      R16, 0x04\r
+   \   000000AC   B115               IN      R17, 0x05\r
+   \   000000AE   ....               LDI     R30, LOW(ADCS)\r
+   \   000000B0   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000B2   8306               STD     Z+6, R16\r
+   \   000000B4   8317               STD     Z+7, R17\r
+    160                                \r
+    161                                // Scale voltage according to jumper setting.\r
+    162                                ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
+   \   000000B6   B124               IN      R18, 0x04\r
+   \   000000B8   B135               IN      R19, 0x05\r
+   \   000000BA   ....               LDI     R20, LOW(VBAT_RANGE)\r
+   \   000000BC   ....               LDI     R21, (VBAT_RANGE) >> 8\r
+   \   000000BE   ....               RCALL   __eeget8_16\r
+   \   000000C0   ....               RCALL   ScaleU\r
+   \   000000C2   ....               LDI     R30, LOW(ADCS)\r
+   \   000000C4   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000C6   8702               STD     Z+10, R16\r
+   \   000000C8   8713               STD     Z+11, R17\r
+    163                                Next=0x17;\r
+   \   000000CA   E197               LDI     R25, 23\r
+   \   000000CC   C071               RJMP    ??ADC_ISR_6\r
+    164          //                    Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
+    165                        break;\r
+    166          \r
+    167          \r
+    168                        case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
+    169                                // If bipolar, from -512 to 0, to 511:\r
+    170                                // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
+    171                        \r
+    172                                // Scale sample according to jumper setting, handle negative numbers.\r
+    173                                if (ADC > 511) {\r
+   \                     ??ADC_ISR_4:\r
+   \   000000CE   B104               IN      R16, 0x04\r
+   \   000000D0   B115               IN      R17, 0x05\r
+   \   000000D2   3000               CPI     R16, 0\r
+   \   000000D4   E022               LDI     R18, 2\r
+   \   000000D6   0712               CPC     R17, R18\r
+   \   000000D8   F0C8               BRCS    ??ADC_ISR_9\r
+    174                                        ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
+    175                                                     (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+   \   000000DA   E000               LDI     R16, 0\r
+   \   000000DC   E014               LDI     R17, 4\r
+   \   000000DE   B124               IN      R18, 0x04\r
+   \   000000E0   B135               IN      R19, 0x05\r
+   \   000000E2   1B02               SUB     R16, R18\r
+   \   000000E4   0B13               SBC     R17, R19\r
+   \   000000E6   9120....           LDS     R18, (ADCS + 1)\r
+   \   000000EA   9522               SWAP    R18\r
+   \   000000EC   702F               ANDI    R18, 0x0F\r
+   \   000000EE   E030               LDI     R19, 0\r
+   \   000000F0   0F20               ADD     R18, R16\r
+   \   000000F2   1F31               ADC     R19, R17\r
+   \   000000F4   ....               LDI     R20, LOW(VBAT_RANGE)\r
+   \   000000F6   ....               LDI     R21, (VBAT_RANGE) >> 8\r
+   \   000000F8   ....               RCALL   __eeget8_16\r
+   \   000000FA   ....               RCALL   ScaleI\r
+   \   000000FC   9511               NEG     R17\r
+   \   000000FE   9501               NEG     R16\r
+   \   00000100   4010               SBCI    R17, 0\r
+   \   00000102   ....               LDI     R30, LOW(ADCS)\r
+   \   00000104   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000106   8704               STD     Z+12, R16\r
+   \   00000108   8715               STD     Z+13, R17\r
+   \   0000010A   C01C               RJMP    ??ADC_ISR_10\r
+    176                                } else if (ADC > 0) {\r
+   \                     ??ADC_ISR_9:\r
+   \   0000010C   B104               IN      R16, 0x04\r
+   \   0000010E   B115               IN      R17, 0x05\r
+   \   00000110   2B01               OR      R16, R17\r
+   \   00000112   F091               BREQ    ??ADC_ISR_11\r
+    177                                        ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
+   \   00000114   B124               IN      R18, 0x04\r
+   \   00000116   B135               IN      R19, 0x05\r
+   \   00000118   9100....           LDS     R16, (ADCS + 1)\r
+   \   0000011C   9502               SWAP    R16\r
+   \   0000011E   700F               ANDI    R16, 0x0F\r
+   \   00000120   E010               LDI     R17, 0\r
+   \   00000122   1B20               SUB     R18, R16\r
+   \   00000124   0B31               SBC     R19, R17\r
+   \   00000126   ....               LDI     R20, LOW(VBAT_RANGE)\r
+   \   00000128   ....               LDI     R21, (VBAT_RANGE) >> 8\r
+   \   0000012A   ....               RCALL   __eeget8_16\r
+   \   0000012C   ....               RCALL   ScaleI\r
+   \   0000012E   ....               LDI     R30, LOW(ADCS)\r
+   \   00000130   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000132   8704               STD     Z+12, R16\r
+   \   00000134   8715               STD     Z+13, R17\r
+   \   00000136   C006               RJMP    ??ADC_ISR_10\r
+    178                                } else {\r
+    179                                        ADCS.IBAT = 0;\r
+   \                     ??ADC_ISR_11:\r
+   \   00000138   E000               LDI     R16, 0\r
+   \   0000013A   E010               LDI     R17, 0\r
+   \   0000013C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000013E   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000140   8704               STD     Z+12, R16\r
+   \   00000142   8715               STD     Z+13, R17\r
+    180                                }\r
+    181          \r
+    182                                // Insert sample of battery current into the averaging-array\r
+    183                                // (overwriting the oldest sample), then recalculate and store the\r
+    184                                // average. This is the last conversion in the sequence, so\r
+    185                                // flag a complete ADC-cycle and restart sequence.\r
+    186                                ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
+   \                     ??ADC_ISR_10:\r
+   \   00000144   ....               LDI     R30, LOW(ADCS)\r
+   \   00000146   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000148   8524               LDD     R18, Z+12\r
+   \   0000014A   8535               LDD     R19, Z+13\r
+   \   0000014C   9100....           LDS     R16, ??avgIndex\r
+   \   00000150   E010               LDI     R17, 0\r
+   \   00000152   7003               ANDI    R16, 0x03\r
+   \   00000154   7010               ANDI    R17, 0x00\r
+   \   00000156   0F00               LSL     R16\r
+   \   00000158   1F11               ROL     R17\r
+   \   0000015A   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000015C   ....               SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+   \   0000015E   ....               SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+   \   00000160   8726               STD     Z+14, R18\r
+   \   00000162   8737               STD     Z+15, R19\r
+   \   00000164   ....               LDI     R30, LOW(??avgIndex)\r
+   \   00000166   ....               LDI     R31, (??avgIndex) >> 8\r
+   \   00000168   8100               LD      R16, Z\r
+   \   0000016A   9503               INC     R16\r
+   \   0000016C   8300               ST      Z, R16\r
+    187                                for (i = 0; i < 4 ; i++) {\r
+   \   0000016E   E080               LDI     R24, 0\r
+   \                     ??ADC_ISR_12:\r
+   \   00000170   3084               CPI     R24, 4\r
+   \   00000172   F468               BRCC    ??ADC_ISR_13\r
+    188                                        temp += ADCS.discIBAT[i];\r
+   \   00000174   2F08               MOV     R16, R24\r
+   \   00000176   E010               LDI     R17, 0\r
+   \   00000178   0F00               LSL     R16\r
+   \   0000017A   1F11               ROL     R17\r
+   \   0000017C   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000017E   ....               SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+   \   00000180   ....               SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+   \   00000182   8506               LDD     R16, Z+14\r
+   \   00000184   8517               LDD     R17, Z+15\r
+   \   00000186   0FA0               ADD     R26, R16\r
+   \   00000188   1FB1               ADC     R27, R17\r
+    189                                }\r
+   \   0000018A   9583               INC     R24\r
+   \   0000018C   CFF1               RJMP    ??ADC_ISR_12\r
+    190                                \r
+    191                                ADCS.avgIBAT = (temp / 4);\r
+   \                     ??ADC_ISR_13:\r
+   \   0000018E   018D               MOVW    R17:R16, R27:R26\r
+   \   00000190   E044               LDI     R20, 4\r
+   \   00000192   E050               LDI     R21, 0\r
+   \   00000194   ....               RCALL   ?SS_DIVMOD_L02\r
+   \   00000196   ....               LDI     R30, LOW(ADCS)\r
+   \   00000198   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000019A   8B06               STD     Z+22, R16\r
+   \   0000019C   8B17               STD     Z+23, R17\r
+    192                                \r
+    193                                ADCS.Flag = TRUE;\r
+   \   0000019E   ....               LDI     R30, LOW(ADCS)\r
+   \   000001A0   ....               LDI     R31, (ADCS) >> 8\r
+   \   000001A2   8100               LD      R16, Z\r
+   \   000001A4   6200               ORI     R16, 0x20\r
+   \   000001A6   8300               ST      Z, R16\r
+    194                                Next=0x01;\r
+   \   000001A8   E091               LDI     R25, 1\r
+    195                                Signed = FALSE;  // This is the only bipolar conversion.\r
+   \   000001AA   2444               CLR     R4\r
+   \   000001AC   C001               RJMP    ??ADC_ISR_6\r
+    196                        break;\r
+    197          \r
+    198                        \r
+    199                        default:  // Should not happen. (Invalid MUX-channel)\r
+    200                                Next=0x01;  // Start at the beginning of sequence.\r
+   \                     ??ADC_ISR_5:\r
+   \   000001AE   E091               LDI     R25, 1\r
+    201                        break;\r
+    202                }\r
+    203                \r
+    204                // Update MUX to next channel in sequence, set a bipolar conversion if\r
+    205                // this has been flagged.\r
+    206                ADCS.MUX = Next;                    \r
+   \                     ??ADC_ISR_6:\r
+   \   000001B0   9110....           LDS     R17, ADCS\r
+   \   000001B4   7E10               ANDI    R17, 0xE0\r
+   \   000001B6   2F09               MOV     R16, R25\r
+   \   000001B8   710F               ANDI    R16, 0x1F\r
+   \   000001BA   2B01               OR      R16, R17\r
+   \   000001BC   9300....           STS     ADCS, R16\r
+    207                ADMUX = (1<<REFS0) + ADCS.MUX;      \r
+   \   000001C0   9100....           LDS     R16, ADCS\r
+   \   000001C4   710F               ANDI    R16, 0x1F\r
+   \   000001C6   5C00               SUBI    R16, 192\r
+   \   000001C8   B907               OUT     0x07, R16\r
+    208          \r
+    209                if (Signed)     {\r
+   \   000001CA   2044               TST     R4\r
+   \   000001CC   F011               BREQ    ??ADC_ISR_14\r
+    210                  ADCSRB |= (1<<BIN);               \r
+   \   000001CE   9A1F               SBI     0x03, 0x07\r
+   \   000001D0   C001               RJMP    ??ADC_ISR_15\r
+    211                } else {\r
+    212                  ADCSRB &= ~(1<<BIN);              \r
+   \                     ??ADC_ISR_14:\r
+   \   000001D2   981F               CBI     0x03, 0x07\r
+    213                }\r
+    214          \r
+    215                // Re-enable the ADC unless a halt has been flagged and a conversion\r
+    216                // cycle has completed.\r
+    217                if (!((ADCS.Halt) && (ADCS.Flag))) {\r
+   \                     ??ADC_ISR_15:\r
+   \   000001D4   9100....           LDS     R16, ADCS\r
+   \   000001D8   7A00               ANDI    R16, 0xA0\r
+   \   000001DA   3A00               CPI     R16, 160\r
+   \   000001DC   F019               BREQ    ??ADC_ISR_16\r
+    218                  ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
+   \   000001DE   B106               IN      R16, 0x06\r
+   \   000001E0   6C00               ORI     R16, 0xC0\r
+   \   000001E2   B906               OUT     0x06, R16\r
+    219                }\r
+    220          }\r
+   \                     ??ADC_ISR_16:\r
+   \   000001E4   BE5F               OUT     0x3F, R5\r
+   \   000001E6   9109               LD      R16, Y+\r
+   \   000001E8   9119               LD      R17, Y+\r
+   \   000001EA   9129               LD      R18, Y+\r
+   \   000001EC   9139               LD      R19, Y+\r
+   \   000001EE   9149               LD      R20, Y+\r
+   \   000001F0   9159               LD      R21, Y+\r
+   \   000001F2   9169               LD      R22, Y+\r
+   \   000001F4   9179               LD      R23, Y+\r
+   \   000001F6   9009               LD      R0, Y+\r
+   \   000001F8   9019               LD      R1, Y+\r
+   \   000001FA   9029               LD      R2, Y+\r
+   \   000001FC   9039               LD      R3, Y+\r
+   \   000001FE   91E9               LD      R30, Y+\r
+   \   00000200   91F9               LD      R31, Y+\r
+   \   00000202   9189               LD      R24, Y+\r
+   \   00000204   9199               LD      R25, Y+\r
+   \   00000206   91A9               LD      R26, Y+\r
+   \   00000208   91B9               LD      R27, Y+\r
+   \   0000020A   9049               LD      R4, Y+\r
+   \   0000020C   9059               LD      R5, Y+\r
+   \   0000020E   9518               RETI\r
+   \   00000210                      REQUIRE _A_ADMUX\r
+   \   00000210                      REQUIRE _A_ADCSRA\r
+   \   00000210                      REQUIRE _A_ADC\r
+   \   00000210                      REQUIRE _A_ADCSRB\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+   \                     ??avgIndex:\r
+   \   00000000                      DS 1\r
+    221          \r
+    222          \r
+    223          /*! \brief Scales sample to represent "actual voltage" in mV.\r
+    224           *\r
+    225           * This function returns the actual sampled voltage, scaled according\r
+    226           * to the jumper settings.\r
+    227           *\r
+    228           * \param setting Indicates what downscaling was used.\r
+    229           * \param data The sampled value.\r
+    230           *\r
+    231           * \note Table for setting-parameter:\n\r
+    232           * <pre>\r
+    233           * Presume VREF = 2.5V and Gain = 1x.\r
+    234           * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
+    235           * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
+    236           * --------+--------+------+------------+-----------+-------\r
+    237           *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
+    238           *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
+    239           *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
+    240           *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
+    241           *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
+    242           *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
+    243           *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
+    244           * </pre>\r
+    245           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    246          unsigned int ScaleU(unsigned char setting, unsigned int data)\r
+   \                     ScaleU:\r
+    247          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE6_L09\r
+   \   00000002                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000002   2FA0               MOV     R26, R16\r
+   \   00000004   01C9               MOVW    R25:R24, R19:R18\r
+    248                // Temporary variable needed.\r
+    249                unsigned int scaled = 0;\r
+   \   00000006   2444               CLR     R4\r
+   \   00000008   2455               CLR     R5\r
+    250          \r
+    251                // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
+    252                if (setting == 3)       {\r
+   \   0000000A   30A3               CPI     R26, 3\r
+   \   0000000C   F491               BRNE    ??ScaleU_0\r
+    253                        scaled = 29 * data;\r
+   \   0000000E   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000010   E10D               LDI     R16, 29\r
+   \   00000012   E010               LDI     R17, 0\r
+   \   00000014   ....               RCALL   ?S_MUL_L02\r
+   \   00000016   0128               MOVW    R5:R4, R17:R16\r
+    254                        scaled += (data >> 2);\r
+   \   00000018   018C               MOVW    R17:R16, R25:R24\r
+   \   0000001A   9516               LSR     R17\r
+   \   0000001C   9507               ROR     R16\r
+   \   0000001E   9516               LSR     R17\r
+   \   00000020   9507               ROR     R16\r
+   \   00000022   0E40               ADD     R4, R16\r
+   \   00000024   1E51               ADC     R5, R17\r
+    255                        scaled += (data >> 4);\r
+   \   00000026   018C               MOVW    R17:R16, R25:R24\r
+   \   00000028   E044               LDI     R20, 4\r
+   \   0000002A   ....               RCALL   ?US_SHR_L02\r
+   \   0000002C   0E40               ADD     R4, R16\r
+   \   0000002E   1E51               ADC     R5, R17\r
+   \   00000030   C011               RJMP    ??ScaleU_1\r
+    256                } else {\r
+    257                        // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
+    258                        scaled = 39 * data;\r
+   \                     ??ScaleU_0:\r
+   \   00000032   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000034   E207               LDI     R16, 39\r
+   \   00000036   E010               LDI     R17, 0\r
+   \   00000038   ....               RCALL   ?S_MUL_L02\r
+   \   0000003A   0128               MOVW    R5:R4, R17:R16\r
+    259                        scaled += (data >> 4);\r
+   \   0000003C   018C               MOVW    R17:R16, R25:R24\r
+   \   0000003E   E044               LDI     R20, 4\r
+   \   00000040   ....               RCALL   ?US_SHR_L02\r
+   \   00000042   0E40               ADD     R4, R16\r
+   \   00000044   1E51               ADC     R5, R17\r
+    260                        \r
+    261                        if (setting <3) {\r
+   \   00000046   30A3               CPI     R26, 3\r
+   \   00000048   F428               BRCC    ??ScaleU_1\r
+    262                                // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
+    263                                //                1: mV/LSB = 9.766 = 39.06 / 4\r
+    264                                //                2: mV/LSB = 19.53 = 39.06 / 2\r
+    265                                scaled = (scaled >> (3-setting));\r
+   \   0000004A   0182               MOVW    R17:R16, R5:R4\r
+   \   0000004C   E043               LDI     R20, 3\r
+   \   0000004E   1B4A               SUB     R20, R26\r
+   \   00000050   ....               RCALL   ?US_SHR_L02\r
+   \   00000052   0128               MOVW    R5:R4, R17:R16\r
+    266                        }\r
+    267                }\r
+    268          \r
+    269                return(scaled);\r
+   \                     ??ScaleU_1:\r
+   \   00000054   0182               MOVW    R17:R16, R5:R4\r
+   \   00000056   E0E6               LDI     R30, 6\r
+   \   00000058   ....               RJMP    ?EPILOGUE_B6_L09\r
+    270          }\r
+    271          \r
+    272          \r
+    273          /*! \brief Scales sample to represent "actual current" in mA.\r
+    274           *\r
+    275           * This function returns the actual sampled current, scaled according\r
+    276           * to the jumper settings.\r
+    277           *\r
+    278           * \param setting Indicates what downscaling was used.\r
+    279           * \param data The sampled value.\r
+    280           *\r
+    281           * \note Table for setting-parameter:\n\r
+    282           * <pre>\r
+    283           * Presume VREF = 2.5V and Gain = 1x or 20x.\r
+    284           * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
+    285           * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
+    286           * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
+    287           * --------+------+------------+----------+----------+--------+-----\r
+    288           *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
+    289           *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
+    290           *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
+    291           *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
+    292           *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
+    293           *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
+    294           *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
+    295           * </pre>\r
+    296           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    297          unsigned int ScaleI(unsigned char setting, unsigned int data)\r
+   \                     ScaleI:\r
+    298          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE6_L09\r
+   \   00000002                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000002   2FA0               MOV     R26, R16\r
+   \   00000004   01C9               MOVW    R25:R24, R19:R18\r
+    299                // Temporary variable needed.\r
+    300                unsigned int  scaled = 0;\r
+   \   00000006   2444               CLR     R4\r
+   \   00000008   2455               CLR     R5\r
+    301                \r
+    302                // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
+    303                if (setting == 3) {\r
+   \   0000000A   30A3               CPI     R26, 3\r
+   \   0000000C   F499               BRNE    ??ScaleI_0\r
+    304                        scaled = 21 * data;\r
+   \   0000000E   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000010   E105               LDI     R16, 21\r
+   \   00000012   E010               LDI     R17, 0\r
+   \   00000014   ....               RCALL   ?S_MUL_L02\r
+   \   00000016   0128               MOVW    R5:R4, R17:R16\r
+    305                        scaled -= (data >> 4);\r
+   \   00000018   018C               MOVW    R17:R16, R25:R24\r
+   \   0000001A   E044               LDI     R20, 4\r
+   \   0000001C   ....               RCALL   ?US_SHR_L02\r
+   \   0000001E   1A40               SUB     R4, R16\r
+   \   00000020   0A51               SBC     R5, R17\r
+    306                        scaled += (data >> 7);\r
+   \   00000022   018C               MOVW    R17:R16, R25:R24\r
+   \   00000024   0F00               LSL     R16\r
+   \   00000026   2F01               MOV     R16, R17\r
+   \   00000028   1F00               ROL     R16\r
+   \   0000002A   E010               LDI     R17, 0\r
+   \   0000002C   1F11               ROL     R17\r
+   \   0000002E   0E40               ADD     R4, R16\r
+   \   00000030   1E51               ADC     R5, R17\r
+   \   00000032   C016               RJMP    ??ScaleI_1\r
+    307                }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
+    308                        scaled = 28 * data;\r
+   \                     ??ScaleI_0:\r
+   \   00000034   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000036   E10C               LDI     R16, 28\r
+   \   00000038   E010               LDI     R17, 0\r
+   \   0000003A   ....               RCALL   ?S_MUL_L02\r
+   \   0000003C   0128               MOVW    R5:R4, R17:R16\r
+    309                        scaled -= (data >> 3);\r
+   \   0000003E   018C               MOVW    R17:R16, R25:R24\r
+   \   00000040   E043               LDI     R20, 3\r
+   \   00000042   ....               RCALL   ?US_SHR_L02\r
+   \   00000044   1A40               SUB     R4, R16\r
+   \   00000046   0A51               SBC     R5, R17\r
+    310                        scaled += (data >> 5);\r
+   \   00000048   018C               MOVW    R17:R16, R25:R24\r
+   \   0000004A   E045               LDI     R20, 5\r
+   \   0000004C   ....               RCALL   ?US_SHR_L02\r
+   \   0000004E   0E40               ADD     R4, R16\r
+   \   00000050   1E51               ADC     R5, R17\r
+    311                        \r
+    312                        if (setting <3) {\r
+   \   00000052   30A3               CPI     R26, 3\r
+   \   00000054   F428               BRCC    ??ScaleI_1\r
+    313                                // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
+    314                                //                1: mA/LSB = 6.978mA = 27.909 / 4\r
+    315                                //                2: mA/LSB = 13.955mA = 27.909 / 2\r
+    316                                scaled = (scaled >> (3-setting));\r
+   \   00000056   0182               MOVW    R17:R16, R5:R4\r
+   \   00000058   E043               LDI     R20, 3\r
+   \   0000005A   1B4A               SUB     R20, R26\r
+   \   0000005C   ....               RCALL   ?US_SHR_L02\r
+   \   0000005E   0128               MOVW    R5:R4, R17:R16\r
+    317                        }\r
+    318                }\r
+    319                \r
+    320                return(scaled);\r
+   \                     ??ScaleI_1:\r
+   \   00000060   0182               MOVW    R17:R16, R5:R4\r
+   \   00000062   E0E6               LDI     R30, 6\r
+   \   00000064   ....               RJMP    ?EPILOGUE_B6_L09\r
+    321          }\r
+    322          \r
+    323          \r
+    324          /*! \brief Waits for two full cycles of ADC-conversions to occur.\r
+    325           *\r
+    326           * This function clears the cycle complete-flag, then waits for it to be set\r
+    327           * again. This is then repeated once before the function exits.\r
+    328           * \r
+    329           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    330          void ADC_Wait(void)\r
+   \                     ADC_Wait:\r
+    331          {\r
+    332                // Clear ADC flag and wait for cycle to complete.\r
+    333                ADCS.Flag = FALSE;              \r
+   \   00000000   ....               LDI     R30, LOW(ADCS)\r
+   \   00000002   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000004   8100               LD      R16, Z\r
+   \   00000006   7D0F               ANDI    R16, 0xDF\r
+   \   00000008   8300               ST      Z, R16\r
+    334                do {\r
+    335                } while (ADCS.Flag == FALSE);      \r
+   \                     ??ADC_Wait_0:\r
+   \   0000000A   ....               LDI     R30, LOW(ADCS)\r
+   \   0000000C   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000000E   8100               LD      R16, Z\r
+   \   00000010   FF05               SBRS    R16, 5\r
+   \   00000012   CFFB               RJMP    ??ADC_Wait_0\r
+    336                \r
+    337                // Repeat, so we are sure the data beong to the same cycle.\r
+    338                ADCS.Flag = FALSE;              \r
+   \   00000014   ....               LDI     R30, LOW(ADCS)\r
+   \   00000016   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000018   8100               LD      R16, Z\r
+   \   0000001A   7D0F               ANDI    R16, 0xDF\r
+   \   0000001C   8300               ST      Z, R16\r
+    339                do {\r
+    340                } while (ADCS.Flag == FALSE);      \r
+   \                     ??ADC_Wait_1:\r
+   \   0000001E   ....               LDI     R30, LOW(ADCS)\r
+   \   00000020   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000022   8100               LD      R16, Z\r
+   \   00000024   FF05               SBRS    R16, 5\r
+   \   00000026   CFFB               RJMP    ??ADC_Wait_1\r
+    341          }\r
+   \   00000028   9508               RET\r
+    342          \r
+    343          \r
+    344          /*! \brief Initializes ADC and input pins.\r
+    345           *\r
+    346           * This function initializes the ADC to free running mode, sampling from\r
+    347           * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
+    348           * It also measures and stores calibration data for offset.\r
+    349           *\r
+    350           * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
+    351           *\r
+    352           * \note Table of MUX settings for offset measurement:\r
+    353           * <pre>\r
+    354           *    Ch | Pin |    Gain |    MUX\r
+    355           * ------+-----+---------+-------\r
+    356           *  ADC1 | PA1 |     20x | 001101\r
+    357           *  ADC3 | PA4 |     20x | 010001\r
+    358           *  ADC5 | PA6 |     20x | 010110\r
+    359           *  ADC9 | PB6 |     20x | 011011\r
+    360           *  ADC0 | PA0 | 20x/32x | 111000\r
+    361           *  ADC0 | PA0 |   1x/8x | 111001\r
+    362           *  ADC1 | PA1 | 20x/32x | 111010\r
+    363           *  ADC2 | PA2 | 20x/32x | 111011\r
+    364           *  ADC4 | PA5 | 20x/32x | 111100\r
+    365           *  ADC5 | PA6 | 20x/32x | 111101\r
+    366           *  ADC6 | PA7 | 20x/32x | 111110\r
+    367           * </pre>\r
+    368           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    369          void ADC_Init(void)\r
+   \                     ADC_Init:\r
+    370          {\r
+   \   00000000   938A               ST      -Y, R24\r
+    371                unsigned char i;\r
+    372          \r
+    373                __disable_interrupt();\r
+   \   00000002   94F8               CLI\r
+    374          \r
+    375                ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
+   \   00000004   ....               LDI     R30, LOW(ADCS)\r
+   \   00000006   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000008   8100               LD      R16, Z\r
+   \   0000000A   770F               ANDI    R16, 0x7F\r
+   \   0000000C   8300               ST      Z, R16\r
+    376          \r
+    377                // Configure ADC pins (inputs and disabled pull-ups).\r
+    378                DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+   \   0000000E   B30A               IN      R16, 0x1A\r
+   \   00000010   7009               ANDI    R16, 0x09\r
+   \   00000012   BB0A               OUT     0x1A, R16\r
+    379                PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+   \   00000014   B30B               IN      R16, 0x1B\r
+   \   00000016   7009               ANDI    R16, 0x09\r
+   \   00000018   BB0B               OUT     0x1B, R16\r
+    380          \r
+    381                // Set ADC3 as reference, and MUX to measure the same pin.\r
+    382                ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
+   \   0000001A   E403               LDI     R16, 67\r
+   \   0000001C   B907               OUT     0x07, R16\r
+    383                \r
+    384                ADCSRB = 0;\r
+   \   0000001E   E000               LDI     R16, 0\r
+   \   00000020   B903               OUT     0x03, R16\r
+    385          \r
+    386                // Start conversion, no interrupt (disable ADC-ISR).\r
+    387                ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+   \   00000022   EC07               LDI     R16, 199\r
+   \   00000024   B906               OUT     0x06, R16\r
+    388          \r
+    389                do { // Wait for conversion to finish.\r
+    390                } while (!(ADCSRA & (1<<ADIF)));\r
+   \                     ??ADC_Init_0:\r
+   \   00000026   9B34               SBIS    0x06, 0x04\r
+   \   00000028   CFFE               RJMP    ??ADC_Init_0\r
+    391          \r
+    392                ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
+   \   0000002A   9A34               SBI     0x06, 0x04\r
+    393          \r
+    394                ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
+   \   0000002C   9120....           LDS     R18, (ADCS + 1)\r
+   \   00000030   7F20               ANDI    R18, 0xF0\r
+   \   00000032   B104               IN      R16, 0x04\r
+   \   00000034   B115               IN      R17, 0x05\r
+   \   00000036   700F               ANDI    R16, 0x0F\r
+   \   00000038   2B02               OR      R16, R18\r
+   \   0000003A   9300....           STS     (ADCS + 1), R16\r
+    395          \r
+    396                ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
+   \   0000003E   E506               LDI     R16, 86\r
+   \   00000040   B907               OUT     0x07, R16\r
+    397                \r
+    398                // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
+    399                ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+   \   00000042   EC07               LDI     R16, 199\r
+   \   00000044   B906               OUT     0x06, R16\r
+    400          \r
+    401                do { // Wait for conversion to finish.\r
+    402                } while (!(ADCSRA & (1<<ADIF)));\r
+   \                     ??ADC_Init_1:\r
+   \   00000046   9B34               SBIS    0x06, 0x04\r
+   \   00000048   CFFE               RJMP    ??ADC_Init_1\r
+    403          \r
+    404                ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
+   \   0000004A   9A34               SBI     0x06, 0x04\r
+    405          \r
+    406                ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
+   \   0000004C   9120....           LDS     R18, (ADCS + 1)\r
+   \   00000050   702F               ANDI    R18, 0x0F\r
+   \   00000052   B104               IN      R16, 0x04\r
+   \   00000054   B115               IN      R17, 0x05\r
+   \   00000056   9502               SWAP    R16\r
+   \   00000058   7F00               ANDI    R16, 0xF0\r
+   \   0000005A   2B02               OR      R16, R18\r
+   \   0000005C   9300....           STS     (ADCS + 1), R16\r
+    407          \r
+    408                // Reset the ADC-cycle.\r
+    409                ADCS.Flag = FALSE;      \r
+   \   00000060   ....               LDI     R30, LOW(ADCS)\r
+   \   00000062   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000064   8100               LD      R16, Z\r
+   \   00000066   7D0F               ANDI    R16, 0xDF\r
+   \   00000068   8300               ST      Z, R16\r
+    410                ADCS.MUX = 0x01;                    \r
+   \   0000006A   9100....           LDS     R16, ADCS\r
+   \   0000006E   7E00               ANDI    R16, 0xE0\r
+   \   00000070   6001               ORI     R16, 0x01\r
+   \   00000072   9300....           STS     ADCS, R16\r
+    411                ADMUX = (1<<REFS0) | ADCS.MUX;      \r
+   \   00000076   9100....           LDS     R16, ADCS\r
+   \   0000007A   710F               ANDI    R16, 0x1F\r
+   \   0000007C   6400               ORI     R16, 0x40\r
+   \   0000007E   B907               OUT     0x07, R16\r
+    412          \r
+    413                // Clear averaged battery current and the discrete readings.\r
+    414                ADCS.avgIBAT = 0;\r
+   \   00000080   E000               LDI     R16, 0\r
+   \   00000082   E010               LDI     R17, 0\r
+   \   00000084   ....               LDI     R30, LOW(ADCS)\r
+   \   00000086   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000088   8B06               STD     Z+22, R16\r
+   \   0000008A   8B17               STD     Z+23, R17\r
+    415                \r
+    416                for (i = 0; i < 4; i++) {\r
+   \   0000008C   E080               LDI     R24, 0\r
+   \                     ??ADC_Init_2:\r
+   \   0000008E   3084               CPI     R24, 4\r
+   \   00000090   F468               BRCC    ??ADC_Init_3\r
+    417                        ADCS.discIBAT[i] = 0;             \r
+   \   00000092   E000               LDI     R16, 0\r
+   \   00000094   E010               LDI     R17, 0\r
+   \   00000096   2F28               MOV     R18, R24\r
+   \   00000098   E030               LDI     R19, 0\r
+   \   0000009A   0F22               LSL     R18\r
+   \   0000009C   1F33               ROL     R19\r
+   \   0000009E   01F9               MOVW    R31:R30, R19:R18\r
+   \   000000A0   ....               SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+   \   000000A2   ....               SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+   \   000000A4   8706               STD     Z+14, R16\r
+   \   000000A6   8717               STD     Z+15, R17\r
+    418                }\r
+   \   000000A8   9583               INC     R24\r
+   \   000000AA   CFF1               RJMP    ??ADC_Init_2\r
+    419                \r
+    420                // Re-enable the ADC and ISR.\r
+    421                ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
+   \                     ??ADC_Init_3:\r
+   \   000000AC   EC0F               LDI     R16, 207\r
+   \   000000AE   B906               OUT     0x06, R16\r
+    422                \r
+    423                __enable_interrupt();\r
+   \   000000B0   9478               SEI\r
+    424          \r
+    425                // Get a complete cycle of data before returning.\r
+    426                ADC_Wait();\r
+   \   000000B2   ....               RCALL   ADC_Wait\r
+    427          }\r
+   \   000000B4   9189               LD      R24, Y+\r
+   \   000000B6   9508               RET\r
+   \   000000B8                      REQUIRE _A_PORTA\r
+   \   000000B8                      REQUIRE _A_DDRA\r
+   \   000000B8                      REQUIRE _A_ADMUX\r
+   \   000000B8                      REQUIRE _A_ADCSRA\r
+   \   000000B8                      REQUIRE _A_ADC\r
+   \   000000B8                      REQUIRE _A_ADCSRB\r
+\r
+   \                                 In  segment INTVEC, offset 0x16, root\r
+   \                     `??ADC_ISR??INTVEC 22`:\r
+   \   00000016   ....               RJMP    ADC_ISR\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function      CSTACK RSTACK\r
+     --------      ------ ------\r
+     ADC_ISR          20      4\r
+       -> ScaleU      20      2\r
+       -> ScaleU      20      2\r
+       -> ScaleI      20      2\r
+       -> ScaleI      20      2\r
+     ADC_Init          1      2\r
+       -> ADC_Wait     1      2\r
+     ADC_Wait          0      2\r
+     ScaleI            6      4\r
+     ScaleU            6      4\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label       Bytes\r
+     --------------       -----\r
+     _A_PORTA                1\r
+     _A_DDRA                 1\r
+     _A_ADMUX                1\r
+     _A_ADCSRA               1\r
+     _A_ADC                  2\r
+     _A_ADCSRB               1\r
+     ADCS                   24\r
+     VBAT_RANGE              1\r
+     ADC_ISR               528\r
+     avgIndex                1\r
+     ScaleU                 90\r
+     ScaleI                102\r
+     ADC_Wait               42\r
+     ADC_Init              184\r
+     ??ADC_ISR??INTVEC 22    2\r
+      Others                 6\r
+\r
\r
+   7 bytes in segment ABSOLUTE\r
+ 946 bytes in segment CODE\r
+   1 byte  in segment EEPROM_I\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment INTVEC\r
+  25 bytes in segment NEAR_Z\r
\r
+ 946 bytes of CODE  memory (+ 8 bytes shared)\r
+  25 bytes of DATA  memory (+ 7 bytes shared)\r
+   1 byte  of XDATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/ADC.s90 b/BaseTinyFirmware/IAR/Debug/List/ADC.s90
new file mode 100644 (file)
index 0000000..6255bf4
--- /dev/null
@@ -0,0 +1,1089 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:38 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c               /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c               /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ADC.s90  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME `ADC`\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B6_L09\r
+        EXTERN ?PROLOGUE6_L09\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?SS_DIVMOD_L02\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?US_SHR_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBWEAK `??ADC_ISR??INTVEC 22`\r
+        PUBLIC ADCS\r
+        PUBLIC ADC_ISR\r
+        PUBLIC ADC_Init\r
+        PUBLIC ADC_Wait\r
+        PUBLIC ScaleI\r
+        PUBLIC ScaleU\r
+        PUBLIC VBAT_RANGE\r
+        PUBWEAK _A_ADC\r
+        PUBWEAK _A_ADCSRA\r
+        PUBWEAK _A_ADCSRB\r
+        PUBWEAK _A_ADMUX\r
+        PUBWEAK _A_DDRA\r
+        PUBWEAK _A_PORTA\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+ADC_ISR             SYMBOL "ADC_ISR"\r
+`??ADC_ISR??INTVEC 22` SYMBOL "??INTVEC 22", ADC_ISR\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for use of ADC\r
+//    6  *\r
+//    7  *      Contains high level functions for initializing the ADC, interrupt\r
+//    8  *      handling, and treatment of samples.\n\r
+//    9  *      The ADC is set to free running mode and uses an external reference\r
+//   10  *      voltage.\n\r
+//   11  *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
+//   12  *      and restarted by the ISR.\r
+//   13  *\r
+//   14  * \par Application note:\r
+//   15  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   16  *      AVR463: Charging NiMH Batteries with BC100\r
+//   17  *\r
+//   18  * \par Documentation:\r
+//   19  *      For comprehensive code documentation, supported compilers, compiler\r
+//   20  *      settings and supported devices see readme.html\r
+//   21  *\r
+//   22  * \author\r
+//   23  *      Atmel Corporation: http://www.atmel.com \n\r
+//   24  *      Support email: avr@atmel.com \n\r
+//   25  *      Original author: \n\r
+//   26  *\r
+//   27  * $Name$\r
+//   28  * $Revision: 2299 $\r
+//   29  * $RCSfile$\r
+//   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
+//   31  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   32  ******************************************************************************/\r
+//   33 \r
+//   34 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03bH\r
+// <unnamed> volatile __io _A_PORTA\r
+_A_PORTA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03aH\r
+// <unnamed> volatile __io _A_DDRA\r
+_A_DDRA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,027H\r
+// <unnamed> volatile __io _A_ADMUX\r
+_A_ADMUX:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,026H\r
+// <unnamed> volatile __io _A_ADCSRA\r
+_A_ADCSRA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,024H\r
+// <unnamed> volatile __io _A_ADC\r
+_A_ADC:\r
+        DS 2\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,023H\r
+// <unnamed> volatile __io _A_ADCSRB\r
+_A_ADCSRB:\r
+        DS 1\r
+//   35 #include <inavr.h>\r
+//   36 \r
+//   37 #include "structs.h"\r
+//   38 \r
+//   39 #include "main.h"\r
+//   40 #include "ADC.h"\r
+//   41 \r
+//   42 \r
+//   43 //******************************************************************************\r
+//   44 // Variables\r
+//   45 //******************************************************************************\r
+//   46 // ADC status struct.\r
+//   47 //! \brief Holds sampled data and ADC-status\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   48 ADC_Status_t ADCS;\r
+ADCS:\r
+        DS 24\r
+//   49 \r
+//   50 \r
+//   51 /*! \brief Indicates maximum battery voltage.\r
+//   52  *\r
+//   53  * This variable is stored in EEPROM and indicates how much the battery voltage\r
+//   54  * is downscaled by HW before it is sampled. The amount of downscaling depends\r
+//   55  * on the maximum battery voltage, and is necessary to avoid saturation of the\r
+//   56  * ADC (reference voltage is 2.5 V).\r
+//   57  *\r
+//   58  * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
+//   59  *\r
+//   60  * \note Defaults to 1, which means 10 V max battery voltage.\r
+//   61  *\r
+//   62  * \note Table of settings:\r
+//   63  * <pre>\r
+//   64  * VBAT_RANGE | Max battery voltage | Jumper setting\r
+//   65  *         0  |             5V      |        1/2\r
+//   66  *         1  |            10V      |        1/4\r
+//   67  *         2  |            20V      |        1/8\r
+//   68  *         3  |            30V      |       1/12\r
+//   69  *         4  |            40V      |       1/16\r
+//   70  * </pre>\r
+//   71  */\r
+//   72 // Maximum battery voltage (affects scaling of samples).\r
+\r
+        RSEG EEPROM_I:XDATA:NOROOT(0)\r
+//   73 __eeprom unsigned char VBAT_RANGE = 1;\r
+VBAT_RANGE:\r
+        DB 1\r
+//   74 \r
+//   75 \r
+//   76 //******************************************************************************\r
+//   77 // Functions\r
+//   78 //******************************************************************************\r
+//   79 /*! \brief Interrupt Service routine for ADC.\r
+//   80  *\r
+//   81  * This ISR stores the sampled values in the ADC status-struct, then\r
+//   82  * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
+//   83  * Once the sequence is completed, ADCS.Flag is set and unless\r
+//   84  * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
+//   85  * is disabled.\n\r
+//   86  * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
+//   87  *\r
+//   88  * \note Table of scanning sequence:\r
+//   89  * <pre>\r
+//   90  * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
+//   91  * ----+--------+----------+----------+------+---------+-------\r
+//   92  *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
+//   93  *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
+//   94  *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
+//   95  *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
+//   96  *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
+//   97  *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
+//   98  *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
+//   99  *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
+//  100  * </pre>\r
+//  101  *\r
+//  102  * \todo IIN (#7 in sequence) is never used.\r
+//  103  *\r
+//  104  * \todo Signed is never set. Signed measurements of IBAT will halve the\r
+//  105  * measuring sensitivity, and is therefore not favourable. At the moment,\r
+//  106  * great currents (f.ex. if something happens with the battery) will be\r
+//  107  * interpreted as negative, which might cause unfavourable behaviour during\r
+//  108  * charging (depending on what PWM behaviour is defined), f.ex.\r
+//  109  * ConstantCurrent() will keep increasing the PWM output. This results in an\r
+//  110  * PWM controller error being flagged and the program going into\r
+//  111  * error-state and eventually reinitializing.\r
+//  112  */\r
+//  113 #pragma vector=ADC_vect\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  114 __interrupt void ADC_ISR(void)\r
+ADC_ISR:\r
+//  115 {\r
+        ST      -Y, R5\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        ST      -Y, R31\r
+        ST      -Y, R30\r
+        ST      -Y, R3\r
+        ST      -Y, R2\r
+        ST      -Y, R1\r
+        ST      -Y, R0\r
+        ST      -Y, R23\r
+        ST      -Y, R22\r
+        ST      -Y, R21\r
+        ST      -Y, R20\r
+        ST      -Y, R19\r
+        ST      -Y, R18\r
+        ST      -Y, R17\r
+        ST      -Y, R16\r
+        IN      R5, 0x3F\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+//  116        static unsigned char avgIndex = 0;\r
+//  117        unsigned char i, Next, Signed;\r
+//  118        signed int  temp = 0;\r
+        LDI     R26, 0\r
+        LDI     R27, 0\r
+//  119        \r
+//  120        Signed = FALSE;  // Presume next conversion is unipolar.\r
+        CLR     R4\r
+//  121        ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
+        CBI     0x06, 0x07\r
+//  122          // conversions take at least 25 ADCCLK. (It is restarted later)\r
+//  123        \r
+//  124        // Handle the conversion, depending on what channel it is from, then\r
+//  125        // switch to the next channel in the sequence.\r
+//  126        switch (ADCS.MUX){\r
+        LDS     R16, ADCS\r
+        ANDI    R16, 0x1F\r
+        SUBI    R16, 1\r
+        BREQ    ??ADC_ISR_0\r
+        DEC     R16\r
+        BREQ    ??ADC_ISR_1\r
+        DEC     R16\r
+        BREQ    ??ADC_ISR_2\r
+        SUBI    R16, 2\r
+        BREQ    ??ADC_ISR_3\r
+        SUBI    R16, 18\r
+        BRNE    $+2+2\r
+        RJMP    ??ADC_ISR_4\r
+        RJMP    ??ADC_ISR_5\r
+//  127                // MUX = 0b000001 => ADC1 (PA1) = NTC\r
+//  128                case 0x01:\r
+//  129                        ADCS.rawNTC = ADC;\r
+??ADC_ISR_0:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+4, R16\r
+        STD     Z+5, R17\r
+//  130                        Next=0x02;\r
+        LDI     R25, 2\r
+        RJMP    ??ADC_ISR_6\r
+//  131                break;\r
+//  132 \r
+//  133                \r
+//  134                // MUX = 0b000010 => ADC2 (PA2) = RID\r
+//  135                case 0x02:\r
+//  136                        ADCS.rawRID = ADC;\r
+??ADC_ISR_1:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//  137                        Next=0x03;\r
+        LDI     R25, 3\r
+        RJMP    ??ADC_ISR_6\r
+//  138                break;\r
+//  139 \r
+//  140                \r
+//  141                // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
+//  142                case 0x03:\r
+//  143                        // Supply voltage is always divided by 16.\r
+//  144                        ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
+??ADC_ISR_2:\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        LDI     R16, 4\r
+        RCALL   ScaleU\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+8, R16\r
+        STD     Z+9, R17\r
+//  145                        \r
+//  146                        // Is mains failing?\r
+//  147                        if (ADCS.VIN < VIN_MIN) {\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+8\r
+        LDD     R17, Z+9\r
+        CPI     R16, 48\r
+        LDI     R18, 17\r
+        CPC     R17, R18\r
+        BRCC    ??ADC_ISR_7\r
+//  148                                ADCS.Mains = FALSE;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xBF\r
+        ST      Z, R16\r
+        RJMP    ??ADC_ISR_8\r
+//  149                        } else {\r
+//  150                                ADCS.Mains = TRUE;\r
+??ADC_ISR_7:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x40\r
+        ST      Z, R16\r
+//  151                        }\r
+//  152                        \r
+//  153                        Next=0x05;\r
+??ADC_ISR_8:\r
+        LDI     R25, 5\r
+        RJMP    ??ADC_ISR_6\r
+//  154                break;\r
+//  155 \r
+//  156                \r
+//  157                // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
+//  158                case 0x05:\r
+//  159                        ADCS.rawVBAT = ADC;\r
+??ADC_ISR_3:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+6, R16\r
+        STD     Z+7, R17\r
+//  160                        \r
+//  161                        // Scale voltage according to jumper setting.\r
+//  162                        ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        LDI     R20, LOW(VBAT_RANGE)\r
+        LDI     R21, (VBAT_RANGE) >> 8\r
+        RCALL   __eeget8_16\r
+        RCALL   ScaleU\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+10, R16\r
+        STD     Z+11, R17\r
+//  163                        Next=0x17;\r
+        LDI     R25, 23\r
+        RJMP    ??ADC_ISR_6\r
+//  164 //                     Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
+//  165                break;\r
+//  166 \r
+//  167 \r
+//  168                case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
+//  169                        // If bipolar, from -512 to 0, to 511:\r
+//  170                        // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
+//  171                \r
+//  172                        // Scale sample according to jumper setting, handle negative numbers.\r
+//  173                        if (ADC > 511) {\r
+??ADC_ISR_4:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        CPI     R16, 0\r
+        LDI     R18, 2\r
+        CPC     R17, R18\r
+        BRCS    ??ADC_ISR_9\r
+//  174                                ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
+//  175                                             (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+        LDI     R16, 0\r
+        LDI     R17, 4\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        LDS     R18, (ADCS + 1)\r
+        SWAP    R18\r
+        ANDI    R18, 0x0F\r
+        LDI     R19, 0\r
+        ADD     R18, R16\r
+        ADC     R19, R17\r
+        LDI     R20, LOW(VBAT_RANGE)\r
+        LDI     R21, (VBAT_RANGE) >> 8\r
+        RCALL   __eeget8_16\r
+        RCALL   ScaleI\r
+        NEG     R17\r
+        NEG     R16\r
+        SBCI    R17, 0\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+12, R16\r
+        STD     Z+13, R17\r
+        RJMP    ??ADC_ISR_10\r
+//  176                        } else if (ADC > 0) {\r
+??ADC_ISR_9:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        OR      R16, R17\r
+        BREQ    ??ADC_ISR_11\r
+//  177                                ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        LDS     R16, (ADCS + 1)\r
+        SWAP    R16\r
+        ANDI    R16, 0x0F\r
+        LDI     R17, 0\r
+        SUB     R18, R16\r
+        SBC     R19, R17\r
+        LDI     R20, LOW(VBAT_RANGE)\r
+        LDI     R21, (VBAT_RANGE) >> 8\r
+        RCALL   __eeget8_16\r
+        RCALL   ScaleI\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+12, R16\r
+        STD     Z+13, R17\r
+        RJMP    ??ADC_ISR_10\r
+//  178                        } else {\r
+//  179                                ADCS.IBAT = 0;\r
+??ADC_ISR_11:\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+12, R16\r
+        STD     Z+13, R17\r
+//  180                        }\r
+//  181 \r
+//  182                        // Insert sample of battery current into the averaging-array\r
+//  183                        // (overwriting the oldest sample), then recalculate and store the\r
+//  184                        // average. This is the last conversion in the sequence, so\r
+//  185                        // flag a complete ADC-cycle and restart sequence.\r
+//  186                        ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
+??ADC_ISR_10:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+12\r
+        LDD     R19, Z+13\r
+        LDS     R16, ??avgIndex\r
+        LDI     R17, 0\r
+        ANDI    R16, 0x03\r
+        ANDI    R17, 0x00\r
+        LSL     R16\r
+        ROL     R17\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+        SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+        STD     Z+14, R18\r
+        STD     Z+15, R19\r
+        LDI     R30, LOW(??avgIndex)\r
+        LDI     R31, (??avgIndex) >> 8\r
+        LD      R16, Z\r
+        INC     R16\r
+        ST      Z, R16\r
+//  187                        for (i = 0; i < 4 ; i++) {\r
+        LDI     R24, 0\r
+??ADC_ISR_12:\r
+        CPI     R24, 4\r
+        BRCC    ??ADC_ISR_13\r
+//  188                                temp += ADCS.discIBAT[i];\r
+        MOV     R16, R24\r
+        LDI     R17, 0\r
+        LSL     R16\r
+        ROL     R17\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+        SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+        LDD     R16, Z+14\r
+        LDD     R17, Z+15\r
+        ADD     R26, R16\r
+        ADC     R27, R17\r
+//  189                        }\r
+        INC     R24\r
+        RJMP    ??ADC_ISR_12\r
+//  190                        \r
+//  191                        ADCS.avgIBAT = (temp / 4);\r
+??ADC_ISR_13:\r
+        MOVW    R17:R16, R27:R26\r
+        LDI     R20, 4\r
+        LDI     R21, 0\r
+        RCALL   ?SS_DIVMOD_L02\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+22, R16\r
+        STD     Z+23, R17\r
+//  192                        \r
+//  193                        ADCS.Flag = TRUE;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x20\r
+        ST      Z, R16\r
+//  194                        Next=0x01;\r
+        LDI     R25, 1\r
+//  195                        Signed = FALSE;  // This is the only bipolar conversion.\r
+        CLR     R4\r
+        RJMP    ??ADC_ISR_6\r
+//  196                break;\r
+//  197 \r
+//  198                \r
+//  199                default:  // Should not happen. (Invalid MUX-channel)\r
+//  200                        Next=0x01;  // Start at the beginning of sequence.\r
+??ADC_ISR_5:\r
+        LDI     R25, 1\r
+//  201                break;\r
+//  202        }\r
+//  203        \r
+//  204        // Update MUX to next channel in sequence, set a bipolar conversion if\r
+//  205        // this has been flagged.\r
+//  206        ADCS.MUX = Next;                    \r
+??ADC_ISR_6:\r
+        LDS     R17, ADCS\r
+        ANDI    R17, 0xE0\r
+        MOV     R16, R25\r
+        ANDI    R16, 0x1F\r
+        OR      R16, R17\r
+        STS     ADCS, R16\r
+//  207        ADMUX = (1<<REFS0) + ADCS.MUX;      \r
+        LDS     R16, ADCS\r
+        ANDI    R16, 0x1F\r
+        SUBI    R16, 192\r
+        OUT     0x07, R16\r
+//  208 \r
+//  209        if (Signed)     {\r
+        TST     R4\r
+        BREQ    ??ADC_ISR_14\r
+//  210          ADCSRB |= (1<<BIN);               \r
+        SBI     0x03, 0x07\r
+        RJMP    ??ADC_ISR_15\r
+//  211        } else {\r
+//  212          ADCSRB &= ~(1<<BIN);              \r
+??ADC_ISR_14:\r
+        CBI     0x03, 0x07\r
+//  213        }\r
+//  214 \r
+//  215        // Re-enable the ADC unless a halt has been flagged and a conversion\r
+//  216        // cycle has completed.\r
+//  217        if (!((ADCS.Halt) && (ADCS.Flag))) {\r
+??ADC_ISR_15:\r
+        LDS     R16, ADCS\r
+        ANDI    R16, 0xA0\r
+        CPI     R16, 160\r
+        BREQ    ??ADC_ISR_16\r
+//  218          ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
+        IN      R16, 0x06\r
+        ORI     R16, 0xC0\r
+        OUT     0x06, R16\r
+//  219        }\r
+//  220 }\r
+??ADC_ISR_16:\r
+        OUT     0x3F, R5\r
+        LD      R16, Y+\r
+        LD      R17, Y+\r
+        LD      R18, Y+\r
+        LD      R19, Y+\r
+        LD      R20, Y+\r
+        LD      R21, Y+\r
+        LD      R22, Y+\r
+        LD      R23, Y+\r
+        LD      R0, Y+\r
+        LD      R1, Y+\r
+        LD      R2, Y+\r
+        LD      R3, Y+\r
+        LD      R30, Y+\r
+        LD      R31, Y+\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        LD      R5, Y+\r
+        RETI\r
+        REQUIRE _A_ADMUX\r
+        REQUIRE _A_ADCSRA\r
+        REQUIRE _A_ADC\r
+        REQUIRE _A_ADCSRB\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+??avgIndex:\r
+        DS 1\r
+//  221 \r
+//  222 \r
+//  223 /*! \brief Scales sample to represent "actual voltage" in mV.\r
+//  224  *\r
+//  225  * This function returns the actual sampled voltage, scaled according\r
+//  226  * to the jumper settings.\r
+//  227  *\r
+//  228  * \param setting Indicates what downscaling was used.\r
+//  229  * \param data The sampled value.\r
+//  230  *\r
+//  231  * \note Table for setting-parameter:\n\r
+//  232  * <pre>\r
+//  233  * Presume VREF = 2.5V and Gain = 1x.\r
+//  234  * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
+//  235  * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
+//  236  * --------+--------+------+------------+-----------+-------\r
+//  237  *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
+//  238  *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
+//  239  *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
+//  240  *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
+//  241  *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
+//  242  *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
+//  243  *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
+//  244  * </pre>\r
+//  245  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  246 unsigned int ScaleU(unsigned char setting, unsigned int data)\r
+ScaleU:\r
+//  247 {\r
+        RCALL   ?PROLOGUE6_L09\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        MOV     R26, R16\r
+        MOVW    R25:R24, R19:R18\r
+//  248        // Temporary variable needed.\r
+//  249        unsigned int scaled = 0;\r
+        CLR     R4\r
+        CLR     R5\r
+//  250 \r
+//  251        // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
+//  252        if (setting == 3)       {\r
+        CPI     R26, 3\r
+        BRNE    ??ScaleU_0\r
+//  253                scaled = 29 * data;\r
+        MOVW    R21:R20, R25:R24\r
+        LDI     R16, 29\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R5:R4, R17:R16\r
+//  254                scaled += (data >> 2);\r
+        MOVW    R17:R16, R25:R24\r
+        LSR     R17\r
+        ROR     R16\r
+        LSR     R17\r
+        ROR     R16\r
+        ADD     R4, R16\r
+        ADC     R5, R17\r
+//  255                scaled += (data >> 4);\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 4\r
+        RCALL   ?US_SHR_L02\r
+        ADD     R4, R16\r
+        ADC     R5, R17\r
+        RJMP    ??ScaleU_1\r
+//  256        } else {\r
+//  257                // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
+//  258                scaled = 39 * data;\r
+??ScaleU_0:\r
+        MOVW    R21:R20, R25:R24\r
+        LDI     R16, 39\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R5:R4, R17:R16\r
+//  259                scaled += (data >> 4);\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 4\r
+        RCALL   ?US_SHR_L02\r
+        ADD     R4, R16\r
+        ADC     R5, R17\r
+//  260                \r
+//  261                if (setting <3) {\r
+        CPI     R26, 3\r
+        BRCC    ??ScaleU_1\r
+//  262                        // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
+//  263                        //                1: mV/LSB = 9.766 = 39.06 / 4\r
+//  264                        //                2: mV/LSB = 19.53 = 39.06 / 2\r
+//  265                        scaled = (scaled >> (3-setting));\r
+        MOVW    R17:R16, R5:R4\r
+        LDI     R20, 3\r
+        SUB     R20, R26\r
+        RCALL   ?US_SHR_L02\r
+        MOVW    R5:R4, R17:R16\r
+//  266                }\r
+//  267        }\r
+//  268 \r
+//  269        return(scaled);\r
+??ScaleU_1:\r
+        MOVW    R17:R16, R5:R4\r
+        LDI     R30, 6\r
+        RJMP    ?EPILOGUE_B6_L09\r
+//  270 }\r
+//  271 \r
+//  272 \r
+//  273 /*! \brief Scales sample to represent "actual current" in mA.\r
+//  274  *\r
+//  275  * This function returns the actual sampled current, scaled according\r
+//  276  * to the jumper settings.\r
+//  277  *\r
+//  278  * \param setting Indicates what downscaling was used.\r
+//  279  * \param data The sampled value.\r
+//  280  *\r
+//  281  * \note Table for setting-parameter:\n\r
+//  282  * <pre>\r
+//  283  * Presume VREF = 2.5V and Gain = 1x or 20x.\r
+//  284  * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
+//  285  * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
+//  286  * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
+//  287  * --------+------+------------+----------+----------+--------+-----\r
+//  288  *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
+//  289  *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
+//  290  *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
+//  291  *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
+//  292  *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
+//  293  *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
+//  294  *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
+//  295  * </pre>\r
+//  296  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  297 unsigned int ScaleI(unsigned char setting, unsigned int data)\r
+ScaleI:\r
+//  298 {\r
+        RCALL   ?PROLOGUE6_L09\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        MOV     R26, R16\r
+        MOVW    R25:R24, R19:R18\r
+//  299        // Temporary variable needed.\r
+//  300        unsigned int  scaled = 0;\r
+        CLR     R4\r
+        CLR     R5\r
+//  301        \r
+//  302        // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
+//  303        if (setting == 3) {\r
+        CPI     R26, 3\r
+        BRNE    ??ScaleI_0\r
+//  304                scaled = 21 * data;\r
+        MOVW    R21:R20, R25:R24\r
+        LDI     R16, 21\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R5:R4, R17:R16\r
+//  305                scaled -= (data >> 4);\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 4\r
+        RCALL   ?US_SHR_L02\r
+        SUB     R4, R16\r
+        SBC     R5, R17\r
+//  306                scaled += (data >> 7);\r
+        MOVW    R17:R16, R25:R24\r
+        LSL     R16\r
+        MOV     R16, R17\r
+        ROL     R16\r
+        LDI     R17, 0\r
+        ROL     R17\r
+        ADD     R4, R16\r
+        ADC     R5, R17\r
+        RJMP    ??ScaleI_1\r
+//  307        }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
+//  308                scaled = 28 * data;\r
+??ScaleI_0:\r
+        MOVW    R21:R20, R25:R24\r
+        LDI     R16, 28\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R5:R4, R17:R16\r
+//  309                scaled -= (data >> 3);\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 3\r
+        RCALL   ?US_SHR_L02\r
+        SUB     R4, R16\r
+        SBC     R5, R17\r
+//  310                scaled += (data >> 5);\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 5\r
+        RCALL   ?US_SHR_L02\r
+        ADD     R4, R16\r
+        ADC     R5, R17\r
+//  311                \r
+//  312                if (setting <3) {\r
+        CPI     R26, 3\r
+        BRCC    ??ScaleI_1\r
+//  313                        // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
+//  314                        //                1: mA/LSB = 6.978mA = 27.909 / 4\r
+//  315                        //                2: mA/LSB = 13.955mA = 27.909 / 2\r
+//  316                        scaled = (scaled >> (3-setting));\r
+        MOVW    R17:R16, R5:R4\r
+        LDI     R20, 3\r
+        SUB     R20, R26\r
+        RCALL   ?US_SHR_L02\r
+        MOVW    R5:R4, R17:R16\r
+//  317                }\r
+//  318        }\r
+//  319        \r
+//  320        return(scaled);\r
+??ScaleI_1:\r
+        MOVW    R17:R16, R5:R4\r
+        LDI     R30, 6\r
+        RJMP    ?EPILOGUE_B6_L09\r
+//  321 }\r
+//  322 \r
+//  323 \r
+//  324 /*! \brief Waits for two full cycles of ADC-conversions to occur.\r
+//  325  *\r
+//  326  * This function clears the cycle complete-flag, then waits for it to be set\r
+//  327  * again. This is then repeated once before the function exits.\r
+//  328  * \r
+//  329  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  330 void ADC_Wait(void)\r
+ADC_Wait:\r
+//  331 {\r
+//  332        // Clear ADC flag and wait for cycle to complete.\r
+//  333        ADCS.Flag = FALSE;              \r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xDF\r
+        ST      Z, R16\r
+//  334        do {\r
+//  335        } while (ADCS.Flag == FALSE);      \r
+??ADC_Wait_0:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 5\r
+        RJMP    ??ADC_Wait_0\r
+//  336        \r
+//  337        // Repeat, so we are sure the data beong to the same cycle.\r
+//  338        ADCS.Flag = FALSE;              \r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xDF\r
+        ST      Z, R16\r
+//  339        do {\r
+//  340        } while (ADCS.Flag == FALSE);      \r
+??ADC_Wait_1:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 5\r
+        RJMP    ??ADC_Wait_1\r
+//  341 }\r
+        RET\r
+//  342 \r
+//  343 \r
+//  344 /*! \brief Initializes ADC and input pins.\r
+//  345  *\r
+//  346  * This function initializes the ADC to free running mode, sampling from\r
+//  347  * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
+//  348  * It also measures and stores calibration data for offset.\r
+//  349  *\r
+//  350  * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
+//  351  *\r
+//  352  * \note Table of MUX settings for offset measurement:\r
+//  353  * <pre>\r
+//  354  *    Ch | Pin |    Gain |    MUX\r
+//  355  * ------+-----+---------+-------\r
+//  356  *  ADC1 | PA1 |     20x | 001101\r
+//  357  *  ADC3 | PA4 |     20x | 010001\r
+//  358  *  ADC5 | PA6 |     20x | 010110\r
+//  359  *  ADC9 | PB6 |     20x | 011011\r
+//  360  *  ADC0 | PA0 | 20x/32x | 111000\r
+//  361  *  ADC0 | PA0 |   1x/8x | 111001\r
+//  362  *  ADC1 | PA1 | 20x/32x | 111010\r
+//  363  *  ADC2 | PA2 | 20x/32x | 111011\r
+//  364  *  ADC4 | PA5 | 20x/32x | 111100\r
+//  365  *  ADC5 | PA6 | 20x/32x | 111101\r
+//  366  *  ADC6 | PA7 | 20x/32x | 111110\r
+//  367  * </pre>\r
+//  368  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  369 void ADC_Init(void)\r
+ADC_Init:\r
+//  370 {\r
+        ST      -Y, R24\r
+//  371        unsigned char i;\r
+//  372 \r
+//  373        __disable_interrupt();\r
+        CLI\r
+//  374 \r
+//  375        ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0x7F\r
+        ST      Z, R16\r
+//  376 \r
+//  377        // Configure ADC pins (inputs and disabled pull-ups).\r
+//  378        DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+        IN      R16, 0x1A\r
+        ANDI    R16, 0x09\r
+        OUT     0x1A, R16\r
+//  379        PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+        IN      R16, 0x1B\r
+        ANDI    R16, 0x09\r
+        OUT     0x1B, R16\r
+//  380 \r
+//  381        // Set ADC3 as reference, and MUX to measure the same pin.\r
+//  382        ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
+        LDI     R16, 67\r
+        OUT     0x07, R16\r
+//  383        \r
+//  384        ADCSRB = 0;\r
+        LDI     R16, 0\r
+        OUT     0x03, R16\r
+//  385 \r
+//  386        // Start conversion, no interrupt (disable ADC-ISR).\r
+//  387        ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+        LDI     R16, 199\r
+        OUT     0x06, R16\r
+//  388 \r
+//  389        do { // Wait for conversion to finish.\r
+//  390        } while (!(ADCSRA & (1<<ADIF)));\r
+??ADC_Init_0:\r
+        SBIS    0x06, 0x04\r
+        RJMP    ??ADC_Init_0\r
+//  391 \r
+//  392        ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
+        SBI     0x06, 0x04\r
+//  393 \r
+//  394        ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
+        LDS     R18, (ADCS + 1)\r
+        ANDI    R18, 0xF0\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        ANDI    R16, 0x0F\r
+        OR      R16, R18\r
+        STS     (ADCS + 1), R16\r
+//  395 \r
+//  396        ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
+        LDI     R16, 86\r
+        OUT     0x07, R16\r
+//  397        \r
+//  398        // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
+//  399        ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+        LDI     R16, 199\r
+        OUT     0x06, R16\r
+//  400 \r
+//  401        do { // Wait for conversion to finish.\r
+//  402        } while (!(ADCSRA & (1<<ADIF)));\r
+??ADC_Init_1:\r
+        SBIS    0x06, 0x04\r
+        RJMP    ??ADC_Init_1\r
+//  403 \r
+//  404        ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
+        SBI     0x06, 0x04\r
+//  405 \r
+//  406        ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
+        LDS     R18, (ADCS + 1)\r
+        ANDI    R18, 0x0F\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        SWAP    R16\r
+        ANDI    R16, 0xF0\r
+        OR      R16, R18\r
+        STS     (ADCS + 1), R16\r
+//  407 \r
+//  408        // Reset the ADC-cycle.\r
+//  409        ADCS.Flag = FALSE;      \r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xDF\r
+        ST      Z, R16\r
+//  410        ADCS.MUX = 0x01;                    \r
+        LDS     R16, ADCS\r
+        ANDI    R16, 0xE0\r
+        ORI     R16, 0x01\r
+        STS     ADCS, R16\r
+//  411        ADMUX = (1<<REFS0) | ADCS.MUX;      \r
+        LDS     R16, ADCS\r
+        ANDI    R16, 0x1F\r
+        ORI     R16, 0x40\r
+        OUT     0x07, R16\r
+//  412 \r
+//  413        // Clear averaged battery current and the discrete readings.\r
+//  414        ADCS.avgIBAT = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        STD     Z+22, R16\r
+        STD     Z+23, R17\r
+//  415        \r
+//  416        for (i = 0; i < 4; i++) {\r
+        LDI     R24, 0\r
+??ADC_Init_2:\r
+        CPI     R24, 4\r
+        BRCC    ??ADC_Init_3\r
+//  417                ADCS.discIBAT[i] = 0;             \r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        MOV     R18, R24\r
+        LDI     R19, 0\r
+        LSL     R18\r
+        ROL     R19\r
+        MOVW    R31:R30, R19:R18\r
+        SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+        SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+        STD     Z+14, R16\r
+        STD     Z+15, R17\r
+//  418        }\r
+        INC     R24\r
+        RJMP    ??ADC_Init_2\r
+//  419        \r
+//  420        // Re-enable the ADC and ISR.\r
+//  421        ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
+??ADC_Init_3:\r
+        LDI     R16, 207\r
+        OUT     0x06, R16\r
+//  422        \r
+//  423        __enable_interrupt();\r
+        SEI\r
+//  424 \r
+//  425        // Get a complete cycle of data before returning.\r
+//  426        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  427 }\r
+        LD      R24, Y+\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+        REQUIRE _A_ADMUX\r
+        REQUIRE _A_ADCSRA\r
+        REQUIRE _A_ADC\r
+        REQUIRE _A_ADCSRB\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        COMMON INTVEC:CODE:ROOT(1)\r
+        ORG 22\r
+`??ADC_ISR??INTVEC 22`:\r
+        RJMP    ADC_ISR\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   7 bytes in segment ABSOLUTE\r
+// 946 bytes in segment CODE\r
+//   1 byte  in segment EEPROM_I\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment INTVEC\r
+//  25 bytes in segment NEAR_Z\r
+// \r
+// 946 bytes of CODE  memory (+ 8 bytes shared)\r
+//  25 bytes of DATA  memory (+ 7 bytes shared)\r
+//   1 byte  of XDATA memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/BC100_tiny.html b/BaseTinyFirmware/IAR/Debug/List/BC100_tiny.html
new file mode 100644 (file)
index 0000000..fe2ce33
--- /dev/null
@@ -0,0 +1,3208 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\r
+<html>\r
+<head>\r
+<title>XLINK Map File for "BC100_tiny"</title>\r
+</head>\r
+<body bgcolor="#dde2a0" text=black>\r
+<h2 align=center>XLINK Map File for "BC100_tiny"</h2>\r
+<h3 align=center>IAR Universal Linker V4.60I/386</h3>\r
+<h4 align=center>Copyright 1987-2007 IAR Systems. All rights reserved.</h4>\r
+\r
+<p align=center>\r
+<a href="#Invocation Map">Invocation</a>\r
+&nbsp;&nbsp;<a href="#Program Entry">Program Entry</a>\r
+&nbsp;&nbsp;<a href="#Module Map">Module Map</a>\r
+&nbsp;&nbsp;<a href="#Module Summary">Module Summary</a>\r
+&nbsp;&nbsp;<a href="#Call Graph">Call Graph</a>\r
+&nbsp;&nbsp;<a href="#Segments in Address Order">Segment Map</a>\r
+&nbsp;&nbsp;<a href="#Memory Summary">Memory Summary</a>\r
+<p><hr>\r
+<p><a name="Invocation Map"></a><table>\r
+<tr valign=top>\r
+  <td><font size=2><b>Link&nbsp;time</font></b>\r
+  <td><font size=2>12/Mar/2008  23:01:40</font>\r
+<tr valign=top>\r
+  <td><font size=2><b>Target&nbsp;CPU</font></b>\r
+  <td><font size=2>A90</font>\r
+<tr valign=top>\r
+  <td><font size=2><b>List&nbsp;file</font></b>\r
+  <td><font size=2>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\BC100_tiny.html</font>\r
+<tr valign=top>\r
+  <td><font size=2><b>Output&nbsp;file&nbsp;1</font></b>\r
+  <td><font size=2>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Exe\BC100_tiny.d90</font>\r
+<tr valign=top>\r
+  <td><font size=2><b></font></b>\r
+  <td><font size=2>Format: ubrof8</font>\r
+<tr valign=top>\r
+  <td><font size=2><b></font></b>\r
+  <td><font size=2>UBROF version 8.0.2</font>\r
+<tr valign=top>\r
+  <td><font size=2><b>Command&nbsp;line</font></b>\r
+  <td><font size=2></font>\r
+<code>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\OWI.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\USI.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\battery.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\chargefunc.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\menu.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\statefunc.r90\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\time.r90\r
+<b>-o</b>\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Exe\BC100_tiny.d90\r
+<b>-F</b>ubrof8\r
+<b>-l</b>\r
+C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\BC100_tiny.html\r
+<b>-x</b>msnoh\r
+<b>"-</b>"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\"\r
+<b>-f</b>\r
+"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\src\template\cfgtiny861.xcl"\r
+( <b>-D</b>_..X_INTVEC_SIZE=26\r
+<b>-D</b>_..X_FLASH_END=1FFF\r
+<b>-D</b>_..X_SRAM_BASE=60\r
+<b>-D</b>_..X_SRAM_TBASE=_..X_SRAM_BASE\r
+<b>-D</b>_..X_SRAM_TSIZE=(100-_..X_SRAM_BASE)\r
+<b>-D</b>_..X_SRAM_END=25F\r
+<b>-D</b>_..X_EXT_SRAM_BASE=_..X_SRAM_END\r
+<b>-D</b>_..X_EXT_SRAM_SIZE=0\r
+<b>-D</b>_..X_EXT_ROM_BASE=_..X_SRAM_END\r
+<b>-D</b>_..X_EXT_ROM_SIZE=0\r
+<b>-D</b>_..X_EXT_NV_BASE=_..X_SRAM_END\r
+<b>-D</b>_..X_EXT_NV_SIZE=0\r
+<b>-D</b>_..X_EEPROM_END=1FF\r
+<b>-D</b>_..X_EEPROM_START=0\r
+) <b>-D</b>_..X_HEAP_SIZE=10\r
+<b>-D</b>_..X_TINY_HEAP_SIZE=0\r
+<b>-D</b>_..X_NEAR_HEAP_SIZE=0\r
+<b>-D</b>_..X_FAR_HEAP_SIZE=0\r
+<b>-D</b>_..X_HUGE_HEAP_SIZE=0\r
+<b>-D</b>_..X_CSTACK_SIZE=40\r
+<b>-D</b>_..X_RSTACK_SIZE=30\r
+<b>-f</b>\r
+"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\src\template\cfg1soim.xcl"\r
+( <b>-c</b>a90\r
+<b>-w</b>29\r
+<b>-Z</b>(CODE)INTVEC=0-_..X_INTVEC_SIZE\r
+<b>-Z</b>(CODE)TINY_F=_..X_FLASH_BASE-FF\r
+<b>-Z</b>(CODE)NEAR_F=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)SWITCH=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)INITTAB=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)DIFUNCT=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)TINY_ID=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)NEAR_ID=_..X_FLASH_BASE-_..X_FLASH_END\r
+<b>-Z</b>(CODE)CHECKSUM#_..X_FLASH_END\r
+<b>-Z</b>(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE\r
+<b>-Z</b>(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_CSTACK_BASE-_..X_CSTACK_END\r
+<b>-Z</b>(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END\r
+<b>-Z</b>(DATA)IOSTREAM_N#_..X_SRAM_BASE-_..X_SRAM_END\r
+<b>-Z</b>(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END\r
+<b>-Z</b>(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE-_..X_RSTACK_END\r
+<b>-Z</b>(DATA)NEAR_I,NEAR_Z,NEAR_N=_..X_SRAM_BASE-_..X_SRAM_END\r
+<b>-Z</b>(XDATA)EEPROM_I,EEPROM_N=_..X_EEPROM_START-_..X_EEPROM_END\r
+) <b>-D</b>_..X_FLASH_BASE=_..X_INTVEC_SIZE\r
+<b>-H</b>1895\r
+<b>-h</b>(CODE)0-(_..X_INTVEC_SIZE-1)\r
+<b>-D</b>_..X_CSTACK_BASE=_..X_SRAM_BASE\r
+<b>-D</b>_..X_CSTACK_END=_..X_SRAM_END\r
+<b>-D</b>_..X_RSTACK_BASE=_..X_SRAM_BASE\r
+<b>-D</b>_..X_RSTACK_END=_..X_SRAM_END\r
+<b>-s</b>\r
+__program_start\r
+"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90"\r
+<b>-e</b>_small_write=_formatted_write\r
+<b>-e</b>_medium_read=_formatted_read\r
+</code>\r
+</table>\r
+\r
+\r
+\r
+<p><hr><a name="Program Entry"></a><p>\r
+       Program entry at : CODE      00000000  Relocatable, from module : ?RESET\r
+\r
+\r
+<p><hr><p>\r
+<a name="Runtime Model"></a>\r
+<table bgcolor="#c0c0" border=1 cellpadding=2>\r
+<tr>\r
+  <th align=center colspan=2><font size=4><B>Runtime Model</B>\r
+</font>\r
+<tr>\r
+  <th><font size=2>Attribute</font>\r
+  <th><font size=2>Value</font>\r
+<tr valign=top>\r
+  <td><font size=2>EEPROM_SIZE</font>\r
+  <td><font size=2>2</font>\r
+<tr valign=top>\r
+  <td><font size=2>R4</font>\r
+  <td><font size=2>REG</font>\r
+<tr valign=top>\r
+  <td><font size=2>R5</font>\r
+  <td><font size=2>REG</font>\r
+<tr valign=top>\r
+  <td><font size=2>R6</font>\r
+  <td><font size=2>REG</font>\r
+<tr valign=top>\r
+  <td><font size=2>R7</font>\r
+  <td><font size=2>REG</font>\r
+<tr valign=top>\r
+  <td><font size=2>R8</font>\r
+  <td><font size=2>REG</font>\r
+<tr valign=top>\r
+  <td><font size=2>__64bit_doubles</font>\r
+  <td><font size=2>disabled</font>\r
+<tr valign=top>\r
+  <td><font size=2>__cpu</font>\r
+  <td><font size=2>1</font>\r
+<tr valign=top>\r
+  <td><font size=2>__cpu_name</font>\r
+  <td><font size=2>ATtiny861</font>\r
+<tr valign=top>\r
+  <td><font size=2>__enhanced_core</font>\r
+  <td><font size=2>enabled</font>\r
+<tr valign=top>\r
+  <td><font size=2>__has_elpm</font>\r
+  <td><font size=2>false</font>\r
+<tr valign=top>\r
+  <td><font size=2>__memory_model</font>\r
+  <td><font size=2>2</font>\r
+<tr valign=top>\r
+  <td><font size=2>__rt_version</font>\r
+  <td><font size=2>3</font>\r
+</table>\r
+<p><hr><p>\r
+<a name="Module Map"></a>\r
+<table bgcolor="#c0c0c0" border=1 cellpadding=2>\r
+<tr>\r
+  <th align=center colspan=6><font size=4><B>Module Map</B>\r
+</font>\r
+<tr>\r
+  <th><font size=2>File</font>\r
+  <th><font size=2>Module</font>\r
+  <th><font size=2>Segment</font>\r
+  <th><font size=2>Symbol</font>\r
+  <th><font size=2>Address</font>\r
+  <th><font size=2>Ref by</font>\r
+<tr valign=top>\r
+  <td rowspan=26 ><font size=2><b></b></font>\r
+  <td rowspan=26><font size=2><a name="MM\?ABS_ENTRY_MOD"><b>?ABS_ENTRY_MOD</b></a><br>Program module</font>\r
+  <td rowspan=26 ><font size=2><i>Absolute parts</i></font>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_RSTACK_END"><b>_..X_RSTACK_END</b></a>\r
+</font>\r
+  <td><font size=2>0000025F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_RSTACK_BASE"><b>_..X_RSTACK_BASE</b></a>\r
+</font>\r
+  <td><font size=2>00000060 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_CSTACK_END"><b>_..X_CSTACK_END</b></a>\r
+</font>\r
+  <td><font size=2>0000025F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_CSTACK_BASE"><b>_..X_CSTACK_BASE</b></a>\r
+</font>\r
+  <td><font size=2>00000060 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_FLASH_BASE"><b>_..X_FLASH_BASE</b></a>\r
+</font>\r
+  <td><font size=2>00000026 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_RSTACK_SIZE"><b>_..X_RSTACK_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000030 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_CSTACK_SIZE"><b>_..X_CSTACK_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000040 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_HUGE_HEAP_SIZE"><b>_..X_HUGE_HEAP_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_FAR_HEAP_SIZE"><b>_..X_FAR_HEAP_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_NEAR_HEAP_SIZE"><b>_..X_NEAR_HEAP_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_TINY_HEAP_SIZE"><b>_..X_TINY_HEAP_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_HEAP_SIZE"><b>_..X_HEAP_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000010 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EEPROM_START"><b>_..X_EEPROM_START</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EEPROM_END"><b>_..X_EEPROM_END</b></a>\r
+</font>\r
+  <td><font size=2>000001FF </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EXT_NV_SIZE"><b>_..X_EXT_NV_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EXT_NV_BASE"><b>_..X_EXT_NV_BASE</b></a>\r
+</font>\r
+  <td><font size=2>0000025F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EXT_ROM_SIZE"><b>_..X_EXT_ROM_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EXT_ROM_BASE"><b>_..X_EXT_ROM_BASE</b></a>\r
+</font>\r
+  <td><font size=2>0000025F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EXT_SRAM_SIZE"><b>_..X_EXT_SRAM_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_EXT_SRAM_BASE"><b>_..X_EXT_SRAM_BASE</b></a>\r
+</font>\r
+  <td><font size=2>0000025F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_SRAM_END"><b>_..X_SRAM_END</b></a>\r
+</font>\r
+  <td><font size=2>0000025F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_SRAM_TSIZE"><b>_..X_SRAM_TSIZE</b></a>\r
+</font>\r
+  <td><font size=2>000000A0 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_SRAM_TBASE"><b>_..X_SRAM_TBASE</b></a>\r
+</font>\r
+  <td><font size=2>00000060 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_SRAM_BASE"><b>_..X_SRAM_BASE</b></a>\r
+</font>\r
+  <td><font size=2>00000060 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_FLASH_END"><b>_..X_FLASH_END</b></a>\r
+</font>\r
+  <td><font size=2>00001FFF </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?ABS_ENTRY_MOD\_..X_INTVEC_SIZE"><b>_..X_INTVEC_SIZE</b></a>\r
+</font>\r
+  <td><font size=2>00000026 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=34 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90</b></font>\r
+  <td rowspan=34><font size=2><a name="MM\ADC"><b>ADC</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_1"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000003B - 0000003B<br>Segment part 1.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<br><a href="#MM\OWI\Segpart_14">OWI_DetectPresence (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_10">OWI_Init (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_13">OWI_ReadBit (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_12">OWI_WriteBit0 (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_11">OWI_WriteBit1 (OWI)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\_A_PORTA"><b>_A_PORTA</b></a>\r
+</font>\r
+  <td><font size=2>0000003B </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_2"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000003A - 0000003A<br>Segment part 2.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<br><a href="#MM\OWI\Segpart_14">OWI_DetectPresence (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_10">OWI_Init (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_13">OWI_ReadBit (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_12">OWI_WriteBit0 (OWI)</a>\r
+<br><a href="#MM\OWI\Segpart_11">OWI_WriteBit1 (OWI)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\_A_DDRA"><b>_A_DDRA</b></a>\r
+</font>\r
+  <td><font size=2>0000003A </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_3"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000027 - 00000027<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<br><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\_A_ADMUX"><b>_A_ADMUX</b></a>\r
+</font>\r
+  <td><font size=2>00000027 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_4"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000026 - 00000026<br>Segment part 4.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<br><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<br><a href="#MM\statefunc\Segpart_20">Doze (statefunc)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\_A_ADCSRA"><b>_A_ADCSRA</b></a>\r
+</font>\r
+  <td><font size=2>00000026 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_5"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000024 - 00000025<br>Segment part 5.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<br><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\_A_ADC"><b>_A_ADC</b></a>\r
+</font>\r
+  <td><font size=2>00000024 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_6"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000023 - 00000023<br>Segment part 6.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<br><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\_A_ADCSRB"><b>_A_ADCSRB</b></a>\r
+</font>\r
+  <td><font size=2>00000023 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_14"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000144 - 0000015B<br>Segment part 14.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<br><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<br><a href="#MM\ADC\Segpart_21">ADC_Wait</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\ADCS"><b>ADCS</b></a>\r
+</font>\r
+  <td><font size=2>00000144 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_20">BatteryStatusRefresh (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_20">Doze (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<br><a href="#MM\battery\Segpart_25">NTCLookUp (battery)</a>\r
+<br><a href="#MM\battery\Segpart_24">RIDLookUp (battery)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_16"><b>EEPROM_I</b></a></b><br>Relative segment<br>XDATA 00000000 - 00000000<br>Segment part 16.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\VBAT_RANGE"><b>VBAT_RANGE</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_18"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000050 - 0000025F<br>Segment part 18.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_11">ADC_ISR::??INTVEC 22</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\ADC_ISR"><b>ADC_ISR</b></a>\r
+<br>               interrupt function\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000014 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000050 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_17"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 0000015C - 0000015C<br>Segment part 17.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\ADC_ISR::avgIndex"><b>ADC_ISR::avgIndex</b></a>\r
+</font>\r
+  <td><font size=2>0000015C </font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_19"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000260 - 000002B9<br>Segment part 19.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\ScaleU"><b>ScaleU</b></a>\r
+<br>               stack 1 = 00000000 ( 00000006 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000260 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_20"><b>CODE</b></a></b><br>Relative segment<br>CODE 000002BA - 0000031F<br>Segment part 20.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\ScaleI"><b>ScaleI</b></a>\r
+<br>               stack 1 = 00000000 ( 00000006 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>000002BA </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_21"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000320 - 00000349<br>Segment part 21.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_22">ADC_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\ADC_Wait"><b>ADC_Wait</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000320 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_20">Doze (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\ADC\Segpart_22"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000034A - 00000401<br>Segment part 22.</font>\r
+  <td nowrap><font size=2><a name="MM\ADC\ADC_Init"><b>ADC_Init</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000001 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>0000034A </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\ADC\Segpart_7"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000001C <br>Segment part 7.</font>\r
+  <td nowrap><font size=2><a name="MM\ADC\__?EECR"><b>__?EECR</b></a>\r
+</font>\r
+  <td><font size=2>0000001C </font>\r
+  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_0">Segment part 0 (?EEPROM_16)</a>\r
+<br><a href="#MM\?EEPROM_16\Segpart_1">Segment part 1 (?EEPROM_16)</a>\r
+<br><a href="#MM\?EEPROM_16\Segpart_8">Segment part 8 (?EEPROM_16)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\ADC\Segpart_8"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000001D <br>Segment part 8.</font>\r
+  <td nowrap><font size=2><a name="MM\ADC\__?EEDR"><b>__?EEDR</b></a>\r
+</font>\r
+  <td><font size=2>0000001D </font>\r
+  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_3">__eeget8_16 (?EEPROM_16)</a>\r
+<br><a href="#MM\?EEPROM_16\Segpart_10">__eeput8_16 (?EEPROM_16)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\ADC\Segpart_9"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000001E <br>Segment part 9.</font>\r
+  <td nowrap><font size=2><a name="MM\ADC\__?EEARL"><b>__?EEARL</b></a>\r
+</font>\r
+  <td><font size=2>0000001E </font>\r
+  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_1">Segment part 1 (?EEPROM_16)</a>\r
+<br><a href="#MM\?EEPROM_16\Segpart_8">Segment part 8 (?EEPROM_16)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\ADC\Segpart_10"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000001F <br>Segment part 10.</font>\r
+  <td nowrap><font size=2><a name="MM\ADC\__?EEARH"><b>__?EEARH</b></a>\r
+</font>\r
+  <td><font size=2>0000001F </font>\r
+  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_1">Segment part 1 (?EEPROM_16)</a>\r
+<br><a href="#MM\?EEPROM_16\Segpart_8">Segment part 8 (?EEPROM_16)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\ADC\Segpart_11"><b>INTVEC</b></a></b><br>Common segment<br>CODE 00000000 - 00000017<br>Segment part 11. ROOT.</font>\r
+  <td nowrap><font size=2><a name="MM\ADC\ADC_ISR::??INTVEC 22"><b>ADC_ISR::??INTVEC 22</b></a>\r
+</font>\r
+  <td><font size=2>00000016 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\ADC\Segpart_15"><b>INITTAB</b></a></b><br>Relative segment<br>CODE 00000044 - 00000049<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\ADC\Segpart_14">ADCS</a>\r
+<br><a href="#MM\ADC\Segpart_17">ADC_ISR::avgIndex</a>\r
+<br><a href="#MM\battery\Segpart_13">BattActive (battery)</a>\r
+<br><a href="#MM\battery\Segpart_10">BattData (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_8">ChargeParameters (chargefunc)</a>\r
+<br><a href="#MM\main\Segpart_7">CurrentState (main)</a>\r
+<br><a href="#MM\statefunc\Segpart_13">ErrorFlags (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_15">ErrorState (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_10">HaltParameters (chargefunc)</a>\r
+<br><a href="#MM\USI\Segpart_13">SPI (USI)</a>\r
+<br><a href="#MM\time\Segpart_13">timeval (time)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\ADC\?&lt;Segment init: NEAR_Z&gt;"><b>?&lt;Segment init: NEAR_Z&gt;</b></a>\r
+</font>\r
+  <td><font size=2>00000044 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge.r90</b></font>\r
+  <td rowspan=1><font size=2><a name="MM\NIMHcharge"><b>NIMHcharge</b></a><br>Program module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\NIMHcharge\Segpart_7"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000402 - 00000565<br>Segment part 7.</font>\r
+  <td nowrap><font size=2><a name="MM\NIMHcharge\Charge"><b>Charge</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000002 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000402 </font>\r
+  <td><font size=2><a href="#MM\menu\Segpart_7">menu_state (menu)</a>\r
+<tr valign=top>\r
+  <td rowspan=13 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\OWI.r90</b></font>\r
+  <td rowspan=13><font size=2><a name="MM\OWI"><b>OWI</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\OWI\Segpart_3"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000039 - 00000039<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\OWI\Segpart_14">OWI_DetectPresence</a>\r
+<br><a href="#MM\OWI\Segpart_13">OWI_ReadBit</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\OWI\_A_PINA"><b>_A_PINA</b></a>\r
+</font>\r
+  <td><font size=2>00000039 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\OWI\Segpart_10"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000566 - 00000587<br>Segment part 10.</font>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_Init"><b>OWI_Init</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000566 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\OWI\Segpart_11"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000588 - 000005C5<br>Segment part 11.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\OWI\Segpart_15">OWI_SendByte</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_WriteBit1"><b>OWI_WriteBit1</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000588 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\OWI\Segpart_12"><b>CODE</b></a></b><br>Relative segment<br>CODE 000005C6 - 00000603<br>Segment part 12.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\OWI\Segpart_15">OWI_SendByte</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_WriteBit0"><b>OWI_WriteBit0</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000005C6 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\OWI\Segpart_13"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000604 - 00000651<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\OWI\Segpart_16">OWI_ReceiveByte</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_ReadBit"><b>OWI_ReadBit</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000604 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\OWI\Segpart_14"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000652 - 000006A9<br>Segment part 14.</font>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_DetectPresence"><b>OWI_DetectPresence</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000652 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\OWI\Segpart_15"><b>CODE</b></a></b><br>Relative segment<br>CODE 000006AA - 000006D3<br>Segment part 15.</font>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_SendByte"><b>OWI_SendByte</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000006AA </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\OWI\Segpart_16"><b>CODE</b></a></b><br>Relative segment<br>CODE 000006D4 - 000006F7<br>Segment part 16.</font>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_ReceiveByte"><b>OWI_ReceiveByte</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000003 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000006D4 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\OWI\Segpart_21"><b>CODE</b></a></b><br>Relative segment<br>CODE 000006F8 - 00000729<br>Segment part 21.</font>\r
+  <td nowrap><font size=2><a name="MM\OWI\OWI_ComputeCRC8"><b>OWI_ComputeCRC8</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000006F8 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=28 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90</b></font>\r
+  <td rowspan=28><font size=2><a name="MM\PWM"><b>PWM</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_1"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000050 - 00000050<br>Segment part 1.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_TCCR1A"><b>_A_TCCR1A</b></a>\r
+</font>\r
+  <td><font size=2>00000050 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_2"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000004F - 0000004F<br>Segment part 2.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_TCCR1B"><b>_A_TCCR1B</b></a>\r
+</font>\r
+  <td><font size=2>0000004F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_3"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000004D - 0000004D<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_OCR1A"><b>_A_OCR1A</b></a>\r
+</font>\r
+  <td><font size=2>0000004D </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_4"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000004C - 0000004C<br>Segment part 4.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_20">BatteryStatusRefresh (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\PWM\Segpart_22">PWM_DecrementDutyCycle</a>\r
+<br><a href="#MM\PWM\Segpart_21">PWM_IncrementDutyCycle</a>\r
+<br><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_OCR1B"><b>_A_OCR1B</b></a>\r
+</font>\r
+  <td><font size=2>0000004C </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_5"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000004B - 0000004B<br>Segment part 5.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_OCR1C"><b>_A_OCR1C</b></a>\r
+</font>\r
+  <td><font size=2>0000004B </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_6"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000004A - 0000004A<br>Segment part 6.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_OCR1D"><b>_A_OCR1D</b></a>\r
+</font>\r
+  <td><font size=2>0000004A </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_7"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000049 - 00000049<br>Segment part 7.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_PLLCSR"><b>_A_PLLCSR</b></a>\r
+</font>\r
+  <td><font size=2>00000049 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_8"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000047 - 00000047<br>Segment part 8.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_TCCR1C"><b>_A_TCCR1C</b></a>\r
+</font>\r
+  <td><font size=2>00000047 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_9"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000046 - 00000046<br>Segment part 9.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_TCCR1D"><b>_A_TCCR1D</b></a>\r
+</font>\r
+  <td><font size=2>00000046 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_10"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000044 - 00000044<br>Segment part 10.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\PWM\Segpart_19">PWM_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_DT1"><b>_A_DT1</b></a>\r
+</font>\r
+  <td><font size=2>00000044 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_11"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000037 - 00000037<br>Segment part 11.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<br><a href="#MM\USI\Segpart_16">SPI_Init (USI)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_DDRB"><b>_A_DDRB</b></a>\r
+</font>\r
+  <td><font size=2>00000037 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\PWM\Segpart_12"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000020 - 00000020<br>Segment part 12.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\PWM\Segpart_20">PWM_Start</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\PWM\_A_TCCR1E"><b>_A_TCCR1E</b></a>\r
+</font>\r
+  <td><font size=2>00000020 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\PWM\Segpart_19"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000072A - 0000074F<br>Segment part 19.</font>\r
+  <td nowrap><font size=2><a name="MM\PWM\PWM_Stop"><b>PWM_Stop</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>0000072A </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\PWM\Segpart_20"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000750 - 000007A9<br>Segment part 20.</font>\r
+  <td nowrap><font size=2><a name="MM\PWM\PWM_Start"><b>PWM_Start</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000750 </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\PWM\Segpart_21"><b>CODE</b></a></b><br>Relative segment<br>CODE 000007AA - 000007BD<br>Segment part 21.</font>\r
+  <td nowrap><font size=2><a name="MM\PWM\PWM_IncrementDutyCycle"><b>PWM_IncrementDutyCycle</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000007AA </font>\r
+  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\PWM\Segpart_22"><b>CODE</b></a></b><br>Relative segment<br>CODE 000007BE - 000007D1<br>Segment part 22.</font>\r
+  <td nowrap><font size=2><a name="MM\PWM\PWM_DecrementDutyCycle"><b>PWM_DecrementDutyCycle</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000007BE </font>\r
+  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=16 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\USI.r90</b></font>\r
+  <td rowspan=16><font size=2><a name="MM\USI"><b>USI</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_1"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000038 - 00000038<br>Segment part 1.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_23">DisableBatteries (battery)</a>\r
+<br><a href="#MM\battery\Segpart_22">EnableBattery (battery)</a>\r
+<br><a href="#MM\USI\Segpart_16">SPI_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\_A_PORTB"><b>_A_PORTB</b></a>\r
+</font>\r
+  <td><font size=2>00000038 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_3"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000002F - 0000002F<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\USI\Segpart_17">SPI_Put</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\_A_USIDR"><b>_A_USIDR</b></a>\r
+</font>\r
+  <td><font size=2>0000002F </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_4"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000002E - 0000002E<br>Segment part 4.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\USI\Segpart_17">SPI_Put</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\_A_USISR"><b>_A_USISR</b></a>\r
+</font>\r
+  <td><font size=2>0000002E </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_5"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 0000002D - 0000002D<br>Segment part 5.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\USI\Segpart_16">SPI_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\_A_USICR"><b>_A_USICR</b></a>\r
+</font>\r
+  <td><font size=2>0000002D </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_13"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 0000015D - 00000160<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\USI\Segpart_16">SPI_Init</a>\r
+<br><a href="#MM\USI\Segpart_17">SPI_Put</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\SPI"><b>SPI</b></a>\r
+</font>\r
+  <td><font size=2>0000015D </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_15"><b>CODE</b></a></b><br>Relative segment<br>CODE 000007D2 - 000009E7<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\USI\Segpart_10">USI_OVF_ISR::??INTVEC 16</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\USI_OVF_ISR"><b>USI_OVF_ISR</b></a>\r
+<br>               interrupt function\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000011 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>000007D2 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\USI\Segpart_16"><b>CODE</b></a></b><br>Relative segment<br>CODE 000009E8 - 00000A4F<br>Segment part 16.</font>\r
+  <td nowrap><font size=2><a name="MM\USI\SPI_Init"><b>SPI_Init</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000009E8 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\USI\Segpart_17"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000A50 - 00000A81<br>Segment part 17.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\USI\Segpart_15">USI_OVF_ISR</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\USI\SPI_Put"><b>SPI_Put</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000A50 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\USI\Segpart_10"><b>INTVEC</b></a></b><br>Common segment<br>CODE 00000000 - 00000011<br>Segment part 10. ROOT.</font>\r
+  <td nowrap><font size=2><a name="MM\USI\USI_OVF_ISR::??INTVEC 16"><b>USI_OVF_ISR::??INTVEC 16</b></a>\r
+</font>\r
+  <td><font size=2>00000010 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=25 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\battery.r90</b></font>\r
+  <td rowspan=25><font size=2><a name="MM\battery"><b>battery</b></a><br>Program module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_9"><b>EEPROM_I</b></a></b><br>Relative segment<br>XDATA 00000001 - 00000002<br>Segment part 9.</font>\r
+  <td nowrap><font size=2><a name="MM\battery\BattControl"><b>BattControl</b></a>\r
+</font>\r
+  <td><font size=2>00000001 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_10"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000161 - 0000016C<br>Segment part 10.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_19">BatteryCheck</a>\r
+<br><a href="#MM\battery\Segpart_21">BatteryDataRefresh</a>\r
+<br><a href="#MM\battery\Segpart_20">BatteryStatusRefresh</a>\r
+<br><a href="#MM\battery\Segpart_25">NTCLookUp</a>\r
+<br><a href="#MM\battery\Segpart_24">RIDLookUp</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\BattData"><b>BattData</b></a>\r
+</font>\r
+  <td><font size=2>00000161 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_12"><b>EEPROM_I</b></a></b><br>Relative segment<br>XDATA 00000003 - 00000082<br>Segment part 12.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\BattEEPROM"><b>BattEEPROM</b></a>\r
+</font>\r
+  <td><font size=2>00000003 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_13"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 0000016D - 0000016D<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_22">EnableBattery</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\BattActive"><b>BattActive</b></a>\r
+</font>\r
+  <td><font size=2>0000016D </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_14"><b>NEAR_I</b></a></b><br>Relative segment<br>DATA 000000D0 - 00000107<br>Segment part 14.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_24">RIDLookUp</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\RID"><b>RID</b></a>\r
+</font>\r
+  <td><font size=2>000000D0 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_17"><b>NEAR_I</b></a></b><br>Relative segment<br>DATA 00000108 - 00000143<br>Segment part 17.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_25">NTCLookUp</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\NTC"><b>NTC</b></a>\r
+</font>\r
+  <td><font size=2>00000108 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_19"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000A82 - 00000AAD<br>Segment part 19.</font>\r
+  <td nowrap><font size=2><a name="MM\battery\BatteryCheck"><b>BatteryCheck</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000A82 </font>\r
+  <td><font size=2><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_20"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000AAE - 00000BA5<br>Segment part 20.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_19">BatteryCheck</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\BatteryStatusRefresh"><b>BatteryStatusRefresh</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000AAE </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_21"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000BA6 - 00000CBD<br>Segment part 21.</font>\r
+  <td nowrap><font size=2><a name="MM\battery\BatteryDataRefresh"><b>BatteryDataRefresh</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000008 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000BA6 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_22"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000CBE - 00000CFF<br>Segment part 22.</font>\r
+  <td nowrap><font size=2><a name="MM\battery\EnableBattery"><b>EnableBattery</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000001 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000CBE </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_23"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000D00 - 00000D07<br>Segment part 23.</font>\r
+  <td nowrap><font size=2><a name="MM\battery\DisableBatteries"><b>DisableBatteries</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00000D00 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_24"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000D08 - 00000E09<br>Segment part 24.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_20">BatteryStatusRefresh</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\RIDLookUp"><b>RIDLookUp</b></a>\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000D08 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_25"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000E0A - 00000EA9<br>Segment part 25.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_20">BatteryStatusRefresh</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\NTCLookUp"><b>NTCLookUp</b></a>\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000E0A </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_15"><b>NEAR_ID</b></a></b><br>Relative segment<br>CODE 0000186A - 000018A1<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_14">RID</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\battery\Segpart_16"><b>INITTAB</b></a></b><br>Relative segment<br>CODE 0000004A - 0000004F<br>Segment part 16.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_17">NTC</a>\r
+<br><a href="#MM\battery\Segpart_14">RID</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\battery\?&lt;Segment init: NEAR_I&gt;"><b>?&lt;Segment init: NEAR_I&gt;</b></a>\r
+</font>\r
+  <td><font size=2>0000004A </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\battery\Segpart_18"><b>NEAR_ID</b></a></b><br>Relative segment<br>CODE 000018A2 - 000018DD<br>Segment part 18.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\battery\Segpart_17">NTC</a>\r
+<tr valign=top>\r
+  <td rowspan=7 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\chargefunc.r90</b></font>\r
+  <td rowspan=7><font size=2><a name="MM\chargefunc"><b>chargefunc</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\chargefunc\Segpart_8"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 0000016E - 00000172<br>Segment part 8.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\chargefunc\ChargeParameters"><b>ChargeParameters</b></a>\r
+</font>\r
+  <td><font size=2>0000016E </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\chargefunc\Segpart_10"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000173 - 00000183<br>Segment part 10.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\chargefunc\Segpart_13">HaltNow</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\chargefunc\HaltParameters"><b>HaltParameters</b></a>\r
+</font>\r
+  <td><font size=2>00000173 </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\chargefunc\Segpart_11"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000EAA - 00000F5D<br>Segment part 11.</font>\r
+  <td nowrap><font size=2><a name="MM\chargefunc\ConstantCurrent"><b>ConstantCurrent</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000EAA </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\chargefunc\Segpart_13"><b>CODE</b></a></b><br>Relative segment<br>CODE 00000F5E - 0000115B<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\chargefunc\HaltNow"><b>HaltNow</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00000F5E </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=3 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90</b></font>\r
+  <td rowspan=3><font size=2><a name="MM\main"><b>main</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\main\Segpart_7"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000184 - 00000184<br>Segment part 7.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\main\Segpart_9">main</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\main\CurrentState"><b>CurrentState</b></a>\r
+</font>\r
+  <td><font size=2>00000184 </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_22">SetErrorFlag (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\main\Segpart_9"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000115C - 00001237<br>Segment part 9.</font>\r
+  <td nowrap><font size=2><a name="MM\main\main"><b>main</b></a>\r
+<br>               calls indirect\r
+<br>               stack 1 = 00000000 ( 00000007 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>0000115C </font>\r
+  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_9">?cstartup_call_main (?C_STARTUP)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\menu.r90</b></font>\r
+  <td rowspan=1><font size=2><a name="MM\menu"><b>menu</b></a><br>Program module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\menu\Segpart_7"><b>NEAR_F</b></a></b><br>Relative segment<br>CODE 00000026 - 00000043<br>Segment part 7.</font>\r
+  <td nowrap><font size=2><a name="MM\menu\menu_state"><b>menu_state</b></a>\r
+</font>\r
+  <td><font size=2>00000026 </font>\r
+  <td><font size=2><a href="#MM\main\Segpart_9">main (main)</a>\r
+<tr valign=top>\r
+  <td rowspan=23 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\statefunc.r90</b></font>\r
+  <td rowspan=23><font size=2><a name="MM\statefunc"><b>statefunc</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_1"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000055 - 00000055<br>Segment part 1.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_20">Doze</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\_A_MCUCR"><b>_A_MCUCR</b></a>\r
+</font>\r
+  <td><font size=2>00000055 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_2"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000054 - 00000054<br>Segment part 2.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_20">Doze</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\_A_MCUSR"><b>_A_MCUSR</b></a>\r
+</font>\r
+  <td><font size=2>00000054 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_3"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000048 - 00000048<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\_A_CLKPR"><b>_A_CLKPR</b></a>\r
+</font>\r
+  <td><font size=2>00000048 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_4"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000041 - 00000041<br>Segment part 4.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_20">Doze</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\_A_WDTCR"><b>_A_WDTCR</b></a>\r
+</font>\r
+  <td><font size=2>00000041 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_13"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000185 - 00000185<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_21">Error</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize</a>\r
+<br><a href="#MM\statefunc\Segpart_22">SetErrorFlag</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\ErrorFlags"><b>ErrorFlags</b></a>\r
+</font>\r
+  <td><font size=2>00000185 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_15"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000186 - 00000186<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_22">SetErrorFlag</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\ErrorState"><b>ErrorState</b></a>\r
+</font>\r
+  <td><font size=2>00000186 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\statefunc\Segpart_16"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001238 - 000012B1<br>Segment part 16.</font>\r
+  <td nowrap><font size=2><a name="MM\statefunc\Initialize"><b>Initialize</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000004 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>00001238 </font>\r
+  <td><font size=2><a href="#MM\menu\Segpart_7">menu_state (menu)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\statefunc\Segpart_17"><b>CODE</b></a></b><br>Relative segment<br>CODE 000012B2 - 0000131F<br>Segment part 17.</font>\r
+  <td nowrap><font size=2><a name="MM\statefunc\BatteryControl"><b>BatteryControl</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000003 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>000012B2 </font>\r
+  <td><font size=2><a href="#MM\menu\Segpart_7">menu_state (menu)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\statefunc\Segpart_18"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001320 - 00001325<br>Segment part 18.</font>\r
+  <td nowrap><font size=2><a name="MM\statefunc\Discharge"><b>Discharge</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001320 </font>\r
+  <td><font size=2><a href="#MM\menu\Segpart_7">menu_state (menu)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\statefunc\Segpart_19"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001326 - 00001357<br>Segment part 19.</font>\r
+  <td nowrap><font size=2><a name="MM\statefunc\Sleep"><b>Sleep</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000002 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001326 </font>\r
+  <td><font size=2><a href="#MM\menu\Segpart_7">menu_state (menu)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_20"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001358 - 000013AF<br>Segment part 20.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_21">Error</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\Doze"><b>Doze</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001358 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\statefunc\Segpart_21"><b>CODE</b></a></b><br>Relative segment<br>CODE 000013B0 - 0000147F<br>Segment part 21.</font>\r
+  <td nowrap><font size=2><a name="MM\statefunc\Error"><b>Error</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000002 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>000013B0 </font>\r
+  <td><font size=2><a href="#MM\menu\Segpart_7">menu_state (menu)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_22"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001480 - 00001493<br>Segment part 22.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\SetErrorFlag"><b>SetErrorFlag</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001480 </font>\r
+  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\statefunc\Segpart_23"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001494 - 00001515<br>Segment part 23.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\statefunc\JumperCheck"><b>JumperCheck</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001494 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=20 ><font size=2><b>C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\time.r90</b></font>\r
+  <td rowspan=20><font size=2><a name="MM\time"><b>time</b></a><br>Program module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_1"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000059 - 00000059<br>Segment part 1.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_20">Time_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\_A_TIMSK"><b>_A_TIMSK</b></a>\r
+</font>\r
+  <td><font size=2>00000059 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_2"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000053 - 00000053<br>Segment part 2.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_20">Time_Init</a>\r
+<br><a href="#MM\time\Segpart_19">Time_Start</a>\r
+<br><a href="#MM\time\Segpart_18">Time_Stop</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\_A_TCCR0B"><b>_A_TCCR0B</b></a>\r
+</font>\r
+  <td><font size=2>00000053 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_3"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000035 - 00000035<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_20">Time_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\_A_TCCR0A"><b>_A_TCCR0A</b></a>\r
+</font>\r
+  <td><font size=2>00000035 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_4"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000033 - 00000033<br>Segment part 4.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_20">Time_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\_A_OCR0A"><b>_A_OCR0A</b></a>\r
+</font>\r
+  <td><font size=2>00000033 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_5"><b>ABSOLUTE</b></a></b><br>Relative segment<br>DATA 00000032 - 00000032<br>Segment part 5.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_20">Time_Init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\_A_OCR0B"><b>_A_OCR0B</b></a>\r
+</font>\r
+  <td><font size=2>00000032 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_13"><b>NEAR_Z</b></a></b><br>Relative segment<br>DATA 00000187 - 00000196<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_15">TICK_ISR</a>\r
+<br><a href="#MM\time\Segpart_20">Time_Init</a>\r
+<br><a href="#MM\time\Segpart_16">Time_Left</a>\r
+<br><a href="#MM\time\Segpart_17">Time_Set</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\timeval"><b>timeval</b></a>\r
+</font>\r
+  <td><font size=2>00000187 </font>\r
+  <td><font size=2><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\time\Segpart_15"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001516 - 0000159D<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\time\Segpart_10">TICK_ISR::??INTVEC 28</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\time\TICK_ISR"><b>TICK_ISR</b></a>\r
+<br>               interrupt function\r
+<br>               stack 1 = 00000000 ( 0000000B )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001516 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\time\Segpart_16"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000159E - 000015C9<br>Segment part 16.</font>\r
+  <td nowrap><font size=2><a name="MM\time\Time_Left"><b>Time_Left</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>0000159E </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_22">EnableBattery (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<br><a href="#MM\PWM\Segpart_20">PWM_Start (PWM)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\time\Segpart_17"><b>CODE</b></a></b><br>Relative segment<br>CODE 000015CA - 0000166F<br>Segment part 17.</font>\r
+  <td nowrap><font size=2><a name="MM\time\Time_Set"><b>Time_Set</b></a>\r
+<br>               stack 1 = 00000000 ( 00000007 )\r
+<br>               stack 2 = 00000000 ( 00000004 )\r
+</font>\r
+  <td><font size=2>000015CA </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\battery\Segpart_22">EnableBattery (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<br><a href="#MM\PWM\Segpart_20">PWM_Start (PWM)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\time\Segpart_18"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001670 - 00001675<br>Segment part 18.</font>\r
+  <td nowrap><font size=2><a name="MM\time\Time_Stop"><b>Time_Stop</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001670 </font>\r
+  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\time\Segpart_19"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001676 - 0000167B<br>Segment part 19.</font>\r
+  <td nowrap><font size=2><a name="MM\time\Time_Start"><b>Time_Start</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001676 </font>\r
+  <td><font size=2><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\time\Segpart_20"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000167C - 000016C1<br>Segment part 20.</font>\r
+  <td nowrap><font size=2><a name="MM\time\Time_Init"><b>Time_Init</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>0000167C </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\time\Segpart_10"><b>INTVEC</b></a></b><br>Common segment<br>CODE 00000000 - 0000001D<br>Segment part 10. ROOT.</font>\r
+  <td nowrap><font size=2><a name="MM\time\TICK_ISR::??INTVEC 28"><b>TICK_ISR::??INTVEC 28</b></a>\r
+</font>\r
+  <td><font size=2>0000001C </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=71 ><font size=2><b>C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90</b></font>\r
+  <td rowspan=5><font size=2><a name="MM\?__exit"><b>?__exit</b></a><br>Library module</font>\r
+  <td rowspan=5 ><font size=2><b><a name="MM\?__exit\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016C2 - 000016C7<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?__exit\__exit"><b>__exit</b></a>\r
+</font>\r
+  <td><font size=2>000016C4 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?__exit\?C_EXIT"><b>?C_EXIT</b></a>\r
+</font>\r
+  <td><font size=2>000016C4 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?__exit\?C_FUNCALL"><b>?C_FUNCALL</b></a>\r
+</font>\r
+  <td><font size=2>000016C2 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?__exit\_exit"><b>_exit</b></a>\r
+</font>\r
+  <td><font size=2>000016C2 </font>\r
+  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_9">?cstartup_call_main (?C_STARTUP)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?__exit\exit"><b>exit</b></a>\r
+</font>\r
+  <td><font size=2>000016C2 </font>\r
+  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_9">?cstartup_call_main (?C_STARTUP)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?abs"><b>?abs</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?abs\Segpart_3"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016C8 - 000016D7<br>Segment part 3.</font>\r
+  <td nowrap><font size=2><a name="MM\?abs\abs"><b>abs</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>000016C8 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_23">JumperCheck (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2><font size=2><a name="MM\?RESET"><b>?RESET</b></a><br>Library module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?RESET\Segpart_0"><b>INTVEC</b></a></b><br>Common segment<br>CODE 00000000 - 00000001<br>Segment part 0. ROOT.</font>\r
+  <td nowrap><font size=2><a name="MM\?RESET\__program_start"><b>__program_start</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td><font size=2><a href="#MM\?ABS_ENTRY_MOD\Absparts">Absolute parts (?ABS_ENTRY_MOD)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?RESET\?RESET"><b>?RESET</b></a>\r
+</font>\r
+  <td><font size=2>00000000 </font>\r
+  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_2">Segment part 2 (?C_STARTUP)</a>\r
+<tr valign=top>\r
+  <td rowspan=8><font size=2><a name="MM\?C_STARTUP"><b>?C_STARTUP</b></a><br>Library module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?C_STARTUP\Segpart_2"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016D8 <br>Segment part 2.</font>\r
+  <td nowrap><font size=2><a name="MM\?C_STARTUP\?C_STARTUP"><b>?C_STARTUP</b></a>\r
+</font>\r
+  <td><font size=2>000016D8 </font>\r
+  <td><font size=2><a href="#MM\?RESET\Segpart_0">Segment part 0 (?RESET)</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?C_STARTUP\__RESTART"><b>__RESTART</b></a>\r
+</font>\r
+  <td><font size=2>000016D8 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?C_STARTUP\Segpart_5"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016D8 - 000016E3<br>Segment part 5.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_2">Segment part 2</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?C_STARTUP\Segpart_7"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016E4 - 000016E5<br>Segment part 7.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_5">Segment part 5</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?C_STARTUP\?call_low_level_init"><b>?call_low_level_init</b></a>\r
+</font>\r
+  <td><font size=2>000016E4 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?C_STARTUP\Segpart_8"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016E6 - 000016EB<br>Segment part 8.</font>\r
+  <td nowrap><font size=2><a name="MM\?C_STARTUP\?need_segment_init"><b>?need_segment_init</b></a>\r
+</font>\r
+  <td><font size=2>000016E6 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_16">?&lt;Segment init: NEAR_I&gt; (battery)</a>\r
+<br><a href="#MM\ADC\Segpart_15">?&lt;Segment init: NEAR_Z&gt; (ADC)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?C_STARTUP\Segpart_9"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016EC - 000016F1<br>Segment part 9.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_7">?call_low_level_init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?C_STARTUP\?cstartup_call_main"><b>?cstartup_call_main</b></a>\r
+</font>\r
+  <td><font size=2>000016EC </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=5><font size=2><a name="MM\?EEPROM_16"><b>?EEPROM_16</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?EEPROM_16\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016F2 - 000016F7<br>Segment part 0.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_1">Segment part 1</a>\r
+<br><a href="#MM\?EEPROM_16\Segpart_10">__eeput8_16</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?EEPROM_16\Segpart_1"><b>CODE</b></a></b><br>Relative segment<br>CODE 000016F8 - 00001705<br>Segment part 1.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_3">__eeget8_16</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?EEPROM_16\Segpart_3"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001706 - 0000170B<br>Segment part 3.</font>\r
+  <td nowrap><font size=2><a name="MM\?EEPROM_16\__eeget8_16"><b>__eeget8_16</b></a>\r
+</font>\r
+  <td><font size=2>00001706 </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR (ADC)</a>\r
+<br><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?EEPROM_16\Segpart_8"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000170C - 0000171D<br>Segment part 8.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EEPROM_16\Segpart_10">__eeput8_16</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?EEPROM_16\Segpart_10"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000171E - 00001725<br>Segment part 10.</font>\r
+  <td nowrap><font size=2><a name="MM\?EEPROM_16\__eeput8_16"><b>__eeput8_16</b></a>\r
+</font>\r
+  <td><font size=2>0000171E </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\USI\Segpart_15">USI_OVF_ISR (USI)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?S_MUL_L02"><b>?S_MUL_L02</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?S_MUL_L02\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001726 - 00001745<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?S_MUL_L02\?S_MUL_L02"><b>?S_MUL_L02</b></a>\r
+</font>\r
+  <td><font size=2>00001726 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\battery\Segpart_25">NTCLookUp (battery)</a>\r
+<br><a href="#MM\battery\Segpart_24">RIDLookUp (battery)</a>\r
+<br><a href="#MM\ADC\Segpart_20">ScaleI (ADC)</a>\r
+<br><a href="#MM\ADC\Segpart_19">ScaleU (ADC)</a>\r
+<br><a href="#MM\main\Segpart_9">main (main)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?S_SHL_L02"><b>?S_SHL_L02</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?S_SHL_L02\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001746 - 00001751<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?S_SHL_L02\?S_SHL_L02"><b>?S_SHL_L02</b></a>\r
+</font>\r
+  <td><font size=2>00001746 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_22">EnableBattery (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?US_SHR_L02"><b>?US_SHR_L02</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?US_SHR_L02\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001752 - 0000175D<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?US_SHR_L02\?US_SHR_L02"><b>?US_SHR_L02</b></a>\r
+</font>\r
+  <td><font size=2>00001752 </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_20">ScaleI (ADC)</a>\r
+<br><a href="#MM\ADC\Segpart_19">ScaleU (ADC)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?US_DIVMOD_L02"><b>?US_DIVMOD_L02</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?US_DIVMOD_L02\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000175E - 00001785<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?US_DIVMOD_L02\?US_DIVMOD_L02"><b>?US_DIVMOD_L02</b></a>\r
+</font>\r
+  <td><font size=2>0000175E </font>\r
+  <td><font size=2><a href="#MM\?SS_DIVMOD_L02\Segpart_0">?SS_DIVMOD_L02 (?SS_DIVMOD_L02)</a>\r
+<br><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\battery\Segpart_25">NTCLookUp (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?SS_DIVMOD_L02"><b>?SS_DIVMOD_L02</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?SS_DIVMOD_L02\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001786 - 000017B3<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?SS_DIVMOD_L02\?SS_DIVMOD_L02"><b>?SS_DIVMOD_L02</b></a>\r
+</font>\r
+  <td><font size=2>0000178E </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR (ADC)</a>\r
+<br><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?L_MUL_L03"><b>?L_MUL_L03</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?L_MUL_L03\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017B4 - 000017E5<br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?L_MUL_L03\?L_MUL_L03"><b>?L_MUL_L03</b></a>\r
+</font>\r
+  <td><font size=2>000017B4 </font>\r
+  <td><font size=2><a href="#MM\time\Segpart_17">Time_Set (time)</a>\r
+<tr valign=top>\r
+  <td rowspan=16><font size=2><a name="MM\?PROLOGUE_L09"><b>?PROLOGUE_L09</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_8"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017E6 - 000017E7<br>Segment part 8.</font>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE8_L09"><b>?PROLOGUE8_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017E6 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_9"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017E8 - 000017E9<br>Segment part 9.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_8">?PROLOGUE8_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE7_L09"><b>?PROLOGUE7_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017E8 </font>\r
+  <td><font size=2><a href="#MM\time\Segpart_17">Time_Set (time)</a>\r
+<br><a href="#MM\main\Segpart_9">main (main)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_10"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017EA - 000017EB<br>Segment part 10.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_9">?PROLOGUE7_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE6_L09"><b>?PROLOGUE6_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017EA </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_20">ScaleI (ADC)</a>\r
+<br><a href="#MM\ADC\Segpart_19">ScaleU (ADC)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_11"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017EC - 000017ED<br>Segment part 11.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_10">?PROLOGUE6_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE5_L09"><b>?PROLOGUE5_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017EC </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_12"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017EE - 000017EF<br>Segment part 12.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_11">?PROLOGUE5_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE4_L09"><b>?PROLOGUE4_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017EE </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_19">BatteryCheck (battery)</a>\r
+<br><a href="#MM\battery\Segpart_20">BatteryStatusRefresh (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\battery\Segpart_25">NTCLookUp (battery)</a>\r
+<br><a href="#MM\OWI\Segpart_15">OWI_SendByte (OWI)</a>\r
+<br><a href="#MM\battery\Segpart_24">RIDLookUp (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_13"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017F0 - 000017F1<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_12">?PROLOGUE4_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE3_L09"><b>?PROLOGUE3_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017F0 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\OWI\Segpart_16">OWI_ReceiveByte (OWI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_14"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017F2 - 000017F3<br>Segment part 14.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_13">?PROLOGUE3_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE2_L09"><b>?PROLOGUE2_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017F2 </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_15"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017F4 - 000017F5<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_14">?PROLOGUE2_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?PROLOGUE_L09\?PROLOGUE1_L09"><b>?PROLOGUE1_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017F4 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?PROLOGUE_L09\Segpart_16"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017F6 - 000017F7<br>Segment part 16.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?PROLOGUE_L09\Segpart_15">?PROLOGUE1_L09</a>\r
+<tr valign=top>\r
+  <td rowspan=17><font size=2><a name="MM\?EPILOGUE_B_L09"><b>?EPILOGUE_B_L09</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_8"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017F8 - 000017F9<br>Segment part 8.</font>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B8_L09"><b>?EPILOGUE_B8_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017F8 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_9"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017FA - 000017FB<br>Segment part 9.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_8">?EPILOGUE_B8_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B7_L09"><b>?EPILOGUE_B7_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017FA </font>\r
+  <td><font size=2><a href="#MM\time\Segpart_17">Time_Set (time)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_10"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017FC - 000017FD<br>Segment part 10.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_9">?EPILOGUE_B7_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B6_L09"><b>?EPILOGUE_B6_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017FC </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_20">ScaleI (ADC)</a>\r
+<br><a href="#MM\ADC\Segpart_19">ScaleU (ADC)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_11"><b>CODE</b></a></b><br>Relative segment<br>CODE 000017FE - 000017FF<br>Segment part 11.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_10">?EPILOGUE_B6_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B5_L09"><b>?EPILOGUE_B5_L09</b></a>\r
+</font>\r
+  <td><font size=2>000017FE </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_12"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001800 - 00001801<br>Segment part 12.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_11">?EPILOGUE_B5_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B4_L09"><b>?EPILOGUE_B4_L09</b></a>\r
+</font>\r
+  <td><font size=2>00001800 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_19">BatteryCheck (battery)</a>\r
+<br><a href="#MM\battery\Segpart_20">BatteryStatusRefresh (battery)</a>\r
+<br><a href="#MM\chargefunc\Segpart_11">ConstantCurrent (chargefunc)</a>\r
+<br><a href="#MM\chargefunc\Segpart_13">HaltNow (chargefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_16">Initialize (statefunc)</a>\r
+<br><a href="#MM\battery\Segpart_25">NTCLookUp (battery)</a>\r
+<br><a href="#MM\OWI\Segpart_15">OWI_SendByte (OWI)</a>\r
+<br><a href="#MM\battery\Segpart_24">RIDLookUp (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_13"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001802 - 00001803<br>Segment part 13.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_12">?EPILOGUE_B4_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B3_L09"><b>?EPILOGUE_B3_L09</b></a>\r
+</font>\r
+  <td><font size=2>00001802 </font>\r
+  <td><font size=2><a href="#MM\statefunc\Segpart_17">BatteryControl (statefunc)</a>\r
+<br><a href="#MM\OWI\Segpart_16">OWI_ReceiveByte (OWI)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_14"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001804 - 00001805<br>Segment part 14.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_13">?EPILOGUE_B3_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B2_L09"><b>?EPILOGUE_B2_L09</b></a>\r
+</font>\r
+  <td><font size=2>00001804 </font>\r
+  <td><font size=2><a href="#MM\NIMHcharge\Segpart_7">Charge (NIMHcharge)</a>\r
+<br><a href="#MM\statefunc\Segpart_21">Error (statefunc)</a>\r
+<br><a href="#MM\statefunc\Segpart_19">Sleep (statefunc)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_15"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001806 - 00001807<br>Segment part 15.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_14">?EPILOGUE_B2_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B1_L09"><b>?EPILOGUE_B1_L09</b></a>\r
+</font>\r
+  <td><font size=2>00001806 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?EPILOGUE_B_L09\Segpart_16"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001808 - 00001815<br>Segment part 16.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?EPILOGUE_B_L09\Segpart_15">?EPILOGUE_B1_L09</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?EPILOGUE_B_L09\?EPILOGUE_B0_L09"><b>?EPILOGUE_B0_L09</b></a>\r
+</font>\r
+  <td><font size=2>00001808 </font>\r
+  <td align=center><font size=2>-</font>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?REGISTER_CGREGR4_L10"><b>?REGISTER_CGREGR4_L10</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?REGISTER_CGREGR4_L10\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001816 <br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?REGISTER_CGREGR4_L10\?Register_R4_is_cg_reg"><b>?Register_R4_is_cg_reg</b></a>\r
+</font>\r
+  <td><font size=2>00001816 </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR (ADC)</a>\r
+<br><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<br><a href="#MM\ADC\Segpart_20">ScaleI (ADC)</a>\r
+<br><a href="#MM\ADC\Segpart_19">ScaleU (ADC)</a>\r
+<br><a href="#MM\time\Segpart_17">Time_Set (time)</a>\r
+<br><a href="#MM\main\Segpart_9">main (main)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?REGISTER_CGREGR5_L10"><b>?REGISTER_CGREGR5_L10</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?REGISTER_CGREGR5_L10\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001816 <br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?REGISTER_CGREGR5_L10\?Register_R5_is_cg_reg"><b>?Register_R5_is_cg_reg</b></a>\r
+</font>\r
+  <td><font size=2>00001816 </font>\r
+  <td><font size=2><a href="#MM\ADC\Segpart_18">ADC_ISR (ADC)</a>\r
+<br><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<br><a href="#MM\ADC\Segpart_20">ScaleI (ADC)</a>\r
+<br><a href="#MM\ADC\Segpart_19">ScaleU (ADC)</a>\r
+<br><a href="#MM\time\Segpart_17">Time_Set (time)</a>\r
+<br><a href="#MM\main\Segpart_9">main (main)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?REGISTER_CGREGR6_L10"><b>?REGISTER_CGREGR6_L10</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?REGISTER_CGREGR6_L10\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001816 <br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?REGISTER_CGREGR6_L10\?Register_R6_is_cg_reg"><b>?Register_R6_is_cg_reg</b></a>\r
+</font>\r
+  <td><font size=2>00001816 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<br><a href="#MM\time\Segpart_17">Time_Set (time)</a>\r
+<br><a href="#MM\main\Segpart_9">main (main)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?REGISTER_CGREGR7_L10"><b>?REGISTER_CGREGR7_L10</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?REGISTER_CGREGR7_L10\Segpart_0"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001816 <br>Segment part 0.</font>\r
+  <td nowrap><font size=2><a name="MM\?REGISTER_CGREGR7_L10\?Register_R7_is_cg_reg"><b>?Register_R7_is_cg_reg</b></a>\r
+</font>\r
+  <td><font size=2>00001816 </font>\r
+  <td><font size=2><a href="#MM\battery\Segpart_21">BatteryDataRefresh (battery)</a>\r
+<tr valign=top>\r
+  <td rowspan=1><font size=2><a name="MM\?low_level_init"><b>?low_level_init</b></a><br>Library module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?low_level_init\Segpart_3"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001816 - 00001819<br>Segment part 3.</font>\r
+  <td nowrap><font size=2><a name="MM\?low_level_init\__low_level_init"><b>__low_level_init</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001816 </font>\r
+  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_7">?call_low_level_init (?C_STARTUP)</a>\r
+<tr valign=top>\r
+  <td rowspan=6><font size=2><a name="MM\?segment_init"><b>?segment_init</b></a><br>Library module</font>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?segment_init\Segpart_3"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000181A - 00001821<br>Segment part 3.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?segment_init\Segpart_6">__segment_init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?segment_init\__memclr"><b>__memclr</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>0000181A </font>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b><a name="MM\?segment_init\Segpart_4"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001822 - 00001829<br>Segment part 4.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?segment_init\Segpart_6">__segment_init</a>\r
+<tr valign=top>\r
+  <td nowrap><font size=2><a name="MM\?segment_init\__flashcpy"><b>__flashcpy</b></a>\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001822 </font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?segment_init\Segpart_5"><b>CODE</b></a></b><br>Relative segment<br>CODE 0000182A - 00001835<br>Segment part 5.</font>\r
+  <td><font size=2>  <i><font size=2>Intra module refs</font>\r
+  <td><font size=2>&nbsp;  <td><font size=2><a href="#MM\?segment_init\Segpart_4">__flashcpy</a>\r
+<br><a href="#MM\?segment_init\Segpart_3">__memclr</a>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?segment_init\Segpart_6"><b>CODE</b></a></b><br>Relative segment<br>CODE 00001836 - 00001869<br>Segment part 6.</font>\r
+  <td nowrap><font size=2><a name="MM\?segment_init\__segment_init"><b>__segment_init</b></a>\r
+<br>               calls direct\r
+<br>               stack 1 = 00000000 ( 00000000 )\r
+<br>               stack 2 = 00000000 ( 00000002 )\r
+</font>\r
+  <td><font size=2>00001836 </font>\r
+  <td><font size=2><a href="#MM\?C_STARTUP\Segpart_8">?need_segment_init (?C_STARTUP)</a>\r
+<tr valign=top>\r
+  <td rowspan=2 ><font size=2><b></b></font>\r
+  <td rowspan=2><font size=2><a name="MM\?FILLER_BYTES"><b>?FILLER_BYTES</b></a><br>Program module</font>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?FILLER_BYTES\Segpart_1"><b>INTVEC</b></a></b><br>Common segment<br>CODE 00000000 - 0000001D<br>Segment part 1.</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2><b><a name="MM\?FILLER_BYTES\Segpart_0"><b>?FILL1</b></a></b><br>Relative segment<br>CODE 0000001E - 00000025<br>Segment part 0.</font>\r
+</table>\r
+\r
+\r
+<p><hr><p>\r
+<h2><a name="Module Summary">Module Summary</a></h2>\r
+\r
+\r
+<table bgcolor="#d0d0d0" border=1 cellpadding=2>\r
+<tr>\r
+<th align=left valign=top><font size=2>Module</font></th>\r
+<th align=right valign=top><font size=2>CODE</font></th>\r
+<th colspan=2 valign=top><font size=2>DATA</font></th>\r
+<th align=right valign=top><font size=2>XDATA</font></th>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>(Rel)</font></td>\r
+<td align=right valign=top><font size=2>(Rel)</font></td>\r
+<td align=right valign=top><font size=2>(Abs)</font></td>\r
+<td align=right valign=top><font size=2>(Rel)</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?C_STARTUP</font></td>\r
+<td align=right valign=top><font size=2>26</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?EEPROM_16</font></td>\r
+<td align=right valign=top><font size=2>52</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?EPILOGUE_B_L09</font></td>\r
+<td align=right valign=top><font size=2>30</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?FILLER_BYTES<br>&nbsp;&nbsp;+&nbsp;common</font></td>\r
+<td align=right valign=top><font size=2>8<br>30</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?L_MUL_L03</font></td>\r
+<td align=right valign=top><font size=2>50</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?PROLOGUE_L09</font></td>\r
+<td align=right valign=top><font size=2>18</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?RESET<br>&nbsp;&nbsp;+&nbsp;common</font></td>\r
+<td align=right valign=top><font size=2><br>2</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?SS_DIVMOD_L02</font></td>\r
+<td align=right valign=top><font size=2>46</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?S_MUL_L02</font></td>\r
+<td align=right valign=top><font size=2>32</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?S_SHL_L02</font></td>\r
+<td align=right valign=top><font size=2>12</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?US_DIVMOD_L02</font></td>\r
+<td align=right valign=top><font size=2>40</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?US_SHR_L02</font></td>\r
+<td align=right valign=top><font size=2>12</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?__exit</font></td>\r
+<td align=right valign=top><font size=2>6</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?abs</font></td>\r
+<td align=right valign=top><font size=2>16</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?low_level_init</font></td>\r
+<td align=right valign=top><font size=2>4</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>?segment_init</font></td>\r
+<td align=right valign=top><font size=2>80</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>ADC<br>&nbsp;&nbsp;+&nbsp;shared<br>&nbsp;&nbsp;+&nbsp;common</font></td>\r
+<td align=right valign=top><font size=2>946<br>6<br>24</font></td>\r
+<td align=right valign=top><font size=2>25</font></td>\r
+<td align=right valign=top><font size=2>4<br>3</font></td>\r
+<td align=right valign=top><font size=2>1</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>NIMHcharge</font></td>\r
+<td align=right valign=top><font size=2>356</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>OWI</font></td>\r
+<td align=right valign=top><font size=2>452</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>1</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>PWM<br>&nbsp;&nbsp;+&nbsp;shared</font></td>\r
+<td align=right valign=top><font size=2>168</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>10<br>2</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>USI<br>&nbsp;&nbsp;+&nbsp;shared<br>&nbsp;&nbsp;+&nbsp;common</font></td>\r
+<td align=right valign=top><font size=2>688<br>18</font></td>\r
+<td align=right valign=top><font size=2>4</font></td>\r
+<td align=right valign=top><font size=2>3<br>1</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>battery</font></td>\r
+<td align=right valign=top><font size=2>1&nbsp;186</font></td>\r
+<td align=right valign=top><font size=2>129</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>130</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>chargefunc</font></td>\r
+<td align=right valign=top><font size=2>690</font></td>\r
+<td align=right valign=top><font size=2>22</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>main</font></td>\r
+<td align=right valign=top><font size=2>220</font></td>\r
+<td align=right valign=top><font size=2>1</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>menu</font></td>\r
+<td align=right valign=top><font size=2>30</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>statefunc</font></td>\r
+<td align=right valign=top><font size=2>734</font></td>\r
+<td align=right valign=top><font size=2>2</font></td>\r
+<td align=right valign=top><font size=2>4</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>time<br>&nbsp;&nbsp;+&nbsp;common</font></td>\r
+<td align=right valign=top><font size=2>428<br>30</font></td>\r
+<td align=right valign=top><font size=2>16</font></td>\r
+<td align=right valign=top><font size=2>5</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>N/A&nbsp;(command&nbsp;line)</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>112</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<td valign=top><font size=2>N/A&nbsp;(alignment)</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+<td align=right valign=top><font size=2>&nbsp;</font></td>\r
+</tr>\r
+<tr>\r
+<th align=left valign=top><font size=2>Total:<br>&nbsp;&nbsp;+&nbsp;common</font></th>\r
+<th align=right valign=top><font size=2>6&nbsp;336<br>30</font></th>\r
+<th align=right valign=top><font size=2>311</font></th>\r
+<th align=right valign=top><font size=2>33</font></th>\r
+<th align=right valign=top><font size=2>131</font></th>\r
+</tr>\r
+</table>\r
+<p><hr><p>\r
+<a name="Call Graph"></a>\r
+<table bgcolor="#9fd975" border=1 cellpadding=2>\r
+<tr>\r
+  <th align=center colspan=8><font size=4><B>Call Graph</B>\r
+</font>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Interrupt function tree that does not make<br>indirect calls</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ScaleI">ScaleI</a> <a name="CG\00025238"><b>*</b></a></font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ScaleI">ScaleI</a> (<a href="#CG\00025238">to first</a>)</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ScaleU">ScaleU</a> <a name="CG\000252E4"><b>*</b></a></font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ScaleU">ScaleU</a> (<a href="#CG\000252E4">to first</a>)</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\ADC\ADC_ISR">ADC_ISR</a> <a name="CG\00024C30"><b>*</b></a></font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>14</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Interrupt function tree that does not make<br>indirect calls</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Set">Time_Set</a> <a name="CG\0014C9AC"><b>*</b></a></font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Left">Time_Left</a> <a name="CG\0014C900"><b>*</b></a></font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> <a name="CG\00148900"><b>*</b></a></font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Put">SPI_Put</a> (<a href="#CG\00148900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\USI\USI_OVF_ISR">USI_OVF_ISR</a> <a name="CG\00148A58"><b>*</b></a></font>\r
+  <td align=right><font size=2>21</font>\r
+  <td align=right><font size=2>A</font>\r
+  <td align=right><font size=2>11</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>32</font>\r
+  <td align=right><font size=2>C</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Interrupt function tree that does not make<br>indirect calls</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>32</font>\r
+  <td align=right><font size=2>C</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\time\TICK_ISR">TICK_ISR</a> <a name="CG\0014C7A8"><b>*</b></a></font>\r
+  <td align=right><font size=2>32</font>\r
+  <td align=right><font size=2>C</font>\r
+  <td align=right><font size=2>B</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Indirectly called function tree that does not make<br>indirect calls (Is not an interrupt and is not flagged<br>as not overlayable)</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Set">Time_Set</a> (<a href="#CG\0014C9AC">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Start">Time_Start</a> <a name="CG\0014CA58"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Stop">Time_Stop</a> <a name="CG\0014CB04"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\SetErrorFlag">SetErrorFlag</a> <a name="CG\0014BAB8"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Set">Time_Set</a> (<a href="#CG\0014C9AC">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Left">Time_Left</a> (<a href="#CG\0014C900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\SetErrorFlag">SetErrorFlag</a> (<a href="#CG\0014BAB8">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>6</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\NTCLookUp">NTCLookUp</a> <a name="CG\001498DC"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>6</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\RIDLookUp">RIDLookUp</a> <a name="CG\00149988"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>5</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\BatteryStatusRefresh">BatteryStatusRefresh</a> <a name="CG\001496D8"><b>*</b></a></font>\r
+  <td align=right><font size=2>41</font>\r
+  <td align=right><font size=2>12</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\BatteryCheck">BatteryCheck</a> <a name="CG\00149580"><b>*</b></a></font>\r
+  <td align=right><font size=2>45</font>\r
+  <td align=right><font size=2>14</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_Stop">PWM_Stop</a> <a name="CG\00147998"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> <a name="CG\0002518C"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\chargefunc\HaltNow">HaltNow</a> <a name="CG\0014A1AC"><b>*</b></a></font>\r
+  <td align=right><font size=2>49</font>\r
+  <td align=right><font size=2>16</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_DecrementDutyCycle">PWM_DecrementDutyCycle</a> <a name="CG\00147794"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_IncrementDutyCycle">PWM_IncrementDutyCycle</a> <a name="CG\00147840"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\chargefunc\ConstantCurrent">ConstantCurrent</a> <a name="CG\0014A054"><b>*</b></a></font>\r
+  <td align=right><font size=2>4D</font>\r
+  <td align=right><font size=2>18</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Set">Time_Set</a> (<a href="#CG\0014C9AC">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Left">Time_Left</a> (<a href="#CG\0014C900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_Start">PWM_Start</a> <a name="CG\001478EC"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_Stop">PWM_Stop</a> (<a href="#CG\00147998">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\NIMHcharge\Charge">Charge</a> <a name="CG\00026374"><b>*</b></a></font>\r
+  <td align=right><font size=2>51</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>2</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>53</font>\r
+  <td align=right><font size=2>1C</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Indirectly called function tree that does not make<br>indirect calls (Is not an interrupt and is not flagged<br>as not overlayable)</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Init">Time_Init</a> <a name="CG\0014C854"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\DisableBatteries">DisableBatteries</a> <a name="CG\00149784"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Set">Time_Set</a> (<a href="#CG\0014C9AC">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Left">Time_Left</a> (<a href="#CG\0014C900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\EnableBattery">EnableBattery</a> <a name="CG\00149830"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>1</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\BatteryStatusRefresh">BatteryStatusRefresh</a> (<a href="#CG\001496D8">to first</a>)</font>\r
+  <td align=right><font size=2>41</font>\r
+  <td align=right><font size=2>12</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\USI\SPI_Init">SPI_Init</a> <a name="CG\00148854"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_Init">OWI_Init</a> <a name="CG\00027814"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Init">ADC_Init</a> <a name="CG\000250E0"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>1</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\statefunc\Initialize">Initialize</a> <a name="CG\0014B960"><b>*</b></a></font>\r
+  <td align=right><font size=2>45</font>\r
+  <td align=right><font size=2>14</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>49</font>\r
+  <td align=right><font size=2>16</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Indirectly called function tree that does not make<br>indirect calls (Is not an interrupt and is not flagged<br>as not overlayable)</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\?abs\abs">abs</a> <a name="CG\00265AA0"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Set">Time_Set</a> (<a href="#CG\0014C9AC">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\time\Time_Left">Time_Left</a> (<a href="#CG\0014C900">to first</a>)</font>\r
+  <td align=right><font size=2>1A</font>\r
+  <td align=right><font size=2>6</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\DisableBatteries">DisableBatteries</a> (<a href="#CG\00149784">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_IncrementDutyCycle">PWM_IncrementDutyCycle</a> (<a href="#CG\00147840">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_Start">PWM_Start</a> (<a href="#CG\001478EC">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_Stop">PWM_Stop</a> (<a href="#CG\00147998">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\JumperCheck">JumperCheck</a> <a name="CG\0014BA0C"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\SetErrorFlag">SetErrorFlag</a> (<a href="#CG\0014BAB8">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\DisableBatteries">DisableBatteries</a> (<a href="#CG\00149784">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\EnableBattery">EnableBattery</a> (<a href="#CG\00149830">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>1</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_ComputeCRC8">OWI_ComputeCRC8</a> <a name="CG\000276BC"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_ReadBit">OWI_ReadBit</a> <a name="CG\0002796C"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_ReceiveByte">OWI_ReceiveByte</a> <a name="CG\00027AC4"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>3</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_WriteBit0">OWI_WriteBit0</a> <a name="CG\00027D74"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>4</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_WriteBit1">OWI_WriteBit1</a> <a name="CG\00027E20"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_SendByte">OWI_SendByte</a> <a name="CG\00027C1C"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\OWI\OWI_DetectPresence">OWI_DetectPresence</a> <a name="CG\00027768"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\BatteryDataRefresh">BatteryDataRefresh</a> <a name="CG\0014962C"><b>*</b></a></font>\r
+  <td align=right><font size=2>41</font>\r
+  <td align=right><font size=2>12</font>\r
+  <td align=right><font size=2>8</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\BatteryStatusRefresh">BatteryStatusRefresh</a> (<a href="#CG\001496D8">to first</a>)</font>\r
+  <td align=right><font size=2>41</font>\r
+  <td align=right><font size=2>12</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\statefunc\BatteryControl">BatteryControl</a> <a name="CG\0014B6B0"><b>*</b></a></font>\r
+  <td align=right><font size=2>49</font>\r
+  <td align=right><font size=2>14</font>\r
+  <td align=right><font size=2>3</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>4C</font>\r
+  <td align=right><font size=2>16</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Indirectly called function tree that does not make<br>indirect calls (Is not an interrupt and is not flagged<br>as not overlayable)</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\statefunc\Discharge">Discharge</a> <a name="CG\0014B75C"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Indirectly called function tree that does not make<br>indirect calls (Is not an interrupt and is not flagged<br>as not overlayable)</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>3</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\Doze">Doze</a> <a name="CG\0014B808"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\DisableBatteries">DisableBatteries</a> (<a href="#CG\00149784">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\EnableBattery">EnableBattery</a> (<a href="#CG\00149830">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>1</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\BatteryStatusRefresh">BatteryStatusRefresh</a> (<a href="#CG\001496D8">to first</a>)</font>\r
+  <td align=right><font size=2>41</font>\r
+  <td align=right><font size=2>12</font>\r
+  <td align=right><font size=2>4</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\ADC\ADC_Wait">ADC_Wait</a> (<a href="#CG\0002518C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\statefunc\Sleep">Sleep</a> <a name="CG\0014BB64"><b>*</b></a></font>\r
+  <td align=right><font size=2>45</font>\r
+  <td align=right><font size=2>14</font>\r
+  <td align=right><font size=2>2</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>47</font>\r
+  <td align=right><font size=2>16</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Indirectly called function tree that does not make<br>indirect calls (Is not an interrupt and is not flagged<br>as not overlayable)</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\JumperCheck">JumperCheck</a> (<a href="#CG\0014BA0C">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\statefunc\Doze">Doze</a> (<a href="#CG\0014B808">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>10</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\battery\DisableBatteries">DisableBatteries</a> (<a href="#CG\00149784">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\PWM\PWM_Stop">PWM_Stop</a> (<a href="#CG\00147998">to first</a>)</font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>E</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\statefunc\Error">Error</a> <a name="CG\0014B8B4"><b>*</b></a></font>\r
+  <td align=right><font size=2>3D</font>\r
+  <td align=right><font size=2>12</font>\r
+  <td align=right><font size=2>2</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>3F</font>\r
+  <td align=right><font size=2>14</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Function tree that makes indirect calls</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>53</font>\r
+  <td align=right><font size=2>1C</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\main\main">main</a> <a name="CG\0014A6F4"><b>*</b></a></font>\r
+  <td align=right><font size=2>53</font>\r
+  <td align=right><font size=2>1C</font>\r
+  <td align=right><font size=2>7</font>\r
+  <td align=right><font size=2>4</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>20</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Function tree</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>20</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\?low_level_init\__low_level_init">__low_level_init</a> <a name="CG\0027FFD8"><b>*</b></a></font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>20</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>22</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <th colspan=6><font size=3>Sub-tree of type: Function tree</font>\r
+<tr>\r
+  <th rowspan=2 valign=top><font size=2>Level</font>\r
+  <th rowspan=2 valign=top><font size=2>Function</font>\r
+  <th colspan=2><font size=2>Stack prev</font>\r
+  <th colspan=2><font size=2>Stack locally</font>\r
+<tr>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+  <th><font size=2>CSTACK</font>\r
+  <th><font size=2>RSTACK</font>\r
+<tr>\r
+  <th colspan=2><font size=2>Before</font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>22</font>\r
+  <td>\r
+  <td>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\?segment_init\__flashcpy">__flashcpy</a> <a name="CG\0028377C"><b>*</b></a></font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>22</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>2</font>\r
+  <td><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;<a href="#MM\?segment_init\__memclr">__memclr</a> <a name="CG\00283828"><b>*</b></a></font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>22</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <td align=right><font size=2>1</font>\r
+  <td><font size=2>&nbsp;&nbsp;<a href="#MM\?segment_init\__segment_init">__segment_init</a> <a name="CG\002838D4"><b>*</b></a></font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>24</font>\r
+  <td align=right><font size=2>0</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr>\r
+  <th colspan=2><font size=2>After</font>\r
+  <td align=right><font size=2>5A</font>\r
+  <td align=right><font size=2>26</font>\r
+  <td>\r
+  <td>\r
+</table>\r
+<p><hr><p>\r
+<a name="Segments in Address Order"></a>\r
+<table bgcolor="#bbbb00" border=1 cellpadding=2>\r
+<tr>\r
+  <th align=center colspan=7><font size=4><B>Segments in Address Order</B>\r
+</font>\r
+<tr>\r
+  <th><font size=2>Segment</font>\r
+  <th><font size=2>Space</font>\r
+  <th><font size=2>Start</font>\r
+  <th><font size=2>End</font>\r
+  <th><font size=2>Size</font>\r
+  <th><font size=2>Kind</font>\r
+  <th><font size=2>Align</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>INTVEC</font>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td align=center colspan=2><font size=2>00000000 - 0000001D</font>\r
+  <td align=right><font size=2>1E</font>\r
+  <td rowspan=1 ><font size=2>Common</font>\r
+  <td align=center><font size=2>1</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>?FILL1</font>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td align=center colspan=2><font size=2>0000001E - 00000025</font>\r
+  <td align=right><font size=2>8</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>NEAR_F</font>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td align=center colspan=2><font size=2>00000026 - 00000043</font>\r
+  <td align=right><font size=2>1E</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>INITTAB</font>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td align=center colspan=2><font size=2>00000044 - 0000004F</font>\r
+  <td align=right><font size=2>C</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td align=center colspan=2><font size=2>00000050 - 00001869</font>\r
+  <td align=right><font size=2>181A</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>1</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>NEAR_ID</font>\r
+  <td rowspan=1 ><font size=2>CODE</font>\r
+  <td align=center colspan=2><font size=2>0000186A - 000018DD</font>\r
+  <td align=right><font size=2>74</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=36 ><font size=2>ABSOLUTE</font>\r
+  <td rowspan=36 ><font size=2>DATA</font>\r
+  <td align=center colspan=2><font size=2>0000001C </font>\r
+  <td align=right><font size=2></font>\r
+  <td rowspan=36 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>0000001D </font>\r
+  <td align=right><font size=2></font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>0000001E </font>\r
+  <td align=right><font size=2></font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>0000001F </font>\r
+  <td align=right><font size=2></font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000020 - 00000020</font>\r
+  <td align=right><font size=2>1</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000023 - 00000027</font>\r
+  <td align=right><font size=2>5</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>0000002D - 0000002F</font>\r
+  <td align=right><font size=2>3</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000032 - 00000033</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000035 - 00000035</font>\r
+  <td align=right><font size=2>1</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000037 - 0000003B</font>\r
+  <td align=right><font size=2>5</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000041 - 00000041</font>\r
+  <td align=right><font size=2>1</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000044 - 00000044</font>\r
+  <td align=right><font size=2>1</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000046 - 0000004D</font>\r
+  <td align=right><font size=2>8</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>0000004F - 00000050</font>\r
+  <td align=right><font size=2>2</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000053 - 00000055</font>\r
+  <td align=right><font size=2>3</font>\r
+<tr valign=top>\r
+  <td align=center colspan=2><font size=2>00000059 - 00000059</font>\r
+  <td align=right><font size=2>1</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>CSTACK</font>\r
+  <td rowspan=1 ><font size=2>DATA</font>\r
+  <td align=center colspan=2><font size=2>00000060 - 0000009F</font>\r
+  <td align=right><font size=2>40</font>\r
+  <td rowspan=1 ><font size=2>Predefined</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>RSTACK</font>\r
+  <td rowspan=1 ><font size=2>DATA</font>\r
+  <td align=center colspan=2><font size=2>000000A0 - 000000CF</font>\r
+  <td align=right><font size=2>30</font>\r
+  <td rowspan=1 ><font size=2>Predefined</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>NEAR_I</font>\r
+  <td rowspan=1 ><font size=2>DATA</font>\r
+  <td align=center colspan=2><font size=2>000000D0 - 00000143</font>\r
+  <td align=right><font size=2>74</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>NEAR_Z</font>\r
+  <td rowspan=1 ><font size=2>DATA</font>\r
+  <td align=center colspan=2><font size=2>00000144 - 00000196</font>\r
+  <td align=right><font size=2>53</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+<tr valign=top>\r
+  <td rowspan=1 ><font size=2>EEPROM_I</font>\r
+  <td rowspan=1 ><font size=2>XDATA</font>\r
+  <td align=center colspan=2><font size=2>00000000 - 00000082</font>\r
+  <td align=right><font size=2>83</font>\r
+  <td rowspan=1 ><font size=2>Relative</font>\r
+  <td align=center><font size=2>0</font>\r
+</table>\r
+\r
+<hr>\r
+\r
+<p><a name="Memory Summary"></a><table>\r
+\r
+<table >\r
+<tr>\r
+<td align=right valign=top>6&nbsp;358</td>\r
+<td valign=top>bytes</td>\r
+<td valign=top>of</td>\r
+<td valign=top>CODE</td>\r
+<td valign=top>memory</td>\r
+<td valign=top>(+</td>\r
+<td valign=top>&nbsp;</td>\r
+<td valign=top>&nbsp;</td>\r
+<td align=right valign=top>8</td>\r
+<td valign=top>range&nbsp;fill</td>\r
+<td valign=top>)</td>\r
+</tr>\r
+<tr>\r
+<td align=right valign=top>311</td>\r
+<td valign=top>bytes</td>\r
+<td valign=top>of</td>\r
+<td valign=top>DATA</td>\r
+<td valign=top>memory</td>\r
+<td valign=top>(+</td>\r
+<td align=right valign=top>33</td>\r
+<td valign=top>absolute</td>\r
+<td valign=top>)</td>\r
+</tr>\r
+<tr>\r
+<td align=right valign=top>131</td>\r
+<td valign=top>bytes</td>\r
+<td valign=top>of</td>\r
+<td valign=top>XDATA</td>\r
+<td valign=top>memory</td>\r
+</tr>\r
+</table>\r
+\r
+Errors: none\r
+Warnings: none\r
+\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.lst b/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.lst
new file mode 100644 (file)
index 0000000..6ff75c9
--- /dev/null
@@ -0,0 +1,414 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:38 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c         #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c         #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\NIMHcharg #\r
+#                    e.lst                                                    #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge #\r
+#                    .r90                                                     #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Charge state function for NiMH batteries\r
+      6           *\r
+      7           *      Contains the charge state function, in which the NiMH charging\r
+      8           *      algorithm is, plus the associated functions.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR463: Charging NiMH Batteries with BC100 \n\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2255 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $\r
+     26           * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          #include <ioavr.h>\r
+     30          \r
+     31          #include "enums.h"\r
+     32          #include "structs.h"\r
+     33          \r
+     34          #include "battery.h"\r
+     35          #include "charge.h"\r
+     36          #include "chargefunc.h"\r
+     37          #include "main.h"\r
+     38          #include "menu.h"\r
+     39          #include "NIMHspecs.h"\r
+     40          #include "PWM.h"\r
+     41          #include "time.h"\r
+     42          \r
+     43          #ifndef NIMH\r
+     44          #error NIMH not defined in main.h!\r
+     45          #endif // NIMH\r
+     46          \r
+     47          \r
+     48          //******************************************************************************\r
+     49          // Functions\r
+     50          //******************************************************************************\r
+     51          /*! \brief Controls the charging.\r
+     52           *\r
+     53           * This function contains the charging algorithm itself, divided into stages.\n\r
+     54           * For each stage the PWM may be started/stopped, and the timer, \r
+     55           * halt-requirements and charge parameters may be set.\n\r
+     56           * The charging functions return whatever state is next, and as long as no\r
+     57           * errors occur this is the next charging stage.\r
+     58           *\r
+     59           * \note If more stages are needed simply define more states in menu.h, include\r
+     60           * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+     61           *\r
+     62           * \note This algorithm is for NiMH batteries.\r
+     63           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     64          unsigned char Charge(unsigned char inp)\r
+   \                     Charge:\r
+     65          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE2_L09\r
+   \   00000002   2F90               MOV     R25, R16\r
+     66                unsigned char NextState;\r
+     67          \r
+     68                switch (CurrentState) {\r
+   \   00000004   9100....           LDS     R16, CurrentState\r
+   \   00000008   510E               SUBI    R16, 30\r
+   \   0000000A   F049               BREQ    ??Charge_0\r
+   \   0000000C   5104               SUBI    R16, 20\r
+   \   0000000E   F1D1               BREQ    ??Charge_1\r
+   \   00000010   500A               SUBI    R16, 10\r
+   \   00000012   F409               BRNE    $+2+2\r
+   \   00000014   C06E               RJMP    ??Charge_2\r
+   \   00000016   500A               SUBI    R16, 10\r
+   \   00000018   F409               BRNE    $+2+2\r
+   \   0000001A   C085               RJMP    ??Charge_3\r
+   \   0000001C   C09F               RJMP    ??Charge_4\r
+     69                // First stage is a prequalification. Attempt to charge battery to 1 V,\r
+     70                // using a 0.1 C current, within 2 minutes.\r
+     71                // If this fails, the battery is likely damaged.\r
+     72                // If it succeeds, start a fast charge.\r
+     73                case ST_PREQUAL:\r
+     74                        \r
+     75                        // Set up charge current and next state.\r
+     76                        ChargeParameters.Current = BattData.Capacity / 10;\r
+   \                     ??Charge_0:\r
+   \   0000001E   ....               LDI     R30, LOW(BattData)\r
+   \   00000020   ....               LDI     R31, (BattData) >> 8\r
+   \   00000022   8104               LDD     R16, Z+4\r
+   \   00000024   8115               LDD     R17, Z+5\r
+   \   00000026   E04A               LDI     R20, 10\r
+   \   00000028   E050               LDI     R21, 0\r
+   \   0000002A   ....               RCALL   ?US_DIVMOD_L02\r
+   \   0000002C   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   0000002E   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   00000030   8302               STD     Z+2, R16\r
+   \   00000032   8313               STD     Z+3, R17\r
+     77                        ChargeParameters.NextState = ST_FASTCHARGE;\r
+   \   00000034   E302               LDI     R16, 50\r
+   \   00000036   9300....           STS     (ChargeParameters + 4), R16\r
+     78                        \r
+     79                        // Halt charge on voltage limit or timeout.\r
+     80                        // Timeout means battery exhaustion.\r
+     81                        HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+     82                                                    HALT_FLAG_EXHAUSTION);\r
+   \   0000003A   E302               LDI     R16, 50\r
+   \   0000003C   9300....           STS     HaltParameters, R16\r
+     83                        \r
+     84                        // Set up voltage limit and temperature limits.\r
+     85                        HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+   \   00000040   EB08               LDI     R16, 184\r
+   \   00000042   E01B               LDI     R17, 11\r
+   \   00000044   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000046   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000048   8303               STD     Z+3, R16\r
+   \   0000004A   8314               STD     Z+4, R17\r
+     86                        HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+   \   0000004C   E005               LDI     R16, 5\r
+   \   0000004E   E010               LDI     R17, 0\r
+   \   00000050   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000052   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000054   8701               STD     Z+9, R16\r
+   \   00000056   8712               STD     Z+10, R17\r
+     87                        HaltParameters.TemperatureMax = 35;\r
+   \   00000058   E203               LDI     R16, 35\r
+   \   0000005A   E010               LDI     R17, 0\r
+   \   0000005C   ....               LDI     R30, LOW(HaltParameters)\r
+   \   0000005E   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000060   8307               STD     Z+7, R16\r
+   \   00000062   8710               STD     Z+8, R17\r
+     88                        \r
+     89                        // Reset temperature measurement for HaltNow().\r
+     90                        HaltParameters.LastNTC = 0;\r
+   \   00000064   E000               LDI     R16, 0\r
+   \   00000066   E010               LDI     R17, 0\r
+   \   00000068   ....               LDI     R30, LOW(HaltParameters)\r
+   \   0000006A   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   0000006C   8707               STD     Z+15, R16\r
+   \   0000006E   8B10               STD     Z+16, R17\r
+     91                        \r
+     92                        // Start PWM and charge timer before calling the charge function.\r
+     93                        PWM_Start();\r
+   \   00000070   ....               RCALL   PWM_Start\r
+     94                        Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+   \   00000072   E040               LDI     R20, 0\r
+   \   00000074   E010               LDI     R17, 0\r
+   \   00000076   E022               LDI     R18, 2\r
+   \   00000078   E030               LDI     R19, 0\r
+   \   0000007A   E001               LDI     R16, 1\r
+   \   0000007C   ....               RCALL   Time_Set\r
+     95                        \r
+     96                        // Call charge function, get next state.\r
+     97                        NextState = ConstantCurrent();\r
+   \   0000007E   ....               RCALL   ConstantCurrent\r
+   \   00000080   2F80               MOV     R24, R16\r
+   \   00000082   C06D               RJMP    ??Charge_5\r
+     98                break;\r
+     99          \r
+    100          \r
+    101                // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,\r
+    102                // until either rate of temperature increase or voltage reaches limit, or\r
+    103                // the voltage drops sufficiently.\r
+    104                // Timeout doesn't mean battery exhaustion now.\r
+    105                case ST_FASTCHARGE:\r
+    106          \r
+    107                        // Set up charge current and next state.\r
+    108                        ChargeParameters.Current = BattData.Capacity;\r
+   \                     ??Charge_1:\r
+   \   00000084   ....               LDI     R30, LOW(BattData)\r
+   \   00000086   ....               LDI     R31, (BattData) >> 8\r
+   \   00000088   8104               LDD     R16, Z+4\r
+   \   0000008A   8115               LDD     R17, Z+5\r
+   \   0000008C   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   0000008E   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   00000090   8302               STD     Z+2, R16\r
+   \   00000092   8313               STD     Z+3, R17\r
+    109                        ChargeParameters.NextState = ST_LOWRATECHARGE;\r
+   \   00000094   E30C               LDI     R16, 60\r
+   \   00000096   9300....           STS     (ChargeParameters + 4), R16\r
+    110                        \r
+    111                        // Halt charge on voltage limit, timeout, voltage drop or rate of \r
+    112                        // temperature increase.\r
+    113                        HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+    114                                                    HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);\r
+   \   0000009A   E10B               LDI     R16, 27\r
+   \   0000009C   9300....           STS     HaltParameters, R16\r
+    115                        \r
+    116                        // Set up limits for voltage, voltage drop, temperature and rate of \r
+    117                        // temperature increase (1 degree C per minute).\r
+    118                        HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+   \   000000A0   EC00               LDI     R16, 192\r
+   \   000000A2   E112               LDI     R17, 18\r
+   \   000000A4   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000A6   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000A8   8303               STD     Z+3, R16\r
+   \   000000AA   8314               STD     Z+4, R17\r
+    119                        HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;\r
+   \   000000AC   E20D               LDI     R16, 45\r
+   \   000000AE   E010               LDI     R17, 0\r
+   \   000000B0   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000B2   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000B4   8301               STD     Z+1, R16\r
+   \   000000B6   8312               STD     Z+2, R17\r
+    120                        HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+   \   000000B8   E302               LDI     R16, 50\r
+   \   000000BA   E010               LDI     R17, 0\r
+   \   000000BC   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000BE   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000C0   8307               STD     Z+7, R16\r
+   \   000000C2   8710               STD     Z+8, R17\r
+    121                        HaltParameters.TemperatureRise = 1;\r
+   \   000000C4   E001               LDI     R16, 1\r
+   \   000000C6   E010               LDI     R17, 0\r
+   \   000000C8   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000CA   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000CC   8703               STD     Z+11, R16\r
+   \   000000CE   8714               STD     Z+12, R17\r
+    122                        \r
+    123                        // Reset maximum voltage measurement for HaltNow().\r
+    124                        HaltParameters.VBATMax = 0;\r
+   \   000000D0   E000               LDI     R16, 0\r
+   \   000000D2   E010               LDI     R17, 0\r
+   \   000000D4   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000D6   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000D8   8705               STD     Z+13, R16\r
+   \   000000DA   8716               STD     Z+14, R17\r
+    125          \r
+    126                        // Start timer, PWM should still be running.\r
+    127                        Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);\r
+   \   000000DC   E040               LDI     R20, 0\r
+   \   000000DE   E010               LDI     R17, 0\r
+   \   000000E0   ....               LDI     R30, LOW(BattData)\r
+   \   000000E2   ....               LDI     R31, (BattData) >> 8\r
+   \   000000E4   8520               LDD     R18, Z+8\r
+   \   000000E6   8531               LDD     R19, Z+9\r
+   \   000000E8   E001               LDI     R16, 1\r
+   \   000000EA   ....               RCALL   Time_Set\r
+    128          \r
+    129                        // Call charge function, get next state.\r
+    130                        NextState = ConstantCurrent();\r
+   \   000000EC   ....               RCALL   ConstantCurrent\r
+   \   000000EE   2F80               MOV     R24, R16\r
+   \   000000F0   C036               RJMP    ??Charge_5\r
+    131                break;\r
+    132          \r
+    133          \r
+    134                // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,\r
+    135                // until either rate of temperature increase or voltage reaches limit.\r
+    136                case ST_LOWRATECHARGE:\r
+    137                        \r
+    138                        // Set up charge current and next state.\r
+    139                        ChargeParameters.Current = BattData.Capacity / 10;\r
+   \                     ??Charge_2:\r
+   \   000000F2   ....               LDI     R30, LOW(BattData)\r
+   \   000000F4   ....               LDI     R31, (BattData) >> 8\r
+   \   000000F6   8104               LDD     R16, Z+4\r
+   \   000000F8   8115               LDD     R17, Z+5\r
+   \   000000FA   E04A               LDI     R20, 10\r
+   \   000000FC   E050               LDI     R21, 0\r
+   \   000000FE   ....               RCALL   ?US_DIVMOD_L02\r
+   \   00000100   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   00000102   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   00000104   8302               STD     Z+2, R16\r
+   \   00000106   8313               STD     Z+3, R17\r
+    140                        ChargeParameters.NextState = ST_ENDCHARGE;\r
+   \   00000108   E406               LDI     R16, 70\r
+   \   0000010A   9300....           STS     (ChargeParameters + 4), R16\r
+    141                        \r
+    142                        // Halt charge on voltage limit, timeout or temperature rise.\r
+    143                        // Use the same requirements as during the last stage (ST_FASTCHARGE).\r
+    144                        HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+    145                                                    HALT_TEMPERATURE_RISE);\r
+   \   0000010E   E10A               LDI     R16, 26\r
+   \   00000110   9300....           STS     HaltParameters, R16\r
+    146          \r
+    147                        // Start timer, 30 minutes.\r
+    148                        Time_Set(TIMER_CHG, 30, 0, 0);\r
+   \   00000114   E040               LDI     R20, 0\r
+   \   00000116   E010               LDI     R17, 0\r
+   \   00000118   E12E               LDI     R18, 30\r
+   \   0000011A   E030               LDI     R19, 0\r
+   \   0000011C   E001               LDI     R16, 1\r
+   \   0000011E   ....               RCALL   Time_Set\r
+    149                        \r
+    150                        // Call charge function, get next state.\r
+    151                        NextState = ConstantCurrent();\r
+   \   00000120   ....               RCALL   ConstantCurrent\r
+   \   00000122   2F80               MOV     R24, R16\r
+   \   00000124   C01C               RJMP    ??Charge_5\r
+    152                break;\r
+    153          \r
+    154          \r
+    155                // Charging is done!\r
+    156                case ST_ENDCHARGE:\r
+    157          \r
+    158                        // Stop the PWM output and flag battery as charged.\r
+    159                        PWM_Stop();\r
+   \                     ??Charge_3:\r
+   \   00000126   ....               RCALL   PWM_Stop\r
+    160                        BattData.Charged = TRUE;\r
+   \   00000128   ....               LDI     R30, LOW(BattData)\r
+   \   0000012A   ....               LDI     R31, (BattData) >> 8\r
+   \   0000012C   8100               LD      R16, Z\r
+   \   0000012E   6002               ORI     R16, 0x02\r
+   \   00000130   8300               ST      Z, R16\r
+    161                        \r
+    162                        // If the other battery is enabled go to ST_BATCON, otherwise\r
+    163                        // go to ST_SLEEP.\r
+    164                        if (BattControl[(BattActive+1)%2].Enabled) {\r
+   \   00000132   9100....           LDS     R16, BattActive\r
+   \   00000136   E010               LDI     R17, 0\r
+   \   00000138   5F0F               SUBI    R16, 255\r
+   \   0000013A   4F1F               SBCI    R17, 255\r
+   \   0000013C   E042               LDI     R20, 2\r
+   \   0000013E   E050               LDI     R21, 0\r
+   \   00000140   ....               RCALL   ?SS_DIVMOD_L02\r
+   \   00000142   ....               LDI     R18, LOW(BattControl)\r
+   \   00000144   ....               LDI     R19, (BattControl) >> 8\r
+   \   00000146   0F24               ADD     R18, R20\r
+   \   00000148   1F35               ADC     R19, R21\r
+   \   0000014A   01A9               MOVW    R21:R20, R19:R18\r
+   \   0000014C   ....               RCALL   __eeget8_16\r
+   \   0000014E   7001               ANDI    R16, 0x01\r
+   \   00000150   2300               TST     R16\r
+   \   00000152   F011               BREQ    ??Charge_6\r
+    165                                NextState = ST_BATCON;\r
+   \   00000154   E184               LDI     R24, 20\r
+   \   00000156   C003               RJMP    ??Charge_5\r
+    166                        } else {\r
+    167                                NextState = ST_SLEEP;\r
+   \                     ??Charge_6:\r
+   \   00000158   E288               LDI     R24, 40\r
+   \   0000015A   C001               RJMP    ??Charge_5\r
+    168                        }               \r
+    169                break;\r
+    170          \r
+    171          \r
+    172                default:  // Shouldn't end up here. Reinitialize for safety.\r
+    173                        NextState = ST_INIT;\r
+   \                     ??Charge_4:\r
+   \   0000015C   E08A               LDI     R24, 10\r
+    174                        break;\r
+    175                }\r
+    176          \r
+    177                // Return the next state to main().\r
+    178                return(NextState);\r
+   \                     ??Charge_5:\r
+   \   0000015E   2F08               MOV     R16, R24\r
+   \   00000160   E0E2               LDI     R30, 2\r
+   \   00000162   ....               RJMP    ?EPILOGUE_B2_L09\r
+    179          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function             CSTACK RSTACK\r
+     --------             ------ ------\r
+     Charge                   2      4\r
+       -> PWM_Start           2      2\r
+       -> Time_Set            2      2\r
+       -> ConstantCurrent     2      2\r
+       -> Time_Set            2      2\r
+       -> ConstantCurrent     2      2\r
+       -> Time_Set            2      2\r
+       -> ConstantCurrent     2      2\r
+       -> PWM_Stop            2      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     Charge          356\r
+\r
\r
+ 356 bytes in segment CODE\r
\r
+ 356 bytes of CODE memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.s90 b/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.s90
new file mode 100644 (file)
index 0000000..e421005
--- /dev/null
@@ -0,0 +1,433 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:38 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c        /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c        /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\NIMHchar /\r
+//                    ge.s90                                                  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME NIMHcharge\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B2_L09\r
+        EXTERN ?PROLOGUE2_L09\r
+        EXTERN ?SS_DIVMOD_L02\r
+        EXTERN ?US_DIVMOD_L02\r
+        EXTERN __eeget8_16\r
+\r
+        PUBLIC Charge\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN PWM_Start\r
+        EXTERN Time_Set\r
+        EXTERN ConstantCurrent\r
+        EXTERN PWM_Stop\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+        EXTERN ChargeParameters\r
+        EXTERN CurrentState\r
+        EXTERN HaltParameters\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Charge state function for NiMH batteries\r
+//    6  *\r
+//    7  *      Contains the charge state function, in which the NiMH charging\r
+//    8  *      algorithm is, plus the associated functions.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100 \n\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2255 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $\r
+//   26  * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 #include <ioavr.h>\r
+//   30 \r
+//   31 #include "enums.h"\r
+//   32 #include "structs.h"\r
+//   33 \r
+//   34 #include "battery.h"\r
+//   35 #include "charge.h"\r
+//   36 #include "chargefunc.h"\r
+//   37 #include "main.h"\r
+//   38 #include "menu.h"\r
+//   39 #include "NIMHspecs.h"\r
+//   40 #include "PWM.h"\r
+//   41 #include "time.h"\r
+//   42 \r
+//   43 #ifndef NIMH\r
+//   44 #error NIMH not defined in main.h!\r
+//   45 #endif // NIMH\r
+//   46 \r
+//   47 \r
+//   48 //******************************************************************************\r
+//   49 // Functions\r
+//   50 //******************************************************************************\r
+//   51 /*! \brief Controls the charging.\r
+//   52  *\r
+//   53  * This function contains the charging algorithm itself, divided into stages.\n\r
+//   54  * For each stage the PWM may be started/stopped, and the timer, \r
+//   55  * halt-requirements and charge parameters may be set.\n\r
+//   56  * The charging functions return whatever state is next, and as long as no\r
+//   57  * errors occur this is the next charging stage.\r
+//   58  *\r
+//   59  * \note If more stages are needed simply define more states in menu.h, include\r
+//   60  * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+//   61  *\r
+//   62  * \note This algorithm is for NiMH batteries.\r
+//   63  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   64 unsigned char Charge(unsigned char inp)\r
+Charge:\r
+//   65 {\r
+        RCALL   ?PROLOGUE2_L09\r
+        MOV     R25, R16\r
+//   66        unsigned char NextState;\r
+//   67 \r
+//   68        switch (CurrentState) {\r
+        LDS     R16, CurrentState\r
+        SUBI    R16, 30\r
+        BREQ    ??Charge_0\r
+        SUBI    R16, 20\r
+        BREQ    ??Charge_1\r
+        SUBI    R16, 10\r
+        BRNE    $+2+2\r
+        RJMP    ??Charge_2\r
+        SUBI    R16, 10\r
+        BRNE    $+2+2\r
+        RJMP    ??Charge_3\r
+        RJMP    ??Charge_4\r
+//   69        // First stage is a prequalification. Attempt to charge battery to 1 V,\r
+//   70        // using a 0.1 C current, within 2 minutes.\r
+//   71        // If this fails, the battery is likely damaged.\r
+//   72        // If it succeeds, start a fast charge.\r
+//   73        case ST_PREQUAL:\r
+//   74                \r
+//   75                // Set up charge current and next state.\r
+//   76                ChargeParameters.Current = BattData.Capacity / 10;\r
+??Charge_0:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R20, 10\r
+        LDI     R21, 0\r
+        RCALL   ?US_DIVMOD_L02\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//   77                ChargeParameters.NextState = ST_FASTCHARGE;\r
+        LDI     R16, 50\r
+        STS     (ChargeParameters + 4), R16\r
+//   78                \r
+//   79                // Halt charge on voltage limit or timeout.\r
+//   80                // Timeout means battery exhaustion.\r
+//   81                HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+//   82                                            HALT_FLAG_EXHAUSTION);\r
+        LDI     R16, 50\r
+        STS     HaltParameters, R16\r
+//   83                \r
+//   84                // Set up voltage limit and temperature limits.\r
+//   85                HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+        LDI     R16, 184\r
+        LDI     R17, 11\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+3, R16\r
+        STD     Z+4, R17\r
+//   86                HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+        LDI     R16, 5\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+9, R16\r
+        STD     Z+10, R17\r
+//   87                HaltParameters.TemperatureMax = 35;\r
+        LDI     R16, 35\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+7, R16\r
+        STD     Z+8, R17\r
+//   88                \r
+//   89                // Reset temperature measurement for HaltNow().\r
+//   90                HaltParameters.LastNTC = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+15, R16\r
+        STD     Z+16, R17\r
+//   91                \r
+//   92                // Start PWM and charge timer before calling the charge function.\r
+//   93                PWM_Start();\r
+        RCALL   PWM_Start\r
+//   94                Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+        LDI     R20, 0\r
+        LDI     R17, 0\r
+        LDI     R18, 2\r
+        LDI     R19, 0\r
+        LDI     R16, 1\r
+        RCALL   Time_Set\r
+//   95                \r
+//   96                // Call charge function, get next state.\r
+//   97                NextState = ConstantCurrent();\r
+        RCALL   ConstantCurrent\r
+        MOV     R24, R16\r
+        RJMP    ??Charge_5\r
+//   98        break;\r
+//   99 \r
+//  100 \r
+//  101        // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,\r
+//  102        // until either rate of temperature increase or voltage reaches limit, or\r
+//  103        // the voltage drops sufficiently.\r
+//  104        // Timeout doesn't mean battery exhaustion now.\r
+//  105        case ST_FASTCHARGE:\r
+//  106 \r
+//  107                // Set up charge current and next state.\r
+//  108                ChargeParameters.Current = BattData.Capacity;\r
+??Charge_1:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//  109                ChargeParameters.NextState = ST_LOWRATECHARGE;\r
+        LDI     R16, 60\r
+        STS     (ChargeParameters + 4), R16\r
+//  110                \r
+//  111                // Halt charge on voltage limit, timeout, voltage drop or rate of \r
+//  112                // temperature increase.\r
+//  113                HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+//  114                                            HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);\r
+        LDI     R16, 27\r
+        STS     HaltParameters, R16\r
+//  115                \r
+//  116                // Set up limits for voltage, voltage drop, temperature and rate of \r
+//  117                // temperature increase (1 degree C per minute).\r
+//  118                HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+        LDI     R16, 192\r
+        LDI     R17, 18\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+3, R16\r
+        STD     Z+4, R17\r
+//  119                HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;\r
+        LDI     R16, 45\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+1, R16\r
+        STD     Z+2, R17\r
+//  120                HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+        LDI     R16, 50\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+7, R16\r
+        STD     Z+8, R17\r
+//  121                HaltParameters.TemperatureRise = 1;\r
+        LDI     R16, 1\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+11, R16\r
+        STD     Z+12, R17\r
+//  122                \r
+//  123                // Reset maximum voltage measurement for HaltNow().\r
+//  124                HaltParameters.VBATMax = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+13, R16\r
+        STD     Z+14, R17\r
+//  125 \r
+//  126                // Start timer, PWM should still be running.\r
+//  127                Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);\r
+        LDI     R20, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R18, Z+8\r
+        LDD     R19, Z+9\r
+        LDI     R16, 1\r
+        RCALL   Time_Set\r
+//  128 \r
+//  129                // Call charge function, get next state.\r
+//  130                NextState = ConstantCurrent();\r
+        RCALL   ConstantCurrent\r
+        MOV     R24, R16\r
+        RJMP    ??Charge_5\r
+//  131        break;\r
+//  132 \r
+//  133 \r
+//  134        // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,\r
+//  135        // until either rate of temperature increase or voltage reaches limit.\r
+//  136        case ST_LOWRATECHARGE:\r
+//  137                \r
+//  138                // Set up charge current and next state.\r
+//  139                ChargeParameters.Current = BattData.Capacity / 10;\r
+??Charge_2:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R20, 10\r
+        LDI     R21, 0\r
+        RCALL   ?US_DIVMOD_L02\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//  140                ChargeParameters.NextState = ST_ENDCHARGE;\r
+        LDI     R16, 70\r
+        STS     (ChargeParameters + 4), R16\r
+//  141                \r
+//  142                // Halt charge on voltage limit, timeout or temperature rise.\r
+//  143                // Use the same requirements as during the last stage (ST_FASTCHARGE).\r
+//  144                HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+//  145                                            HALT_TEMPERATURE_RISE);\r
+        LDI     R16, 26\r
+        STS     HaltParameters, R16\r
+//  146 \r
+//  147                // Start timer, 30 minutes.\r
+//  148                Time_Set(TIMER_CHG, 30, 0, 0);\r
+        LDI     R20, 0\r
+        LDI     R17, 0\r
+        LDI     R18, 30\r
+        LDI     R19, 0\r
+        LDI     R16, 1\r
+        RCALL   Time_Set\r
+//  149                \r
+//  150                // Call charge function, get next state.\r
+//  151                NextState = ConstantCurrent();\r
+        RCALL   ConstantCurrent\r
+        MOV     R24, R16\r
+        RJMP    ??Charge_5\r
+//  152        break;\r
+//  153 \r
+//  154 \r
+//  155        // Charging is done!\r
+//  156        case ST_ENDCHARGE:\r
+//  157 \r
+//  158                // Stop the PWM output and flag battery as charged.\r
+//  159                PWM_Stop();\r
+??Charge_3:\r
+        RCALL   PWM_Stop\r
+//  160                BattData.Charged = TRUE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x02\r
+        ST      Z, R16\r
+//  161                \r
+//  162                // If the other battery is enabled go to ST_BATCON, otherwise\r
+//  163                // go to ST_SLEEP.\r
+//  164                if (BattControl[(BattActive+1)%2].Enabled) {\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        SUBI    R16, 255\r
+        SBCI    R17, 255\r
+        LDI     R20, 2\r
+        LDI     R21, 0\r
+        RCALL   ?SS_DIVMOD_L02\r
+        LDI     R18, LOW(BattControl)\r
+        LDI     R19, (BattControl) >> 8\r
+        ADD     R18, R20\r
+        ADC     R19, R21\r
+        MOVW    R21:R20, R19:R18\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        TST     R16\r
+        BREQ    ??Charge_6\r
+//  165                        NextState = ST_BATCON;\r
+        LDI     R24, 20\r
+        RJMP    ??Charge_5\r
+//  166                } else {\r
+//  167                        NextState = ST_SLEEP;\r
+??Charge_6:\r
+        LDI     R24, 40\r
+        RJMP    ??Charge_5\r
+//  168                }               \r
+//  169        break;\r
+//  170 \r
+//  171 \r
+//  172        default:  // Shouldn't end up here. Reinitialize for safety.\r
+//  173                NextState = ST_INIT;\r
+??Charge_4:\r
+        LDI     R24, 10\r
+//  174                break;\r
+//  175        }\r
+//  176 \r
+//  177        // Return the next state to main().\r
+//  178        return(NextState);\r
+??Charge_5:\r
+        MOV     R16, R24\r
+        LDI     R30, 2\r
+        RJMP    ?EPILOGUE_B2_L09\r
+//  179 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+// \r
+// 356 bytes in segment CODE\r
+// \r
+// 356 bytes of CODE memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/OWI.lst b/BaseTinyFirmware/IAR/Debug/List/OWI.lst
new file mode 100644 (file)
index 0000000..7711e61
--- /dev/null
@@ -0,0 +1,1124 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:38 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c                #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c --cpu=tiny861  #\r
+#                    -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\    #\r
+#                    -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB  #\r
+#                    C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\          #\r
+#                    --initializers_in_flash -z2 --no_cse --no_inline         #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\OWI.lst   #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\OWI.r90    #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file ********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for 1-Wire(R) bus communication\r
+      6           *\r
+      7           *      High level functions for transmission of full bytes on the 1-Wire(R)\r
+      8           *      bus and implementations of ROM commands.\n\r
+      9           *      Polled software only implementation of the basic bit-level signalling\r
+     10           *      in the 1-Wire(R) protocol.\n\r
+     11           *      Includes functions for computing and checking CRC8 & 16 values of data\r
+     12           *      sets, and of 64 bit ROM identifiers.\r
+     13           *      Supported devices:  All AVRs.\r
+     14           *\r
+     15           * \par Application Note:\r
+     16           *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+     17           *      AVR463: Charging NiMH Batteries with BC100\n\r
+     18           *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+     19           *\r
+     20           * \par Documentation:\r
+     21           *      For comprehensive code documentation, supported compilers, compiler\r
+     22           *      settings and supported devices see readme.html\r
+     23           *\r
+     24           * \author\r
+     25           *      Atmel Corporation: http://www.atmel.com \n\r
+     26           *      Support email: avr@atmel.com \n\r
+     27           *      Original author: \n\r
+     28           *\r
+     29           * $Name$\r
+     30           * $Revision: 2299 $\r
+     31           * $RCSfile$\r
+     32           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
+     33           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     34          ****************************************************************************/\r
+     35          \r
+     36          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3b\r
+   \   <unnamed> volatile __io _A_PORTA\r
+   \                     _A_PORTA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3a\r
+   \   <unnamed> volatile __io _A_DDRA\r
+   \                     _A_DDRA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x39\r
+   \   <unnamed> volatile __io _A_PINA\r
+   \                     _A_PINA:\r
+   \   00000000                      DS 1\r
+     37          #include <inavr.h>\r
+     38          \r
+     39          #include "OWI.h"\r
+     40          \r
+     41          \r
+     42          //******************************************************************************\r
+     43          // Functions\r
+     44          //******************************************************************************\r
+     45          /*! \brief Initialization of the one wire bus(es). (Software only driver)\r
+     46           *  \r
+     47           *  This function initializes the 1-Wire bus(es) by releasing it and\r
+     48           *  waiting until any presence signals are finished.\r
+     49           *\r
+     50           *  \param  pins    A bitmask of the buses to initialize.\r
+     51           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     52          void OWI_Init(unsigned char pins){\r
+   \                     OWI_Init:\r
+     53                OWI_RELEASE_BUS(pins);\r
+   \   00000000   2F10               MOV     R17, R16\r
+   \   00000002   9510               COM     R17\r
+   \   00000004   B32A               IN      R18, 0x1A\r
+   \   00000006   2321               AND     R18, R17\r
+   \   00000008   BB2A               OUT     0x1A, R18\r
+   \   0000000A   2F10               MOV     R17, R16\r
+   \   0000000C   9510               COM     R17\r
+   \   0000000E   B32B               IN      R18, 0x1B\r
+   \   00000010   2321               AND     R18, R17\r
+   \   00000012   BB2B               OUT     0x1B, R18\r
+     54                // The first rising edge can be interpreted by a slave as the end of a\r
+     55                // Reset-pulse. Delay for the required reset recovery time (H) to be \r
+     56                // sure that the real reset is interpreted correctly.\r
+     57                __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+   \   00000014   EB2C               LDI     R18, 188\r
+   \   00000016   E033               LDI     R19, 3\r
+   \   00000018   5021               SUBI    R18, 1\r
+   \   0000001A   4030               SBCI    R19, 0\r
+   \   0000001C   F7E9               BRNE    $-4\r
+   \   0000001E   C000               RJMP    $+2\r
+     58          }\r
+   \   00000020   9508               RET\r
+   \   00000022                      REQUIRE _A_PORTA\r
+   \   00000022                      REQUIRE _A_DDRA\r
+     59          \r
+     60          \r
+     61          /*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
+     62           *\r
+     63           *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
+     64           *  bus.\r
+     65           *\r
+     66           *  \param  pins    A bitmask of the buses to write to.\r
+     67           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     68          void OWI_WriteBit1(unsigned char pins){\r
+   \                     OWI_WriteBit1:\r
+     69                unsigned char intState;\r
+     70                \r
+     71                // Disable interrupts.\r
+     72                intState = __save_interrupt();\r
+   \   00000000   B72F               IN      R18, 0x3F\r
+   \   00000002   2F12               MOV     R17, R18\r
+     73                __disable_interrupt();\r
+   \   00000004   94F8               CLI\r
+     74                \r
+     75                // Drive bus low and delay.\r
+     76                OWI_PULL_BUS_LOW(pins);\r
+   \   00000006   B32A               IN      R18, 0x1A\r
+   \   00000008   2B20               OR      R18, R16\r
+   \   0000000A   BB2A               OUT     0x1A, R18\r
+   \   0000000C   2F20               MOV     R18, R16\r
+   \   0000000E   9520               COM     R18\r
+   \   00000010   B33B               IN      R19, 0x1B\r
+   \   00000012   2332               AND     R19, R18\r
+   \   00000014   BB3B               OUT     0x1B, R19\r
+     77                __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+   \   00000016   E02B               LDI     R18, 11\r
+   \   00000018   952A               DEC     R18\r
+   \   0000001A   F7F1               BRNE    $-2\r
+   \   0000001C   C000               RJMP    $+2\r
+     78                \r
+     79                // Release bus and delay.\r
+     80                OWI_RELEASE_BUS(pins);\r
+   \   0000001E   2F20               MOV     R18, R16\r
+   \   00000020   9520               COM     R18\r
+   \   00000022   B33A               IN      R19, 0x1A\r
+   \   00000024   2332               AND     R19, R18\r
+   \   00000026   BB3A               OUT     0x1A, R19\r
+   \   00000028   2F20               MOV     R18, R16\r
+   \   0000002A   9520               COM     R18\r
+   \   0000002C   B33B               IN      R19, 0x1B\r
+   \   0000002E   2332               AND     R19, R18\r
+   \   00000030   BB3B               OUT     0x1B, R19\r
+     81                __delay_cycles(OWI_DELAY_B_STD_MODE);\r
+   \   00000032   EA26               LDI     R18, 166\r
+   \   00000034   952A               DEC     R18\r
+   \   00000036   F7F1               BRNE    $-2\r
+   \   00000038   0000               NOP\r
+     82                \r
+     83                // Restore interrupts.\r
+     84                __restore_interrupt(intState);\r
+   \   0000003A   BF1F               OUT     0x3F, R17\r
+     85          }\r
+   \   0000003C   9508               RET\r
+   \   0000003E                      REQUIRE _A_PORTA\r
+   \   0000003E                      REQUIRE _A_DDRA\r
+     86          \r
+     87          /*! \brief  Write a '0' to the bus(es). (Software only driver)\r
+     88           *\r
+     89           *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
+     90           *  bus.\r
+     91           *\r
+     92           *  \param  pins    A bitmask of the buses to write to.\r
+     93           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     94          void OWI_WriteBit0(unsigned char pins)\r
+   \                     OWI_WriteBit0:\r
+     95          {\r
+     96                unsigned char intState;\r
+     97                \r
+     98                // Disable interrupts.\r
+     99                intState = __save_interrupt();\r
+   \   00000000   B72F               IN      R18, 0x3F\r
+   \   00000002   2F12               MOV     R17, R18\r
+    100                __disable_interrupt();\r
+   \   00000004   94F8               CLI\r
+    101                \r
+    102                // Drive bus low and delay.\r
+    103                OWI_PULL_BUS_LOW(pins);\r
+   \   00000006   B32A               IN      R18, 0x1A\r
+   \   00000008   2B20               OR      R18, R16\r
+   \   0000000A   BB2A               OUT     0x1A, R18\r
+   \   0000000C   2F20               MOV     R18, R16\r
+   \   0000000E   9520               COM     R18\r
+   \   00000010   B33B               IN      R19, 0x1B\r
+   \   00000012   2332               AND     R19, R18\r
+   \   00000014   BB3B               OUT     0x1B, R19\r
+    104                __delay_cycles(OWI_DELAY_C_STD_MODE);\r
+   \   00000016   E92B               LDI     R18, 155\r
+   \   00000018   952A               DEC     R18\r
+   \   0000001A   F7F1               BRNE    $-2\r
+   \   0000001C   C000               RJMP    $+2\r
+    105                \r
+    106                // Release bus and delay.\r
+    107                OWI_RELEASE_BUS(pins);\r
+   \   0000001E   2F20               MOV     R18, R16\r
+   \   00000020   9520               COM     R18\r
+   \   00000022   B33A               IN      R19, 0x1A\r
+   \   00000024   2332               AND     R19, R18\r
+   \   00000026   BB3A               OUT     0x1A, R19\r
+   \   00000028   2F20               MOV     R18, R16\r
+   \   0000002A   9520               COM     R18\r
+   \   0000002C   B33B               IN      R19, 0x1B\r
+   \   0000002E   2332               AND     R19, R18\r
+   \   00000030   BB3B               OUT     0x1B, R19\r
+    108                __delay_cycles(OWI_DELAY_D_STD_MODE);\r
+   \   00000032   E126               LDI     R18, 22\r
+   \   00000034   952A               DEC     R18\r
+   \   00000036   F7F1               BRNE    $-2\r
+   \   00000038   0000               NOP\r
+    109                \r
+    110                // Restore interrupts.\r
+    111                __restore_interrupt(intState);\r
+   \   0000003A   BF1F               OUT     0x3F, R17\r
+    112          }\r
+   \   0000003C   9508               RET\r
+   \   0000003E                      REQUIRE _A_PORTA\r
+   \   0000003E                      REQUIRE _A_DDRA\r
+    113          \r
+    114          /*! \brief  Read a bit from the bus(es). (Software only driver)\r
+    115           *\r
+    116           *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
+    117           *\r
+    118           *  \param  pins    A bitmask of the bus(es) to read from.\r
+    119           *\r
+    120           *  \return A bitmask of the buses where a '1' was read.\r
+    121           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    122          unsigned char OWI_ReadBit(unsigned char pins)\r
+   \                     OWI_ReadBit:\r
+    123          {\r
+   \   00000000   2F10               MOV     R17, R16\r
+    124                unsigned char intState;\r
+    125                unsigned char bitsRead;\r
+    126                \r
+    127                // Disable interrupts.\r
+    128                intState = __save_interrupt();\r
+   \   00000002   B73F               IN      R19, 0x3F\r
+   \   00000004   2F23               MOV     R18, R19\r
+    129                __disable_interrupt();\r
+   \   00000006   94F8               CLI\r
+    130                \r
+    131                // Drive bus low and delay.\r
+    132                OWI_PULL_BUS_LOW(pins);\r
+   \   00000008   B33A               IN      R19, 0x1A\r
+   \   0000000A   2B31               OR      R19, R17\r
+   \   0000000C   BB3A               OUT     0x1A, R19\r
+   \   0000000E   2F31               MOV     R19, R17\r
+   \   00000010   9530               COM     R19\r
+   \   00000012   B34B               IN      R20, 0x1B\r
+   \   00000014   2343               AND     R20, R19\r
+   \   00000016   BB4B               OUT     0x1B, R20\r
+    133                __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+   \   00000018   E03B               LDI     R19, 11\r
+   \   0000001A   953A               DEC     R19\r
+   \   0000001C   F7F1               BRNE    $-2\r
+   \   0000001E   C000               RJMP    $+2\r
+    134                \r
+    135                // Release bus and delay.\r
+    136                OWI_RELEASE_BUS(pins);\r
+   \   00000020   2F31               MOV     R19, R17\r
+   \   00000022   9530               COM     R19\r
+   \   00000024   B34A               IN      R20, 0x1A\r
+   \   00000026   2343               AND     R20, R19\r
+   \   00000028   BB4A               OUT     0x1A, R20\r
+   \   0000002A   2F31               MOV     R19, R17\r
+   \   0000002C   9530               COM     R19\r
+   \   0000002E   B34B               IN      R20, 0x1B\r
+   \   00000030   2343               AND     R20, R19\r
+   \   00000032   BB4B               OUT     0x1B, R20\r
+    137                __delay_cycles(OWI_DELAY_E_STD_MODE);\r
+   \   00000034   E133               LDI     R19, 19\r
+   \   00000036   953A               DEC     R19\r
+   \   00000038   F7F1               BRNE    $-2\r
+   \   0000003A   C000               RJMP    $+2\r
+    138                \r
+    139                // Sample bus and delay.\r
+    140                bitsRead = OWI_PIN & pins;\r
+   \   0000003C   B339               IN      R19, 0x19\r
+   \   0000003E   2331               AND     R19, R17\r
+   \   00000040   2F03               MOV     R16, R19\r
+    141                __delay_cycles(OWI_DELAY_F_STD_MODE);\r
+   \   00000042   E83E               LDI     R19, 142\r
+   \   00000044   953A               DEC     R19\r
+   \   00000046   F7F1               BRNE    $-2\r
+   \   00000048   0000               NOP\r
+    142                \r
+    143                // Restore interrupts.\r
+    144                __restore_interrupt(intState);\r
+   \   0000004A   BF2F               OUT     0x3F, R18\r
+    145                \r
+    146                return bitsRead;\r
+   \   0000004C   9508               RET\r
+   \   0000004E                      REQUIRE _A_PORTA\r
+   \   0000004E                      REQUIRE _A_DDRA\r
+   \   0000004E                      REQUIRE _A_PINA\r
+    147          }\r
+    148          \r
+    149          \r
+    150          /*! \brief  Send a Reset signal and listen for Presence signal. (software\r
+    151           *  only driver)\r
+    152           *\r
+    153           *  Generates the waveform for transmission of a Reset pulse on the \r
+    154           *  1-Wire(R) bus and listens for presence signals.\r
+    155           *\r
+    156           *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
+    157           *\r
+    158           *  \return A bitmask of the buses where a presence signal was detected.\r
+    159           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    160          unsigned char OWI_DetectPresence(unsigned char pins)\r
+   \                     OWI_DetectPresence:\r
+    161          {\r
+   \   00000000   2F10               MOV     R17, R16\r
+    162                unsigned char intState;\r
+    163                unsigned char presenceDetected;\r
+    164                \r
+    165                // Disable interrupts.\r
+    166                intState = __save_interrupt();\r
+   \   00000002   B73F               IN      R19, 0x3F\r
+   \   00000004   2F23               MOV     R18, R19\r
+    167                __disable_interrupt();\r
+   \   00000006   94F8               CLI\r
+    168                \r
+    169                // Drive bus low and delay.\r
+    170                OWI_PULL_BUS_LOW(pins);\r
+   \   00000008   B33A               IN      R19, 0x1A\r
+   \   0000000A   2B31               OR      R19, R17\r
+   \   0000000C   BB3A               OUT     0x1A, R19\r
+   \   0000000E   2F31               MOV     R19, R17\r
+   \   00000010   9530               COM     R19\r
+   \   00000012   B34B               IN      R20, 0x1B\r
+   \   00000014   2343               AND     R20, R19\r
+   \   00000016   BB4B               OUT     0x1B, R20\r
+    171                __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+   \   00000018   EB4C               LDI     R20, 188\r
+   \   0000001A   E053               LDI     R21, 3\r
+   \   0000001C   5041               SUBI    R20, 1\r
+   \   0000001E   4050               SBCI    R21, 0\r
+   \   00000020   F7E9               BRNE    $-4\r
+   \   00000022   C000               RJMP    $+2\r
+    172                \r
+    173                // Release bus and delay.\r
+    174                OWI_RELEASE_BUS(pins);\r
+   \   00000024   2F31               MOV     R19, R17\r
+   \   00000026   9530               COM     R19\r
+   \   00000028   B34A               IN      R20, 0x1A\r
+   \   0000002A   2343               AND     R20, R19\r
+   \   0000002C   BB4A               OUT     0x1A, R20\r
+   \   0000002E   2F31               MOV     R19, R17\r
+   \   00000030   9530               COM     R19\r
+   \   00000032   B34B               IN      R20, 0x1B\r
+   \   00000034   2343               AND     R20, R19\r
+   \   00000036   BB4B               OUT     0x1B, R20\r
+    175                __delay_cycles(OWI_DELAY_I_STD_MODE);\r
+   \   00000038   EB36               LDI     R19, 182\r
+   \   0000003A   953A               DEC     R19\r
+   \   0000003C   F7F1               BRNE    $-2\r
+   \   0000003E   0000               NOP\r
+    176                \r
+    177                // Sample bus to detect presence signal and delay.\r
+    178                presenceDetected = ((~OWI_PIN) & pins);\r
+   \   00000040   B339               IN      R19, 0x19\r
+   \   00000042   9530               COM     R19\r
+   \   00000044   2331               AND     R19, R17\r
+   \   00000046   2F03               MOV     R16, R19\r
+    179                __delay_cycles(OWI_DELAY_J_STD_MODE);\r
+   \   00000048   E340               LDI     R20, 48\r
+   \   0000004A   E053               LDI     R21, 3\r
+   \   0000004C   5041               SUBI    R20, 1\r
+   \   0000004E   4050               SBCI    R21, 0\r
+   \   00000050   F7E9               BRNE    $-4\r
+   \   00000052   C000               RJMP    $+2\r
+    180                \r
+    181                // Restore interrupts.\r
+    182                __restore_interrupt(intState);\r
+   \   00000054   BF2F               OUT     0x3F, R18\r
+    183                \r
+    184                return presenceDetected;\r
+   \   00000056   9508               RET\r
+   \   00000058                      REQUIRE _A_PORTA\r
+   \   00000058                      REQUIRE _A_DDRA\r
+   \   00000058                      REQUIRE _A_PINA\r
+    185          }\r
+    186          \r
+    187          \r
+    188          /*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
+    189           *  \r
+    190           *  This function automates the task of sending a complete byte\r
+    191           *  of data on the 1-Wire bus(es).\r
+    192           *\r
+    193           *  \param  data    The data to send on the bus(es).\r
+    194           *  \r
+    195           *  \param  pins    A bitmask of the buses to send the data to.\r
+    196           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    197          void OWI_SendByte(unsigned char data, unsigned char pins)\r
+   \                     OWI_SendByte:\r
+    198          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+   \   00000002   2FA0               MOV     R26, R16\r
+   \   00000004   2F91               MOV     R25, R17\r
+    199                unsigned char temp;\r
+    200                unsigned char i;\r
+    201                \r
+    202                // Do once for each bit\r
+    203                for (i = 0; i < 8; i++) {\r
+   \   00000006   E080               LDI     R24, 0\r
+   \                     ??OWI_SendByte_0:\r
+   \   00000008   3088               CPI     R24, 8\r
+   \   0000000A   F468               BRCC    ??OWI_SendByte_1\r
+    204                        // Determine if LSB is '0' or '1' and transmit corresponding\r
+    205                        // waveform on the bus.\r
+    206                        temp = data & 0x01;\r
+   \   0000000C   2F0A               MOV     R16, R26\r
+   \   0000000E   7001               ANDI    R16, 0x01\r
+   \   00000010   2FB0               MOV     R27, R16\r
+    207                        \r
+    208                        if (temp) {\r
+   \   00000012   23BB               TST     R27\r
+   \   00000014   F019               BREQ    ??OWI_SendByte_2\r
+    209                                OWI_WriteBit1(pins);\r
+   \   00000016   2F09               MOV     R16, R25\r
+   \   00000018   ....               RCALL   OWI_WriteBit1\r
+   \   0000001A   C002               RJMP    ??OWI_SendByte_3\r
+    210                        } else {\r
+    211                                OWI_WriteBit0(pins);\r
+   \                     ??OWI_SendByte_2:\r
+   \   0000001C   2F09               MOV     R16, R25\r
+   \   0000001E   ....               RCALL   OWI_WriteBit0\r
+    212                        }\r
+    213                \r
+    214                        data >>= 1;  // Right shift the data to get next bit.\r
+   \                     ??OWI_SendByte_3:\r
+   \   00000020   95A6               LSR     R26\r
+    215                }\r
+   \   00000022   9583               INC     R24\r
+   \   00000024   CFF1               RJMP    ??OWI_SendByte_0\r
+    216          }\r
+   \                     ??OWI_SendByte_1:\r
+   \   00000026   E0E4               LDI     R30, 4\r
+   \   00000028   ....               RJMP    ?EPILOGUE_B4_L09\r
+    217          \r
+    218          \r
+    219          /*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
+    220           *\r
+    221           *  This function automates the task of receiving a complete byte \r
+    222           *  of data from the 1-Wire bus.\r
+    223           *\r
+    224           *  \param  pin     A bitmask of the bus to read from.\r
+    225           *  \r
+    226           *  \return     The byte read from the bus.\r
+    227           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    228          unsigned char OWI_ReceiveByte(unsigned char pin)\r
+   \                     OWI_ReceiveByte:\r
+    229          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE3_L09\r
+   \   00000002   2FA0               MOV     R26, R16\r
+    230                unsigned char data;\r
+    231                unsigned char i;\r
+    232                \r
+    233                // Clear the temporary input variable.\r
+    234                data = 0x00;\r
+   \   00000004   E090               LDI     R25, 0\r
+    235                \r
+    236                // Do once for each bit\r
+    237                for (i = 0; i < 8; i++) {\r
+   \   00000006   E080               LDI     R24, 0\r
+   \                     ??OWI_ReceiveByte_0:\r
+   \   00000008   3088               CPI     R24, 8\r
+   \   0000000A   F448               BRCC    ??OWI_ReceiveByte_1\r
+    238                        // Shift temporary input variable right.\r
+    239                        data >>= 1;\r
+   \   0000000C   9596               LSR     R25\r
+    240                        \r
+    241                        // Set the MSB if a '1' value is read from the bus.\r
+    242                        // Leave as it is ('0') else.\r
+    243                        if (OWI_ReadBit(pin)) {\r
+   \   0000000E   2F0A               MOV     R16, R26\r
+   \   00000010   ....               RCALL   OWI_ReadBit\r
+   \   00000012   2300               TST     R16\r
+   \   00000014   F011               BREQ    ??OWI_ReceiveByte_2\r
+    244                                data |= 0x80;\r
+   \   00000016   6890               ORI     R25, 0x80\r
+   \   00000018   E001               LDI     R16, 1\r
+    245                        }\r
+    246                }\r
+   \                     ??OWI_ReceiveByte_2:\r
+   \   0000001A   9583               INC     R24\r
+   \   0000001C   CFF5               RJMP    ??OWI_ReceiveByte_0\r
+    247                \r
+    248                return data;\r
+   \                     ??OWI_ReceiveByte_1:\r
+   \   0000001E   2F09               MOV     R16, R25\r
+   \   00000020   E0E3               LDI     R30, 3\r
+   \   00000022   ....               RJMP    ?EPILOGUE_B3_L09\r
+    249          }\r
+    250          \r
+    251          \r
+    252          /*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
+    253           *\r
+    254           *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
+    255           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    256          void OWI_SkipRom(unsigned char pins)\r
+   \                     OWI_SkipRom:\r
+    257          {\r
+   \   00000000   938A               ST      -Y, R24\r
+   \   00000002   2F80               MOV     R24, R16\r
+    258                // Send the SKIP ROM command on the bus.\r
+    259                OWI_SendByte(OWI_ROM_SKIP, pins);\r
+   \   00000004   2F18               MOV     R17, R24\r
+   \   00000006   EC0C               LDI     R16, 204\r
+   \   00000008   ....               RCALL   OWI_SendByte\r
+    260          }\r
+   \   0000000A   9189               LD      R24, Y+\r
+   \   0000000C   9508               RET\r
+    261          \r
+    262          \r
+    263          /*! \brief  Sends the READ ROM command and reads back the ROM id.\r
+    264           *\r
+    265           *  \param  romValue    A pointer where the id will be placed.\r
+    266           *\r
+    267           *  \param  pin     A bitmask of the bus to read from.\r
+    268           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    269          void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
+   \                     OWI_ReadRom:\r
+    270          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+   \   00000002   01D8               MOVW    R27:R26, R17:R16\r
+   \   00000004   2F92               MOV     R25, R18\r
+    271                unsigned char bytesLeft = 8;\r
+   \   00000006   E088               LDI     R24, 8\r
+    272                \r
+    273                // Send the READ ROM command on the bus.\r
+    274                OWI_SendByte(OWI_ROM_READ, pin);\r
+   \   00000008   2F19               MOV     R17, R25\r
+   \   0000000A   E303               LDI     R16, 51\r
+   \   0000000C   ....               RCALL   OWI_SendByte\r
+    275                \r
+    276                // Do 8 times.\r
+    277                while (bytesLeft > 0) {\r
+   \                     ??OWI_ReadRom_0:\r
+   \   0000000E   3081               CPI     R24, 1\r
+   \   00000010   F030               BRCS    ??OWI_ReadRom_1\r
+    278                        // Place the received data in memory.\r
+    279                        *romValue++ = OWI_ReceiveByte(pin);\r
+   \   00000012   2F09               MOV     R16, R25\r
+   \   00000014   ....               RCALL   OWI_ReceiveByte\r
+   \   00000016   930C               ST      X, R16\r
+   \   00000018   9611               ADIW    R27:R26, 1\r
+    280                        bytesLeft--;\r
+   \   0000001A   958A               DEC     R24\r
+   \   0000001C   CFF8               RJMP    ??OWI_ReadRom_0\r
+    281                }\r
+    282          }\r
+   \                     ??OWI_ReadRom_1:\r
+   \   0000001E   E0E4               LDI     R30, 4\r
+   \   00000020   ....               RJMP    ?EPILOGUE_B4_L09\r
+    283          \r
+    284          \r
+    285          /*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
+    286           *\r
+    287           *  \param  romValue    A pointer to the ID to match against.\r
+    288           *\r
+    289           *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
+    290           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    291          void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
+   \                     OWI_MatchRom:\r
+    292          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+   \   00000002   01D8               MOVW    R27:R26, R17:R16\r
+   \   00000004   2F92               MOV     R25, R18\r
+    293                unsigned char bytesLeft = 8;   \r
+   \   00000006   E088               LDI     R24, 8\r
+    294                \r
+    295                // Send the MATCH ROM command.\r
+    296                OWI_SendByte(OWI_ROM_MATCH, pins);\r
+   \   00000008   2F19               MOV     R17, R25\r
+   \   0000000A   E505               LDI     R16, 85\r
+   \   0000000C   ....               RCALL   OWI_SendByte\r
+    297                \r
+    298                // Do once for each byte.\r
+    299                while (bytesLeft > 0) {\r
+   \                     ??OWI_MatchRom_0:\r
+   \   0000000E   3081               CPI     R24, 1\r
+   \   00000010   F030               BRCS    ??OWI_MatchRom_1\r
+    300                        // Transmit 1 byte of the ID to match.\r
+    301                        OWI_SendByte(*romValue++, pins);\r
+   \   00000012   2F19               MOV     R17, R25\r
+   \   00000014   910C               LD      R16, X\r
+   \   00000016   ....               RCALL   OWI_SendByte\r
+   \   00000018   9611               ADIW    R27:R26, 1\r
+    302                        bytesLeft--;\r
+   \   0000001A   958A               DEC     R24\r
+   \   0000001C   CFF8               RJMP    ??OWI_MatchRom_0\r
+    303                }\r
+    304          }\r
+   \                     ??OWI_MatchRom_1:\r
+   \   0000001E   E0E4               LDI     R30, 4\r
+   \   00000020   ....               RJMP    ?EPILOGUE_B4_L09\r
+    305          \r
+    306          \r
+    307          /*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
+    308           *          1-Wire(R) bus.\r
+    309           *\r
+    310           *  \param  bitPattern      A pointer to an 8 byte char array where the \r
+    311           *                          discovered identifier will be placed. When \r
+    312           *                          searching for several slaves, a copy of the \r
+    313           *                          last found identifier should be supplied in \r
+    314           *                          the array, or the search will fail.\r
+    315           *\r
+    316           *  \param  lastDeviation   The bit position where the algorithm made a \r
+    317           *                          choice the last time it was run. This argument \r
+    318           *                          should be 0 when a search is initiated. Supplying \r
+    319           *                          the return argument of this function when calling \r
+    320           *                          repeatedly will go through the complete slave \r
+    321           *                          search.\r
+    322           *\r
+    323           *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
+    324           *\r
+    325           *  \return The last bit position where there was a discrepancy between slave\r
+    326           *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
+    327           *  if an error was detected (e.g. a device was connected to the bus during the\r
+    328           *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
+    329           *  discovered.\r
+    330           *\r
+    331           *  \note   See main.c for an example of how to utilize this function.\r
+    332           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    333          unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+   \                     OWI_SearchRom:\r
+    334                                                        unsigned char lastDeviation, unsigned char pin)\r
+    335          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE9_L09\r
+   \   00000002                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R7_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R8_is_cg_reg\r
+   \   00000002   0128               MOVW    R5:R4, R17:R16\r
+   \   00000004   2E82               MOV     R8, R18\r
+   \   00000006   2FB3               MOV     R27, R19\r
+    336                unsigned char currentBit = 1;\r
+   \   00000008   E081               LDI     R24, 1\r
+    337                unsigned char newDeviation = 0;\r
+   \   0000000A   E0A0               LDI     R26, 0\r
+    338                unsigned char bitMask = 0x01;\r
+   \   0000000C   E091               LDI     R25, 1\r
+    339                unsigned char bitA;\r
+    340                unsigned char bitB;\r
+    341                \r
+    342                // Send SEARCH ROM command on the bus.\r
+    343                OWI_SendByte(OWI_ROM_SEARCH, pin);\r
+   \   0000000E   2F1B               MOV     R17, R27\r
+   \   00000010   EF00               LDI     R16, 240\r
+   \   00000012   ....               RCALL   OWI_SendByte\r
+    344                \r
+    345                // Walk through all 64 bits.\r
+    346                while (currentBit <= 64) {\r
+   \                     ??OWI_SearchRom_0:\r
+   \   00000014   3481               CPI     R24, 65\r
+   \   00000016   F008               BRCS    $+2+2\r
+   \   00000018   C04B               RJMP    ??OWI_SearchRom_1\r
+    347                        // Read bit from bus twice.\r
+    348                        bitA = OWI_ReadBit(pin);\r
+   \   0000001A   2F0B               MOV     R16, R27\r
+   \   0000001C   ....               RCALL   OWI_ReadBit\r
+   \   0000001E   2E60               MOV     R6, R16\r
+    349                        bitB = OWI_ReadBit(pin);\r
+   \   00000020   2F0B               MOV     R16, R27\r
+   \   00000022   ....               RCALL   OWI_ReadBit\r
+   \   00000024   2E70               MOV     R7, R16\r
+    350                        \r
+    351                        if (bitA && bitB) {\r
+   \   00000026   2066               TST     R6\r
+   \   00000028   F029               BREQ    ??OWI_SearchRom_2\r
+   \   0000002A   2077               TST     R7\r
+   \   0000002C   F019               BREQ    ??OWI_SearchRom_2\r
+    352                                // Both bits 1 (Error).\r
+    353                                newDeviation = OWI_ROM_SEARCH_FAILED;\r
+   \   0000002E   EFAF               LDI     R26, 255\r
+    354                                return newDeviation;\r
+   \   00000030   2F0A               MOV     R16, R26\r
+   \   00000032   C03F               RJMP    ??OWI_SearchRom_3\r
+    355                        } else if (bitA ^ bitB) {\r
+   \                     ??OWI_SearchRom_2:\r
+   \   00000034   2D07               MOV     R16, R7\r
+   \   00000036   2506               EOR     R16, R6\r
+   \   00000038   2300               TST     R16\r
+   \   0000003A   F071               BREQ    ??OWI_SearchRom_4\r
+    356                                // Bits A and B are different. All devices have the same bit here.\r
+    357                                // Set the bit in bitPattern to this value.\r
+    358                                if (bitA) {\r
+   \   0000003C   2066               TST     R6\r
+   \   0000003E   F029               BREQ    ??OWI_SearchRom_5\r
+    359                                        (*bitPattern) |= bitMask;\r
+   \   00000040   01F2               MOVW    R31:R30, R5:R4\r
+   \   00000042   8100               LD      R16, Z\r
+   \   00000044   2B09               OR      R16, R25\r
+   \   00000046   8300               ST      Z, R16\r
+   \   00000048   C01E               RJMP    ??OWI_SearchRom_6\r
+    360                                } else {\r
+    361                                        (*bitPattern) &= ~bitMask;\r
+   \                     ??OWI_SearchRom_5:\r
+   \   0000004A   2F09               MOV     R16, R25\r
+   \   0000004C   9500               COM     R16\r
+   \   0000004E   01F2               MOVW    R31:R30, R5:R4\r
+   \   00000050   8110               LD      R17, Z\r
+   \   00000052   2310               AND     R17, R16\r
+   \   00000054   8310               ST      Z, R17\r
+   \   00000056   C017               RJMP    ??OWI_SearchRom_6\r
+    362                                }\r
+    363                        } else {\r
+    364                                // If this is where a choice was made the last time,\r
+    365                                // a '1' bit is selected this time.\r
+    366                                if (currentBit == lastDeviation) {\r
+   \                     ??OWI_SearchRom_4:\r
+   \   00000058   1588               CP      R24, R8\r
+   \   0000005A   F429               BRNE    ??OWI_SearchRom_7\r
+    367                                        (*bitPattern) |= bitMask;\r
+   \   0000005C   01F2               MOVW    R31:R30, R5:R4\r
+   \   0000005E   8100               LD      R16, Z\r
+   \   00000060   2B09               OR      R16, R25\r
+   \   00000062   8300               ST      Z, R16\r
+   \   00000064   C010               RJMP    ??OWI_SearchRom_6\r
+    368                                }\r
+    369                                \r
+    370                                // For the rest of the id, '0' bits are selected when\r
+    371                                // discrepancies occur.\r
+    372                                else if (currentBit > lastDeviation) {\r
+   \                     ??OWI_SearchRom_7:\r
+   \   00000066   1688               CP      R8, R24\r
+   \   00000068   F440               BRCC    ??OWI_SearchRom_8\r
+    373                                        (*bitPattern) &= ~bitMask;\r
+   \   0000006A   2F09               MOV     R16, R25\r
+   \   0000006C   9500               COM     R16\r
+   \   0000006E   01F2               MOVW    R31:R30, R5:R4\r
+   \   00000070   8110               LD      R17, Z\r
+   \   00000072   2310               AND     R17, R16\r
+   \   00000074   8310               ST      Z, R17\r
+    374                                        newDeviation = currentBit;\r
+   \   00000076   2FA8               MOV     R26, R24\r
+   \   00000078   C006               RJMP    ??OWI_SearchRom_6\r
+    375                                }\r
+    376                                \r
+    377                                // If current bit in bit pattern = 0, then this is\r
+    378                                // out new deviation.\r
+    379                                else if ( !(*bitPattern & bitMask)) {\r
+   \                     ??OWI_SearchRom_8:\r
+   \   0000007A   01F2               MOVW    R31:R30, R5:R4\r
+   \   0000007C   8100               LD      R16, Z\r
+   \   0000007E   2309               AND     R16, R25\r
+   \   00000080   2300               TST     R16\r
+   \   00000082   F409               BRNE    ??OWI_SearchRom_6\r
+    380                                        newDeviation = currentBit;\r
+   \   00000084   2FA8               MOV     R26, R24\r
+    381                                }\r
+    382                                \r
+    383                        // IF the bit is already 1, do nothing.\r
+    384                                else {\r
+    385                                }\r
+    386                        }\r
+    387                        \r
+    388                        // Send the selected bit to the bus.\r
+    389                        if ((*bitPattern) & bitMask) {\r
+   \                     ??OWI_SearchRom_6:\r
+   \   00000086   01F2               MOVW    R31:R30, R5:R4\r
+   \   00000088   8100               LD      R16, Z\r
+   \   0000008A   2309               AND     R16, R25\r
+   \   0000008C   2300               TST     R16\r
+   \   0000008E   F019               BREQ    ??OWI_SearchRom_9\r
+    390                                OWI_WriteBit1(pin);\r
+   \   00000090   2F0B               MOV     R16, R27\r
+   \   00000092   ....               RCALL   OWI_WriteBit1\r
+   \   00000094   C002               RJMP    ??OWI_SearchRom_10\r
+    391                        } else {\r
+    392                                OWI_WriteBit0(pin);\r
+   \                     ??OWI_SearchRom_9:\r
+   \   00000096   2F0B               MOV     R16, R27\r
+   \   00000098   ....               RCALL   OWI_WriteBit0\r
+    393                        }\r
+    394                        \r
+    395                        // Increment current bit.    \r
+    396                        currentBit++;\r
+   \                     ??OWI_SearchRom_10:\r
+   \   0000009A   9583               INC     R24\r
+    397                        \r
+    398                        // Adjust bitMask and bitPattern pointer.    \r
+    399                        bitMask <<= 1;\r
+   \   0000009C   0F99               LSL     R25\r
+    400                        if (!bitMask) {\r
+   \   0000009E   2399               TST     R25\r
+   \   000000A0   F009               BREQ    $+2+2\r
+   \   000000A2   CFB8               RJMP    ??OWI_SearchRom_0\r
+    401                                bitMask = 0x01;\r
+   \   000000A4   E091               LDI     R25, 1\r
+    402                                bitPattern++;\r
+   \   000000A6   E001               LDI     R16, 1\r
+   \   000000A8   0E40               ADD     R4, R16\r
+   \   000000AA   E000               LDI     R16, 0\r
+   \   000000AC   1E50               ADC     R5, R16\r
+   \   000000AE   CFB2               RJMP    ??OWI_SearchRom_0\r
+    403                        }\r
+    404                }\r
+    405                \r
+    406                return newDeviation;\r
+   \                     ??OWI_SearchRom_1:\r
+   \   000000B0   2F0A               MOV     R16, R26\r
+   \                     ??OWI_SearchRom_3:\r
+   \   000000B2   E0E9               LDI     R30, 9\r
+   \   000000B4   ....               RJMP    ?EPILOGUE_B9_L09\r
+    407          }\r
+    408          \r
+    409          \r
+    410          /* Functions for handling CRC */\r
+    411          /*! \brief  Compute the CRC8 value of a data set.\r
+    412           *\r
+    413           *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
+    414           *  as inital value for the CRC.\r
+    415           *\r
+    416           *  \param  inData  One byte of data to compute CRC from.\r
+    417           *\r
+    418           *  \param  seed    The starting value of the CRC.\r
+    419           *\r
+    420           *  \return The CRC8 of inData with seed as initial value.\r
+    421           *\r
+    422           *  \note   Setting seed to 0 computes the crc8 of the inData.\r
+    423           *\r
+    424           *  \note   Constantly passing the return value of this function \r
+    425           *          As the seed argument computes the CRC8 value of a\r
+    426           *          longer string of data.\r
+    427           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    428          unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
+   \                     OWI_ComputeCRC8:\r
+    429          {\r
+   \   00000000   2F30               MOV     R19, R16\r
+   \   00000002   2F01               MOV     R16, R17\r
+    430                unsigned char bitsLeft;\r
+    431                unsigned char temp;\r
+    432                \r
+    433                for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+   \   00000004   E018               LDI     R17, 8\r
+   \                     ??OWI_ComputeCRC8_0:\r
+   \   00000006   3011               CPI     R17, 1\r
+   \   00000008   F098               BRCS    ??OWI_ComputeCRC8_1\r
+    434                        temp = ((seed ^ inData) & 0x01);\r
+   \   0000000A   2F50               MOV     R21, R16\r
+   \   0000000C   7051               ANDI    R21, 0x01\r
+   \   0000000E   2F23               MOV     R18, R19\r
+   \   00000010   7021               ANDI    R18, 0x01\r
+   \   00000012   2725               EOR     R18, R21\r
+   \   00000014   7021               ANDI    R18, 0x01\r
+   \   00000016   2F42               MOV     R20, R18\r
+    435                        \r
+    436                        if (temp == 0) {\r
+   \   00000018   2344               TST     R20\r
+   \   0000001A   F411               BRNE    ??OWI_ComputeCRC8_2\r
+    437                        seed >>= 1;\r
+   \   0000001C   9506               LSR     R16\r
+   \   0000001E   C005               RJMP    ??OWI_ComputeCRC8_3\r
+    438                        } else {\r
+    439                                seed ^= 0x18;\r
+   \                     ??OWI_ComputeCRC8_2:\r
+   \   00000020   E128               LDI     R18, 24\r
+   \   00000022   2702               EOR     R16, R18\r
+    440                                seed >>= 1;\r
+   \   00000024   9506               LSR     R16\r
+    441                                seed |= 0x80;\r
+   \   00000026   6800               ORI     R16, 0x80\r
+   \   00000028   E021               LDI     R18, 1\r
+    442                        }\r
+    443                        \r
+    444                        inData >>= 1;\r
+   \                     ??OWI_ComputeCRC8_3:\r
+   \   0000002A   9536               LSR     R19\r
+    445                }\r
+   \   0000002C   951A               DEC     R17\r
+   \   0000002E   CFEB               RJMP    ??OWI_ComputeCRC8_0\r
+    446                return seed;    \r
+   \                     ??OWI_ComputeCRC8_1:\r
+   \   00000030   9508               RET\r
+    447          }\r
+    448          \r
+    449          \r
+    450          /*! \brief  Compute the CRC16 value of a data set.\r
+    451           *\r
+    452           *  This function will compute the CRC16 of inData using seed\r
+    453           *  as inital value for the CRC.\r
+    454           *\r
+    455           *  \param  inData  One byte of data to compute CRC from.\r
+    456           *\r
+    457           *  \param  seed    The starting value of the CRC.\r
+    458           *\r
+    459           *  \return The CRC16 of inData with seed as initial value.\r
+    460           *\r
+    461           *  \note   Setting seed to 0 computes the crc16 of the inData.\r
+    462           *\r
+    463           *  \note   Constantly passing the return value of this function \r
+    464           *          As the seed argument computes the CRC16 value of a\r
+    465           *          longer string of data.\r
+    466           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    467          unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
+   \                     OWI_ComputeCRC16:\r
+    468          {\r
+   \   00000000   2F50               MOV     R21, R16\r
+    469                unsigned char bitsLeft;\r
+    470                unsigned char temp;\r
+    471                \r
+    472                for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+   \   00000002   E048               LDI     R20, 8\r
+   \                     ??OWI_ComputeCRC16_0:\r
+   \   00000004   3041               CPI     R20, 1\r
+   \   00000006   F0C0               BRCS    ??OWI_ComputeCRC16_1\r
+    473                        temp = ((seed ^ inData) & 0x01);\r
+   \   00000008   2F12               MOV     R17, R18\r
+   \   0000000A   7011               ANDI    R17, 0x01\r
+   \   0000000C   2F05               MOV     R16, R21\r
+   \   0000000E   7001               ANDI    R16, 0x01\r
+   \   00000010   2701               EOR     R16, R17\r
+   \   00000012   7001               ANDI    R16, 0x01\r
+   \   00000014   2F60               MOV     R22, R16\r
+    474                        \r
+    475                        if (temp == 0) {\r
+   \   00000016   2366               TST     R22\r
+   \   00000018   F419               BRNE    ??OWI_ComputeCRC16_2\r
+    476                                seed >>= 1;\r
+   \   0000001A   9536               LSR     R19\r
+   \   0000001C   9527               ROR     R18\r
+   \   0000001E   C009               RJMP    ??OWI_ComputeCRC16_3\r
+    477                  } else {\r
+    478                                seed ^= 0x4002;\r
+   \                     ??OWI_ComputeCRC16_2:\r
+   \   00000020   E002               LDI     R16, 2\r
+   \   00000022   E410               LDI     R17, 64\r
+   \   00000024   2720               EOR     R18, R16\r
+   \   00000026   2731               EOR     R19, R17\r
+    479                                seed >>= 1;\r
+   \   00000028   9536               LSR     R19\r
+   \   0000002A   9527               ROR     R18\r
+    480                                seed |= 0x8000;\r
+   \   0000002C   6830               ORI     R19, 0x80\r
+   \   0000002E   E001               LDI     R16, 1\r
+   \   00000030   E010               LDI     R17, 0\r
+    481                        }\r
+    482          \r
+    483                        inData >>= 1;\r
+   \                     ??OWI_ComputeCRC16_3:\r
+   \   00000032   9556               LSR     R21\r
+    484                }\r
+   \   00000034   954A               DEC     R20\r
+   \   00000036   CFE6               RJMP    ??OWI_ComputeCRC16_0\r
+    485                \r
+    486                return seed;    \r
+   \                     ??OWI_ComputeCRC16_1:\r
+   \   00000038   0189               MOVW    R17:R16, R19:R18\r
+   \   0000003A   9508               RET\r
+    487          }\r
+    488          \r
+    489          \r
+    490          /*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
+    491           *  \r
+    492           *  This function computes the CRC8 value of the first 56 bits of a\r
+    493           *  64 bit identifier. It then checks the calculated value against the\r
+    494           *  CRC value stored in ROM.\r
+    495           *\r
+    496           *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
+    497           *\r
+    498           *  \retval OWI_CRC_OK      The CRC's matched.\r
+    499           *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
+    500           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    501          unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
+   \                     OWI_CheckRomCRC:\r
+    502          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+   \   00000002   01D8               MOVW    R27:R26, R17:R16\r
+    503                unsigned char i;\r
+    504                unsigned char crc8 = 0;\r
+   \   00000004   E090               LDI     R25, 0\r
+    505                \r
+    506                for (i = 0; i < 7; i++) {\r
+   \   00000006   E080               LDI     R24, 0\r
+   \                     ??OWI_CheckRomCRC_0:\r
+   \   00000008   3087               CPI     R24, 7\r
+   \   0000000A   F440               BRCC    ??OWI_CheckRomCRC_1\r
+    507                        crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
+   \   0000000C   2F19               MOV     R17, R25\r
+   \   0000000E   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000010   8100               LD      R16, Z\r
+   \   00000012   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000014   2F90               MOV     R25, R16\r
+    508                        romValue++;\r
+   \   00000016   9611               ADIW    R27:R26, 1\r
+    509                }\r
+   \   00000018   9583               INC     R24\r
+   \   0000001A   CFF6               RJMP    ??OWI_CheckRomCRC_0\r
+    510                \r
+    511                if (crc8 == (*romValue)) {\r
+   \                     ??OWI_CheckRomCRC_1:\r
+   \   0000001C   910C               LD      R16, X\r
+   \   0000001E   1790               CP      R25, R16\r
+   \   00000020   F411               BRNE    ??OWI_CheckRomCRC_2\r
+    512                        return OWI_CRC_OK;\r
+   \   00000022   E000               LDI     R16, 0\r
+   \   00000024   C001               RJMP    ??OWI_CheckRomCRC_3\r
+    513                }\r
+    514                \r
+    515                return OWI_CRC_ERROR;\r
+   \                     ??OWI_CheckRomCRC_2:\r
+   \   00000026   E001               LDI     R16, 1\r
+   \                     ??OWI_CheckRomCRC_3:\r
+   \   00000028   E0E4               LDI     R30, 4\r
+   \   0000002A   ....               RJMP    ?EPILOGUE_B4_L09\r
+    516          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function             CSTACK RSTACK\r
+     --------             ------ ------\r
+     OWI_CheckRomCRC          4      2\r
+       -> OWI_ComputeCRC8     4      2\r
+     OWI_ComputeCRC16         0      2\r
+     OWI_ComputeCRC8          0      2\r
+     OWI_DetectPresence       0      2\r
+     OWI_Init                 0      2\r
+     OWI_MatchRom             4      2\r
+       -> OWI_SendByte        4      2\r
+       -> OWI_SendByte        4      2\r
+     OWI_ReadBit              0      2\r
+     OWI_ReadRom              4      2\r
+       -> OWI_SendByte        4      2\r
+       -> OWI_ReceiveByte     4      2\r
+     OWI_ReceiveByte          3      2\r
+       -> OWI_ReadBit         3      2\r
+     OWI_SearchRom            9      2\r
+       -> OWI_SendByte        9      2\r
+       -> OWI_ReadBit         9      2\r
+       -> OWI_ReadBit         9      2\r
+       -> OWI_WriteBit1       9      2\r
+       -> OWI_WriteBit0       9      2\r
+     OWI_SendByte             4      2\r
+       -> OWI_WriteBit1       4      2\r
+       -> OWI_WriteBit0       4      2\r
+     OWI_SkipRom              1      2\r
+       -> OWI_SendByte        1      2\r
+     OWI_WriteBit0            0      2\r
+     OWI_WriteBit1            0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label     Bytes\r
+     --------------     -----\r
+     _A_PORTA              1\r
+     _A_DDRA               1\r
+     _A_PINA               1\r
+     OWI_Init             34\r
+     OWI_WriteBit1        62\r
+     OWI_WriteBit0        62\r
+     OWI_ReadBit          78\r
+     OWI_DetectPresence   88\r
+     OWI_SendByte         42\r
+     OWI_ReceiveByte      36\r
+     OWI_SkipRom          14\r
+     OWI_ReadRom          34\r
+     OWI_MatchRom         34\r
+     OWI_SearchRom       182\r
+     OWI_ComputeCRC8      50\r
+     OWI_ComputeCRC16     60\r
+     OWI_CheckRomCRC      44\r
+\r
\r
+   3 bytes in segment ABSOLUTE\r
+ 820 bytes in segment CODE\r
\r
+ 820 bytes of CODE memory\r
+   0 bytes of DATA memory (+ 3 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/OWI.s90 b/BaseTinyFirmware/IAR/Debug/List/OWI.s90
new file mode 100644 (file)
index 0000000..9a58126
--- /dev/null
@@ -0,0 +1,1120 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:38 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c               /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c               /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\OWI.s90  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME OWI\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B3_L09\r
+        EXTERN ?EPILOGUE_B4_L09\r
+        EXTERN ?EPILOGUE_B9_L09\r
+        EXTERN ?PROLOGUE3_L09\r
+        EXTERN ?PROLOGUE4_L09\r
+        EXTERN ?PROLOGUE9_L09\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?Register_R7_is_cg_reg\r
+        EXTERN ?Register_R8_is_cg_reg\r
+\r
+        PUBLIC OWI_CheckRomCRC\r
+        PUBLIC OWI_ComputeCRC16\r
+        PUBLIC OWI_ComputeCRC8\r
+        PUBLIC OWI_DetectPresence\r
+        PUBLIC OWI_Init\r
+        PUBLIC OWI_MatchRom\r
+        PUBLIC OWI_ReadBit\r
+        PUBLIC OWI_ReadRom\r
+        PUBLIC OWI_ReceiveByte\r
+        PUBLIC OWI_SearchRom\r
+        PUBLIC OWI_SendByte\r
+        PUBLIC OWI_SkipRom\r
+        PUBLIC OWI_WriteBit0\r
+        PUBLIC OWI_WriteBit1\r
+        PUBWEAK _A_DDRA\r
+        PUBWEAK _A_PINA\r
+        PUBWEAK _A_PORTA\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file ********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for 1-Wire(R) bus communication\r
+//    6  *\r
+//    7  *      High level functions for transmission of full bytes on the 1-Wire(R)\r
+//    8  *      bus and implementations of ROM commands.\n\r
+//    9  *      Polled software only implementation of the basic bit-level signalling\r
+//   10  *      in the 1-Wire(R) protocol.\n\r
+//   11  *      Includes functions for computing and checking CRC8 & 16 values of data\r
+//   12  *      sets, and of 64 bit ROM identifiers.\r
+//   13  *      Supported devices:  All AVRs.\r
+//   14  *\r
+//   15  * \par Application Note:\r
+//   16  *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+//   17  *      AVR463: Charging NiMH Batteries with BC100\n\r
+//   18  *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+//   19  *\r
+//   20  * \par Documentation:\r
+//   21  *      For comprehensive code documentation, supported compilers, compiler\r
+//   22  *      settings and supported devices see readme.html\r
+//   23  *\r
+//   24  * \author\r
+//   25  *      Atmel Corporation: http://www.atmel.com \n\r
+//   26  *      Support email: avr@atmel.com \n\r
+//   27  *      Original author: \n\r
+//   28  *\r
+//   29  * $Name$\r
+//   30  * $Revision: 2299 $\r
+//   31  * $RCSfile$\r
+//   32  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
+//   33  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   34 ****************************************************************************/\r
+//   35 \r
+//   36 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03bH\r
+// <unnamed> volatile __io _A_PORTA\r
+_A_PORTA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03aH\r
+// <unnamed> volatile __io _A_DDRA\r
+_A_DDRA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,039H\r
+// <unnamed> volatile __io _A_PINA\r
+_A_PINA:\r
+        DS 1\r
+//   37 #include <inavr.h>\r
+//   38 \r
+//   39 #include "OWI.h"\r
+//   40 \r
+//   41 \r
+//   42 //******************************************************************************\r
+//   43 // Functions\r
+//   44 //******************************************************************************\r
+//   45 /*! \brief Initialization of the one wire bus(es). (Software only driver)\r
+//   46  *  \r
+//   47  *  This function initializes the 1-Wire bus(es) by releasing it and\r
+//   48  *  waiting until any presence signals are finished.\r
+//   49  *\r
+//   50  *  \param  pins    A bitmask of the buses to initialize.\r
+//   51  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   52 void OWI_Init(unsigned char pins){\r
+OWI_Init:\r
+//   53        OWI_RELEASE_BUS(pins);\r
+        MOV     R17, R16\r
+        COM     R17\r
+        IN      R18, 0x1A\r
+        AND     R18, R17\r
+        OUT     0x1A, R18\r
+        MOV     R17, R16\r
+        COM     R17\r
+        IN      R18, 0x1B\r
+        AND     R18, R17\r
+        OUT     0x1B, R18\r
+//   54        // The first rising edge can be interpreted by a slave as the end of a\r
+//   55        // Reset-pulse. Delay for the required reset recovery time (H) to be \r
+//   56        // sure that the real reset is interpreted correctly.\r
+//   57        __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+        LDI     R18, 188\r
+        LDI     R19, 3\r
+        SUBI    R18, 1\r
+        SBCI    R19, 0\r
+        BRNE    $-4\r
+        RJMP    $+2\r
+//   58 }\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+//   59 \r
+//   60 \r
+//   61 /*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
+//   62  *\r
+//   63  *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
+//   64  *  bus.\r
+//   65  *\r
+//   66  *  \param  pins    A bitmask of the buses to write to.\r
+//   67  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   68 void OWI_WriteBit1(unsigned char pins){\r
+OWI_WriteBit1:\r
+//   69        unsigned char intState;\r
+//   70        \r
+//   71        // Disable interrupts.\r
+//   72        intState = __save_interrupt();\r
+        IN      R18, 0x3F\r
+        MOV     R17, R18\r
+//   73        __disable_interrupt();\r
+        CLI\r
+//   74        \r
+//   75        // Drive bus low and delay.\r
+//   76        OWI_PULL_BUS_LOW(pins);\r
+        IN      R18, 0x1A\r
+        OR      R18, R16\r
+        OUT     0x1A, R18\r
+        MOV     R18, R16\r
+        COM     R18\r
+        IN      R19, 0x1B\r
+        AND     R19, R18\r
+        OUT     0x1B, R19\r
+//   77        __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+        LDI     R18, 11\r
+        DEC     R18\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//   78        \r
+//   79        // Release bus and delay.\r
+//   80        OWI_RELEASE_BUS(pins);\r
+        MOV     R18, R16\r
+        COM     R18\r
+        IN      R19, 0x1A\r
+        AND     R19, R18\r
+        OUT     0x1A, R19\r
+        MOV     R18, R16\r
+        COM     R18\r
+        IN      R19, 0x1B\r
+        AND     R19, R18\r
+        OUT     0x1B, R19\r
+//   81        __delay_cycles(OWI_DELAY_B_STD_MODE);\r
+        LDI     R18, 166\r
+        DEC     R18\r
+        BRNE    $-2\r
+        NOP\r
+//   82        \r
+//   83        // Restore interrupts.\r
+//   84        __restore_interrupt(intState);\r
+        OUT     0x3F, R17\r
+//   85 }\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+//   86 \r
+//   87 /*! \brief  Write a '0' to the bus(es). (Software only driver)\r
+//   88  *\r
+//   89  *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
+//   90  *  bus.\r
+//   91  *\r
+//   92  *  \param  pins    A bitmask of the buses to write to.\r
+//   93  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   94 void OWI_WriteBit0(unsigned char pins)\r
+OWI_WriteBit0:\r
+//   95 {\r
+//   96        unsigned char intState;\r
+//   97        \r
+//   98        // Disable interrupts.\r
+//   99        intState = __save_interrupt();\r
+        IN      R18, 0x3F\r
+        MOV     R17, R18\r
+//  100        __disable_interrupt();\r
+        CLI\r
+//  101        \r
+//  102        // Drive bus low and delay.\r
+//  103        OWI_PULL_BUS_LOW(pins);\r
+        IN      R18, 0x1A\r
+        OR      R18, R16\r
+        OUT     0x1A, R18\r
+        MOV     R18, R16\r
+        COM     R18\r
+        IN      R19, 0x1B\r
+        AND     R19, R18\r
+        OUT     0x1B, R19\r
+//  104        __delay_cycles(OWI_DELAY_C_STD_MODE);\r
+        LDI     R18, 155\r
+        DEC     R18\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//  105        \r
+//  106        // Release bus and delay.\r
+//  107        OWI_RELEASE_BUS(pins);\r
+        MOV     R18, R16\r
+        COM     R18\r
+        IN      R19, 0x1A\r
+        AND     R19, R18\r
+        OUT     0x1A, R19\r
+        MOV     R18, R16\r
+        COM     R18\r
+        IN      R19, 0x1B\r
+        AND     R19, R18\r
+        OUT     0x1B, R19\r
+//  108        __delay_cycles(OWI_DELAY_D_STD_MODE);\r
+        LDI     R18, 22\r
+        DEC     R18\r
+        BRNE    $-2\r
+        NOP\r
+//  109        \r
+//  110        // Restore interrupts.\r
+//  111        __restore_interrupt(intState);\r
+        OUT     0x3F, R17\r
+//  112 }\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+//  113 \r
+//  114 /*! \brief  Read a bit from the bus(es). (Software only driver)\r
+//  115  *\r
+//  116  *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
+//  117  *\r
+//  118  *  \param  pins    A bitmask of the bus(es) to read from.\r
+//  119  *\r
+//  120  *  \return A bitmask of the buses where a '1' was read.\r
+//  121  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  122 unsigned char OWI_ReadBit(unsigned char pins)\r
+OWI_ReadBit:\r
+//  123 {\r
+        MOV     R17, R16\r
+//  124        unsigned char intState;\r
+//  125        unsigned char bitsRead;\r
+//  126        \r
+//  127        // Disable interrupts.\r
+//  128        intState = __save_interrupt();\r
+        IN      R19, 0x3F\r
+        MOV     R18, R19\r
+//  129        __disable_interrupt();\r
+        CLI\r
+//  130        \r
+//  131        // Drive bus low and delay.\r
+//  132        OWI_PULL_BUS_LOW(pins);\r
+        IN      R19, 0x1A\r
+        OR      R19, R17\r
+        OUT     0x1A, R19\r
+        MOV     R19, R17\r
+        COM     R19\r
+        IN      R20, 0x1B\r
+        AND     R20, R19\r
+        OUT     0x1B, R20\r
+//  133        __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+        LDI     R19, 11\r
+        DEC     R19\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//  134        \r
+//  135        // Release bus and delay.\r
+//  136        OWI_RELEASE_BUS(pins);\r
+        MOV     R19, R17\r
+        COM     R19\r
+        IN      R20, 0x1A\r
+        AND     R20, R19\r
+        OUT     0x1A, R20\r
+        MOV     R19, R17\r
+        COM     R19\r
+        IN      R20, 0x1B\r
+        AND     R20, R19\r
+        OUT     0x1B, R20\r
+//  137        __delay_cycles(OWI_DELAY_E_STD_MODE);\r
+        LDI     R19, 19\r
+        DEC     R19\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//  138        \r
+//  139        // Sample bus and delay.\r
+//  140        bitsRead = OWI_PIN & pins;\r
+        IN      R19, 0x19\r
+        AND     R19, R17\r
+        MOV     R16, R19\r
+//  141        __delay_cycles(OWI_DELAY_F_STD_MODE);\r
+        LDI     R19, 142\r
+        DEC     R19\r
+        BRNE    $-2\r
+        NOP\r
+//  142        \r
+//  143        // Restore interrupts.\r
+//  144        __restore_interrupt(intState);\r
+        OUT     0x3F, R18\r
+//  145        \r
+//  146        return bitsRead;\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+        REQUIRE _A_PINA\r
+//  147 }\r
+//  148 \r
+//  149 \r
+//  150 /*! \brief  Send a Reset signal and listen for Presence signal. (software\r
+//  151  *  only driver)\r
+//  152  *\r
+//  153  *  Generates the waveform for transmission of a Reset pulse on the \r
+//  154  *  1-Wire(R) bus and listens for presence signals.\r
+//  155  *\r
+//  156  *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
+//  157  *\r
+//  158  *  \return A bitmask of the buses where a presence signal was detected.\r
+//  159  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  160 unsigned char OWI_DetectPresence(unsigned char pins)\r
+OWI_DetectPresence:\r
+//  161 {\r
+        MOV     R17, R16\r
+//  162        unsigned char intState;\r
+//  163        unsigned char presenceDetected;\r
+//  164        \r
+//  165        // Disable interrupts.\r
+//  166        intState = __save_interrupt();\r
+        IN      R19, 0x3F\r
+        MOV     R18, R19\r
+//  167        __disable_interrupt();\r
+        CLI\r
+//  168        \r
+//  169        // Drive bus low and delay.\r
+//  170        OWI_PULL_BUS_LOW(pins);\r
+        IN      R19, 0x1A\r
+        OR      R19, R17\r
+        OUT     0x1A, R19\r
+        MOV     R19, R17\r
+        COM     R19\r
+        IN      R20, 0x1B\r
+        AND     R20, R19\r
+        OUT     0x1B, R20\r
+//  171        __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+        LDI     R20, 188\r
+        LDI     R21, 3\r
+        SUBI    R20, 1\r
+        SBCI    R21, 0\r
+        BRNE    $-4\r
+        RJMP    $+2\r
+//  172        \r
+//  173        // Release bus and delay.\r
+//  174        OWI_RELEASE_BUS(pins);\r
+        MOV     R19, R17\r
+        COM     R19\r
+        IN      R20, 0x1A\r
+        AND     R20, R19\r
+        OUT     0x1A, R20\r
+        MOV     R19, R17\r
+        COM     R19\r
+        IN      R20, 0x1B\r
+        AND     R20, R19\r
+        OUT     0x1B, R20\r
+//  175        __delay_cycles(OWI_DELAY_I_STD_MODE);\r
+        LDI     R19, 182\r
+        DEC     R19\r
+        BRNE    $-2\r
+        NOP\r
+//  176        \r
+//  177        // Sample bus to detect presence signal and delay.\r
+//  178        presenceDetected = ((~OWI_PIN) & pins);\r
+        IN      R19, 0x19\r
+        COM     R19\r
+        AND     R19, R17\r
+        MOV     R16, R19\r
+//  179        __delay_cycles(OWI_DELAY_J_STD_MODE);\r
+        LDI     R20, 48\r
+        LDI     R21, 3\r
+        SUBI    R20, 1\r
+        SBCI    R21, 0\r
+        BRNE    $-4\r
+        RJMP    $+2\r
+//  180        \r
+//  181        // Restore interrupts.\r
+//  182        __restore_interrupt(intState);\r
+        OUT     0x3F, R18\r
+//  183        \r
+//  184        return presenceDetected;\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+        REQUIRE _A_PINA\r
+//  185 }\r
+//  186 \r
+//  187 \r
+//  188 /*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
+//  189  *  \r
+//  190  *  This function automates the task of sending a complete byte\r
+//  191  *  of data on the 1-Wire bus(es).\r
+//  192  *\r
+//  193  *  \param  data    The data to send on the bus(es).\r
+//  194  *  \r
+//  195  *  \param  pins    A bitmask of the buses to send the data to.\r
+//  196  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  197 void OWI_SendByte(unsigned char data, unsigned char pins)\r
+OWI_SendByte:\r
+//  198 {\r
+        RCALL   ?PROLOGUE4_L09\r
+        MOV     R26, R16\r
+        MOV     R25, R17\r
+//  199        unsigned char temp;\r
+//  200        unsigned char i;\r
+//  201        \r
+//  202        // Do once for each bit\r
+//  203        for (i = 0; i < 8; i++) {\r
+        LDI     R24, 0\r
+??OWI_SendByte_0:\r
+        CPI     R24, 8\r
+        BRCC    ??OWI_SendByte_1\r
+//  204                // Determine if LSB is '0' or '1' and transmit corresponding\r
+//  205                // waveform on the bus.\r
+//  206                temp = data & 0x01;\r
+        MOV     R16, R26\r
+        ANDI    R16, 0x01\r
+        MOV     R27, R16\r
+//  207                \r
+//  208                if (temp) {\r
+        TST     R27\r
+        BREQ    ??OWI_SendByte_2\r
+//  209                        OWI_WriteBit1(pins);\r
+        MOV     R16, R25\r
+        RCALL   OWI_WriteBit1\r
+        RJMP    ??OWI_SendByte_3\r
+//  210                } else {\r
+//  211                        OWI_WriteBit0(pins);\r
+??OWI_SendByte_2:\r
+        MOV     R16, R25\r
+        RCALL   OWI_WriteBit0\r
+//  212                }\r
+//  213        \r
+//  214                data >>= 1;  // Right shift the data to get next bit.\r
+??OWI_SendByte_3:\r
+        LSR     R26\r
+//  215        }\r
+        INC     R24\r
+        RJMP    ??OWI_SendByte_0\r
+//  216 }\r
+??OWI_SendByte_1:\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  217 \r
+//  218 \r
+//  219 /*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
+//  220  *\r
+//  221  *  This function automates the task of receiving a complete byte \r
+//  222  *  of data from the 1-Wire bus.\r
+//  223  *\r
+//  224  *  \param  pin     A bitmask of the bus to read from.\r
+//  225  *  \r
+//  226  *  \return     The byte read from the bus.\r
+//  227  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  228 unsigned char OWI_ReceiveByte(unsigned char pin)\r
+OWI_ReceiveByte:\r
+//  229 {\r
+        RCALL   ?PROLOGUE3_L09\r
+        MOV     R26, R16\r
+//  230        unsigned char data;\r
+//  231        unsigned char i;\r
+//  232        \r
+//  233        // Clear the temporary input variable.\r
+//  234        data = 0x00;\r
+        LDI     R25, 0\r
+//  235        \r
+//  236        // Do once for each bit\r
+//  237        for (i = 0; i < 8; i++) {\r
+        LDI     R24, 0\r
+??OWI_ReceiveByte_0:\r
+        CPI     R24, 8\r
+        BRCC    ??OWI_ReceiveByte_1\r
+//  238                // Shift temporary input variable right.\r
+//  239                data >>= 1;\r
+        LSR     R25\r
+//  240                \r
+//  241                // Set the MSB if a '1' value is read from the bus.\r
+//  242                // Leave as it is ('0') else.\r
+//  243                if (OWI_ReadBit(pin)) {\r
+        MOV     R16, R26\r
+        RCALL   OWI_ReadBit\r
+        TST     R16\r
+        BREQ    ??OWI_ReceiveByte_2\r
+//  244                        data |= 0x80;\r
+        ORI     R25, 0x80\r
+        LDI     R16, 1\r
+//  245                }\r
+//  246        }\r
+??OWI_ReceiveByte_2:\r
+        INC     R24\r
+        RJMP    ??OWI_ReceiveByte_0\r
+//  247        \r
+//  248        return data;\r
+??OWI_ReceiveByte_1:\r
+        MOV     R16, R25\r
+        LDI     R30, 3\r
+        RJMP    ?EPILOGUE_B3_L09\r
+//  249 }\r
+//  250 \r
+//  251 \r
+//  252 /*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
+//  253  *\r
+//  254  *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
+//  255  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  256 void OWI_SkipRom(unsigned char pins)\r
+OWI_SkipRom:\r
+//  257 {\r
+        ST      -Y, R24\r
+        MOV     R24, R16\r
+//  258        // Send the SKIP ROM command on the bus.\r
+//  259        OWI_SendByte(OWI_ROM_SKIP, pins);\r
+        MOV     R17, R24\r
+        LDI     R16, 204\r
+        RCALL   OWI_SendByte\r
+//  260 }\r
+        LD      R24, Y+\r
+        RET\r
+//  261 \r
+//  262 \r
+//  263 /*! \brief  Sends the READ ROM command and reads back the ROM id.\r
+//  264  *\r
+//  265  *  \param  romValue    A pointer where the id will be placed.\r
+//  266  *\r
+//  267  *  \param  pin     A bitmask of the bus to read from.\r
+//  268  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
+OWI_ReadRom:\r
+//  270 {\r
+        RCALL   ?PROLOGUE4_L09\r
+        MOVW    R27:R26, R17:R16\r
+        MOV     R25, R18\r
+//  271        unsigned char bytesLeft = 8;\r
+        LDI     R24, 8\r
+//  272        \r
+//  273        // Send the READ ROM command on the bus.\r
+//  274        OWI_SendByte(OWI_ROM_READ, pin);\r
+        MOV     R17, R25\r
+        LDI     R16, 51\r
+        RCALL   OWI_SendByte\r
+//  275        \r
+//  276        // Do 8 times.\r
+//  277        while (bytesLeft > 0) {\r
+??OWI_ReadRom_0:\r
+        CPI     R24, 1\r
+        BRCS    ??OWI_ReadRom_1\r
+//  278                // Place the received data in memory.\r
+//  279                *romValue++ = OWI_ReceiveByte(pin);\r
+        MOV     R16, R25\r
+        RCALL   OWI_ReceiveByte\r
+        ST      X, R16\r
+        ADIW    R27:R26, 1\r
+//  280                bytesLeft--;\r
+        DEC     R24\r
+        RJMP    ??OWI_ReadRom_0\r
+//  281        }\r
+//  282 }\r
+??OWI_ReadRom_1:\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  283 \r
+//  284 \r
+//  285 /*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
+//  286  *\r
+//  287  *  \param  romValue    A pointer to the ID to match against.\r
+//  288  *\r
+//  289  *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
+//  290  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
+OWI_MatchRom:\r
+//  292 {\r
+        RCALL   ?PROLOGUE4_L09\r
+        MOVW    R27:R26, R17:R16\r
+        MOV     R25, R18\r
+//  293        unsigned char bytesLeft = 8;   \r
+        LDI     R24, 8\r
+//  294        \r
+//  295        // Send the MATCH ROM command.\r
+//  296        OWI_SendByte(OWI_ROM_MATCH, pins);\r
+        MOV     R17, R25\r
+        LDI     R16, 85\r
+        RCALL   OWI_SendByte\r
+//  297        \r
+//  298        // Do once for each byte.\r
+//  299        while (bytesLeft > 0) {\r
+??OWI_MatchRom_0:\r
+        CPI     R24, 1\r
+        BRCS    ??OWI_MatchRom_1\r
+//  300                // Transmit 1 byte of the ID to match.\r
+//  301                OWI_SendByte(*romValue++, pins);\r
+        MOV     R17, R25\r
+        LD      R16, X\r
+        RCALL   OWI_SendByte\r
+        ADIW    R27:R26, 1\r
+//  302                bytesLeft--;\r
+        DEC     R24\r
+        RJMP    ??OWI_MatchRom_0\r
+//  303        }\r
+//  304 }\r
+??OWI_MatchRom_1:\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  305 \r
+//  306 \r
+//  307 /*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
+//  308  *          1-Wire(R) bus.\r
+//  309  *\r
+//  310  *  \param  bitPattern      A pointer to an 8 byte char array where the \r
+//  311  *                          discovered identifier will be placed. When \r
+//  312  *                          searching for several slaves, a copy of the \r
+//  313  *                          last found identifier should be supplied in \r
+//  314  *                          the array, or the search will fail.\r
+//  315  *\r
+//  316  *  \param  lastDeviation   The bit position where the algorithm made a \r
+//  317  *                          choice the last time it was run. This argument \r
+//  318  *                          should be 0 when a search is initiated. Supplying \r
+//  319  *                          the return argument of this function when calling \r
+//  320  *                          repeatedly will go through the complete slave \r
+//  321  *                          search.\r
+//  322  *\r
+//  323  *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
+//  324  *\r
+//  325  *  \return The last bit position where there was a discrepancy between slave\r
+//  326  *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
+//  327  *  if an error was detected (e.g. a device was connected to the bus during the\r
+//  328  *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
+//  329  *  discovered.\r
+//  330  *\r
+//  331  *  \note   See main.c for an example of how to utilize this function.\r
+//  332  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  333 unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+OWI_SearchRom:\r
+//  334                                                unsigned char lastDeviation, unsigned char pin)\r
+//  335 {\r
+        RCALL   ?PROLOGUE9_L09\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        REQUIRE ?Register_R7_is_cg_reg\r
+        REQUIRE ?Register_R8_is_cg_reg\r
+        MOVW    R5:R4, R17:R16\r
+        MOV     R8, R18\r
+        MOV     R27, R19\r
+//  336        unsigned char currentBit = 1;\r
+        LDI     R24, 1\r
+//  337        unsigned char newDeviation = 0;\r
+        LDI     R26, 0\r
+//  338        unsigned char bitMask = 0x01;\r
+        LDI     R25, 1\r
+//  339        unsigned char bitA;\r
+//  340        unsigned char bitB;\r
+//  341        \r
+//  342        // Send SEARCH ROM command on the bus.\r
+//  343        OWI_SendByte(OWI_ROM_SEARCH, pin);\r
+        MOV     R17, R27\r
+        LDI     R16, 240\r
+        RCALL   OWI_SendByte\r
+//  344        \r
+//  345        // Walk through all 64 bits.\r
+//  346        while (currentBit <= 64) {\r
+??OWI_SearchRom_0:\r
+        CPI     R24, 65\r
+        BRCS    $+2+2\r
+        RJMP    ??OWI_SearchRom_1\r
+//  347                // Read bit from bus twice.\r
+//  348                bitA = OWI_ReadBit(pin);\r
+        MOV     R16, R27\r
+        RCALL   OWI_ReadBit\r
+        MOV     R6, R16\r
+//  349                bitB = OWI_ReadBit(pin);\r
+        MOV     R16, R27\r
+        RCALL   OWI_ReadBit\r
+        MOV     R7, R16\r
+//  350                \r
+//  351                if (bitA && bitB) {\r
+        TST     R6\r
+        BREQ    ??OWI_SearchRom_2\r
+        TST     R7\r
+        BREQ    ??OWI_SearchRom_2\r
+//  352                        // Both bits 1 (Error).\r
+//  353                        newDeviation = OWI_ROM_SEARCH_FAILED;\r
+        LDI     R26, 255\r
+//  354                        return newDeviation;\r
+        MOV     R16, R26\r
+        RJMP    ??OWI_SearchRom_3\r
+//  355                } else if (bitA ^ bitB) {\r
+??OWI_SearchRom_2:\r
+        MOV     R16, R7\r
+        EOR     R16, R6\r
+        TST     R16\r
+        BREQ    ??OWI_SearchRom_4\r
+//  356                        // Bits A and B are different. All devices have the same bit here.\r
+//  357                        // Set the bit in bitPattern to this value.\r
+//  358                        if (bitA) {\r
+        TST     R6\r
+        BREQ    ??OWI_SearchRom_5\r
+//  359                                (*bitPattern) |= bitMask;\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R16, Z\r
+        OR      R16, R25\r
+        ST      Z, R16\r
+        RJMP    ??OWI_SearchRom_6\r
+//  360                        } else {\r
+//  361                                (*bitPattern) &= ~bitMask;\r
+??OWI_SearchRom_5:\r
+        MOV     R16, R25\r
+        COM     R16\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+        RJMP    ??OWI_SearchRom_6\r
+//  362                        }\r
+//  363                } else {\r
+//  364                        // If this is where a choice was made the last time,\r
+//  365                        // a '1' bit is selected this time.\r
+//  366                        if (currentBit == lastDeviation) {\r
+??OWI_SearchRom_4:\r
+        CP      R24, R8\r
+        BRNE    ??OWI_SearchRom_7\r
+//  367                                (*bitPattern) |= bitMask;\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R16, Z\r
+        OR      R16, R25\r
+        ST      Z, R16\r
+        RJMP    ??OWI_SearchRom_6\r
+//  368                        }\r
+//  369                        \r
+//  370                        // For the rest of the id, '0' bits are selected when\r
+//  371                        // discrepancies occur.\r
+//  372                        else if (currentBit > lastDeviation) {\r
+??OWI_SearchRom_7:\r
+        CP      R8, R24\r
+        BRCC    ??OWI_SearchRom_8\r
+//  373                                (*bitPattern) &= ~bitMask;\r
+        MOV     R16, R25\r
+        COM     R16\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+//  374                                newDeviation = currentBit;\r
+        MOV     R26, R24\r
+        RJMP    ??OWI_SearchRom_6\r
+//  375                        }\r
+//  376                        \r
+//  377                        // If current bit in bit pattern = 0, then this is\r
+//  378                        // out new deviation.\r
+//  379                        else if ( !(*bitPattern & bitMask)) {\r
+??OWI_SearchRom_8:\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R16, Z\r
+        AND     R16, R25\r
+        TST     R16\r
+        BRNE    ??OWI_SearchRom_6\r
+//  380                                newDeviation = currentBit;\r
+        MOV     R26, R24\r
+//  381                        }\r
+//  382                        \r
+//  383                // IF the bit is already 1, do nothing.\r
+//  384                        else {\r
+//  385                        }\r
+//  386                }\r
+//  387                \r
+//  388                // Send the selected bit to the bus.\r
+//  389                if ((*bitPattern) & bitMask) {\r
+??OWI_SearchRom_6:\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R16, Z\r
+        AND     R16, R25\r
+        TST     R16\r
+        BREQ    ??OWI_SearchRom_9\r
+//  390                        OWI_WriteBit1(pin);\r
+        MOV     R16, R27\r
+        RCALL   OWI_WriteBit1\r
+        RJMP    ??OWI_SearchRom_10\r
+//  391                } else {\r
+//  392                        OWI_WriteBit0(pin);\r
+??OWI_SearchRom_9:\r
+        MOV     R16, R27\r
+        RCALL   OWI_WriteBit0\r
+//  393                }\r
+//  394                \r
+//  395                // Increment current bit.    \r
+//  396                currentBit++;\r
+??OWI_SearchRom_10:\r
+        INC     R24\r
+//  397                \r
+//  398                // Adjust bitMask and bitPattern pointer.    \r
+//  399                bitMask <<= 1;\r
+        LSL     R25\r
+//  400                if (!bitMask) {\r
+        TST     R25\r
+        BREQ    $+2+2\r
+        RJMP    ??OWI_SearchRom_0\r
+//  401                        bitMask = 0x01;\r
+        LDI     R25, 1\r
+//  402                        bitPattern++;\r
+        LDI     R16, 1\r
+        ADD     R4, R16\r
+        LDI     R16, 0\r
+        ADC     R5, R16\r
+        RJMP    ??OWI_SearchRom_0\r
+//  403                }\r
+//  404        }\r
+//  405        \r
+//  406        return newDeviation;\r
+??OWI_SearchRom_1:\r
+        MOV     R16, R26\r
+??OWI_SearchRom_3:\r
+        LDI     R30, 9\r
+        RJMP    ?EPILOGUE_B9_L09\r
+//  407 }\r
+//  408 \r
+//  409 \r
+//  410 /* Functions for handling CRC */\r
+//  411 /*! \brief  Compute the CRC8 value of a data set.\r
+//  412  *\r
+//  413  *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
+//  414  *  as inital value for the CRC.\r
+//  415  *\r
+//  416  *  \param  inData  One byte of data to compute CRC from.\r
+//  417  *\r
+//  418  *  \param  seed    The starting value of the CRC.\r
+//  419  *\r
+//  420  *  \return The CRC8 of inData with seed as initial value.\r
+//  421  *\r
+//  422  *  \note   Setting seed to 0 computes the crc8 of the inData.\r
+//  423  *\r
+//  424  *  \note   Constantly passing the return value of this function \r
+//  425  *          As the seed argument computes the CRC8 value of a\r
+//  426  *          longer string of data.\r
+//  427  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
+OWI_ComputeCRC8:\r
+//  429 {\r
+        MOV     R19, R16\r
+        MOV     R16, R17\r
+//  430        unsigned char bitsLeft;\r
+//  431        unsigned char temp;\r
+//  432        \r
+//  433        for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+        LDI     R17, 8\r
+??OWI_ComputeCRC8_0:\r
+        CPI     R17, 1\r
+        BRCS    ??OWI_ComputeCRC8_1\r
+//  434                temp = ((seed ^ inData) & 0x01);\r
+        MOV     R21, R16\r
+        ANDI    R21, 0x01\r
+        MOV     R18, R19\r
+        ANDI    R18, 0x01\r
+        EOR     R18, R21\r
+        ANDI    R18, 0x01\r
+        MOV     R20, R18\r
+//  435                \r
+//  436                if (temp == 0) {\r
+        TST     R20\r
+        BRNE    ??OWI_ComputeCRC8_2\r
+//  437                seed >>= 1;\r
+        LSR     R16\r
+        RJMP    ??OWI_ComputeCRC8_3\r
+//  438                } else {\r
+//  439                        seed ^= 0x18;\r
+??OWI_ComputeCRC8_2:\r
+        LDI     R18, 24\r
+        EOR     R16, R18\r
+//  440                        seed >>= 1;\r
+        LSR     R16\r
+//  441                        seed |= 0x80;\r
+        ORI     R16, 0x80\r
+        LDI     R18, 1\r
+//  442                }\r
+//  443                \r
+//  444                inData >>= 1;\r
+??OWI_ComputeCRC8_3:\r
+        LSR     R19\r
+//  445        }\r
+        DEC     R17\r
+        RJMP    ??OWI_ComputeCRC8_0\r
+//  446        return seed;    \r
+??OWI_ComputeCRC8_1:\r
+        RET\r
+//  447 }\r
+//  448 \r
+//  449 \r
+//  450 /*! \brief  Compute the CRC16 value of a data set.\r
+//  451  *\r
+//  452  *  This function will compute the CRC16 of inData using seed\r
+//  453  *  as inital value for the CRC.\r
+//  454  *\r
+//  455  *  \param  inData  One byte of data to compute CRC from.\r
+//  456  *\r
+//  457  *  \param  seed    The starting value of the CRC.\r
+//  458  *\r
+//  459  *  \return The CRC16 of inData with seed as initial value.\r
+//  460  *\r
+//  461  *  \note   Setting seed to 0 computes the crc16 of the inData.\r
+//  462  *\r
+//  463  *  \note   Constantly passing the return value of this function \r
+//  464  *          As the seed argument computes the CRC16 value of a\r
+//  465  *          longer string of data.\r
+//  466  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
+OWI_ComputeCRC16:\r
+//  468 {\r
+        MOV     R21, R16\r
+//  469        unsigned char bitsLeft;\r
+//  470        unsigned char temp;\r
+//  471        \r
+//  472        for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+        LDI     R20, 8\r
+??OWI_ComputeCRC16_0:\r
+        CPI     R20, 1\r
+        BRCS    ??OWI_ComputeCRC16_1\r
+//  473                temp = ((seed ^ inData) & 0x01);\r
+        MOV     R17, R18\r
+        ANDI    R17, 0x01\r
+        MOV     R16, R21\r
+        ANDI    R16, 0x01\r
+        EOR     R16, R17\r
+        ANDI    R16, 0x01\r
+        MOV     R22, R16\r
+//  474                \r
+//  475                if (temp == 0) {\r
+        TST     R22\r
+        BRNE    ??OWI_ComputeCRC16_2\r
+//  476                        seed >>= 1;\r
+        LSR     R19\r
+        ROR     R18\r
+        RJMP    ??OWI_ComputeCRC16_3\r
+//  477          } else {\r
+//  478                        seed ^= 0x4002;\r
+??OWI_ComputeCRC16_2:\r
+        LDI     R16, 2\r
+        LDI     R17, 64\r
+        EOR     R18, R16\r
+        EOR     R19, R17\r
+//  479                        seed >>= 1;\r
+        LSR     R19\r
+        ROR     R18\r
+//  480                        seed |= 0x8000;\r
+        ORI     R19, 0x80\r
+        LDI     R16, 1\r
+        LDI     R17, 0\r
+//  481                }\r
+//  482 \r
+//  483                inData >>= 1;\r
+??OWI_ComputeCRC16_3:\r
+        LSR     R21\r
+//  484        }\r
+        DEC     R20\r
+        RJMP    ??OWI_ComputeCRC16_0\r
+//  485        \r
+//  486        return seed;    \r
+??OWI_ComputeCRC16_1:\r
+        MOVW    R17:R16, R19:R18\r
+        RET\r
+//  487 }\r
+//  488 \r
+//  489 \r
+//  490 /*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
+//  491  *  \r
+//  492  *  This function computes the CRC8 value of the first 56 bits of a\r
+//  493  *  64 bit identifier. It then checks the calculated value against the\r
+//  494  *  CRC value stored in ROM.\r
+//  495  *\r
+//  496  *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
+//  497  *\r
+//  498  *  \retval OWI_CRC_OK      The CRC's matched.\r
+//  499  *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
+//  500  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  501 unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
+OWI_CheckRomCRC:\r
+//  502 {\r
+        RCALL   ?PROLOGUE4_L09\r
+        MOVW    R27:R26, R17:R16\r
+//  503        unsigned char i;\r
+//  504        unsigned char crc8 = 0;\r
+        LDI     R25, 0\r
+//  505        \r
+//  506        for (i = 0; i < 7; i++) {\r
+        LDI     R24, 0\r
+??OWI_CheckRomCRC_0:\r
+        CPI     R24, 7\r
+        BRCC    ??OWI_CheckRomCRC_1\r
+//  507                crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
+        MOV     R17, R25\r
+        MOVW    R31:R30, R27:R26\r
+        LD      R16, Z\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R25, R16\r
+//  508                romValue++;\r
+        ADIW    R27:R26, 1\r
+//  509        }\r
+        INC     R24\r
+        RJMP    ??OWI_CheckRomCRC_0\r
+//  510        \r
+//  511        if (crc8 == (*romValue)) {\r
+??OWI_CheckRomCRC_1:\r
+        LD      R16, X\r
+        CP      R25, R16\r
+        BRNE    ??OWI_CheckRomCRC_2\r
+//  512                return OWI_CRC_OK;\r
+        LDI     R16, 0\r
+        RJMP    ??OWI_CheckRomCRC_3\r
+//  513        }\r
+//  514        \r
+//  515        return OWI_CRC_ERROR;\r
+??OWI_CheckRomCRC_2:\r
+        LDI     R16, 1\r
+??OWI_CheckRomCRC_3:\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  516 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+// \r
+//   3 bytes in segment ABSOLUTE\r
+// 820 bytes in segment CODE\r
+// \r
+// 820 bytes of CODE memory\r
+//   0 bytes of DATA memory (+ 3 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/PWM.lst b/BaseTinyFirmware/IAR/Debug/List/PWM.lst
new file mode 100644 (file)
index 0000000..f58fee0
--- /dev/null
@@ -0,0 +1,400 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:38 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c                #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c --cpu=tiny861  #\r
+#                    -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\    #\r
+#                    -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB  #\r
+#                    C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\          #\r
+#                    --initializers_in_flash -z2 --no_cse --no_inline         #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\PWM.lst   #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90    #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for use of PWM\r
+      6           *\r
+      7           *      Contains functions for initializing and controlling PWM output.\r
+      8           *\r
+      9           * \par Application note:\r
+     10           *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+     11           *      AVR463: Charging NiMH Batteries with BC100\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2299 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
+     26           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x50\r
+   \   <unnamed> volatile __io _A_TCCR1A\r
+   \                     _A_TCCR1A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4f\r
+   \   <unnamed> volatile __io _A_TCCR1B\r
+   \                     _A_TCCR1B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4d\r
+   \   <unnamed> volatile __io _A_OCR1A\r
+   \                     _A_OCR1A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4c\r
+   \   <unnamed> volatile __io _A_OCR1B\r
+   \                     _A_OCR1B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4b\r
+   \   <unnamed> volatile __io _A_OCR1C\r
+   \                     _A_OCR1C:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4a\r
+   \   <unnamed> volatile __io _A_OCR1D\r
+   \                     _A_OCR1D:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x49\r
+   \   <unnamed> volatile __io _A_PLLCSR\r
+   \                     _A_PLLCSR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x47\r
+   \   <unnamed> volatile __io _A_TCCR1C\r
+   \                     _A_TCCR1C:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x46\r
+   \   <unnamed> volatile __io _A_TCCR1D\r
+   \                     _A_TCCR1D:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x44\r
+   \   <unnamed> volatile __io _A_DT1\r
+   \                     _A_DT1:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x37\r
+   \   <unnamed> volatile __io _A_DDRB\r
+   \                     _A_DDRB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x20\r
+   \   <unnamed> volatile __io _A_TCCR1E\r
+   \                     _A_TCCR1E:\r
+   \   00000000                      DS 1\r
+     30          \r
+     31          #include "enums.h"\r
+     32          \r
+     33          #include "main.h"\r
+     34          #include "PWM.h"\r
+     35          #include "time.h"\r
+     36          \r
+     37          \r
+     38          //******************************************************************************\r
+     39          // Functions\r
+     40          //******************************************************************************\r
+     41          /*! \brief Stops PWM output\r
+     42           *\r
+     43           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     44          void PWM_Stop(void)\r
+   \                     PWM_Stop:\r
+     45          {\r
+     46                OCR1B = 0;  // Reset compare level.\r
+   \   00000000   E000               LDI     R16, 0\r
+   \   00000002   BD0C               OUT     0x2C, R16\r
+     47                PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
+   \   00000004   E000               LDI     R16, 0\r
+   \   00000006   BD09               OUT     0x29, R16\r
+     48                TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
+   \   00000008   E000               LDI     R16, 0\r
+   \   0000000A   BF00               OUT     0x30, R16\r
+     49                TCCR1B = 0; // Stop timer/counter1.\r
+   \   0000000C   E000               LDI     R16, 0\r
+   \   0000000E   BD0F               OUT     0x2F, R16\r
+     50                TCCR1C = 0; // Set normal port operation.\r
+   \   00000010   E000               LDI     R16, 0\r
+   \   00000012   BD07               OUT     0x27, R16\r
+     51                TCCR1D = 0; // No fault protection, normal waveform.\r
+   \   00000014   E000               LDI     R16, 0\r
+   \   00000016   BD06               OUT     0x26, R16\r
+     52                OCR1C = 0;  // Reset compare.\r
+   \   00000018   E000               LDI     R16, 0\r
+   \   0000001A   BD0B               OUT     0x2B, R16\r
+     53                OCR1D = 0;  // Reset compare.\r
+   \   0000001C   E000               LDI     R16, 0\r
+   \   0000001E   BD0A               OUT     0x2A, R16\r
+     54                DT1 = 0;    // No dead time values.\r
+   \   00000020   E000               LDI     R16, 0\r
+   \   00000022   BD04               OUT     0x24, R16\r
+     55          }\r
+   \   00000024   9508               RET\r
+   \   00000026                      REQUIRE _A_TCCR1A\r
+   \   00000026                      REQUIRE _A_TCCR1B\r
+   \   00000026                      REQUIRE _A_OCR1B\r
+   \   00000026                      REQUIRE _A_OCR1C\r
+   \   00000026                      REQUIRE _A_OCR1D\r
+   \   00000026                      REQUIRE _A_PLLCSR\r
+   \   00000026                      REQUIRE _A_TCCR1C\r
+   \   00000026                      REQUIRE _A_TCCR1D\r
+   \   00000026                      REQUIRE _A_DT1\r
+     56          \r
+     57          \r
+     58          /*! \brief Initializes and starts PWM output\r
+     59           *\r
+     60           * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
+     61           * Its comparator is connected to PB3 and will output high until timer1 reaches\r
+     62           * the value of OCR1B. It is then dropped to 0.\n\r
+     63           * The comparator outputs high again when the counter overflows, which will\r
+     64           * happen at a rate of 250 kHz.\r
+     65           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     66          void PWM_Start(void)\r
+   \                     PWM_Start:\r
+     67          {\r
+     68                // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
+     69                TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
+   \   00000000   E201               LDI     R16, 33\r
+   \   00000002   BF00               OUT     0x30, R16\r
+     70                \r
+     71                // Non-inverted PWM, T/C stopped.\r
+     72                TCCR1B = 0;\r
+   \   00000004   E000               LDI     R16, 0\r
+   \   00000006   BD0F               OUT     0x2F, R16\r
+     73                \r
+     74                // Copy shadow bits, disconnect OC1D.\r
+     75                TCCR1C = (TCCR1A & 0xF0);\r
+   \   00000008   B700               IN      R16, 0x30\r
+   \   0000000A   7F00               ANDI    R16, 0xF0\r
+   \   0000000C   BD07               OUT     0x27, R16\r
+     76                \r
+     77                // No fault protection, use phase & frequency correct PWM.\r
+     78                TCCR1D = (0<<WGM11)|(1<WGM10);\r
+   \   0000000E   E000               LDI     R16, 0\r
+   \   00000010   BD06               OUT     0x26, R16\r
+     79                \r
+     80                // Does not matter -- PWM6 mode not used.\r
+     81                TCCR1E = 0;\r
+   \   00000012   E000               LDI     R16, 0\r
+   \   00000014   B900               OUT     0x00, R16\r
+     82                \r
+     83                // Does not matter -- OC1A is disabled.\r
+     84                OCR1A = 0;\r
+   \   00000016   E000               LDI     R16, 0\r
+   \   00000018   BD0D               OUT     0x2D, R16\r
+     85                \r
+     86                // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
+     87                OCR1B = PWM_OFFSET;\r
+   \   0000001A   E00C               LDI     R16, 12\r
+   \   0000001C   BD0C               OUT     0x2C, R16\r
+     88                \r
+     89                // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
+     90                OCR1C = 0xFF;\r
+   \   0000001E   EF0F               LDI     R16, 255\r
+   \   00000020   BD0B               OUT     0x2B, R16\r
+     91                \r
+     92                // Does not matter -- OC1D is disabled.\r
+     93                OCR1D = 0;\r
+   \   00000022   E000               LDI     R16, 0\r
+   \   00000024   BD0A               OUT     0x2A, R16\r
+     94                \r
+     95                // No dead time values.\r
+     96                DT1 = 0;\r
+   \   00000026   E000               LDI     R16, 0\r
+   \   00000028   BD04               OUT     0x24, R16\r
+     97                \r
+     98                // Set PWM port pin to output.\r
+     99                DDRB |= (1<<PB3);\r
+   \   0000002A   9ABB               SBI     0x17, 0x03\r
+    100                \r
+    101                // Enable PLL, use full speed mode.\r
+    102                PLLCSR = (0<<LSM) | (1<<PLLE);\r
+   \   0000002C   E002               LDI     R16, 2\r
+   \   0000002E   BD09               OUT     0x29, R16\r
+    103                \r
+    104                // Use general timer and wait 1 ms for PLL lock to settle.\r
+    105                Time_Set(TIMER_GEN,0,0,1);\r
+   \   00000030   E041               LDI     R20, 1\r
+   \   00000032   E010               LDI     R17, 0\r
+   \   00000034   E020               LDI     R18, 0\r
+   \   00000036   E030               LDI     R19, 0\r
+   \   00000038   E002               LDI     R16, 2\r
+   \   0000003A   ....               RCALL   Time_Set\r
+    106                do{ \r
+    107                }while(Time_Left(TIMER_GEN));\r
+   \                     ??PWM_Start_0:\r
+   \   0000003C   E002               LDI     R16, 2\r
+   \   0000003E   ....               RCALL   Time_Left\r
+   \   00000040   2300               TST     R16\r
+   \   00000042   F7E1               BRNE    ??PWM_Start_0\r
+    108                \r
+    109                // Now wait for PLL to lock.\r
+    110                do{ \r
+    111                }while((PLLCSR & (1<<PLOCK)) == 0);\r
+   \                     ??PWM_Start_1:\r
+   \   00000044   B509               IN      R16, 0x29\r
+   \   00000046   2F10               MOV     R17, R16\r
+   \   00000048   FF10               SBRS    R17, 0\r
+   \   0000004A   CFFC               RJMP    ??PWM_Start_1\r
+    112          \r
+    113                // Use PLL as clock source.\r
+    114                PLLCSR |= (1<<PCKE);\r
+   \   0000004C   B509               IN      R16, 0x29\r
+   \   0000004E   6004               ORI     R16, 0x04\r
+   \   00000050   BD09               OUT     0x29, R16\r
+    115                \r
+    116                // CLK PCK = 64MHz / 1 = 64MHz.\r
+    117                TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
+   \   00000052   B50F               IN      R16, 0x2F\r
+   \   00000054   6001               ORI     R16, 0x01\r
+   \   00000056   BD0F               OUT     0x2F, R16\r
+    118          }\r
+   \   00000058   9508               RET\r
+   \   0000005A                      REQUIRE _A_TCCR1A\r
+   \   0000005A                      REQUIRE _A_TCCR1B\r
+   \   0000005A                      REQUIRE _A_OCR1A\r
+   \   0000005A                      REQUIRE _A_OCR1B\r
+   \   0000005A                      REQUIRE _A_OCR1C\r
+   \   0000005A                      REQUIRE _A_OCR1D\r
+   \   0000005A                      REQUIRE _A_PLLCSR\r
+   \   0000005A                      REQUIRE _A_TCCR1C\r
+   \   0000005A                      REQUIRE _A_TCCR1D\r
+   \   0000005A                      REQUIRE _A_DT1\r
+   \   0000005A                      REQUIRE _A_DDRB\r
+   \   0000005A                      REQUIRE _A_TCCR1E\r
+    119          \r
+    120          \r
+    121          /*! \brief Increments the PWM duty cycle, if not already at max\r
+    122           *\r
+    123           * \retval TRUE Success, duty cycle could be incremented.\r
+    124           * \retval FALSE Failure, duty cycle already at maximum.\r
+    125           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    126          unsigned char PWM_IncrementDutyCycle(void){\r
+   \                     PWM_IncrementDutyCycle:\r
+    127          \r
+    128                if (OCR1B < PWM_MAX) {\r
+   \   00000000   B50C               IN      R16, 0x2C\r
+   \   00000002   3F0F               CPI     R16, 255\r
+   \   00000004   F428               BRCC    ??PWM_IncrementDutyCycle_0\r
+    129                        OCR1B += 1;\r
+   \   00000006   B50C               IN      R16, 0x2C\r
+   \   00000008   9503               INC     R16\r
+   \   0000000A   BD0C               OUT     0x2C, R16\r
+    130                        return(TRUE);\r
+   \   0000000C   E001               LDI     R16, 1\r
+   \   0000000E   9508               RET\r
+    131                } else {\r
+    132                        return(FALSE);\r
+   \                     ??PWM_IncrementDutyCycle_0:\r
+   \   00000010   E000               LDI     R16, 0\r
+   \   00000012   9508               RET\r
+   \   00000014                      REQUIRE _A_OCR1B\r
+    133                }\r
+    134          }\r
+    135          \r
+    136          \r
+    137          /*! \brief Decrements the PWM duty cycle, if not already at zero.\r
+    138           *\r
+    139           * \retval TRUE Success, duty cycle could be decremented.\r
+    140           * \retval FALSE Failure, duty cycle already at zero.\r
+    141           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    142          unsigned char PWM_DecrementDutyCycle(void){\r
+   \                     PWM_DecrementDutyCycle:\r
+    143                \r
+    144                if (OCR1B > 0)  {\r
+   \   00000000   B50C               IN      R16, 0x2C\r
+   \   00000002   3001               CPI     R16, 1\r
+   \   00000004   F028               BRCS    ??PWM_DecrementDutyCycle_0\r
+    145                        OCR1B -= 1;\r
+   \   00000006   B50C               IN      R16, 0x2C\r
+   \   00000008   950A               DEC     R16\r
+   \   0000000A   BD0C               OUT     0x2C, R16\r
+    146                        return(TRUE);\r
+   \   0000000C   E001               LDI     R16, 1\r
+   \   0000000E   9508               RET\r
+    147                } else {\r
+    148                        return(FALSE);\r
+   \                     ??PWM_DecrementDutyCycle_0:\r
+   \   00000010   E000               LDI     R16, 0\r
+   \   00000012   9508               RET\r
+   \   00000014                      REQUIRE _A_OCR1B\r
+    149                }\r
+    150          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function               CSTACK RSTACK\r
+     --------               ------ ------\r
+     PWM_DecrementDutyCycle     0      2\r
+     PWM_IncrementDutyCycle     0      2\r
+     PWM_Start                  0      2\r
+       -> Time_Set              0      2\r
+       -> Time_Left             0      2\r
+     PWM_Stop                   0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label         Bytes\r
+     --------------         -----\r
+     _A_TCCR1A                 1\r
+     _A_TCCR1B                 1\r
+     _A_OCR1A                  1\r
+     _A_OCR1B                  1\r
+     _A_OCR1C                  1\r
+     _A_OCR1D                  1\r
+     _A_PLLCSR                 1\r
+     _A_TCCR1C                 1\r
+     _A_TCCR1D                 1\r
+     _A_DT1                    1\r
+     _A_DDRB                   1\r
+     _A_TCCR1E                 1\r
+     PWM_Stop                 38\r
+     PWM_Start                90\r
+     PWM_IncrementDutyCycle   20\r
+     PWM_DecrementDutyCycle   20\r
+\r
\r
+  12 bytes in segment ABSOLUTE\r
+ 168 bytes in segment CODE\r
\r
+ 168 bytes of CODE memory\r
+   0 bytes of DATA memory (+ 12 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/PWM.s90 b/BaseTinyFirmware/IAR/Debug/List/PWM.s90
new file mode 100644 (file)
index 0000000..ce1e31a
--- /dev/null
@@ -0,0 +1,409 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:38 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c               /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c               /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\PWM.s90  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME PWM\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        PUBLIC PWM_DecrementDutyCycle\r
+        PUBLIC PWM_IncrementDutyCycle\r
+        PUBLIC PWM_Start\r
+        PUBLIC PWM_Stop\r
+        PUBWEAK _A_DDRB\r
+        PUBWEAK _A_DT1\r
+        PUBWEAK _A_OCR1A\r
+        PUBWEAK _A_OCR1B\r
+        PUBWEAK _A_OCR1C\r
+        PUBWEAK _A_OCR1D\r
+        PUBWEAK _A_PLLCSR\r
+        PUBWEAK _A_TCCR1A\r
+        PUBWEAK _A_TCCR1B\r
+        PUBWEAK _A_TCCR1C\r
+        PUBWEAK _A_TCCR1D\r
+        PUBWEAK _A_TCCR1E\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN Time_Set\r
+        EXTERN Time_Left\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for use of PWM\r
+//    6  *\r
+//    7  *      Contains functions for initializing and controlling PWM output.\r
+//    8  *\r
+//    9  * \par Application note:\r
+//   10  *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2299 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
+//   26  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,050H\r
+// <unnamed> volatile __io _A_TCCR1A\r
+_A_TCCR1A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04fH\r
+// <unnamed> volatile __io _A_TCCR1B\r
+_A_TCCR1B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04dH\r
+// <unnamed> volatile __io _A_OCR1A\r
+_A_OCR1A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
+// <unnamed> volatile __io _A_OCR1B\r
+_A_OCR1B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04bH\r
+// <unnamed> volatile __io _A_OCR1C\r
+_A_OCR1C:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04aH\r
+// <unnamed> volatile __io _A_OCR1D\r
+_A_OCR1D:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,049H\r
+// <unnamed> volatile __io _A_PLLCSR\r
+_A_PLLCSR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,047H\r
+// <unnamed> volatile __io _A_TCCR1C\r
+_A_TCCR1C:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,046H\r
+// <unnamed> volatile __io _A_TCCR1D\r
+_A_TCCR1D:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,044H\r
+// <unnamed> volatile __io _A_DT1\r
+_A_DT1:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,037H\r
+// <unnamed> volatile __io _A_DDRB\r
+_A_DDRB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,020H\r
+// <unnamed> volatile __io _A_TCCR1E\r
+_A_TCCR1E:\r
+        DS 1\r
+//   30 \r
+//   31 #include "enums.h"\r
+//   32 \r
+//   33 #include "main.h"\r
+//   34 #include "PWM.h"\r
+//   35 #include "time.h"\r
+//   36 \r
+//   37 \r
+//   38 //******************************************************************************\r
+//   39 // Functions\r
+//   40 //******************************************************************************\r
+//   41 /*! \brief Stops PWM output\r
+//   42  *\r
+//   43  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   44 void PWM_Stop(void)\r
+PWM_Stop:\r
+//   45 {\r
+//   46        OCR1B = 0;  // Reset compare level.\r
+        LDI     R16, 0\r
+        OUT     0x2C, R16\r
+//   47        PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
+        LDI     R16, 0\r
+        OUT     0x29, R16\r
+//   48        TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
+        LDI     R16, 0\r
+        OUT     0x30, R16\r
+//   49        TCCR1B = 0; // Stop timer/counter1.\r
+        LDI     R16, 0\r
+        OUT     0x2F, R16\r
+//   50        TCCR1C = 0; // Set normal port operation.\r
+        LDI     R16, 0\r
+        OUT     0x27, R16\r
+//   51        TCCR1D = 0; // No fault protection, normal waveform.\r
+        LDI     R16, 0\r
+        OUT     0x26, R16\r
+//   52        OCR1C = 0;  // Reset compare.\r
+        LDI     R16, 0\r
+        OUT     0x2B, R16\r
+//   53        OCR1D = 0;  // Reset compare.\r
+        LDI     R16, 0\r
+        OUT     0x2A, R16\r
+//   54        DT1 = 0;    // No dead time values.\r
+        LDI     R16, 0\r
+        OUT     0x24, R16\r
+//   55 }\r
+        RET\r
+        REQUIRE _A_TCCR1A\r
+        REQUIRE _A_TCCR1B\r
+        REQUIRE _A_OCR1B\r
+        REQUIRE _A_OCR1C\r
+        REQUIRE _A_OCR1D\r
+        REQUIRE _A_PLLCSR\r
+        REQUIRE _A_TCCR1C\r
+        REQUIRE _A_TCCR1D\r
+        REQUIRE _A_DT1\r
+//   56 \r
+//   57 \r
+//   58 /*! \brief Initializes and starts PWM output\r
+//   59  *\r
+//   60  * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
+//   61  * Its comparator is connected to PB3 and will output high until timer1 reaches\r
+//   62  * the value of OCR1B. It is then dropped to 0.\n\r
+//   63  * The comparator outputs high again when the counter overflows, which will\r
+//   64  * happen at a rate of 250 kHz.\r
+//   65  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   66 void PWM_Start(void)\r
+PWM_Start:\r
+//   67 {\r
+//   68        // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
+//   69        TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
+        LDI     R16, 33\r
+        OUT     0x30, R16\r
+//   70        \r
+//   71        // Non-inverted PWM, T/C stopped.\r
+//   72        TCCR1B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2F, R16\r
+//   73        \r
+//   74        // Copy shadow bits, disconnect OC1D.\r
+//   75        TCCR1C = (TCCR1A & 0xF0);\r
+        IN      R16, 0x30\r
+        ANDI    R16, 0xF0\r
+        OUT     0x27, R16\r
+//   76        \r
+//   77        // No fault protection, use phase & frequency correct PWM.\r
+//   78        TCCR1D = (0<<WGM11)|(1<WGM10);\r
+        LDI     R16, 0\r
+        OUT     0x26, R16\r
+//   79        \r
+//   80        // Does not matter -- PWM6 mode not used.\r
+//   81        TCCR1E = 0;\r
+        LDI     R16, 0\r
+        OUT     0x00, R16\r
+//   82        \r
+//   83        // Does not matter -- OC1A is disabled.\r
+//   84        OCR1A = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2D, R16\r
+//   85        \r
+//   86        // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
+//   87        OCR1B = PWM_OFFSET;\r
+        LDI     R16, 12\r
+        OUT     0x2C, R16\r
+//   88        \r
+//   89        // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
+//   90        OCR1C = 0xFF;\r
+        LDI     R16, 255\r
+        OUT     0x2B, R16\r
+//   91        \r
+//   92        // Does not matter -- OC1D is disabled.\r
+//   93        OCR1D = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2A, R16\r
+//   94        \r
+//   95        // No dead time values.\r
+//   96        DT1 = 0;\r
+        LDI     R16, 0\r
+        OUT     0x24, R16\r
+//   97        \r
+//   98        // Set PWM port pin to output.\r
+//   99        DDRB |= (1<<PB3);\r
+        SBI     0x17, 0x03\r
+//  100        \r
+//  101        // Enable PLL, use full speed mode.\r
+//  102        PLLCSR = (0<<LSM) | (1<<PLLE);\r
+        LDI     R16, 2\r
+        OUT     0x29, R16\r
+//  103        \r
+//  104        // Use general timer and wait 1 ms for PLL lock to settle.\r
+//  105        Time_Set(TIMER_GEN,0,0,1);\r
+        LDI     R20, 1\r
+        LDI     R17, 0\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 2\r
+        RCALL   Time_Set\r
+//  106        do{ \r
+//  107        }while(Time_Left(TIMER_GEN));\r
+??PWM_Start_0:\r
+        LDI     R16, 2\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??PWM_Start_0\r
+//  108        \r
+//  109        // Now wait for PLL to lock.\r
+//  110        do{ \r
+//  111        }while((PLLCSR & (1<<PLOCK)) == 0);\r
+??PWM_Start_1:\r
+        IN      R16, 0x29\r
+        MOV     R17, R16\r
+        SBRS    R17, 0\r
+        RJMP    ??PWM_Start_1\r
+//  112 \r
+//  113        // Use PLL as clock source.\r
+//  114        PLLCSR |= (1<<PCKE);\r
+        IN      R16, 0x29\r
+        ORI     R16, 0x04\r
+        OUT     0x29, R16\r
+//  115        \r
+//  116        // CLK PCK = 64MHz / 1 = 64MHz.\r
+//  117        TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
+        IN      R16, 0x2F\r
+        ORI     R16, 0x01\r
+        OUT     0x2F, R16\r
+//  118 }\r
+        RET\r
+        REQUIRE _A_TCCR1A\r
+        REQUIRE _A_TCCR1B\r
+        REQUIRE _A_OCR1A\r
+        REQUIRE _A_OCR1B\r
+        REQUIRE _A_OCR1C\r
+        REQUIRE _A_OCR1D\r
+        REQUIRE _A_PLLCSR\r
+        REQUIRE _A_TCCR1C\r
+        REQUIRE _A_TCCR1D\r
+        REQUIRE _A_DT1\r
+        REQUIRE _A_DDRB\r
+        REQUIRE _A_TCCR1E\r
+//  119 \r
+//  120 \r
+//  121 /*! \brief Increments the PWM duty cycle, if not already at max\r
+//  122  *\r
+//  123  * \retval TRUE Success, duty cycle could be incremented.\r
+//  124  * \retval FALSE Failure, duty cycle already at maximum.\r
+//  125  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  126 unsigned char PWM_IncrementDutyCycle(void){\r
+PWM_IncrementDutyCycle:\r
+//  127 \r
+//  128        if (OCR1B < PWM_MAX) {\r
+        IN      R16, 0x2C\r
+        CPI     R16, 255\r
+        BRCC    ??PWM_IncrementDutyCycle_0\r
+//  129                OCR1B += 1;\r
+        IN      R16, 0x2C\r
+        INC     R16\r
+        OUT     0x2C, R16\r
+//  130                return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//  131        } else {\r
+//  132                return(FALSE);\r
+??PWM_IncrementDutyCycle_0:\r
+        LDI     R16, 0\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  133        }\r
+//  134 }\r
+//  135 \r
+//  136 \r
+//  137 /*! \brief Decrements the PWM duty cycle, if not already at zero.\r
+//  138  *\r
+//  139  * \retval TRUE Success, duty cycle could be decremented.\r
+//  140  * \retval FALSE Failure, duty cycle already at zero.\r
+//  141  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  142 unsigned char PWM_DecrementDutyCycle(void){\r
+PWM_DecrementDutyCycle:\r
+//  143        \r
+//  144        if (OCR1B > 0)  {\r
+        IN      R16, 0x2C\r
+        CPI     R16, 1\r
+        BRCS    ??PWM_DecrementDutyCycle_0\r
+//  145                OCR1B -= 1;\r
+        IN      R16, 0x2C\r
+        DEC     R16\r
+        OUT     0x2C, R16\r
+//  146                return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//  147        } else {\r
+//  148                return(FALSE);\r
+??PWM_DecrementDutyCycle_0:\r
+        LDI     R16, 0\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  149        }\r
+//  150 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+// \r
+//  12 bytes in segment ABSOLUTE\r
+// 168 bytes in segment CODE\r
+// \r
+// 168 bytes of CODE memory\r
+//   0 bytes of DATA memory (+ 12 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/USI.lst b/BaseTinyFirmware/IAR/Debug/List/USI.lst
new file mode 100644 (file)
index 0000000..13a0e12
--- /dev/null
@@ -0,0 +1,779 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:39 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\USI.c                #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\USI.c --cpu=tiny861  #\r
+#                    -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\    #\r
+#                    -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB  #\r
+#                    C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\          #\r
+#                    --initializers_in_flash -z2 --no_cse --no_inline         #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\USI.lst   #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\USI.r90    #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\USI.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for use of the Universal Serial Interface\r
+      6           *\r
+      7           *      Contains high level functions for initializing the USI as an SPI slave,\r
+      8           *      interrupt handling, sending and receiving single bytes.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13           *\r
+     14           * \par Documentation:\r
+     15           *      For comprehensive code documentation, supported compilers, compiler\r
+     16           *      settings and supported devices see readme.html\r
+     17           *\r
+     18           * \author\r
+     19           *      Atmel Corporation: http://www.atmel.com \n\r
+     20           *      Support email: avr@atmel.com \n\r
+     21           *      Original author: \n\r
+     22           *\r
+     23           * $Name$\r
+     24           * $Revision: 2299 $\r
+     25           * $RCSfile$\r
+     26           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
+     27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     28           ******************************************************************************/\r
+     29          \r
+     30          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x38\r
+   \   <unnamed> volatile __io _A_PORTB\r
+   \                     _A_PORTB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x37\r
+   \   <unnamed> volatile __io _A_DDRB\r
+   \                     _A_DDRB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x2f\r
+   \   <unnamed> volatile __io _A_USIDR\r
+   \                     _A_USIDR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x2e\r
+   \   <unnamed> volatile __io _A_USISR\r
+   \                     _A_USISR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x2d\r
+   \   <unnamed> volatile __io _A_USICR\r
+   \                     _A_USICR:\r
+   \   00000000                      DS 1\r
+     31          #include <inavr.h>\r
+     32          \r
+     33          #include "enums.h"\r
+     34          #include "structs.h"\r
+     35          \r
+     36          #include "main.h"\r
+     37          #include "ADC.h"\r
+     38          #include "battery.h"\r
+     39          #include "time.h"\r
+     40          #include "USI.h"\r
+     41          \r
+     42          \r
+     43          //******************************************************************************\r
+     44          // Variables\r
+     45          //******************************************************************************\r
+     46          //! SPI status struct\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     47          SPI_Status_t SPI;\r
+   \                     SPI:\r
+   \   00000000                      DS 4\r
+     48          \r
+     49          \r
+     50          //******************************************************************************\r
+     51          //Functions\r
+     52          //*****************************************************************************\r
+     53          /*! \brief USI Counter Overflow Interrupt Service Routine\r
+     54           *\r
+     55           * When the USI counter overflows, a byte has been transferred.\n\r
+     56           * The USIDR contents are stored and flags are updated.\r
+     57           *\r
+     58           * The protocol is quite simple and has three sequential states: command,\r
+     59           * address and data.\r
+     60           * (Keep in mind that the Master is in charge of data clocking, which means\r
+     61           * there is a one byte "delay" from when the Slave puts something to SPI till\r
+     62           * the Master can read it.)\r
+     63           *\r
+     64           * 1. If a non-zero byte is received in the command state, the ISR will\r
+     65           * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
+     66           * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
+     67           * If a zero byte (0x00) is received in the command state, it is simply ignored\r
+     68           * because it is an invalid command.\r
+     69           *\r
+     70           * 2. When a byte is received in the address state, it is stored to the SPI\r
+     71           * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
+     72           * \r
+     73           * 3. In the data state, variables are read/written "from back to front" until\r
+     74           * the byte counter reaches zero. Since the Master is in charge of the data\r
+     75           * clocking, the Slave will go to command state before the last byte is\r
+     76           * transferred during reading. This means that the Master should send an \r
+     77           * invalid command when getting each byte, ie 0x00.\r
+     78           *\r
+     79           * If the time between two transfers is 1 second or more, the Slave\r
+     80           * automatically reverts to command state.\r
+     81           *\r
+     82           * \note Battery charging is not automatically halted during SPI communication.\r
+     83           * This means that the current charge state (current and voltage) will\r
+     84           * remain constant during heavy and prolonged serial traffic.\r
+     85           *\r
+     86           * \todo Variable writing not implemented yet.\r
+     87           * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
+     88           */\r
+     89          #pragma vector=USI_OVF_vect\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     90          __interrupt void USI_OVF_ISR(void)\r
+   \                     USI_OVF_ISR:\r
+     91          {\r
+   \   00000000   93AA               ST      -Y, R26\r
+   \   00000002   939A               ST      -Y, R25\r
+   \   00000004   938A               ST      -Y, R24\r
+   \   00000006   93FA               ST      -Y, R31\r
+   \   00000008   93EA               ST      -Y, R30\r
+   \   0000000A   923A               ST      -Y, R3\r
+   \   0000000C   922A               ST      -Y, R2\r
+   \   0000000E   921A               ST      -Y, R1\r
+   \   00000010   920A               ST      -Y, R0\r
+   \   00000012   937A               ST      -Y, R23\r
+   \   00000014   936A               ST      -Y, R22\r
+   \   00000016   935A               ST      -Y, R21\r
+   \   00000018   934A               ST      -Y, R20\r
+   \   0000001A   933A               ST      -Y, R19\r
+   \   0000001C   932A               ST      -Y, R18\r
+   \   0000001E   931A               ST      -Y, R17\r
+   \   00000020   930A               ST      -Y, R16\r
+   \   00000022   B7AF               IN      R26, 0x3F\r
+     92                // If the communication timed out, set ST_CMD as current state.\r
+     93                if (!Time_Left(TIMER_USI)) {\r
+   \   00000024   E000               LDI     R16, 0\r
+   \   00000026   ....               RCALL   Time_Left\r
+   \   00000028   2300               TST     R16\r
+   \   0000002A   F431               BRNE    ??USI_OVF_ISR_0\r
+     94                        SPI.State = ST_CMD;\r
+   \   0000002C   9100....           LDS     R16, (SPI + 2)\r
+   \   00000030   730F               ANDI    R16, 0x3F\r
+   \   00000032   6400               ORI     R16, 0x40\r
+   \   00000034   9300....           STS     (SPI + 2), R16\r
+     95                }\r
+     96          \r
+     97                // Start communication timer. If further communication doesn't happen\r
+     98                // within 1 second, the SPI communication state is reset to CMD.\r
+     99                Time_Set(TIMER_USI, 0, 1, 0);\r
+   \                     ??USI_OVF_ISR_0:\r
+   \   00000038   E040               LDI     R20, 0\r
+   \   0000003A   E011               LDI     R17, 1\r
+   \   0000003C   E020               LDI     R18, 0\r
+   \   0000003E   E030               LDI     R19, 0\r
+   \   00000040   E000               LDI     R16, 0\r
+   \   00000042   ....               RCALL   Time_Set\r
+    100                \r
+    101                // Clear USI counter and flag completed transfer.\r
+    102                USISR = (1<<USIOIF);\r
+   \   00000044   E400               LDI     R16, 64\r
+   \   00000046   B90E               OUT     0x0E, R16\r
+    103                SPI.XferComplete = TRUE;\r
+   \   00000048   ....               LDI     R30, LOW(SPI)\r
+   \   0000004A   ....               LDI     R31, (SPI) >> 8\r
+   \   0000004C   8103               LDD     R16, Z+3\r
+   \   0000004E   6004               ORI     R16, 0x04\r
+   \   00000050   8303               STD     Z+3, R16\r
+    104                \r
+    105                // Process incoming data.\r
+    106                switch(SPI.State)       {\r
+   \   00000052   9100....           LDS     R16, (SPI + 2)\r
+   \   00000056   0F00               LSL     R16\r
+   \   00000058   1F00               ROL     R16\r
+   \   0000005A   1F00               ROL     R16\r
+   \   0000005C   7003               ANDI    R16, 0x03\r
+   \   0000005E   5001               SUBI    R16, 1\r
+   \   00000060   F039               BREQ    ??USI_OVF_ISR_1\r
+   \   00000062   950A               DEC     R16\r
+   \   00000064   F409               BRNE    $+2+2\r
+   \   00000066   C040               RJMP    ??USI_OVF_ISR_2\r
+   \   00000068   950A               DEC     R16\r
+   \   0000006A   F409               BRNE    $+2+2\r
+   \   0000006C   C050               RJMP    ??USI_OVF_ISR_3\r
+   \   0000006E   C0C0               RJMP    ??USI_OVF_ISR_4\r
+    107                // A valid SPI transfer starts with a Command Byte sent by the Master.\r
+    108                case ST_CMD:   \r
+    109                        SPI.Data = USIDR;  // Store the transferred byte.\r
+   \                     ??USI_OVF_ISR_1:\r
+   \   00000070   B10F               IN      R16, 0x0F\r
+   \   00000072   9110....           LDS     R17, SPI\r
+   \   00000076   9300....           STS     SPI, R16\r
+    110                        \r
+    111                        // If the master sent 0, it is trying to get data. Ignore in this state.\r
+    112                        if (SPI.Data != 0) {\r
+   \   0000007A   9100....           LDS     R16, SPI\r
+   \   0000007E   2300               TST     R16\r
+   \   00000080   F409               BRNE    $+2+2\r
+   \   00000082   C0B6               RJMP    ??USI_OVF_ISR_4\r
+    113                                // Does the master want to read or write?\r
+    114                                if (SPI.Data & 0x40) {\r
+   \   00000084   ....               LDI     R30, LOW(SPI)\r
+   \   00000086   ....               LDI     R31, (SPI) >> 8\r
+   \   00000088   8100               LD      R16, Z\r
+   \   0000008A   FF06               SBRS    R16, 6\r
+   \   0000008C   C006               RJMP    ??USI_OVF_ISR_5\r
+    115                                        SPI.Read = FALSE;\r
+   \   0000008E   ....               LDI     R30, LOW(SPI)\r
+   \   00000090   ....               LDI     R31, (SPI) >> 8\r
+   \   00000092   8103               LDD     R16, Z+3\r
+   \   00000094   7F0E               ANDI    R16, 0xFE\r
+   \   00000096   8303               STD     Z+3, R16\r
+   \   00000098   C005               RJMP    ??USI_OVF_ISR_6\r
+    116                                } else {\r
+    117                                        SPI.Read = TRUE;\r
+   \                     ??USI_OVF_ISR_5:\r
+   \   0000009A   ....               LDI     R30, LOW(SPI)\r
+   \   0000009C   ....               LDI     R31, (SPI) >> 8\r
+   \   0000009E   8103               LDD     R16, Z+3\r
+   \   000000A0   6001               ORI     R16, 0x01\r
+   \   000000A2   8303               STD     Z+3, R16\r
+    118                                }\r
+    119          \r
+    120                                        // From/to EEPROM or SRAM?\r
+    121                                if (SPI.Data &0x80) {\r
+   \                     ??USI_OVF_ISR_6:\r
+   \   000000A4   ....               LDI     R30, LOW(SPI)\r
+   \   000000A6   ....               LDI     R31, (SPI) >> 8\r
+   \   000000A8   8100               LD      R16, Z\r
+   \   000000AA   FF07               SBRS    R16, 7\r
+   \   000000AC   C006               RJMP    ??USI_OVF_ISR_7\r
+    122                                        SPI.EEPROM = TRUE;\r
+   \   000000AE   ....               LDI     R30, LOW(SPI)\r
+   \   000000B0   ....               LDI     R31, (SPI) >> 8\r
+   \   000000B2   8103               LDD     R16, Z+3\r
+   \   000000B4   6002               ORI     R16, 0x02\r
+   \   000000B6   8303               STD     Z+3, R16\r
+   \   000000B8   C005               RJMP    ??USI_OVF_ISR_8\r
+    123                                } else {\r
+    124                                        SPI.EEPROM = FALSE;\r
+   \                     ??USI_OVF_ISR_7:\r
+   \   000000BA   ....               LDI     R30, LOW(SPI)\r
+   \   000000BC   ....               LDI     R31, (SPI) >> 8\r
+   \   000000BE   8103               LDD     R16, Z+3\r
+   \   000000C0   7F0D               ANDI    R16, 0xFD\r
+   \   000000C2   8303               STD     Z+3, R16\r
+    125                                }\r
+    126          \r
+    127                                SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
+   \                     ??USI_OVF_ISR_8:\r
+   \   000000C4   9110....           LDS     R17, (SPI + 2)\r
+   \   000000C8   7C10               ANDI    R17, 0xC0\r
+   \   000000CA   9100....           LDS     R16, SPI\r
+   \   000000CE   730F               ANDI    R16, 0x3F\r
+   \   000000D0   2B01               OR      R16, R17\r
+   \   000000D2   9300....           STS     (SPI + 2), R16\r
+    128                                SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
+   \   000000D6   9100....           LDS     R16, (SPI + 2)\r
+   \   000000DA   730F               ANDI    R16, 0x3F\r
+   \   000000DC   6800               ORI     R16, 0x80\r
+   \   000000DE   9300....           STS     (SPI + 2), R16\r
+    129          \r
+    130                                SPI_Put(0xCC);  // Signal that command was received.\r
+   \   000000E2   EC0C               LDI     R16, 204\r
+   \   000000E4   ....               RCALL   SPI_Put\r
+   \   000000E6   C084               RJMP    ??USI_OVF_ISR_4\r
+    131                        }\r
+    132                break;\r
+    133          \r
+    134                                \r
+    135                case ST_ADDR:  \r
+    136                        SPI.Data = USIDR;  // Store the address.\r
+   \                     ??USI_OVF_ISR_2:\r
+   \   000000E8   B10F               IN      R16, 0x0F\r
+   \   000000EA   9180....           LDS     R24, SPI\r
+   \   000000EE   9300....           STS     SPI, R16\r
+    137                        SPI.Address = SPI.Data;\r
+   \   000000F2   9190....           LDS     R25, (SPI + 1)\r
+   \   000000F6   9100....           LDS     R16, SPI\r
+   \   000000FA   9300....           STS     (SPI + 1), R16\r
+    138                        SPI.State = ST_DATA;  // The master will send/wait for data next.\r
+   \   000000FE   ....               LDI     R30, LOW(SPI)\r
+   \   00000100   ....               LDI     R31, (SPI) >> 8\r
+   \   00000102   8102               LDD     R16, Z+2\r
+   \   00000104   6C00               ORI     R16, 0xC0\r
+   \   00000106   8302               STD     Z+2, R16\r
+    139          \r
+    140                        SPI_Put(0xBB);  // Signal that address was received.\r
+   \   00000108   EB0B               LDI     R16, 187\r
+   \   0000010A   ....               RCALL   SPI_Put\r
+   \   0000010C   C071               RJMP    ??USI_OVF_ISR_4\r
+    141                break;\r
+    142          \r
+    143          \r
+    144                // Note well: this will process at least one byte, regardless of Count.\r
+    145                case ST_DATA:\r
+    146                        if (SPI.Count-- > 0) {\r
+   \                     ??USI_OVF_ISR_3:\r
+   \   0000010E   9100....           LDS     R16, (SPI + 2)\r
+   \   00000112   2F20               MOV     R18, R16\r
+   \   00000114   7C20               ANDI    R18, 0xC0\r
+   \   00000116   2F10               MOV     R17, R16\r
+   \   00000118   951A               DEC     R17\r
+   \   0000011A   731F               ANDI    R17, 0x3F\r
+   \   0000011C   2B12               OR      R17, R18\r
+   \   0000011E   9310....           STS     (SPI + 2), R17\r
+   \   00000122   730F               ANDI    R16, 0x3F\r
+   \   00000124   3001               CPI     R16, 1\r
+   \   00000126   F408               BRCC    $+2+2\r
+   \   00000128   C05D               RJMP    ??USI_OVF_ISR_9\r
+    147                                // Write specified variable to SPI, "back to front".\r
+    148                                if (SPI.Read) {\r
+   \   0000012A   ....               LDI     R30, LOW(SPI)\r
+   \   0000012C   ....               LDI     R31, (SPI) >> 8\r
+   \   0000012E   8103               LDD     R16, Z+3\r
+   \   00000130   FF00               SBRS    R16, 0\r
+   \   00000132   C043               RJMP    ??USI_OVF_ISR_10\r
+    149                                        switch (SPI.Address) {\r
+   \   00000134   9100....           LDS     R16, (SPI + 1)\r
+   \   00000138   5001               SUBI    R16, 1\r
+   \   0000013A   F049               BREQ    ??USI_OVF_ISR_11\r
+   \   0000013C   950A               DEC     R16\r
+   \   0000013E   F089               BREQ    ??USI_OVF_ISR_12\r
+   \   00000140   950A               DEC     R16\r
+   \   00000142   F0C9               BREQ    ??USI_OVF_ISR_13\r
+   \   00000144   950A               DEC     R16\r
+   \   00000146   F109               BREQ    ??USI_OVF_ISR_14\r
+   \   00000148   950A               DEC     R16\r
+   \   0000014A   F151               BREQ    ??USI_OVF_ISR_15\r
+   \   0000014C   C033               RJMP    ??USI_OVF_ISR_16\r
+    150                                        case ADR_ADCS:\r
+    151                                                SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_11:\r
+   \   0000014E   9100....           LDS     R16, (SPI + 2)\r
+   \   00000152   730F               ANDI    R16, 0x3F\r
+   \   00000154   E010               LDI     R17, 0\r
+   \   00000156   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000158   ....               SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+   \   0000015A   ....               SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+   \   0000015C   8100               LD      R16, Z\r
+   \   0000015E   ....               RCALL   SPI_Put\r
+   \   00000160   C047               RJMP    ??USI_OVF_ISR_4\r
+    152                                        break;\r
+    153                                        \r
+    154                                        \r
+    155                                        case ADR_BATTACTIVE:\r
+    156                                                SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_12:\r
+   \   00000162   9100....           LDS     R16, (SPI + 2)\r
+   \   00000166   730F               ANDI    R16, 0x3F\r
+   \   00000168   E010               LDI     R17, 0\r
+   \   0000016A   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000016C   ....               SUBI    R30, LOW((-(BattActive) & 0xFFFF))\r
+   \   0000016E   ....               SBCI    R31, (-(BattActive) & 0xFFFF) >> 8\r
+   \   00000170   8100               LD      R16, Z\r
+   \   00000172   ....               RCALL   SPI_Put\r
+   \   00000174   C03D               RJMP    ??USI_OVF_ISR_4\r
+    157                                        break;\r
+    158                                        \r
+    159                                        \r
+    160                                        case ADR_BATTDATA:\r
+    161                                                SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_13:\r
+   \   00000176   9100....           LDS     R16, (SPI + 2)\r
+   \   0000017A   730F               ANDI    R16, 0x3F\r
+   \   0000017C   E010               LDI     R17, 0\r
+   \   0000017E   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000180   ....               SUBI    R30, LOW((-(BattData) & 0xFFFF))\r
+   \   00000182   ....               SBCI    R31, (-(BattData) & 0xFFFF) >> 8\r
+   \   00000184   8100               LD      R16, Z\r
+   \   00000186   ....               RCALL   SPI_Put\r
+   \   00000188   C033               RJMP    ??USI_OVF_ISR_4\r
+    162                                        break;\r
+    163                                        \r
+    164                                        \r
+    165                                        case ADR_BATTCTRL:\r
+    166                                                SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_14:\r
+   \   0000018A   9100....           LDS     R16, (SPI + 2)\r
+   \   0000018E   730F               ANDI    R16, 0x3F\r
+   \   00000190   E010               LDI     R17, 0\r
+   \   00000192   ....               LDI     R20, LOW(BattControl)\r
+   \   00000194   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000196   0F40               ADD     R20, R16\r
+   \   00000198   1F51               ADC     R21, R17\r
+   \   0000019A   ....               RCALL   __eeget8_16\r
+   \   0000019C   ....               RCALL   SPI_Put\r
+   \   0000019E   C028               RJMP    ??USI_OVF_ISR_4\r
+    167                                        break;\r
+    168                                        \r
+    169                                        case ADR_TIMERS:\r
+    170                                                SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_15:\r
+   \   000001A0   9100....           LDS     R16, (SPI + 2)\r
+   \   000001A4   730F               ANDI    R16, 0x3F\r
+   \   000001A6   E010               LDI     R17, 0\r
+   \   000001A8   01F8               MOVW    R31:R30, R17:R16\r
+   \   000001AA   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   000001AC   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   000001AE   8100               LD      R16, Z\r
+   \   000001B0   ....               RCALL   SPI_Put\r
+   \   000001B2   C01E               RJMP    ??USI_OVF_ISR_4\r
+    171                                        break;\r
+    172          \r
+    173                                        \r
+    174                                        default:\r
+    175                                                SPI_Put(0);\r
+   \                     ??USI_OVF_ISR_16:\r
+   \   000001B4   E000               LDI     R16, 0\r
+   \   000001B6   ....               RCALL   SPI_Put\r
+   \   000001B8   C01B               RJMP    ??USI_OVF_ISR_4\r
+    176                                        break;\r
+    177                                        }\r
+    178                                } else {\r
+    179                                        // Read byte from SPI\r
+    180                                        SPI.Data = USIDR;\r
+   \                     ??USI_OVF_ISR_10:\r
+   \   000001BA   B10F               IN      R16, 0x0F\r
+   \   000001BC   9110....           LDS     R17, SPI\r
+   \   000001C0   9300....           STS     SPI, R16\r
+    181          \r
+    182                                        // ********************************************\r
+    183                                        // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
+    184                                        // ********************************************\r
+    185                                                                        \r
+    186                                        // Save byte to specified variable.\r
+    187                                        switch (SPI.Address) {\r
+   \   000001C4   9100....           LDS     R16, (SPI + 1)\r
+   \   000001C8   5004               SUBI    R16, 4\r
+   \   000001CA   F491               BRNE    ??USI_OVF_ISR_4\r
+    188                                        case ADR_BATTCTRL:\r
+    189                                                *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
+   \   000001CC   9100....           LDS     R16, SPI\r
+   \   000001D0   9120....           LDS     R18, (SPI + 2)\r
+   \   000001D4   732F               ANDI    R18, 0x3F\r
+   \   000001D6   E030               LDI     R19, 0\r
+   \   000001D8   ....               LDI     R20, LOW(BattControl)\r
+   \   000001DA   ....               LDI     R21, (BattControl) >> 8\r
+   \   000001DC   0F42               ADD     R20, R18\r
+   \   000001DE   1F53               ADC     R21, R19\r
+   \   000001E0   ....               RCALL   __eeput8_16\r
+   \   000001E2   C006               RJMP    ??USI_OVF_ISR_4\r
+    190                                        break;\r
+    191          \r
+    192                                        \r
+    193                                        default:\r
+    194                                        break;\r
+    195                                        }\r
+    196                                }\r
+    197                                \r
+    198          \r
+    199                        } else {\r
+    200                                SPI.State = ST_CMD;\r
+   \                     ??USI_OVF_ISR_9:\r
+   \   000001E4   9100....           LDS     R16, (SPI + 2)\r
+   \   000001E8   730F               ANDI    R16, 0x3F\r
+   \   000001EA   6400               ORI     R16, 0x40\r
+   \   000001EC   9300....           STS     (SPI + 2), R16\r
+    201                        }\r
+    202                break;\r
+    203          \r
+    204                default:  // Shouldn't end up here. (Unknown SPI-state)\r
+    205                break;\r
+    206                }\r
+    207          }\r
+   \                     ??USI_OVF_ISR_4:\r
+   \   000001F0   BFAF               OUT     0x3F, R26\r
+   \   000001F2   9109               LD      R16, Y+\r
+   \   000001F4   9119               LD      R17, Y+\r
+   \   000001F6   9129               LD      R18, Y+\r
+   \   000001F8   9139               LD      R19, Y+\r
+   \   000001FA   9149               LD      R20, Y+\r
+   \   000001FC   9159               LD      R21, Y+\r
+   \   000001FE   9169               LD      R22, Y+\r
+   \   00000200   9179               LD      R23, Y+\r
+   \   00000202   9009               LD      R0, Y+\r
+   \   00000204   9019               LD      R1, Y+\r
+   \   00000206   9029               LD      R2, Y+\r
+   \   00000208   9039               LD      R3, Y+\r
+   \   0000020A   91E9               LD      R30, Y+\r
+   \   0000020C   91F9               LD      R31, Y+\r
+   \   0000020E   9189               LD      R24, Y+\r
+   \   00000210   9199               LD      R25, Y+\r
+   \   00000212   91A9               LD      R26, Y+\r
+   \   00000214   9518               RETI\r
+   \   00000216                      REQUIRE _A_USIDR\r
+   \   00000216                      REQUIRE _A_USISR\r
+    208          \r
+    209          \r
+    210          /*! \brief Initializes USI as an SPI slave\r
+    211           *\r
+    212           * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
+    213           * I/O and clock, and USI counter overflow interrupts enabled.\n\r
+    214           * Also initializes the SPI status struct.\r
+    215           * \r
+    216           * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
+    217           * (1) edge of clock signal\r
+    218           *\r
+    219           * \note Clears the stored data\r
+    220           *\r
+    221           * \todo Timer should reset SPI protocol on timeout\r
+    222           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    223          void SPI_Init(unsigned char spi_mode)\r
+   \                     SPI_Init:\r
+    224          {\r
+    225                __disable_interrupt();\r
+   \   00000000   94F8               CLI\r
+    226                \r
+    227                // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
+    228                USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
+   \   00000002   9AB9               SBI     0x17, 0x01\r
+    229                USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
+   \   00000004   B317               IN      R17, 0x17\r
+   \   00000006   7F1A               ANDI    R17, 0xFA\r
+   \   00000008   BB17               OUT     0x17, R17\r
+    230                USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
+   \   0000000A   B318               IN      R17, 0x18\r
+   \   0000000C   6015               ORI     R17, 0x05\r
+   \   0000000E   BB18               OUT     0x18, R17\r
+    231                \r
+    232                // Configure USI to 3-wire slave mode with overflow interrupt\r
+    233                USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
+   \   00000010   2F10               MOV     R17, R16\r
+   \   00000012   0F11               LSL     R17\r
+   \   00000014   0F11               LSL     R17\r
+   \   00000016   6518               ORI     R17, 0x58\r
+   \   00000018   B91D               OUT     0x0D, R17\r
+    234          \r
+    235                // Initialize the SPI struct\r
+    236                SPI.Data = 0;                 // Clear data.\r
+   \   0000001A   E010               LDI     R17, 0\r
+   \   0000001C   9310....           STS     SPI, R17\r
+    237                SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
+   \   00000020   9110....           LDS     R17, (SPI + 2)\r
+   \   00000024   731F               ANDI    R17, 0x3F\r
+   \   00000026   6410               ORI     R17, 0x40\r
+   \   00000028   9310....           STS     (SPI + 2), R17\r
+    238                SPI.Read = FALSE;             // Doesn't matter right now.\r
+   \   0000002C   ....               LDI     R30, LOW(SPI)\r
+   \   0000002E   ....               LDI     R31, (SPI) >> 8\r
+   \   00000030   8113               LDD     R17, Z+3\r
+   \   00000032   7F1E               ANDI    R17, 0xFE\r
+   \   00000034   8313               STD     Z+3, R17\r
+    239                SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
+   \   00000036   ....               LDI     R30, LOW(SPI)\r
+   \   00000038   ....               LDI     R31, (SPI) >> 8\r
+   \   0000003A   8113               LDD     R17, Z+3\r
+   \   0000003C   7F1D               ANDI    R17, 0xFD\r
+   \   0000003E   8313               STD     Z+3, R17\r
+    240                SPI.Count = 0;                // Doesn't matter right now.\r
+   \   00000040   ....               LDI     R30, LOW(SPI)\r
+   \   00000042   ....               LDI     R31, (SPI) >> 8\r
+   \   00000044   8112               LDD     R17, Z+2\r
+   \   00000046   7C10               ANDI    R17, 0xC0\r
+   \   00000048   8312               STD     Z+2, R17\r
+    241                SPI.Address = 0;              // Doesn't matter right now.\r
+   \   0000004A   E010               LDI     R17, 0\r
+   \   0000004C   9310....           STS     (SPI + 1), R17\r
+    242                SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
+   \   00000050   ....               LDI     R30, LOW(SPI)\r
+   \   00000052   ....               LDI     R31, (SPI) >> 8\r
+   \   00000054   8113               LDD     R17, Z+3\r
+   \   00000056   7F1B               ANDI    R17, 0xFB\r
+   \   00000058   8313               STD     Z+3, R17\r
+    243                SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
+   \   0000005A   ....               LDI     R30, LOW(SPI)\r
+   \   0000005C   ....               LDI     R31, (SPI) >> 8\r
+   \   0000005E   8113               LDD     R17, Z+3\r
+   \   00000060   7F17               ANDI    R17, 0xF7\r
+   \   00000062   8313               STD     Z+3, R17\r
+    244          \r
+    245                __enable_interrupt();\r
+   \   00000064   9478               SEI\r
+    246          }\r
+   \   00000066   9508               RET\r
+   \   00000068                      REQUIRE _A_PORTB\r
+   \   00000068                      REQUIRE _A_DDRB\r
+   \   00000068                      REQUIRE _A_USICR\r
+    247          \r
+    248          \r
+    249          // Put one byte on bus. Use this function like you would write to the SPDR\r
+    250          // register in the native SPI module. Calling this function will prepare a\r
+    251          // byte for the next transfer initiated by the master device. If a transfer\r
+    252          // is in progress, this function will set the write collision flag and return\r
+    253          // without altering the data registers.\r
+    254          //\r
+    255          // Returns 0 if a write collision occurred, 1 otherwise.\r
+    256          /*! \brief Write a byte to SPI bus\r
+    257           *\r
+    258           * This function first checks if a transmission is in progress, and if so, flags\r
+    259           * a write collision, and returns FALSE.\n\r
+    260           * If a transmission is not in progress, the flags for write collision and\r
+    261           * transfer complete are cleared, and the input byte is written to SPDR.\n\r
+    262           *\r
+    263           * \param val The byte to send.\r
+    264           *\r
+    265           * \retval FALSE A write collision happened.\r
+    266           * \retval TRUE Byte written to SPDR.\r
+    267           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    268          unsigned char SPI_Put(unsigned char val)\r
+   \                     SPI_Put:\r
+    269          {\r
+   \   00000000   2F10               MOV     R17, R16\r
+    270                // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
+    271                // If this fails, flag a write collision and return.\r
+    272                if((USISR & 0x0F) != 0) {\r
+   \   00000002   B10E               IN      R16, 0x0E\r
+   \   00000004   700F               ANDI    R16, 0x0F\r
+   \   00000006   2300               TST     R16\r
+   \   00000008   F039               BREQ    ??SPI_Put_0\r
+    273                        SPI.WriteCollision = TRUE;\r
+   \   0000000A   ....               LDI     R30, LOW(SPI)\r
+   \   0000000C   ....               LDI     R31, (SPI) >> 8\r
+   \   0000000E   8103               LDD     R16, Z+3\r
+   \   00000010   6008               ORI     R16, 0x08\r
+   \   00000012   8303               STD     Z+3, R16\r
+    274                        return(FALSE);\r
+   \   00000014   E000               LDI     R16, 0\r
+   \   00000016   9508               RET\r
+    275                }\r
+    276          \r
+    277                // Reinitialize flags.\r
+    278                SPI.XferComplete = FALSE;\r
+   \                     ??SPI_Put_0:\r
+   \   00000018   ....               LDI     R30, LOW(SPI)\r
+   \   0000001A   ....               LDI     R31, (SPI) >> 8\r
+   \   0000001C   8103               LDD     R16, Z+3\r
+   \   0000001E   7F0B               ANDI    R16, 0xFB\r
+   \   00000020   8303               STD     Z+3, R16\r
+    279                SPI.WriteCollision = FALSE;\r
+   \   00000022   ....               LDI     R30, LOW(SPI)\r
+   \   00000024   ....               LDI     R31, (SPI) >> 8\r
+   \   00000026   8103               LDD     R16, Z+3\r
+   \   00000028   7F07               ANDI    R16, 0xF7\r
+   \   0000002A   8303               STD     Z+3, R16\r
+    280          \r
+    281                USIDR = val;  // Put data in USI data register.\r
+   \   0000002C   B91F               OUT     0x0F, R17\r
+    282          \r
+    283                return (TRUE);\r
+   \   0000002E   E001               LDI     R16, 1\r
+   \   00000030   9508               RET\r
+   \   00000032                      REQUIRE _A_USIDR\r
+   \   00000032                      REQUIRE _A_USISR\r
+    284          }\r
+    285          \r
+    286          \r
+    287          // Get one byte from bus. This function only returns the previous stored\r
+    288          // USIDR value. The transfer complete flag is not checked. Use this function\r
+    289          // like you would read from the SPDR register in the native SPI module.\r
+    290          /*! \brief Get the last byte received from SPI bus\r
+    291           *\r
+    292           * This function simply returns the last byte stored to the SPI status struct,\r
+    293           * without checking if a completed transfer is flagged.\r
+    294           *\r
+    295           * \retval SPI.Data The last byte read from SPI.\r
+    296           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    297          unsigned char SPI_Get(void)\r
+   \                     SPI_Get:\r
+    298          {\r
+    299                return SPI.Data;\r
+   \   00000000   9100....           LDS     R16, SPI\r
+   \   00000004   9508               RET\r
+    300          }\r
+    301          \r
+    302          \r
+    303          /*! \brief Wait for SPI transfer to complete\r
+    304           *\r
+    305           * This function waits for a transfer complete to be flagged.\r
+    306           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    307          void SPI_Wait(void)\r
+   \                     SPI_Wait:\r
+   \                     ??SPI_Wait_0:\r
+    308          {\r
+    309                do {  // Wait for transfer complete.\r
+    310                } while (SPI.XferComplete == FALSE);\r
+   \   00000000   ....               LDI     R30, LOW(SPI)\r
+   \   00000002   ....               LDI     R31, (SPI) >> 8\r
+   \   00000004   8103               LDD     R16, Z+3\r
+   \   00000006   FF02               SBRS    R16, 2\r
+   \   00000008   CFFB               RJMP    ??SPI_Wait_0\r
+    311          }\r
+   \   0000000A   9508               RET\r
+\r
+   \                                 In  segment INTVEC, offset 0x10, root\r
+   \                     `??USI_OVF_ISR??INTVEC 16`:\r
+   \   00000010   ....               RJMP    USI_OVF_ISR\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function       CSTACK RSTACK\r
+     --------       ------ ------\r
+     SPI_Get            0      2\r
+     SPI_Init           0      2\r
+     SPI_Put            0      2\r
+     SPI_Wait           0      2\r
+     USI_OVF_ISR       17      4\r
+       -> Time_Left    17      2\r
+       -> Time_Set     17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+       -> SPI_Put      17      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label           Bytes\r
+     --------------           -----\r
+     _A_PORTB                    1\r
+     _A_DDRB                     1\r
+     _A_USIDR                    1\r
+     _A_USISR                    1\r
+     _A_USICR                    1\r
+     SPI                         4\r
+     USI_OVF_ISR               534\r
+     SPI_Init                  104\r
+     SPI_Put                    50\r
+     SPI_Get                     6\r
+     ??SPI_Wait_0               12\r
+     ??USI_OVF_ISR??INTVEC 16    2\r
+      Others                     6\r
+\r
\r
+   5 bytes in segment ABSOLUTE\r
+ 706 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment INTVEC\r
+   4 bytes in segment NEAR_Z\r
\r
+ 706 bytes of CODE memory (+ 8 bytes shared)\r
+   4 bytes of DATA memory (+ 5 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/USI.s90 b/BaseTinyFirmware/IAR/Debug/List/USI.s90
new file mode 100644 (file)
index 0000000..18cf029
--- /dev/null
@@ -0,0 +1,799 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\USI.c               /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\USI.c               /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\USI.s90  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME USI\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBWEAK `??USI_OVF_ISR??INTVEC 16`\r
+        PUBLIC SPI\r
+        PUBLIC SPI_Get\r
+        PUBLIC SPI_Init\r
+        PUBLIC SPI_Put\r
+        PUBLIC SPI_Wait\r
+        PUBLIC USI_OVF_ISR\r
+        PUBWEAK _A_DDRB\r
+        PUBWEAK _A_PORTB\r
+        PUBWEAK _A_USICR\r
+        PUBWEAK _A_USIDR\r
+        PUBWEAK _A_USISR\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+USI_OVF_ISR         SYMBOL "USI_OVF_ISR"\r
+`??USI_OVF_ISR??INTVEC 16` SYMBOL "??INTVEC 16", USI_OVF_ISR\r
+\r
+        EXTERN Time_Left\r
+        EXTERN Time_Set\r
+        EXTERN ADCS\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+        EXTERN timeval\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\USI.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for use of the Universal Serial Interface\r
+//    6  *\r
+//    7  *      Contains high level functions for initializing the USI as an SPI slave,\r
+//    8  *      interrupt handling, sending and receiving single bytes.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13  *\r
+//   14  * \par Documentation:\r
+//   15  *      For comprehensive code documentation, supported compilers, compiler\r
+//   16  *      settings and supported devices see readme.html\r
+//   17  *\r
+//   18  * \author\r
+//   19  *      Atmel Corporation: http://www.atmel.com \n\r
+//   20  *      Support email: avr@atmel.com \n\r
+//   21  *      Original author: \n\r
+//   22  *\r
+//   23  * $Name$\r
+//   24  * $Revision: 2299 $\r
+//   25  * $RCSfile$\r
+//   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
+//   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   28  ******************************************************************************/\r
+//   29 \r
+//   30 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,038H\r
+// <unnamed> volatile __io _A_PORTB\r
+_A_PORTB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,037H\r
+// <unnamed> volatile __io _A_DDRB\r
+_A_DDRB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,02fH\r
+// <unnamed> volatile __io _A_USIDR\r
+_A_USIDR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,02eH\r
+// <unnamed> volatile __io _A_USISR\r
+_A_USISR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,02dH\r
+// <unnamed> volatile __io _A_USICR\r
+_A_USICR:\r
+        DS 1\r
+//   31 #include <inavr.h>\r
+//   32 \r
+//   33 #include "enums.h"\r
+//   34 #include "structs.h"\r
+//   35 \r
+//   36 #include "main.h"\r
+//   37 #include "ADC.h"\r
+//   38 #include "battery.h"\r
+//   39 #include "time.h"\r
+//   40 #include "USI.h"\r
+//   41 \r
+//   42 \r
+//   43 //******************************************************************************\r
+//   44 // Variables\r
+//   45 //******************************************************************************\r
+//   46 //! SPI status struct\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   47 SPI_Status_t SPI;\r
+SPI:\r
+        DS 4\r
+//   48 \r
+//   49 \r
+//   50 //******************************************************************************\r
+//   51 //Functions\r
+//   52 //*****************************************************************************\r
+//   53 /*! \brief USI Counter Overflow Interrupt Service Routine\r
+//   54  *\r
+//   55  * When the USI counter overflows, a byte has been transferred.\n\r
+//   56  * The USIDR contents are stored and flags are updated.\r
+//   57  *\r
+//   58  * The protocol is quite simple and has three sequential states: command,\r
+//   59  * address and data.\r
+//   60  * (Keep in mind that the Master is in charge of data clocking, which means\r
+//   61  * there is a one byte "delay" from when the Slave puts something to SPI till\r
+//   62  * the Master can read it.)\r
+//   63  *\r
+//   64  * 1. If a non-zero byte is received in the command state, the ISR will\r
+//   65  * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
+//   66  * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
+//   67  * If a zero byte (0x00) is received in the command state, it is simply ignored\r
+//   68  * because it is an invalid command.\r
+//   69  *\r
+//   70  * 2. When a byte is received in the address state, it is stored to the SPI\r
+//   71  * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
+//   72  * \r
+//   73  * 3. In the data state, variables are read/written "from back to front" until\r
+//   74  * the byte counter reaches zero. Since the Master is in charge of the data\r
+//   75  * clocking, the Slave will go to command state before the last byte is\r
+//   76  * transferred during reading. This means that the Master should send an \r
+//   77  * invalid command when getting each byte, ie 0x00.\r
+//   78  *\r
+//   79  * If the time between two transfers is 1 second or more, the Slave\r
+//   80  * automatically reverts to command state.\r
+//   81  *\r
+//   82  * \note Battery charging is not automatically halted during SPI communication.\r
+//   83  * This means that the current charge state (current and voltage) will\r
+//   84  * remain constant during heavy and prolonged serial traffic.\r
+//   85  *\r
+//   86  * \todo Variable writing not implemented yet.\r
+//   87  * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
+//   88  */\r
+//   89 #pragma vector=USI_OVF_vect\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   90 __interrupt void USI_OVF_ISR(void)\r
+USI_OVF_ISR:\r
+//   91 {\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        ST      -Y, R31\r
+        ST      -Y, R30\r
+        ST      -Y, R3\r
+        ST      -Y, R2\r
+        ST      -Y, R1\r
+        ST      -Y, R0\r
+        ST      -Y, R23\r
+        ST      -Y, R22\r
+        ST      -Y, R21\r
+        ST      -Y, R20\r
+        ST      -Y, R19\r
+        ST      -Y, R18\r
+        ST      -Y, R17\r
+        ST      -Y, R16\r
+        IN      R26, 0x3F\r
+//   92        // If the communication timed out, set ST_CMD as current state.\r
+//   93        if (!Time_Left(TIMER_USI)) {\r
+        LDI     R16, 0\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??USI_OVF_ISR_0\r
+//   94                SPI.State = ST_CMD;\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        ORI     R16, 0x40\r
+        STS     (SPI + 2), R16\r
+//   95        }\r
+//   96 \r
+//   97        // Start communication timer. If further communication doesn't happen\r
+//   98        // within 1 second, the SPI communication state is reset to CMD.\r
+//   99        Time_Set(TIMER_USI, 0, 1, 0);\r
+??USI_OVF_ISR_0:\r
+        LDI     R20, 0\r
+        LDI     R17, 1\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 0\r
+        RCALL   Time_Set\r
+//  100        \r
+//  101        // Clear USI counter and flag completed transfer.\r
+//  102        USISR = (1<<USIOIF);\r
+        LDI     R16, 64\r
+        OUT     0x0E, R16\r
+//  103        SPI.XferComplete = TRUE;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x04\r
+        STD     Z+3, R16\r
+//  104        \r
+//  105        // Process incoming data.\r
+//  106        switch(SPI.State)       {\r
+        LDS     R16, (SPI + 2)\r
+        LSL     R16\r
+        ROL     R16\r
+        ROL     R16\r
+        ANDI    R16, 0x03\r
+        SUBI    R16, 1\r
+        BREQ    ??USI_OVF_ISR_1\r
+        DEC     R16\r
+        BRNE    $+2+2\r
+        RJMP    ??USI_OVF_ISR_2\r
+        DEC     R16\r
+        BRNE    $+2+2\r
+        RJMP    ??USI_OVF_ISR_3\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  107        // A valid SPI transfer starts with a Command Byte sent by the Master.\r
+//  108        case ST_CMD:   \r
+//  109                SPI.Data = USIDR;  // Store the transferred byte.\r
+??USI_OVF_ISR_1:\r
+        IN      R16, 0x0F\r
+        LDS     R17, SPI\r
+        STS     SPI, R16\r
+//  110                \r
+//  111                // If the master sent 0, it is trying to get data. Ignore in this state.\r
+//  112                if (SPI.Data != 0) {\r
+        LDS     R16, SPI\r
+        TST     R16\r
+        BRNE    $+2+2\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  113                        // Does the master want to read or write?\r
+//  114                        if (SPI.Data & 0x40) {\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 6\r
+        RJMP    ??USI_OVF_ISR_5\r
+//  115                                SPI.Read = FALSE;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xFE\r
+        STD     Z+3, R16\r
+        RJMP    ??USI_OVF_ISR_6\r
+//  116                        } else {\r
+//  117                                SPI.Read = TRUE;\r
+??USI_OVF_ISR_5:\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x01\r
+        STD     Z+3, R16\r
+//  118                        }\r
+//  119 \r
+//  120                                // From/to EEPROM or SRAM?\r
+//  121                        if (SPI.Data &0x80) {\r
+??USI_OVF_ISR_6:\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 7\r
+        RJMP    ??USI_OVF_ISR_7\r
+//  122                                SPI.EEPROM = TRUE;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x02\r
+        STD     Z+3, R16\r
+        RJMP    ??USI_OVF_ISR_8\r
+//  123                        } else {\r
+//  124                                SPI.EEPROM = FALSE;\r
+??USI_OVF_ISR_7:\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xFD\r
+        STD     Z+3, R16\r
+//  125                        }\r
+//  126 \r
+//  127                        SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
+??USI_OVF_ISR_8:\r
+        LDS     R17, (SPI + 2)\r
+        ANDI    R17, 0xC0\r
+        LDS     R16, SPI\r
+        ANDI    R16, 0x3F\r
+        OR      R16, R17\r
+        STS     (SPI + 2), R16\r
+//  128                        SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        ORI     R16, 0x80\r
+        STS     (SPI + 2), R16\r
+//  129 \r
+//  130                        SPI_Put(0xCC);  // Signal that command was received.\r
+        LDI     R16, 204\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  131                }\r
+//  132        break;\r
+//  133 \r
+//  134                        \r
+//  135        case ST_ADDR:  \r
+//  136                SPI.Data = USIDR;  // Store the address.\r
+??USI_OVF_ISR_2:\r
+        IN      R16, 0x0F\r
+        LDS     R24, SPI\r
+        STS     SPI, R16\r
+//  137                SPI.Address = SPI.Data;\r
+        LDS     R25, (SPI + 1)\r
+        LDS     R16, SPI\r
+        STS     (SPI + 1), R16\r
+//  138                SPI.State = ST_DATA;  // The master will send/wait for data next.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+2\r
+        ORI     R16, 0xC0\r
+        STD     Z+2, R16\r
+//  139 \r
+//  140                SPI_Put(0xBB);  // Signal that address was received.\r
+        LDI     R16, 187\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  141        break;\r
+//  142 \r
+//  143 \r
+//  144        // Note well: this will process at least one byte, regardless of Count.\r
+//  145        case ST_DATA:\r
+//  146                if (SPI.Count-- > 0) {\r
+??USI_OVF_ISR_3:\r
+        LDS     R16, (SPI + 2)\r
+        MOV     R18, R16\r
+        ANDI    R18, 0xC0\r
+        MOV     R17, R16\r
+        DEC     R17\r
+        ANDI    R17, 0x3F\r
+        OR      R17, R18\r
+        STS     (SPI + 2), R17\r
+        ANDI    R16, 0x3F\r
+        CPI     R16, 1\r
+        BRCC    $+2+2\r
+        RJMP    ??USI_OVF_ISR_9\r
+//  147                        // Write specified variable to SPI, "back to front".\r
+//  148                        if (SPI.Read) {\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        SBRS    R16, 0\r
+        RJMP    ??USI_OVF_ISR_10\r
+//  149                                switch (SPI.Address) {\r
+        LDS     R16, (SPI + 1)\r
+        SUBI    R16, 1\r
+        BREQ    ??USI_OVF_ISR_11\r
+        DEC     R16\r
+        BREQ    ??USI_OVF_ISR_12\r
+        DEC     R16\r
+        BREQ    ??USI_OVF_ISR_13\r
+        DEC     R16\r
+        BREQ    ??USI_OVF_ISR_14\r
+        DEC     R16\r
+        BREQ    ??USI_OVF_ISR_15\r
+        RJMP    ??USI_OVF_ISR_16\r
+//  150                                case ADR_ADCS:\r
+//  151                                        SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
+??USI_OVF_ISR_11:\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+        SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  152                                break;\r
+//  153                                \r
+//  154                                \r
+//  155                                case ADR_BATTACTIVE:\r
+//  156                                        SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
+??USI_OVF_ISR_12:\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(BattActive) & 0xFFFF))\r
+        SBCI    R31, (-(BattActive) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  157                                break;\r
+//  158                                \r
+//  159                                \r
+//  160                                case ADR_BATTDATA:\r
+//  161                                        SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
+??USI_OVF_ISR_13:\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(BattData) & 0xFFFF))\r
+        SBCI    R31, (-(BattData) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  162                                break;\r
+//  163                                \r
+//  164                                \r
+//  165                                case ADR_BATTCTRL:\r
+//  166                                        SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
+??USI_OVF_ISR_14:\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  167                                break;\r
+//  168                                \r
+//  169                                case ADR_TIMERS:\r
+//  170                                        SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
+??USI_OVF_ISR_15:\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  171                                break;\r
+//  172 \r
+//  173                                \r
+//  174                                default:\r
+//  175                                        SPI_Put(0);\r
+??USI_OVF_ISR_16:\r
+        LDI     R16, 0\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  176                                break;\r
+//  177                                }\r
+//  178                        } else {\r
+//  179                                // Read byte from SPI\r
+//  180                                SPI.Data = USIDR;\r
+??USI_OVF_ISR_10:\r
+        IN      R16, 0x0F\r
+        LDS     R17, SPI\r
+        STS     SPI, R16\r
+//  181 \r
+//  182                                // ********************************************\r
+//  183                                // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
+//  184                                // ********************************************\r
+//  185                                                                \r
+//  186                                // Save byte to specified variable.\r
+//  187                                switch (SPI.Address) {\r
+        LDS     R16, (SPI + 1)\r
+        SUBI    R16, 4\r
+        BRNE    ??USI_OVF_ISR_4\r
+//  188                                case ADR_BATTCTRL:\r
+//  189                                        *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
+        LDS     R16, SPI\r
+        LDS     R18, (SPI + 2)\r
+        ANDI    R18, 0x3F\r
+        LDI     R19, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R18\r
+        ADC     R21, R19\r
+        RCALL   __eeput8_16\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  190                                break;\r
+//  191 \r
+//  192                                \r
+//  193                                default:\r
+//  194                                break;\r
+//  195                                }\r
+//  196                        }\r
+//  197                        \r
+//  198 \r
+//  199                } else {\r
+//  200                        SPI.State = ST_CMD;\r
+??USI_OVF_ISR_9:\r
+        LDS     R16, (SPI + 2)\r
+        ANDI    R16, 0x3F\r
+        ORI     R16, 0x40\r
+        STS     (SPI + 2), R16\r
+//  201                }\r
+//  202        break;\r
+//  203 \r
+//  204        default:  // Shouldn't end up here. (Unknown SPI-state)\r
+//  205        break;\r
+//  206        }\r
+//  207 }\r
+??USI_OVF_ISR_4:\r
+        OUT     0x3F, R26\r
+        LD      R16, Y+\r
+        LD      R17, Y+\r
+        LD      R18, Y+\r
+        LD      R19, Y+\r
+        LD      R20, Y+\r
+        LD      R21, Y+\r
+        LD      R22, Y+\r
+        LD      R23, Y+\r
+        LD      R0, Y+\r
+        LD      R1, Y+\r
+        LD      R2, Y+\r
+        LD      R3, Y+\r
+        LD      R30, Y+\r
+        LD      R31, Y+\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        RETI\r
+        REQUIRE _A_USIDR\r
+        REQUIRE _A_USISR\r
+//  208 \r
+//  209 \r
+//  210 /*! \brief Initializes USI as an SPI slave\r
+//  211  *\r
+//  212  * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
+//  213  * I/O and clock, and USI counter overflow interrupts enabled.\n\r
+//  214  * Also initializes the SPI status struct.\r
+//  215  * \r
+//  216  * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
+//  217  * (1) edge of clock signal\r
+//  218  *\r
+//  219  * \note Clears the stored data\r
+//  220  *\r
+//  221  * \todo Timer should reset SPI protocol on timeout\r
+//  222  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  223 void SPI_Init(unsigned char spi_mode)\r
+SPI_Init:\r
+//  224 {\r
+//  225        __disable_interrupt();\r
+        CLI\r
+//  226        \r
+//  227        // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
+//  228        USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
+        SBI     0x17, 0x01\r
+//  229        USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
+        IN      R17, 0x17\r
+        ANDI    R17, 0xFA\r
+        OUT     0x17, R17\r
+//  230        USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
+        IN      R17, 0x18\r
+        ORI     R17, 0x05\r
+        OUT     0x18, R17\r
+//  231        \r
+//  232        // Configure USI to 3-wire slave mode with overflow interrupt\r
+//  233        USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
+        MOV     R17, R16\r
+        LSL     R17\r
+        LSL     R17\r
+        ORI     R17, 0x58\r
+        OUT     0x0D, R17\r
+//  234 \r
+//  235        // Initialize the SPI struct\r
+//  236        SPI.Data = 0;                 // Clear data.\r
+        LDI     R17, 0\r
+        STS     SPI, R17\r
+//  237        SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
+        LDS     R17, (SPI + 2)\r
+        ANDI    R17, 0x3F\r
+        ORI     R17, 0x40\r
+        STS     (SPI + 2), R17\r
+//  238        SPI.Read = FALSE;             // Doesn't matter right now.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R17, Z+3\r
+        ANDI    R17, 0xFE\r
+        STD     Z+3, R17\r
+//  239        SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R17, Z+3\r
+        ANDI    R17, 0xFD\r
+        STD     Z+3, R17\r
+//  240        SPI.Count = 0;                // Doesn't matter right now.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R17, Z+2\r
+        ANDI    R17, 0xC0\r
+        STD     Z+2, R17\r
+//  241        SPI.Address = 0;              // Doesn't matter right now.\r
+        LDI     R17, 0\r
+        STS     (SPI + 1), R17\r
+//  242        SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R17, Z+3\r
+        ANDI    R17, 0xFB\r
+        STD     Z+3, R17\r
+//  243        SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R17, Z+3\r
+        ANDI    R17, 0xF7\r
+        STD     Z+3, R17\r
+//  244 \r
+//  245        __enable_interrupt();\r
+        SEI\r
+//  246 }\r
+        RET\r
+        REQUIRE _A_PORTB\r
+        REQUIRE _A_DDRB\r
+        REQUIRE _A_USICR\r
+//  247 \r
+//  248 \r
+//  249 // Put one byte on bus. Use this function like you would write to the SPDR\r
+//  250 // register in the native SPI module. Calling this function will prepare a\r
+//  251 // byte for the next transfer initiated by the master device. If a transfer\r
+//  252 // is in progress, this function will set the write collision flag and return\r
+//  253 // without altering the data registers.\r
+//  254 //\r
+//  255 // Returns 0 if a write collision occurred, 1 otherwise.\r
+//  256 /*! \brief Write a byte to SPI bus\r
+//  257  *\r
+//  258  * This function first checks if a transmission is in progress, and if so, flags\r
+//  259  * a write collision, and returns FALSE.\n\r
+//  260  * If a transmission is not in progress, the flags for write collision and\r
+//  261  * transfer complete are cleared, and the input byte is written to SPDR.\n\r
+//  262  *\r
+//  263  * \param val The byte to send.\r
+//  264  *\r
+//  265  * \retval FALSE A write collision happened.\r
+//  266  * \retval TRUE Byte written to SPDR.\r
+//  267  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  268 unsigned char SPI_Put(unsigned char val)\r
+SPI_Put:\r
+//  269 {\r
+        MOV     R17, R16\r
+//  270        // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
+//  271        // If this fails, flag a write collision and return.\r
+//  272        if((USISR & 0x0F) != 0) {\r
+        IN      R16, 0x0E\r
+        ANDI    R16, 0x0F\r
+        TST     R16\r
+        BREQ    ??SPI_Put_0\r
+//  273                SPI.WriteCollision = TRUE;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x08\r
+        STD     Z+3, R16\r
+//  274                return(FALSE);\r
+        LDI     R16, 0\r
+        RET\r
+//  275        }\r
+//  276 \r
+//  277        // Reinitialize flags.\r
+//  278        SPI.XferComplete = FALSE;\r
+??SPI_Put_0:\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xFB\r
+        STD     Z+3, R16\r
+//  279        SPI.WriteCollision = FALSE;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xF7\r
+        STD     Z+3, R16\r
+//  280 \r
+//  281        USIDR = val;  // Put data in USI data register.\r
+        OUT     0x0F, R17\r
+//  282 \r
+//  283        return (TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+        REQUIRE _A_USIDR\r
+        REQUIRE _A_USISR\r
+//  284 }\r
+//  285 \r
+//  286 \r
+//  287 // Get one byte from bus. This function only returns the previous stored\r
+//  288 // USIDR value. The transfer complete flag is not checked. Use this function\r
+//  289 // like you would read from the SPDR register in the native SPI module.\r
+//  290 /*! \brief Get the last byte received from SPI bus\r
+//  291  *\r
+//  292  * This function simply returns the last byte stored to the SPI status struct,\r
+//  293  * without checking if a completed transfer is flagged.\r
+//  294  *\r
+//  295  * \retval SPI.Data The last byte read from SPI.\r
+//  296  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  297 unsigned char SPI_Get(void)\r
+SPI_Get:\r
+//  298 {\r
+//  299        return SPI.Data;\r
+        LDS     R16, SPI\r
+        RET\r
+//  300 }\r
+//  301 \r
+//  302 \r
+//  303 /*! \brief Wait for SPI transfer to complete\r
+//  304  *\r
+//  305  * This function waits for a transfer complete to be flagged.\r
+//  306  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  307 void SPI_Wait(void)\r
+SPI_Wait:\r
+??SPI_Wait_0:\r
+//  308 {\r
+//  309        do {  // Wait for transfer complete.\r
+//  310        } while (SPI.XferComplete == FALSE);\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        SBRS    R16, 2\r
+        RJMP    ??SPI_Wait_0\r
+//  311 }\r
+        RET\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        COMMON INTVEC:CODE:ROOT(1)\r
+        ORG 16\r
+`??USI_OVF_ISR??INTVEC 16`:\r
+        RJMP    USI_OVF_ISR\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   5 bytes in segment ABSOLUTE\r
+// 706 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment INTVEC\r
+//   4 bytes in segment NEAR_Z\r
+// \r
+// 706 bytes of CODE memory (+ 8 bytes shared)\r
+//   4 bytes of DATA memory (+ 5 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/battery.lst b/BaseTinyFirmware/IAR/Debug/List/battery.lst
new file mode 100644 (file)
index 0000000..7c7a96c
--- /dev/null
@@ -0,0 +1,1220 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:38 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\battery.c            #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\battery.c            #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\battery.l #\r
+#                    st                                                       #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\battery.r9 #\r
+#                    0                                                        #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\battery.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions related to battery control and data acquisition.\r
+      6           *\r
+      7           *      Contains functions for enabling/disabling batteries, and looking up\r
+      8           *      their status and specifications using the ADC.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13          \r
+     14           *\r
+     15           * \par Documentation\r
+     16           *      For comprehensive code documentation, supported compilers, compiler \r
+     17           *      settings and supported devices see readme.html\r
+     18           *\r
+     19           * \author\r
+     20           *      Atmel Corporation: http://www.atmel.com \n\r
+     21           *      Support email: avr@atmel.com\r
+     22           *\r
+     23           * \r
+     24           * $Name$\r
+     25           * $Revision: 2299 $\r
+     26           * $RCSfile$\r
+     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
+     28           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     29           ******************************************************************************/\r
+     30          \r
+     31          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4c\r
+   \   <unnamed> volatile __io _A_OCR1B\r
+   \                     _A_OCR1B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x38\r
+   \   <unnamed> volatile __io _A_PORTB\r
+   \                     _A_PORTB:\r
+   \   00000000                      DS 1\r
+     32          #include <inavr.h>\r
+     33          \r
+     34          #include "structs.h"\r
+     35          #include "enums.h"\r
+     36          \r
+     37          #include "ADC.h"\r
+     38          #include "battery.h"\r
+     39          #include "main.h"\r
+     40          #include "OWI.h"\r
+     41          #include "time.h"\r
+     42          \r
+     43          #ifdef NIMH\r
+     44          #include "NIMHspecs.h"\r
+     45          #endif // NIMH\r
+     46          \r
+     47          #ifdef LIION\r
+     48          #include "LIIONspecs.h"\r
+     49          #endif // LIION\r
+     50          \r
+     51          \r
+     52          \r
+     53          //******************************************************************************\r
+     54          // Variables\r
+     55          //******************************************************************************\r
+     56          /* Control-struct for batteries */\r
+     57          /*! \brief Holds control data for both batteries\r
+     58           * \note Stored in EEPROM.\r
+     59           */\r
+\r
+   \                                 In  segment EEPROM_I, align 1, keep-with-next\r
+     60          __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},\r
+   \                     BattControl:\r
+   \   00000000   0303               DB 3, 3\r
+     61                                               {TRUE, TRUE, FALSE}};\r
+     62          \r
+     63          /* Data-struct for battery */\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     64          Batteries_t BattData; //!< Holds data for the current battery\r
+   \                     BattData:\r
+   \   00000000                      DS 12\r
+     65          \r
+     66          \r
+     67          /* Storage for battery EPROM */\r
+     68          /*! \brief Storage space for data from the batteries' own EPROMs.\r
+     69           * \note Stored in EEPROM.\r
+     70           */\r
+\r
+   \                                 In  segment EEPROM_I, align 1, keep-with-next\r
+     71          __eeprom unsigned char BattEEPROM[4][32];\r
+   \                     BattEEPROM:\r
+   \   00000000   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000010   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000020   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000030   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000040   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000050   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000060   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000070   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+     72          \r
+     73          \r
+     74          //! Global that indicates current battery (0 = battery A, 1 = B)\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     75          unsigned char BattActive;\r
+   \                     BattActive:\r
+   \   00000000                      DS 1\r
+     76          \r
+     77          \r
+     78          /*! \brief RID lookup-table\r
+     79           *\r
+     80           * Contains Resistor ID data specified by manufacturer.\r
+     81           *\r
+     82           * \note Values have been calculated assuming a +/- 15% tolerance.\r
+     83           */\r
+\r
+   \                                 In  segment NEAR_I, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_I>`\r
+     84          const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
+   \                     RID:\r
+   \   00000000                      DS 56\r
+   \   00000038                      REQUIRE `?<Initializer for RID>`\r
+     85            {558, 659, 3900, 550, 260, 300, 10},\r
+     86            {744, 843, 6800, 750, 360, 300, 14},\r
+     87            {869, 958, 10000, 1000, 475, 300, 19},\r
+     88            {1097, 1153, 24000, 2000, 475, 420, 38}\r
+     89          };\r
+     90          \r
+     91          \r
+     92          /*! \brief NTC lookup-table\r
+     93           *\r
+     94           * The first entry is 0 degrees. For every entry after, temperature increases\r
+     95           * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
+     96           * It must be sorted in descending ADC order.\r
+     97           *\r
+     98           * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
+     99           *\r
+    100           * \note NTCLookUp() must be modified if this table is changed so that:\r
+    101           * - first entry is no longer 0 degrees.\r
+    102           * - temperature difference between entries is no longer 4 degrees.\r
+    103           * - ADCsteps no longer specifies ADC steps per half degree.\r
+    104           */\r
+    105          // FOR VARTA POLYFLEX NTC\r
+\r
+   \                                 In  segment NEAR_I, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_I>`\r
+    106          const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+   \                     NTC:\r
+   \   00000000                      DS 60\r
+   \   0000003C                      REQUIRE `?<Initializer for NTC>`\r
+    107                {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
+    108                {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
+    109                {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
+    110                {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
+    111          };\r
+    112          \r
+    113          \r
+    114          // FOR MITSUBISHI NTC\r
+    115          /*\r
+    116          const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+    117            {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
+    118            {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
+    119            {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
+    120            {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
+    121          };\r
+    122          */\r
+    123          \r
+    124          \r
+    125          //******************************************************************************\r
+    126          // Functions\r
+    127          //******************************************************************************\r
+    128          /*! \brief Checks if battery has changed\r
+    129           *\r
+    130           * Stores current capacity, then attempts to refresh battery status.\n\r
+    131           * If the refresh is successful, old capacity is compared with the new one.\r
+    132           * \r
+    133           * \retval FALSE Battery is disconnected, or capacity has changed.\r
+    134           * \retval TRUE All OK.\r
+    135           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    136          unsigned char BatteryCheck(void)\r
+   \                     BatteryCheck:\r
+    137          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+    138                unsigned char success = TRUE;\r
+   \   00000002   E081               LDI     R24, 1\r
+    139                unsigned int  oldCapacity;\r
+    140                \r
+    141                // Save to see if battery data has changed.\r
+    142                oldCapacity = BattData.Capacity;  \r
+   \   00000004   ....               LDI     R30, LOW(BattData)\r
+   \   00000006   ....               LDI     R31, (BattData) >> 8\r
+   \   00000008   8104               LDD     R16, Z+4\r
+   \   0000000A   8115               LDD     R17, Z+5\r
+   \   0000000C   01D8               MOVW    R27:R26, R17:R16\r
+    143                \r
+    144                if (!BatteryStatusRefresh()) {\r
+   \   0000000E   ....               RCALL   BatteryStatusRefresh\r
+   \   00000010   2300               TST     R16\r
+   \   00000012   F409               BRNE    ??BatteryCheck_0\r
+    145                        success = FALSE;              // Battery not present or RID was invalid.\r
+   \   00000014   E080               LDI     R24, 0\r
+    146                }\r
+    147                \r
+    148                if (oldCapacity != BattData.Capacity) {\r
+   \                     ??BatteryCheck_0:\r
+   \   00000016   ....               LDI     R30, LOW(BattData)\r
+   \   00000018   ....               LDI     R31, (BattData) >> 8\r
+   \   0000001A   8104               LDD     R16, Z+4\r
+   \   0000001C   8115               LDD     R17, Z+5\r
+   \   0000001E   17A0               CP      R26, R16\r
+   \   00000020   07B1               CPC     R27, R17\r
+   \   00000022   F009               BREQ    ??BatteryCheck_1\r
+    149                        success = FALSE;              // Battery configuration has changed.\r
+   \   00000024   E080               LDI     R24, 0\r
+    150                }\r
+    151          \r
+    152                return(success);\r
+   \                     ??BatteryCheck_1:\r
+   \   00000026   2F08               MOV     R16, R24\r
+   \   00000028   E0E4               LDI     R30, 4\r
+   \   0000002A   ....               RJMP    ?EPILOGUE_B4_L09\r
+    153          }\r
+    154          \r
+    155          \r
+    156          /*! \brief Refreshes battery status information\r
+    157           *\r
+    158           * Refreshes battery status information, if it is present, based on\r
+    159           * RID and NTC (read by ADC).\n\r
+    160           * The battery must have been enabled and a complete set of ADC data must have\r
+    161           * been collected before calling.\n\r
+    162           *\r
+    163           * \retval FALSE No battery present.\r
+    164           * \retval TRUE Battery present, status refreshed.\r
+    165           *\r
+    166           * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
+    167           * is found in the lookup table. Instead, default battery data will be used.\r
+    168           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    169          unsigned char BatteryStatusRefresh(void)\r
+   \                     BatteryStatusRefresh:\r
+    170          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+    171                // Assume the worst..\r
+    172                unsigned char success = FALSE;\r
+   \   00000002   E080               LDI     R24, 0\r
+    173                \r
+    174                BattData.Present = FALSE;\r
+   \   00000004   ....               LDI     R30, LOW(BattData)\r
+   \   00000006   ....               LDI     R31, (BattData) >> 8\r
+   \   00000008   8100               LD      R16, Z\r
+   \   0000000A   7F0E               ANDI    R16, 0xFE\r
+   \   0000000C   8300               ST      Z, R16\r
+    175                BattData.Charged = FALSE;\r
+   \   0000000E   ....               LDI     R30, LOW(BattData)\r
+   \   00000010   ....               LDI     R31, (BattData) >> 8\r
+   \   00000012   8100               LD      R16, Z\r
+   \   00000014   7F0D               ANDI    R16, 0xFD\r
+   \   00000016   8300               ST      Z, R16\r
+    176                BattData.Low = TRUE;\r
+   \   00000018   ....               LDI     R30, LOW(BattData)\r
+   \   0000001A   ....               LDI     R31, (BattData) >> 8\r
+   \   0000001C   8100               LD      R16, Z\r
+   \   0000001E   6004               ORI     R16, 0x04\r
+   \   00000020   8300               ST      Z, R16\r
+    177                BattData.Circuit = OW_NONE;\r
+   \   00000022   E000               LDI     R16, 0\r
+   \   00000024   9300....           STS     (BattData + 1), R16\r
+    178                BattData.Temperature = 0;\r
+   \   00000028   E000               LDI     R16, 0\r
+   \   0000002A   9300....           STS     (BattData + 2), R16\r
+    179                BattData.Capacity = 0;\r
+   \   0000002E   E000               LDI     R16, 0\r
+   \   00000030   E010               LDI     R17, 0\r
+   \   00000032   ....               LDI     R30, LOW(BattData)\r
+   \   00000034   ....               LDI     R31, (BattData) >> 8\r
+   \   00000036   8304               STD     Z+4, R16\r
+   \   00000038   8315               STD     Z+5, R17\r
+    180                BattData.MaxCurrent = 0;\r
+   \   0000003A   E000               LDI     R16, 0\r
+   \   0000003C   E010               LDI     R17, 0\r
+   \   0000003E   ....               LDI     R30, LOW(BattData)\r
+   \   00000040   ....               LDI     R31, (BattData) >> 8\r
+   \   00000042   8306               STD     Z+6, R16\r
+   \   00000044   8317               STD     Z+7, R17\r
+    181                BattData.MaxTime = 0;\r
+   \   00000046   E000               LDI     R16, 0\r
+   \   00000048   E010               LDI     R17, 0\r
+   \   0000004A   ....               LDI     R30, LOW(BattData)\r
+   \   0000004C   ....               LDI     R31, (BattData) >> 8\r
+   \   0000004E   8700               STD     Z+8, R16\r
+   \   00000050   8711               STD     Z+9, R17\r
+    182                BattData.MinCurrent = 0;\r
+   \   00000052   E000               LDI     R16, 0\r
+   \   00000054   E010               LDI     R17, 0\r
+   \   00000056   ....               LDI     R30, LOW(BattData)\r
+   \   00000058   ....               LDI     R31, (BattData) >> 8\r
+   \   0000005A   8702               STD     Z+10, R16\r
+   \   0000005C   8713               STD     Z+11, R17\r
+    183          \r
+    184                NTCLookUp();\r
+   \   0000005E   ....               RCALL   NTCLookUp\r
+    185                BattData.HasRID = RIDLookUp();\r
+   \   00000060   ....               RCALL   RIDLookUp\r
+   \   00000062   2F10               MOV     R17, R16\r
+   \   00000064   7011               ANDI    R17, 0x01\r
+   \   00000066   ....               LDI     R30, LOW(BattData)\r
+   \   00000068   ....               LDI     R31, (BattData) >> 8\r
+   \   0000006A   FB10               BST     R17, 0\r
+   \   0000006C   8100               LD      R16, Z\r
+   \   0000006E   F904               BLD     R16, 4\r
+   \   00000070   8300               ST      Z, R16\r
+   \   00000072   E000               LDI     R16, 0\r
+   \   00000074   F900               BLD     R16, 0\r
+    186          \r
+    187                // Is the battery voltage above minimum safe cell voltage?\r
+    188                if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+   \   00000076   ....               LDI     R30, LOW(ADCS)\r
+   \   00000078   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000007A   8502               LDD     R16, Z+10\r
+   \   0000007C   8513               LDD     R17, Z+11\r
+   \   0000007E   3600               CPI     R16, 96\r
+   \   00000080   E029               LDI     R18, 9\r
+   \   00000082   0712               CPC     R17, R18\r
+   \   00000084   F028               BRCS    ??BatteryStatusRefresh_0\r
+    189                        BattData.Low = FALSE;\r
+   \   00000086   ....               LDI     R30, LOW(BattData)\r
+   \   00000088   ....               LDI     R31, (BattData) >> 8\r
+   \   0000008A   8100               LD      R16, Z\r
+   \   0000008C   7F0B               ANDI    R16, 0xFB\r
+   \   0000008E   8300               ST      Z, R16\r
+    190                }\r
+    191          \r
+    192                // Is the battery charged?\r
+    193                if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+   \                     ??BatteryStatusRefresh_0:\r
+   \   00000090   ....               LDI     R30, LOW(ADCS)\r
+   \   00000092   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000094   8502               LDD     R16, Z+10\r
+   \   00000096   8513               LDD     R17, Z+11\r
+   \   00000098   3D02               CPI     R16, 210\r
+   \   0000009A   E02F               LDI     R18, 15\r
+   \   0000009C   0712               CPC     R17, R18\r
+   \   0000009E   F028               BRCS    ??BatteryStatusRefresh_1\r
+    194                        BattData.Charged = TRUE;\r
+   \   000000A0   ....               LDI     R30, LOW(BattData)\r
+   \   000000A2   ....               LDI     R31, (BattData) >> 8\r
+   \   000000A4   8100               LD      R16, Z\r
+   \   000000A6   6002               ORI     R16, 0x02\r
+   \   000000A8   8300               ST      Z, R16\r
+    195                }\r
+    196          \r
+    197                // If we are not charging, yet VBAT is above safe limit, battery is present.\r
+    198                // If we are charging and there's a current flowing, the battery is present.\r
+    199                \r
+    200                /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
+    201                * check is redundant since charging will be aborted due to low current at\r
+    202                * max duty cycle. That is preferrable since the charge current reading is\r
+    203                * not 100% proof.\r
+    204                */\r
+    205                if (((OCR1B == 0) && (!BattData.Low)) ||\r
+    206                    ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+   \                     ??BatteryStatusRefresh_1:\r
+   \   000000AA   B50C               IN      R16, 0x2C\r
+   \   000000AC   2300               TST     R16\r
+   \   000000AE   F429               BRNE    ??BatteryStatusRefresh_2\r
+   \   000000B0   ....               LDI     R30, LOW(BattData)\r
+   \   000000B2   ....               LDI     R31, (BattData) >> 8\r
+   \   000000B4   8100               LD      R16, Z\r
+   \   000000B6   FF02               SBRS    R16, 2\r
+   \   000000B8   C00A               RJMP    ??BatteryStatusRefresh_3\r
+   \                     ??BatteryStatusRefresh_2:\r
+   \   000000BA   B50C               IN      R16, 0x2C\r
+   \   000000BC   2300               TST     R16\r
+   \   000000BE   F071               BREQ    ??BatteryStatusRefresh_4\r
+   \   000000C0   ....               LDI     R26, LOW((ADCS + 22))\r
+   \   000000C2   ....               LDI     R27, HIGH((ADCS + 22))\r
+   \   000000C4   91ED               LD      R30, X+\r
+   \   000000C6   91FC               LD      R31, X\r
+   \   000000C8   9711               SBIW    R27:R26, 1\r
+   \   000000CA   9731               SBIW    R31:R30, 1\r
+   \   000000CC   F03C               BRLT    ??BatteryStatusRefresh_4\r
+    207                        BattData.Present = TRUE;\r
+   \                     ??BatteryStatusRefresh_3:\r
+   \   000000CE   ....               LDI     R30, LOW(BattData)\r
+   \   000000D0   ....               LDI     R31, (BattData) >> 8\r
+   \   000000D2   8100               LD      R16, Z\r
+   \   000000D4   6001               ORI     R16, 0x01\r
+   \   000000D6   8300               ST      Z, R16\r
+    208                        success = TRUE;\r
+   \   000000D8   E081               LDI     R24, 1\r
+   \   000000DA   C006               RJMP    ??BatteryStatusRefresh_5\r
+    209                } else {\r
+    210                        BattData.Low = FALSE;  // (This is just a technicality..)\r
+   \                     ??BatteryStatusRefresh_4:\r
+   \   000000DC   ....               LDI     R30, LOW(BattData)\r
+   \   000000DE   ....               LDI     R31, (BattData) >> 8\r
+   \   000000E0   8100               LD      R16, Z\r
+   \   000000E2   7F0B               ANDI    R16, 0xFB\r
+   \   000000E4   8300               ST      Z, R16\r
+    211                        success = FALSE;\r
+   \   000000E6   E080               LDI     R24, 0\r
+    212                }\r
+    213          \r
+    214          #ifndef ALLOW_NO_RID\r
+    215                // Return FALSE if no valid RID entry was found, to stop charging.\r
+    216                if(!BattData.HasRID) {\r
+   \                     ??BatteryStatusRefresh_5:\r
+   \   000000E8   ....               LDI     R30, LOW(BattData)\r
+   \   000000EA   ....               LDI     R31, (BattData) >> 8\r
+   \   000000EC   8100               LD      R16, Z\r
+   \   000000EE   FF04               SBRS    R16, 4\r
+    217                        success = FALSE;\r
+   \   000000F0   E080               LDI     R24, 0\r
+    218                }\r
+    219          #endif\r
+    220          \r
+    221                return(success);\r
+   \                     ??BatteryStatusRefresh_6:\r
+   \   000000F2   2F08               MOV     R16, R24\r
+   \   000000F4   E0E4               LDI     R30, 4\r
+   \   000000F6   ....               RJMP    ?EPILOGUE_B4_L09\r
+   \   000000F8                      REQUIRE _A_OCR1B\r
+    222          }\r
+    223          \r
+    224          \r
+    225          /*! \brief Refreshes battery data in the EEPROM\r
+    226           *\r
+    227           * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
+    228           * these data in on-chip EEPROM.\n\r
+    229           * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
+    230           *\r
+    231           * \todo Updating BattData with these data. Specs needed.\r
+    232           *\r
+    233           * \retval FALSE Refresh failed.\r
+    234           * \retval TRUE Refresh successful.\r
+    235           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    236          unsigned char BatteryDataRefresh(void)\r
+   \                     BatteryDataRefresh:\r
+    237          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE8_L09\r
+   \   00000002                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R7_is_cg_reg\r
+    238                unsigned char offset;\r
+    239                unsigned char i, crc, family, temp, page;\r
+    240                unsigned char success;\r
+    241                \r
+    242                // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
+    243                for (page = 0; page < 4; page++)        {\r
+   \   00000002   E090               LDI     R25, 0\r
+   \                     ??BatteryDataRefresh_0:\r
+   \   00000004   3094               CPI     R25, 4\r
+   \   00000006   F008               BRCS    $+2+2\r
+   \   00000008   C084               RJMP    ??BatteryDataRefresh_1\r
+    244                        success = FALSE;\r
+   \   0000000A   E0B0               LDI     R27, 0\r
+    245                \r
+    246                        if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
+   \   0000000C   E001               LDI     R16, 1\r
+   \   0000000E   ....               RCALL   OWI_DetectPresence\r
+   \   00000010   3001               CPI     R16, 1\r
+   \   00000012   F009               BREQ    $+2+2\r
+   \   00000014   C065               RJMP    ??BatteryDataRefresh_2\r
+    247                                \r
+    248                                // Presence detected, check type and CRC.\r
+    249                                OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
+   \   00000016   E011               LDI     R17, 1\r
+   \   00000018   E303               LDI     R16, 51\r
+   \   0000001A   ....               RCALL   OWI_SendByte\r
+    250                                family = OWI_ReceiveByte(OWIBUS);\r
+   \   0000001C   E001               LDI     R16, 1\r
+   \   0000001E   ....               RCALL   OWI_ReceiveByte\r
+   \   00000020   2E60               MOV     R6, R16\r
+    251                                crc = OWI_ComputeCRC8(family,0);\r
+   \   00000022   E010               LDI     R17, 0\r
+   \   00000024   2D06               MOV     R16, R6\r
+   \   00000026   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000028   2E50               MOV     R5, R16\r
+    252          \r
+    253                                for (i = 0; i < 6; i++) {\r
+   \   0000002A   E080               LDI     R24, 0\r
+   \                     ??BatteryDataRefresh_3:\r
+   \   0000002C   3086               CPI     R24, 6\r
+   \   0000002E   F438               BRCC    ??BatteryDataRefresh_4\r
+    254                                        crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
+   \   00000030   E001               LDI     R16, 1\r
+   \   00000032   ....               RCALL   OWI_ReceiveByte\r
+   \   00000034   2D15               MOV     R17, R5\r
+   \   00000036   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000038   2E50               MOV     R5, R16\r
+    255                                }\r
+   \   0000003A   9583               INC     R24\r
+   \   0000003C   CFF7               RJMP    ??BatteryDataRefresh_3\r
+    256          \r
+    257                                // CRC ok, device found.\r
+    258                                if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+   \                     ??BatteryDataRefresh_4:\r
+   \   0000003E   E001               LDI     R16, 1\r
+   \   00000040   ....               RCALL   OWI_ReceiveByte\r
+   \   00000042   2D15               MOV     R17, R5\r
+   \   00000044   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000046   2300               TST     R16\r
+   \   00000048   F009               BREQ    $+2+2\r
+   \   0000004A   C04A               RJMP    ??BatteryDataRefresh_2\r
+    259                                        BattData.Circuit = family;\r
+   \   0000004C   9260....           STS     (BattData + 1), R6\r
+    260          \r
+    261                                        // For now, we only read data from DS2505 EPROMs.\r
+    262                                        if (BattData.Circuit == OW_DS2505) {\r
+   \   00000050   9100....           LDS     R16, (BattData + 1)\r
+   \   00000054   3009               CPI     R16, 9\r
+   \   00000056   F009               BREQ    $+2+2\r
+   \   00000058   C043               RJMP    ??BatteryDataRefresh_2\r
+    263                                                offset = page*32;\r
+   \   0000005A   2F09               MOV     R16, R25\r
+   \   0000005C   9502               SWAP    R16\r
+   \   0000005E   7F00               ANDI    R16, 0xF0\r
+   \   00000060   0F00               LSL     R16\r
+   \   00000062   2E40               MOV     R4, R16\r
+    264                                                OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
+   \   00000064   E011               LDI     R17, 1\r
+   \   00000066   EC03               LDI     R16, 195\r
+   \   00000068   ....               RCALL   OWI_SendByte\r
+    265                                                OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
+   \   0000006A   E011               LDI     R17, 1\r
+   \   0000006C   2D04               MOV     R16, R4\r
+   \   0000006E   ....               RCALL   OWI_SendByte\r
+    266                                                OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
+   \   00000070   E011               LDI     R17, 1\r
+   \   00000072   E000               LDI     R16, 0\r
+   \   00000074   ....               RCALL   OWI_SendByte\r
+    267          \r
+    268                                                // Calculate checksums.\r
+    269                                                crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
+   \   00000076   E010               LDI     R17, 0\r
+   \   00000078   EC03               LDI     R16, 195\r
+   \   0000007A   ....               RCALL   OWI_ComputeCRC8\r
+   \   0000007C   2E50               MOV     R5, R16\r
+    270                                                crc = OWI_ComputeCRC8(offset,crc);\r
+   \   0000007E   2D15               MOV     R17, R5\r
+   \   00000080   2D04               MOV     R16, R4\r
+   \   00000082   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000084   2E50               MOV     R5, R16\r
+    271                                                crc = OWI_ComputeCRC8(0,crc);\r
+   \   00000086   2D15               MOV     R17, R5\r
+   \   00000088   E000               LDI     R16, 0\r
+   \   0000008A   ....               RCALL   OWI_ComputeCRC8\r
+   \   0000008C   2E50               MOV     R5, R16\r
+    272          \r
+    273                                                // Command received succesfully, now start reading data\r
+    274                                                // and writing it to EEPROM.\r
+    275                                                if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+   \   0000008E   E001               LDI     R16, 1\r
+   \   00000090   ....               RCALL   OWI_ReceiveByte\r
+   \   00000092   2D15               MOV     R17, R5\r
+   \   00000094   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000096   2300               TST     R16\r
+   \   00000098   F519               BRNE    ??BatteryDataRefresh_2\r
+    276                                                        crc = 0;\r
+   \   0000009A   2455               CLR     R5\r
+    277                                                        \r
+    278                                                        // Fill page with data.\r
+    279                                                        for (i=0; i<32; i++) {\r
+   \   0000009C   E080               LDI     R24, 0\r
+   \                     ??BatteryDataRefresh_5:\r
+   \   0000009E   3280               CPI     R24, 32\r
+   \   000000A0   F4C0               BRCC    ??BatteryDataRefresh_6\r
+    280                                                                temp = OWI_ReceiveByte(OWIBUS);\r
+   \   000000A2   E001               LDI     R16, 1\r
+   \   000000A4   ....               RCALL   OWI_ReceiveByte\r
+   \   000000A6   2E70               MOV     R7, R16\r
+    281                                                                crc = OWI_ComputeCRC8(temp, crc);\r
+   \   000000A8   2D15               MOV     R17, R5\r
+   \   000000AA   2D07               MOV     R16, R7\r
+   \   000000AC   ....               RCALL   OWI_ComputeCRC8\r
+   \   000000AE   2E50               MOV     R5, R16\r
+    282                                                                BattEEPROM[page][i] = temp;\r
+   \   000000B0   2F49               MOV     R20, R25\r
+   \   000000B2   E050               LDI     R21, 0\r
+   \   000000B4   E200               LDI     R16, 32\r
+   \   000000B6   E010               LDI     R17, 0\r
+   \   000000B8   ....               RCALL   ?S_MUL_L02\r
+   \   000000BA   ....               LDI     R20, LOW(BattEEPROM)\r
+   \   000000BC   ....               LDI     R21, (BattEEPROM) >> 8\r
+   \   000000BE   0F40               ADD     R20, R16\r
+   \   000000C0   1F51               ADC     R21, R17\r
+   \   000000C2   2F08               MOV     R16, R24\r
+   \   000000C4   E010               LDI     R17, 0\r
+   \   000000C6   0F40               ADD     R20, R16\r
+   \   000000C8   1F51               ADC     R21, R17\r
+   \   000000CA   2D07               MOV     R16, R7\r
+   \   000000CC   ....               RCALL   __eeput8_16\r
+    283                                                        }\r
+   \   000000CE   9583               INC     R24\r
+   \   000000D0   CFE6               RJMP    ??BatteryDataRefresh_5\r
+    284                                                        \r
+    285                                                        if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+   \                     ??BatteryDataRefresh_6:\r
+   \   000000D2   E001               LDI     R16, 1\r
+   \   000000D4   ....               RCALL   OWI_ReceiveByte\r
+   \   000000D6   2D15               MOV     R17, R5\r
+   \   000000D8   ....               RCALL   OWI_ComputeCRC8\r
+   \   000000DA   2300               TST     R16\r
+   \   000000DC   F409               BRNE    ??BatteryDataRefresh_2\r
+    286                                                                        success = TRUE;  // Data read OK\r
+   \   000000DE   E0B1               LDI     R27, 1\r
+    287                                                        }\r
+    288                                                } else { // Not able to start reading data.\r
+    289                                                }\r
+    290                                        } else { // Wrong device type.\r
+    291                                        }\r
+    292                                } else { // No device found.             \r
+    293                                }\r
+    294                        } else { // No presence detected on one-wire bus.\r
+    295                        }\r
+    296          \r
+    297                  // Erase local EEPROM page if there were any errors during transfer.\r
+    298                        if (!success) {\r
+   \                     ??BatteryDataRefresh_2:\r
+   \   000000E0   23BB               TST     R27\r
+   \   000000E2   F4A9               BRNE    ??BatteryDataRefresh_7\r
+    299                                for (i=0; i<32; i++) {\r
+   \   000000E4   E080               LDI     R24, 0\r
+   \                     ??BatteryDataRefresh_8:\r
+   \   000000E6   3280               CPI     R24, 32\r
+   \   000000E8   F490               BRCC    ??BatteryDataRefresh_7\r
+    300                                        BattEEPROM[page][i] = 0;\r
+   \   000000EA   E0A0               LDI     R26, 0\r
+   \   000000EC   2F49               MOV     R20, R25\r
+   \   000000EE   E050               LDI     R21, 0\r
+   \   000000F0   E200               LDI     R16, 32\r
+   \   000000F2   E010               LDI     R17, 0\r
+   \   000000F4   ....               RCALL   ?S_MUL_L02\r
+   \   000000F6   ....               LDI     R20, LOW(BattEEPROM)\r
+   \   000000F8   ....               LDI     R21, (BattEEPROM) >> 8\r
+   \   000000FA   0F40               ADD     R20, R16\r
+   \   000000FC   1F51               ADC     R21, R17\r
+   \   000000FE   2F08               MOV     R16, R24\r
+   \   00000100   E010               LDI     R17, 0\r
+   \   00000102   0F40               ADD     R20, R16\r
+   \   00000104   1F51               ADC     R21, R17\r
+   \   00000106   2F0A               MOV     R16, R26\r
+   \   00000108   ....               RCALL   __eeput8_16\r
+    301                                }\r
+   \   0000010A   9583               INC     R24\r
+   \   0000010C   CFEC               RJMP    ??BatteryDataRefresh_8\r
+    302                        }\r
+    303                }\r
+   \                     ??BatteryDataRefresh_7:\r
+   \   0000010E   9593               INC     R25\r
+   \   00000110   CF79               RJMP    ??BatteryDataRefresh_0\r
+    304          \r
+    305                return(success);\r
+   \                     ??BatteryDataRefresh_1:\r
+   \   00000112   2F0B               MOV     R16, R27\r
+   \   00000114   E0E8               LDI     R30, 8\r
+   \   00000116   ....               RJMP    ?EPILOGUE_B8_L09\r
+    306          }\r
+    307          \r
+    308          \r
+    309          /*! \brief Enables specified battery\r
+    310           *\r
+    311           * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
+    312           * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
+    313           * The function takes 100 ms to allow the port switch to settle.\r
+    314           *\r
+    315           * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
+    316           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    317          void EnableBattery(unsigned char bat)\r
+   \                     EnableBattery:\r
+    318          {\r
+   \   00000000   938A               ST      -Y, R24\r
+   \   00000002   2F80               MOV     R24, R16\r
+    319                // Use general timer, set timeout to 100ms.\r
+    320                Time_Set(TIMER_GEN,0,0,100);\r
+   \   00000004   E644               LDI     R20, 100\r
+   \   00000006   E010               LDI     R17, 0\r
+   \   00000008   E020               LDI     R18, 0\r
+   \   0000000A   E030               LDI     R19, 0\r
+   \   0000000C   E002               LDI     R16, 2\r
+   \   0000000E   ....               RCALL   Time_Set\r
+    321          \r
+    322                // Set specified battery as the active one.\r
+    323                BattActive = bat;\r
+   \   00000010   9380....           STS     BattActive, R24\r
+    324          \r
+    325                // Enable current battery in hardware, light LED & connect battery.\r
+    326                PORTB |= (1 << (PB4+bat));\r
+   \   00000014   E001               LDI     R16, 1\r
+   \   00000016   E010               LDI     R17, 0\r
+   \   00000018   2F48               MOV     R20, R24\r
+   \   0000001A   5F4C               SUBI    R20, 252\r
+   \   0000001C   ....               RCALL   ?S_SHL_L02\r
+   \   0000001E   B318               IN      R17, 0x18\r
+   \   00000020   2B10               OR      R17, R16\r
+   \   00000022   BB18               OUT     0x18, R17\r
+    327          \r
+    328                // Disconnect other battery.\r
+    329                PORTB &= ~(1<<(PB5-bat));     \r
+   \   00000024   E001               LDI     R16, 1\r
+   \   00000026   E010               LDI     R17, 0\r
+   \   00000028   E045               LDI     R20, 5\r
+   \   0000002A   1B48               SUB     R20, R24\r
+   \   0000002C   ....               RCALL   ?S_SHL_L02\r
+   \   0000002E   9500               COM     R16\r
+   \   00000030   B318               IN      R17, 0x18\r
+   \   00000032   2310               AND     R17, R16\r
+   \   00000034   BB18               OUT     0x18, R17\r
+    330          \r
+    331                do { // Let port switch settle.\r
+    332                } while (Time_Left(TIMER_GEN));  \r
+   \                     ??EnableBattery_0:\r
+   \   00000036   E002               LDI     R16, 2\r
+   \   00000038   ....               RCALL   Time_Left\r
+   \   0000003A   2300               TST     R16\r
+   \   0000003C   F7E1               BRNE    ??EnableBattery_0\r
+    333          }\r
+   \   0000003E   9189               LD      R24, Y+\r
+   \   00000040   9508               RET\r
+   \   00000042                      REQUIRE _A_PORTB\r
+    334          \r
+    335          \r
+    336          /*! \brief Disables both batteries\r
+    337           *\r
+    338           * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
+    339           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    340          void DisableBatteries(void)\r
+   \                     DisableBatteries:\r
+    341          {\r
+    342                // Turn off LEDs and disconnect batteries.\r
+    343                PORTB &= ~((1<<PB4)|(1<<PB5));  \r
+   \   00000000   B308               IN      R16, 0x18\r
+   \   00000002   7C0F               ANDI    R16, 0xCF\r
+   \   00000004   BB08               OUT     0x18, R16\r
+    344          }\r
+   \   00000006   9508               RET\r
+   \   00000008                      REQUIRE _A_PORTB\r
+    345          \r
+    346          \r
+    347          /*! \brief Looks up battery data from RID table\r
+    348           *\r
+    349           * Attempts to find data for the battery from the RID lookup-table.\n\r
+    350           * If no valid entry is found, default data (defined in battery.h)\r
+    351           * are used.\r
+    352           *\r
+    353           * \retval TRUE Entry found, battery data updated.\r
+    354           * \retval FALSE No entry found, using defaults for battery data.\r
+    355           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    356          unsigned char RIDLookUp (void)\r
+   \                     RIDLookUp:\r
+    357          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+    358                unsigned char i, found = FALSE;\r
+   \   00000002   E090               LDI     R25, 0\r
+    359                        \r
+    360                // Lookup in the RID-table. If measured RID is within the limits\r
+    361                // of an entry, those data are used, and TRUE is returned.\r
+    362                for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
+   \   00000004   E080               LDI     R24, 0\r
+   \                     ??RIDLookUp_0:\r
+   \   00000006   3084               CPI     R24, 4\r
+   \   00000008   F008               BRCS    $+2+2\r
+   \   0000000A   C05E               RJMP    ??RIDLookUp_1\r
+    363                        if (ADCS.rawRID >= RID[i].Low) {\r
+   \   0000000C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000000E   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000010   81A2               LDD     R26, Z+2\r
+   \   00000012   81B3               LDD     R27, Z+3\r
+   \   00000014   2F48               MOV     R20, R24\r
+   \   00000016   E050               LDI     R21, 0\r
+   \   00000018   E00E               LDI     R16, 14\r
+   \   0000001A   E010               LDI     R17, 0\r
+   \   0000001C   ....               RCALL   ?S_MUL_L02\r
+   \   0000001E   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000020   ....               SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+   \   00000022   ....               SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+   \   00000024   8100               LD      R16, Z\r
+   \   00000026   8111               LDD     R17, Z+1\r
+   \   00000028   17A0               CP      R26, R16\r
+   \   0000002A   07B1               CPC     R27, R17\r
+   \   0000002C   F408               BRCC    $+2+2\r
+   \   0000002E   C04A               RJMP    ??RIDLookUp_2\r
+    364                                if (ADCS.rawRID <= RID[i].High) {\r
+   \   00000030   2F48               MOV     R20, R24\r
+   \   00000032   E050               LDI     R21, 0\r
+   \   00000034   E00E               LDI     R16, 14\r
+   \   00000036   E010               LDI     R17, 0\r
+   \   00000038   ....               RCALL   ?S_MUL_L02\r
+   \   0000003A   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000003C   ....               SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+   \   0000003E   ....               SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+   \   00000040   8102               LDD     R16, Z+2\r
+   \   00000042   8113               LDD     R17, Z+3\r
+   \   00000044   ....               LDI     R30, LOW(ADCS)\r
+   \   00000046   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000048   8122               LDD     R18, Z+2\r
+   \   0000004A   8133               LDD     R19, Z+3\r
+   \   0000004C   1702               CP      R16, R18\r
+   \   0000004E   0713               CPC     R17, R19\r
+   \   00000050   F1C8               BRCS    ??RIDLookUp_2\r
+    365                                        BattData.Capacity = RID[i].Capacity;\r
+   \   00000052   2F48               MOV     R20, R24\r
+   \   00000054   E050               LDI     R21, 0\r
+   \   00000056   E00E               LDI     R16, 14\r
+   \   00000058   E010               LDI     R17, 0\r
+   \   0000005A   ....               RCALL   ?S_MUL_L02\r
+   \   0000005C   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000005E   ....               SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+   \   00000060   ....               SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+   \   00000062   8106               LDD     R16, Z+6\r
+   \   00000064   8117               LDD     R17, Z+7\r
+   \   00000066   ....               LDI     R30, LOW(BattData)\r
+   \   00000068   ....               LDI     R31, (BattData) >> 8\r
+   \   0000006A   8304               STD     Z+4, R16\r
+   \   0000006C   8315               STD     Z+5, R17\r
+    366                                        BattData.MaxCurrent = RID[i].Icharge;\r
+   \   0000006E   2F48               MOV     R20, R24\r
+   \   00000070   E050               LDI     R21, 0\r
+   \   00000072   E00E               LDI     R16, 14\r
+   \   00000074   E010               LDI     R17, 0\r
+   \   00000076   ....               RCALL   ?S_MUL_L02\r
+   \   00000078   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000007A   ....               SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+   \   0000007C   ....               SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+   \   0000007E   8500               LDD     R16, Z+8\r
+   \   00000080   8511               LDD     R17, Z+9\r
+   \   00000082   ....               LDI     R30, LOW(BattData)\r
+   \   00000084   ....               LDI     R31, (BattData) >> 8\r
+   \   00000086   8306               STD     Z+6, R16\r
+   \   00000088   8317               STD     Z+7, R17\r
+    367                                        BattData.MaxTime = RID[i].tCutOff;\r
+   \   0000008A   2F48               MOV     R20, R24\r
+   \   0000008C   E050               LDI     R21, 0\r
+   \   0000008E   E00E               LDI     R16, 14\r
+   \   00000090   E010               LDI     R17, 0\r
+   \   00000092   ....               RCALL   ?S_MUL_L02\r
+   \   00000094   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000096   ....               SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+   \   00000098   ....               SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+   \   0000009A   8502               LDD     R16, Z+10\r
+   \   0000009C   8513               LDD     R17, Z+11\r
+   \   0000009E   ....               LDI     R30, LOW(BattData)\r
+   \   000000A0   ....               LDI     R31, (BattData) >> 8\r
+   \   000000A2   8700               STD     Z+8, R16\r
+   \   000000A4   8711               STD     Z+9, R17\r
+    368                                        BattData.MinCurrent = RID[i].ICutOff;\r
+   \   000000A6   2F48               MOV     R20, R24\r
+   \   000000A8   E050               LDI     R21, 0\r
+   \   000000AA   E00E               LDI     R16, 14\r
+   \   000000AC   E010               LDI     R17, 0\r
+   \   000000AE   ....               RCALL   ?S_MUL_L02\r
+   \   000000B0   01F8               MOVW    R31:R30, R17:R16\r
+   \   000000B2   ....               SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+   \   000000B4   ....               SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+   \   000000B6   8504               LDD     R16, Z+12\r
+   \   000000B8   8515               LDD     R17, Z+13\r
+   \   000000BA   ....               LDI     R30, LOW(BattData)\r
+   \   000000BC   ....               LDI     R31, (BattData) >> 8\r
+   \   000000BE   8702               STD     Z+10, R16\r
+   \   000000C0   8713               STD     Z+11, R17\r
+    369                                        \r
+    370                                        found = TRUE;\r
+   \   000000C2   E091               LDI     R25, 1\r
+    371                                }\r
+    372                        }\r
+    373                }\r
+   \                     ??RIDLookUp_2:\r
+   \   000000C4   9583               INC     R24\r
+   \   000000C6   CF9F               RJMP    ??RIDLookUp_0\r
+    374                \r
+    375                // If no valid entry is found, use defaults and return FALSE.\r
+    376                if (!found) {\r
+   \                     ??RIDLookUp_1:\r
+   \   000000C8   2399               TST     R25\r
+   \   000000CA   F4C1               BRNE    ??RIDLookUp_3\r
+    377                        BattData.Capacity = DEF_BAT_CAPACITY;\r
+   \   000000CC   E000               LDI     R16, 0\r
+   \   000000CE   E010               LDI     R17, 0\r
+   \   000000D0   ....               LDI     R30, LOW(BattData)\r
+   \   000000D2   ....               LDI     R31, (BattData) >> 8\r
+   \   000000D4   8304               STD     Z+4, R16\r
+   \   000000D6   8315               STD     Z+5, R17\r
+    378                        BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
+   \   000000D8   E000               LDI     R16, 0\r
+   \   000000DA   E010               LDI     R17, 0\r
+   \   000000DC   ....               LDI     R30, LOW(BattData)\r
+   \   000000DE   ....               LDI     R31, (BattData) >> 8\r
+   \   000000E0   8306               STD     Z+6, R16\r
+   \   000000E2   8317               STD     Z+7, R17\r
+    379                        BattData.MaxTime = DEF_BAT_TIME_MAX;\r
+   \   000000E4   E000               LDI     R16, 0\r
+   \   000000E6   E010               LDI     R17, 0\r
+   \   000000E8   ....               LDI     R30, LOW(BattData)\r
+   \   000000EA   ....               LDI     R31, (BattData) >> 8\r
+   \   000000EC   8700               STD     Z+8, R16\r
+   \   000000EE   8711               STD     Z+9, R17\r
+    380                        BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
+   \   000000F0   E000               LDI     R16, 0\r
+   \   000000F2   E010               LDI     R17, 0\r
+   \   000000F4   ....               LDI     R30, LOW(BattData)\r
+   \   000000F6   ....               LDI     R31, (BattData) >> 8\r
+   \   000000F8   8702               STD     Z+10, R16\r
+   \   000000FA   8713               STD     Z+11, R17\r
+    381                }\r
+    382                \r
+    383                return(found);\r
+   \                     ??RIDLookUp_3:\r
+   \   000000FC   2F09               MOV     R16, R25\r
+   \   000000FE   E0E4               LDI     R30, 4\r
+   \   00000100   ....               RJMP    ?EPILOGUE_B4_L09\r
+    384          }\r
+    385          \r
+    386          \r
+    387          /*! \brief Calculates temperature from a lookup table\r
+    388           *\r
+    389           * Looks up the highest NTC value below or equal to the measured one.\n\r
+    390           * With the current lookup table, temperature is calculated with the formula:\n\r
+    391           * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
+    392           *\r
+    393           * \note If the NTC-measurement is saturated, with the current lookup table,\r
+    394           * the temperature will be reported as -1 C.\r
+    395           *\r
+    396           * \note If no valid entry is found, battery temperature is set to 80.\r
+    397           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    398          void NTCLookUp (void)\r
+   \                     NTCLookUp:\r
+    399          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+    400                unsigned char i;\r
+    401                unsigned char found = FALSE;\r
+   \   00000002   E090               LDI     R25, 0\r
+    402                \r
+    403                // Lookup in the NTC-table. Use the first entry which is equal or below\r
+    404                // sampled NTC. Calculate temperature by using the index number, and the\r
+    405                // difference between the measured NTC value and the one in the entry.\r
+    406                for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
+   \   00000004   E080               LDI     R24, 0\r
+   \                     ??NTCLookUp_0:\r
+   \   00000006   3184               CPI     R24, 20\r
+   \   00000008   F008               BRCS    $+2+2\r
+   \   0000000A   C043               RJMP    ??NTCLookUp_1\r
+   \   0000000C   2399               TST     R25\r
+   \   0000000E   F009               BREQ    $+2+2\r
+   \   00000010   C040               RJMP    ??NTCLookUp_1\r
+    407                        if (ADCS.rawNTC >= NTC[i].ADC) {\r
+   \   00000012   ....               LDI     R30, LOW(ADCS)\r
+   \   00000014   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000016   81A4               LDD     R26, Z+4\r
+   \   00000018   81B5               LDD     R27, Z+5\r
+   \   0000001A   2F48               MOV     R20, R24\r
+   \   0000001C   E050               LDI     R21, 0\r
+   \   0000001E   E003               LDI     R16, 3\r
+   \   00000020   E010               LDI     R17, 0\r
+   \   00000022   ....               RCALL   ?S_MUL_L02\r
+   \   00000024   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000026   ....               SUBI    R30, LOW((-(NTC) & 0xFFFF))\r
+   \   00000028   ....               SBCI    R31, (-(NTC) & 0xFFFF) >> 8\r
+   \   0000002A   8100               LD      R16, Z\r
+   \   0000002C   8111               LDD     R17, Z+1\r
+   \   0000002E   17A0               CP      R26, R16\r
+   \   00000030   07B1               CPC     R27, R17\r
+   \   00000032   F168               BRCS    ??NTCLookUp_2\r
+    408                                BattData.Temperature = (i<<2) ;\r
+   \   00000034   2F08               MOV     R16, R24\r
+   \   00000036   0F00               LSL     R16\r
+   \   00000038   0F00               LSL     R16\r
+   \   0000003A   9300....           STS     (BattData + 2), R16\r
+    409                                BattData.ADCSteps = NTC[i].ADCsteps;  \r
+   \   0000003E   2F48               MOV     R20, R24\r
+   \   00000040   E050               LDI     R21, 0\r
+   \   00000042   E003               LDI     R16, 3\r
+   \   00000044   E010               LDI     R17, 0\r
+   \   00000046   ....               RCALL   ?S_MUL_L02\r
+   \   00000048   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000004A   ....               SUBI    R30, LOW((-(NTC) & 0xFFFF))\r
+   \   0000004C   ....               SBCI    R31, (-(NTC) & 0xFFFF) >> 8\r
+   \   0000004E   8102               LDD     R16, Z+2\r
+   \   00000050   9300....           STS     (BattData + 3), R16\r
+    410                                BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;\r
+   \   00000054   ....               LDI     R30, LOW(ADCS)\r
+   \   00000056   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000058   81A4               LDD     R26, Z+4\r
+   \   0000005A   81B5               LDD     R27, Z+5\r
+   \   0000005C   2F48               MOV     R20, R24\r
+   \   0000005E   E050               LDI     R21, 0\r
+   \   00000060   E003               LDI     R16, 3\r
+   \   00000062   E010               LDI     R17, 0\r
+   \   00000064   ....               RCALL   ?S_MUL_L02\r
+   \   00000066   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000068   ....               SUBI    R30, LOW((-(NTC) & 0xFFFF))\r
+   \   0000006A   ....               SBCI    R31, (-(NTC) & 0xFFFF) >> 8\r
+   \   0000006C   8100               LD      R16, Z\r
+   \   0000006E   8111               LDD     R17, Z+1\r
+   \   00000070   1BA0               SUB     R26, R16\r
+   \   00000072   0BB1               SBC     R27, R17\r
+   \   00000074   0FAA               LSL     R26\r
+   \   00000076   1FBB               ROL     R27\r
+   \   00000078   018D               MOVW    R17:R16, R27:R26\r
+   \   0000007A   9140....           LDS     R20, (BattData + 3)\r
+   \   0000007E   E050               LDI     R21, 0\r
+   \   00000080   ....               RCALL   ?US_DIVMOD_L02\r
+   \   00000082   ....               LDI     R30, LOW(BattData)\r
+   \   00000084   ....               LDI     R31, (BattData) >> 8\r
+   \   00000086   8112               LDD     R17, Z+2\r
+   \   00000088   1B10               SUB     R17, R16\r
+   \   0000008A   8312               STD     Z+2, R17\r
+    411                                \r
+    412                                found = TRUE;  // Could be done with a break, but that violates MISRA.\r
+   \   0000008C   E091               LDI     R25, 1\r
+    413                        }\r
+    414                }\r
+   \                     ??NTCLookUp_2:\r
+   \   0000008E   9583               INC     R24\r
+   \   00000090   CFBA               RJMP    ??NTCLookUp_0\r
+    415                \r
+    416                // For safety, is temperature is greater than the NTC \r
+    417                if (!found) {\r
+   \                     ??NTCLookUp_1:\r
+   \   00000092   2399               TST     R25\r
+   \   00000094   F419               BRNE    ??NTCLookUp_3\r
+    418                        BattData.Temperature = 80;\r
+   \   00000096   E500               LDI     R16, 80\r
+   \   00000098   9300....           STS     (BattData + 2), R16\r
+    419                }\r
+    420          }\r
+   \                     ??NTCLookUp_3:\r
+   \   0000009C   E0E4               LDI     R30, 4\r
+   \   0000009E   ....               RJMP    ?EPILOGUE_B4_L09\r
+\r
+   \                                 In  segment NEAR_ID, align 1, keep-with-next\r
+   \                     `?<Initializer for RID>`:\r
+   \   00000000   022E02930F3C       DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14\r
+   \              02260104012C\r
+   \              000A02E8034B\r
+   \              1A9002EE0168\r
+   \              012C000E    \r
+   \   0000001C   036503BE2710       DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475\r
+   \              03E801DB012C\r
+   \              001304490481\r
+   \              5DC007D001DB\r
+   \   00000034   01A40026           DW 420, 38\r
+\r
+   \                                 In  segment NEAR_ID, align 1, keep-with-next\r
+   \                     `?<Initializer for NTC>`:\r
+   \   00000000   03EA               DW 1002\r
+   \   00000002   17                 DB 23\r
+   \   00000003   03B9               DW 953\r
+   \   00000005   19                 DB 25\r
+   \   00000006   0386               DW 902\r
+   \   00000008   1A                 DB 26\r
+   \   00000009   0351               DW 849\r
+   \   0000000B   1B                 DB 27\r
+   \   0000000C   031C               DW 796\r
+   \   0000000E   1B                 DB 27\r
+   \   0000000F   02E6               DW 742\r
+   \   00000011   1B                 DB 27\r
+   \   00000012   02B1               DW 689\r
+   \   00000014   1A                 DB 26\r
+   \   00000015   027D               DW 637\r
+   \   00000017   1A                 DB 26\r
+   \   00000018   024B               DW 587\r
+   \   0000001A   19                 DB 25\r
+   \   0000001B   021B               DW 539\r
+   \   0000001D   18                 DB 24\r
+   \   0000001E   01EE               DW 494\r
+   \   00000020   16                 DB 22\r
+   \   00000021   01C3               DW 451\r
+   \   00000023   15                 DB 21\r
+   \   00000024   019C               DW 412\r
+   \   00000026   13                 DB 19\r
+   \   00000027   0177               DW 375\r
+   \   00000029   12                 DB 18\r
+   \   0000002A   0155               DW 341\r
+   \   0000002C   11                 DB 17\r
+   \   0000002D   0136               DW 310\r
+   \   0000002F   0F                 DB 15\r
+   \   00000030   011A               DW 282\r
+   \   00000032   0E                 DB 14\r
+   \   00000033   0100               DW 256\r
+   \   00000035   0D                 DB 13\r
+   \   00000036   00E9               DW 233\r
+   \   00000038   0B                 DB 11\r
+   \   00000039   00D4               DW 212\r
+   \   0000003B   0A                 DB 10\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function                  CSTACK RSTACK\r
+     --------                  ------ ------\r
+     BatteryCheck                  4      2\r
+       -> BatteryStatusRefresh     4      2\r
+     BatteryDataRefresh            8      4\r
+       -> OWI_DetectPresence       8      2\r
+       -> OWI_SendByte             8      2\r
+       -> OWI_ReceiveByte          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ReceiveByte          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ReceiveByte          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_SendByte             8      2\r
+       -> OWI_SendByte             8      2\r
+       -> OWI_SendByte             8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ReceiveByte          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ReceiveByte          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+       -> OWI_ReceiveByte          8      2\r
+       -> OWI_ComputeCRC8          8      2\r
+     BatteryStatusRefresh          4      2\r
+       -> NTCLookUp                4      2\r
+       -> RIDLookUp                4      2\r
+     DisableBatteries              0      2\r
+     EnableBattery                 1      4\r
+       -> Time_Set                 1      2\r
+       -> Time_Left                1      2\r
+     NTCLookUp                     4      4\r
+     RIDLookUp                     4      4\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label         Bytes\r
+     --------------         -----\r
+     _A_OCR1B                  1\r
+     _A_PORTB                  1\r
+     BattControl               2\r
+     BattData                 12\r
+     BattEEPROM              128\r
+     BattActive                1\r
+     RID                      56\r
+     NTC                      60\r
+     BatteryCheck             44\r
+     BatteryStatusRefresh    248\r
+     BatteryDataRefresh      280\r
+     EnableBattery            66\r
+     DisableBatteries          8\r
+     RIDLookUp               258\r
+     NTCLookUp               160\r
+     ?<Initializer for RID>   56\r
+     ?<Initializer for NTC>   60\r
+      Others                  12\r
+\r
\r
+     2 bytes in segment ABSOLUTE\r
+ 1 064 bytes in segment CODE\r
+   130 bytes in segment EEPROM_I\r
+    12 bytes in segment INITTAB\r
+   116 bytes in segment NEAR_I\r
+   116 bytes in segment NEAR_ID\r
+    13 bytes in segment NEAR_Z\r
\r
+ 1 180 bytes of CODE  memory (+ 12 bytes shared)\r
+   129 bytes of DATA  memory (+  2 bytes shared)\r
+   130 bytes of XDATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/battery.s90 b/BaseTinyFirmware/IAR/Debug/List/battery.s90
new file mode 100644 (file)
index 0000000..8060a46
--- /dev/null
@@ -0,0 +1,1211 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:38 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\battery.c           /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\battery.c           /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\battery. /\r
+//                    s90                                                     /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME battery\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B4_L09\r
+        EXTERN ?EPILOGUE_B8_L09\r
+        EXTERN ?PROLOGUE4_L09\r
+        EXTERN ?PROLOGUE8_L09\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?Register_R7_is_cg_reg\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?S_SHL_L02\r
+        EXTERN ?US_DIVMOD_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_I>`\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC BattActive\r
+        PUBLIC BattControl\r
+        PUBLIC BattData\r
+        PUBLIC BattEEPROM\r
+        PUBLIC BatteryCheck\r
+        PUBLIC BatteryDataRefresh\r
+        PUBLIC BatteryStatusRefresh\r
+        PUBLIC DisableBatteries\r
+        PUBLIC EnableBattery\r
+        PUBLIC NTC\r
+        PUBLIC NTCLookUp\r
+        PUBLIC RID\r
+        PUBLIC RIDLookUp\r
+        PUBWEAK _A_OCR1B\r
+        PUBWEAK _A_PORTB\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN OWI_DetectPresence\r
+        EXTERN OWI_SendByte\r
+        EXTERN OWI_ReceiveByte\r
+        EXTERN OWI_ComputeCRC8\r
+        EXTERN Time_Set\r
+        EXTERN Time_Left\r
+        EXTERN ADCS\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\battery.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions related to battery control and data acquisition.\r
+//    6  *\r
+//    7  *      Contains functions for enabling/disabling batteries, and looking up\r
+//    8  *      their status and specifications using the ADC.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13 \r
+//   14  *\r
+//   15  * \par Documentation\r
+//   16  *      For comprehensive code documentation, supported compilers, compiler \r
+//   17  *      settings and supported devices see readme.html\r
+//   18  *\r
+//   19  * \author\r
+//   20  *      Atmel Corporation: http://www.atmel.com \n\r
+//   21  *      Support email: avr@atmel.com\r
+//   22  *\r
+//   23  * \r
+//   24  * $Name$\r
+//   25  * $Revision: 2299 $\r
+//   26  * $RCSfile$\r
+//   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
+//   28  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   29  ******************************************************************************/\r
+//   30 \r
+//   31 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
+// <unnamed> volatile __io _A_OCR1B\r
+_A_OCR1B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,038H\r
+// <unnamed> volatile __io _A_PORTB\r
+_A_PORTB:\r
+        DS 1\r
+//   32 #include <inavr.h>\r
+//   33 \r
+//   34 #include "structs.h"\r
+//   35 #include "enums.h"\r
+//   36 \r
+//   37 #include "ADC.h"\r
+//   38 #include "battery.h"\r
+//   39 #include "main.h"\r
+//   40 #include "OWI.h"\r
+//   41 #include "time.h"\r
+//   42 \r
+//   43 #ifdef NIMH\r
+//   44 #include "NIMHspecs.h"\r
+//   45 #endif // NIMH\r
+//   46 \r
+//   47 #ifdef LIION\r
+//   48 #include "LIIONspecs.h"\r
+//   49 #endif // LIION\r
+//   50 \r
+//   51 \r
+//   52 \r
+//   53 //******************************************************************************\r
+//   54 // Variables\r
+//   55 //******************************************************************************\r
+//   56 /* Control-struct for batteries */\r
+//   57 /*! \brief Holds control data for both batteries\r
+//   58  * \note Stored in EEPROM.\r
+//   59  */\r
+\r
+        RSEG EEPROM_I:XDATA:NOROOT(0)\r
+//   60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},\r
+BattControl:\r
+        DB 3, 3\r
+//   61                                      {TRUE, TRUE, FALSE}};\r
+//   62 \r
+//   63 /* Data-struct for battery */\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   64 Batteries_t BattData; //!< Holds data for the current battery\r
+BattData:\r
+        DS 12\r
+//   65 \r
+//   66 \r
+//   67 /* Storage for battery EPROM */\r
+//   68 /*! \brief Storage space for data from the batteries' own EPROMs.\r
+//   69  * \note Stored in EEPROM.\r
+//   70  */\r
+\r
+        RSEG EEPROM_I:XDATA:NOROOT(0)\r
+//   71 __eeprom unsigned char BattEEPROM[4][32];\r
+BattEEPROM:\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+//   72 \r
+//   73 \r
+//   74 //! Global that indicates current battery (0 = battery A, 1 = B)\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   75 unsigned char BattActive;\r
+BattActive:\r
+        DS 1\r
+//   76 \r
+//   77 \r
+//   78 /*! \brief RID lookup-table\r
+//   79  *\r
+//   80  * Contains Resistor ID data specified by manufacturer.\r
+//   81  *\r
+//   82  * \note Values have been calculated assuming a +/- 15% tolerance.\r
+//   83  */\r
+\r
+        RSEG NEAR_I:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_I>`\r
+//   84 const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
+RID:\r
+        DS 56\r
+        REQUIRE `?<Initializer for RID>`\r
+//   85   {558, 659, 3900, 550, 260, 300, 10},\r
+//   86   {744, 843, 6800, 750, 360, 300, 14},\r
+//   87   {869, 958, 10000, 1000, 475, 300, 19},\r
+//   88   {1097, 1153, 24000, 2000, 475, 420, 38}\r
+//   89 };\r
+//   90 \r
+//   91 \r
+//   92 /*! \brief NTC lookup-table\r
+//   93  *\r
+//   94  * The first entry is 0 degrees. For every entry after, temperature increases\r
+//   95  * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
+//   96  * It must be sorted in descending ADC order.\r
+//   97  *\r
+//   98  * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
+//   99  *\r
+//  100  * \note NTCLookUp() must be modified if this table is changed so that:\r
+//  101  * - first entry is no longer 0 degrees.\r
+//  102  * - temperature difference between entries is no longer 4 degrees.\r
+//  103  * - ADCsteps no longer specifies ADC steps per half degree.\r
+//  104  */\r
+//  105 // FOR VARTA POLYFLEX NTC\r
+\r
+        RSEG NEAR_I:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_I>`\r
+//  106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+NTC:\r
+        DS 60\r
+        REQUIRE `?<Initializer for NTC>`\r
+//  107        {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
+//  108        {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
+//  109        {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
+//  110        {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
+//  111 };\r
+//  112 \r
+//  113 \r
+//  114 // FOR MITSUBISHI NTC\r
+//  115 /*\r
+//  116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+//  117   {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
+//  118   {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
+//  119   {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
+//  120   {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
+//  121 };\r
+//  122 */\r
+//  123 \r
+//  124 \r
+//  125 //******************************************************************************\r
+//  126 // Functions\r
+//  127 //******************************************************************************\r
+//  128 /*! \brief Checks if battery has changed\r
+//  129  *\r
+//  130  * Stores current capacity, then attempts to refresh battery status.\n\r
+//  131  * If the refresh is successful, old capacity is compared with the new one.\r
+//  132  * \r
+//  133  * \retval FALSE Battery is disconnected, or capacity has changed.\r
+//  134  * \retval TRUE All OK.\r
+//  135  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  136 unsigned char BatteryCheck(void)\r
+BatteryCheck:\r
+//  137 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//  138        unsigned char success = TRUE;\r
+        LDI     R24, 1\r
+//  139        unsigned int  oldCapacity;\r
+//  140        \r
+//  141        // Save to see if battery data has changed.\r
+//  142        oldCapacity = BattData.Capacity;  \r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        MOVW    R27:R26, R17:R16\r
+//  143        \r
+//  144        if (!BatteryStatusRefresh()) {\r
+        RCALL   BatteryStatusRefresh\r
+        TST     R16\r
+        BRNE    ??BatteryCheck_0\r
+//  145                success = FALSE;              // Battery not present or RID was invalid.\r
+        LDI     R24, 0\r
+//  146        }\r
+//  147        \r
+//  148        if (oldCapacity != BattData.Capacity) {\r
+??BatteryCheck_0:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BREQ    ??BatteryCheck_1\r
+//  149                success = FALSE;              // Battery configuration has changed.\r
+        LDI     R24, 0\r
+//  150        }\r
+//  151 \r
+//  152        return(success);\r
+??BatteryCheck_1:\r
+        MOV     R16, R24\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  153 }\r
+//  154 \r
+//  155 \r
+//  156 /*! \brief Refreshes battery status information\r
+//  157  *\r
+//  158  * Refreshes battery status information, if it is present, based on\r
+//  159  * RID and NTC (read by ADC).\n\r
+//  160  * The battery must have been enabled and a complete set of ADC data must have\r
+//  161  * been collected before calling.\n\r
+//  162  *\r
+//  163  * \retval FALSE No battery present.\r
+//  164  * \retval TRUE Battery present, status refreshed.\r
+//  165  *\r
+//  166  * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
+//  167  * is found in the lookup table. Instead, default battery data will be used.\r
+//  168  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  169 unsigned char BatteryStatusRefresh(void)\r
+BatteryStatusRefresh:\r
+//  170 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//  171        // Assume the worst..\r
+//  172        unsigned char success = FALSE;\r
+        LDI     R24, 0\r
+//  173        \r
+//  174        BattData.Present = FALSE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xFE\r
+        ST      Z, R16\r
+//  175        BattData.Charged = FALSE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xFD\r
+        ST      Z, R16\r
+//  176        BattData.Low = TRUE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x04\r
+        ST      Z, R16\r
+//  177        BattData.Circuit = OW_NONE;\r
+        LDI     R16, 0\r
+        STS     (BattData + 1), R16\r
+//  178        BattData.Temperature = 0;\r
+        LDI     R16, 0\r
+        STS     (BattData + 2), R16\r
+//  179        BattData.Capacity = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+4, R16\r
+        STD     Z+5, R17\r
+//  180        BattData.MaxCurrent = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+6, R16\r
+        STD     Z+7, R17\r
+//  181        BattData.MaxTime = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+8, R16\r
+        STD     Z+9, R17\r
+//  182        BattData.MinCurrent = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+10, R16\r
+        STD     Z+11, R17\r
+//  183 \r
+//  184        NTCLookUp();\r
+        RCALL   NTCLookUp\r
+//  185        BattData.HasRID = RIDLookUp();\r
+        RCALL   RIDLookUp\r
+        MOV     R17, R16\r
+        ANDI    R17, 0x01\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        BST     R17, 0\r
+        LD      R16, Z\r
+        BLD     R16, 4\r
+        ST      Z, R16\r
+        LDI     R16, 0\r
+        BLD     R16, 0\r
+//  186 \r
+//  187        // Is the battery voltage above minimum safe cell voltage?\r
+//  188        if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        CPI     R16, 96\r
+        LDI     R18, 9\r
+        CPC     R17, R18\r
+        BRCS    ??BatteryStatusRefresh_0\r
+//  189                BattData.Low = FALSE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xFB\r
+        ST      Z, R16\r
+//  190        }\r
+//  191 \r
+//  192        // Is the battery charged?\r
+//  193        if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+??BatteryStatusRefresh_0:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        CPI     R16, 210\r
+        LDI     R18, 15\r
+        CPC     R17, R18\r
+        BRCS    ??BatteryStatusRefresh_1\r
+//  194                BattData.Charged = TRUE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x02\r
+        ST      Z, R16\r
+//  195        }\r
+//  196 \r
+//  197        // If we are not charging, yet VBAT is above safe limit, battery is present.\r
+//  198        // If we are charging and there's a current flowing, the battery is present.\r
+//  199        \r
+//  200        /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
+//  201        * check is redundant since charging will be aborted due to low current at\r
+//  202        * max duty cycle. That is preferrable since the charge current reading is\r
+//  203        * not 100% proof.\r
+//  204        */\r
+//  205        if (((OCR1B == 0) && (!BattData.Low)) ||\r
+//  206            ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+??BatteryStatusRefresh_1:\r
+        IN      R16, 0x2C\r
+        TST     R16\r
+        BRNE    ??BatteryStatusRefresh_2\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 2\r
+        RJMP    ??BatteryStatusRefresh_3\r
+??BatteryStatusRefresh_2:\r
+        IN      R16, 0x2C\r
+        TST     R16\r
+        BREQ    ??BatteryStatusRefresh_4\r
+        LDI     R26, LOW((ADCS + 22))\r
+        LDI     R27, HIGH((ADCS + 22))\r
+        LD      R30, X+\r
+        LD      R31, X\r
+        SBIW    R27:R26, 1\r
+        SBIW    R31:R30, 1\r
+        BRLT    ??BatteryStatusRefresh_4\r
+//  207                BattData.Present = TRUE;\r
+??BatteryStatusRefresh_3:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x01\r
+        ST      Z, R16\r
+//  208                success = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??BatteryStatusRefresh_5\r
+//  209        } else {\r
+//  210                BattData.Low = FALSE;  // (This is just a technicality..)\r
+??BatteryStatusRefresh_4:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xFB\r
+        ST      Z, R16\r
+//  211                success = FALSE;\r
+        LDI     R24, 0\r
+//  212        }\r
+//  213 \r
+//  214 #ifndef ALLOW_NO_RID\r
+//  215        // Return FALSE if no valid RID entry was found, to stop charging.\r
+//  216        if(!BattData.HasRID) {\r
+??BatteryStatusRefresh_5:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 4\r
+//  217                success = FALSE;\r
+        LDI     R24, 0\r
+//  218        }\r
+//  219 #endif\r
+//  220 \r
+//  221        return(success);\r
+??BatteryStatusRefresh_6:\r
+        MOV     R16, R24\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+        REQUIRE _A_OCR1B\r
+//  222 }\r
+//  223 \r
+//  224 \r
+//  225 /*! \brief Refreshes battery data in the EEPROM\r
+//  226  *\r
+//  227  * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
+//  228  * these data in on-chip EEPROM.\n\r
+//  229  * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
+//  230  *\r
+//  231  * \todo Updating BattData with these data. Specs needed.\r
+//  232  *\r
+//  233  * \retval FALSE Refresh failed.\r
+//  234  * \retval TRUE Refresh successful.\r
+//  235  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  236 unsigned char BatteryDataRefresh(void)\r
+BatteryDataRefresh:\r
+//  237 {\r
+        RCALL   ?PROLOGUE8_L09\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        REQUIRE ?Register_R7_is_cg_reg\r
+//  238        unsigned char offset;\r
+//  239        unsigned char i, crc, family, temp, page;\r
+//  240        unsigned char success;\r
+//  241        \r
+//  242        // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
+//  243        for (page = 0; page < 4; page++)        {\r
+        LDI     R25, 0\r
+??BatteryDataRefresh_0:\r
+        CPI     R25, 4\r
+        BRCS    $+2+2\r
+        RJMP    ??BatteryDataRefresh_1\r
+//  244                success = FALSE;\r
+        LDI     R27, 0\r
+//  245        \r
+//  246                if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
+        LDI     R16, 1\r
+        RCALL   OWI_DetectPresence\r
+        CPI     R16, 1\r
+        BREQ    $+2+2\r
+        RJMP    ??BatteryDataRefresh_2\r
+//  247                        \r
+//  248                        // Presence detected, check type and CRC.\r
+//  249                        OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
+        LDI     R17, 1\r
+        LDI     R16, 51\r
+        RCALL   OWI_SendByte\r
+//  250                        family = OWI_ReceiveByte(OWIBUS);\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R6, R16\r
+//  251                        crc = OWI_ComputeCRC8(family,0);\r
+        LDI     R17, 0\r
+        MOV     R16, R6\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R5, R16\r
+//  252 \r
+//  253                        for (i = 0; i < 6; i++) {\r
+        LDI     R24, 0\r
+??BatteryDataRefresh_3:\r
+        CPI     R24, 6\r
+        BRCC    ??BatteryDataRefresh_4\r
+//  254                                crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R5\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R5, R16\r
+//  255                        }\r
+        INC     R24\r
+        RJMP    ??BatteryDataRefresh_3\r
+//  256 \r
+//  257                        // CRC ok, device found.\r
+//  258                        if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+??BatteryDataRefresh_4:\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R5\r
+        RCALL   OWI_ComputeCRC8\r
+        TST     R16\r
+        BREQ    $+2+2\r
+        RJMP    ??BatteryDataRefresh_2\r
+//  259                                BattData.Circuit = family;\r
+        STS     (BattData + 1), R6\r
+//  260 \r
+//  261                                // For now, we only read data from DS2505 EPROMs.\r
+//  262                                if (BattData.Circuit == OW_DS2505) {\r
+        LDS     R16, (BattData + 1)\r
+        CPI     R16, 9\r
+        BREQ    $+2+2\r
+        RJMP    ??BatteryDataRefresh_2\r
+//  263                                        offset = page*32;\r
+        MOV     R16, R25\r
+        SWAP    R16\r
+        ANDI    R16, 0xF0\r
+        LSL     R16\r
+        MOV     R4, R16\r
+//  264                                        OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
+        LDI     R17, 1\r
+        LDI     R16, 195\r
+        RCALL   OWI_SendByte\r
+//  265                                        OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
+        LDI     R17, 1\r
+        MOV     R16, R4\r
+        RCALL   OWI_SendByte\r
+//  266                                        OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
+        LDI     R17, 1\r
+        LDI     R16, 0\r
+        RCALL   OWI_SendByte\r
+//  267 \r
+//  268                                        // Calculate checksums.\r
+//  269                                        crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
+        LDI     R17, 0\r
+        LDI     R16, 195\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R5, R16\r
+//  270                                        crc = OWI_ComputeCRC8(offset,crc);\r
+        MOV     R17, R5\r
+        MOV     R16, R4\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R5, R16\r
+//  271                                        crc = OWI_ComputeCRC8(0,crc);\r
+        MOV     R17, R5\r
+        LDI     R16, 0\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R5, R16\r
+//  272 \r
+//  273                                        // Command received succesfully, now start reading data\r
+//  274                                        // and writing it to EEPROM.\r
+//  275                                        if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R5\r
+        RCALL   OWI_ComputeCRC8\r
+        TST     R16\r
+        BRNE    ??BatteryDataRefresh_2\r
+//  276                                                crc = 0;\r
+        CLR     R5\r
+//  277                                                \r
+//  278                                                // Fill page with data.\r
+//  279                                                for (i=0; i<32; i++) {\r
+        LDI     R24, 0\r
+??BatteryDataRefresh_5:\r
+        CPI     R24, 32\r
+        BRCC    ??BatteryDataRefresh_6\r
+//  280                                                        temp = OWI_ReceiveByte(OWIBUS);\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R7, R16\r
+//  281                                                        crc = OWI_ComputeCRC8(temp, crc);\r
+        MOV     R17, R5\r
+        MOV     R16, R7\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R5, R16\r
+//  282                                                        BattEEPROM[page][i] = temp;\r
+        MOV     R20, R25\r
+        LDI     R21, 0\r
+        LDI     R16, 32\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R20, LOW(BattEEPROM)\r
+        LDI     R21, (BattEEPROM) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R24\r
+        LDI     R17, 0\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R7\r
+        RCALL   __eeput8_16\r
+//  283                                                }\r
+        INC     R24\r
+        RJMP    ??BatteryDataRefresh_5\r
+//  284                                                \r
+//  285                                                if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+??BatteryDataRefresh_6:\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R5\r
+        RCALL   OWI_ComputeCRC8\r
+        TST     R16\r
+        BRNE    ??BatteryDataRefresh_2\r
+//  286                                                                success = TRUE;  // Data read OK\r
+        LDI     R27, 1\r
+//  287                                                }\r
+//  288                                        } else { // Not able to start reading data.\r
+//  289                                        }\r
+//  290                                } else { // Wrong device type.\r
+//  291                                }\r
+//  292                        } else { // No device found.             \r
+//  293                        }\r
+//  294                } else { // No presence detected on one-wire bus.\r
+//  295                }\r
+//  296 \r
+//  297          // Erase local EEPROM page if there were any errors during transfer.\r
+//  298                if (!success) {\r
+??BatteryDataRefresh_2:\r
+        TST     R27\r
+        BRNE    ??BatteryDataRefresh_7\r
+//  299                        for (i=0; i<32; i++) {\r
+        LDI     R24, 0\r
+??BatteryDataRefresh_8:\r
+        CPI     R24, 32\r
+        BRCC    ??BatteryDataRefresh_7\r
+//  300                                BattEEPROM[page][i] = 0;\r
+        LDI     R26, 0\r
+        MOV     R20, R25\r
+        LDI     R21, 0\r
+        LDI     R16, 32\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R20, LOW(BattEEPROM)\r
+        LDI     R21, (BattEEPROM) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R24\r
+        LDI     R17, 0\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R26\r
+        RCALL   __eeput8_16\r
+//  301                        }\r
+        INC     R24\r
+        RJMP    ??BatteryDataRefresh_8\r
+//  302                }\r
+//  303        }\r
+??BatteryDataRefresh_7:\r
+        INC     R25\r
+        RJMP    ??BatteryDataRefresh_0\r
+//  304 \r
+//  305        return(success);\r
+??BatteryDataRefresh_1:\r
+        MOV     R16, R27\r
+        LDI     R30, 8\r
+        RJMP    ?EPILOGUE_B8_L09\r
+//  306 }\r
+//  307 \r
+//  308 \r
+//  309 /*! \brief Enables specified battery\r
+//  310  *\r
+//  311  * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
+//  312  * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
+//  313  * The function takes 100 ms to allow the port switch to settle.\r
+//  314  *\r
+//  315  * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
+//  316  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  317 void EnableBattery(unsigned char bat)\r
+EnableBattery:\r
+//  318 {\r
+        ST      -Y, R24\r
+        MOV     R24, R16\r
+//  319        // Use general timer, set timeout to 100ms.\r
+//  320        Time_Set(TIMER_GEN,0,0,100);\r
+        LDI     R20, 100\r
+        LDI     R17, 0\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 2\r
+        RCALL   Time_Set\r
+//  321 \r
+//  322        // Set specified battery as the active one.\r
+//  323        BattActive = bat;\r
+        STS     BattActive, R24\r
+//  324 \r
+//  325        // Enable current battery in hardware, light LED & connect battery.\r
+//  326        PORTB |= (1 << (PB4+bat));\r
+        LDI     R16, 1\r
+        LDI     R17, 0\r
+        MOV     R20, R24\r
+        SUBI    R20, 252\r
+        RCALL   ?S_SHL_L02\r
+        IN      R17, 0x18\r
+        OR      R17, R16\r
+        OUT     0x18, R17\r
+//  327 \r
+//  328        // Disconnect other battery.\r
+//  329        PORTB &= ~(1<<(PB5-bat));     \r
+        LDI     R16, 1\r
+        LDI     R17, 0\r
+        LDI     R20, 5\r
+        SUB     R20, R24\r
+        RCALL   ?S_SHL_L02\r
+        COM     R16\r
+        IN      R17, 0x18\r
+        AND     R17, R16\r
+        OUT     0x18, R17\r
+//  330 \r
+//  331        do { // Let port switch settle.\r
+//  332        } while (Time_Left(TIMER_GEN));  \r
+??EnableBattery_0:\r
+        LDI     R16, 2\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??EnableBattery_0\r
+//  333 }\r
+        LD      R24, Y+\r
+        RET\r
+        REQUIRE _A_PORTB\r
+//  334 \r
+//  335 \r
+//  336 /*! \brief Disables both batteries\r
+//  337  *\r
+//  338  * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
+//  339  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  340 void DisableBatteries(void)\r
+DisableBatteries:\r
+//  341 {\r
+//  342        // Turn off LEDs and disconnect batteries.\r
+//  343        PORTB &= ~((1<<PB4)|(1<<PB5));  \r
+        IN      R16, 0x18\r
+        ANDI    R16, 0xCF\r
+        OUT     0x18, R16\r
+//  344 }\r
+        RET\r
+        REQUIRE _A_PORTB\r
+//  345 \r
+//  346 \r
+//  347 /*! \brief Looks up battery data from RID table\r
+//  348  *\r
+//  349  * Attempts to find data for the battery from the RID lookup-table.\n\r
+//  350  * If no valid entry is found, default data (defined in battery.h)\r
+//  351  * are used.\r
+//  352  *\r
+//  353  * \retval TRUE Entry found, battery data updated.\r
+//  354  * \retval FALSE No entry found, using defaults for battery data.\r
+//  355  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  356 unsigned char RIDLookUp (void)\r
+RIDLookUp:\r
+//  357 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//  358        unsigned char i, found = FALSE;\r
+        LDI     R25, 0\r
+//  359                \r
+//  360        // Lookup in the RID-table. If measured RID is within the limits\r
+//  361        // of an entry, those data are used, and TRUE is returned.\r
+//  362        for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
+        LDI     R24, 0\r
+??RIDLookUp_0:\r
+        CPI     R24, 4\r
+        BRCS    $+2+2\r
+        RJMP    ??RIDLookUp_1\r
+//  363                if (ADCS.rawRID >= RID[i].Low) {\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R26, Z+2\r
+        LDD     R27, Z+3\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 14\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+        SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        LDD     R17, Z+1\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BRCC    $+2+2\r
+        RJMP    ??RIDLookUp_2\r
+//  364                        if (ADCS.rawRID <= RID[i].High) {\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 14\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+        SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+        LDD     R16, Z+2\r
+        LDD     R17, Z+3\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+2\r
+        LDD     R19, Z+3\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCS    ??RIDLookUp_2\r
+//  365                                BattData.Capacity = RID[i].Capacity;\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 14\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+        SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+        LDD     R16, Z+6\r
+        LDD     R17, Z+7\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+4, R16\r
+        STD     Z+5, R17\r
+//  366                                BattData.MaxCurrent = RID[i].Icharge;\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 14\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+        SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+        LDD     R16, Z+8\r
+        LDD     R17, Z+9\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+6, R16\r
+        STD     Z+7, R17\r
+//  367                                BattData.MaxTime = RID[i].tCutOff;\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 14\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+        SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+8, R16\r
+        STD     Z+9, R17\r
+//  368                                BattData.MinCurrent = RID[i].ICutOff;\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 14\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(RID) & 0xFFFF))\r
+        SBCI    R31, (-(RID) & 0xFFFF) >> 8\r
+        LDD     R16, Z+12\r
+        LDD     R17, Z+13\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+10, R16\r
+        STD     Z+11, R17\r
+//  369                                \r
+//  370                                found = TRUE;\r
+        LDI     R25, 1\r
+//  371                        }\r
+//  372                }\r
+//  373        }\r
+??RIDLookUp_2:\r
+        INC     R24\r
+        RJMP    ??RIDLookUp_0\r
+//  374        \r
+//  375        // If no valid entry is found, use defaults and return FALSE.\r
+//  376        if (!found) {\r
+??RIDLookUp_1:\r
+        TST     R25\r
+        BRNE    ??RIDLookUp_3\r
+//  377                BattData.Capacity = DEF_BAT_CAPACITY;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+4, R16\r
+        STD     Z+5, R17\r
+//  378                BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+6, R16\r
+        STD     Z+7, R17\r
+//  379                BattData.MaxTime = DEF_BAT_TIME_MAX;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+8, R16\r
+        STD     Z+9, R17\r
+//  380                BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        STD     Z+10, R16\r
+        STD     Z+11, R17\r
+//  381        }\r
+//  382        \r
+//  383        return(found);\r
+??RIDLookUp_3:\r
+        MOV     R16, R25\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  384 }\r
+//  385 \r
+//  386 \r
+//  387 /*! \brief Calculates temperature from a lookup table\r
+//  388  *\r
+//  389  * Looks up the highest NTC value below or equal to the measured one.\n\r
+//  390  * With the current lookup table, temperature is calculated with the formula:\n\r
+//  391  * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
+//  392  *\r
+//  393  * \note If the NTC-measurement is saturated, with the current lookup table,\r
+//  394  * the temperature will be reported as -1 C.\r
+//  395  *\r
+//  396  * \note If no valid entry is found, battery temperature is set to 80.\r
+//  397  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  398 void NTCLookUp (void)\r
+NTCLookUp:\r
+//  399 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//  400        unsigned char i;\r
+//  401        unsigned char found = FALSE;\r
+        LDI     R25, 0\r
+//  402        \r
+//  403        // Lookup in the NTC-table. Use the first entry which is equal or below\r
+//  404        // sampled NTC. Calculate temperature by using the index number, and the\r
+//  405        // difference between the measured NTC value and the one in the entry.\r
+//  406        for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
+        LDI     R24, 0\r
+??NTCLookUp_0:\r
+        CPI     R24, 20\r
+        BRCS    $+2+2\r
+        RJMP    ??NTCLookUp_1\r
+        TST     R25\r
+        BREQ    $+2+2\r
+        RJMP    ??NTCLookUp_1\r
+//  407                if (ADCS.rawNTC >= NTC[i].ADC) {\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R26, Z+4\r
+        LDD     R27, Z+5\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(NTC) & 0xFFFF))\r
+        SBCI    R31, (-(NTC) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        LDD     R17, Z+1\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BRCS    ??NTCLookUp_2\r
+//  408                        BattData.Temperature = (i<<2) ;\r
+        MOV     R16, R24\r
+        LSL     R16\r
+        LSL     R16\r
+        STS     (BattData + 2), R16\r
+//  409                        BattData.ADCSteps = NTC[i].ADCsteps;  \r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(NTC) & 0xFFFF))\r
+        SBCI    R31, (-(NTC) & 0xFFFF) >> 8\r
+        LDD     R16, Z+2\r
+        STS     (BattData + 3), R16\r
+//  410                        BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R26, Z+4\r
+        LDD     R27, Z+5\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(NTC) & 0xFFFF))\r
+        SBCI    R31, (-(NTC) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        LDD     R17, Z+1\r
+        SUB     R26, R16\r
+        SBC     R27, R17\r
+        LSL     R26\r
+        ROL     R27\r
+        MOVW    R17:R16, R27:R26\r
+        LDS     R20, (BattData + 3)\r
+        LDI     R21, 0\r
+        RCALL   ?US_DIVMOD_L02\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R17, Z+2\r
+        SUB     R17, R16\r
+        STD     Z+2, R17\r
+//  411                        \r
+//  412                        found = TRUE;  // Could be done with a break, but that violates MISRA.\r
+        LDI     R25, 1\r
+//  413                }\r
+//  414        }\r
+??NTCLookUp_2:\r
+        INC     R24\r
+        RJMP    ??NTCLookUp_0\r
+//  415        \r
+//  416        // For safety, is temperature is greater than the NTC \r
+//  417        if (!found) {\r
+??NTCLookUp_1:\r
+        TST     R25\r
+        BRNE    ??NTCLookUp_3\r
+//  418                BattData.Temperature = 80;\r
+        LDI     R16, 80\r
+        STS     (BattData + 2), R16\r
+//  419        }\r
+//  420 }\r
+??NTCLookUp_3:\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        RSEG NEAR_ID:CODE:NOROOT(0)\r
+`?<Initializer for RID>`:\r
+        DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14\r
+        DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475\r
+        DW 420, 38\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_I>`:\r
+        DW      SFE(NEAR_I) - SFB(NEAR_I)\r
+        DW      SFB(NEAR_I)\r
+        DW      SFB(NEAR_ID)\r
+        REQUIRE ?need_segment_init\r
+\r
+        RSEG NEAR_ID:CODE:NOROOT(0)\r
+`?<Initializer for NTC>`:\r
+        DW 1002\r
+        DB 23\r
+        DW 953\r
+        DB 25\r
+        DW 902\r
+        DB 26\r
+        DW 849\r
+        DB 27\r
+        DW 796\r
+        DB 27\r
+        DW 742\r
+        DB 27\r
+        DW 689\r
+        DB 26\r
+        DW 637\r
+        DB 26\r
+        DW 587\r
+        DB 25\r
+        DW 539\r
+        DB 24\r
+        DW 494\r
+        DB 22\r
+        DW 451\r
+        DB 21\r
+        DW 412\r
+        DB 19\r
+        DW 375\r
+        DB 18\r
+        DW 341\r
+        DB 17\r
+        DW 310\r
+        DB 15\r
+        DW 282\r
+        DB 14\r
+        DW 256\r
+        DB 13\r
+        DW 233\r
+        DB 11\r
+        DW 212\r
+        DB 10\r
+\r
+        END\r
+// \r
+//     2 bytes in segment ABSOLUTE\r
+// 1 064 bytes in segment CODE\r
+//   130 bytes in segment EEPROM_I\r
+//    12 bytes in segment INITTAB\r
+//   116 bytes in segment NEAR_I\r
+//   116 bytes in segment NEAR_ID\r
+//    13 bytes in segment NEAR_Z\r
+// \r
+// 1 180 bytes of CODE  memory (+ 12 bytes shared)\r
+//   129 bytes of DATA  memory (+  2 bytes shared)\r
+//   130 bytes of XDATA memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/chargefunc.lst b/BaseTinyFirmware/IAR/Debug/List/chargefunc.lst
new file mode 100644 (file)
index 0000000..b649880
--- /dev/null
@@ -0,0 +1,907 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:39 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c         #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c         #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\chargefun #\r
+#                    c.lst                                                    #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\chargefunc #\r
+#                    .r90                                                     #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Charge functions\r
+      6           *\r
+      7           *      Contains the functions for charging with constant current and voltage,\r
+      8           *      and for deciding when to halt.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13           *\r
+     14           * \par Documentation\r
+     15           *      For comprehensive code documentation, supported compilers, compiler \r
+     16           *      settings and supported devices see readme.html\r
+     17           *\r
+     18           * \author\r
+     19           *      Atmel Corporation: http://www.atmel.com \n\r
+     20           *      Support email: avr@atmel.com\r
+     21           *\r
+     22           * \r
+     23           * $Name$\r
+     24           * $Revision: 2299 $\r
+     25           * $RCSfile$\r
+     26           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $\r
+     27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     28           ******************************************************************************/\r
+     29          \r
+     30          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4c\r
+   \   <unnamed> volatile __io _A_OCR1B\r
+   \                     _A_OCR1B:\r
+   \   00000000                      DS 1\r
+     31          \r
+     32          #include "enums.h"\r
+     33          #include "structs.h"\r
+     34          \r
+     35          #include "ADC.h"\r
+     36          #include "battery.h"\r
+     37          #include "chargefunc.h"\r
+     38          #include "main.h"\r
+     39          #include "menu.h"\r
+     40          #include "PWM.h"\r
+     41          #include "statefunc.h"\r
+     42          #include "time.h"\r
+     43          \r
+     44          #ifdef NIMH\r
+     45          #include "NIMHspecs.h"\r
+     46          #endif // NIMH\r
+     47          \r
+     48          #ifdef LIION\r
+     49          #include "LIIONspecs.h"\r
+     50          #endif // LIION\r
+     51          \r
+     52          \r
+     53          //******************************************************************************\r
+     54          // Variables\r
+     55          //******************************************************************************\r
+     56          //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     57          ChargeParameters_t ChargeParameters;\r
+   \                     ChargeParameters:\r
+   \   00000000                      DS 5\r
+     58          \r
+     59          //! Struct that holds parameters for HaltNow().\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     60          HaltParameters_t HaltParameters;\r
+   \                     HaltParameters:\r
+   \   00000000                      DS 17\r
+     61          \r
+     62          \r
+     63          //******************************************************************************\r
+     64          // Functions\r
+     65          //******************************************************************************\r
+     66          /*! \brief Charges battery with a constant current.\r
+     67           *\r
+     68           * This function applies a constant current (set in ChargeParameters.Current)\r
+     69           * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+     70           * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+     71           * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n\r
+     72           * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+     73           * Once the battery is no longer flagged for charge inhibit, timers are\r
+     74           * started again and charging resumed.\r
+     75           *\r
+     76           * \retval ChargeParameters.NextState Next state once this stage is done.\r
+     77           * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+     78           * HaltNow() will have set a new next state.\r
+     79           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     80          unsigned char ConstantCurrent(void)\r
+   \                     ConstantCurrent:\r
+     81          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+     82                unsigned char error = FALSE,\r
+   \   00000002   E080               LDI     R24, 0\r
+     83                              wasStopped = FALSE;\r
+   \   00000004   E090               LDI     R25, 0\r
+     84                \r
+     85                do      {\r
+     86                // Wait for ADC conversions to complete.\r
+     87                        ADC_Wait();\r
+   \                     ??ConstantCurrent_0:\r
+   \   00000006   ....               RCALL   ADC_Wait\r
+     88          \r
+     89                        // If Master has flagged for a charge inhibit, pause charging.\r
+     90                        // (This is to prevent damage during prolonged serial communication.)\r
+     91                        if (BattControl[BattActive].ChargeInhibit) {\r
+   \   00000008   9100....           LDS     R16, BattActive\r
+   \   0000000C   E010               LDI     R17, 0\r
+   \   0000000E   ....               LDI     R20, LOW(BattControl)\r
+   \   00000010   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000012   0F40               ADD     R20, R16\r
+   \   00000014   1F51               ADC     R21, R17\r
+   \   00000016   ....               RCALL   __eeget8_16\r
+   \   00000018   7004               ANDI    R16, 0x04\r
+   \   0000001A   2300               TST     R16\r
+   \   0000001C   F029               BREQ    ??ConstantCurrent_1\r
+     92                                wasStopped = TRUE;\r
+   \   0000001E   E091               LDI     R25, 1\r
+     93                                Time_Stop();\r
+   \   00000020   ....               RCALL   Time_Stop\r
+     94                                OCR1B = 0;\r
+   \   00000022   E000               LDI     R16, 0\r
+   \   00000024   BD0C               OUT     0x2C, R16\r
+   \   00000026   C03C               RJMP    ??ConstantCurrent_2\r
+     95                        } else {\r
+     96                                // Continue charging!\r
+     97                                if (wasStopped) {\r
+   \                     ??ConstantCurrent_1:\r
+   \   00000028   2399               TST     R25\r
+   \   0000002A   F011               BREQ    ??ConstantCurrent_3\r
+     98                                        wasStopped = FALSE;\r
+   \   0000002C   E090               LDI     R25, 0\r
+     99                                        \r
+    100                                        // Timer variables are not reset by this.\r
+    101                                        Time_Start();\r
+   \   0000002E   ....               RCALL   Time_Start\r
+    102                                }\r
+    103                   \r
+    104                                // Adjust the charge current to within ChargeParameters.Current\r
+    105                                // +/- BAT_CURRENT_HYST.\r
+    106                                if ((ADCS.avgIBAT < 0) ||\r
+    107                                    (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+   \                     ??ConstantCurrent_3:\r
+   \   00000030   ....               LDI     R30, LOW(ADCS)\r
+   \   00000032   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000034   8906               LDD     R16, Z+22\r
+   \   00000036   8917               LDD     R17, Z+23\r
+   \   00000038   2311               TST     R17\r
+   \   0000003A   F06A               BRMI    ??ConstantCurrent_4\r
+   \   0000003C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000003E   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000040   8926               LDD     R18, Z+22\r
+   \   00000042   8937               LDD     R19, Z+23\r
+   \   00000044   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   00000046   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   00000048   8102               LDD     R16, Z+2\r
+   \   0000004A   8113               LDD     R17, Z+3\r
+   \   0000004C   5003               SUBI    R16, 3\r
+   \   0000004E   4010               SBCI    R17, 0\r
+   \   00000050   1720               CP      R18, R16\r
+   \   00000052   0731               CPC     R19, R17\r
+   \   00000054   F450               BRCC    ??ConstantCurrent_5\r
+    108                                                 \r
+    109                                        if(!PWM_IncrementDutyCycle()) {\r
+   \                     ??ConstantCurrent_4:\r
+   \   00000056   ....               RCALL   PWM_IncrementDutyCycle\r
+   \   00000058   2300               TST     R16\r
+   \   0000005A   F511               BRNE    ??ConstantCurrent_2\r
+    110          #ifdef ABORT_IF_PWM_MAX\r
+    111                                        // If the duty cycle cannot be incremented, flag error and\r
+    112                                        // go to error state.\r
+    113                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+   \   0000005C   E004               LDI     R16, 4\r
+   \   0000005E   ....               RCALL   SetErrorFlag\r
+    114                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   00000060   E50A               LDI     R16, 90\r
+   \   00000062   9300....           STS     (ChargeParameters + 4), R16\r
+    115                                                error = TRUE;\r
+   \   00000066   E081               LDI     R24, 1\r
+   \   00000068   C01B               RJMP    ??ConstantCurrent_2\r
+    116          #endif\r
+    117                                        }\r
+    118                                } else if ((ADCS.avgIBAT >= 0) &&\r
+    119                                         (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+   \                     ??ConstantCurrent_5:\r
+   \   0000006A   ....               LDI     R30, LOW(ADCS)\r
+   \   0000006C   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000006E   8906               LDD     R16, Z+22\r
+   \   00000070   8917               LDD     R17, Z+23\r
+   \   00000072   2311               TST     R17\r
+   \   00000074   F0AA               BRMI    ??ConstantCurrent_2\r
+   \   00000076   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   00000078   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   0000007A   81A2               LDD     R26, Z+2\r
+   \   0000007C   81B3               LDD     R27, Z+3\r
+   \   0000007E   9613               ADIW    R27:R26, 3\r
+   \   00000080   ....               LDI     R30, LOW(ADCS)\r
+   \   00000082   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000084   8906               LDD     R16, Z+22\r
+   \   00000086   8917               LDD     R17, Z+23\r
+   \   00000088   17A0               CP      R26, R16\r
+   \   0000008A   07B1               CPC     R27, R17\r
+   \   0000008C   F448               BRCC    ??ConstantCurrent_2\r
+    120                                                 \r
+    121                                        if(!PWM_DecrementDutyCycle()) {\r
+   \   0000008E   ....               RCALL   PWM_DecrementDutyCycle\r
+   \   00000090   2300               TST     R16\r
+   \   00000092   F431               BRNE    ??ConstantCurrent_2\r
+    122          #ifdef ABORT_IF_PWM_MIN\r
+    123                                                // If the duty cycle cannot be decremented, flag error and\r
+    124                                                // go to error state.\r
+    125                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+   \   00000094   E004               LDI     R16, 4\r
+   \   00000096   ....               RCALL   SetErrorFlag\r
+    126                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   00000098   E50A               LDI     R16, 90\r
+   \   0000009A   9300....           STS     (ChargeParameters + 4), R16\r
+    127                                                error = TRUE;\r
+   \   0000009E   E081               LDI     R24, 1\r
+    128          #endif\r
+    129                                        }\r
+    130                                }\r
+    131                        }\r
+    132                } while (!HaltNow() && !error);\r
+   \                     ??ConstantCurrent_2:\r
+   \   000000A0   ....               RCALL   HaltNow\r
+   \   000000A2   2300               TST     R16\r
+   \   000000A4   F419               BRNE    ??ConstantCurrent_6\r
+   \   000000A6   2388               TST     R24\r
+   \   000000A8   F409               BRNE    $+2+2\r
+   \   000000AA   CFAD               RJMP    ??ConstantCurrent_0\r
+    133          \r
+    134                // Return the next state to Charge(). If an error has occured, this will\r
+    135                // point to some other state than the next state of charging.\r
+    136                return(ChargeParameters.NextState);\r
+   \                     ??ConstantCurrent_6:\r
+   \   000000AC   9100....           LDS     R16, (ChargeParameters + 4)\r
+   \   000000B0   E0E4               LDI     R30, 4\r
+   \   000000B2   ....               RJMP    ?EPILOGUE_B4_L09\r
+   \   000000B4                      REQUIRE _A_OCR1B\r
+    137          }\r
+    138          \r
+    139          \r
+    140          /*! \brief Charges battery with a constant voltage\r
+    141           *\r
+    142           * This function applies a constant voltage (set in ChargeParameters.Voltage)\r
+    143           * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+    144           * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+    145           * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n\r
+    146           * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+    147           * Once the battery is no longer flagged for charge inhibit, timers are\r
+    148           * started again and charging resumed.\r
+    149           *\r
+    150           * \retval ChargeParameters.NextState Next state once this stage is done.\r
+    151           * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+    152           * HaltNow() will have set a new next state.\r
+    153           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    154          unsigned char ConstantVoltage(void)\r
+   \                     ConstantVoltage:\r
+    155          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+    156                unsigned char error = FALSE,\r
+   \   00000002   E080               LDI     R24, 0\r
+    157                              wasStopped = FALSE;\r
+   \   00000004   E090               LDI     R25, 0\r
+    158                \r
+    159                do{\r
+    160                        \r
+    161                        // Wait for ADC conversions to complete.\r
+    162                        ADC_Wait();\r
+   \                     ??ConstantVoltage_0:\r
+   \   00000006   ....               RCALL   ADC_Wait\r
+    163                        \r
+    164                        // If Master has flagged for a charge inhibit, pause charging.\r
+    165                        // (This is to prevent damage during prolonged serial communication.)\r
+    166                        if (BattControl[BattActive].ChargeInhibit) {\r
+   \   00000008   9100....           LDS     R16, BattActive\r
+   \   0000000C   E010               LDI     R17, 0\r
+   \   0000000E   ....               LDI     R20, LOW(BattControl)\r
+   \   00000010   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000012   0F40               ADD     R20, R16\r
+   \   00000014   1F51               ADC     R21, R17\r
+   \   00000016   ....               RCALL   __eeget8_16\r
+   \   00000018   7004               ANDI    R16, 0x04\r
+   \   0000001A   2300               TST     R16\r
+   \   0000001C   F029               BREQ    ??ConstantVoltage_1\r
+    167                                wasStopped = TRUE;\r
+   \   0000001E   E091               LDI     R25, 1\r
+    168                                Time_Stop();\r
+   \   00000020   ....               RCALL   Time_Stop\r
+    169                                OCR1B = 0;\r
+   \   00000022   E000               LDI     R16, 0\r
+   \   00000024   BD0C               OUT     0x2C, R16\r
+   \   00000026   C030               RJMP    ??ConstantVoltage_2\r
+    170                        }\r
+    171                        \r
+    172                        else {\r
+    173                                // Continue charging!\r
+    174                                if (wasStopped) {\r
+   \                     ??ConstantVoltage_1:\r
+   \   00000028   2399               TST     R25\r
+   \   0000002A   F011               BREQ    ??ConstantVoltage_3\r
+    175                                        wasStopped = FALSE;\r
+   \   0000002C   E090               LDI     R25, 0\r
+    176                                        \r
+    177                                        // Timer variables aren't reset by this.\r
+    178                                        Time_Start();\r
+   \   0000002E   ....               RCALL   Time_Start\r
+    179                                }\r
+    180                                \r
+    181                                // Adjust the charge voltage to within ChargeParameters.Voltage\r
+    182                                // +/- BAT_VOLTAGE_HYST.\r
+    183                                if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+   \                     ??ConstantVoltage_3:\r
+   \   00000030   ....               LDI     R30, LOW(ADCS)\r
+   \   00000032   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000034   8522               LDD     R18, Z+10\r
+   \   00000036   8533               LDD     R19, Z+11\r
+   \   00000038   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   0000003A   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   0000003C   8100               LD      R16, Z\r
+   \   0000003E   8111               LDD     R17, Z+1\r
+   \   00000040   500A               SUBI    R16, 10\r
+   \   00000042   4010               SBCI    R17, 0\r
+   \   00000044   1720               CP      R18, R16\r
+   \   00000046   0731               CPC     R19, R17\r
+   \   00000048   F450               BRCC    ??ConstantVoltage_4\r
+    184          \r
+    185                                        if(!PWM_IncrementDutyCycle()) {\r
+   \   0000004A   ....               RCALL   PWM_IncrementDutyCycle\r
+   \   0000004C   2300               TST     R16\r
+   \   0000004E   F4E1               BRNE    ??ConstantVoltage_2\r
+    186          #ifdef ABORT_IF_PWM_MAX\r
+    187                                        // Flag PWM control error and go to error-state if the duty\r
+    188                                        // cycle cannot be incremented.\r
+    189                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+   \   00000050   E004               LDI     R16, 4\r
+   \   00000052   ....               RCALL   SetErrorFlag\r
+    190                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   00000054   E50A               LDI     R16, 90\r
+   \   00000056   9300....           STS     (ChargeParameters + 4), R16\r
+    191                                                error = TRUE;\r
+   \   0000005A   E081               LDI     R24, 1\r
+   \   0000005C   C015               RJMP    ??ConstantVoltage_2\r
+    192          #endif\r
+    193                                        }\r
+    194                                } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+   \                     ??ConstantVoltage_4:\r
+   \   0000005E   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   00000060   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   00000062   81A0               LD      R26, Z\r
+   \   00000064   81B1               LDD     R27, Z+1\r
+   \   00000066   961A               ADIW    R27:R26, 10\r
+   \   00000068   ....               LDI     R30, LOW(ADCS)\r
+   \   0000006A   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000006C   8502               LDD     R16, Z+10\r
+   \   0000006E   8513               LDD     R17, Z+11\r
+   \   00000070   17A0               CP      R26, R16\r
+   \   00000072   07B1               CPC     R27, R17\r
+   \   00000074   F448               BRCC    ??ConstantVoltage_2\r
+    195          \r
+    196                                        if(!PWM_DecrementDutyCycle()) {\r
+   \   00000076   ....               RCALL   PWM_DecrementDutyCycle\r
+   \   00000078   2300               TST     R16\r
+   \   0000007A   F431               BRNE    ??ConstantVoltage_2\r
+    197          #ifdef ABORT_IF_PWM_MIN\r
+    198                                                // Flag PWM control error and go to error-state if duty\r
+    199                                                // cycle cannot be decremented.\r
+    200                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+   \   0000007C   E004               LDI     R16, 4\r
+   \   0000007E   ....               RCALL   SetErrorFlag\r
+    201                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   00000080   E50A               LDI     R16, 90\r
+   \   00000082   9300....           STS     (ChargeParameters + 4), R16\r
+    202                                                error = TRUE;\r
+   \   00000086   E081               LDI     R24, 1\r
+    203          #endif\r
+    204                                        }\r
+    205                                }\r
+    206                        }\r
+    207          \r
+    208                } while (!HaltNow() && !error);\r
+   \                     ??ConstantVoltage_2:\r
+   \   00000088   ....               RCALL   HaltNow\r
+   \   0000008A   2300               TST     R16\r
+   \   0000008C   F419               BRNE    ??ConstantVoltage_5\r
+   \   0000008E   2388               TST     R24\r
+   \   00000090   F409               BRNE    $+2+2\r
+   \   00000092   CFB9               RJMP    ??ConstantVoltage_0\r
+    209          \r
+    210                // Return the next state to Charge(). If an error has occured, this will\r
+    211                // point to some other state than the next state of charging.\r
+    212                return(ChargeParameters.NextState);\r
+   \                     ??ConstantVoltage_5:\r
+   \   00000094   9100....           LDS     R16, (ChargeParameters + 4)\r
+   \   00000098   E0E4               LDI     R30, 4\r
+   \   0000009A   ....               RJMP    ?EPILOGUE_B4_L09\r
+   \   0000009C                      REQUIRE _A_OCR1B\r
+    213          }\r
+    214          \r
+    215          \r
+    216          /*! \brief Determines when to halt charging.\r
+    217           *\r
+    218           * This function evaluates parameters depending on what has been flagged in\r
+    219           * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should\r
+    220           * halt or not.\n\r
+    221           * In addition, error flagging on timeout (battery exhaustion) can be set.\n\r
+    222           *\r
+    223           * The function also checks if the battery temperature is within limits,\r
+    224           * if mains is OK, and if BatteryCheck() returns TRUE.\r
+    225           * If an error is detected, the associated errorflag is set and \r
+    226           * ChargeParameters.NextState is changed to an appropriate state.\r
+    227           *\r
+    228           * \retval TRUE Halt now.\r
+    229           * \retval FALSE Don't halt now.\r
+    230           *\r
+    231           * \note See chargefunc.h for definitions of halt flags.\r
+    232           * \note It is generally a bad idea not to halt on a timeout.\r
+    233           * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be\r
+    234           * reset in Charge() before calling a charging-function.\r
+    235           *\r
+    236           * \todo "Priorities" of standard error checks OK?\r
+    237           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    238          unsigned char HaltNow(void)\r
+   \                     HaltNow:\r
+    239          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+    240                unsigned char i, halt = FALSE;\r
+   \   00000002   E080               LDI     R24, 0\r
+    241                \r
+    242                // Wait for a full ADC-cycle to finish.\r
+    243                ADC_Wait();\r
+   \   00000004   ....               RCALL   ADC_Wait\r
+    244          \r
+    245                // Evaluate ADC readings according to HaltFlags. Flag errors if selected.\r
+    246                // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.\r
+    247                // (Gets overridden if either mains is failing, or the battery changes.)\r
+    248                for (i = 0x01; i != 0; i <<= 1) {\r
+   \   00000006   E091               LDI     R25, 1\r
+   \                     ??HaltNow_0:\r
+   \   00000008   2399               TST     R25\r
+   \   0000000A   F409               BRNE    $+2+2\r
+   \   0000000C   C0C4               RJMP    ??HaltNow_1\r
+    249                        if (HaltParameters.HaltFlags & i) {\r
+   \   0000000E   9100....           LDS     R16, HaltParameters\r
+   \   00000012   2309               AND     R16, R25\r
+   \   00000014   2300               TST     R16\r
+   \   00000016   F409               BRNE    $+2+2\r
+   \   00000018   C0BC               RJMP    ??HaltNow_2\r
+    250                                switch (i) {\r
+   \   0000001A   2F09               MOV     R16, R25\r
+   \   0000001C   5001               SUBI    R16, 1\r
+   \   0000001E   F059               BREQ    ??HaltNow_3\r
+   \   00000020   950A               DEC     R16\r
+   \   00000022   F189               BREQ    ??HaltNow_4\r
+   \   00000024   5002               SUBI    R16, 2\r
+   \   00000026   F1E9               BREQ    ??HaltNow_5\r
+   \   00000028   5004               SUBI    R16, 4\r
+   \   0000002A   F409               BRNE    $+2+2\r
+   \   0000002C   C048               RJMP    ??HaltNow_6\r
+   \   0000002E   5008               SUBI    R16, 8\r
+   \   00000030   F409               BRNE    $+2+2\r
+   \   00000032   C089               RJMP    ??HaltNow_7\r
+   \   00000034   C0AE               RJMP    ??HaltNow_2\r
+    251                                // Is VBAT less than the recorded maximum?\r
+    252                                case HALT_VOLTAGE_DROP:\r
+    253          \r
+    254                                        // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
+    255                                        if (ADCS.VBAT > HaltParameters.VBATMax) {\r
+   \                     ??HaltNow_3:\r
+   \   00000036   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000038   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   0000003A   8505               LDD     R16, Z+13\r
+   \   0000003C   8516               LDD     R17, Z+14\r
+   \   0000003E   ....               LDI     R30, LOW(ADCS)\r
+   \   00000040   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000042   8522               LDD     R18, Z+10\r
+   \   00000044   8533               LDD     R19, Z+11\r
+   \   00000046   1702               CP      R16, R18\r
+   \   00000048   0713               CPC     R17, R19\r
+   \   0000004A   F448               BRCC    ??HaltNow_8\r
+    256                                                HaltParameters.VBATMax = ADCS.VBAT;\r
+   \   0000004C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000004E   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000050   8502               LDD     R16, Z+10\r
+   \   00000052   8513               LDD     R17, Z+11\r
+   \   00000054   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000056   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000058   8705               STD     Z+13, R16\r
+   \   0000005A   8716               STD     Z+14, R17\r
+   \   0000005C   C09A               RJMP    ??HaltNow_2\r
+    257                                        } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+    258                                                  HaltParameters.VoltageDrop) {\r
+   \                     ??HaltNow_8:\r
+   \   0000005E   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000060   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000062   8505               LDD     R16, Z+13\r
+   \   00000064   8516               LDD     R17, Z+14\r
+   \   00000066   ....               LDI     R30, LOW(ADCS)\r
+   \   00000068   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000006A   8522               LDD     R18, Z+10\r
+   \   0000006C   8533               LDD     R19, Z+11\r
+   \   0000006E   1B02               SUB     R16, R18\r
+   \   00000070   0B13               SBC     R17, R19\r
+   \   00000072   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000074   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000076   8121               LDD     R18, Z+1\r
+   \   00000078   8132               LDD     R19, Z+2\r
+   \   0000007A   1702               CP      R16, R18\r
+   \   0000007C   0713               CPC     R17, R19\r
+   \   0000007E   F408               BRCC    $+2+2\r
+   \   00000080   C088               RJMP    ??HaltNow_2\r
+    259                                                halt = TRUE;\r
+   \   00000082   E081               LDI     R24, 1\r
+   \   00000084   C086               RJMP    ??HaltNow_2\r
+    260                                        }\r
+    261                                break;\r
+    262          \r
+    263                                \r
+    264                                // Has VBAT reached the maximum limit?\r
+    265                                case HALT_VOLTAGE_MAX:  \r
+    266                                        \r
+    267                                        if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+   \                     ??HaltNow_4:\r
+   \   00000086   ....               LDI     R30, LOW(ADCS)\r
+   \   00000088   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000008A   8502               LDD     R16, Z+10\r
+   \   0000008C   8513               LDD     R17, Z+11\r
+   \   0000008E   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000090   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000092   8123               LDD     R18, Z+3\r
+   \   00000094   8134               LDD     R19, Z+4\r
+   \   00000096   1702               CP      R16, R18\r
+   \   00000098   0713               CPC     R17, R19\r
+   \   0000009A   F408               BRCC    $+2+2\r
+   \   0000009C   C07A               RJMP    ??HaltNow_2\r
+    268                                                halt = TRUE;\r
+   \   0000009E   E081               LDI     R24, 1\r
+   \   000000A0   C078               RJMP    ??HaltNow_2\r
+    269                                        }\r
+    270                                        break;\r
+    271          \r
+    272          \r
+    273                                // Has IBAT reached the minimum limit?\r
+    274                                case HALT_CURRENT_MIN:\r
+    275                                        \r
+    276                                        if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+   \                     ??HaltNow_5:\r
+   \   000000A2   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000A4   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000A6   8105               LDD     R16, Z+5\r
+   \   000000A8   8116               LDD     R17, Z+6\r
+   \   000000AA   ....               LDI     R30, LOW(ADCS)\r
+   \   000000AC   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000AE   8926               LDD     R18, Z+22\r
+   \   000000B0   8937               LDD     R19, Z+23\r
+   \   000000B2   1702               CP      R16, R18\r
+   \   000000B4   0713               CPC     R17, R19\r
+   \   000000B6   F408               BRCC    $+2+2\r
+   \   000000B8   C06C               RJMP    ??HaltNow_2\r
+    277                                                halt = TRUE;\r
+   \   000000BA   E081               LDI     R24, 1\r
+   \   000000BC   C06A               RJMP    ??HaltNow_2\r
+    278                                        }\r
+    279                                        break;\r
+    280                \r
+    281                                        \r
+    282                                // Is the temperature rising too fast?\r
+    283                                case HALT_TEMPERATURE_RISE:\r
+    284          \r
+    285                                        // If rawNTC has increased, the temperature has dropped.\r
+    286                                        // We can store this value for now, and start the timer.\r
+    287                                        // Otherwise, check if NTC has changed too fast.\r
+    288                                        if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
+   \                     ??HaltNow_6:\r
+   \   000000BE   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000C0   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000C2   8507               LDD     R16, Z+15\r
+   \   000000C4   8910               LDD     R17, Z+16\r
+   \   000000C6   ....               LDI     R30, LOW(ADCS)\r
+   \   000000C8   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000CA   8124               LDD     R18, Z+4\r
+   \   000000CC   8135               LDD     R19, Z+5\r
+   \   000000CE   1702               CP      R16, R18\r
+   \   000000D0   0713               CPC     R17, R19\r
+   \   000000D2   F478               BRCC    ??HaltNow_9\r
+    289                                                HaltParameters.LastNTC = ADCS.rawNTC;\r
+   \   000000D4   ....               LDI     R30, LOW(ADCS)\r
+   \   000000D6   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000D8   8104               LDD     R16, Z+4\r
+   \   000000DA   8115               LDD     R17, Z+5\r
+   \   000000DC   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000DE   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000E0   8707               STD     Z+15, R16\r
+   \   000000E2   8B10               STD     Z+16, R17\r
+    290                                                Time_Set(TIMER_TEMP,0,30,0);\r
+   \   000000E4   E040               LDI     R20, 0\r
+   \   000000E6   E11E               LDI     R17, 30\r
+   \   000000E8   E020               LDI     R18, 0\r
+   \   000000EA   E030               LDI     R19, 0\r
+   \   000000EC   E003               LDI     R16, 3\r
+   \   000000EE   ....               RCALL   Time_Set\r
+   \   000000F0   C050               RJMP    ??HaltNow_2\r
+    291                                                \r
+    292                                        // Is the increase in temperature greater than the set threshold?\r
+    293                                        } else  if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+    294                                          (BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
+   \                     ??HaltNow_9:\r
+   \   000000F2   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000000F4   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000000F6   85A7               LDD     R26, Z+15\r
+   \   000000F8   89B0               LDD     R27, Z+16\r
+   \   000000FA   ....               LDI     R30, LOW(ADCS)\r
+   \   000000FC   ....               LDI     R31, (ADCS) >> 8\r
+   \   000000FE   8104               LDD     R16, Z+4\r
+   \   00000100   8115               LDD     R17, Z+5\r
+   \   00000102   1BA0               SUB     R26, R16\r
+   \   00000104   0BB1               SBC     R27, R17\r
+   \   00000106   9140....           LDS     R20, (BattData + 3)\r
+   \   0000010A   E050               LDI     R21, 0\r
+   \   0000010C   ....               LDI     R30, LOW(HaltParameters)\r
+   \   0000010E   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000110   8503               LDD     R16, Z+11\r
+   \   00000112   8514               LDD     R17, Z+12\r
+   \   00000114   ....               RCALL   ?S_MUL_L02\r
+   \   00000116   17A0               CP      R26, R16\r
+   \   00000118   07B1               CPC     R27, R17\r
+   \   0000011A   F1D8               BRCS    ??HaltNow_2\r
+    295                                                \r
+    296                                                // If this happened within a timeframe of 30 seconds, the \r
+    297                                                // temperature is rising faster than we want.\r
+    298                                                // If not, update LastNTC and reset timer.\r
+    299                                                if (Time_Left(TIMER_TEMP))  {\r
+   \   0000011C   E003               LDI     R16, 3\r
+   \   0000011E   ....               RCALL   Time_Left\r
+   \   00000120   2300               TST     R16\r
+   \   00000122   F011               BREQ    ??HaltNow_10\r
+    300                                                        halt = TRUE;\r
+   \   00000124   E081               LDI     R24, 1\r
+   \   00000126   C035               RJMP    ??HaltNow_2\r
+    301                                                } else {\r
+    302                                                        HaltParameters.LastNTC = ADCS.rawNTC;\r
+   \                     ??HaltNow_10:\r
+   \   00000128   ....               LDI     R30, LOW(ADCS)\r
+   \   0000012A   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000012C   8104               LDD     R16, Z+4\r
+   \   0000012E   8115               LDD     R17, Z+5\r
+   \   00000130   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000132   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000134   8707               STD     Z+15, R16\r
+   \   00000136   8B10               STD     Z+16, R17\r
+    303                                                        Time_Set(TIMER_TEMP,0,30,0);\r
+   \   00000138   E040               LDI     R20, 0\r
+   \   0000013A   E11E               LDI     R17, 30\r
+   \   0000013C   E020               LDI     R18, 0\r
+   \   0000013E   E030               LDI     R19, 0\r
+   \   00000140   E003               LDI     R16, 3\r
+   \   00000142   ....               RCALL   Time_Set\r
+   \   00000144   C026               RJMP    ??HaltNow_2\r
+    304                                                }\r
+    305                                        }\r
+    306                                break;\r
+    307                \r
+    308                                \r
+    309                                // Is there any time left?\r
+    310                                case HALT_TIME:  \r
+    311                                        \r
+    312                                        if (!Time_Left(TIMER_CHG)) {\r
+   \                     ??HaltNow_7:\r
+   \   00000146   E001               LDI     R16, 1\r
+   \   00000148   ....               RCALL   Time_Left\r
+   \   0000014A   2300               TST     R16\r
+   \   0000014C   F511               BRNE    ??HaltNow_2\r
+    313                                                halt = TRUE;\r
+   \   0000014E   E081               LDI     R24, 1\r
+    314                                                \r
+    315                                                // If exhaustion flagging is selected, stop the PWM, disable the \r
+    316                                                // battery and flag it as exhausted. Make ST_ERROR next state.\r
+    317                                                if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
+   \   00000150   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000152   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000154   8100               LD      R16, Z\r
+   \   00000156   FF05               SBRS    R16, 5\r
+   \   00000158   C01C               RJMP    ??HaltNow_2\r
+    318                                                                PWM_Stop();\r
+   \   0000015A   ....               RCALL   PWM_Stop\r
+    319                                                                BattControl[BattActive].Enabled = FALSE;\r
+   \   0000015C   9100....           LDS     R16, BattActive\r
+   \   00000160   E010               LDI     R17, 0\r
+   \   00000162   ....               LDI     R20, LOW(BattControl)\r
+   \   00000164   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000166   0F40               ADD     R20, R16\r
+   \   00000168   1F51               ADC     R21, R17\r
+   \   0000016A   ....               RCALL   __eeget8_16\r
+   \   0000016C   7F0E               ANDI    R16, 0xFE\r
+   \   0000016E   9120....           LDS     R18, BattActive\r
+   \   00000172   E030               LDI     R19, 0\r
+   \   00000174   ....               LDI     R20, LOW(BattControl)\r
+   \   00000176   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000178   0F42               ADD     R20, R18\r
+   \   0000017A   1F53               ADC     R21, R19\r
+   \   0000017C   ....               RCALL   __eeput8_16\r
+    320                                                                BattData.Exhausted = TRUE;\r
+   \   0000017E   ....               LDI     R30, LOW(BattData)\r
+   \   00000180   ....               LDI     R31, (BattData) >> 8\r
+   \   00000182   8100               LD      R16, Z\r
+   \   00000184   6008               ORI     R16, 0x08\r
+   \   00000186   8300               ST      Z, R16\r
+    321                                                                SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
+   \   00000188   E100               LDI     R16, 16\r
+   \   0000018A   ....               RCALL   SetErrorFlag\r
+    322                                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   0000018C   E50A               LDI     R16, 90\r
+   \   0000018E   9300....           STS     (ChargeParameters + 4), R16\r
+    323                                                }\r
+    324                                        }\r
+    325                                break;\r
+    326                                \r
+    327                                \r
+    328                                default:  // Shouldn't end up here, but is needed for MISRA compliance.\r
+    329                                break;\r
+    330                                }\r
+    331                        }\r
+    332                }\r
+   \                     ??HaltNow_2:\r
+   \   00000192   0F99               LSL     R25\r
+   \   00000194   CF39               RJMP    ??HaltNow_0\r
+    333          \r
+    334                // Standard checks:\r
+    335          \r
+    336                // Battery too cold or hot?\r
+    337                if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||\r
+    338                    (BattData.Temperature >= HaltParameters.TemperatureMax)) {\r
+   \                     ??HaltNow_1:\r
+   \   00000196   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000198   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   0000019A   8521               LDD     R18, Z+9\r
+   \   0000019C   8532               LDD     R19, Z+10\r
+   \   0000019E   9100....           LDS     R16, (BattData + 2)\r
+   \   000001A2   2F10               MOV     R17, R16\r
+   \   000001A4   0F11               LSL     R17\r
+   \   000001A6   0B11               SBC     R17, R17\r
+   \   000001A8   1720               CP      R18, R16\r
+   \   000001AA   0731               CPC     R19, R17\r
+   \   000001AC   F464               BRGE    ??HaltNow_11\r
+   \   000001AE   9100....           LDS     R16, (BattData + 2)\r
+   \   000001B2   2F10               MOV     R17, R16\r
+   \   000001B4   0F11               LSL     R17\r
+   \   000001B6   0B11               SBC     R17, R17\r
+   \   000001B8   ....               LDI     R30, LOW(HaltParameters)\r
+   \   000001BA   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   000001BC   8127               LDD     R18, Z+7\r
+   \   000001BE   8530               LDD     R19, Z+8\r
+   \   000001C0   1702               CP      R16, R18\r
+   \   000001C2   0713               CPC     R17, R19\r
+   \   000001C4   F038               BRCS    ??HaltNow_12\r
+    339                                \r
+    340                        PWM_Stop();\r
+   \                     ??HaltNow_11:\r
+   \   000001C6   ....               RCALL   PWM_Stop\r
+    341                        SetErrorFlag(ERR_BATTERY_TEMPERATURE);\r
+   \   000001C8   E008               LDI     R16, 8\r
+   \   000001CA   ....               RCALL   SetErrorFlag\r
+    342                        ChargeParameters.NextState = ST_ERROR;\r
+   \   000001CC   E50A               LDI     R16, 90\r
+   \   000001CE   9300....           STS     (ChargeParameters + 4), R16\r
+    343                        halt = TRUE;\r
+   \   000001D2   E081               LDI     R24, 1\r
+    344                }\r
+    345          \r
+    346                // Battery not OK?\r
+    347                if (!BatteryCheck()) {\r
+   \                     ??HaltNow_12:\r
+   \   000001D4   ....               RCALL   BatteryCheck\r
+   \   000001D6   2300               TST     R16\r
+   \   000001D8   F429               BRNE    ??HaltNow_13\r
+    348                        PWM_Stop();\r
+   \   000001DA   ....               RCALL   PWM_Stop\r
+    349                        ChargeParameters.NextState = ST_INIT;\r
+   \   000001DC   E00A               LDI     R16, 10\r
+   \   000001DE   9300....           STS     (ChargeParameters + 4), R16\r
+    350                        halt = TRUE;\r
+   \   000001E2   E081               LDI     R24, 1\r
+    351                }\r
+    352          \r
+    353                // Is mains voltage OK?\r
+    354                if (!ADCS.Mains) {\r
+   \                     ??HaltNow_13:\r
+   \   000001E4   ....               LDI     R30, LOW(ADCS)\r
+   \   000001E6   ....               LDI     R31, (ADCS) >> 8\r
+   \   000001E8   8100               LD      R16, Z\r
+   \   000001EA   FD06               SBRC    R16, 6\r
+   \   000001EC   C005               RJMP    ??HaltNow_14\r
+    355                        PWM_Stop();\r
+   \   000001EE   ....               RCALL   PWM_Stop\r
+    356                        ChargeParameters.NextState = ST_SLEEP;\r
+   \   000001F0   E208               LDI     R16, 40\r
+   \   000001F2   9300....           STS     (ChargeParameters + 4), R16\r
+    357                        halt = TRUE;\r
+   \   000001F6   E081               LDI     R24, 1\r
+    358                }\r
+    359          \r
+    360                return(halt);\r
+   \                     ??HaltNow_14:\r
+   \   000001F8   2F08               MOV     R16, R24\r
+   \   000001FA   E0E4               LDI     R30, 4\r
+   \   000001FC   ....               RJMP    ?EPILOGUE_B4_L09\r
+    361          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function                    CSTACK RSTACK\r
+     --------                    ------ ------\r
+     ConstantCurrent                 4      4\r
+       -> ADC_Wait                   4      2\r
+       -> Time_Stop                  4      2\r
+       -> Time_Start                 4      2\r
+       -> PWM_IncrementDutyCycle     4      2\r
+       -> SetErrorFlag               4      2\r
+       -> PWM_DecrementDutyCycle     4      2\r
+       -> SetErrorFlag               4      2\r
+       -> HaltNow                    4      2\r
+     ConstantVoltage                 4      4\r
+       -> ADC_Wait                   4      2\r
+       -> Time_Stop                  4      2\r
+       -> Time_Start                 4      2\r
+       -> PWM_IncrementDutyCycle     4      2\r
+       -> SetErrorFlag               4      2\r
+       -> PWM_DecrementDutyCycle     4      2\r
+       -> SetErrorFlag               4      2\r
+       -> HaltNow                    4      2\r
+     HaltNow                         4      4\r
+       -> ADC_Wait                   4      2\r
+       -> Time_Set                   4      2\r
+       -> Time_Left                  4      2\r
+       -> Time_Set                   4      2\r
+       -> Time_Left                  4      2\r
+       -> PWM_Stop                   4      2\r
+       -> SetErrorFlag               4      2\r
+       -> PWM_Stop                   4      2\r
+       -> SetErrorFlag               4      2\r
+       -> BatteryCheck               4      2\r
+       -> PWM_Stop                   4      2\r
+       -> PWM_Stop                   4      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label   Bytes\r
+     --------------   -----\r
+     _A_OCR1B            1\r
+     ChargeParameters    5\r
+     HaltParameters     17\r
+     ConstantCurrent   180\r
+     ConstantVoltage   156\r
+     HaltNow           510\r
+      Others             6\r
+\r
\r
+   1 byte  in segment ABSOLUTE\r
+ 846 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+  22 bytes in segment NEAR_Z\r
\r
+ 846 bytes of CODE memory (+ 6 bytes shared)\r
+  22 bytes of DATA memory (+ 1 byte  shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/chargefunc.s90 b/BaseTinyFirmware/IAR/Debug/List/chargefunc.s90
new file mode 100644 (file)
index 0000000..d189a26
--- /dev/null
@@ -0,0 +1,916 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c        /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c        /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\chargefu /\r
+//                    nc.s90                                                  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME chargefunc\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B4_L09\r
+        EXTERN ?PROLOGUE4_L09\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC ChargeParameters\r
+        PUBLIC ConstantCurrent\r
+        PUBLIC ConstantVoltage\r
+        PUBLIC HaltNow\r
+        PUBLIC HaltParameters\r
+        PUBWEAK _A_OCR1B\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN ADC_Wait\r
+        EXTERN Time_Stop\r
+        EXTERN Time_Start\r
+        EXTERN PWM_IncrementDutyCycle\r
+        EXTERN SetErrorFlag\r
+        EXTERN PWM_DecrementDutyCycle\r
+        EXTERN Time_Set\r
+        EXTERN Time_Left\r
+        EXTERN PWM_Stop\r
+        EXTERN BatteryCheck\r
+        EXTERN ADCS\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Charge functions\r
+//    6  *\r
+//    7  *      Contains the functions for charging with constant current and voltage,\r
+//    8  *      and for deciding when to halt.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13  *\r
+//   14  * \par Documentation\r
+//   15  *      For comprehensive code documentation, supported compilers, compiler \r
+//   16  *      settings and supported devices see readme.html\r
+//   17  *\r
+//   18  * \author\r
+//   19  *      Atmel Corporation: http://www.atmel.com \n\r
+//   20  *      Support email: avr@atmel.com\r
+//   21  *\r
+//   22  * \r
+//   23  * $Name$\r
+//   24  * $Revision: 2299 $\r
+//   25  * $RCSfile$\r
+//   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $\r
+//   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   28  ******************************************************************************/\r
+//   29 \r
+//   30 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
+// <unnamed> volatile __io _A_OCR1B\r
+_A_OCR1B:\r
+        DS 1\r
+//   31 \r
+//   32 #include "enums.h"\r
+//   33 #include "structs.h"\r
+//   34 \r
+//   35 #include "ADC.h"\r
+//   36 #include "battery.h"\r
+//   37 #include "chargefunc.h"\r
+//   38 #include "main.h"\r
+//   39 #include "menu.h"\r
+//   40 #include "PWM.h"\r
+//   41 #include "statefunc.h"\r
+//   42 #include "time.h"\r
+//   43 \r
+//   44 #ifdef NIMH\r
+//   45 #include "NIMHspecs.h"\r
+//   46 #endif // NIMH\r
+//   47 \r
+//   48 #ifdef LIION\r
+//   49 #include "LIIONspecs.h"\r
+//   50 #endif // LIION\r
+//   51 \r
+//   52 \r
+//   53 //******************************************************************************\r
+//   54 // Variables\r
+//   55 //******************************************************************************\r
+//   56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   57 ChargeParameters_t ChargeParameters;\r
+ChargeParameters:\r
+        DS 5\r
+//   58 \r
+//   59 //! Struct that holds parameters for HaltNow().\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   60 HaltParameters_t HaltParameters;\r
+HaltParameters:\r
+        DS 17\r
+//   61 \r
+//   62 \r
+//   63 //******************************************************************************\r
+//   64 // Functions\r
+//   65 //******************************************************************************\r
+//   66 /*! \brief Charges battery with a constant current.\r
+//   67  *\r
+//   68  * This function applies a constant current (set in ChargeParameters.Current)\r
+//   69  * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+//   70  * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+//   71  * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n\r
+//   72  * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+//   73  * Once the battery is no longer flagged for charge inhibit, timers are\r
+//   74  * started again and charging resumed.\r
+//   75  *\r
+//   76  * \retval ChargeParameters.NextState Next state once this stage is done.\r
+//   77  * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+//   78  * HaltNow() will have set a new next state.\r
+//   79  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   80 unsigned char ConstantCurrent(void)\r
+ConstantCurrent:\r
+//   81 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//   82        unsigned char error = FALSE,\r
+        LDI     R24, 0\r
+//   83                      wasStopped = FALSE;\r
+        LDI     R25, 0\r
+//   84        \r
+//   85        do      {\r
+//   86       // Wait for ADC conversions to complete.\r
+//   87                ADC_Wait();\r
+??ConstantCurrent_0:\r
+        RCALL   ADC_Wait\r
+//   88 \r
+//   89                // If Master has flagged for a charge inhibit, pause charging.\r
+//   90                // (This is to prevent damage during prolonged serial communication.)\r
+//   91                if (BattControl[BattActive].ChargeInhibit) {\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x04\r
+        TST     R16\r
+        BREQ    ??ConstantCurrent_1\r
+//   92                        wasStopped = TRUE;\r
+        LDI     R25, 1\r
+//   93                        Time_Stop();\r
+        RCALL   Time_Stop\r
+//   94                        OCR1B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2C, R16\r
+        RJMP    ??ConstantCurrent_2\r
+//   95                } else {\r
+//   96                        // Continue charging!\r
+//   97                        if (wasStopped) {\r
+??ConstantCurrent_1:\r
+        TST     R25\r
+        BREQ    ??ConstantCurrent_3\r
+//   98                                wasStopped = FALSE;\r
+        LDI     R25, 0\r
+//   99                                \r
+//  100                                // Timer variables are not reset by this.\r
+//  101                                Time_Start();\r
+        RCALL   Time_Start\r
+//  102                        }\r
+//  103          \r
+//  104                        // Adjust the charge current to within ChargeParameters.Current\r
+//  105                        // +/- BAT_CURRENT_HYST.\r
+//  106                        if ((ADCS.avgIBAT < 0) ||\r
+//  107                            (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+??ConstantCurrent_3:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+22\r
+        LDD     R17, Z+23\r
+        TST     R17\r
+        BRMI    ??ConstantCurrent_4\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+22\r
+        LDD     R19, Z+23\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        LDD     R16, Z+2\r
+        LDD     R17, Z+3\r
+        SUBI    R16, 3\r
+        SBCI    R17, 0\r
+        CP      R18, R16\r
+        CPC     R19, R17\r
+        BRCC    ??ConstantCurrent_5\r
+//  108                                         \r
+//  109                                if(!PWM_IncrementDutyCycle()) {\r
+??ConstantCurrent_4:\r
+        RCALL   PWM_IncrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??ConstantCurrent_2\r
+//  110 #ifdef ABORT_IF_PWM_MAX\r
+//  111                                // If the duty cycle cannot be incremented, flag error and\r
+//  112                                // go to error state.\r
+//  113                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+        LDI     R16, 4\r
+        RCALL   SetErrorFlag\r
+//  114                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (ChargeParameters + 4), R16\r
+//  115                                        error = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??ConstantCurrent_2\r
+//  116 #endif\r
+//  117                                }\r
+//  118                        } else if ((ADCS.avgIBAT >= 0) &&\r
+//  119                                 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+??ConstantCurrent_5:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+22\r
+        LDD     R17, Z+23\r
+        TST     R17\r
+        BRMI    ??ConstantCurrent_2\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        LDD     R26, Z+2\r
+        LDD     R27, Z+3\r
+        ADIW    R27:R26, 3\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+22\r
+        LDD     R17, Z+23\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BRCC    ??ConstantCurrent_2\r
+//  120                                         \r
+//  121                                if(!PWM_DecrementDutyCycle()) {\r
+        RCALL   PWM_DecrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??ConstantCurrent_2\r
+//  122 #ifdef ABORT_IF_PWM_MIN\r
+//  123                                        // If the duty cycle cannot be decremented, flag error and\r
+//  124                                        // go to error state.\r
+//  125                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+        LDI     R16, 4\r
+        RCALL   SetErrorFlag\r
+//  126                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (ChargeParameters + 4), R16\r
+//  127                                        error = TRUE;\r
+        LDI     R24, 1\r
+//  128 #endif\r
+//  129                                }\r
+//  130                        }\r
+//  131                }\r
+//  132        } while (!HaltNow() && !error);\r
+??ConstantCurrent_2:\r
+        RCALL   HaltNow\r
+        TST     R16\r
+        BRNE    ??ConstantCurrent_6\r
+        TST     R24\r
+        BRNE    $+2+2\r
+        RJMP    ??ConstantCurrent_0\r
+//  133 \r
+//  134        // Return the next state to Charge(). If an error has occured, this will\r
+//  135        // point to some other state than the next state of charging.\r
+//  136        return(ChargeParameters.NextState);\r
+??ConstantCurrent_6:\r
+        LDS     R16, (ChargeParameters + 4)\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+        REQUIRE _A_OCR1B\r
+//  137 }\r
+//  138 \r
+//  139 \r
+//  140 /*! \brief Charges battery with a constant voltage\r
+//  141  *\r
+//  142  * This function applies a constant voltage (set in ChargeParameters.Voltage)\r
+//  143  * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+//  144  * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+//  145  * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n\r
+//  146  * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+//  147  * Once the battery is no longer flagged for charge inhibit, timers are\r
+//  148  * started again and charging resumed.\r
+//  149  *\r
+//  150  * \retval ChargeParameters.NextState Next state once this stage is done.\r
+//  151  * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+//  152  * HaltNow() will have set a new next state.\r
+//  153  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  154 unsigned char ConstantVoltage(void)\r
+ConstantVoltage:\r
+//  155 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//  156        unsigned char error = FALSE,\r
+        LDI     R24, 0\r
+//  157                      wasStopped = FALSE;\r
+        LDI     R25, 0\r
+//  158        \r
+//  159        do{\r
+//  160                \r
+//  161                // Wait for ADC conversions to complete.\r
+//  162                ADC_Wait();\r
+??ConstantVoltage_0:\r
+        RCALL   ADC_Wait\r
+//  163                \r
+//  164                // If Master has flagged for a charge inhibit, pause charging.\r
+//  165                // (This is to prevent damage during prolonged serial communication.)\r
+//  166                if (BattControl[BattActive].ChargeInhibit) {\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x04\r
+        TST     R16\r
+        BREQ    ??ConstantVoltage_1\r
+//  167                        wasStopped = TRUE;\r
+        LDI     R25, 1\r
+//  168                        Time_Stop();\r
+        RCALL   Time_Stop\r
+//  169                        OCR1B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2C, R16\r
+        RJMP    ??ConstantVoltage_2\r
+//  170                }\r
+//  171                \r
+//  172                else {\r
+//  173                        // Continue charging!\r
+//  174                        if (wasStopped) {\r
+??ConstantVoltage_1:\r
+        TST     R25\r
+        BREQ    ??ConstantVoltage_3\r
+//  175                                wasStopped = FALSE;\r
+        LDI     R25, 0\r
+//  176                                \r
+//  177                                // Timer variables aren't reset by this.\r
+//  178                                Time_Start();\r
+        RCALL   Time_Start\r
+//  179                        }\r
+//  180                        \r
+//  181                        // Adjust the charge voltage to within ChargeParameters.Voltage\r
+//  182                        // +/- BAT_VOLTAGE_HYST.\r
+//  183                        if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+??ConstantVoltage_3:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+10\r
+        LDD     R19, Z+11\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        LD      R16, Z\r
+        LDD     R17, Z+1\r
+        SUBI    R16, 10\r
+        SBCI    R17, 0\r
+        CP      R18, R16\r
+        CPC     R19, R17\r
+        BRCC    ??ConstantVoltage_4\r
+//  184 \r
+//  185                                if(!PWM_IncrementDutyCycle()) {\r
+        RCALL   PWM_IncrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??ConstantVoltage_2\r
+//  186 #ifdef ABORT_IF_PWM_MAX\r
+//  187                                // Flag PWM control error and go to error-state if the duty\r
+//  188                                // cycle cannot be incremented.\r
+//  189                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+        LDI     R16, 4\r
+        RCALL   SetErrorFlag\r
+//  190                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (ChargeParameters + 4), R16\r
+//  191                                        error = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??ConstantVoltage_2\r
+//  192 #endif\r
+//  193                                }\r
+//  194                        } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+??ConstantVoltage_4:\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        LD      R26, Z\r
+        LDD     R27, Z+1\r
+        ADIW    R27:R26, 10\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BRCC    ??ConstantVoltage_2\r
+//  195 \r
+//  196                                if(!PWM_DecrementDutyCycle()) {\r
+        RCALL   PWM_DecrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??ConstantVoltage_2\r
+//  197 #ifdef ABORT_IF_PWM_MIN\r
+//  198                                        // Flag PWM control error and go to error-state if duty\r
+//  199                                        // cycle cannot be decremented.\r
+//  200                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+        LDI     R16, 4\r
+        RCALL   SetErrorFlag\r
+//  201                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (ChargeParameters + 4), R16\r
+//  202                                        error = TRUE;\r
+        LDI     R24, 1\r
+//  203 #endif\r
+//  204                                }\r
+//  205                        }\r
+//  206                }\r
+//  207 \r
+//  208        } while (!HaltNow() && !error);\r
+??ConstantVoltage_2:\r
+        RCALL   HaltNow\r
+        TST     R16\r
+        BRNE    ??ConstantVoltage_5\r
+        TST     R24\r
+        BRNE    $+2+2\r
+        RJMP    ??ConstantVoltage_0\r
+//  209 \r
+//  210        // Return the next state to Charge(). If an error has occured, this will\r
+//  211        // point to some other state than the next state of charging.\r
+//  212        return(ChargeParameters.NextState);\r
+??ConstantVoltage_5:\r
+        LDS     R16, (ChargeParameters + 4)\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+        REQUIRE _A_OCR1B\r
+//  213 }\r
+//  214 \r
+//  215 \r
+//  216 /*! \brief Determines when to halt charging.\r
+//  217  *\r
+//  218  * This function evaluates parameters depending on what has been flagged in\r
+//  219  * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should\r
+//  220  * halt or not.\n\r
+//  221  * In addition, error flagging on timeout (battery exhaustion) can be set.\n\r
+//  222  *\r
+//  223  * The function also checks if the battery temperature is within limits,\r
+//  224  * if mains is OK, and if BatteryCheck() returns TRUE.\r
+//  225  * If an error is detected, the associated errorflag is set and \r
+//  226  * ChargeParameters.NextState is changed to an appropriate state.\r
+//  227  *\r
+//  228  * \retval TRUE Halt now.\r
+//  229  * \retval FALSE Don't halt now.\r
+//  230  *\r
+//  231  * \note See chargefunc.h for definitions of halt flags.\r
+//  232  * \note It is generally a bad idea not to halt on a timeout.\r
+//  233  * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be\r
+//  234  * reset in Charge() before calling a charging-function.\r
+//  235  *\r
+//  236  * \todo "Priorities" of standard error checks OK?\r
+//  237  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  238 unsigned char HaltNow(void)\r
+HaltNow:\r
+//  239 {\r
+        RCALL   ?PROLOGUE4_L09\r
+//  240        unsigned char i, halt = FALSE;\r
+        LDI     R24, 0\r
+//  241        \r
+//  242        // Wait for a full ADC-cycle to finish.\r
+//  243        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  244 \r
+//  245        // Evaluate ADC readings according to HaltFlags. Flag errors if selected.\r
+//  246        // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.\r
+//  247        // (Gets overridden if either mains is failing, or the battery changes.)\r
+//  248        for (i = 0x01; i != 0; i <<= 1) {\r
+        LDI     R25, 1\r
+??HaltNow_0:\r
+        TST     R25\r
+        BRNE    $+2+2\r
+        RJMP    ??HaltNow_1\r
+//  249                if (HaltParameters.HaltFlags & i) {\r
+        LDS     R16, HaltParameters\r
+        AND     R16, R25\r
+        TST     R16\r
+        BRNE    $+2+2\r
+        RJMP    ??HaltNow_2\r
+//  250                        switch (i) {\r
+        MOV     R16, R25\r
+        SUBI    R16, 1\r
+        BREQ    ??HaltNow_3\r
+        DEC     R16\r
+        BREQ    ??HaltNow_4\r
+        SUBI    R16, 2\r
+        BREQ    ??HaltNow_5\r
+        SUBI    R16, 4\r
+        BRNE    $+2+2\r
+        RJMP    ??HaltNow_6\r
+        SUBI    R16, 8\r
+        BRNE    $+2+2\r
+        RJMP    ??HaltNow_7\r
+        RJMP    ??HaltNow_2\r
+//  251                        // Is VBAT less than the recorded maximum?\r
+//  252                        case HALT_VOLTAGE_DROP:\r
+//  253 \r
+//  254                                // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
+//  255                                if (ADCS.VBAT > HaltParameters.VBATMax) {\r
+??HaltNow_3:\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R16, Z+13\r
+        LDD     R17, Z+14\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+10\r
+        LDD     R19, Z+11\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    ??HaltNow_8\r
+//  256                                        HaltParameters.VBATMax = ADCS.VBAT;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+13, R16\r
+        STD     Z+14, R17\r
+        RJMP    ??HaltNow_2\r
+//  257                                } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+//  258                                          HaltParameters.VoltageDrop) {\r
+??HaltNow_8:\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R16, Z+13\r
+        LDD     R17, Z+14\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+10\r
+        LDD     R19, Z+11\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R18, Z+1\r
+        LDD     R19, Z+2\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    $+2+2\r
+        RJMP    ??HaltNow_2\r
+//  259                                        halt = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??HaltNow_2\r
+//  260                                }\r
+//  261                        break;\r
+//  262 \r
+//  263                        \r
+//  264                        // Has VBAT reached the maximum limit?\r
+//  265                        case HALT_VOLTAGE_MAX:  \r
+//  266                                \r
+//  267                                if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+??HaltNow_4:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R18, Z+3\r
+        LDD     R19, Z+4\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    $+2+2\r
+        RJMP    ??HaltNow_2\r
+//  268                                        halt = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??HaltNow_2\r
+//  269                                }\r
+//  270                                break;\r
+//  271 \r
+//  272 \r
+//  273                        // Has IBAT reached the minimum limit?\r
+//  274                        case HALT_CURRENT_MIN:\r
+//  275                                \r
+//  276                                if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+??HaltNow_5:\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R16, Z+5\r
+        LDD     R17, Z+6\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+22\r
+        LDD     R19, Z+23\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    $+2+2\r
+        RJMP    ??HaltNow_2\r
+//  277                                        halt = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??HaltNow_2\r
+//  278                                }\r
+//  279                                break;\r
+//  280        \r
+//  281                                \r
+//  282                        // Is the temperature rising too fast?\r
+//  283                        case HALT_TEMPERATURE_RISE:\r
+//  284 \r
+//  285                                // If rawNTC has increased, the temperature has dropped.\r
+//  286                                // We can store this value for now, and start the timer.\r
+//  287                                // Otherwise, check if NTC has changed too fast.\r
+//  288                                if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
+??HaltNow_6:\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R16, Z+15\r
+        LDD     R17, Z+16\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+4\r
+        LDD     R19, Z+5\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    ??HaltNow_9\r
+//  289                                        HaltParameters.LastNTC = ADCS.rawNTC;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+15, R16\r
+        STD     Z+16, R17\r
+//  290                                        Time_Set(TIMER_TEMP,0,30,0);\r
+        LDI     R20, 0\r
+        LDI     R17, 30\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 3\r
+        RCALL   Time_Set\r
+        RJMP    ??HaltNow_2\r
+//  291                                        \r
+//  292                                // Is the increase in temperature greater than the set threshold?\r
+//  293                                } else  if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+//  294                                  (BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
+??HaltNow_9:\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R26, Z+15\r
+        LDD     R27, Z+16\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        SUB     R26, R16\r
+        SBC     R27, R17\r
+        LDS     R20, (BattData + 3)\r
+        LDI     R21, 0\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R16, Z+11\r
+        LDD     R17, Z+12\r
+        RCALL   ?S_MUL_L02\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BRCS    ??HaltNow_2\r
+//  295                                        \r
+//  296                                        // If this happened within a timeframe of 30 seconds, the \r
+//  297                                        // temperature is rising faster than we want.\r
+//  298                                        // If not, update LastNTC and reset timer.\r
+//  299                                        if (Time_Left(TIMER_TEMP))  {\r
+        LDI     R16, 3\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BREQ    ??HaltNow_10\r
+//  300                                                halt = TRUE;\r
+        LDI     R24, 1\r
+        RJMP    ??HaltNow_2\r
+//  301                                        } else {\r
+//  302                                                HaltParameters.LastNTC = ADCS.rawNTC;\r
+??HaltNow_10:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        STD     Z+15, R16\r
+        STD     Z+16, R17\r
+//  303                                                Time_Set(TIMER_TEMP,0,30,0);\r
+        LDI     R20, 0\r
+        LDI     R17, 30\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 3\r
+        RCALL   Time_Set\r
+        RJMP    ??HaltNow_2\r
+//  304                                        }\r
+//  305                                }\r
+//  306                        break;\r
+//  307        \r
+//  308                        \r
+//  309                        // Is there any time left?\r
+//  310                        case HALT_TIME:  \r
+//  311                                \r
+//  312                                if (!Time_Left(TIMER_CHG)) {\r
+??HaltNow_7:\r
+        LDI     R16, 1\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??HaltNow_2\r
+//  313                                        halt = TRUE;\r
+        LDI     R24, 1\r
+//  314                                        \r
+//  315                                        // If exhaustion flagging is selected, stop the PWM, disable the \r
+//  316                                        // battery and flag it as exhausted. Make ST_ERROR next state.\r
+//  317                                        if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 5\r
+        RJMP    ??HaltNow_2\r
+//  318                                                        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  319                                                        BattControl[BattActive].Enabled = FALSE;\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0xFE\r
+        LDS     R18, BattActive\r
+        LDI     R19, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R18\r
+        ADC     R21, R19\r
+        RCALL   __eeput8_16\r
+//  320                                                        BattData.Exhausted = TRUE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x08\r
+        ST      Z, R16\r
+//  321                                                        SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
+        LDI     R16, 16\r
+        RCALL   SetErrorFlag\r
+//  322                                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (ChargeParameters + 4), R16\r
+//  323                                        }\r
+//  324                                }\r
+//  325                        break;\r
+//  326                        \r
+//  327                        \r
+//  328                        default:  // Shouldn't end up here, but is needed for MISRA compliance.\r
+//  329                        break;\r
+//  330                        }\r
+//  331                }\r
+//  332        }\r
+??HaltNow_2:\r
+        LSL     R25\r
+        RJMP    ??HaltNow_0\r
+//  333 \r
+//  334        // Standard checks:\r
+//  335 \r
+//  336        // Battery too cold or hot?\r
+//  337        if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||\r
+//  338            (BattData.Temperature >= HaltParameters.TemperatureMax)) {\r
+??HaltNow_1:\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R18, Z+9\r
+        LDD     R19, Z+10\r
+        LDS     R16, (BattData + 2)\r
+        MOV     R17, R16\r
+        LSL     R17\r
+        SBC     R17, R17\r
+        CP      R18, R16\r
+        CPC     R19, R17\r
+        BRGE    ??HaltNow_11\r
+        LDS     R16, (BattData + 2)\r
+        MOV     R17, R16\r
+        LSL     R17\r
+        SBC     R17, R17\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDD     R18, Z+7\r
+        LDD     R19, Z+8\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCS    ??HaltNow_12\r
+//  339                        \r
+//  340                PWM_Stop();\r
+??HaltNow_11:\r
+        RCALL   PWM_Stop\r
+//  341                SetErrorFlag(ERR_BATTERY_TEMPERATURE);\r
+        LDI     R16, 8\r
+        RCALL   SetErrorFlag\r
+//  342                ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (ChargeParameters + 4), R16\r
+//  343                halt = TRUE;\r
+        LDI     R24, 1\r
+//  344        }\r
+//  345 \r
+//  346        // Battery not OK?\r
+//  347        if (!BatteryCheck()) {\r
+??HaltNow_12:\r
+        RCALL   BatteryCheck\r
+        TST     R16\r
+        BRNE    ??HaltNow_13\r
+//  348                PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  349                ChargeParameters.NextState = ST_INIT;\r
+        LDI     R16, 10\r
+        STS     (ChargeParameters + 4), R16\r
+//  350                halt = TRUE;\r
+        LDI     R24, 1\r
+//  351        }\r
+//  352 \r
+//  353        // Is mains voltage OK?\r
+//  354        if (!ADCS.Mains) {\r
+??HaltNow_13:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        SBRC    R16, 6\r
+        RJMP    ??HaltNow_14\r
+//  355                PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  356                ChargeParameters.NextState = ST_SLEEP;\r
+        LDI     R16, 40\r
+        STS     (ChargeParameters + 4), R16\r
+//  357                halt = TRUE;\r
+        LDI     R24, 1\r
+//  358        }\r
+//  359 \r
+//  360        return(halt);\r
+??HaltNow_14:\r
+        MOV     R16, R24\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+//  361 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   1 byte  in segment ABSOLUTE\r
+// 846 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//  22 bytes in segment NEAR_Z\r
+// \r
+// 846 bytes of CODE memory (+ 6 bytes shared)\r
+//  22 bytes of DATA memory (+ 1 byte  shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/main.lst b/BaseTinyFirmware/IAR/Debug/List/main.lst
new file mode 100644 (file)
index 0000000..261a4e6
--- /dev/null
@@ -0,0 +1,385 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:39 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\main.c               #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\main.c               #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\main.lst  #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90   #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\main.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Main program file\r
+      6           *\r
+      7           *      Contains the main program, which is a basic state machine.\r
+      8           *\r
+      9           * \par Application note:\r
+     10           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     11           *      AVR463: Charging NiMH Batteries with BC100\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2302 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $\r
+     26           * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          /*! \page License\r
+     30           * Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+     31           *\r
+     32           * Redistribution and use in source and binary forms, with or without\r
+     33           * modification, are permitted provided that the following conditions are met:\r
+     34           *\r
+     35           * 1. Redistributions of source code must retain the above copyright notice,\r
+     36           * this list of conditions and the following disclaimer.\r
+     37           *\r
+     38           * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+     39           * this list of conditions and the following disclaimer in the documentation\r
+     40           * and/or other materials provided with the distribution.\r
+     41           *\r
+     42           * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+     43           * from this software without specific prior written permission.\r
+     44           *\r
+     45           * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+     46           * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+     47           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+     48           * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+     49           * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+     50           * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+     51           * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+     52           * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+     53           * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+     54           * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+     55           */\r
+     56          \r
+     57          #include <ioavr.h>\r
+     58          #include <inavr.h>\r
+     59          #include <stdlib.h>\r
+     60          \r
+     61          #include "structs.h"\r
+     62          \r
+     63          #include "main.h"\r
+     64          #include "ADC.h"\r
+     65          #include "statefunc.h"\r
+     66          #include "battery.h"\r
+     67          #include "menu.h"\r
+     68          #include "OWI.h"\r
+     69          #include "PWM.h"\r
+     70          #include "time.h"\r
+     71          #include "USI.h"\r
+     72          \r
+     73          \r
+     74          \r
+     75          //******************************************************************************\r
+     76          // Globals\r
+     77          //******************************************************************************\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     78          unsigned char CurrentState;     //!< \brief Global that indicates current state\r
+   \                     CurrentState:\r
+   \   00000000                      DS 1\r
+     79                                          //!<\r
+     80                                          //!< Updated by main().\r
+     81                                          //!< \note See menu.h for definition of states.\r
+     82          \r
+     83          \r
+     84          //******************************************************************************\r
+     85          // Functions\r
+     86          //******************************************************************************\r
+     87          /*! \brief Main program\r
+     88           *\r
+     89           * The main function goes into an infinite loop, keeping track of the current\r
+     90           * state and the next one. If the next state is different from the current, it\r
+     91           * looks up the address to the next state function, in \ref menu_state[], and \r
+     92           * updates \ref CurrentState. The state function is then called and will\r
+     93           * eventually return a new state, and so the loop reiterates.\r
+     94           *\r
+     95           * \todo The variable inp is passed to all state functions, but is not used\r
+     96           * for anything yet. Remove?\r
+     97           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     98          int main( void )\r
+   \                     main:\r
+     99          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE7_L09\r
+   \   00000002                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R6_is_cg_reg\r
+    100                unsigned char nextstate, inp, i;\r
+    101                unsigned char (*pStateFunc)(unsigned char);   // Function pointer.\r
+    102                \r
+    103                // Initialize local state variables.\r
+    104                inp = ZERO;\r
+   \   00000002   2466               CLR     R6\r
+    105                CurrentState = nextstate = ST_INIT;\r
+   \   00000004   E00A               LDI     R16, 10\r
+   \   00000006   2F90               MOV     R25, R16\r
+   \   00000008   9300....           STS     CurrentState, R16\r
+    106                pStateFunc = NULL;\r
+   \   0000000C   E000               LDI     R16, 0\r
+   \   0000000E   E010               LDI     R17, 0\r
+   \   00000010   0128               MOVW    R5:R4, R17:R16\r
+    107                \r
+    108                // Look for function associated with current state, get its address.\r
+    109                for (i = 0; menu_state[i].state != 0; i++) {\r
+   \   00000012   E080               LDI     R24, 0\r
+   \                     ??main_0:\r
+   \   00000014   2F48               MOV     R20, R24\r
+   \   00000016   E050               LDI     R21, 0\r
+   \   00000018   E003               LDI     R16, 3\r
+   \   0000001A   E010               LDI     R17, 0\r
+   \   0000001C   ....               RCALL   ?S_MUL_L02\r
+   \   0000001E   ....               LDI     R30, LOW(menu_state)\r
+   \   00000020   ....               LDI     R31, (menu_state) >> 8\r
+   \   00000022   0FE0               ADD     R30, R16\r
+   \   00000024   1FF1               ADC     R31, R17\r
+   \   00000026   9104               LPM     R16, Z\r
+   \   00000028   2300               TST     R16\r
+   \   0000002A   F0F1               BREQ    ??main_1\r
+    110                        if (menu_state[i].state == CurrentState) {\r
+   \   0000002C   2F48               MOV     R20, R24\r
+   \   0000002E   E050               LDI     R21, 0\r
+   \   00000030   E003               LDI     R16, 3\r
+   \   00000032   E010               LDI     R17, 0\r
+   \   00000034   ....               RCALL   ?S_MUL_L02\r
+   \   00000036   ....               LDI     R30, LOW(menu_state)\r
+   \   00000038   ....               LDI     R31, (menu_state) >> 8\r
+   \   0000003A   0FE0               ADD     R30, R16\r
+   \   0000003C   1FF1               ADC     R31, R17\r
+   \   0000003E   9104               LPM     R16, Z\r
+   \   00000040   9110....           LDS     R17, CurrentState\r
+   \   00000044   1701               CP      R16, R17\r
+   \   00000046   F471               BRNE    ??main_2\r
+    111                                pStateFunc = menu_state[i].pFunc;\r
+   \   00000048   ....               LDI     R26, LOW((menu_state + 1))\r
+   \   0000004A   ....               LDI     R27, HIGH((menu_state + 1))\r
+   \   0000004C   2F48               MOV     R20, R24\r
+   \   0000004E   E050               LDI     R21, 0\r
+   \   00000050   E003               LDI     R16, 3\r
+   \   00000052   E010               LDI     R17, 0\r
+   \   00000054   ....               RCALL   ?S_MUL_L02\r
+   \   00000056   0FA0               ADD     R26, R16\r
+   \   00000058   1FB1               ADC     R27, R17\r
+   \   0000005A   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000005C   9105               LPM     R16, Z+\r
+   \   0000005E   9114               LPM     R17, Z\r
+   \   00000060   9731               SBIW    R31:R30, 1\r
+   \   00000062   0128               MOVW    R5:R4, R17:R16\r
+    112                        }\r
+    113                }\r
+   \                     ??main_2:\r
+   \   00000064   9583               INC     R24\r
+   \   00000066   CFD6               RJMP    ??main_0\r
+    114          \r
+    115                while (TRUE) {\r
+    116                        // Run function associated with current state, get next state in return.\r
+    117                        if (pStateFunc != NULL){\r
+   \                     ??main_1:\r
+   \   00000068   E000               LDI     R16, 0\r
+   \   0000006A   E010               LDI     R17, 0\r
+   \   0000006C   1640               CP      R4, R16\r
+   \   0000006E   0651               CPC     R5, R17\r
+   \   00000070   F021               BREQ    ??main_3\r
+    118                                nextstate = pStateFunc(inp);\r
+   \   00000072   2D06               MOV     R16, R6\r
+   \   00000074   01F2               MOVW    R31:R30, R5:R4\r
+   \   00000076   9509               ICALL\r
+   \   00000078   2F90               MOV     R25, R16\r
+    119                        }\r
+    120          \r
+    121                        // Look up function for next state, if it differs from the current.\r
+    122                        if (nextstate != CurrentState) {\r
+   \                     ??main_3:\r
+   \   0000007A   9100....           LDS     R16, CurrentState\r
+   \   0000007E   1790               CP      R25, R16\r
+   \   00000080   F399               BREQ    ??main_1\r
+    123                                CurrentState = nextstate;\r
+   \   00000082   9390....           STS     CurrentState, R25\r
+    124                                for ( i = 0; menu_state[i].state != 0; i++) {\r
+   \   00000086   E080               LDI     R24, 0\r
+   \                     ??main_4:\r
+   \   00000088   2F48               MOV     R20, R24\r
+   \   0000008A   E050               LDI     R21, 0\r
+   \   0000008C   E003               LDI     R16, 3\r
+   \   0000008E   E010               LDI     R17, 0\r
+   \   00000090   ....               RCALL   ?S_MUL_L02\r
+   \   00000092   ....               LDI     R30, LOW(menu_state)\r
+   \   00000094   ....               LDI     R31, (menu_state) >> 8\r
+   \   00000096   0FE0               ADD     R30, R16\r
+   \   00000098   1FF1               ADC     R31, R17\r
+   \   0000009A   9104               LPM     R16, Z\r
+   \   0000009C   2300               TST     R16\r
+   \   0000009E   F321               BREQ    ??main_1\r
+    125                                        if (menu_state[i].state == CurrentState) {\r
+   \   000000A0   2F48               MOV     R20, R24\r
+   \   000000A2   E050               LDI     R21, 0\r
+   \   000000A4   E003               LDI     R16, 3\r
+   \   000000A6   E010               LDI     R17, 0\r
+   \   000000A8   ....               RCALL   ?S_MUL_L02\r
+   \   000000AA   ....               LDI     R30, LOW(menu_state)\r
+   \   000000AC   ....               LDI     R31, (menu_state) >> 8\r
+   \   000000AE   0FE0               ADD     R30, R16\r
+   \   000000B0   1FF1               ADC     R31, R17\r
+   \   000000B2   9104               LPM     R16, Z\r
+   \   000000B4   9110....           LDS     R17, CurrentState\r
+   \   000000B8   1701               CP      R16, R17\r
+   \   000000BA   F471               BRNE    ??main_5\r
+    126                                                pStateFunc = menu_state[i].pFunc;\r
+   \   000000BC   ....               LDI     R26, LOW((menu_state + 1))\r
+   \   000000BE   ....               LDI     R27, HIGH((menu_state + 1))\r
+   \   000000C0   2F48               MOV     R20, R24\r
+   \   000000C2   E050               LDI     R21, 0\r
+   \   000000C4   E003               LDI     R16, 3\r
+   \   000000C6   E010               LDI     R17, 0\r
+   \   000000C8   ....               RCALL   ?S_MUL_L02\r
+   \   000000CA   0FA0               ADD     R26, R16\r
+   \   000000CC   1FB1               ADC     R27, R17\r
+   \   000000CE   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000D0   9105               LPM     R16, Z+\r
+   \   000000D2   9114               LPM     R17, Z\r
+   \   000000D4   9731               SBIW    R31:R30, 1\r
+   \   000000D6   0128               MOVW    R5:R4, R17:R16\r
+    127                                        }\r
+    128                                }\r
+   \                     ??main_5:\r
+   \   000000D8   9583               INC     R24\r
+   \   000000DA   CFD6               RJMP    ??main_4\r
+    129                        }\r
+    130                }\r
+    131          }\r
+    132          \r
+    133          \r
+    134          /* Doxygen documentation mainpage ********************************************/\r
+    135          /*! \mainpage\r
+    136           * \section intro Introduction\r
+    137           * This documents the software for application note AVR458. This is a charger\r
+    138           * for Li-Ion batteries, based on ATAVRBC100.\r
+    139           *\r
+    140           * \section compinfo Compilation Info\r
+    141           * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC \r
+    142           * the source have to be modified.\n\r
+    143           * \n\r
+    144           * To make project on IAR EWAVR:\n\r
+    145           * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,\r
+    146           * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,\r
+    147           * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate\r
+    148           * battery data if needed.\n\r
+    149           * \n\r
+    150           * Use device --cpu=tiny861, enable bit definitions in I/O include files,\r
+    151           * optimization low for debug target and high for release, output format: ubrof8\r
+    152           * for Debug and intel_extended for Release. \n\r
+    153           *\r
+    154           * \section deviceinfo Device Info\r
+    155           * This application is based on the ATtiny 861, but it is possible to migrate \r
+    156           * the design to other AVR microcontrollers, such as pin-compatible devices\r
+    157           * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be\r
+    158           * used, but with reduced functionality.\r
+    159           * \r
+    160           * Required fuse bit settings:\r
+    161           *    <pre>\r
+    162           *    FUSE BIT  | SETTING\r
+    163           *    ----------+--------------------\r
+    164           *    CKDIV8    | 1 (unprogrammed)\r
+    165           *    CKSEL3..0 | 0010 (internal osc)\r
+    166           *    </pre>\r
+    167           *\r
+    168           *\r
+    169           * \section todo To Do-list\r
+    170           * \todo\r
+    171           * - Finalize master-slave communication protocol\r
+    172           * - Implement discharge mode\r
+    173           *\r
+    174           * \section contactinfo Contact Info\r
+    175           * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n\r
+    176           * For application notes visit \r
+    177           * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n\r
+    178           * Support mail: avr@atmel.com\r
+    179           */\r
+    180          \r
+    181          \r
+    182          /*! \page misra MISRA C rule violations\r
+    183           *\r
+    184           * \par Rule 1\r
+    185           * <i>"All code shall conform to ISO 9899 standard C, with no extensions\r
+    186           * permitted."</i>\r
+    187           *\r
+    188           * Extensions are necessary because ISO C has no way of specifying that a\r
+    189           * function should be an interrupt service routine, or that we would like data\r
+    190           * members to be stored in f.ex. EEPROM.\r
+    191           *\r
+    192           *\r
+    193           * \par Rule 37\r
+    194           * <i>"Bitwise operations shall not be performed on signed integer types."</i>\r
+    195           *\r
+    196           * The compiler assumes all the 1's we shift around to make bitmasks are signed\r
+    197           * integers. Specifying them all to be (unsigned int), either directly or via a\r
+    198           * definition, would fix the rule violations, but also reduce code readability.\r
+    199           *\r
+    200           *\r
+    201           * \par Rule 45\r
+    202           * <i>"Type casting from any type to or from pointers shall not be used."</i>\r
+    203           *\r
+    204           * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..\r
+    205           *\r
+    206           *\r
+    207           * \par Rule 96\r
+    208           * <i>"In the definition of a function-like macro the whole definition, and each\r
+    209           * instance of a parameter, shall be enclosed in parentheses."</i>\r
+    210           * \r
+    211           * It is difficult to use parentheses with void function-like macros.\r
+    212           */\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function             CSTACK RSTACK\r
+     --------             ------ ------\r
+     main                     7      4\r
+       ->   Indirect call     7      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     CurrentState      1\r
+     main            220\r
+      Others           6\r
+\r
\r
+ 220 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   1 byte  in segment NEAR_Z\r
\r
+ 220 bytes of CODE memory (+ 6 bytes shared)\r
+   1 byte  of DATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/main.s90 b/BaseTinyFirmware/IAR/Debug/List/main.s90
new file mode 100644 (file)
index 0000000..b1f8205
--- /dev/null
@@ -0,0 +1,411 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\main.c              /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\main.c              /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\main.s90 /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME main\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?PROLOGUE7_L09\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?need_segment_init\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC CurrentState\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+        PUBLIC main\r
+\r
+        EXTERN menu_state\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\main.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Main program file\r
+//    6  *\r
+//    7  *      Contains the main program, which is a basic state machine.\r
+//    8  *\r
+//    9  * \par Application note:\r
+//   10  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2302 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $\r
+//   26  * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 /*! \page License\r
+//   30  * Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+//   31  *\r
+//   32  * Redistribution and use in source and binary forms, with or without\r
+//   33  * modification, are permitted provided that the following conditions are met:\r
+//   34  *\r
+//   35  * 1. Redistributions of source code must retain the above copyright notice,\r
+//   36  * this list of conditions and the following disclaimer.\r
+//   37  *\r
+//   38  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+//   39  * this list of conditions and the following disclaimer in the documentation\r
+//   40  * and/or other materials provided with the distribution.\r
+//   41  *\r
+//   42  * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+//   43  * from this software without specific prior written permission.\r
+//   44  *\r
+//   45  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+//   46  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+//   47  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+//   48  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+//   49  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+//   50  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+//   51  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+//   52  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+//   53  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+//   54  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//   55  */\r
+//   56 \r
+//   57 #include <ioavr.h>\r
+//   58 #include <inavr.h>\r
+//   59 #include <stdlib.h>\r
+//   60 \r
+//   61 #include "structs.h"\r
+//   62 \r
+//   63 #include "main.h"\r
+//   64 #include "ADC.h"\r
+//   65 #include "statefunc.h"\r
+//   66 #include "battery.h"\r
+//   67 #include "menu.h"\r
+//   68 #include "OWI.h"\r
+//   69 #include "PWM.h"\r
+//   70 #include "time.h"\r
+//   71 #include "USI.h"\r
+//   72 \r
+//   73 \r
+//   74 \r
+//   75 //******************************************************************************\r
+//   76 // Globals\r
+//   77 //******************************************************************************\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   78 unsigned char CurrentState;     //!< \brief Global that indicates current state\r
+CurrentState:\r
+        DS 1\r
+//   79                                 //!<\r
+//   80                                 //!< Updated by main().\r
+//   81                                 //!< \note See menu.h for definition of states.\r
+//   82 \r
+//   83 \r
+//   84 //******************************************************************************\r
+//   85 // Functions\r
+//   86 //******************************************************************************\r
+//   87 /*! \brief Main program\r
+//   88  *\r
+//   89  * The main function goes into an infinite loop, keeping track of the current\r
+//   90  * state and the next one. If the next state is different from the current, it\r
+//   91  * looks up the address to the next state function, in \ref menu_state[], and \r
+//   92  * updates \ref CurrentState. The state function is then called and will\r
+//   93  * eventually return a new state, and so the loop reiterates.\r
+//   94  *\r
+//   95  * \todo The variable inp is passed to all state functions, but is not used\r
+//   96  * for anything yet. Remove?\r
+//   97  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   98 int main( void )\r
+main:\r
+//   99 {\r
+        RCALL   ?PROLOGUE7_L09\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+//  100        unsigned char nextstate, inp, i;\r
+//  101        unsigned char (*pStateFunc)(unsigned char);   // Function pointer.\r
+//  102        \r
+//  103        // Initialize local state variables.\r
+//  104        inp = ZERO;\r
+        CLR     R6\r
+//  105        CurrentState = nextstate = ST_INIT;\r
+        LDI     R16, 10\r
+        MOV     R25, R16\r
+        STS     CurrentState, R16\r
+//  106        pStateFunc = NULL;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        MOVW    R5:R4, R17:R16\r
+//  107        \r
+//  108        // Look for function associated with current state, get its address.\r
+//  109        for (i = 0; menu_state[i].state != 0; i++) {\r
+        LDI     R24, 0\r
+??main_0:\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R30, LOW(menu_state)\r
+        LDI     R31, (menu_state) >> 8\r
+        ADD     R30, R16\r
+        ADC     R31, R17\r
+        LPM     R16, Z\r
+        TST     R16\r
+        BREQ    ??main_1\r
+//  110                if (menu_state[i].state == CurrentState) {\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R30, LOW(menu_state)\r
+        LDI     R31, (menu_state) >> 8\r
+        ADD     R30, R16\r
+        ADC     R31, R17\r
+        LPM     R16, Z\r
+        LDS     R17, CurrentState\r
+        CP      R16, R17\r
+        BRNE    ??main_2\r
+//  111                        pStateFunc = menu_state[i].pFunc;\r
+        LDI     R26, LOW((menu_state + 1))\r
+        LDI     R27, HIGH((menu_state + 1))\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        ADD     R26, R16\r
+        ADC     R27, R17\r
+        MOVW    R31:R30, R27:R26\r
+        LPM     R16, Z+\r
+        LPM     R17, Z\r
+        SBIW    R31:R30, 1\r
+        MOVW    R5:R4, R17:R16\r
+//  112                }\r
+//  113        }\r
+??main_2:\r
+        INC     R24\r
+        RJMP    ??main_0\r
+//  114 \r
+//  115        while (TRUE) {\r
+//  116                // Run function associated with current state, get next state in return.\r
+//  117                if (pStateFunc != NULL){\r
+??main_1:\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        CP      R4, R16\r
+        CPC     R5, R17\r
+        BREQ    ??main_3\r
+//  118                        nextstate = pStateFunc(inp);\r
+        MOV     R16, R6\r
+        MOVW    R31:R30, R5:R4\r
+        ICALL\r
+        MOV     R25, R16\r
+//  119                }\r
+//  120 \r
+//  121                // Look up function for next state, if it differs from the current.\r
+//  122                if (nextstate != CurrentState) {\r
+??main_3:\r
+        LDS     R16, CurrentState\r
+        CP      R25, R16\r
+        BREQ    ??main_1\r
+//  123                        CurrentState = nextstate;\r
+        STS     CurrentState, R25\r
+//  124                        for ( i = 0; menu_state[i].state != 0; i++) {\r
+        LDI     R24, 0\r
+??main_4:\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R30, LOW(menu_state)\r
+        LDI     R31, (menu_state) >> 8\r
+        ADD     R30, R16\r
+        ADC     R31, R17\r
+        LPM     R16, Z\r
+        TST     R16\r
+        BREQ    ??main_1\r
+//  125                                if (menu_state[i].state == CurrentState) {\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R30, LOW(menu_state)\r
+        LDI     R31, (menu_state) >> 8\r
+        ADD     R30, R16\r
+        ADC     R31, R17\r
+        LPM     R16, Z\r
+        LDS     R17, CurrentState\r
+        CP      R16, R17\r
+        BRNE    ??main_5\r
+//  126                                        pStateFunc = menu_state[i].pFunc;\r
+        LDI     R26, LOW((menu_state + 1))\r
+        LDI     R27, HIGH((menu_state + 1))\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        LDI     R16, 3\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        ADD     R26, R16\r
+        ADC     R27, R17\r
+        MOVW    R31:R30, R27:R26\r
+        LPM     R16, Z+\r
+        LPM     R17, Z\r
+        SBIW    R31:R30, 1\r
+        MOVW    R5:R4, R17:R16\r
+//  127                                }\r
+//  128                        }\r
+??main_5:\r
+        INC     R24\r
+        RJMP    ??main_4\r
+//  129                }\r
+//  130        }\r
+//  131 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+//  132 \r
+//  133 \r
+//  134 /* Doxygen documentation mainpage ********************************************/\r
+//  135 /*! \mainpage\r
+//  136  * \section intro Introduction\r
+//  137  * This documents the software for application note AVR458. This is a charger\r
+//  138  * for Li-Ion batteries, based on ATAVRBC100.\r
+//  139  *\r
+//  140  * \section compinfo Compilation Info\r
+//  141  * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC \r
+//  142  * the source have to be modified.\n\r
+//  143  * \n\r
+//  144  * To make project on IAR EWAVR:\n\r
+//  145  * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,\r
+//  146  * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,\r
+//  147  * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate\r
+//  148  * battery data if needed.\n\r
+//  149  * \n\r
+//  150  * Use device --cpu=tiny861, enable bit definitions in I/O include files,\r
+//  151  * optimization low for debug target and high for release, output format: ubrof8\r
+//  152  * for Debug and intel_extended for Release. \n\r
+//  153  *\r
+//  154  * \section deviceinfo Device Info\r
+//  155  * This application is based on the ATtiny 861, but it is possible to migrate \r
+//  156  * the design to other AVR microcontrollers, such as pin-compatible devices\r
+//  157  * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be\r
+//  158  * used, but with reduced functionality.\r
+//  159  * \r
+//  160  * Required fuse bit settings:\r
+//  161  *    <pre>\r
+//  162  *    FUSE BIT  | SETTING\r
+//  163  *    ----------+--------------------\r
+//  164  *    CKDIV8    | 1 (unprogrammed)\r
+//  165  *    CKSEL3..0 | 0010 (internal osc)\r
+//  166  *    </pre>\r
+//  167  *\r
+//  168  *\r
+//  169  * \section todo To Do-list\r
+//  170  * \todo\r
+//  171  * - Finalize master-slave communication protocol\r
+//  172  * - Implement discharge mode\r
+//  173  *\r
+//  174  * \section contactinfo Contact Info\r
+//  175  * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n\r
+//  176  * For application notes visit \r
+//  177  * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n\r
+//  178  * Support mail: avr@atmel.com\r
+//  179  */\r
+//  180 \r
+//  181 \r
+//  182 /*! \page misra MISRA C rule violations\r
+//  183  *\r
+//  184  * \par Rule 1\r
+//  185  * <i>"All code shall conform to ISO 9899 standard C, with no extensions\r
+//  186  * permitted."</i>\r
+//  187  *\r
+//  188  * Extensions are necessary because ISO C has no way of specifying that a\r
+//  189  * function should be an interrupt service routine, or that we would like data\r
+//  190  * members to be stored in f.ex. EEPROM.\r
+//  191  *\r
+//  192  *\r
+//  193  * \par Rule 37\r
+//  194  * <i>"Bitwise operations shall not be performed on signed integer types."</i>\r
+//  195  *\r
+//  196  * The compiler assumes all the 1's we shift around to make bitmasks are signed\r
+//  197  * integers. Specifying them all to be (unsigned int), either directly or via a\r
+//  198  * definition, would fix the rule violations, but also reduce code readability.\r
+//  199  *\r
+//  200  *\r
+//  201  * \par Rule 45\r
+//  202  * <i>"Type casting from any type to or from pointers shall not be used."</i>\r
+//  203  *\r
+//  204  * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..\r
+//  205  *\r
+//  206  *\r
+//  207  * \par Rule 96\r
+//  208  * <i>"In the definition of a function-like macro the whole definition, and each\r
+//  209  * instance of a parameter, shall be enclosed in parentheses."</i>\r
+//  210  * \r
+//  211  * It is difficult to use parentheses with void function-like macros.\r
+//  212  */\r
+// \r
+// 220 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   1 byte  in segment NEAR_Z\r
+// \r
+// 220 bytes of CODE memory (+ 6 bytes shared)\r
+//   1 byte  of DATA memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/menu.lst b/BaseTinyFirmware/IAR/Debug/List/menu.lst
new file mode 100644 (file)
index 0000000..8b79c7d
--- /dev/null
@@ -0,0 +1,141 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:39 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\menu.c               #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\menu.c               #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\menu.lst  #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\menu.r90   #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\menu.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      State menu definition\r
+      6           * \r
+      7           *      Contains the definition of the state menu.\n\r
+      8           *      The state menu contains all states and adresses to associated functions.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13           *\r
+     14           * \par Documentation:\r
+     15           *      For comprehensive code documentation, supported compilers, compiler\r
+     16           *      settings and supported devices see readme.html\r
+     17           *\r
+     18           * \author\r
+     19           *      Atmel Corporation: http://www.atmel.com \n\r
+     20           *      Support email: avr@atmel.com\r
+     21           *\r
+     22           *\r
+     23           * $Name$\r
+     24           * $Revision: 2299 $\r
+     25           * $RCSfile$\r
+     26           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $\r
+     27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     28           ******************************************************************************/\r
+     29          \r
+     30          #include <stdlib.h>\r
+     31          \r
+     32          #include "statefunc.h"\r
+     33          #include "charge.h"\r
+     34          #include "main.h"\r
+     35          #include "menu.h"\r
+     36          \r
+     37          \r
+     38          //******************************************************************************\r
+     39          // State menu (relies on the proper battery type to be defined in main.h!)\r
+     40          //******************************************************************************\r
+     41          #ifdef NIMH\r
+     42          /*! \brief The state menu\r
+     43           *\r
+     44           * Contains all the defined states and addresses to their associated functions.\r
+     45           */\r
+\r
+   \                                 In  segment NEAR_F, align 1, keep-with-next\r
+     46          __flash const MENU_STATE_t menu_state[] = {\r
+   \                     menu_state:\r
+   \   00000000   0A                 DB 10\r
+   \   00000001   ....               DW Initialize/2\r
+   \   00000003   14                 DB 20\r
+   \   00000004   ....               DW BatteryControl/2\r
+   \   00000006   1E                 DB 30\r
+   \   00000007   ....               DW Charge/2\r
+   \   00000009   28                 DB 40\r
+   \   0000000A   ....               DW `Sleep`/2\r
+   \   0000000C   32                 DB 50\r
+   \   0000000D   ....               DW Charge/2\r
+   \   0000000F   3C                 DB 60\r
+   \   00000010   ....               DW Charge/2\r
+   \   00000012   46                 DB 70\r
+   \   00000013   ....               DW Charge/2\r
+   \   00000015   50                 DB 80\r
+   \   00000016   ....               DW Discharge/2\r
+   \   00000018   5A                 DB 90\r
+   \   00000019   ....               DW Error/2\r
+   \   0000001B   00                 DB 0\r
+   \   0000001C   0000               DW 0H\r
+     47          //  State                                     State function\r
+     48            { ST_INIT,            Initialize},\r
+     49            { ST_BATCON,          BatteryControl},\r
+     50            { ST_PREQUAL,         Charge},\r
+     51            { ST_SLEEP,           Sleep},\r
+     52            { ST_FASTCHARGE,      Charge},\r
+     53            { ST_LOWRATECHARGE,   Charge},\r
+     54            { ST_ENDCHARGE,       Charge},      \r
+     55            { ST_DISCHARGE,       Discharge},\r
+     56            { ST_ERROR,           Error},\r
+     57            { 0,                  NULL},\r
+     58          };\r
+     59          #endif // NIMH\r
+     60          \r
+     61          #ifdef LIION\r
+     62          /*! \brief The state menu\r
+     63           *\r
+     64           * Contains all the defined states and addresses to their associated functions.\r
+     65           */\r
+     66          __flash const MENU_STATE_t menu_state[] = {\r
+     67          //  State                                     State function\r
+     68            { ST_INIT,            Initialize},\r
+     69            { ST_BATCON,          BatteryControl},\r
+     70            { ST_PREQUAL,         Charge},\r
+     71            { ST_SLEEP,           Sleep},\r
+     72            { ST_CCURRENT,        Charge},\r
+     73            { ST_CVOLTAGE,        Charge},\r
+     74            { ST_ENDCHARGE,       Charge},      \r
+     75            { ST_DISCHARGE,       Discharge},\r
+     76            { ST_ERROR,           Error},\r
+     77            { 0,                  NULL},\r
+     78          };\r
+     79          #endif // LIION\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     menu_state       30\r
+\r
\r
+ 30 bytes in segment NEAR_F\r
\r
+ 30 bytes of CODE memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/menu.s90 b/BaseTinyFirmware/IAR/Debug/List/menu.s90
new file mode 100644 (file)
index 0000000..43a5f51
--- /dev/null
@@ -0,0 +1,165 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\menu.c              /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\menu.c              /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\menu.s90 /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME menu\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+        PUBLIC menu_state\r
+\r
+        EXTERN BatteryControl\r
+        EXTERN Charge\r
+        EXTERN Discharge\r
+        EXTERN Error\r
+        EXTERN Initialize\r
+        EXTERN `Sleep`\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\menu.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      State menu definition\r
+//    6  * \r
+//    7  *      Contains the definition of the state menu.\n\r
+//    8  *      The state menu contains all states and adresses to associated functions.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13  *\r
+//   14  * \par Documentation:\r
+//   15  *      For comprehensive code documentation, supported compilers, compiler\r
+//   16  *      settings and supported devices see readme.html\r
+//   17  *\r
+//   18  * \author\r
+//   19  *      Atmel Corporation: http://www.atmel.com \n\r
+//   20  *      Support email: avr@atmel.com\r
+//   21  *\r
+//   22  *\r
+//   23  * $Name$\r
+//   24  * $Revision: 2299 $\r
+//   25  * $RCSfile$\r
+//   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $\r
+//   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   28  ******************************************************************************/\r
+//   29 \r
+//   30 #include <stdlib.h>\r
+//   31 \r
+//   32 #include "statefunc.h"\r
+//   33 #include "charge.h"\r
+//   34 #include "main.h"\r
+//   35 #include "menu.h"\r
+//   36 \r
+//   37 \r
+//   38 //******************************************************************************\r
+//   39 // State menu (relies on the proper battery type to be defined in main.h!)\r
+//   40 //******************************************************************************\r
+//   41 #ifdef NIMH\r
+//   42 /*! \brief The state menu\r
+//   43  *\r
+//   44  * Contains all the defined states and addresses to their associated functions.\r
+//   45  */\r
+\r
+        RSEG NEAR_F:CODE:NOROOT(0)\r
+//   46 __flash const MENU_STATE_t menu_state[] = {\r
+menu_state:\r
+        DB 10\r
+        DW Initialize/2\r
+        DB 20\r
+        DW BatteryControl/2\r
+        DB 30\r
+        DW Charge/2\r
+        DB 40\r
+        DW `Sleep`/2\r
+        DB 50\r
+        DW Charge/2\r
+        DB 60\r
+        DW Charge/2\r
+        DB 70\r
+        DW Charge/2\r
+        DB 80\r
+        DW Discharge/2\r
+        DB 90\r
+        DW Error/2\r
+        DB 0\r
+        DW 0H\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+//   47 //  State                                      State function\r
+//   48   { ST_INIT,            Initialize},\r
+//   49   { ST_BATCON,          BatteryControl},\r
+//   50   { ST_PREQUAL,         Charge},\r
+//   51   { ST_SLEEP,           Sleep},\r
+//   52   { ST_FASTCHARGE,      Charge},\r
+//   53   { ST_LOWRATECHARGE,   Charge},\r
+//   54   { ST_ENDCHARGE,       Charge},       \r
+//   55   { ST_DISCHARGE,       Discharge},\r
+//   56   { ST_ERROR,           Error},\r
+//   57   { 0,                  NULL},\r
+//   58 };\r
+//   59 #endif // NIMH\r
+//   60 \r
+//   61 #ifdef LIION\r
+//   62 /*! \brief The state menu\r
+//   63  *\r
+//   64  * Contains all the defined states and addresses to their associated functions.\r
+//   65  */\r
+//   66 __flash const MENU_STATE_t menu_state[] = {\r
+//   67 //  State                                      State function\r
+//   68   { ST_INIT,            Initialize},\r
+//   69   { ST_BATCON,          BatteryControl},\r
+//   70   { ST_PREQUAL,         Charge},\r
+//   71   { ST_SLEEP,           Sleep},\r
+//   72   { ST_CCURRENT,        Charge},\r
+//   73   { ST_CVOLTAGE,        Charge},\r
+//   74   { ST_ENDCHARGE,       Charge},       \r
+//   75   { ST_DISCHARGE,       Discharge},\r
+//   76   { ST_ERROR,           Error},\r
+//   77   { 0,                  NULL},\r
+//   78 };\r
+//   79 #endif // LIION\r
+// \r
+// 30 bytes in segment NEAR_F\r
+// \r
+// 30 bytes of CODE memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/statefunc.lst b/BaseTinyFirmware/IAR/Debug/List/statefunc.lst
new file mode 100644 (file)
index 0000000..139b867
--- /dev/null
@@ -0,0 +1,997 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:39 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c          #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c          #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\statefunc #\r
+#                    .lst                                                     #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\statefunc. #\r
+#                    r90                                                      #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      State functions\r
+      6           *\r
+      7           *      Contains the functions related to the states defined in menu.h.\n\r
+      8           *      Also contains related functions, i.e. for checking jumpers, setting\r
+      9           *      error flags and "dozing".\r
+     10           *\r
+     11           *      \note The state function Charge() is in a separate file since it\r
+     12           *      should easily be changed with regard to battery type.\r
+     13           *\r
+     14           * \par Application note:\r
+     15           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     16           *      AVR463: Charging NiMH Batteries with BC100\r
+     17           *\r
+     18           * \par Documentation\r
+     19           *      For comprehensive code documentation, supported compilers, compiler \r
+     20           *      settings and supported devices see readme.html\r
+     21           *\r
+     22           * \author\r
+     23           *      Atmel Corporation: http://www.atmel.com \n\r
+     24           *      Support email: avr@atmel.com\r
+     25           *\r
+     26           * \r
+     27           * $Name$\r
+     28           * $Revision: 2299 $\r
+     29           * $RCSfile$\r
+     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
+     31           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     32           ******************************************************************************/\r
+     33          \r
+     34          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x55\r
+   \   <unnamed> volatile __io _A_MCUCR\r
+   \                     _A_MCUCR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x54\r
+   \   <unnamed> volatile __io _A_MCUSR\r
+   \                     _A_MCUSR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x48\r
+   \   <unnamed> volatile __io _A_CLKPR\r
+   \                     _A_CLKPR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x41\r
+   \   <unnamed> volatile __io _A_WDTCR\r
+   \                     _A_WDTCR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x37\r
+   \   <unnamed> volatile __io _A_DDRB\r
+   \                     _A_DDRB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x26\r
+   \   <unnamed> volatile __io _A_ADCSRA\r
+   \                     _A_ADCSRA:\r
+   \   00000000                      DS 1\r
+     35          #include <inavr.h>\r
+     36          #include <stdlib.h>\r
+     37          \r
+     38          #include "structs.h"\r
+     39          #include "enums.h"\r
+     40          \r
+     41          #include "ADC.h"\r
+     42          #include "statefunc.h"\r
+     43          #include "battery.h"\r
+     44          #include "charge.h"\r
+     45          #include "main.h"\r
+     46          #include "menu.h"\r
+     47          #include "OWI.h"\r
+     48          #include "PWM.h"\r
+     49          #include "time.h"\r
+     50          #include "USI.h"\r
+     51          \r
+     52          \r
+     53          //******************************************************************************\r
+     54          // Variables\r
+     55          //******************************************************************************\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     56          unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
+   \                     ErrorFlags:\r
+   \   00000000                      DS 1\r
+     57                                     //!< \note See statefunc.h for definitions of flags.\r
+     58          \r
+     59          //! \brief Holds the state in which latest error flag was set.\r
+     60          //! \note See menu.h for definitions of states.\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     61          unsigned char ErrorState;\r
+   \                     ErrorState:\r
+   \   00000000                      DS 1\r
+     62          \r
+     63          \r
+     64          //******************************************************************************\r
+     65          // Functions\r
+     66          //******************************************************************************\r
+     67          /*! \brief Initialization\r
+     68           *\r
+     69           * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
+     70           * - Initializes the one-wire interface\r
+     71           * - Clears on-chip EEPROM\r
+     72           * - Sets battery enable pins as outputs, then disables batteries\r
+     73           * - Initializes SPI according to \ref SPIMODE\r
+     74           * - Initializes ADC\r
+     75           * - Initializes timers\r
+     76           * - Reads battery data from both battery inputs (via ADC)\r
+     77           * - Disables batteries again\r
+     78           * - Sets battery A as the current one (\ref BattActive = 0)\r
+     79           * - Clears ErrorFlags\r
+     80           *\r
+     81           * \param inp Not used.\r
+     82           *\r
+     83           * \retval ST_BATCON Next state in the sequence.\r
+     84           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     85          unsigned char Initialize(unsigned char inp)\r
+   \                     Initialize:\r
+     86          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE4_L09\r
+   \   00000002   2FB0               MOV     R27, R16\r
+     87                unsigned char i, page;\r
+     88          \r
+     89                // Disable interrupts while setting prescaler.\r
+     90                __disable_interrupt();\r
+   \   00000004   94F8               CLI\r
+     91                \r
+     92                CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
+   \   00000006   E800               LDI     R16, 128\r
+   \   00000008   BD08               OUT     0x28, R16\r
+     93                CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
+   \   0000000A   E000               LDI     R16, 0\r
+   \   0000000C   BD08               OUT     0x28, R16\r
+     94                \r
+     95                // Init 1-Wire(R) interface.\r
+     96                OWI_Init(OWIBUS);\r
+   \   0000000E   E001               LDI     R16, 1\r
+   \   00000010   ....               RCALL   OWI_Init\r
+     97                \r
+     98                // Clear on-chip EEPROM.\r
+     99                for (page = 0; page < 4; page++)        {\r
+   \   00000012   E090               LDI     R25, 0\r
+   \                     ??Initialize_0:\r
+   \   00000014   3094               CPI     R25, 4\r
+   \   00000016   F4B8               BRCC    ??Initialize_1\r
+    100                        for (i = 0; i < 32; i++) {\r
+   \   00000018   E080               LDI     R24, 0\r
+   \                     ??Initialize_2:\r
+   \   0000001A   3280               CPI     R24, 32\r
+   \   0000001C   F490               BRCC    ??Initialize_3\r
+    101                                BattEEPROM[page][i] = 0;\r
+   \   0000001E   E0A0               LDI     R26, 0\r
+   \   00000020   2F49               MOV     R20, R25\r
+   \   00000022   E050               LDI     R21, 0\r
+   \   00000024   E200               LDI     R16, 32\r
+   \   00000026   E010               LDI     R17, 0\r
+   \   00000028   ....               RCALL   ?S_MUL_L02\r
+   \   0000002A   ....               LDI     R20, LOW(BattEEPROM)\r
+   \   0000002C   ....               LDI     R21, (BattEEPROM) >> 8\r
+   \   0000002E   0F40               ADD     R20, R16\r
+   \   00000030   1F51               ADC     R21, R17\r
+   \   00000032   2F08               MOV     R16, R24\r
+   \   00000034   E010               LDI     R17, 0\r
+   \   00000036   0F40               ADD     R20, R16\r
+   \   00000038   1F51               ADC     R21, R17\r
+   \   0000003A   2F0A               MOV     R16, R26\r
+   \   0000003C   ....               RCALL   __eeput8_16\r
+    102                        }\r
+   \   0000003E   9583               INC     R24\r
+   \   00000040   CFEC               RJMP    ??Initialize_2\r
+    103                }\r
+   \                     ??Initialize_3:\r
+   \   00000042   9593               INC     R25\r
+   \   00000044   CFE7               RJMP    ??Initialize_0\r
+    104          \r
+    105                DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
+   \                     ??Initialize_1:\r
+   \   00000046   E300               LDI     R16, 48\r
+   \   00000048   BB07               OUT     0x17, R16\r
+    106                DisableBatteries();\r
+   \   0000004A   ....               RCALL   DisableBatteries\r
+    107                SPI_Init(SPIMODE);\r
+   \   0000004C   E000               LDI     R16, 0\r
+   \   0000004E   ....               RCALL   SPI_Init\r
+    108                ADC_Init();\r
+   \   00000050   ....               RCALL   ADC_Init\r
+    109                Time_Init();\r
+   \   00000052   ....               RCALL   Time_Init\r
+    110          \r
+    111                // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
+    112                for (i = 0; i < 2; i++) {\r
+   \   00000054   E080               LDI     R24, 0\r
+   \                     ??Initialize_4:\r
+   \   00000056   3082               CPI     R24, 2\r
+   \   00000058   F430               BRCC    ??Initialize_5\r
+    113                        EnableBattery(i);\r
+   \   0000005A   2F08               MOV     R16, R24\r
+   \   0000005C   ....               RCALL   EnableBattery\r
+    114                        ADC_Wait();\r
+   \   0000005E   ....               RCALL   ADC_Wait\r
+    115                        BatteryStatusRefresh();\r
+   \   00000060   ....               RCALL   BatteryStatusRefresh\r
+    116                }\r
+   \   00000062   9583               INC     R24\r
+   \   00000064   CFF8               RJMP    ??Initialize_4\r
+    117              \r
+    118                DisableBatteries();\r
+   \                     ??Initialize_5:\r
+   \   00000066   ....               RCALL   DisableBatteries\r
+    119                \r
+    120                BattActive = 0;               // We have to start somewhere..\r
+   \   00000068   E000               LDI     R16, 0\r
+   \   0000006A   9300....           STS     BattActive, R16\r
+    121                ErrorFlags = 0;\r
+   \   0000006E   E000               LDI     R16, 0\r
+   \   00000070   9300....           STS     ErrorFlags, R16\r
+    122                \r
+    123                // Init complete! Go to ST_BATCON next.\r
+    124                return(ST_BATCON);\r
+   \   00000074   E104               LDI     R16, 20\r
+   \   00000076   E0E4               LDI     R30, 4\r
+   \   00000078   ....               RJMP    ?EPILOGUE_B4_L09\r
+   \   0000007A                      REQUIRE _A_CLKPR\r
+   \   0000007A                      REQUIRE _A_DDRB\r
+    125          }\r
+    126          \r
+    127          \r
+    128          /*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
+    129           *\r
+    130           * First, JumperCheck() is called. If successful, the function checks if any\r
+    131           * valid batteries are connected and attempts to charge these, if necessary.\n\r
+    132           * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
+    133           * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
+    134           * batteries. In this last case, the error is also flagged.\r
+    135           *\r
+    136           * \param inp Not used.\r
+    137           *\r
+    138           * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
+    139           * no valid batteries.\r
+    140           * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
+    141           * charged.\r
+    142           * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
+    143           * charged.\r
+    144           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    145          unsigned char BatteryControl(unsigned char inp)\r
+   \                     BatteryControl:\r
+    146          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE3_L09\r
+   \   00000002   2FA0               MOV     R26, R16\r
+    147                unsigned char i;\r
+    148                \r
+    149                // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
+    150                if (!JumperCheck()) {\r
+   \   00000004   ....               RCALL   JumperCheck\r
+   \   00000006   2300               TST     R16\r
+   \   00000008   F411               BRNE    ??BatteryControl_0\r
+    151                        return(ST_ERROR);           // Error. Exit before damage is done!\r
+   \   0000000A   E50A               LDI     R16, 90\r
+   \   0000000C   C02E               RJMP    ??BatteryControl_1\r
+    152                }\r
+    153                \r
+    154                // If neither battery is valid, flag error and go to error state\r
+    155                if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
+   \                     ??BatteryControl_0:\r
+   \   0000000E   ....               LDI     R20, LOW(BattControl)\r
+   \   00000010   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000012   ....               RCALL   __eeget8_16\r
+   \   00000014   7001               ANDI    R16, 0x01\r
+   \   00000016   2300               TST     R16\r
+   \   00000018   F451               BRNE    ??BatteryControl_2\r
+   \   0000001A   ....               LDI     R20, LOW((BattControl + 1))\r
+   \   0000001C   ....               LDI     R21, HIGH((BattControl + 1))\r
+   \   0000001E   ....               RCALL   __eeget8_16\r
+   \   00000020   7001               ANDI    R16, 0x01\r
+   \   00000022   2300               TST     R16\r
+   \   00000024   F421               BRNE    ??BatteryControl_2\r
+    156                        SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
+   \   00000026   E002               LDI     R16, 2\r
+   \   00000028   ....               RCALL   SetErrorFlag\r
+    157                        \r
+    158                        return(ST_ERROR);\r
+   \   0000002A   E50A               LDI     R16, 90\r
+   \   0000002C   C01E               RJMP    ??BatteryControl_1\r
+    159                }\r
+    160          \r
+    161                // Get ADC-readings, try to read EPROM, and start prequalification\r
+    162                // of any uncharged battery.\r
+    163                for (i = 0; i < 2; i++) {\r
+   \                     ??BatteryControl_2:\r
+   \   0000002E   E080               LDI     R24, 0\r
+   \                     ??BatteryControl_3:\r
+   \   00000030   3082               CPI     R24, 2\r
+   \   00000032   F4C8               BRCC    ??BatteryControl_4\r
+    164                        if (BattControl[i].Enabled) {      \r
+   \   00000034   E090               LDI     R25, 0\r
+   \   00000036   ....               LDI     R20, LOW(BattControl)\r
+   \   00000038   ....               LDI     R21, (BattControl) >> 8\r
+   \   0000003A   0F48               ADD     R20, R24\r
+   \   0000003C   1F59               ADC     R21, R25\r
+   \   0000003E   ....               RCALL   __eeget8_16\r
+   \   00000040   7001               ANDI    R16, 0x01\r
+   \   00000042   2300               TST     R16\r
+   \   00000044   F071               BREQ    ??BatteryControl_5\r
+    165                                EnableBattery(i);\r
+   \   00000046   2F08               MOV     R16, R24\r
+   \   00000048   ....               RCALL   EnableBattery\r
+    166                                ADC_Wait();\r
+   \   0000004A   ....               RCALL   ADC_Wait\r
+    167          \r
+    168                                if (BatteryStatusRefresh()) {\r
+   \   0000004C   ....               RCALL   BatteryStatusRefresh\r
+   \   0000004E   2300               TST     R16\r
+   \   00000050   F041               BREQ    ??BatteryControl_5\r
+    169                                        if (!BattData.Charged) {\r
+   \   00000052   ....               LDI     R30, LOW(BattData)\r
+   \   00000054   ....               LDI     R31, (BattData) >> 8\r
+   \   00000056   8100               LD      R16, Z\r
+   \   00000058   FD01               SBRC    R16, 1\r
+   \   0000005A   C003               RJMP    ??BatteryControl_5\r
+    170                                                BatteryDataRefresh();\r
+   \   0000005C   ....               RCALL   BatteryDataRefresh\r
+    171          \r
+    172                                                return(ST_PREQUAL);       \r
+   \   0000005E   E10E               LDI     R16, 30\r
+   \   00000060   C004               RJMP    ??BatteryControl_1\r
+    173                                        }\r
+    174                                }\r
+    175                        }\r
+    176                }\r
+   \                     ??BatteryControl_5:\r
+   \   00000062   9583               INC     R24\r
+   \   00000064   CFE5               RJMP    ??BatteryControl_3\r
+    177          \r
+    178                // If we end up here, one or two batteries are found and fully charged.\r
+    179                // Disconnect, so we don't drain them, and go to sleep.\r
+    180                DisableBatteries();\r
+   \                     ??BatteryControl_4:\r
+   \   00000066   ....               RCALL   DisableBatteries\r
+    181          \r
+    182                return(ST_SLEEP);\r
+   \   00000068   E208               LDI     R16, 40\r
+   \                     ??BatteryControl_1:\r
+   \   0000006A   E0E3               LDI     R30, 3\r
+   \   0000006C   ....               RJMP    ?EPILOGUE_B3_L09\r
+    183          }\r
+    184          \r
+    185          \r
+    186          /*! \brief Start running on batteries\r
+    187           *\r
+    188           * \todo Run on batteries, if battery voltage high enough.\r
+    189           * \todo Jump here when mains voltage drops below threshold\r
+    190           *\r
+    191           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    192          unsigned char Discharge(unsigned char inp)\r
+   \                     Discharge:\r
+    193          {\r
+   \   00000000   2F10               MOV     R17, R16\r
+    194                return(ST_BATCON);  // Supply voltage restored, start charging\r
+   \   00000002   E104               LDI     R16, 20\r
+   \   00000004   9508               RET\r
+    195          }\r
+    196          \r
+    197          \r
+    198          /*! \brief Sleeps until either battery needs charging\r
+    199           *\r
+    200           * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
+    201           * connected batteries are both charged, the function will loop. If not, it's\r
+    202           * back to ST_BATCON.\r
+    203           *\r
+    204           * \param inp Not used.\r
+    205           *\r
+    206           * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
+    207           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    208          unsigned char Sleep(unsigned char inp)\r
+   \                     `Sleep`:\r
+    209          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE2_L09\r
+   \   00000002   2F90               MOV     R25, R16\r
+    210                unsigned char i;\r
+    211          \r
+    212                do {\r
+    213                        Doze();               // Take a nap (~8 seconds).\r
+   \                     ??Sleep_0:\r
+   \   00000004   ....               RCALL   Doze\r
+    214          \r
+    215                        // If any batteries need charging, go to ST_BATCON.\r
+    216                        // Otherwise, keep sleeping.\r
+    217                        for (i = 0; i < 2; i++) {\r
+   \   00000006   E080               LDI     R24, 0\r
+   \                     ??Sleep_1:\r
+   \   00000008   3082               CPI     R24, 2\r
+   \   0000000A   F478               BRCC    ??Sleep_2\r
+    218                                EnableBattery(i);\r
+   \   0000000C   2F08               MOV     R16, R24\r
+   \   0000000E   ....               RCALL   EnableBattery\r
+    219                                ADC_Wait();\r
+   \   00000010   ....               RCALL   ADC_Wait\r
+    220                                if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
+   \   00000012   ....               RCALL   BatteryStatusRefresh\r
+   \   00000014   2300               TST     R16\r
+   \   00000016   F039               BREQ    ??Sleep_3\r
+   \   00000018   ....               LDI     R30, LOW(BattData)\r
+   \   0000001A   ....               LDI     R31, (BattData) >> 8\r
+   \   0000001C   8100               LD      R16, Z\r
+   \   0000001E   FD01               SBRC    R16, 1\r
+   \   00000020   C002               RJMP    ??Sleep_3\r
+    221                                        return(ST_BATCON);\r
+   \   00000022   E104               LDI     R16, 20\r
+   \   00000024   C004               RJMP    ??Sleep_4\r
+   \                     ??Sleep_3:\r
+   \   00000026   9583               INC     R24\r
+   \   00000028   CFEF               RJMP    ??Sleep_1\r
+    222                                }\r
+    223                        }\r
+    224                        \r
+    225                        DisableBatteries();  // Disable both batteries before Doze()!\r
+   \                     ??Sleep_2:\r
+   \   0000002A   ....               RCALL   DisableBatteries\r
+    226                } while (TRUE);\r
+   \   0000002C   CFEB               RJMP    ??Sleep_0\r
+   \                     ??Sleep_4:\r
+   \   0000002E   E0E2               LDI     R30, 2\r
+   \   00000030   ....               RJMP    ?EPILOGUE_B2_L09\r
+    227          }\r
+    228          \r
+    229          \r
+    230          /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
+    231           *\r
+    232           * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
+    233           * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
+    234           * On wakeup, ADC is re-enabled.\r
+    235           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    236          void Doze(void)\r
+   \                     Doze:\r
+    237          {\r
+    238                // Wait for this ADC cycle to complete, then halt after the next one.\r
+    239                ADC_Wait();\r
+   \   00000000   ....               RCALL   ADC_Wait\r
+    240                ADCS.Halt = TRUE;\r
+   \   00000002   ....               LDI     R30, LOW(ADCS)\r
+   \   00000004   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000006   8100               LD      R16, Z\r
+   \   00000008   6800               ORI     R16, 0x80\r
+   \   0000000A   8300               ST      Z, R16\r
+    241                ADCS.Flag = FALSE;\r
+   \   0000000C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000000E   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000010   8100               LD      R16, Z\r
+   \   00000012   7D0F               ANDI    R16, 0xDF\r
+   \   00000014   8300               ST      Z, R16\r
+    242                \r
+    243                do {\r
+    244                } while (ADCS.Flag == FALSE);    \r
+   \                     ??Doze_0:\r
+   \   00000016   ....               LDI     R30, LOW(ADCS)\r
+   \   00000018   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000001A   8100               LD      R16, Z\r
+   \   0000001C   FF05               SBRS    R16, 5\r
+   \   0000001E   CFFB               RJMP    ??Doze_0\r
+    245                \r
+    246                WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
+   \   00000020   E201               LDI     R16, 33\r
+   \   00000022   BD01               OUT     0x21, R16\r
+    247                WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
+   \   00000024   B501               IN      R16, 0x21\r
+   \   00000026   6C08               ORI     R16, 0xC8\r
+   \   00000028   BD01               OUT     0x21, R16\r
+    248                MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
+   \   0000002A   B705               IN      R16, 0x35\r
+   \   0000002C   6308               ORI     R16, 0x38\r
+   \   0000002E   BF05               OUT     0x35, R16\r
+    249                __sleep();                              // Go to sleep, wake up by WDT.\r
+   \   00000030   9588               SLEEP\r
+    250                \r
+    251                __watchdog_reset();                     // Clear watchdog reset flag.\r
+   \   00000032   95A8               WDR\r
+    252                MCUSR &= ~(1<<WDRF);          \r
+   \   00000034   B704               IN      R16, 0x34\r
+   \   00000036   7F07               ANDI    R16, 0xF7\r
+   \   00000038   BF04               OUT     0x34, R16\r
+    253                WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
+   \   0000003A   B501               IN      R16, 0x21\r
+   \   0000003C   6108               ORI     R16, 0x18\r
+   \   0000003E   BD01               OUT     0x21, R16\r
+    254                WDTCR = 0;                              // Turn off watchdog.\r
+   \   00000040   E000               LDI     R16, 0\r
+   \   00000042   BD01               OUT     0x21, R16\r
+    255                \r
+    256                ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
+   \   00000044   ....               LDI     R30, LOW(ADCS)\r
+   \   00000046   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000048   8100               LD      R16, Z\r
+   \   0000004A   770F               ANDI    R16, 0x7F\r
+   \   0000004C   8300               ST      Z, R16\r
+    257                ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
+   \   0000004E   B106               IN      R16, 0x06\r
+   \   00000050   6C00               ORI     R16, 0xC0\r
+   \   00000052   B906               OUT     0x06, R16\r
+    258                \r
+    259                // Wait for this cycle to complete.\r
+    260                ADC_Wait();                             \r
+   \   00000054   ....               RCALL   ADC_Wait\r
+    261          }\r
+   \   00000056   9508               RET\r
+   \   00000058                      REQUIRE _A_MCUCR\r
+   \   00000058                      REQUIRE _A_MCUSR\r
+   \   00000058                      REQUIRE _A_WDTCR\r
+   \   00000058                      REQUIRE _A_ADCSRA\r
+    262          \r
+    263          \r
+    264          /*! \brief Handles errors\r
+    265           *\r
+    266           * Stops PWM output and disables batteries. The function then goes into a loop\r
+    267           * that starts with a call to Doze(), then attempts to handle each error. The\r
+    268           * loop will reiterate until all flags are cleared.\n\r
+    269           * The charger will reinitialize after this.\r
+    270           *\r
+    271           * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
+    272           * If unsuccessful, the error flag will now have been set again.\n\r
+    273           *\r
+    274           * If there are no valid batteries, the loop will simply reiterate until a\r
+    275           * valid battery is found. The error flag will then be cleared.\n\r
+    276           *\r
+    277           * In the case of PWM controller or battery temperature errors, the error\r
+    278           * flag is simply cleared. This is because the problem may have gone away during\r
+    279           * Doze(), or after reinitializing.\n\r
+    280           *\r
+    281           * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
+    282           * and change batteries before clearing the error flag.\r
+    283           *\r
+    284           * \param inp Not used.\r
+    285           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    286          unsigned char Error(unsigned char inp)\r
+   \                     Error:\r
+    287                {\r
+   \   00000000   ....               RCALL   ?PROLOGUE2_L09\r
+   \   00000002   2F90               MOV     R25, R16\r
+    288                unsigned char i;\r
+    289                \r
+    290                PWM_Stop();           // Stop charging.\r
+   \   00000004   ....               RCALL   PWM_Stop\r
+    291                DisableBatteries();   // Disable all loads.\r
+   \   00000006   ....               RCALL   DisableBatteries\r
+    292                \r
+    293                do {\r
+    294                        Doze();           // Take a nap.\r
+   \                     ??Error_0:\r
+   \   00000008   ....               RCALL   Doze\r
+    295          \r
+    296                        // For each bit in ErrorFlags, starting with LSB, handle\r
+    297                        // associated error, if the flag is set.\r
+    298                        for (i = 0x01; i!=0; i<<=1) {\r
+   \   0000000A   E081               LDI     R24, 1\r
+   \                     ??Error_1:\r
+   \   0000000C   2388               TST     R24\r
+   \   0000000E   F409               BRNE    $+2+2\r
+   \   00000010   C057               RJMP    ??Error_2\r
+    299                                if(i & ErrorFlags) {\r
+   \   00000012   9100....           LDS     R16, ErrorFlags\r
+   \   00000016   2308               AND     R16, R24\r
+   \   00000018   2300               TST     R16\r
+   \   0000001A   F409               BRNE    $+2+2\r
+   \   0000001C   C04F               RJMP    ??Error_3\r
+    300                                        switch (i) {\r
+   \   0000001E   2F08               MOV     R16, R24\r
+   \   00000020   5001               SUBI    R16, 1\r
+   \   00000022   F049               BREQ    ??Error_4\r
+   \   00000024   950A               DEC     R16\r
+   \   00000026   F081               BREQ    ??Error_5\r
+   \   00000028   5002               SUBI    R16, 2\r
+   \   0000002A   F111               BREQ    ??Error_6\r
+   \   0000002C   5004               SUBI    R16, 4\r
+   \   0000002E   F141               BREQ    ??Error_7\r
+   \   00000030   5008               SUBI    R16, 8\r
+   \   00000032   F171               BREQ    ??Error_8\r
+   \   00000034   C043               RJMP    ??Error_3\r
+    301                                        \r
+    302                                        case  ERR_JUMPER_MISMATCH:\r
+    303                                                // Clear flag & recheck.\r
+    304                                                ErrorFlags &= ~i;\r
+   \                     ??Error_4:\r
+   \   00000036   2F08               MOV     R16, R24\r
+   \   00000038   9500               COM     R16\r
+   \   0000003A   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   0000003C   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   0000003E   8110               LD      R17, Z\r
+   \   00000040   2310               AND     R17, R16\r
+   \   00000042   8310               ST      Z, R17\r
+    305                                                JumperCheck();\r
+   \   00000044   ....               RCALL   JumperCheck\r
+   \   00000046   C03A               RJMP    ??Error_3\r
+    306                                        break;\r
+    307          \r
+    308          \r
+    309                                        case  ERR_NO_BATTERIES_ENABLED:\r
+    310                                                // Clear if any battery gets enabled.\r
+    311                                                if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {\r
+   \                     ??Error_5:\r
+   \   00000048   ....               LDI     R20, LOW(BattControl)\r
+   \   0000004A   ....               LDI     R21, (BattControl) >> 8\r
+   \   0000004C   ....               RCALL   __eeget8_16\r
+   \   0000004E   7001               ANDI    R16, 0x01\r
+   \   00000050   2300               TST     R16\r
+   \   00000052   F431               BRNE    ??Error_9\r
+   \   00000054   ....               LDI     R20, LOW((BattControl + 1))\r
+   \   00000056   ....               LDI     R21, HIGH((BattControl + 1))\r
+   \   00000058   ....               RCALL   __eeget8_16\r
+   \   0000005A   7001               ANDI    R16, 0x01\r
+   \   0000005C   2300               TST     R16\r
+   \   0000005E   F171               BREQ    ??Error_3\r
+    312                                                                ErrorFlags &= ~i;\r
+   \                     ??Error_9:\r
+   \   00000060   2F08               MOV     R16, R24\r
+   \   00000062   9500               COM     R16\r
+   \   00000064   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   00000066   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   00000068   8110               LD      R17, Z\r
+   \   0000006A   2310               AND     R17, R16\r
+   \   0000006C   8310               ST      Z, R17\r
+   \   0000006E   C026               RJMP    ??Error_3\r
+    313                                                }\r
+    314                                        break;\r
+    315          \r
+    316          \r
+    317                                        case  ERR_PWM_CONTROL:\r
+    318                                                // Clear flag.\r
+    319                                                ErrorFlags &= ~i;\r
+   \                     ??Error_6:\r
+   \   00000070   2F08               MOV     R16, R24\r
+   \   00000072   9500               COM     R16\r
+   \   00000074   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   00000076   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   00000078   8110               LD      R17, Z\r
+   \   0000007A   2310               AND     R17, R16\r
+   \   0000007C   8310               ST      Z, R17\r
+   \   0000007E   C01E               RJMP    ??Error_3\r
+    320                                        break;\r
+    321          \r
+    322          \r
+    323                                        case  ERR_BATTERY_TEMPERATURE:\r
+    324                                                // Clear flag.\r
+    325                                                ErrorFlags &= ~i;\r
+   \                     ??Error_7:\r
+   \   00000080   2F08               MOV     R16, R24\r
+   \   00000082   9500               COM     R16\r
+   \   00000084   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   00000086   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   00000088   8110               LD      R17, Z\r
+   \   0000008A   2310               AND     R17, R16\r
+   \   0000008C   8310               ST      Z, R17\r
+   \   0000008E   C016               RJMP    ??Error_3\r
+    326                                        break;\r
+    327          \r
+    328          \r
+    329                                        case  ERR_BATTERY_EXHAUSTED:\r
+    330                                                // Try the other battery.\r
+    331                                                BattData.Exhausted = FALSE;\r
+   \                     ??Error_8:\r
+   \   00000090   ....               LDI     R30, LOW(BattData)\r
+   \   00000092   ....               LDI     R31, (BattData) >> 8\r
+   \   00000094   8100               LD      R16, Z\r
+   \   00000096   7F07               ANDI    R16, 0xF7\r
+   \   00000098   8300               ST      Z, R16\r
+    332                                                BattActive = (BattActive + 1) % 2;\r
+   \   0000009A   91E0....           LDS     R30, BattActive\r
+   \   0000009E   E0F0               LDI     R31, 0\r
+   \   000000A0   9631               ADIW    R31:R30, 1\r
+   \   000000A2   018F               MOVW    R17:R16, R31:R30\r
+   \   000000A4   E042               LDI     R20, 2\r
+   \   000000A6   E050               LDI     R21, 0\r
+   \   000000A8   ....               RCALL   ?SS_DIVMOD_L02\r
+   \   000000AA   9340....           STS     BattActive, R20\r
+    333                                                ErrorFlags &= ~i;\r
+   \   000000AE   2F08               MOV     R16, R24\r
+   \   000000B0   9500               COM     R16\r
+   \   000000B2   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   000000B4   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   000000B6   8110               LD      R17, Z\r
+   \   000000B8   2310               AND     R17, R16\r
+   \   000000BA   8310               ST      Z, R17\r
+    334                                        break;\r
+    335          \r
+    336                                                \r
+    337                                        default:\r
+    338                                        break;\r
+    339                                        }\r
+    340                                }\r
+    341                        }\r
+   \                     ??Error_3:\r
+   \   000000BC   0F88               LSL     R24\r
+   \   000000BE   CFA6               RJMP    ??Error_1\r
+    342                } while (ErrorFlags);\r
+   \                     ??Error_2:\r
+   \   000000C0   9100....           LDS     R16, ErrorFlags\r
+   \   000000C4   2300               TST     R16\r
+   \   000000C6   F009               BREQ    $+2+2\r
+   \   000000C8   CF9F               RJMP    ??Error_0\r
+    343          \r
+    344                return(ST_INIT);\r
+   \   000000CA   E00A               LDI     R16, 10\r
+   \   000000CC   E0E2               LDI     R30, 2\r
+   \   000000CE   ....               RJMP    ?EPILOGUE_B2_L09\r
+    345          }\r
+    346          \r
+    347          \r
+    348          /*! \brief Sets the specified error-flag and saves the current state\r
+    349           *\r
+    350           * Updates \ref ErrorFlags and \ref ErrorState.\r
+    351           *\r
+    352           * \note Error flags are specified in statefunc.h.\r
+    353           *\r
+    354           * \param Flag Specifies what error to flag.\r
+    355           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    356          void SetErrorFlag(unsigned char Flag)\r
+   \                     SetErrorFlag:\r
+    357          {\r
+    358                ErrorFlags |= Flag;\r
+   \   00000000   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   00000002   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   00000004   8110               LD      R17, Z\r
+   \   00000006   2B10               OR      R17, R16\r
+   \   00000008   8310               ST      Z, R17\r
+    359                ErrorState = CurrentState;\r
+   \   0000000A   9110....           LDS     R17, CurrentState\r
+   \   0000000E   9310....           STS     ErrorState, R17\r
+    360          }\r
+   \   00000012   9508               RET\r
+    361          \r
+    362          \r
+    363          /*! \brief Checks on-board jumpers.\r
+    364           *\r
+    365           * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
+    366           * increasing the duty cycle until conditioned output voltage equals conditioned\r
+    367           * input voltage. At low PWM duty and no load buck output should be zero and,\r
+    368           * when increasing PWM duty, should quickly jump to steady state output roughly\r
+    369           * equal to input voltage. Will disable and leave disabled all batteries.\r
+    370           *\r
+    371           * \retval FALSE If jumper or load mismatch.\r
+    372           * \retval TRUE If everything OK.\r
+    373           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    374          unsigned char JumperCheck(void)\r
+   \                     JumperCheck:\r
+    375          {\r
+    376                 DisableBatteries();       // Disconnect, or loads may be destroyed!\r
+   \   00000000   ....               RCALL   DisableBatteries\r
+    377                 \r
+    378                 PWM_Start();              // Start PWM (controls the buck charger).\r
+   \   00000002   ....               RCALL   PWM_Start\r
+    379                \r
+    380                 // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
+    381                 Time_Set(TIMER_GEN,0,1,0);\r
+   \   00000004   E040               LDI     R20, 0\r
+   \   00000006   E011               LDI     R17, 1\r
+   \   00000008   E020               LDI     R18, 0\r
+   \   0000000A   E030               LDI     R19, 0\r
+   \   0000000C   E002               LDI     R16, 2\r
+   \   0000000E   ....               RCALL   Time_Set\r
+    382                \r
+    383                do {\r
+    384                        // If the PWM output voltage saturates the ADC, stop PWM output and\r
+    385                        // report a failure.\r
+    386                        if (ADCS.rawVBAT == 1023) {\r
+   \                     ??JumperCheck_0:\r
+   \   00000010   ....               LDI     R30, LOW(ADCS)\r
+   \   00000012   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000014   8106               LDD     R16, Z+6\r
+   \   00000016   8117               LDD     R17, Z+7\r
+   \   00000018   3F0F               CPI     R16, 255\r
+   \   0000001A   E023               LDI     R18, 3\r
+   \   0000001C   0712               CPC     R17, R18\r
+   \   0000001E   F419               BRNE    ??JumperCheck_1\r
+    387                                PWM_Stop();\r
+   \   00000020   ....               RCALL   PWM_Stop\r
+    388                                return(FALSE);\r
+   \   00000022   E000               LDI     R16, 0\r
+   \   00000024   9508               RET\r
+    389                        }\r
+    390          \r
+    391                        // If the absolute difference between measured (VIN - VBAT) and the\r
+    392                        // typical value are below our set maximum, everything is OK.\r
+    393                        if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+    394                                             VIN_VBAT_DIFF_MAX ) {\r
+   \                     ??JumperCheck_1:\r
+   \   00000026   ....               LDI     R30, LOW(ADCS)\r
+   \   00000028   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000002A   8500               LDD     R16, Z+8\r
+   \   0000002C   8511               LDD     R17, Z+9\r
+   \   0000002E   5508               SUBI    R16, 88\r
+   \   00000030   4012               SBCI    R17, 2\r
+   \   00000032   ....               LDI     R30, LOW(ADCS)\r
+   \   00000034   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000036   8522               LDD     R18, Z+10\r
+   \   00000038   8533               LDD     R19, Z+11\r
+   \   0000003A   1B02               SUB     R16, R18\r
+   \   0000003C   0B13               SBC     R17, R19\r
+   \   0000003E   ....               RCALL   abs\r
+   \   00000040   3F04               CPI     R16, 244\r
+   \   00000042   E021               LDI     R18, 1\r
+   \   00000044   0712               CPC     R17, R18\r
+   \   00000046   F41C               BRGE    ??JumperCheck_2\r
+    395                                         \r
+    396                                PWM_Stop();\r
+   \   00000048   ....               RCALL   PWM_Stop\r
+    397                                return(TRUE);\r
+   \   0000004A   E001               LDI     R16, 1\r
+   \   0000004C   9508               RET\r
+    398                        }\r
+    399          \r
+    400                        // Charge current is too high -> check load and jumper J405 and J406.\r
+    401                        if (abs(ADCS.IBAT) > 100) {\r
+   \                     ??JumperCheck_2:\r
+   \   0000004E   ....               LDI     R30, LOW(ADCS)\r
+   \   00000050   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000052   8504               LDD     R16, Z+12\r
+   \   00000054   8515               LDD     R17, Z+13\r
+   \   00000056   ....               RCALL   abs\r
+   \   00000058   3605               CPI     R16, 101\r
+   \   0000005A   E020               LDI     R18, 0\r
+   \   0000005C   0712               CPC     R17, R18\r
+   \   0000005E   F01C               BRLT    ??JumperCheck_3\r
+    402                                PWM_Stop();\r
+   \   00000060   ....               RCALL   PWM_Stop\r
+    403                                return(FALSE);\r
+   \   00000062   E000               LDI     R16, 0\r
+   \   00000064   9508               RET\r
+    404                        }\r
+    405          \r
+    406                        // If the PWM output can't be increased high enough -> check jumpers\r
+    407                        // J400-J404, J407 and J408.\r
+    408                        if (!PWM_IncrementDutyCycle()) {\r
+   \                     ??JumperCheck_3:\r
+   \   00000066   ....               RCALL   PWM_IncrementDutyCycle\r
+   \   00000068   2300               TST     R16\r
+   \   0000006A   F419               BRNE    ??JumperCheck_4\r
+    409                                PWM_Stop();\r
+   \   0000006C   ....               RCALL   PWM_Stop\r
+    410                                return(FALSE);\r
+   \   0000006E   E000               LDI     R16, 0\r
+   \   00000070   9508               RET\r
+    411                        }\r
+    412                        \r
+    413                // Wait for ADC conversions to complete\r
+    414                        ADC_Wait();\r
+   \                     ??JumperCheck_4:\r
+   \   00000072   ....               RCALL   ADC_Wait\r
+    415                } while (Time_Left(TIMER_GEN));\r
+   \   00000074   E002               LDI     R16, 2\r
+   \   00000076   ....               RCALL   Time_Left\r
+   \   00000078   2300               TST     R16\r
+   \   0000007A   F651               BRNE    ??JumperCheck_0\r
+    416                \r
+    417          \r
+    418                // If we end up here, the measurements took too long.\r
+    419                PWM_Stop();\r
+   \   0000007C   ....               RCALL   PWM_Stop\r
+    420                return(FALSE);\r
+   \   0000007E   E000               LDI     R16, 0\r
+   \   00000080   9508               RET\r
+    421          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function                    CSTACK RSTACK\r
+     --------                    ------ ------\r
+     BatteryControl                  3      4\r
+       -> JumperCheck                3      2\r
+       -> SetErrorFlag               3      2\r
+       -> EnableBattery              3      2\r
+       -> ADC_Wait                   3      2\r
+       -> BatteryStatusRefresh       3      2\r
+       -> BatteryDataRefresh         3      2\r
+       -> DisableBatteries           3      2\r
+     Discharge                       0      2\r
+     Doze                            0      2\r
+       -> ADC_Wait                   0      2\r
+       -> ADC_Wait                   0      2\r
+     Error                           2      4\r
+       -> PWM_Stop                   2      2\r
+       -> DisableBatteries           2      2\r
+       -> Doze                       2      2\r
+       -> JumperCheck                2      2\r
+     Initialize                      4      4\r
+       -> OWI_Init                   4      2\r
+       -> DisableBatteries           4      2\r
+       -> SPI_Init                   4      2\r
+       -> ADC_Init                   4      2\r
+       -> Time_Init                  4      2\r
+       -> EnableBattery              4      2\r
+       -> ADC_Wait                   4      2\r
+       -> BatteryStatusRefresh       4      2\r
+       -> DisableBatteries           4      2\r
+     JumperCheck                     0      2\r
+       -> DisableBatteries           0      2\r
+       -> PWM_Start                  0      2\r
+       -> Time_Set                   0      2\r
+       -> PWM_Stop                   0      2\r
+       -> abs                        0      2\r
+       -> PWM_Stop                   0      2\r
+       -> abs                        0      2\r
+       -> PWM_Stop                   0      2\r
+       -> PWM_IncrementDutyCycle     0      2\r
+       -> PWM_Stop                   0      2\r
+       -> ADC_Wait                   0      2\r
+       -> Time_Left                  0      2\r
+       -> PWM_Stop                   0      2\r
+     SetErrorFlag                    0      2\r
+     Sleep                           2      2\r
+       -> Doze                       2      2\r
+       -> EnableBattery              2      2\r
+       -> ADC_Wait                   2      2\r
+       -> BatteryStatusRefresh       2      2\r
+       -> DisableBatteries           2      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     _A_MCUCR          1\r
+     _A_MCUSR          1\r
+     _A_CLKPR          1\r
+     _A_WDTCR          1\r
+     _A_DDRB           1\r
+     _A_ADCSRA         1\r
+     ErrorFlags        1\r
+     ErrorState        1\r
+     Initialize      122\r
+     BatteryControl  110\r
+     Discharge         6\r
+     Sleep            50\r
+     Doze             88\r
+     Error           208\r
+     SetErrorFlag     20\r
+     JumperCheck     130\r
+      Others           6\r
+\r
\r
+   6 bytes in segment ABSOLUTE\r
+ 734 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment NEAR_Z\r
\r
+ 734 bytes of CODE memory (+ 6 bytes shared)\r
+   2 bytes of DATA memory (+ 6 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/statefunc.s90 b/BaseTinyFirmware/IAR/Debug/List/statefunc.s90
new file mode 100644 (file)
index 0000000..4c8dfd3
--- /dev/null
@@ -0,0 +1,1001 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:39 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c         /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c         /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\statefun /\r
+//                    c.s90                                                   /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME statefunc\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B2_L09\r
+        EXTERN ?EPILOGUE_B3_L09\r
+        EXTERN ?EPILOGUE_B4_L09\r
+        EXTERN ?PROLOGUE2_L09\r
+        EXTERN ?PROLOGUE3_L09\r
+        EXTERN ?PROLOGUE4_L09\r
+        EXTERN ?SS_DIVMOD_L02\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC BatteryControl\r
+        PUBLIC Discharge\r
+        PUBLIC Doze\r
+        PUBLIC Error\r
+        PUBLIC ErrorFlags\r
+        PUBLIC ErrorState\r
+        PUBLIC Initialize\r
+        PUBLIC JumperCheck\r
+        PUBLIC SetErrorFlag\r
+        PUBLIC `Sleep`\r
+        PUBWEAK _A_ADCSRA\r
+        PUBWEAK _A_CLKPR\r
+        PUBWEAK _A_DDRB\r
+        PUBWEAK _A_MCUCR\r
+        PUBWEAK _A_MCUSR\r
+        PUBWEAK _A_WDTCR\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN OWI_Init\r
+        EXTERN DisableBatteries\r
+        EXTERN SPI_Init\r
+        EXTERN ADC_Init\r
+        EXTERN Time_Init\r
+        EXTERN EnableBattery\r
+        EXTERN ADC_Wait\r
+        EXTERN BatteryStatusRefresh\r
+        EXTERN BatteryDataRefresh\r
+        EXTERN PWM_Stop\r
+        EXTERN PWM_Start\r
+        EXTERN Time_Set\r
+        EXTERN abs\r
+        EXTERN PWM_IncrementDutyCycle\r
+        EXTERN Time_Left\r
+        EXTERN ADCS\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+        EXTERN BattEEPROM\r
+        EXTERN CurrentState\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      State functions\r
+//    6  *\r
+//    7  *      Contains the functions related to the states defined in menu.h.\n\r
+//    8  *      Also contains related functions, i.e. for checking jumpers, setting\r
+//    9  *      error flags and "dozing".\r
+//   10  *\r
+//   11  *      \note The state function Charge() is in a separate file since it\r
+//   12  *      should easily be changed with regard to battery type.\r
+//   13  *\r
+//   14  * \par Application note:\r
+//   15  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   16  *      AVR463: Charging NiMH Batteries with BC100\r
+//   17  *\r
+//   18  * \par Documentation\r
+//   19  *      For comprehensive code documentation, supported compilers, compiler \r
+//   20  *      settings and supported devices see readme.html\r
+//   21  *\r
+//   22  * \author\r
+//   23  *      Atmel Corporation: http://www.atmel.com \n\r
+//   24  *      Support email: avr@atmel.com\r
+//   25  *\r
+//   26  * \r
+//   27  * $Name$\r
+//   28  * $Revision: 2299 $\r
+//   29  * $RCSfile$\r
+//   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
+//   31  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   32  ******************************************************************************/\r
+//   33 \r
+//   34 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,055H\r
+// <unnamed> volatile __io _A_MCUCR\r
+_A_MCUCR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,054H\r
+// <unnamed> volatile __io _A_MCUSR\r
+_A_MCUSR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,048H\r
+// <unnamed> volatile __io _A_CLKPR\r
+_A_CLKPR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,041H\r
+// <unnamed> volatile __io _A_WDTCR\r
+_A_WDTCR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,037H\r
+// <unnamed> volatile __io _A_DDRB\r
+_A_DDRB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,026H\r
+// <unnamed> volatile __io _A_ADCSRA\r
+_A_ADCSRA:\r
+        DS 1\r
+//   35 #include <inavr.h>\r
+//   36 #include <stdlib.h>\r
+//   37 \r
+//   38 #include "structs.h"\r
+//   39 #include "enums.h"\r
+//   40 \r
+//   41 #include "ADC.h"\r
+//   42 #include "statefunc.h"\r
+//   43 #include "battery.h"\r
+//   44 #include "charge.h"\r
+//   45 #include "main.h"\r
+//   46 #include "menu.h"\r
+//   47 #include "OWI.h"\r
+//   48 #include "PWM.h"\r
+//   49 #include "time.h"\r
+//   50 #include "USI.h"\r
+//   51 \r
+//   52 \r
+//   53 //******************************************************************************\r
+//   54 // Variables\r
+//   55 //******************************************************************************\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   56 unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
+ErrorFlags:\r
+        DS 1\r
+//   57                            //!< \note See statefunc.h for definitions of flags.\r
+//   58 \r
+//   59 //! \brief Holds the state in which latest error flag was set.\r
+//   60 //! \note See menu.h for definitions of states.\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   61 unsigned char ErrorState;\r
+ErrorState:\r
+        DS 1\r
+//   62 \r
+//   63 \r
+//   64 //******************************************************************************\r
+//   65 // Functions\r
+//   66 //******************************************************************************\r
+//   67 /*! \brief Initialization\r
+//   68  *\r
+//   69  * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
+//   70  * - Initializes the one-wire interface\r
+//   71  * - Clears on-chip EEPROM\r
+//   72  * - Sets battery enable pins as outputs, then disables batteries\r
+//   73  * - Initializes SPI according to \ref SPIMODE\r
+//   74  * - Initializes ADC\r
+//   75  * - Initializes timers\r
+//   76  * - Reads battery data from both battery inputs (via ADC)\r
+//   77  * - Disables batteries again\r
+//   78  * - Sets battery A as the current one (\ref BattActive = 0)\r
+//   79  * - Clears ErrorFlags\r
+//   80  *\r
+//   81  * \param inp Not used.\r
+//   82  *\r
+//   83  * \retval ST_BATCON Next state in the sequence.\r
+//   84  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   85 unsigned char Initialize(unsigned char inp)\r
+Initialize:\r
+//   86 {\r
+        RCALL   ?PROLOGUE4_L09\r
+        MOV     R27, R16\r
+//   87        unsigned char i, page;\r
+//   88 \r
+//   89        // Disable interrupts while setting prescaler.\r
+//   90        __disable_interrupt();\r
+        CLI\r
+//   91        \r
+//   92        CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
+        LDI     R16, 128\r
+        OUT     0x28, R16\r
+//   93        CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
+        LDI     R16, 0\r
+        OUT     0x28, R16\r
+//   94        \r
+//   95        // Init 1-Wire(R) interface.\r
+//   96        OWI_Init(OWIBUS);\r
+        LDI     R16, 1\r
+        RCALL   OWI_Init\r
+//   97        \r
+//   98        // Clear on-chip EEPROM.\r
+//   99        for (page = 0; page < 4; page++)        {\r
+        LDI     R25, 0\r
+??Initialize_0:\r
+        CPI     R25, 4\r
+        BRCC    ??Initialize_1\r
+//  100                for (i = 0; i < 32; i++) {\r
+        LDI     R24, 0\r
+??Initialize_2:\r
+        CPI     R24, 32\r
+        BRCC    ??Initialize_3\r
+//  101                        BattEEPROM[page][i] = 0;\r
+        LDI     R26, 0\r
+        MOV     R20, R25\r
+        LDI     R21, 0\r
+        LDI     R16, 32\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LDI     R20, LOW(BattEEPROM)\r
+        LDI     R21, (BattEEPROM) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R24\r
+        LDI     R17, 0\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R26\r
+        RCALL   __eeput8_16\r
+//  102                }\r
+        INC     R24\r
+        RJMP    ??Initialize_2\r
+//  103        }\r
+??Initialize_3:\r
+        INC     R25\r
+        RJMP    ??Initialize_0\r
+//  104 \r
+//  105        DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
+??Initialize_1:\r
+        LDI     R16, 48\r
+        OUT     0x17, R16\r
+//  106        DisableBatteries();\r
+        RCALL   DisableBatteries\r
+//  107        SPI_Init(SPIMODE);\r
+        LDI     R16, 0\r
+        RCALL   SPI_Init\r
+//  108        ADC_Init();\r
+        RCALL   ADC_Init\r
+//  109        Time_Init();\r
+        RCALL   Time_Init\r
+//  110 \r
+//  111        // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
+//  112        for (i = 0; i < 2; i++) {\r
+        LDI     R24, 0\r
+??Initialize_4:\r
+        CPI     R24, 2\r
+        BRCC    ??Initialize_5\r
+//  113                EnableBattery(i);\r
+        MOV     R16, R24\r
+        RCALL   EnableBattery\r
+//  114                ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  115                BatteryStatusRefresh();\r
+        RCALL   BatteryStatusRefresh\r
+//  116        }\r
+        INC     R24\r
+        RJMP    ??Initialize_4\r
+//  117     \r
+//  118        DisableBatteries();\r
+??Initialize_5:\r
+        RCALL   DisableBatteries\r
+//  119        \r
+//  120        BattActive = 0;               // We have to start somewhere..\r
+        LDI     R16, 0\r
+        STS     BattActive, R16\r
+//  121        ErrorFlags = 0;\r
+        LDI     R16, 0\r
+        STS     ErrorFlags, R16\r
+//  122        \r
+//  123        // Init complete! Go to ST_BATCON next.\r
+//  124        return(ST_BATCON);\r
+        LDI     R16, 20\r
+        LDI     R30, 4\r
+        RJMP    ?EPILOGUE_B4_L09\r
+        REQUIRE _A_CLKPR\r
+        REQUIRE _A_DDRB\r
+//  125 }\r
+//  126 \r
+//  127 \r
+//  128 /*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
+//  129  *\r
+//  130  * First, JumperCheck() is called. If successful, the function checks if any\r
+//  131  * valid batteries are connected and attempts to charge these, if necessary.\n\r
+//  132  * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
+//  133  * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
+//  134  * batteries. In this last case, the error is also flagged.\r
+//  135  *\r
+//  136  * \param inp Not used.\r
+//  137  *\r
+//  138  * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
+//  139  * no valid batteries.\r
+//  140  * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
+//  141  * charged.\r
+//  142  * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
+//  143  * charged.\r
+//  144  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  145 unsigned char BatteryControl(unsigned char inp)\r
+BatteryControl:\r
+//  146 {\r
+        RCALL   ?PROLOGUE3_L09\r
+        MOV     R26, R16\r
+//  147        unsigned char i;\r
+//  148        \r
+//  149        // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
+//  150        if (!JumperCheck()) {\r
+        RCALL   JumperCheck\r
+        TST     R16\r
+        BRNE    ??BatteryControl_0\r
+//  151                return(ST_ERROR);           // Error. Exit before damage is done!\r
+        LDI     R16, 90\r
+        RJMP    ??BatteryControl_1\r
+//  152        }\r
+//  153        \r
+//  154        // If neither battery is valid, flag error and go to error state\r
+//  155        if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
+??BatteryControl_0:\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        TST     R16\r
+        BRNE    ??BatteryControl_2\r
+        LDI     R20, LOW((BattControl + 1))\r
+        LDI     R21, HIGH((BattControl + 1))\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        TST     R16\r
+        BRNE    ??BatteryControl_2\r
+//  156                SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
+        LDI     R16, 2\r
+        RCALL   SetErrorFlag\r
+//  157                \r
+//  158                return(ST_ERROR);\r
+        LDI     R16, 90\r
+        RJMP    ??BatteryControl_1\r
+//  159        }\r
+//  160 \r
+//  161        // Get ADC-readings, try to read EPROM, and start prequalification\r
+//  162        // of any uncharged battery.\r
+//  163        for (i = 0; i < 2; i++) {\r
+??BatteryControl_2:\r
+        LDI     R24, 0\r
+??BatteryControl_3:\r
+        CPI     R24, 2\r
+        BRCC    ??BatteryControl_4\r
+//  164                if (BattControl[i].Enabled) {      \r
+        LDI     R25, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R24\r
+        ADC     R21, R25\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        TST     R16\r
+        BREQ    ??BatteryControl_5\r
+//  165                        EnableBattery(i);\r
+        MOV     R16, R24\r
+        RCALL   EnableBattery\r
+//  166                        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  167 \r
+//  168                        if (BatteryStatusRefresh()) {\r
+        RCALL   BatteryStatusRefresh\r
+        TST     R16\r
+        BREQ    ??BatteryControl_5\r
+//  169                                if (!BattData.Charged) {\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        SBRC    R16, 1\r
+        RJMP    ??BatteryControl_5\r
+//  170                                        BatteryDataRefresh();\r
+        RCALL   BatteryDataRefresh\r
+//  171 \r
+//  172                                        return(ST_PREQUAL);       \r
+        LDI     R16, 30\r
+        RJMP    ??BatteryControl_1\r
+//  173                                }\r
+//  174                        }\r
+//  175                }\r
+//  176        }\r
+??BatteryControl_5:\r
+        INC     R24\r
+        RJMP    ??BatteryControl_3\r
+//  177 \r
+//  178        // If we end up here, one or two batteries are found and fully charged.\r
+//  179        // Disconnect, so we don't drain them, and go to sleep.\r
+//  180        DisableBatteries();\r
+??BatteryControl_4:\r
+        RCALL   DisableBatteries\r
+//  181 \r
+//  182        return(ST_SLEEP);\r
+        LDI     R16, 40\r
+??BatteryControl_1:\r
+        LDI     R30, 3\r
+        RJMP    ?EPILOGUE_B3_L09\r
+//  183 }\r
+//  184 \r
+//  185 \r
+//  186 /*! \brief Start running on batteries\r
+//  187  *\r
+//  188  * \todo Run on batteries, if battery voltage high enough.\r
+//  189  * \todo Jump here when mains voltage drops below threshold\r
+//  190  *\r
+//  191  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  192 unsigned char Discharge(unsigned char inp)\r
+Discharge:\r
+//  193 {\r
+        MOV     R17, R16\r
+//  194        return(ST_BATCON);  // Supply voltage restored, start charging\r
+        LDI     R16, 20\r
+        RET\r
+//  195 }\r
+//  196 \r
+//  197 \r
+//  198 /*! \brief Sleeps until either battery needs charging\r
+//  199  *\r
+//  200  * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
+//  201  * connected batteries are both charged, the function will loop. If not, it's\r
+//  202  * back to ST_BATCON.\r
+//  203  *\r
+//  204  * \param inp Not used.\r
+//  205  *\r
+//  206  * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
+//  207  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  208 unsigned char Sleep(unsigned char inp)\r
+`Sleep`:\r
+//  209 {\r
+        RCALL   ?PROLOGUE2_L09\r
+        MOV     R25, R16\r
+//  210        unsigned char i;\r
+//  211 \r
+//  212        do {\r
+//  213                Doze();               // Take a nap (~8 seconds).\r
+??Sleep_0:\r
+        RCALL   Doze\r
+//  214 \r
+//  215                // If any batteries need charging, go to ST_BATCON.\r
+//  216                // Otherwise, keep sleeping.\r
+//  217                for (i = 0; i < 2; i++) {\r
+        LDI     R24, 0\r
+??Sleep_1:\r
+        CPI     R24, 2\r
+        BRCC    ??Sleep_2\r
+//  218                        EnableBattery(i);\r
+        MOV     R16, R24\r
+        RCALL   EnableBattery\r
+//  219                        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  220                        if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
+        RCALL   BatteryStatusRefresh\r
+        TST     R16\r
+        BREQ    ??Sleep_3\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        SBRC    R16, 1\r
+        RJMP    ??Sleep_3\r
+//  221                                return(ST_BATCON);\r
+        LDI     R16, 20\r
+        RJMP    ??Sleep_4\r
+??Sleep_3:\r
+        INC     R24\r
+        RJMP    ??Sleep_1\r
+//  222                        }\r
+//  223                }\r
+//  224                \r
+//  225                DisableBatteries();  // Disable both batteries before Doze()!\r
+??Sleep_2:\r
+        RCALL   DisableBatteries\r
+//  226        } while (TRUE);\r
+        RJMP    ??Sleep_0\r
+??Sleep_4:\r
+        LDI     R30, 2\r
+        RJMP    ?EPILOGUE_B2_L09\r
+//  227 }\r
+//  228 \r
+//  229 \r
+//  230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
+//  231  *\r
+//  232  * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
+//  233  * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
+//  234  * On wakeup, ADC is re-enabled.\r
+//  235  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  236 void Doze(void)\r
+Doze:\r
+//  237 {\r
+//  238        // Wait for this ADC cycle to complete, then halt after the next one.\r
+//  239        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  240        ADCS.Halt = TRUE;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x80\r
+        ST      Z, R16\r
+//  241        ADCS.Flag = FALSE;\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xDF\r
+        ST      Z, R16\r
+//  242        \r
+//  243        do {\r
+//  244        } while (ADCS.Flag == FALSE);    \r
+??Doze_0:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        SBRS    R16, 5\r
+        RJMP    ??Doze_0\r
+//  245        \r
+//  246        WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
+        LDI     R16, 33\r
+        OUT     0x21, R16\r
+//  247        WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
+        IN      R16, 0x21\r
+        ORI     R16, 0xC8\r
+        OUT     0x21, R16\r
+//  248        MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
+        IN      R16, 0x35\r
+        ORI     R16, 0x38\r
+        OUT     0x35, R16\r
+//  249        __sleep();                              // Go to sleep, wake up by WDT.\r
+        SLEEP\r
+//  250        \r
+//  251        __watchdog_reset();                     // Clear watchdog reset flag.\r
+        WDR\r
+//  252        MCUSR &= ~(1<<WDRF);          \r
+        IN      R16, 0x34\r
+        ANDI    R16, 0xF7\r
+        OUT     0x34, R16\r
+//  253        WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
+        IN      R16, 0x21\r
+        ORI     R16, 0x18\r
+        OUT     0x21, R16\r
+//  254        WDTCR = 0;                              // Turn off watchdog.\r
+        LDI     R16, 0\r
+        OUT     0x21, R16\r
+//  255        \r
+//  256        ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0x7F\r
+        ST      Z, R16\r
+//  257        ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
+        IN      R16, 0x06\r
+        ORI     R16, 0xC0\r
+        OUT     0x06, R16\r
+//  258        \r
+//  259        // Wait for this cycle to complete.\r
+//  260        ADC_Wait();                             \r
+        RCALL   ADC_Wait\r
+//  261 }\r
+        RET\r
+        REQUIRE _A_MCUCR\r
+        REQUIRE _A_MCUSR\r
+        REQUIRE _A_WDTCR\r
+        REQUIRE _A_ADCSRA\r
+//  262 \r
+//  263 \r
+//  264 /*! \brief Handles errors\r
+//  265  *\r
+//  266  * Stops PWM output and disables batteries. The function then goes into a loop\r
+//  267  * that starts with a call to Doze(), then attempts to handle each error. The\r
+//  268  * loop will reiterate until all flags are cleared.\n\r
+//  269  * The charger will reinitialize after this.\r
+//  270  *\r
+//  271  * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
+//  272  * If unsuccessful, the error flag will now have been set again.\n\r
+//  273  *\r
+//  274  * If there are no valid batteries, the loop will simply reiterate until a\r
+//  275  * valid battery is found. The error flag will then be cleared.\n\r
+//  276  *\r
+//  277  * In the case of PWM controller or battery temperature errors, the error\r
+//  278  * flag is simply cleared. This is because the problem may have gone away during\r
+//  279  * Doze(), or after reinitializing.\n\r
+//  280  *\r
+//  281  * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
+//  282  * and change batteries before clearing the error flag.\r
+//  283  *\r
+//  284  * \param inp Not used.\r
+//  285  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  286 unsigned char Error(unsigned char inp)\r
+Error:\r
+//  287        {\r
+        RCALL   ?PROLOGUE2_L09\r
+        MOV     R25, R16\r
+//  288        unsigned char i;\r
+//  289        \r
+//  290        PWM_Stop();           // Stop charging.\r
+        RCALL   PWM_Stop\r
+//  291        DisableBatteries();   // Disable all loads.\r
+        RCALL   DisableBatteries\r
+//  292        \r
+//  293        do {\r
+//  294                Doze();           // Take a nap.\r
+??Error_0:\r
+        RCALL   Doze\r
+//  295 \r
+//  296                // For each bit in ErrorFlags, starting with LSB, handle\r
+//  297                // associated error, if the flag is set.\r
+//  298                for (i = 0x01; i!=0; i<<=1) {\r
+        LDI     R24, 1\r
+??Error_1:\r
+        TST     R24\r
+        BRNE    $+2+2\r
+        RJMP    ??Error_2\r
+//  299                        if(i & ErrorFlags) {\r
+        LDS     R16, ErrorFlags\r
+        AND     R16, R24\r
+        TST     R16\r
+        BRNE    $+2+2\r
+        RJMP    ??Error_3\r
+//  300                                switch (i) {\r
+        MOV     R16, R24\r
+        SUBI    R16, 1\r
+        BREQ    ??Error_4\r
+        DEC     R16\r
+        BREQ    ??Error_5\r
+        SUBI    R16, 2\r
+        BREQ    ??Error_6\r
+        SUBI    R16, 4\r
+        BREQ    ??Error_7\r
+        SUBI    R16, 8\r
+        BREQ    ??Error_8\r
+        RJMP    ??Error_3\r
+//  301                                \r
+//  302                                case  ERR_JUMPER_MISMATCH:\r
+//  303                                        // Clear flag & recheck.\r
+//  304                                        ErrorFlags &= ~i;\r
+??Error_4:\r
+        MOV     R16, R24\r
+        COM     R16\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+//  305                                        JumperCheck();\r
+        RCALL   JumperCheck\r
+        RJMP    ??Error_3\r
+//  306                                break;\r
+//  307 \r
+//  308 \r
+//  309                                case  ERR_NO_BATTERIES_ENABLED:\r
+//  310                                        // Clear if any battery gets enabled.\r
+//  311                                        if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {\r
+??Error_5:\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        TST     R16\r
+        BRNE    ??Error_9\r
+        LDI     R20, LOW((BattControl + 1))\r
+        LDI     R21, HIGH((BattControl + 1))\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        TST     R16\r
+        BREQ    ??Error_3\r
+//  312                                                        ErrorFlags &= ~i;\r
+??Error_9:\r
+        MOV     R16, R24\r
+        COM     R16\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+        RJMP    ??Error_3\r
+//  313                                        }\r
+//  314                                break;\r
+//  315 \r
+//  316 \r
+//  317                                case  ERR_PWM_CONTROL:\r
+//  318                                        // Clear flag.\r
+//  319                                        ErrorFlags &= ~i;\r
+??Error_6:\r
+        MOV     R16, R24\r
+        COM     R16\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+        RJMP    ??Error_3\r
+//  320                                break;\r
+//  321 \r
+//  322 \r
+//  323                                case  ERR_BATTERY_TEMPERATURE:\r
+//  324                                        // Clear flag.\r
+//  325                                        ErrorFlags &= ~i;\r
+??Error_7:\r
+        MOV     R16, R24\r
+        COM     R16\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+        RJMP    ??Error_3\r
+//  326                                break;\r
+//  327 \r
+//  328 \r
+//  329                                case  ERR_BATTERY_EXHAUSTED:\r
+//  330                                        // Try the other battery.\r
+//  331                                        BattData.Exhausted = FALSE;\r
+??Error_8:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0xF7\r
+        ST      Z, R16\r
+//  332                                        BattActive = (BattActive + 1) % 2;\r
+        LDS     R30, BattActive\r
+        LDI     R31, 0\r
+        ADIW    R31:R30, 1\r
+        MOVW    R17:R16, R31:R30\r
+        LDI     R20, 2\r
+        LDI     R21, 0\r
+        RCALL   ?SS_DIVMOD_L02\r
+        STS     BattActive, R20\r
+//  333                                        ErrorFlags &= ~i;\r
+        MOV     R16, R24\r
+        COM     R16\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        AND     R17, R16\r
+        ST      Z, R17\r
+//  334                                break;\r
+//  335 \r
+//  336                                        \r
+//  337                                default:\r
+//  338                                break;\r
+//  339                                }\r
+//  340                        }\r
+//  341                }\r
+??Error_3:\r
+        LSL     R24\r
+        RJMP    ??Error_1\r
+//  342        } while (ErrorFlags);\r
+??Error_2:\r
+        LDS     R16, ErrorFlags\r
+        TST     R16\r
+        BREQ    $+2+2\r
+        RJMP    ??Error_0\r
+//  343 \r
+//  344        return(ST_INIT);\r
+        LDI     R16, 10\r
+        LDI     R30, 2\r
+        RJMP    ?EPILOGUE_B2_L09\r
+//  345 }\r
+//  346 \r
+//  347 \r
+//  348 /*! \brief Sets the specified error-flag and saves the current state\r
+//  349  *\r
+//  350  * Updates \ref ErrorFlags and \ref ErrorState.\r
+//  351  *\r
+//  352  * \note Error flags are specified in statefunc.h.\r
+//  353  *\r
+//  354  * \param Flag Specifies what error to flag.\r
+//  355  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  356 void SetErrorFlag(unsigned char Flag)\r
+SetErrorFlag:\r
+//  357 {\r
+//  358        ErrorFlags |= Flag;\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        OR      R17, R16\r
+        ST      Z, R17\r
+//  359        ErrorState = CurrentState;\r
+        LDS     R17, CurrentState\r
+        STS     ErrorState, R17\r
+//  360 }\r
+        RET\r
+//  361 \r
+//  362 \r
+//  363 /*! \brief Checks on-board jumpers.\r
+//  364  *\r
+//  365  * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
+//  366  * increasing the duty cycle until conditioned output voltage equals conditioned\r
+//  367  * input voltage. At low PWM duty and no load buck output should be zero and,\r
+//  368  * when increasing PWM duty, should quickly jump to steady state output roughly\r
+//  369  * equal to input voltage. Will disable and leave disabled all batteries.\r
+//  370  *\r
+//  371  * \retval FALSE If jumper or load mismatch.\r
+//  372  * \retval TRUE If everything OK.\r
+//  373  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  374 unsigned char JumperCheck(void)\r
+JumperCheck:\r
+//  375 {\r
+//  376         DisableBatteries();       // Disconnect, or loads may be destroyed!\r
+        RCALL   DisableBatteries\r
+//  377         \r
+//  378         PWM_Start();              // Start PWM (controls the buck charger).\r
+        RCALL   PWM_Start\r
+//  379        \r
+//  380         // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
+//  381         Time_Set(TIMER_GEN,0,1,0);\r
+        LDI     R20, 0\r
+        LDI     R17, 1\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 2\r
+        RCALL   Time_Set\r
+//  382        \r
+//  383        do {\r
+//  384                // If the PWM output voltage saturates the ADC, stop PWM output and\r
+//  385                // report a failure.\r
+//  386                if (ADCS.rawVBAT == 1023) {\r
+??JumperCheck_0:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+6\r
+        LDD     R17, Z+7\r
+        CPI     R16, 255\r
+        LDI     R18, 3\r
+        CPC     R17, R18\r
+        BRNE    ??JumperCheck_1\r
+//  387                        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  388                        return(FALSE);\r
+        LDI     R16, 0\r
+        RET\r
+//  389                }\r
+//  390 \r
+//  391                // If the absolute difference between measured (VIN - VBAT) and the\r
+//  392                // typical value are below our set maximum, everything is OK.\r
+//  393                if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+//  394                                     VIN_VBAT_DIFF_MAX ) {\r
+??JumperCheck_1:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+8\r
+        LDD     R17, Z+9\r
+        SUBI    R16, 88\r
+        SBCI    R17, 2\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+10\r
+        LDD     R19, Z+11\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        RCALL   abs\r
+        CPI     R16, 244\r
+        LDI     R18, 1\r
+        CPC     R17, R18\r
+        BRGE    ??JumperCheck_2\r
+//  395                                 \r
+//  396                        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  397                        return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//  398                }\r
+//  399 \r
+//  400                // Charge current is too high -> check load and jumper J405 and J406.\r
+//  401                if (abs(ADCS.IBAT) > 100) {\r
+??JumperCheck_2:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+12\r
+        LDD     R17, Z+13\r
+        RCALL   abs\r
+        CPI     R16, 101\r
+        LDI     R18, 0\r
+        CPC     R17, R18\r
+        BRLT    ??JumperCheck_3\r
+//  402                        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  403                        return(FALSE);\r
+        LDI     R16, 0\r
+        RET\r
+//  404                }\r
+//  405 \r
+//  406                // If the PWM output can't be increased high enough -> check jumpers\r
+//  407                // J400-J404, J407 and J408.\r
+//  408                if (!PWM_IncrementDutyCycle()) {\r
+??JumperCheck_3:\r
+        RCALL   PWM_IncrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??JumperCheck_4\r
+//  409                        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  410                        return(FALSE);\r
+        LDI     R16, 0\r
+        RET\r
+//  411                }\r
+//  412                \r
+//  413       // Wait for ADC conversions to complete\r
+//  414                ADC_Wait();\r
+??JumperCheck_4:\r
+        RCALL   ADC_Wait\r
+//  415        } while (Time_Left(TIMER_GEN));\r
+        LDI     R16, 2\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??JumperCheck_0\r
+//  416        \r
+//  417 \r
+//  418        // If we end up here, the measurements took too long.\r
+//  419        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  420        return(FALSE);\r
+        LDI     R16, 0\r
+        RET\r
+//  421 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   6 bytes in segment ABSOLUTE\r
+// 734 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment NEAR_Z\r
+// \r
+// 734 bytes of CODE memory (+ 6 bytes shared)\r
+//   2 bytes of DATA memory (+ 6 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/time.lst b/BaseTinyFirmware/IAR/Debug/List/time.lst
new file mode 100644 (file)
index 0000000..15d2e6f
--- /dev/null
@@ -0,0 +1,512 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               12/Mar/2008  23:01:40 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\time.c               #\r
+#    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\time.c               #\r
+#                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR #\r
+#                    \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu #\r
+#                    g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li #\r
+#                    st\ --initializers_in_flash -z2 --no_cse --no_inline     #\r
+#                    --no_code_motion --no_cross_call --no_clustering         #\r
+#                    --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e            #\r
+#                    --require_prototypes -I "C:\Program Files\IAR            #\r
+#                    Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program  #\r
+#                    Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  #\r
+#                    --eeprom_size 512                                        #\r
+#    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\time.lst  #\r
+#    Object file  =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\time.r90   #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100_cal\IAR\time.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for timing\r
+      6           *\r
+      7           *      Contains functions to initialize, set, poll and stop timers.\r
+      8           *\r
+      9           * \par Application note:\r
+     10           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     11           *      AVR463: Charging NiMH Batteries with BC100\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2299 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $\r
+     26           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x59\r
+   \   <unnamed> volatile __io _A_TIMSK\r
+   \                     _A_TIMSK:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x53\r
+   \   <unnamed> volatile __io _A_TCCR0B\r
+   \                     _A_TCCR0B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x35\r
+   \   <unnamed> volatile __io _A_TCCR0A\r
+   \                     _A_TCCR0A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x33\r
+   \   <unnamed> volatile __io _A_OCR0A\r
+   \                     _A_OCR0A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x32\r
+   \   <unnamed> volatile __io _A_OCR0B\r
+   \                     _A_OCR0B:\r
+   \   00000000                      DS 1\r
+     30          #include <inavr.h>\r
+     31          \r
+     32          #include "enums.h"\r
+     33          \r
+     34          #include "main.h"\r
+     35          #include "time.h"\r
+     36          \r
+     37          \r
+     38          //******************************************************************************\r
+     39          // Variables\r
+     40          //******************************************************************************\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     41          unsigned long timeval[TIMERS];  //!< Contains the values for each timer.\r
+   \                     timeval:\r
+   \   00000000                      DS 16\r
+     42          \r
+     43          // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
+     44          //#pragma vector = TIM0_OVF_vect\r
+     45          \r
+     46          \r
+     47          //******************************************************************************\r
+     48          // Functions\r
+     49          //******************************************************************************\r
+     50          /*! \brief Interrupt service routine for timer 0 overflow\r
+     51           *\r
+     52           * Timer 0 runs at 125 kHz and compare match will occur every millisecond\r
+     53           * (125 / 125 kHz = 1.0 ms), which will result in a call to this function.\r
+     54           * When called, this function will decrement the time left for each timer,\r
+     55           * unless they are already at zero.\r
+     56           */\r
+     57          #pragma vector = TIM0_COMPA_vect\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     58          __interrupt void TICK_ISR(void)\r
+   \                     TICK_ISR:\r
+     59          {\r
+   \   00000000   93FA               ST      -Y, R31\r
+   \   00000002   93EA               ST      -Y, R30\r
+   \   00000004   920A               ST      -Y, R0\r
+   \   00000006   937A               ST      -Y, R23\r
+   \   00000008   936A               ST      -Y, R22\r
+   \   0000000A   935A               ST      -Y, R21\r
+   \   0000000C   934A               ST      -Y, R20\r
+   \   0000000E   933A               ST      -Y, R19\r
+   \   00000010   932A               ST      -Y, R18\r
+   \   00000012   931A               ST      -Y, R17\r
+   \   00000014   930A               ST      -Y, R16\r
+   \   00000016   B60F               IN      R0, 0x3F\r
+     60                unsigned char i;\r
+     61          \r
+     62                // 1 ms has passed, decrement all non-zero timers.\r
+     63                for (i = 0; i < TIMERS; i++) {\r
+   \   00000018   E000               LDI     R16, 0\r
+   \                     ??TICK_ISR_0:\r
+   \   0000001A   3004               CPI     R16, 4\r
+   \   0000001C   F540               BRCC    ??TICK_ISR_1\r
+     64                        if(timeval[i] > 0) {\r
+   \   0000001E   2F20               MOV     R18, R16\r
+   \   00000020   E030               LDI     R19, 0\r
+   \   00000022   0F22               LSL     R18\r
+   \   00000024   1F33               ROL     R19\r
+   \   00000026   0F22               LSL     R18\r
+   \   00000028   1F33               ROL     R19\r
+   \   0000002A   01F9               MOVW    R31:R30, R19:R18\r
+   \   0000002C   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   0000002E   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000030   8140               LD      R20, Z\r
+   \   00000032   8151               LDD     R21, Z+1\r
+   \   00000034   8162               LDD     R22, Z+2\r
+   \   00000036   8173               LDD     R23, Z+3\r
+   \   00000038   2B45               OR      R20, R21\r
+   \   0000003A   2B46               OR      R20, R22\r
+   \   0000003C   2B47               OR      R20, R23\r
+   \   0000003E   F0A9               BREQ    ??TICK_ISR_2\r
+     65                                timeval[i]--;\r
+   \   00000040   2F20               MOV     R18, R16\r
+   \   00000042   E030               LDI     R19, 0\r
+   \   00000044   0F22               LSL     R18\r
+   \   00000046   1F33               ROL     R19\r
+   \   00000048   0F22               LSL     R18\r
+   \   0000004A   1F33               ROL     R19\r
+   \   0000004C   01F9               MOVW    R31:R30, R19:R18\r
+   \   0000004E   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   00000050   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000052   8140               LD      R20, Z\r
+   \   00000054   8151               LDD     R21, Z+1\r
+   \   00000056   8162               LDD     R22, Z+2\r
+   \   00000058   8173               LDD     R23, Z+3\r
+   \   0000005A   5041               SUBI    R20, 1\r
+   \   0000005C   4050               SBCI    R21, 0\r
+   \   0000005E   4060               SBCI    R22, 0\r
+   \   00000060   4070               SBCI    R23, 0\r
+   \   00000062   8340               ST      Z, R20\r
+   \   00000064   8351               STD     Z+1, R21\r
+   \   00000066   8362               STD     Z+2, R22\r
+   \   00000068   8373               STD     Z+3, R23\r
+     66                        }\r
+     67                }\r
+   \                     ??TICK_ISR_2:\r
+   \   0000006A   9503               INC     R16\r
+   \   0000006C   CFD6               RJMP    ??TICK_ISR_0\r
+     68          }\r
+   \                     ??TICK_ISR_1:\r
+   \   0000006E   BE0F               OUT     0x3F, R0\r
+   \   00000070   9109               LD      R16, Y+\r
+   \   00000072   9119               LD      R17, Y+\r
+   \   00000074   9129               LD      R18, Y+\r
+   \   00000076   9139               LD      R19, Y+\r
+   \   00000078   9149               LD      R20, Y+\r
+   \   0000007A   9159               LD      R21, Y+\r
+   \   0000007C   9169               LD      R22, Y+\r
+   \   0000007E   9179               LD      R23, Y+\r
+   \   00000080   9009               LD      R0, Y+\r
+   \   00000082   91E9               LD      R30, Y+\r
+   \   00000084   91F9               LD      R31, Y+\r
+   \   00000086   9518               RETI\r
+     69          \r
+     70          \r
+     71          /*! \brief Checks if a specified timer has expired\r
+     72           *\r
+     73           * \param timer Specifies timer\r
+     74           *\r
+     75           * \retval TRUE Timer still going.\r
+     76           * \retval FALSE Timer has expired.\r
+     77           */ \r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     78          unsigned char Time_Left(unsigned char timer)\r
+   \                     Time_Left:\r
+     79          {\r
+   \   00000000   2F20               MOV     R18, R16\r
+     80                if(timeval[timer] > 0) {\r
+   \   00000002   2F02               MOV     R16, R18\r
+   \   00000004   E010               LDI     R17, 0\r
+   \   00000006   0F00               LSL     R16\r
+   \   00000008   1F11               ROL     R17\r
+   \   0000000A   0F00               LSL     R16\r
+   \   0000000C   1F11               ROL     R17\r
+   \   0000000E   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000010   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   00000012   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000014   8140               LD      R20, Z\r
+   \   00000016   8151               LDD     R21, Z+1\r
+   \   00000018   8162               LDD     R22, Z+2\r
+   \   0000001A   8173               LDD     R23, Z+3\r
+   \   0000001C   2B45               OR      R20, R21\r
+   \   0000001E   2B46               OR      R20, R22\r
+   \   00000020   2B47               OR      R20, R23\r
+   \   00000022   F011               BREQ    ??Time_Left_0\r
+     81                        return(TRUE);\r
+   \   00000024   E001               LDI     R16, 1\r
+   \   00000026   9508               RET\r
+     82                } else {\r
+     83                        return(FALSE);\r
+   \                     ??Time_Left_0:\r
+   \   00000028   E000               LDI     R16, 0\r
+   \   0000002A   9508               RET\r
+     84                }\r
+     85          }\r
+     86          \r
+     87          \r
+     88          /*! \brief Sets the specified timer\r
+     89           *\r
+     90           * \param timer Specifies timer\r
+     91           * \param min Minutes for timer to count down\r
+     92           * \param sec Seconds for timer to count down\r
+     93           * \param ms Milliseconds for timer to count down\r
+     94           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     95          void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+   \                     Time_Set:\r
+     96                                          unsigned char ms)\r
+     97          {\r
+   \   00000000   ....               RCALL   ?PROLOGUE7_L09\r
+   \   00000002                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000002                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000002   2FA0               MOV     R26, R16\r
+   \   00000004   01C9               MOVW    R25:R24, R19:R18\r
+   \   00000006   2E61               MOV     R6, R17\r
+   \   00000008   2E44               MOV     R4, R20\r
+     98          //    timeval[i] = 4 * (1000*(sec + 60*min) + ms);   // about 4000 ticks per second\r
+     99          //    timeval[i] = 240000 * (unsigned long)min;\r
+    100          //    timeval[i] += 4000 * (unsigned long)sec;\r
+    101          //    timeval[i] += 4 * (unsigned long)ms;\r
+    102          \r
+    103                timeval[timer] = 60000 * (unsigned long)min;\r
+   \   0000000A   01AC               MOVW    R21:R20, R25:R24\r
+   \   0000000C   E060               LDI     R22, 0\r
+   \   0000000E   E070               LDI     R23, 0\r
+   \   00000010   E600               LDI     R16, 96\r
+   \   00000012   EE1A               LDI     R17, 234\r
+   \   00000014   E020               LDI     R18, 0\r
+   \   00000016   E030               LDI     R19, 0\r
+   \   00000018   ....               RCALL   ?L_MUL_L03\r
+   \   0000001A   2F4A               MOV     R20, R26\r
+   \   0000001C   E050               LDI     R21, 0\r
+   \   0000001E   0F44               LSL     R20\r
+   \   00000020   1F55               ROL     R21\r
+   \   00000022   0F44               LSL     R20\r
+   \   00000024   1F55               ROL     R21\r
+   \   00000026   01FA               MOVW    R31:R30, R21:R20\r
+   \   00000028   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   0000002A   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   0000002C   8300               ST      Z, R16\r
+   \   0000002E   8311               STD     Z+1, R17\r
+   \   00000030   8322               STD     Z+2, R18\r
+   \   00000032   8333               STD     Z+3, R19\r
+    104                timeval[timer] += 1000 * (unsigned long)sec;\r
+   \   00000034   2D46               MOV     R20, R6\r
+   \   00000036   E050               LDI     R21, 0\r
+   \   00000038   E060               LDI     R22, 0\r
+   \   0000003A   E070               LDI     R23, 0\r
+   \   0000003C   EE08               LDI     R16, 232\r
+   \   0000003E   E013               LDI     R17, 3\r
+   \   00000040   E020               LDI     R18, 0\r
+   \   00000042   E030               LDI     R19, 0\r
+   \   00000044   ....               RCALL   ?L_MUL_L03\r
+   \   00000046   2F4A               MOV     R20, R26\r
+   \   00000048   E050               LDI     R21, 0\r
+   \   0000004A   0F44               LSL     R20\r
+   \   0000004C   1F55               ROL     R21\r
+   \   0000004E   0F44               LSL     R20\r
+   \   00000050   1F55               ROL     R21\r
+   \   00000052   01FA               MOVW    R31:R30, R21:R20\r
+   \   00000054   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   00000056   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000058   8140               LD      R20, Z\r
+   \   0000005A   8151               LDD     R21, Z+1\r
+   \   0000005C   8162               LDD     R22, Z+2\r
+   \   0000005E   8173               LDD     R23, Z+3\r
+   \   00000060   0F40               ADD     R20, R16\r
+   \   00000062   1F51               ADC     R21, R17\r
+   \   00000064   1F62               ADC     R22, R18\r
+   \   00000066   1F73               ADC     R23, R19\r
+   \   00000068   8340               ST      Z, R20\r
+   \   0000006A   8351               STD     Z+1, R21\r
+   \   0000006C   8362               STD     Z+2, R22\r
+   \   0000006E   8373               STD     Z+3, R23\r
+    105                timeval[timer] += 1 * (unsigned long)ms;\r
+   \   00000070   2455               CLR     R5\r
+   \   00000072   0182               MOVW    R17:R16, R5:R4\r
+   \   00000074   E020               LDI     R18, 0\r
+   \   00000076   E030               LDI     R19, 0\r
+   \   00000078   2F4A               MOV     R20, R26\r
+   \   0000007A   E050               LDI     R21, 0\r
+   \   0000007C   0F44               LSL     R20\r
+   \   0000007E   1F55               ROL     R21\r
+   \   00000080   0F44               LSL     R20\r
+   \   00000082   1F55               ROL     R21\r
+   \   00000084   01FA               MOVW    R31:R30, R21:R20\r
+   \   00000086   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   00000088   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   0000008A   8140               LD      R20, Z\r
+   \   0000008C   8151               LDD     R21, Z+1\r
+   \   0000008E   8162               LDD     R22, Z+2\r
+   \   00000090   8173               LDD     R23, Z+3\r
+   \   00000092   0F40               ADD     R20, R16\r
+   \   00000094   1F51               ADC     R21, R17\r
+   \   00000096   1F62               ADC     R22, R18\r
+   \   00000098   1F73               ADC     R23, R19\r
+   \   0000009A   8340               ST      Z, R20\r
+   \   0000009C   8351               STD     Z+1, R21\r
+   \   0000009E   8362               STD     Z+2, R22\r
+   \   000000A0   8373               STD     Z+3, R23\r
+    106          }\r
+   \   000000A2   E0E7               LDI     R30, 7\r
+   \   000000A4   ....               RJMP    ?EPILOGUE_B7_L09\r
+    107          \r
+    108          \r
+    109          /*! \brief Stops timers\r
+    110           *\r
+    111           * Sets timer0's clock source to none.\r
+    112           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    113          void Time_Stop(void)\r
+   \                     Time_Stop:\r
+    114          {\r
+    115                TCCR0B = 0;\r
+   \   00000000   E000               LDI     R16, 0\r
+   \   00000002   BF03               OUT     0x33, R16\r
+    116          }\r
+   \   00000004   9508               RET\r
+   \   00000006                      REQUIRE _A_TCCR0B\r
+    117          \r
+    118          \r
+    119          /*! \brief Starts timers\r
+    120           *\r
+    121           * Sets timer0's clock source to system clock divided by 64.\r
+    122           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    123          void Time_Start(void)\r
+   \                     Time_Start:\r
+    124          {\r
+    125                TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+   \   00000000   E003               LDI     R16, 3\r
+   \   00000002   BF03               OUT     0x33, R16\r
+    126          }\r
+   \   00000004   9508               RET\r
+   \   00000006                      REQUIRE _A_TCCR0B\r
+    127          \r
+    128          \r
+    129          /*! \brief Initializes timers\r
+    130           *\r
+    131           * Resets all the timer values to 0, then sets up timer 0 for a compare match\r
+    132           * every millisecond.\r
+    133           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    134          void Time_Init(void)\r
+   \                     Time_Init:\r
+    135          {\r
+    136                unsigned char i;\r
+    137                \r
+    138                for (i = 0; i<<TIMERS; i++)     {\r
+   \   00000000   E040               LDI     R20, 0\r
+   \                     ??Time_Init_0:\r
+   \   00000002   2344               TST     R20\r
+   \   00000004   F099               BREQ    ??Time_Init_1\r
+    139                        timeval[i] = 0;\r
+   \   00000006   E000               LDI     R16, 0\r
+   \   00000008   E010               LDI     R17, 0\r
+   \   0000000A   E020               LDI     R18, 0\r
+   \   0000000C   E030               LDI     R19, 0\r
+   \   0000000E   2F64               MOV     R22, R20\r
+   \   00000010   E070               LDI     R23, 0\r
+   \   00000012   0F66               LSL     R22\r
+   \   00000014   1F77               ROL     R23\r
+   \   00000016   0F66               LSL     R22\r
+   \   00000018   1F77               ROL     R23\r
+   \   0000001A   01FB               MOVW    R31:R30, R23:R22\r
+   \   0000001C   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   0000001E   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000020   8300               ST      Z, R16\r
+   \   00000022   8311               STD     Z+1, R17\r
+   \   00000024   8322               STD     Z+2, R18\r
+   \   00000026   8333               STD     Z+3, R19\r
+    140                }\r
+   \   00000028   9543               INC     R20\r
+   \   0000002A   CFEB               RJMP    ??Time_Init_0\r
+    141          \r
+    142                //    OCR0A = 0;  // Doesn't matter, will run in normal mode.\r
+    143                \r
+    144                OCR0A = 125;  // Will give a compare match every ms.\r
+   \                     ??Time_Init_1:\r
+   \   0000002C   E70D               LDI     R16, 125\r
+   \   0000002E   BB03               OUT     0x13, R16\r
+    145                \r
+    146                OCR0B = 0;  // Doesn't matter, will run in normal mode.\r
+   \   00000030   E000               LDI     R16, 0\r
+   \   00000032   BB02               OUT     0x12, R16\r
+    147          \r
+    148                        //    TCCR0A = 0;  // Normal 8-bit mode, no input capture.\r
+    149          \r
+    150                TCCR0A = (1<<WGM00);  // 8-bit CTC mode.\r
+   \   00000034   E001               LDI     R16, 1\r
+   \   00000036   BB05               OUT     0x15, R16\r
+    151                \r
+    152                //    TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00);  // CLKT0 = CLK/8 = 1 MHz.\r
+    153                \r
+    154                TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+   \   00000038   E003               LDI     R16, 3\r
+   \   0000003A   BF03               OUT     0x33, R16\r
+    155          \r
+    156                //    TIMSK |= (1<<TOIE0);      // Overflow interrupt enabled.\r
+    157          \r
+    158                TIMSK |= (1<<OCIE0A);  // Timer 0, Compare match A interrupt enabled.\r
+   \   0000003C   B709               IN      R16, 0x39\r
+   \   0000003E   6100               ORI     R16, 0x10\r
+   \   00000040   BF09               OUT     0x39, R16\r
+    159          \r
+    160                // Enable interrupts, just in case they weren't already.\r
+    161                __enable_interrupt();       \r
+   \   00000042   9478               SEI\r
+    162          }\r
+   \   00000044   9508               RET\r
+   \   00000046                      REQUIRE _A_TIMSK\r
+   \   00000046                      REQUIRE _A_TCCR0B\r
+   \   00000046                      REQUIRE _A_TCCR0A\r
+   \   00000046                      REQUIRE _A_OCR0A\r
+   \   00000046                      REQUIRE _A_OCR0B\r
+\r
+   \                                 In  segment INTVEC, offset 0x1c, root\r
+   \                     `??TICK_ISR??INTVEC 28`:\r
+   \   0000001C   ....               RJMP    TICK_ISR\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function   CSTACK RSTACK\r
+     --------   ------ ------\r
+     TICK_ISR      11      2\r
+     Time_Init      0      2\r
+     Time_Left      0      2\r
+     Time_Set       7      4\r
+     Time_Start     0      2\r
+     Time_Stop      0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label        Bytes\r
+     --------------        -----\r
+     _A_TIMSK                 1\r
+     _A_TCCR0B                1\r
+     _A_TCCR0A                1\r
+     _A_OCR0A                 1\r
+     _A_OCR0B                 1\r
+     timeval                 16\r
+     TICK_ISR               136\r
+     Time_Left               44\r
+     Time_Set               166\r
+     Time_Stop                6\r
+     Time_Start               6\r
+     Time_Init               70\r
+     ??TICK_ISR??INTVEC 28    2\r
+      Others                  6\r
+\r
\r
+   5 bytes in segment ABSOLUTE\r
+ 428 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment INTVEC\r
+  16 bytes in segment NEAR_Z\r
\r
+ 428 bytes of CODE memory (+ 8 bytes shared)\r
+  16 bytes of DATA memory (+ 5 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/List/time.s90 b/BaseTinyFirmware/IAR/Debug/List/time.s90
new file mode 100644 (file)
index 0000000..8f27185
--- /dev/null
@@ -0,0 +1,537 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              12/Mar/2008  23:01:40 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file  =  C:\home\kevin\pub\src\bc100_cal\IAR\time.c              /\r
+//    Command line =  C:\home\kevin\pub\src\bc100_cal\IAR\time.c              /\r
+//                    --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA /\r
+//                    R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De /\r
+//                    bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug /\r
+//                    \List\ --initializers_in_flash -z2 --no_cse             /\r
+//                    --no_inline --no_code_motion --no_cross_call            /\r
+//                    --no_clustering --no_tbaa --debug                       /\r
+//                    -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I     /\r
+//                    "C:\Program Files\IAR Systems\Embedded Workbench        /\r
+//                    4.0\avr\INC\" -I "C:\Program Files\IAR                  /\r
+//                    Systems\Embedded Workbench 4.0\avr\INC\CLIB\"           /\r
+//                    --eeprom_size 512                                       /\r
+//    List file    =  C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\time.s90 /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME time\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?EPILOGUE_B7_L09\r
+        EXTERN ?L_MUL_L03\r
+        EXTERN ?PROLOGUE7_L09\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?need_segment_init\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBWEAK `??TICK_ISR??INTVEC 28`\r
+        PUBLIC TICK_ISR\r
+        PUBLIC Time_Init\r
+        PUBLIC Time_Left\r
+        PUBLIC Time_Set\r
+        PUBLIC Time_Start\r
+        PUBLIC Time_Stop\r
+        PUBWEAK _A_OCR0A\r
+        PUBWEAK _A_OCR0B\r
+        PUBWEAK _A_TCCR0A\r
+        PUBWEAK _A_TCCR0B\r
+        PUBWEAK _A_TIMSK\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+        PUBLIC timeval\r
+\r
+TICK_ISR            SYMBOL "TICK_ISR"\r
+`??TICK_ISR??INTVEC 28` SYMBOL "??INTVEC 28", TICK_ISR\r
+\r
+// C:\home\kevin\pub\src\bc100_cal\IAR\time.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for timing\r
+//    6  *\r
+//    7  *      Contains functions to initialize, set, poll and stop timers.\r
+//    8  *\r
+//    9  * \par Application note:\r
+//   10  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2299 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $\r
+//   26  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,059H\r
+// <unnamed> volatile __io _A_TIMSK\r
+_A_TIMSK:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,053H\r
+// <unnamed> volatile __io _A_TCCR0B\r
+_A_TCCR0B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,035H\r
+// <unnamed> volatile __io _A_TCCR0A\r
+_A_TCCR0A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,033H\r
+// <unnamed> volatile __io _A_OCR0A\r
+_A_OCR0A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,032H\r
+// <unnamed> volatile __io _A_OCR0B\r
+_A_OCR0B:\r
+        DS 1\r
+//   30 #include <inavr.h>\r
+//   31 \r
+//   32 #include "enums.h"\r
+//   33 \r
+//   34 #include "main.h"\r
+//   35 #include "time.h"\r
+//   36 \r
+//   37 \r
+//   38 //******************************************************************************\r
+//   39 // Variables\r
+//   40 //******************************************************************************\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   41 unsigned long timeval[TIMERS];  //!< Contains the values for each timer.\r
+timeval:\r
+        DS 16\r
+//   42 \r
+//   43 // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
+//   44 //#pragma vector = TIM0_OVF_vect\r
+//   45 \r
+//   46 \r
+//   47 //******************************************************************************\r
+//   48 // Functions\r
+//   49 //******************************************************************************\r
+//   50 /*! \brief Interrupt service routine for timer 0 overflow\r
+//   51  *\r
+//   52  * Timer 0 runs at 125 kHz and compare match will occur every millisecond\r
+//   53  * (125 / 125 kHz = 1.0 ms), which will result in a call to this function.\r
+//   54  * When called, this function will decrement the time left for each timer,\r
+//   55  * unless they are already at zero.\r
+//   56  */\r
+//   57 #pragma vector = TIM0_COMPA_vect\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   58 __interrupt void TICK_ISR(void)\r
+TICK_ISR:\r
+//   59 {\r
+        ST      -Y, R31\r
+        ST      -Y, R30\r
+        ST      -Y, R0\r
+        ST      -Y, R23\r
+        ST      -Y, R22\r
+        ST      -Y, R21\r
+        ST      -Y, R20\r
+        ST      -Y, R19\r
+        ST      -Y, R18\r
+        ST      -Y, R17\r
+        ST      -Y, R16\r
+        IN      R0, 0x3F\r
+//   60        unsigned char i;\r
+//   61 \r
+//   62        // 1 ms has passed, decrement all non-zero timers.\r
+//   63        for (i = 0; i < TIMERS; i++) {\r
+        LDI     R16, 0\r
+??TICK_ISR_0:\r
+        CPI     R16, 4\r
+        BRCC    ??TICK_ISR_1\r
+//   64                if(timeval[i] > 0) {\r
+        MOV     R18, R16\r
+        LDI     R19, 0\r
+        LSL     R18\r
+        ROL     R19\r
+        LSL     R18\r
+        ROL     R19\r
+        MOVW    R31:R30, R19:R18\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R20, Z\r
+        LDD     R21, Z+1\r
+        LDD     R22, Z+2\r
+        LDD     R23, Z+3\r
+        OR      R20, R21\r
+        OR      R20, R22\r
+        OR      R20, R23\r
+        BREQ    ??TICK_ISR_2\r
+//   65                        timeval[i]--;\r
+        MOV     R18, R16\r
+        LDI     R19, 0\r
+        LSL     R18\r
+        ROL     R19\r
+        LSL     R18\r
+        ROL     R19\r
+        MOVW    R31:R30, R19:R18\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R20, Z\r
+        LDD     R21, Z+1\r
+        LDD     R22, Z+2\r
+        LDD     R23, Z+3\r
+        SUBI    R20, 1\r
+        SBCI    R21, 0\r
+        SBCI    R22, 0\r
+        SBCI    R23, 0\r
+        ST      Z, R20\r
+        STD     Z+1, R21\r
+        STD     Z+2, R22\r
+        STD     Z+3, R23\r
+//   66                }\r
+//   67        }\r
+??TICK_ISR_2:\r
+        INC     R16\r
+        RJMP    ??TICK_ISR_0\r
+//   68 }\r
+??TICK_ISR_1:\r
+        OUT     0x3F, R0\r
+        LD      R16, Y+\r
+        LD      R17, Y+\r
+        LD      R18, Y+\r
+        LD      R19, Y+\r
+        LD      R20, Y+\r
+        LD      R21, Y+\r
+        LD      R22, Y+\r
+        LD      R23, Y+\r
+        LD      R0, Y+\r
+        LD      R30, Y+\r
+        LD      R31, Y+\r
+        RETI\r
+//   69 \r
+//   70 \r
+//   71 /*! \brief Checks if a specified timer has expired\r
+//   72  *\r
+//   73  * \param timer Specifies timer\r
+//   74  *\r
+//   75  * \retval TRUE Timer still going.\r
+//   76  * \retval FALSE Timer has expired.\r
+//   77  */ \r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   78 unsigned char Time_Left(unsigned char timer)\r
+Time_Left:\r
+//   79 {\r
+        MOV     R18, R16\r
+//   80        if(timeval[timer] > 0) {\r
+        MOV     R16, R18\r
+        LDI     R17, 0\r
+        LSL     R16\r
+        ROL     R17\r
+        LSL     R16\r
+        ROL     R17\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R20, Z\r
+        LDD     R21, Z+1\r
+        LDD     R22, Z+2\r
+        LDD     R23, Z+3\r
+        OR      R20, R21\r
+        OR      R20, R22\r
+        OR      R20, R23\r
+        BREQ    ??Time_Left_0\r
+//   81                return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//   82        } else {\r
+//   83                return(FALSE);\r
+??Time_Left_0:\r
+        LDI     R16, 0\r
+        RET\r
+//   84        }\r
+//   85 }\r
+//   86 \r
+//   87 \r
+//   88 /*! \brief Sets the specified timer\r
+//   89  *\r
+//   90  * \param timer Specifies timer\r
+//   91  * \param min Minutes for timer to count down\r
+//   92  * \param sec Seconds for timer to count down\r
+//   93  * \param ms Milliseconds for timer to count down\r
+//   94  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   95 void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+Time_Set:\r
+//   96                                  unsigned char ms)\r
+//   97 {\r
+        RCALL   ?PROLOGUE7_L09\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        MOV     R26, R16\r
+        MOVW    R25:R24, R19:R18\r
+        MOV     R6, R17\r
+        MOV     R4, R20\r
+//   98 //     timeval[i] = 4 * (1000*(sec + 60*min) + ms);   // about 4000 ticks per second\r
+//   99 //     timeval[i] = 240000 * (unsigned long)min;\r
+//  100 //     timeval[i] += 4000 * (unsigned long)sec;\r
+//  101 //     timeval[i] += 4 * (unsigned long)ms;\r
+//  102 \r
+//  103        timeval[timer] = 60000 * (unsigned long)min;\r
+        MOVW    R21:R20, R25:R24\r
+        LDI     R22, 0\r
+        LDI     R23, 0\r
+        LDI     R16, 96\r
+        LDI     R17, 234\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        RCALL   ?L_MUL_L03\r
+        MOV     R20, R26\r
+        LDI     R21, 0\r
+        LSL     R20\r
+        ROL     R21\r
+        LSL     R20\r
+        ROL     R21\r
+        MOVW    R31:R30, R21:R20\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        ST      Z, R16\r
+        STD     Z+1, R17\r
+        STD     Z+2, R18\r
+        STD     Z+3, R19\r
+//  104        timeval[timer] += 1000 * (unsigned long)sec;\r
+        MOV     R20, R6\r
+        LDI     R21, 0\r
+        LDI     R22, 0\r
+        LDI     R23, 0\r
+        LDI     R16, 232\r
+        LDI     R17, 3\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        RCALL   ?L_MUL_L03\r
+        MOV     R20, R26\r
+        LDI     R21, 0\r
+        LSL     R20\r
+        ROL     R21\r
+        LSL     R20\r
+        ROL     R21\r
+        MOVW    R31:R30, R21:R20\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R20, Z\r
+        LDD     R21, Z+1\r
+        LDD     R22, Z+2\r
+        LDD     R23, Z+3\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        ADC     R22, R18\r
+        ADC     R23, R19\r
+        ST      Z, R20\r
+        STD     Z+1, R21\r
+        STD     Z+2, R22\r
+        STD     Z+3, R23\r
+//  105        timeval[timer] += 1 * (unsigned long)ms;\r
+        CLR     R5\r
+        MOVW    R17:R16, R5:R4\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        MOV     R20, R26\r
+        LDI     R21, 0\r
+        LSL     R20\r
+        ROL     R21\r
+        LSL     R20\r
+        ROL     R21\r
+        MOVW    R31:R30, R21:R20\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R20, Z\r
+        LDD     R21, Z+1\r
+        LDD     R22, Z+2\r
+        LDD     R23, Z+3\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        ADC     R22, R18\r
+        ADC     R23, R19\r
+        ST      Z, R20\r
+        STD     Z+1, R21\r
+        STD     Z+2, R22\r
+        STD     Z+3, R23\r
+//  106 }\r
+        LDI     R30, 7\r
+        RJMP    ?EPILOGUE_B7_L09\r
+//  107 \r
+//  108 \r
+//  109 /*! \brief Stops timers\r
+//  110  *\r
+//  111  * Sets timer0's clock source to none.\r
+//  112  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  113 void Time_Stop(void)\r
+Time_Stop:\r
+//  114 {\r
+//  115        TCCR0B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x33, R16\r
+//  116 }\r
+        RET\r
+        REQUIRE _A_TCCR0B\r
+//  117 \r
+//  118 \r
+//  119 /*! \brief Starts timers\r
+//  120  *\r
+//  121  * Sets timer0's clock source to system clock divided by 64.\r
+//  122  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  123 void Time_Start(void)\r
+Time_Start:\r
+//  124 {\r
+//  125        TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+        LDI     R16, 3\r
+        OUT     0x33, R16\r
+//  126 }\r
+        RET\r
+        REQUIRE _A_TCCR0B\r
+//  127 \r
+//  128 \r
+//  129 /*! \brief Initializes timers\r
+//  130  *\r
+//  131  * Resets all the timer values to 0, then sets up timer 0 for a compare match\r
+//  132  * every millisecond.\r
+//  133  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  134 void Time_Init(void)\r
+Time_Init:\r
+//  135 {\r
+//  136        unsigned char i;\r
+//  137        \r
+//  138        for (i = 0; i<<TIMERS; i++)     {\r
+        LDI     R20, 0\r
+??Time_Init_0:\r
+        TST     R20\r
+        BREQ    ??Time_Init_1\r
+//  139                timeval[i] = 0;\r
+        LDI     R16, 0\r
+        LDI     R17, 0\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        MOV     R22, R20\r
+        LDI     R23, 0\r
+        LSL     R22\r
+        ROL     R23\r
+        LSL     R22\r
+        ROL     R23\r
+        MOVW    R31:R30, R23:R22\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        ST      Z, R16\r
+        STD     Z+1, R17\r
+        STD     Z+2, R18\r
+        STD     Z+3, R19\r
+//  140        }\r
+        INC     R20\r
+        RJMP    ??Time_Init_0\r
+//  141 \r
+//  142        //    OCR0A = 0;  // Doesn't matter, will run in normal mode.\r
+//  143        \r
+//  144        OCR0A = 125;  // Will give a compare match every ms.\r
+??Time_Init_1:\r
+        LDI     R16, 125\r
+        OUT     0x13, R16\r
+//  145        \r
+//  146        OCR0B = 0;  // Doesn't matter, will run in normal mode.\r
+        LDI     R16, 0\r
+        OUT     0x12, R16\r
+//  147 \r
+//  148                //    TCCR0A = 0;  // Normal 8-bit mode, no input capture.\r
+//  149 \r
+//  150        TCCR0A = (1<<WGM00);  // 8-bit CTC mode.\r
+        LDI     R16, 1\r
+        OUT     0x15, R16\r
+//  151        \r
+//  152        //    TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00);  // CLKT0 = CLK/8 = 1 MHz.\r
+//  153        \r
+//  154        TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+        LDI     R16, 3\r
+        OUT     0x33, R16\r
+//  155 \r
+//  156        //    TIMSK |= (1<<TOIE0);      // Overflow interrupt enabled.\r
+//  157 \r
+//  158        TIMSK |= (1<<OCIE0A);  // Timer 0, Compare match A interrupt enabled.\r
+        IN      R16, 0x39\r
+        ORI     R16, 0x10\r
+        OUT     0x39, R16\r
+//  159 \r
+//  160        // Enable interrupts, just in case they weren't already.\r
+//  161        __enable_interrupt();       \r
+        SEI\r
+//  162 }\r
+        RET\r
+        REQUIRE _A_TIMSK\r
+        REQUIRE _A_TCCR0B\r
+        REQUIRE _A_TCCR0A\r
+        REQUIRE _A_OCR0A\r
+        REQUIRE _A_OCR0B\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        COMMON INTVEC:CODE:ROOT(1)\r
+        ORG 28\r
+`??TICK_ISR??INTVEC 28`:\r
+        RJMP    TICK_ISR\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   5 bytes in segment ABSOLUTE\r
+// 428 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment INTVEC\r
+//  16 bytes in segment NEAR_Z\r
+// \r
+// 428 bytes of CODE memory (+ 8 bytes shared)\r
+//  16 bytes of DATA memory (+ 5 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/ADC.r90 b/BaseTinyFirmware/IAR/Debug/Obj/ADC.r90
new file mode 100644 (file)
index 0000000..8113fb8
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/ADC.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/BC100_tiny.pbd b/BaseTinyFirmware/IAR/Debug/Obj/BC100_tiny.pbd
new file mode 100644 (file)
index 0000000..3c882c0
--- /dev/null
@@ -0,0 +1,13 @@
+This is an internal working file generated by the Source Browser.\r
+04:48 47s\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\ADC.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\NIMHcharge.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\OWI.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\PWM.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\USI.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\battery.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\chargefunc.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\main.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\menu.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\statefunc.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\time.pbi\r
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/NIMHcharge.r90 b/BaseTinyFirmware/IAR/Debug/Obj/NIMHcharge.r90
new file mode 100644 (file)
index 0000000..f0e493d
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/NIMHcharge.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/OWI.r90 b/BaseTinyFirmware/IAR/Debug/Obj/OWI.r90
new file mode 100644 (file)
index 0000000..55dae46
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/OWI.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/PWM.r90 b/BaseTinyFirmware/IAR/Debug/Obj/PWM.r90
new file mode 100644 (file)
index 0000000..663cdc1
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/PWM.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/USI.r90 b/BaseTinyFirmware/IAR/Debug/Obj/USI.r90
new file mode 100644 (file)
index 0000000..846ee5e
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/USI.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/battery.r90 b/BaseTinyFirmware/IAR/Debug/Obj/battery.r90
new file mode 100644 (file)
index 0000000..b3c28a7
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/battery.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/chargefunc.r90 b/BaseTinyFirmware/IAR/Debug/Obj/chargefunc.r90
new file mode 100644 (file)
index 0000000..7fd779e
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/chargefunc.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/main.r90 b/BaseTinyFirmware/IAR/Debug/Obj/main.r90
new file mode 100644 (file)
index 0000000..bf41cf2
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/main.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/menu.r90 b/BaseTinyFirmware/IAR/Debug/Obj/menu.r90
new file mode 100644 (file)
index 0000000..45df4a6
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/menu.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/statefunc.r90 b/BaseTinyFirmware/IAR/Debug/Obj/statefunc.r90
new file mode 100644 (file)
index 0000000..7286036
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/statefunc.r90 differ
diff --git a/BaseTinyFirmware/IAR/Debug/Obj/time.r90 b/BaseTinyFirmware/IAR/Debug/Obj/time.r90
new file mode 100644 (file)
index 0000000..c2691b0
Binary files /dev/null and b/BaseTinyFirmware/IAR/Debug/Obj/time.r90 differ
diff --git a/BaseTinyFirmware/IAR/LIIONcharge.c b/BaseTinyFirmware/IAR/LIIONcharge.c
new file mode 100644 (file)
index 0000000..49dfe5b
--- /dev/null
@@ -0,0 +1,156 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Charge state function for Li-Ion batteries\r
+ *\r
+ *      Contains the charge state function, in which the Li-Ion charging\r
+ *      algorithm is, plus the associated functions.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONcharge.c $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "battery.h"\r
+#include "charge.h"\r
+#include "chargefunc.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "LIIONspecs.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+\r
+#ifndef LIION\r
+#error LIION not defined in main.h!\r
+#endif // LIION\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Controls the charging.\r
+ *\r
+ * This function contains the charging algorithm itself, divided into stages.\n\r
+ * For each stage the PWM may be started/stopped, and the timer, \r
+ * halt-requirements and charge parameters may be set.\n\r
+ * The charging functions return whatever state is next, and as long as no\r
+ * errors occur this is the next charging stage.\r
+ *\r
+ * \note If more stages are needed simply define more states in menu.h, include\r
+ * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+ *\r
+ * \note This algorithm is for Li-Ion batteries.\r
+ */\r
+unsigned char Charge(unsigned char inp)\r
+{\r
+       unsigned char NextState;\r
+\r
+       switch (CurrentState)   {\r
+       case ST_PREQUAL:  // First step is prequalification.\r
+               \r
+               // Charge with the defined prequalifiction-current, and if no errors\r
+               // occur return ST_CCURRENT as the next state.\r
+               ChargeParameters.Current = BAT_CURRENT_PREQUAL;\r
+               ChargeParameters.NextState = ST_CCURRENT;\r
+               \r
+               // We want charging to halt if voltage reaches a limit or time runs out.\r
+               // In case of timeout the battery will be flagged as exhausted, and an\r
+               // error will be flagged.\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | \r
+                                           HALT_FLAG_EXHAUSTION);\r
+               \r
+               // Set the maximum temperature and charge voltage limit.\r
+               HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+               HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+\r
+               // Start PWM output and charging timer first.\r
+               PWM_Start();\r
+               Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+\r
+               // Call the constant current charging-function.\r
+               // If all goes well, we will get ST_CCURRENT in return.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+       \r
+\r
+       case ST_CCURRENT:  // Second step is constant current charging.\r
+               \r
+               // Set charging timer to the battery's maximum charge time.\r
+               Time_Set(TIMER_CHG,BattData.MaxTime,0,0);\r
+\r
+               // Charge at the battery's maximum current, go to ST_CVOLTAGE next.\r
+               ChargeParameters.Current = BattData.MaxCurrent;\r
+               ChargeParameters.NextState = ST_CVOLTAGE;\r
+\r
+\r
+               // Charge until the defined BatChargeVoltage is reached.\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+               \r
+               // Start charging using constant current.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       case ST_CVOLTAGE:  // Third step is constant voltage charging.\r
+               \r
+               // Charge with the defined charge-voltage, go to ST_ENDCHARGE next.\r
+               ChargeParameters.Voltage = BAT_VOLTAGE_MAX;\r
+               ChargeParameters.NextState = ST_ENDCHARGE;\r
+               \r
+               // We want charging to halt if temperature rises too high, if current\r
+               // sinks below limit, or time runs out. Also, flag error if temperature\r
+               // limit is reached. Timeout doesn't mean anything is wrong at this point.\r
+               HaltParameters.HaltFlags = (HALT_CURRENT_MIN | HALT_TIME);\r
+               \r
+               HaltParameters.CurrentMin = BattData.MinCurrent;\r
+               \r
+               // Start charging using constant voltage. We will continue on the \r
+               // timer started in ST_CCURRENT.\r
+               NextState = ConstantVoltage(); \r
+       break;\r
+\r
+\r
+       case ST_ENDCHARGE:  // Charging is done!\r
+\r
+               PWM_Stop();\r
+               BattData.Charged = TRUE;\r
+               \r
+               // If the other battery is enabled go to ST_BATCON, otherwise\r
+               // go to ST_SLEEP.\r
+               if (BattControl[(BattActive+1)%2].Enabled) {\r
+                       NextState = ST_BATCON;\r
+               } else {\r
+                       NextState = ST_SLEEP;\r
+               }               \r
+       break;\r
+\r
+\r
+       default:  // Shouldn't end up here. Reinitialize for safety.\r
+               NextState = ST_INIT;\r
+               break;\r
+       }\r
+\r
+       // Return the next state.\r
+       return(NextState);\r
+}\r
diff --git a/BaseTinyFirmware/IAR/LIIONspecs.h b/BaseTinyFirmware/IAR/LIIONspecs.h
new file mode 100644 (file)
index 0000000..e662b1e
--- /dev/null
@@ -0,0 +1,102 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Li-Ion specifications\r
+ *\r
+ *      Contains example definitions of Li-Ion battery specifications.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONspecs.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef LIIONSPECS_H\r
+#define LIIONSPECS_H\r
+\r
+\r
+//******************************************************************************\r
+// Cell limits\r
+//******************************************************************************\r
+// This is for common NiMH batteries.\r
+#define        CELL_VOLTAGE_SAFETY     0  /*!< \brief Buffer for unmatched batteries.\r
+ * \r
+ * If we are charging a multicell battery and the cells aren't matched, we\r
+ * may risk overcharging at least one. Therefore, we may subtract this constant\r
+ * per additional cell in battery to allow for a "buffer".\r
+ *\r
+ * \note Set to 0 if batteries are properly matched.\r
+ *\r
+ * \note If this is changed to something higher than (CELL_VOLTAGE_MAX -\r
+ * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit\r
+ * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause\r
+ * the charger to keep trying to charge, but instantly finishing because\r
+ * the battery voltage is already at max.\r
+ */\r
+//! Maximum charge voltage for cell, in mV.\r
+#define        CELL_VOLTAGE_MAX     4200\r
+\r
+//! Minimum voltage to consider cell charged at, in mV.\r
+#define        CELL_VOLTAGE_LOW     4050\r
+\r
+//! Minimum voltage to start charging at, in mV.\r
+#define        CELL_VOLTAGE_MIN     2750\r
+\r
+//! Target voltage during prequalification, in mV.\r
+#define        CELL_VOLTAGE_PREQUAL 3000\r
+\r
+\r
+//******************************************************************************\r
+// Battery limits\r
+//******************************************************************************\r
+// Battery-definitions.\r
+//! Number of cells in battery.\r
+#define        BAT_CELL_NUMBER      1\r
+\r
+//! Maximum cell temperature (Celsius).\r
+#define        BAT_TEMPERATURE_MAX  45\r
+\r
+//! Minimum Cell temperature (Celsius).\r
+#define BAT_TEMPERATURE_MIN   0\r
+\r
+//! Maximum time for prequalification, in minutes.\r
+#define        BAT_TIME_PREQUAL     9\r
+\r
+//! \brief Constant charge current, in mA, during prequalification mode.\r
+//! \note This is typically lower than the main charge current.\r
+#define        BAT_CURRENT_PREQUAL  150\r
+\r
+//! Charge current hysteresis, in mA.\r
+#define        BAT_CURRENT_HYST     5\r
+\r
+//! Charge voltage hysteresis, in mV.\r
+#define        BAT_VOLTAGE_HYST     10\r
+\r
+//! Maximum battery voltage, in mV. \r
+#define        BAT_VOLTAGE_MAX      (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \\r
+                              ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY)\r
+\r
+//! Minimum voltage, in mV, to consider battery charged.\r
+#define        BAT_VOLTAGE_LOW      (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER)\r
+\r
+//! Minimum voltage, in mV, to consider battery safe to charge.\r
+#define        BAT_VOLTAGE_MIN      (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER)\r
+\r
+//! Charge voltage to achieve, in mV, during prequalification mode.\r
+#define BAT_VOLTAGE_PREQUAL    (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER)\r
+\r
+#endif // LIIONSPECS_H\r
diff --git a/BaseTinyFirmware/IAR/NIMHcharge.c b/BaseTinyFirmware/IAR/NIMHcharge.c
new file mode 100644 (file)
index 0000000..5d85a71
--- /dev/null
@@ -0,0 +1,179 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Charge state function for NiMH batteries\r
+ *\r
+ *      Contains the charge state function, in which the NiMH charging\r
+ *      algorithm is, plus the associated functions.\r
+ *\r
+ * \par Application note:\r
+ *      AVR463: Charging NiMH Batteries with BC100 \n\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2255 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $\r
+ * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "battery.h"\r
+#include "charge.h"\r
+#include "chargefunc.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "NIMHspecs.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+\r
+#ifndef NIMH\r
+#error NIMH not defined in main.h!\r
+#endif // NIMH\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Controls the charging.\r
+ *\r
+ * This function contains the charging algorithm itself, divided into stages.\n\r
+ * For each stage the PWM may be started/stopped, and the timer, \r
+ * halt-requirements and charge parameters may be set.\n\r
+ * The charging functions return whatever state is next, and as long as no\r
+ * errors occur this is the next charging stage.\r
+ *\r
+ * \note If more stages are needed simply define more states in menu.h, include\r
+ * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+ *\r
+ * \note This algorithm is for NiMH batteries.\r
+ */\r
+unsigned char Charge(unsigned char inp)\r
+{\r
+       unsigned char NextState;\r
+\r
+       switch (CurrentState) {\r
+       // First stage is a prequalification. Attempt to charge battery to 1 V,\r
+       // using a 0.1 C current, within 2 minutes.\r
+       // If this fails, the battery is likely damaged.\r
+       // If it succeeds, start a fast charge.\r
+       case ST_PREQUAL:\r
+               \r
+               // Set up charge current and next state.\r
+               ChargeParameters.Current = BattData.Capacity / 10;\r
+               ChargeParameters.NextState = ST_FASTCHARGE;\r
+               \r
+               // Halt charge on voltage limit or timeout.\r
+               // Timeout means battery exhaustion.\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+                                           HALT_FLAG_EXHAUSTION);\r
+               \r
+               // Set up voltage limit and temperature limits.\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+               HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+               HaltParameters.TemperatureMax = 35;\r
+               \r
+               // Reset temperature measurement for HaltNow().\r
+               HaltParameters.LastNTC = 0;\r
+               \r
+               // Start PWM and charge timer before calling the charge function.\r
+               PWM_Start();\r
+               Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+               \r
+               // Call charge function, get next state.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,\r
+       // until either rate of temperature increase or voltage reaches limit, or\r
+       // the voltage drops sufficiently.\r
+       // Timeout doesn't mean battery exhaustion now.\r
+       case ST_FASTCHARGE:\r
+\r
+               // Set up charge current and next state.\r
+               ChargeParameters.Current = BattData.Capacity;\r
+               ChargeParameters.NextState = ST_LOWRATECHARGE;\r
+               \r
+               // Halt charge on voltage limit, timeout, voltage drop or rate of \r
+               // temperature increase.\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+                                           HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);\r
+               \r
+               // Set up limits for voltage, voltage drop, temperature and rate of \r
+               // temperature increase (1 degree C per minute).\r
+               HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+               HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;\r
+               HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+               HaltParameters.TemperatureRise = 1;\r
+               \r
+               // Reset maximum voltage measurement for HaltNow().\r
+               HaltParameters.VBATMax = 0;\r
+\r
+               // Start timer, PWM should still be running.\r
+               Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);\r
+\r
+               // Call charge function, get next state.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,\r
+       // until either rate of temperature increase or voltage reaches limit.\r
+       case ST_LOWRATECHARGE:\r
+               \r
+               // Set up charge current and next state.\r
+               ChargeParameters.Current = BattData.Capacity / 10;\r
+               ChargeParameters.NextState = ST_ENDCHARGE;\r
+               \r
+               // Halt charge on voltage limit, timeout or temperature rise.\r
+               // Use the same requirements as during the last stage (ST_FASTCHARGE).\r
+               HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+                                           HALT_TEMPERATURE_RISE);\r
+\r
+               // Start timer, 30 minutes.\r
+               Time_Set(TIMER_CHG, 30, 0, 0);\r
+               \r
+               // Call charge function, get next state.\r
+               NextState = ConstantCurrent();\r
+       break;\r
+\r
+\r
+       // Charging is done!\r
+       case ST_ENDCHARGE:\r
+\r
+               // Stop the PWM output and flag battery as charged.\r
+               PWM_Stop();\r
+               BattData.Charged = TRUE;\r
+               \r
+               // If the other battery is enabled go to ST_BATCON, otherwise\r
+               // go to ST_SLEEP.\r
+               if (BattControl[(BattActive+1)%2].Enabled) {\r
+                       NextState = ST_BATCON;\r
+               } else {\r
+                       NextState = ST_SLEEP;\r
+               }               \r
+       break;\r
+\r
+\r
+       default:  // Shouldn't end up here. Reinitialize for safety.\r
+               NextState = ST_INIT;\r
+               break;\r
+       }\r
+\r
+       // Return the next state to main().\r
+       return(NextState);\r
+}\r
diff --git a/BaseTinyFirmware/IAR/NIMHspecs.h b/BaseTinyFirmware/IAR/NIMHspecs.h
new file mode 100644 (file)
index 0000000..cd27677
--- /dev/null
@@ -0,0 +1,108 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      NiMH specifications\r
+ *\r
+ *      Contains example definitions of NiMH battery specifications.\r
+ *\r
+ * \par Application note:\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2255 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHspecs.h $\r
+ * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef NIMHSPECS_H\r
+#define NIMHSPECS_H\r
+\r
+\r
+//******************************************************************************\r
+// Cell limits\r
+//******************************************************************************\r
+// This is for common NiMH batteries.\r
+#define        CELL_VOLTAGE_SAFETY     0  /*!< \brief Buffer for unmatched batteries.\r
+ * \r
+ * If we are charging a multicell battery and the cells aren't matched, we\r
+ * may risk overcharging at least one. Therefore, we may subtract this constant\r
+ * per additional cell in battery to allow for a "buffer".\r
+ *\r
+ * \note Set to 0 if batteries are properly matched.\r
+ *\r
+ * \note If this is changed to something higher than (CELL_VOLTAGE_MAX -\r
+ * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit\r
+ * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause\r
+ * the charger to keep trying to charge, but instantly finishing because\r
+ * the battery voltage is already at max.\r
+ */\r
+//! Maximum charge voltage for cell, in mV.\r
+#define        CELL_VOLTAGE_MAX     1600\r
+\r
+//! Minimum voltage to consider cell charged at, in mV.\r
+#define        CELL_VOLTAGE_LOW     1350\r
+\r
+//! Minimum voltage to start charging at, in mV.\r
+#define        CELL_VOLTAGE_MIN     800\r
+\r
+//! Target voltage during prequalification, in mV.\r
+#define        CELL_VOLTAGE_PREQUAL 1000\r
+\r
+//! Cell voltage drop when full charge is achieved.\r
+#define CELL_VOLTAGE_DROP     15\r
+\r
+\r
+//******************************************************************************\r
+// Battery limits\r
+//******************************************************************************\r
+// Battery-definitions.\r
+//! Number of cells in battery.\r
+#define        BAT_CELL_NUMBER      3\r
+\r
+//! Maximum cell temperature (Celsius).\r
+#define        BAT_TEMPERATURE_MAX  50\r
+\r
+//! Minimum Cell temperature (Celsius).\r
+#define BAT_TEMPERATURE_MIN   5\r
+\r
+//! Maximum time for prequalification, in minutes.\r
+#define        BAT_TIME_PREQUAL     2\r
+\r
+//! \brief Constant charge current, in mA, during prequalification mode.\r
+//! \note This is typically lower than the main charge current.\r
+#define        BAT_CURRENT_PREQUAL  150\r
+\r
+//! Charge current hysteresis, in mA.\r
+#define        BAT_CURRENT_HYST     3\r
+\r
+//! Charge voltage hysteresis, in mV.\r
+#define        BAT_VOLTAGE_HYST     10\r
+\r
+//! Maximum battery voltage, in mV. \r
+#define        BAT_VOLTAGE_MAX      (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \\r
+                              ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY)\r
+\r
+//! Minimum voltage, in mV, to consider battery charged.\r
+#define        BAT_VOLTAGE_LOW      (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER)\r
+\r
+//! Minimum voltage, in mV, to consider battery safe to charge.\r
+#define        BAT_VOLTAGE_MIN      (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER)\r
+\r
+//! Voltage drop, in mV, when full charge is achieved.\r
+#define BAT_VOLTAGE_DROP      (CELL_VOLTAGE_DROP * BAT_CELL_NUMBER)\r
+\r
+//! Charge voltage to achieve, in mV, during prequalification mode.\r
+#define BAT_VOLTAGE_PREQUAL    (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER)\r
+\r
+#endif // NIMHSPECS_H\r
diff --git a/BaseTinyFirmware/IAR/OWI.c b/BaseTinyFirmware/IAR/OWI.c
new file mode 100644 (file)
index 0000000..98cdd9c
--- /dev/null
@@ -0,0 +1,516 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file ********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for 1-Wire(R) bus communication\r
+ *\r
+ *      High level functions for transmission of full bytes on the 1-Wire(R)\r
+ *      bus and implementations of ROM commands.\n\r
+ *      Polled software only implementation of the basic bit-level signalling\r
+ *      in the 1-Wire(R) protocol.\n\r
+ *      Includes functions for computing and checking CRC8 & 16 values of data\r
+ *      sets, and of 64 bit ROM identifiers.\r
+ *      Supported devices:  All AVRs.\r
+ *\r
+ * \par Application Note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+ *      AVR463: Charging NiMH Batteries with BC100\n\r
+ *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+****************************************************************************/\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+\r
+#include "OWI.h"\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Initialization of the one wire bus(es). (Software only driver)\r
+ *  \r
+ *  This function initializes the 1-Wire bus(es) by releasing it and\r
+ *  waiting until any presence signals are finished.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to initialize.\r
+ */\r
+void OWI_Init(unsigned char pins){\r
+       OWI_RELEASE_BUS(pins);\r
+       // The first rising edge can be interpreted by a slave as the end of a\r
+       // Reset-pulse. Delay for the required reset recovery time (H) to be \r
+       // sure that the real reset is interpreted correctly.\r
+       __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+}\r
+\r
+\r
+/*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
+ *\r
+ *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
+ *  bus.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to write to.\r
+ */\r
+void OWI_WriteBit1(unsigned char pins){\r
+       unsigned char intState;\r
+       \r
+       // Disable interrupts.\r
+       intState = __save_interrupt();\r
+       __disable_interrupt();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       __delay_cycles(OWI_DELAY_B_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       __restore_interrupt(intState);\r
+}\r
+\r
+/*! \brief  Write a '0' to the bus(es). (Software only driver)\r
+ *\r
+ *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
+ *  bus.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to write to.\r
+ */\r
+void OWI_WriteBit0(unsigned char pins)\r
+{\r
+       unsigned char intState;\r
+       \r
+       // Disable interrupts.\r
+       intState = __save_interrupt();\r
+       __disable_interrupt();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       __delay_cycles(OWI_DELAY_C_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       __delay_cycles(OWI_DELAY_D_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       __restore_interrupt(intState);\r
+}\r
+\r
+/*! \brief  Read a bit from the bus(es). (Software only driver)\r
+ *\r
+ *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
+ *\r
+ *  \param  pins    A bitmask of the bus(es) to read from.\r
+ *\r
+ *  \return A bitmask of the buses where a '1' was read.\r
+ */\r
+unsigned char OWI_ReadBit(unsigned char pins)\r
+{\r
+       unsigned char intState;\r
+       unsigned char bitsRead;\r
+       \r
+       // Disable interrupts.\r
+       intState = __save_interrupt();\r
+       __disable_interrupt();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       __delay_cycles(OWI_DELAY_E_STD_MODE);\r
+       \r
+       // Sample bus and delay.\r
+       bitsRead = OWI_PIN & pins;\r
+       __delay_cycles(OWI_DELAY_F_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       __restore_interrupt(intState);\r
+       \r
+       return bitsRead;\r
+}\r
+\r
+\r
+/*! \brief  Send a Reset signal and listen for Presence signal. (software\r
+ *  only driver)\r
+ *\r
+ *  Generates the waveform for transmission of a Reset pulse on the \r
+ *  1-Wire(R) bus and listens for presence signals.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
+ *\r
+ *  \return A bitmask of the buses where a presence signal was detected.\r
+ */\r
+unsigned char OWI_DetectPresence(unsigned char pins)\r
+{\r
+       unsigned char intState;\r
+       unsigned char presenceDetected;\r
+       \r
+       // Disable interrupts.\r
+       intState = __save_interrupt();\r
+       __disable_interrupt();\r
+       \r
+       // Drive bus low and delay.\r
+       OWI_PULL_BUS_LOW(pins);\r
+       __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+       \r
+       // Release bus and delay.\r
+       OWI_RELEASE_BUS(pins);\r
+       __delay_cycles(OWI_DELAY_I_STD_MODE);\r
+       \r
+       // Sample bus to detect presence signal and delay.\r
+       presenceDetected = ((~OWI_PIN) & pins);\r
+       __delay_cycles(OWI_DELAY_J_STD_MODE);\r
+       \r
+       // Restore interrupts.\r
+       __restore_interrupt(intState);\r
+       \r
+       return presenceDetected;\r
+}\r
+\r
+\r
+/*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
+ *  \r
+ *  This function automates the task of sending a complete byte\r
+ *  of data on the 1-Wire bus(es).\r
+ *\r
+ *  \param  data    The data to send on the bus(es).\r
+ *  \r
+ *  \param  pins    A bitmask of the buses to send the data to.\r
+ */\r
+void OWI_SendByte(unsigned char data, unsigned char pins)\r
+{\r
+       unsigned char temp;\r
+       unsigned char i;\r
+       \r
+       // Do once for each bit\r
+       for (i = 0; i < 8; i++) {\r
+               // Determine if LSB is '0' or '1' and transmit corresponding\r
+               // waveform on the bus.\r
+               temp = data & 0x01;\r
+               \r
+               if (temp) {\r
+                       OWI_WriteBit1(pins);\r
+               } else {\r
+                       OWI_WriteBit0(pins);\r
+               }\r
+       \r
+               data >>= 1;  // Right shift the data to get next bit.\r
+       }\r
+}\r
+\r
+\r
+/*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
+ *\r
+ *  This function automates the task of receiving a complete byte \r
+ *  of data from the 1-Wire bus.\r
+ *\r
+ *  \param  pin     A bitmask of the bus to read from.\r
+ *  \r
+ *  \return     The byte read from the bus.\r
+ */\r
+unsigned char OWI_ReceiveByte(unsigned char pin)\r
+{\r
+       unsigned char data;\r
+       unsigned char i;\r
+       \r
+       // Clear the temporary input variable.\r
+       data = 0x00;\r
+       \r
+       // Do once for each bit\r
+       for (i = 0; i < 8; i++) {\r
+               // Shift temporary input variable right.\r
+               data >>= 1;\r
+               \r
+               // Set the MSB if a '1' value is read from the bus.\r
+               // Leave as it is ('0') else.\r
+               if (OWI_ReadBit(pin)) {\r
+                       data |= 0x80;\r
+               }\r
+       }\r
+       \r
+       return data;\r
+}\r
+\r
+\r
+/*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
+ *\r
+ *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
+ */\r
+void OWI_SkipRom(unsigned char pins)\r
+{\r
+       // Send the SKIP ROM command on the bus.\r
+       OWI_SendByte(OWI_ROM_SKIP, pins);\r
+}\r
+\r
+\r
+/*! \brief  Sends the READ ROM command and reads back the ROM id.\r
+ *\r
+ *  \param  romValue    A pointer where the id will be placed.\r
+ *\r
+ *  \param  pin     A bitmask of the bus to read from.\r
+ */\r
+void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
+{\r
+       unsigned char bytesLeft = 8;\r
+       \r
+       // Send the READ ROM command on the bus.\r
+       OWI_SendByte(OWI_ROM_READ, pin);\r
+       \r
+       // Do 8 times.\r
+       while (bytesLeft > 0) {\r
+               // Place the received data in memory.\r
+               *romValue++ = OWI_ReceiveByte(pin);\r
+               bytesLeft--;\r
+       }\r
+}\r
+\r
+\r
+/*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
+ *\r
+ *  \param  romValue    A pointer to the ID to match against.\r
+ *\r
+ *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
+ */\r
+void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
+{\r
+       unsigned char bytesLeft = 8;   \r
+       \r
+       // Send the MATCH ROM command.\r
+       OWI_SendByte(OWI_ROM_MATCH, pins);\r
+       \r
+       // Do once for each byte.\r
+       while (bytesLeft > 0) {\r
+               // Transmit 1 byte of the ID to match.\r
+               OWI_SendByte(*romValue++, pins);\r
+               bytesLeft--;\r
+       }\r
+}\r
+\r
+\r
+/*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
+ *          1-Wire(R) bus.\r
+ *\r
+ *  \param  bitPattern      A pointer to an 8 byte char array where the \r
+ *                          discovered identifier will be placed. When \r
+ *                          searching for several slaves, a copy of the \r
+ *                          last found identifier should be supplied in \r
+ *                          the array, or the search will fail.\r
+ *\r
+ *  \param  lastDeviation   The bit position where the algorithm made a \r
+ *                          choice the last time it was run. This argument \r
+ *                          should be 0 when a search is initiated. Supplying \r
+ *                          the return argument of this function when calling \r
+ *                          repeatedly will go through the complete slave \r
+ *                          search.\r
+ *\r
+ *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
+ *\r
+ *  \return The last bit position where there was a discrepancy between slave\r
+ *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
+ *  if an error was detected (e.g. a device was connected to the bus during the\r
+ *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
+ *  discovered.\r
+ *\r
+ *  \note   See main.c for an example of how to utilize this function.\r
+ */\r
+unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+                                               unsigned char lastDeviation, unsigned char pin)\r
+{\r
+       unsigned char currentBit = 1;\r
+       unsigned char newDeviation = 0;\r
+       unsigned char bitMask = 0x01;\r
+       unsigned char bitA;\r
+       unsigned char bitB;\r
+       \r
+       // Send SEARCH ROM command on the bus.\r
+       OWI_SendByte(OWI_ROM_SEARCH, pin);\r
+       \r
+       // Walk through all 64 bits.\r
+       while (currentBit <= 64) {\r
+               // Read bit from bus twice.\r
+               bitA = OWI_ReadBit(pin);\r
+               bitB = OWI_ReadBit(pin);\r
+               \r
+               if (bitA && bitB) {\r
+                       // Both bits 1 (Error).\r
+                       newDeviation = OWI_ROM_SEARCH_FAILED;\r
+                       return newDeviation;\r
+               } else if (bitA ^ bitB) {\r
+                       // Bits A and B are different. All devices have the same bit here.\r
+                       // Set the bit in bitPattern to this value.\r
+                       if (bitA) {\r
+                               (*bitPattern) |= bitMask;\r
+                       } else {\r
+                               (*bitPattern) &= ~bitMask;\r
+                       }\r
+               } else {\r
+                       // If this is where a choice was made the last time,\r
+                       // a '1' bit is selected this time.\r
+                       if (currentBit == lastDeviation) {\r
+                               (*bitPattern) |= bitMask;\r
+                       }\r
+                       \r
+                       // For the rest of the id, '0' bits are selected when\r
+                       // discrepancies occur.\r
+                       else if (currentBit > lastDeviation) {\r
+                               (*bitPattern) &= ~bitMask;\r
+                               newDeviation = currentBit;\r
+                       }\r
+                       \r
+                       // If current bit in bit pattern = 0, then this is\r
+                       // out new deviation.\r
+                       else if ( !(*bitPattern & bitMask)) {\r
+                               newDeviation = currentBit;\r
+                       }\r
+                       \r
+               // IF the bit is already 1, do nothing.\r
+                       else {\r
+                       }\r
+               }\r
+               \r
+               // Send the selected bit to the bus.\r
+               if ((*bitPattern) & bitMask) {\r
+                       OWI_WriteBit1(pin);\r
+               } else {\r
+                       OWI_WriteBit0(pin);\r
+               }\r
+               \r
+               // Increment current bit.    \r
+               currentBit++;\r
+               \r
+               // Adjust bitMask and bitPattern pointer.    \r
+               bitMask <<= 1;\r
+               if (!bitMask) {\r
+                       bitMask = 0x01;\r
+                       bitPattern++;\r
+               }\r
+       }\r
+       \r
+       return newDeviation;\r
+}\r
+\r
+\r
+/* Functions for handling CRC */\r
+/*! \brief  Compute the CRC8 value of a data set.\r
+ *\r
+ *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
+ *  as inital value for the CRC.\r
+ *\r
+ *  \param  inData  One byte of data to compute CRC from.\r
+ *\r
+ *  \param  seed    The starting value of the CRC.\r
+ *\r
+ *  \return The CRC8 of inData with seed as initial value.\r
+ *\r
+ *  \note   Setting seed to 0 computes the crc8 of the inData.\r
+ *\r
+ *  \note   Constantly passing the return value of this function \r
+ *          As the seed argument computes the CRC8 value of a\r
+ *          longer string of data.\r
+ */\r
+unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
+{\r
+       unsigned char bitsLeft;\r
+       unsigned char temp;\r
+       \r
+       for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+               temp = ((seed ^ inData) & 0x01);\r
+               \r
+               if (temp == 0) {\r
+               seed >>= 1;\r
+               } else {\r
+                       seed ^= 0x18;\r
+                       seed >>= 1;\r
+                       seed |= 0x80;\r
+               }\r
+               \r
+               inData >>= 1;\r
+       }\r
+       return seed;    \r
+}\r
+\r
+\r
+/*! \brief  Compute the CRC16 value of a data set.\r
+ *\r
+ *  This function will compute the CRC16 of inData using seed\r
+ *  as inital value for the CRC.\r
+ *\r
+ *  \param  inData  One byte of data to compute CRC from.\r
+ *\r
+ *  \param  seed    The starting value of the CRC.\r
+ *\r
+ *  \return The CRC16 of inData with seed as initial value.\r
+ *\r
+ *  \note   Setting seed to 0 computes the crc16 of the inData.\r
+ *\r
+ *  \note   Constantly passing the return value of this function \r
+ *          As the seed argument computes the CRC16 value of a\r
+ *          longer string of data.\r
+ */\r
+unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
+{\r
+       unsigned char bitsLeft;\r
+       unsigned char temp;\r
+       \r
+       for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+               temp = ((seed ^ inData) & 0x01);\r
+               \r
+               if (temp == 0) {\r
+                       seed >>= 1;\r
+         } else {\r
+                       seed ^= 0x4002;\r
+                       seed >>= 1;\r
+                       seed |= 0x8000;\r
+               }\r
+\r
+               inData >>= 1;\r
+       }\r
+       \r
+       return seed;    \r
+}\r
+\r
+\r
+/*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
+ *  \r
+ *  This function computes the CRC8 value of the first 56 bits of a\r
+ *  64 bit identifier. It then checks the calculated value against the\r
+ *  CRC value stored in ROM.\r
+ *\r
+ *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
+ *\r
+ *  \retval OWI_CRC_OK      The CRC's matched.\r
+ *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
+ */\r
+unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
+{\r
+       unsigned char i;\r
+       unsigned char crc8 = 0;\r
+       \r
+       for (i = 0; i < 7; i++) {\r
+               crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
+               romValue++;\r
+       }\r
+       \r
+       if (crc8 == (*romValue)) {\r
+               return OWI_CRC_OK;\r
+       }\r
+       \r
+       return OWI_CRC_ERROR;\r
+}\r
diff --git a/BaseTinyFirmware/IAR/OWI.h b/BaseTinyFirmware/IAR/OWI.h
new file mode 100644 (file)
index 0000000..f07f7a2
--- /dev/null
@@ -0,0 +1,178 @@
+// This file has been prepared for Doxygen automatic documentation generation.\r
+/*! \file ********************************************************************\r
+ *\r
+ * \brief\r
+ *      Header file for OWI.c\r
+ *\r
+ *      Contains definitions used in the polled 1-Wire(R) driver.\r
+ *\r
+ * \par Application Note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+ *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+****************************************************************************/\r
+\r
+#ifndef OWI_H\r
+#define OWI_H\r
+\r
+#include <ioavr.h>\r
+\r
+\r
+//******************************************************************************\r
+// Defines for CRC-functions\r
+//******************************************************************************\r
+#define     OWI_CRC_OK      0x00    //!< CRC check succeded\r
+#define     OWI_CRC_ERROR   0x01    //!< CRC check failed\r
+\r
+\r
+//******************************************************************************\r
+// Defines for OWI-functions\r
+//******************************************************************************\r
+/*! \brief  CPU clock frequency. \r
+ *  \r
+ *  This define is used to calculate delays when the software only driver\r
+ *  is used. The CPU frequency must be at least 2.170 MHz to be able to\r
+ *  generate the shortest delays.\r
+ */\r
+#define     CPU_FREQUENCY   8.000\r
+\r
+\r
+/*! \brief  Use internal pull-up resistor on 1-Wire buses.\r
+ *\r
+ *  If this symbol is defined, the internal pull-up resister on the GPIO pins \r
+ *  of the AVR will be used to generate the necessary pull-up on the bus. If \r
+ *  an external pull-up resistor is used, uncomment this define.\r
+ */\r
+//#define     OWI_USE_INTERNAL_PULLUP\r
+\r
+\r
+// Port configuration registers for 1-Wire buses.\r
+// Make sure that all three registers belong to the same port.\r
+#define     OWI_PORT        PORTA   //!< 1-Wire PORT Data register.\r
+#define     OWI_PIN         PINA    //!< 1-Wire Input pin register.\r
+#define     OWI_DDR         DDRA    //!< 1-Wire Data direction register.\r
+\r
+\r
+//******************************************************************************\r
+// Pin bitmasks\r
+//******************************************************************************\r
+#define     OWI_PIN_0       0x01\r
+#define     OWI_PIN_1       0x02\r
+#define     OWI_PIN_2       0x04\r
+#define     OWI_PIN_3       0x08\r
+#define     OWI_PIN_4       0x10\r
+#define     OWI_PIN_5       0x20\r
+#define     OWI_PIN_6       0x40\r
+#define     OWI_PIN_7       0x80\r
+\r
+\r
+//******************************************************************************\r
+// Timing parameters\r
+//******************************************************************************\r
+//! Timing delay when pulling bus low and releasing bus.\r
+#define     OWI_DELAY_OFFSET_CYCLES    13   \r
+\r
+// Bit timing delays in clock cycles (= us*clock freq in MHz).\r
+#define     OWI_DELAY_A_STD_MODE    (unsigned long)((6   * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_B_STD_MODE    (unsigned long)((64  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_C_STD_MODE    (unsigned long)((60  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_D_STD_MODE    (unsigned long)((10  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_E_STD_MODE    (unsigned long)((9   * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_F_STD_MODE    (unsigned long)((55  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+//#define     OWI_DELAY_G_STD_MODE  (unsigned long)((0   * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_H_STD_MODE    (unsigned long)((480 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_I_STD_MODE    (unsigned long)((70  * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+#define     OWI_DELAY_J_STD_MODE    (unsigned long)((410 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES)\r
+\r
+\r
+//******************************************************************************\r
+// ROM commands\r
+//******************************************************************************\r
+#define     OWI_ROM_READ    0x33    //!< READ ROM command code.\r
+#define     OWI_ROM_SKIP    0xcc    //!< SKIP ROM command code.\r
+#define     OWI_ROM_MATCH   0x55    //!< MATCH ROM command code.\r
+#define     OWI_ROM_SEARCH  0xf0    //!< SEARCH ROM command code.\r
+\r
+\r
+//******************************************************************************\r
+// Return codes\r
+//******************************************************************************\r
+#define     OWI_ROM_SEARCH_FINISHED     0x00   //!< Search finished return code.\r
+#define     OWI_ROM_SEARCH_FAILED       0xff   //!< Search failed return code.\r
+\r
+\r
+//******************************************************************************\r
+// Macros\r
+//******************************************************************************\r
+/*! \brief Pull 1-Wire bus low.\r
+ *\r
+ *  This macro sets the direction of the 1-Wire pin(s) to output and \r
+ *  pull the line(s) low.\r
+ *  \r
+ *  \param bitMask  A bitmask of the buses to pull low.\r
+ */\r
+#define OWI_PULL_BUS_LOW(bitMask) \\r
+                       OWI_DDR |= (bitMask); \\r
+                       OWI_PORT &= ~(bitMask)\r
+\r
+\r
+/*! \def OWI_RELEASE_BUS(bitMask)\r
+ *\r
+ * \brief  Release the bus. \r
+ *\r
+ * This macro releases the bus and enables the internal pull-up if\r
+ * it is used.\r
+ *\r
+ * \param  bitMask A bitmask of the buses to release.\r
+ */\r
+#ifdef OWI_USE_INTERNAL_PULLUP            \r
+       // Set 1-Wire pin(s) to input and enable internal pull-up resistor.\r
+#define OWI_RELEASE_BUS(bitMask) \\r
+                       OWI_DDR &= ~(bitMask); \\r
+                       OWI_PORT |= (bitMask)\r
+\r
+#else\r
+       // Set 1-Wire pin(s) to input mode. No internal pull-up enabled.\r
+#define OWI_RELEASE_BUS(bitMask) \\r
+                       OWI_DDR &= ~(bitMask); \\r
+                       OWI_PORT &= ~(bitMask)\r
+\r
+#endif\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+void OWI_SendByte(unsigned char data, unsigned char pins);\r
+unsigned char OWI_ReceiveByte(unsigned char pin);\r
+void OWI_SkipRom(unsigned char pins);\r
+void OWI_ReadRom(unsigned char * romValue, unsigned char pin);\r
+void OWI_MatchRom(unsigned char * romValue, unsigned char pins);\r
+unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+                                                                        unsigned char lastDeviation, unsigned char pin);\r
+void OWI_Init(unsigned char pins);\r
+void OWI_WriteBit1(unsigned char pins);\r
+void OWI_WriteBit0(unsigned char pins);\r
+unsigned char OWI_ReadBit(unsigned char pins);\r
+unsigned char OWI_DetectPresence(unsigned char pins);\r
+\r
+unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed);\r
+unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed);\r
+unsigned char OWI_CheckRomCRC(unsigned char *romValue);\r
+\r
+#endif // OWI_H\r
+\r
diff --git a/BaseTinyFirmware/IAR/PWM.c b/BaseTinyFirmware/IAR/PWM.c
new file mode 100644 (file)
index 0000000..b00c75a
--- /dev/null
@@ -0,0 +1,150 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for use of PWM\r
+ *\r
+ *      Contains functions for initializing and controlling PWM output.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+\r
+#include "enums.h"\r
+\r
+#include "main.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Stops PWM output\r
+ *\r
+ */\r
+void PWM_Stop(void)\r
+{\r
+       OCR1B = 0;  // Reset compare level.\r
+       PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
+       TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
+       TCCR1B = 0; // Stop timer/counter1.\r
+       TCCR1C = 0; // Set normal port operation.\r
+       TCCR1D = 0; // No fault protection, normal waveform.\r
+       OCR1C = 0;  // Reset compare.\r
+       OCR1D = 0;  // Reset compare.\r
+       DT1 = 0;    // No dead time values.\r
+}\r
+\r
+\r
+/*! \brief Initializes and starts PWM output\r
+ *\r
+ * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
+ * Its comparator is connected to PB3 and will output high until timer1 reaches\r
+ * the value of OCR1B. It is then dropped to 0.\n\r
+ * The comparator outputs high again when the counter overflows, which will\r
+ * happen at a rate of 250 kHz.\r
+ */\r
+void PWM_Start(void)\r
+{\r
+       // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
+       TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
+       \r
+       // Non-inverted PWM, T/C stopped.\r
+       TCCR1B = 0;\r
+       \r
+       // Copy shadow bits, disconnect OC1D.\r
+       TCCR1C = (TCCR1A & 0xF0);\r
+       \r
+       // No fault protection, use phase & frequency correct PWM.\r
+       TCCR1D = (0<<WGM11)|(1<WGM10);\r
+       \r
+       // Does not matter -- PWM6 mode not used.\r
+       TCCR1E = 0;\r
+       \r
+       // Does not matter -- OC1A is disabled.\r
+       OCR1A = 0;\r
+       \r
+       // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
+       OCR1B = PWM_OFFSET;\r
+       \r
+       // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
+       OCR1C = 0xFF;\r
+       \r
+       // Does not matter -- OC1D is disabled.\r
+       OCR1D = 0;\r
+       \r
+       // No dead time values.\r
+       DT1 = 0;\r
+       \r
+       // Set PWM port pin to output.\r
+       DDRB |= (1<<PB3);\r
+       \r
+       // Enable PLL, use full speed mode.\r
+       PLLCSR = (0<<LSM) | (1<<PLLE);\r
+       \r
+       // Use general timer and wait 1 ms for PLL lock to settle.\r
+       Time_Set(TIMER_GEN,0,0,1);\r
+       do{ \r
+       }while(Time_Left(TIMER_GEN));\r
+       \r
+       // Now wait for PLL to lock.\r
+       do{ \r
+       }while((PLLCSR & (1<<PLOCK)) == 0);\r
+\r
+       // Use PLL as clock source.\r
+       PLLCSR |= (1<<PCKE);\r
+       \r
+       // CLK PCK = 64MHz / 1 = 64MHz.\r
+       TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
+}\r
+\r
+\r
+/*! \brief Increments the PWM duty cycle, if not already at max\r
+ *\r
+ * \retval TRUE Success, duty cycle could be incremented.\r
+ * \retval FALSE Failure, duty cycle already at maximum.\r
+ */\r
+unsigned char PWM_IncrementDutyCycle(void){\r
+\r
+       if (OCR1B < PWM_MAX) {\r
+               OCR1B += 1;\r
+               return(TRUE);\r
+       } else {\r
+               return(FALSE);\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Decrements the PWM duty cycle, if not already at zero.\r
+ *\r
+ * \retval TRUE Success, duty cycle could be decremented.\r
+ * \retval FALSE Failure, duty cycle already at zero.\r
+ */\r
+unsigned char PWM_DecrementDutyCycle(void){\r
+       \r
+       if (OCR1B > 0)  {\r
+               OCR1B -= 1;\r
+               return(TRUE);\r
+       } else {\r
+               return(FALSE);\r
+       }\r
+}\r
diff --git a/BaseTinyFirmware/IAR/PWM.h b/BaseTinyFirmware/IAR/PWM.h
new file mode 100644 (file)
index 0000000..bda3a88
--- /dev/null
@@ -0,0 +1,50 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Header file for PWM.c\r
+ *\r
+ *      Contains definitions to control PWM behaviour.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef PWM_H\r
+#define PWM_H\r
+\r
+//******************************************************************************\r
+// Constants for PWM\r
+//******************************************************************************\r
+//! Needed for JumperCheck() to succeed. ADC is saturated otherwise!\r
+#define PWM_OFFSET     12\r
+\r
+//! PWM duty cycle limit (must be less than 256).\r
+#define PWM_MAX        255\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+void PWM_Start(void);\r
+void PWM_Stop(void);\r
+unsigned char PWM_IncrementDutyCycle(void);\r
+unsigned char PWM_DecrementDutyCycle(void);\r
+\r
+#endif // PWM_H\r
+\r
diff --git a/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny.hex b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny.hex
new file mode 100644 (file)
index 0000000..1bf58a1
--- /dev/null
@@ -0,0 +1,298 @@
+:020000020000FC\r
+:100000004BC8189518951895189518951895189522\r
+:100010001FC3189518951CC018951895A1C7189559\r
+:100020001895189518950AFF061428071E9D012893\r
+:100030006707329D013C9D01469D015065075A6945\r
+:10004000070000005300440100007400D000FA11C2\r
+:100050004A92BA93AA939A938A93FA93EA933A921A\r
+:100060002A921A920A927A936A935A934A933A93EB\r
+:100070002A931A930A934FB680E090E03798A4E44D\r
+:10008000B1E00C910F710A9549F00A9571F00A954B\r
+:1000900099F0025011F1025181F17EC004B115B105\r
+:1000A000FD010483158302E078C004B115B1FD01A0\r
+:1000B0000283138303E071C024B135B104E092D010\r
+:1000C000FD0100871187003311410C9110F40F7B63\r
+:1000D00001C000640C9305E060C004B115B1FD01DE\r
+:1000E0000683178324B135B140E050E0ECD77AD0D5\r
+:1000F000FD010287138707E150C004B115B112302A\r
+:10010000C0F000E014E024B135B1021B130BFD0177\r
+:10011000218122952F7030E0200F311F40E050E008\r
+:10012000D2D793D0119501951040FD010487158712\r
+:1001300014C004B115B1012B69F024B135B1FD0132\r
+:10014000018102950F70201B304040E050E0BBD78A\r
+:100150007CD0EBCFFD018487858724853585008D94\r
+:100160000370000FE00FF81F26873787FD01008D11\r
+:100170000395008F3E9604E021913191820F931FE9\r
+:100180000A95D1F78C0144E050E0E1D7FD01068BE0\r
+:10019000178B0C9100620C9301E01C91107E0F7183\r
+:1001A000012B0C930F71005C07B91F980C91007A1A\r
+:1001B000003A19F006B1006C06B94FBE09911991C9\r
+:1001C00029913991499159916991799109901990A1\r
+:1001D00029903990E991F99189919991A991B991D1\r
+:1001E000499018952A2EBC01A02FC9010330A901FE\r
+:1001F000A1F40DE110E077D7369527953695279530\r
+:10020000200D311D9695879596958795969587959E\r
+:1002100096958795820F931F14C007E210E063D76D\r
+:1002200096958795969587959695879596958795B2\r
+:10023000800D911DA33028F48C0143E04A1B69D73F\r
+:10024000C8018C01CB01A22D08952A2EBC01A02F3C\r
+:10025000C9010330A901A9F405E110E044D736959E\r
+:100260002795369527953695279536952795021B20\r
+:10027000130B880F892F881F90E0991F800F911F03\r
+:100280001AC00CE110E02FD798018C011695079544\r
+:100290001695079516950795201B310B8C0145E0A7\r
+:1002A00038D7C801820F931FA33028F48C0143E094\r
+:1002B0004A1B2FD7C8018C01CB01A22D0895FFCF77\r
+:1002C000F894E4E4F1E000810F7700830AB3097049\r
+:1002D0000ABB0BB309700BBB03E407B900E003B919\r
+:1002E00007EC06B9349BFECF349A2181207F04B1FC\r
+:1002F00015B10F70022B018316E517B917EC16B96B\r
+:10030000349BFECF349A0F7024B135B12295207FF3\r
+:10031000202B21830081007C0160008301E407B968\r
+:1003200000E0068B078B3E9624E0019301932A950B\r
+:10033000E1F70FEC06B97894FFCF009184010E51DC\r
+:1003400049F0045149F10A5009F44AC00A5009F42D\r
+:100350005EC077C0E1E6F1E0048115814AE050E03B\r
+:10036000DED6EFE7F1E00283138302E30483EEE6D7\r
+:10037000F1E0008308EB1BE00383148305E010E049\r
+:100380000187128703E2078310871787108B24D118\r
+:1003900040E010E022E037C021E631E0F9010481BD\r
+:1003A0001581EFE7F1E0028313830CE30483EEE6AB\r
+:1003B000F1E00BE1008300EC12E1038314830DE212\r
+:1003C00010E00183128302E30783108701E00387B3\r
+:1003D00014871587168740E0F9012085318515C0FF\r
+:1003E000E1E6F1E0048115814AE050E098D6EFE7BC\r
+:1003F000F1E00283138306E404830AE100936E01B3\r
+:1004000040E010E02EE130E001E0E9D596C3D9D01C\r
+:10041000E1E6F1E000810260008300916D0110E0EF\r
+:100420000F5F1F4F42E050E092D621E030E0240FF2\r
+:10043000351FA90148D6017011F004E1089508E2C2\r
+:1004400008950AE0089500951AB310231ABB1BB350\r
+:1004500010231BBB0CEB13E001501040E9F700C068\r
+:1004600008951FB7F8942AB3202B2ABB00952BB30D\r
+:1004700020232BBB2BE02A95F1F700C02AB32023C1\r
+:100480002ABB2BB320232BBB06EA0A95F1F7000009\r
+:100490001FBF08951FB7F8942AB3202B2ABB0095DD\r
+:1004A0002BB320232BBB2BE92A95F1F700C02AB3ED\r
+:1004B00020232ABB2BB320232BBB06E10A95F1F79F\r
+:1004C00000001FBF08952FB7F8941AB3102B1ABB62\r
+:1004D000102F10953BB331233BBB3BE03A95F1F72E\r
+:1004E00000C03AB331233ABB3BB331233BBB13E1EA\r
+:1004F0001A95F1F700C019B310230EE80A95F1F729\r
+:1005000000002FBF012F08952FB7F8941AB3102BB6\r
+:100510001ABB102F10953BB331233BBB4CEB53E080\r
+:1005200041505040E9F700C03AB331233ABB3BB3E6\r
+:1005300031233BBB16EB1A95F1F7000019B3109568\r
+:10054000012340E353E041505040E9F700C02FBF82\r
+:100550000895AA939A938A93A02F912F88E0A0FBE5\r
+:10056000092F16F47EDF01C095DFA6958A95B9F7AD\r
+:1005700089919991A9910895AA939A938A93A02F0A\r
+:1005800090E088E096950A2F9EDF002309F090689E\r
+:100590008A95C1F7092F89919991A991089538E019\r
+:1005A000212F2170402F4170422711F4169504C06D\r
+:1005B00028E112271695106806953A9589F7012FBC\r
+:1005C000089500E00CBD09BD00BF0FBD07BD06BD0D\r
+:1005D0000BBD0ABD04BD089501E200BF00E00FBDE0\r
+:1005E00000B7007F07BD00E006BD00B90DBD0CE0FF\r
+:1005F0000CBD0FEF0BBD00E00ABD04BDBB9A02E0CD\r
+:1006000009BD41E010E020E030E0E9D402E0D3D4BD\r
+:100610000023E1F709B500FFFDCF09B5046009BD6E\r
+:100620000FB501600FBD08950CB50F3F29F00CB553\r
+:1006300003950CBD01E0089500E008950CB500237A\r
+:1006400029F00CB50A950CBD01E0089500E008956D\r
+:100650008A93FA93EA933A922A921A920A927A9396\r
+:100660006A935A934A933A932A931A930A938FB7A9\r
+:1006700000E0A1D4002331F4EDE5F1E002810F7335\r
+:100680000064028340E011E020E030E000E0A7D405\r
+:1006900000E40EB9EDE5F1E003810460038312810B\r
+:1006A000012F000F001F001F0370015029F00A9551\r
+:1006B00001F10A9531F172C00FB10083002309F4F2\r
+:1006C0006DC006FF03C003810E7F02C0038101607D\r
+:1006D0000383008107FF03C00381026002C003811E\r
+:1006E0000D7F038300810F73006802830CEC83D0BD\r
+:1006F00055C00FB100830183012F006C02830BEB07\r
+:10070000F6CF212F107C022F0A950F73012B028345\r
+:100710002F7309F440C02181138110FF2EC02A9548\r
+:1007200049F02A9571F02A9591F02A95B1F02A9511\r
+:10073000E1F021C00F7310E0F801EC5BFE4F008187\r
+:10074000D6CF0F7310E0F801E359FE4FF8CF0F73C7\r
+:1007500010E0F801EF59FE4FF2CF0F7310E041E0C7\r
+:1007600050E0400F511FAFD4C2CF0F7310E0F8011B\r
+:10077000E957FE4FE4CF00E0BACF1FB110832450F9\r
+:1007800069F4212F0F7310E041E050E0400F511F3A\r
+:10079000022FA5D403C00F73006402838FBF099199\r
+:1007A00019912991399149915991699179910990BA\r
+:1007B000199029903990E991F99189911895F894B7\r
+:1007C000B99A17B31A7F17BB18B3156018BB000F7F\r
+:1007D000000F08650DB9EDE5F1E000E0008303814D\r
+:1007E0000C7F038300E4028300E001830381037F25\r
+:1007F0000383789408951EB11F70EDE5F1E029F0B0\r
+:1008000003810860038300E008951381137F13833D\r
+:100810000FB901E00895BA93AA938A9381E0E1E6C3\r
+:10082000F1E0A481B58110D0002309F480E0E1E675\r
+:10083000F1E004811581A017B10709F080E0082FCD\r
+:100840008991A991B9910895BA93AA939A938A9399\r
+:10085000A1E6B1E00C910C7F04600C9300E0FD0177\r
+:10086000018302830483058306830783008701874E\r
+:10087000028703871ED1DBD0102F117010FB0C9163\r
+:1008800004F90C93E4E4F1E002851385003629E0D5\r
+:10089000120718F00C910B7F0C930285023D1F404C\r
+:1008A00018F00C9102600C930CB5002319F40C9114\r
+:1008B00002FF08C00CB5002351F08689978981306A\r
+:1008C00090402CF00C9101600C9301E004C00C915D\r
+:1008D0000B7F0C9300E01C9114FF00E0899199912B\r
+:1008E000A991B99108958A927A926A925A924A92FB\r
+:1008F000BA93AA939A938A9390E0A3E0B0E0772406\r
+:1009000001E002DE013009F055C011E003E321DE11\r
+:1009100001E032DE502E10E042DE802F06E0402E55\r
+:1009200001E02ADE182F3BDE802F4A94C9F701E050\r
+:1009300023DE182F34DE0023E9F550926201009186\r
+:1009400062010930B9F5492E429400EF4022440C6F\r
+:1009500011E003ECFEDD11E0042DFBDD11E000E011\r
+:10096000F8DD10E003EC1BDE102F042D18DE102F35\r
+:1009700000E015DE802F01E0FFDD182F10DE0023E0\r
+:10098000C9F480E02D0100E2602E01E0F5DD802E4B\r
+:10099000182F05DE802F082DA201A1D301E0400E03\r
+:1009A000571C6A9491F7E8DD182FF9DD002311F444\r
+:1009B000739408C0AD0110E200E091D34F5F5F4F28\r
+:1009C0001A95D1F793959096943008F498CF072D07\r
+:1009D00089919991A991B99149905990699079908B\r
+:1009E000899008958A93802F44E610E020E030E05B\r
+:1009F00002E0F5D280936D0101E010E0482F4C5FDA\r
+:100A000082D318B3102B18BB01E010E045E0481B5F\r
+:100A10007AD3009518B3102318BB02E0CCD2002380\r
+:100A2000E1F78991089508B30F7C08BB08953B2F27\r
+:100A30002A2E40E0E0EDF0E024E001E611E0A6E43B\r
+:100A4000B1E06D917C910080118060157105F0F02E\r
+:100A50000280138006161706C8F046815781D80118\r
+:100A600014964D935C9340855185D80116964D930D\r
+:100A70005C9342855385D80118964D935C934485C9\r
+:100A80005585D8011A964D935C9341E03E962A9580\r
+:100A9000B1F6442351F420E0F80124832583268312\r
+:100AA00027832087218722872387042FA22DB32F16\r
+:100AB0000895BA933A2E282E00E080E0A1E6B1E036\r
+:100AC000482F50E09A01440F551F420F531F28E052\r
+:100AD00031E0240F351FE4E4F1E044815581F90150\r
+:100AE0006081718146175707D0F0082F000F000F63\r
+:100AF000FD010283F9014281FD0143830091480118\r
+:100B0000152FF90120813181021B130B000F111FDA\r
+:100B100050E005D3FD011281101B128301E0839583\r
+:100B2000843110F4002361F2002319F400E50093EE\r
+:100B30006301822DA32DB99108955A924A92BA93D6\r
+:100B4000AA939A938A9355244424B9DB00916D01AA\r
+:100B500010E041E050E0400F511FB5D2047031F079\r
+:100B6000442443947BD200E00CBD25C0442011F006\r
+:100B7000442477D2E4E4F1E00689178911234AF08E\r
+:100B8000A1E8B1E0ED91FC91CF0103970817190797\r
+:100B900058F44ADD002379F404E09FD10AE500937C\r
+:100BA00083015524539407C03396E017F10718F4D6\r
+:100BB00045DD002389F30DD0002311F4552029F2DF\r
+:100BC0000091830189919991A991B9914990599086\r
+:100BD00008959A928A927A926A925A924A92BA9313\r
+:100BE000AA939A938A9377246ADB6624639484E4B5\r
+:100BF00091E001E6402E01E0502EAEE6B1E00C910E\r
+:100C0000062109F47CC0062D0A9551F00A9509F1D8\r
+:100C1000025051F1045079F1085009F453C06FC0EB\r
+:100C2000FD0105851685FC01228533850217130712\r
+:100C300020F4FD012587368762C0021B130BFD01DE\r
+:100C4000218132810217130708F459C07724739465\r
+:100C500056C0FC0102851385FD01238134810217F2\r
+:100C6000130708F44CC0F2CFFD0105811681FC0189\r
+:100C700026893789F4CFFC0104811581FD01878421\r
+:100C800090888016910668F4FC0104811581FD01AD\r
+:100C90000787108B40E01EE120E030E003E09FD1A9\r
+:100CA0002EC0801A910AF201438150E0FD010385B4\r
+:100CB000148519D28014910410F103E07CD1002333\r
+:100CC00029F6E2CF01E077D10023C9F477247394A9\r
+:100CD0000C9105FF14C075DC00916D0110E041E03E\r
+:100CE00050E0400F511FEFD10E7FF9D1F20100818A\r
+:100CF0000860008300E1F1D00AE5FD01058B660C78\r
+:100D000009F07DCFE1E6F1E00281FD012185328528\r
+:100D1000102F110F110B2017310744F4102F110F52\r
+:100D2000110B278130850217130740F04ADC08E0D9\r
+:100D3000D4D00AE5FD01058B772473946CDD002384\r
+:100D400031F43FDC0AE0FD01058B772473940091B8\r
+:100D5000440106FD06C035DC08E2FD01058B772461\r
+:100D60007394072D89919991A991B99149905990BE\r
+:100D7000699079908990999008959A938A932AE03E\r
+:100D80002093840180E090E000E006C01A3019F45E\r
+:100D90003196859194910395402F50E0BA01440F0C\r
+:100DA000551F460F571FE6E2F0E0E40FF51F1491C0\r
+:100DB000112361F700E08030900719F0FC010995DC\r
+:100DC000202F009184012017A9F32093840100E0D3\r
+:100DD000402F50E0BA01440F551F460F571FE6E25F\r
+:100DE000F0E0E40FF51F1491112321F330918401F9\r
+:100DF000131719F43196859194910395E9CF8A934D\r
+:100E0000F89400E808BD00E008BD01E01CDB43E009\r
+:100E100050E010E800E063D14F5F5F4F1A95D1F7C3\r
+:100E200000E307BB00DE00E0CADC4ADA1DD180E047\r
+:100E3000082FD8DD44DA08DD83958230C8F3F3DD6E\r
+:100E400000E000936D010093850104E1899108950C\r
+:100E5000BA93AA939A938A9349D0002311F40AE58E\r
+:100E60002FC081E090E0AC012ED1017079F4AC018B\r
+:100E70004F5F5F4F28D1017049F4E5E8F1E0008150\r
+:100E800002600083009184010183E9CFA0E0B0E01B\r
+:100E9000AC014A0F5B1F17D1017069F00A2FA2DD68\r
+:100EA0000EDAD2DC002339F00091610101FD03C0AC\r
+:100EB0001ADD0EE105C0A395A23048F3B4DD08E2C7\r
+:100EC00089919991A991B991089504E10895F7D96B\r
+:100ED000FFCF77DBA8DDF3D9FFCFE5E8F1E01081A4\r
+:100EE000102B10830091840101830895BA93AA9373\r
+:100EF0009ADD72DB40E011E020E030E002E06FD0EC\r
+:100F0000A4E4B1E010C01C960D911C911D97BCD0BB\r
+:100F1000053610407CF488DB002361F0D0D902E074\r
+:100F20004AD0002339F016960D911C9117970F3F68\r
+:100F3000134019F446DB00E010C018960D911D9186\r
+:100F4000085512402D913C911B97021B130B9CD00E\r
+:100F5000043F1140C4F635DB01E0A991B991089531\r
+:100F6000FA93EA937A936A935A934A931A930A9359\r
+:100F70001FB7E7E8F1E004E04081518162817381AD\r
+:100F8000452B462B472B49F0408141505040604053\r
+:100F90007040408351836283738334960A950023A3\r
+:100FA00059F71FBF09911991499159916991799107\r
+:100FB000E991F991189510E0000F111F000F111F12\r
+:100FC000F801E957FE4F0081118122813381012B05\r
+:100FD000022B032B11F001E0089500E008958A929E\r
+:100FE0006A925A924A92BA93AA939A938A93402EFB\r
+:100FF000812E642EA90160E070E000E61AEE20E088\r
+:1010000030E0B8D0C801D901482D50E060E070E070\r
+:1010100008EE13E020E030E0ADD0080F191F2A1FC2\r
+:101020003B1F462D50E060E070E0400F511F621FF3\r
+:10103000731F5524440C551C440C551CF201E957F0\r
+:10104000FE4F408351836283738389919991A99163\r
+:10105000B9914990599069908990089500E003BF33\r
+:10106000089503E003BF08950DE703BB00E002BB52\r
+:1010700001E005BB03E003BF09B7006109BF789435\r
+:10108000089500008895FECF11231AF4119501955B\r
+:1010900010409801890108950FEC0DBF00E00EBFCC\r
+:1010A000C0EAD0E080D0002309F08DD066DEE9DF11\r
+:1010B000E8CFE199FECF08954F5F5F4FFADF4EBB57\r
+:1010C0005FBBE09A0895FADF0DB308954F5F5F4F5D\r
+:1010D0004EBB5FBBF894E29AE19A0FBE08950FB63B\r
+:1010E000E8DF0DBBF5CF002411240030010741F0EB\r
+:1010F0001695079510F4040E151E440F551FF5CFD5\r
+:10110000002D112D08954A951AF0000F111FFBCFE5\r
+:1011100008954A951AF016950795FBCF0895002477\r
+:101120001124EFE0001F111F001C111C04161506EE\r
+:1011300010F0041A150AEA95AAF7001F111FA00162\r
+:101140000095109508955195419550400895FF27B9\r
+:10115000552312F4F160F7DF112312F4F09506D055\r
+:10116000DEDFF0FD03D0F1FDEECF0895119501957E\r
+:1011700010400895002411241001E02FE12BE22BF0\r
+:10118000E32B71F0369527951795079520F4040EFB\r
+:10119000151E261E371E440F551F661F771FEDCFE5\r
+:1011A00080019101089501E0089520E006D0E9F75B\r
+:1011B0000895259102D0E9F708952D93015010402C\r
+:1011C000202F212B089584E490E0FC0105911491D7\r
+:1011D000FC013296A591B491FC013496259134918D\r
+:1011E000422F432B19F0F901E4DF01C0DEDF069640\r
+:1011F00010E08035910748F308952E0293023C0FCA\r
+:10120000260204012C010A00E8024B03901AEE02A8\r
+:1012100068012C010E006503BE031027E803DB0103\r
+:101220002C01130049048104C05DD007DB01A40137\r
+:101230002600EA0317B9031986031A51031B1C037E\r
+:101240001BE6021BB1021A7D021A4B02191B02187F\r
+:10125000EE0116C301159C011377011255011136D9\r
+:0E126000010F1A010E00010DE9000BD4000A67\r
+:0400000300000000F9\r
+:00000001FF\r
diff --git a/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_data.hex b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_data.hex
new file mode 100644 (file)
index 0000000..8f152e0
--- /dev/null
@@ -0,0 +1,2 @@
+:0400000300000000F9\r
+:00000001FF\r
diff --git a/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_eeprom.hex b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_eeprom.hex
new file mode 100644 (file)
index 0000000..09e3e1c
--- /dev/null
@@ -0,0 +1,12 @@
+:020000020000FC\r
+:1000000001030300000000000000000000000000E9\r
+:1000100000000000000000000000000000000000E0\r
+:1000200000000000000000000000000000000000D0\r
+:1000300000000000000000000000000000000000C0\r
+:1000400000000000000000000000000000000000B0\r
+:1000500000000000000000000000000000000000A0\r
+:100060000000000000000000000000000000000090\r
+:100070000000000000000000000000000000000080\r
+:030080000000007D\r
+:0400000300000000F9\r
+:00000001FF\r
diff --git a/BaseTinyFirmware/IAR/Release/List/ADC.lst b/BaseTinyFirmware/IAR/Release/List/ADC.lst
new file mode 100644 (file)
index 0000000..c465541
--- /dev/null
@@ -0,0 +1,983 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:49:35 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\ADC.c           #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\ADC.c           #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\AD #\r
+#                             C.lst                                           #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC #\r
+#                             .r90                                            #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\ADC.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for use of ADC\r
+      6           *\r
+      7           *      Contains high level functions for initializing the ADC, interrupt\r
+      8           *      handling, and treatment of samples.\n\r
+      9           *      The ADC is set to free running mode and uses an external reference\r
+     10           *      voltage.\n\r
+     11           *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
+     12           *      and restarted by the ISR.\r
+     13           *\r
+     14           * \par Application note:\r
+     15           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     16           *      AVR463: Charging NiMH Batteries with BC100\r
+     17           *\r
+     18           * \par Documentation:\r
+     19           *      For comprehensive code documentation, supported compilers, compiler\r
+     20           *      settings and supported devices see readme.html\r
+     21           *\r
+     22           * \author\r
+     23           *      Atmel Corporation: http://www.atmel.com \n\r
+     24           *      Support email: avr@atmel.com \n\r
+     25           *      Original author: \n\r
+     26           *\r
+     27           * $Name$\r
+     28           * $Revision: 2299 $\r
+     29           * $RCSfile$\r
+     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
+     31           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     32           ******************************************************************************/\r
+     33          \r
+     34          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3b\r
+   \   <unnamed> volatile __io _A_PORTA\r
+   \                     _A_PORTA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3a\r
+   \   <unnamed> volatile __io _A_DDRA\r
+   \                     _A_DDRA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x27\r
+   \   <unnamed> volatile __io _A_ADMUX\r
+   \                     _A_ADMUX:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x26\r
+   \   <unnamed> volatile __io _A_ADCSRA\r
+   \                     _A_ADCSRA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x24\r
+   \   <unnamed> volatile __io _A_ADC\r
+   \                     _A_ADC:\r
+   \   00000000                      DS 2\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x23\r
+   \   <unnamed> volatile __io _A_ADCSRB\r
+   \                     _A_ADCSRB:\r
+   \   00000000                      DS 1\r
+     35          #include <inavr.h>\r
+     36          \r
+     37          #include "structs.h"\r
+     38          \r
+     39          #include "main.h"\r
+     40          #include "ADC.h"\r
+     41          \r
+     42          \r
+     43          //******************************************************************************\r
+     44          // Variables\r
+     45          //******************************************************************************\r
+     46          // ADC status struct.\r
+     47          //! \brief Holds sampled data and ADC-status\r
+     48          ADC_Status_t ADCS;\r
+     49          \r
+     50          \r
+     51          /*! \brief Indicates maximum battery voltage.\r
+     52           *\r
+     53           * This variable is stored in EEPROM and indicates how much the battery voltage\r
+     54           * is downscaled by HW before it is sampled. The amount of downscaling depends\r
+     55           * on the maximum battery voltage, and is necessary to avoid saturation of the\r
+     56           * ADC (reference voltage is 2.5 V).\r
+     57           *\r
+     58           * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
+     59           *\r
+     60           * \note Defaults to 1, which means 10 V max battery voltage.\r
+     61           *\r
+     62           * \note Table of settings:\r
+     63           * <pre>\r
+     64           * VBAT_RANGE | Max battery voltage | Jumper setting\r
+     65           *         0  |             5V      |        1/2\r
+     66           *         1  |            10V      |        1/4\r
+     67           *         2  |            20V      |        1/8\r
+     68           *         3  |            30V      |       1/12\r
+     69           *         4  |            40V      |       1/16\r
+     70           * </pre>\r
+     71           */\r
+     72          // Maximum battery voltage (affects scaling of samples).\r
+\r
+   \                                 In  segment EEPROM_I, align 1, keep-with-next\r
+     73          __eeprom unsigned char VBAT_RANGE = 1;\r
+   \                     VBAT_RANGE:\r
+   \   00000000   01                 DB 1\r
+     74          \r
+     75          \r
+     76          //******************************************************************************\r
+     77          // Functions\r
+     78          //******************************************************************************\r
+     79          /*! \brief Interrupt Service routine for ADC.\r
+     80           *\r
+     81           * This ISR stores the sampled values in the ADC status-struct, then\r
+     82           * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
+     83           * Once the sequence is completed, ADCS.Flag is set and unless\r
+     84           * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
+     85           * is disabled.\n\r
+     86           * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
+     87           *\r
+     88           * \note Table of scanning sequence:\r
+     89           * <pre>\r
+     90           * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
+     91           * ----+--------+----------+----------+------+---------+-------\r
+     92           *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
+     93           *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
+     94           *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
+     95           *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
+     96           *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
+     97           *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
+     98           *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
+     99           *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
+    100           * </pre>\r
+    101           *\r
+    102           * \todo IIN (#7 in sequence) is never used.\r
+    103           *\r
+    104           * \todo Signed is never set. Signed measurements of IBAT will halve the\r
+    105           * measuring sensitivity, and is therefore not favourable. At the moment,\r
+    106           * great currents (f.ex. if something happens with the battery) will be\r
+    107           * interpreted as negative, which might cause unfavourable behaviour during\r
+    108           * charging (depending on what PWM behaviour is defined), f.ex.\r
+    109           * ConstantCurrent() will keep increasing the PWM output. This results in an\r
+    110           * PWM controller error being flagged and the program going into\r
+    111           * error-state and eventually reinitializing.\r
+    112           */\r
+    113          #pragma vector=ADC_vect\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    114          __interrupt void ADC_ISR(void)\r
+   \                     ADC_ISR:\r
+    115          {\r
+   \   00000000   924A               ST      -Y, R4\r
+   \   00000002   93BA               ST      -Y, R27\r
+   \   00000004   93AA               ST      -Y, R26\r
+   \   00000006   939A               ST      -Y, R25\r
+   \   00000008   938A               ST      -Y, R24\r
+   \   0000000A   93FA               ST      -Y, R31\r
+   \   0000000C   93EA               ST      -Y, R30\r
+   \   0000000E   923A               ST      -Y, R3\r
+   \   00000010   922A               ST      -Y, R2\r
+   \   00000012   921A               ST      -Y, R1\r
+   \   00000014   920A               ST      -Y, R0\r
+   \   00000016   937A               ST      -Y, R23\r
+   \   00000018   936A               ST      -Y, R22\r
+   \   0000001A   935A               ST      -Y, R21\r
+   \   0000001C   934A               ST      -Y, R20\r
+   \   0000001E   933A               ST      -Y, R19\r
+   \   00000020   932A               ST      -Y, R18\r
+   \   00000022   931A               ST      -Y, R17\r
+   \   00000024   930A               ST      -Y, R16\r
+   \   00000026   B64F               IN      R4, 0x3F\r
+   \   00000028                      REQUIRE ?Register_R4_is_cg_reg\r
+    116                static unsigned char avgIndex = 0;\r
+    117                unsigned char i, Next, Signed;\r
+    118                signed int  temp = 0;\r
+   \   00000028   E080               LDI     R24, 0\r
+   \   0000002A   E090               LDI     R25, 0\r
+    119                \r
+    120                Signed = FALSE;  // Presume next conversion is unipolar.\r
+    121                ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
+   \   0000002C   9837               CBI     0x06, 0x07\r
+    122                  // conversions take at least 25 ADCCLK. (It is restarted later)\r
+    123                \r
+    124                // Handle the conversion, depending on what channel it is from, then\r
+    125                // switch to the next channel in the sequence.\r
+    126                switch (ADCS.MUX){\r
+   \   0000002E   ....               LDI     R26, LOW(ADCS)\r
+   \   00000030   ....               LDI     R27, (ADCS) >> 8\r
+   \   00000032   910C               LD      R16, X\r
+   \   00000034   710F               ANDI    R16, 0x1F\r
+   \   00000036   950A               DEC     R16\r
+   \   00000038   F049               BREQ    ??ADC_ISR_0\r
+   \   0000003A   950A               DEC     R16\r
+   \   0000003C   F071               BREQ    ??ADC_ISR_1\r
+   \   0000003E   950A               DEC     R16\r
+   \   00000040   F099               BREQ    ??ADC_ISR_2\r
+   \   00000042   5002               SUBI    R16, 2\r
+   \   00000044   F111               BREQ    ??ADC_ISR_3\r
+   \   00000046   5102               SUBI    R16, 18\r
+   \   00000048   F181               BREQ    ??ADC_ISR_4\r
+   \   0000004A   C07E               RJMP    ??ADC_ISR_5\r
+    127                        // MUX = 0b000001 => ADC1 (PA1) = NTC\r
+    128                        case 0x01:\r
+    129                                ADCS.rawNTC = ADC;\r
+   \                     ??ADC_ISR_0:\r
+   \   0000004C   B104               IN      R16, 0x04\r
+   \   0000004E   B115               IN      R17, 0x05\r
+   \   00000050   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000052   8304               STD     Z+4, R16\r
+   \   00000054   8315               STD     Z+5, R17\r
+    130                                Next=0x02;\r
+   \   00000056   E002               LDI     R16, 2\r
+   \   00000058   C078               RJMP    ??ADC_ISR_6\r
+    131                        break;\r
+    132          \r
+    133                        \r
+    134                        // MUX = 0b000010 => ADC2 (PA2) = RID\r
+    135                        case 0x02:\r
+    136                                ADCS.rawRID = ADC;\r
+   \                     ??ADC_ISR_1:\r
+   \   0000005A   B104               IN      R16, 0x04\r
+   \   0000005C   B115               IN      R17, 0x05\r
+   \   0000005E   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000060   8302               STD     Z+2, R16\r
+   \   00000062   8313               STD     Z+3, R17\r
+    137                                Next=0x03;\r
+   \   00000064   E003               LDI     R16, 3\r
+   \   00000066   C071               RJMP    ??ADC_ISR_6\r
+    138                        break;\r
+    139          \r
+    140                        \r
+    141                        // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
+    142                        case 0x03:\r
+    143                                // Supply voltage is always divided by 16.\r
+    144                                ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
+   \                     ??ADC_ISR_2:\r
+   \   00000068   B124               IN      R18, 0x04\r
+   \   0000006A   B135               IN      R19, 0x05\r
+   \   0000006C   E004               LDI     R16, 4\r
+   \   0000006E   ....               RCALL   ScaleU\r
+   \   00000070   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000072   8700               STD     Z+8, R16\r
+   \   00000074   8711               STD     Z+9, R17\r
+    145                                \r
+    146                                // Is mains failing?\r
+    147                                if (ADCS.VIN < VIN_MIN) {\r
+   \   00000076   3300               CPI     R16, 48\r
+   \   00000078   4111               SBCI    R17, 17\r
+   \   0000007A   910C               LD      R16, X\r
+   \   0000007C   F410               BRCC    ??ADC_ISR_7\r
+    148                                        ADCS.Mains = FALSE;\r
+   \   0000007E   7B0F               ANDI    R16, 0xBF\r
+   \   00000080   C001               RJMP    ??ADC_ISR_8\r
+    149                                } else {\r
+    150                                        ADCS.Mains = TRUE;\r
+   \                     ??ADC_ISR_7:\r
+   \   00000082   6400               ORI     R16, 0x40\r
+   \                     ??ADC_ISR_8:\r
+   \   00000084   930C               ST      X, R16\r
+    151                                }\r
+    152                                \r
+    153                                Next=0x05;\r
+   \   00000086   E005               LDI     R16, 5\r
+   \   00000088   C060               RJMP    ??ADC_ISR_6\r
+    154                        break;\r
+    155          \r
+    156                        \r
+    157                        // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
+    158                        case 0x05:\r
+    159                                ADCS.rawVBAT = ADC;\r
+   \                     ??ADC_ISR_3:\r
+   \   0000008A   B104               IN      R16, 0x04\r
+   \   0000008C   B115               IN      R17, 0x05\r
+   \   0000008E   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000090   8306               STD     Z+6, R16\r
+   \   00000092   8317               STD     Z+7, R17\r
+    160                                \r
+    161                                // Scale voltage according to jumper setting.\r
+    162                                ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
+   \   00000094   B124               IN      R18, 0x04\r
+   \   00000096   B135               IN      R19, 0x05\r
+   \   00000098   ....               LDI     R20, LOW(VBAT_RANGE)\r
+   \   0000009A   ....               LDI     R21, (VBAT_RANGE) >> 8\r
+   \   0000009C   ....               RCALL   __eeget8_16\r
+   \   0000009E   ....               RCALL   ScaleU\r
+   \   000000A0   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000A2   8702               STD     Z+10, R16\r
+   \   000000A4   8713               STD     Z+11, R17\r
+    163                                Next=0x17;\r
+   \   000000A6   E107               LDI     R16, 23\r
+   \   000000A8   C050               RJMP    ??ADC_ISR_6\r
+    164          //                    Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
+    165                        break;\r
+    166          \r
+    167          \r
+    168                        case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
+    169                                // If bipolar, from -512 to 0, to 511:\r
+    170                                // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
+    171                        \r
+    172                                // Scale sample according to jumper setting, handle negative numbers.\r
+    173                                if (ADC > 511) {\r
+   \                     ??ADC_ISR_4:\r
+   \   000000AA   B104               IN      R16, 0x04\r
+   \   000000AC   B115               IN      R17, 0x05\r
+   \   000000AE   3012               CPI     R17, 2\r
+   \   000000B0   F0C0               BRCS    ??ADC_ISR_9\r
+    174                                        ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
+    175                                                     (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+   \   000000B2   E000               LDI     R16, 0\r
+   \   000000B4   E014               LDI     R17, 4\r
+   \   000000B6   B124               IN      R18, 0x04\r
+   \   000000B8   B135               IN      R19, 0x05\r
+   \   000000BA   1B02               SUB     R16, R18\r
+   \   000000BC   0B13               SBC     R17, R19\r
+   \   000000BE   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000C0   8121               LDD     R18, Z+1\r
+   \   000000C2   9522               SWAP    R18\r
+   \   000000C4   702F               ANDI    R18, 0x0F\r
+   \   000000C6   E030               LDI     R19, 0\r
+   \   000000C8   0F20               ADD     R18, R16\r
+   \   000000CA   1F31               ADC     R19, R17\r
+   \   000000CC   ....               LDI     R20, LOW(VBAT_RANGE)\r
+   \   000000CE   ....               LDI     R21, (VBAT_RANGE) >> 8\r
+   \   000000D0   ....               RCALL   __eeget8_16\r
+   \   000000D2   ....               RCALL   ScaleI\r
+   \   000000D4   9511               NEG     R17\r
+   \   000000D6   9501               NEG     R16\r
+   \   000000D8   4010               SBCI    R17, 0\r
+   \                     ??ADC_ISR_10:\r
+   \   000000DA   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000DC   8704               STD     Z+12, R16\r
+   \   000000DE   8715               STD     Z+13, R17\r
+   \   000000E0   C014               RJMP    ??ADC_ISR_11\r
+    176                                } else if (ADC > 0) {\r
+   \                     ??ADC_ISR_9:\r
+   \   000000E2   B104               IN      R16, 0x04\r
+   \   000000E4   B115               IN      R17, 0x05\r
+   \   000000E6   2B01               OR      R16, R17\r
+   \   000000E8   F069               BREQ    ??ADC_ISR_12\r
+    177                                        ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
+   \   000000EA   B124               IN      R18, 0x04\r
+   \   000000EC   B135               IN      R19, 0x05\r
+   \   000000EE   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000F0   8101               LDD     R16, Z+1\r
+   \   000000F2   9502               SWAP    R16\r
+   \   000000F4   700F               ANDI    R16, 0x0F\r
+   \   000000F6   1B20               SUB     R18, R16\r
+   \   000000F8   4030               SBCI    R19, 0\r
+   \   000000FA   ....               LDI     R20, LOW(VBAT_RANGE)\r
+   \   000000FC   ....               LDI     R21, (VBAT_RANGE) >> 8\r
+   \   000000FE   ....               RCALL   __eeget8_16\r
+   \   00000100   ....               RCALL   ScaleI\r
+   \   00000102   CFEB               RJMP    ??ADC_ISR_10\r
+    178                                } else {\r
+    179                                        ADCS.IBAT = 0;\r
+   \                     ??ADC_ISR_12:\r
+   \   00000104   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000106   8784               STD     Z+12, R24\r
+   \   00000108   8785               STD     Z+13, R24\r
+    180                                }\r
+    181          \r
+    182                                // Insert sample of battery current into the averaging-array\r
+    183                                // (overwriting the oldest sample), then recalculate and store the\r
+    184                                // average. This is the last conversion in the sequence, so\r
+    185                                // flag a complete ADC-cycle and restart sequence.\r
+    186                                ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
+   \                     ??ADC_ISR_11:\r
+   \   0000010A   8524               LDD     R18, Z+12\r
+   \   0000010C   8535               LDD     R19, Z+13\r
+   \   0000010E   8D00               LDD     R16, Z+24\r
+   \   00000110   7003               ANDI    R16, 0x03\r
+   \   00000112   0F00               LSL     R16\r
+   \   00000114   0FE0               ADD     R30, R16\r
+   \   00000116   1FF8               ADC     R31, R24\r
+   \   00000118   8726               STD     Z+14, R18\r
+   \   0000011A   8737               STD     Z+15, R19\r
+   \   0000011C   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000011E   8D00               LDD     R16, Z+24\r
+   \   00000120   9503               INC     R16\r
+   \   00000122   8F00               STD     Z+24, R16\r
+    187                                for (i = 0; i < 4 ; i++) {\r
+   \   00000124   963E               ADIW    R31:R30, 14\r
+   \   00000126   E004               LDI     R16, 4\r
+    188                                        temp += ADCS.discIBAT[i];\r
+   \                     ??ADC_ISR_13:\r
+   \   00000128   9121               LD      R18, Z+\r
+   \   0000012A   9131               LD      R19, Z+\r
+   \   0000012C   0F82               ADD     R24, R18\r
+   \   0000012E   1F93               ADC     R25, R19\r
+    189                                }\r
+   \   00000130   950A               DEC     R16\r
+   \   00000132   F7D1               BRNE    ??ADC_ISR_13\r
+    190                                \r
+    191                                ADCS.avgIBAT = (temp / 4);\r
+   \   00000134   018C               MOVW    R17:R16, R25:R24\r
+   \   00000136   E044               LDI     R20, 4\r
+   \   00000138   E050               LDI     R21, 0\r
+   \   0000013A   ....               RCALL   ?SS_DIVMOD_L02\r
+   \   0000013C   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000013E   8B06               STD     Z+22, R16\r
+   \   00000140   8B17               STD     Z+23, R17\r
+    192                                \r
+    193                                ADCS.Flag = TRUE;\r
+   \   00000142   910C               LD      R16, X\r
+   \   00000144   6200               ORI     R16, 0x20\r
+   \   00000146   930C               ST      X, R16\r
+    194                                Next=0x01;\r
+    195                                Signed = FALSE;  // This is the only bipolar conversion.\r
+    196                        break;\r
+    197          \r
+    198                        \r
+    199                        default:  // Should not happen. (Invalid MUX-channel)\r
+    200                                Next=0x01;  // Start at the beginning of sequence.\r
+   \                     ??ADC_ISR_5:\r
+   \   00000148   E001               LDI     R16, 1\r
+    201                        break;\r
+    202                }\r
+    203                \r
+    204                // Update MUX to next channel in sequence, set a bipolar conversion if\r
+    205                // this has been flagged.\r
+    206                ADCS.MUX = Next;                    \r
+   \                     ??ADC_ISR_6:\r
+   \   0000014A   911C               LD      R17, X\r
+   \   0000014C   7E10               ANDI    R17, 0xE0\r
+   \   0000014E   710F               ANDI    R16, 0x1F\r
+   \   00000150   2B01               OR      R16, R17\r
+   \   00000152   930C               ST      X, R16\r
+    207                ADMUX = (1<<REFS0) + ADCS.MUX;      \r
+   \   00000154   710F               ANDI    R16, 0x1F\r
+   \   00000156   5C00               SUBI    R16, 192\r
+   \   00000158   B907               OUT     0x07, R16\r
+    208          \r
+    209                if (Signed)     {\r
+    210                  ADCSRB |= (1<<BIN);               \r
+    211                } else {\r
+    212                  ADCSRB &= ~(1<<BIN);              \r
+   \   0000015A   981F               CBI     0x03, 0x07\r
+    213                }\r
+    214          \r
+    215                // Re-enable the ADC unless a halt has been flagged and a conversion\r
+    216                // cycle has completed.\r
+    217                if (!((ADCS.Halt) && (ADCS.Flag))) {\r
+   \   0000015C   910C               LD      R16, X\r
+   \   0000015E   7A00               ANDI    R16, 0xA0\r
+   \   00000160   3A00               CPI     R16, 160\r
+   \   00000162   F019               BREQ    ??ADC_ISR_14\r
+    218                  ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
+   \   00000164   B106               IN      R16, 0x06\r
+   \   00000166   6C00               ORI     R16, 0xC0\r
+   \   00000168   B906               OUT     0x06, R16\r
+    219                }\r
+    220          }\r
+   \                     ??ADC_ISR_14:\r
+   \   0000016A   BE4F               OUT     0x3F, R4\r
+   \   0000016C   9109               LD      R16, Y+\r
+   \   0000016E   9119               LD      R17, Y+\r
+   \   00000170   9129               LD      R18, Y+\r
+   \   00000172   9139               LD      R19, Y+\r
+   \   00000174   9149               LD      R20, Y+\r
+   \   00000176   9159               LD      R21, Y+\r
+   \   00000178   9169               LD      R22, Y+\r
+   \   0000017A   9179               LD      R23, Y+\r
+   \   0000017C   9009               LD      R0, Y+\r
+   \   0000017E   9019               LD      R1, Y+\r
+   \   00000180   9029               LD      R2, Y+\r
+   \   00000182   9039               LD      R3, Y+\r
+   \   00000184   91E9               LD      R30, Y+\r
+   \   00000186   91F9               LD      R31, Y+\r
+   \   00000188   9189               LD      R24, Y+\r
+   \   0000018A   9199               LD      R25, Y+\r
+   \   0000018C   91A9               LD      R26, Y+\r
+   \   0000018E   91B9               LD      R27, Y+\r
+   \   00000190   9049               LD      R4, Y+\r
+   \   00000192   9518               RETI\r
+   \   00000194                      REQUIRE _A_ADMUX\r
+   \   00000194                      REQUIRE _A_ADCSRA\r
+   \   00000194                      REQUIRE _A_ADC\r
+   \   00000194                      REQUIRE _A_ADCSRB\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+   \                     ADCS:\r
+   \   00000000                      DS 24\r
+   \   00000018                      DS 1\r
+    221          \r
+    222          \r
+    223          /*! \brief Scales sample to represent "actual voltage" in mV.\r
+    224           *\r
+    225           * This function returns the actual sampled voltage, scaled according\r
+    226           * to the jumper settings.\r
+    227           *\r
+    228           * \param setting Indicates what downscaling was used.\r
+    229           * \param data The sampled value.\r
+    230           *\r
+    231           * \note Table for setting-parameter:\n\r
+    232           * <pre>\r
+    233           * Presume VREF = 2.5V and Gain = 1x.\r
+    234           * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
+    235           * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
+    236           * --------+--------+------+------------+-----------+-------\r
+    237           *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
+    238           *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
+    239           *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
+    240           *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
+    241           *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
+    242           *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
+    243           *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
+    244           * </pre>\r
+    245           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    246          unsigned int ScaleU(unsigned char setting, unsigned int data)\r
+   \                     ScaleU:\r
+    247          {\r
+   \   00000000   2E2A               MOV     R2, R26\r
+   \   00000002   01BC               MOVW    R23:R22, R25:R24\r
+   \   00000004   2FA0               MOV     R26, R16\r
+   \   00000006   01C9               MOVW    R25:R24, R19:R18\r
+    248                // Temporary variable needed.\r
+    249                unsigned int scaled = 0;\r
+    250          \r
+    251                // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
+    252                if (setting == 3)       {\r
+   \   00000008   3003               CPI     R16, 3\r
+   \   0000000A   01A9               MOVW    R21:R20, R19:R18\r
+   \   0000000C   F4A1               BRNE    ??ScaleU_0\r
+    253                        scaled = 29 * data;\r
+    254                        scaled += (data >> 2);\r
+    255                        scaled += (data >> 4);\r
+   \   0000000E   E10D               LDI     R16, 29\r
+   \   00000010   E010               LDI     R17, 0\r
+   \   00000012   ....               RCALL   ?S_MUL_L02\r
+   \   00000014   9536               LSR     R19\r
+   \   00000016   9527               ROR     R18\r
+   \   00000018   9536               LSR     R19\r
+   \   0000001A   9527               ROR     R18\r
+   \   0000001C   0D20               ADD     R18, R0\r
+   \   0000001E   1D31               ADC     R19, R1\r
+   \   00000020   9596               LSR     R25\r
+   \   00000022   9587               ROR     R24\r
+   \   00000024   9596               LSR     R25\r
+   \   00000026   9587               ROR     R24\r
+   \   00000028   9596               LSR     R25\r
+   \   0000002A   9587               ROR     R24\r
+   \   0000002C   9596               LSR     R25\r
+   \   0000002E   9587               ROR     R24\r
+   \   00000030   0F82               ADD     R24, R18\r
+   \   00000032   1F93               ADC     R25, R19\r
+   \   00000034   C014               RJMP    ??ScaleU_1\r
+    256                } else {\r
+    257                        // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
+    258                        scaled = 39 * data;\r
+    259                        scaled += (data >> 4);\r
+   \                     ??ScaleU_0:\r
+   \   00000036   E207               LDI     R16, 39\r
+   \   00000038   E010               LDI     R17, 0\r
+   \   0000003A   ....               RCALL   ?S_MUL_L02\r
+   \   0000003C   9596               LSR     R25\r
+   \   0000003E   9587               ROR     R24\r
+   \   00000040   9596               LSR     R25\r
+   \   00000042   9587               ROR     R24\r
+   \   00000044   9596               LSR     R25\r
+   \   00000046   9587               ROR     R24\r
+   \   00000048   9596               LSR     R25\r
+   \   0000004A   9587               ROR     R24\r
+   \   0000004C   0D80               ADD     R24, R0\r
+   \   0000004E   1D91               ADC     R25, R1\r
+    260                        \r
+    261                        if (setting <3) {\r
+   \   00000050   30A3               CPI     R26, 3\r
+   \   00000052   F428               BRCC    ??ScaleU_1\r
+    262                                // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
+    263                                //                1: mV/LSB = 9.766 = 39.06 / 4\r
+    264                                //                2: mV/LSB = 19.53 = 39.06 / 2\r
+    265                                scaled = (scaled >> (3-setting));\r
+   \   00000054   018C               MOVW    R17:R16, R25:R24\r
+   \   00000056   E043               LDI     R20, 3\r
+   \   00000058   1B4A               SUB     R20, R26\r
+   \   0000005A   ....               RCALL   ?US_SHR_L02\r
+   \   0000005C   01C8               MOVW    R25:R24, R17:R16\r
+    266                        }\r
+    267                }\r
+    268          \r
+    269                return(scaled);\r
+   \                     ??ScaleU_1:\r
+   \   0000005E   018C               MOVW    R17:R16, R25:R24\r
+   \   00000060   01CB               MOVW    R25:R24, R23:R22\r
+   \   00000062   2DA2               MOV     R26, R2\r
+   \   00000064   9508               RET\r
+    270          }\r
+    271          \r
+    272          \r
+    273          /*! \brief Scales sample to represent "actual current" in mA.\r
+    274           *\r
+    275           * This function returns the actual sampled current, scaled according\r
+    276           * to the jumper settings.\r
+    277           *\r
+    278           * \param setting Indicates what downscaling was used.\r
+    279           * \param data The sampled value.\r
+    280           *\r
+    281           * \note Table for setting-parameter:\n\r
+    282           * <pre>\r
+    283           * Presume VREF = 2.5V and Gain = 1x or 20x.\r
+    284           * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
+    285           * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
+    286           * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
+    287           * --------+------+------------+----------+----------+--------+-----\r
+    288           *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
+    289           *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
+    290           *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
+    291           *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
+    292           *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
+    293           *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
+    294           *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
+    295           * </pre>\r
+    296           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    297          unsigned int ScaleI(unsigned char setting, unsigned int data)\r
+   \                     ScaleI:\r
+    298          {\r
+   \   00000000   2E2A               MOV     R2, R26\r
+   \   00000002   01BC               MOVW    R23:R22, R25:R24\r
+   \   00000004   2FA0               MOV     R26, R16\r
+   \   00000006   01C9               MOVW    R25:R24, R19:R18\r
+    299                // Temporary variable needed.\r
+    300                unsigned int  scaled = 0;\r
+    301                \r
+    302                // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
+    303                if (setting == 3) {\r
+   \   00000008   3003               CPI     R16, 3\r
+   \   0000000A   01A9               MOVW    R21:R20, R19:R18\r
+   \   0000000C   F4A9               BRNE    ??ScaleI_0\r
+    304                        scaled = 21 * data;\r
+    305                        scaled -= (data >> 4);\r
+    306                        scaled += (data >> 7);\r
+   \   0000000E   E105               LDI     R16, 21\r
+   \   00000010   E010               LDI     R17, 0\r
+   \   00000012   ....               RCALL   ?S_MUL_L02\r
+   \   00000014   9536               LSR     R19\r
+   \   00000016   9527               ROR     R18\r
+   \   00000018   9536               LSR     R19\r
+   \   0000001A   9527               ROR     R18\r
+   \   0000001C   9536               LSR     R19\r
+   \   0000001E   9527               ROR     R18\r
+   \   00000020   9536               LSR     R19\r
+   \   00000022   9527               ROR     R18\r
+   \   00000024   1B02               SUB     R16, R18\r
+   \   00000026   0B13               SBC     R17, R19\r
+   \   00000028   0F88               LSL     R24\r
+   \   0000002A   2F89               MOV     R24, R25\r
+   \   0000002C   1F88               ROL     R24\r
+   \   0000002E   E090               LDI     R25, 0\r
+   \   00000030   1F99               ROL     R25\r
+   \   00000032   0F80               ADD     R24, R16\r
+   \   00000034   1F91               ADC     R25, R17\r
+   \   00000036   C01A               RJMP    ??ScaleI_1\r
+    307                }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
+    308                        scaled = 28 * data;\r
+    309                        scaled -= (data >> 3);\r
+    310                        scaled += (data >> 5);\r
+   \                     ??ScaleI_0:\r
+   \   00000038   E10C               LDI     R16, 28\r
+   \   0000003A   E010               LDI     R17, 0\r
+   \   0000003C   ....               RCALL   ?S_MUL_L02\r
+   \   0000003E   0198               MOVW    R19:R18, R17:R16\r
+   \   00000040   018C               MOVW    R17:R16, R25:R24\r
+   \   00000042   9516               LSR     R17\r
+   \   00000044   9507               ROR     R16\r
+   \   00000046   9516               LSR     R17\r
+   \   00000048   9507               ROR     R16\r
+   \   0000004A   9516               LSR     R17\r
+   \   0000004C   9507               ROR     R16\r
+   \   0000004E   1B20               SUB     R18, R16\r
+   \   00000050   0B31               SBC     R19, R17\r
+   \   00000052   018C               MOVW    R17:R16, R25:R24\r
+   \   00000054   E045               LDI     R20, 5\r
+   \   00000056   ....               RCALL   ?US_SHR_L02\r
+   \   00000058   01C8               MOVW    R25:R24, R17:R16\r
+   \   0000005A   0F82               ADD     R24, R18\r
+   \   0000005C   1F93               ADC     R25, R19\r
+    311                        \r
+    312                        if (setting <3) {\r
+   \   0000005E   30A3               CPI     R26, 3\r
+   \   00000060   F428               BRCC    ??ScaleI_1\r
+    313                                // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
+    314                                //                1: mA/LSB = 6.978mA = 27.909 / 4\r
+    315                                //                2: mA/LSB = 13.955mA = 27.909 / 2\r
+    316                                scaled = (scaled >> (3-setting));\r
+   \   00000062   018C               MOVW    R17:R16, R25:R24\r
+   \   00000064   E043               LDI     R20, 3\r
+   \   00000066   1B4A               SUB     R20, R26\r
+   \   00000068   ....               RCALL   ?US_SHR_L02\r
+   \   0000006A   01C8               MOVW    R25:R24, R17:R16\r
+    317                        }\r
+    318                }\r
+    319                \r
+    320                return(scaled);\r
+   \                     ??ScaleI_1:\r
+   \   0000006C   018C               MOVW    R17:R16, R25:R24\r
+   \   0000006E   01CB               MOVW    R25:R24, R23:R22\r
+   \   00000070   2DA2               MOV     R26, R2\r
+   \   00000072   9508               RET\r
+    321          }\r
+    322          \r
+    323          \r
+    324          /*! \brief Waits for two full cycles of ADC-conversions to occur.\r
+    325           *\r
+    326           * This function clears the cycle complete-flag, then waits for it to be set\r
+    327           * again. This is then repeated once before the function exits.\r
+    328           * \r
+    329           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    330          void ADC_Wait(void)\r
+   \                     ADC_Wait:\r
+   \                     ??ADC_Wait_0:\r
+    331          {\r
+    332                // Clear ADC flag and wait for cycle to complete.\r
+    333                ADCS.Flag = FALSE;              \r
+    334                do {\r
+    335                } while (ADCS.Flag == FALSE);      \r
+   \   00000000   CFFF               RJMP    ??ADC_Wait_0\r
+    336                \r
+    337                // Repeat, so we are sure the data beong to the same cycle.\r
+    338                ADCS.Flag = FALSE;              \r
+    339                do {\r
+    340                } while (ADCS.Flag == FALSE);      \r
+    341          }\r
+    342          \r
+    343          \r
+    344          /*! \brief Initializes ADC and input pins.\r
+    345           *\r
+    346           * This function initializes the ADC to free running mode, sampling from\r
+    347           * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
+    348           * It also measures and stores calibration data for offset.\r
+    349           *\r
+    350           * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
+    351           *\r
+    352           * \note Table of MUX settings for offset measurement:\r
+    353           * <pre>\r
+    354           *    Ch | Pin |    Gain |    MUX\r
+    355           * ------+-----+---------+-------\r
+    356           *  ADC1 | PA1 |     20x | 001101\r
+    357           *  ADC3 | PA4 |     20x | 010001\r
+    358           *  ADC5 | PA6 |     20x | 010110\r
+    359           *  ADC9 | PB6 |     20x | 011011\r
+    360           *  ADC0 | PA0 | 20x/32x | 111000\r
+    361           *  ADC0 | PA0 |   1x/8x | 111001\r
+    362           *  ADC1 | PA1 | 20x/32x | 111010\r
+    363           *  ADC2 | PA2 | 20x/32x | 111011\r
+    364           *  ADC4 | PA5 | 20x/32x | 111100\r
+    365           *  ADC5 | PA6 | 20x/32x | 111101\r
+    366           *  ADC6 | PA7 | 20x/32x | 111110\r
+    367           * </pre>\r
+    368           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    369          void ADC_Init(void)\r
+   \                     ADC_Init:\r
+    370          {\r
+    371                unsigned char i;\r
+    372          \r
+    373                __disable_interrupt();\r
+   \   00000000   94F8               CLI\r
+    374          \r
+    375                ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
+   \   00000002   ....               LDI     R30, LOW(ADCS)\r
+   \   00000004   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000006   8100               LD      R16, Z\r
+   \   00000008   770F               ANDI    R16, 0x7F\r
+   \   0000000A   8300               ST      Z, R16\r
+    376          \r
+    377                // Configure ADC pins (inputs and disabled pull-ups).\r
+    378                DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+   \   0000000C   B30A               IN      R16, 0x1A\r
+   \   0000000E   7009               ANDI    R16, 0x09\r
+   \   00000010   BB0A               OUT     0x1A, R16\r
+    379                PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+   \   00000012   B30B               IN      R16, 0x1B\r
+   \   00000014   7009               ANDI    R16, 0x09\r
+   \   00000016   BB0B               OUT     0x1B, R16\r
+    380          \r
+    381                // Set ADC3 as reference, and MUX to measure the same pin.\r
+    382                ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
+   \   00000018   E403               LDI     R16, 67\r
+   \   0000001A   B907               OUT     0x07, R16\r
+    383                \r
+    384                ADCSRB = 0;\r
+   \   0000001C   E000               LDI     R16, 0\r
+   \   0000001E   B903               OUT     0x03, R16\r
+    385          \r
+    386                // Start conversion, no interrupt (disable ADC-ISR).\r
+    387                ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+   \   00000020   EC07               LDI     R16, 199\r
+   \   00000022   B906               OUT     0x06, R16\r
+    388          \r
+    389                do { // Wait for conversion to finish.\r
+    390                } while (!(ADCSRA & (1<<ADIF)));\r
+   \                     ??ADC_Init_0:\r
+   \   00000024   9B34               SBIS    0x06, 0x04\r
+   \   00000026   CFFE               RJMP    ??ADC_Init_0\r
+    391          \r
+    392                ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
+   \   00000028   9A34               SBI     0x06, 0x04\r
+    393          \r
+    394                ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
+   \   0000002A   8121               LDD     R18, Z+1\r
+   \   0000002C   7F20               ANDI    R18, 0xF0\r
+   \   0000002E   B104               IN      R16, 0x04\r
+   \   00000030   B115               IN      R17, 0x05\r
+   \   00000032   700F               ANDI    R16, 0x0F\r
+   \   00000034   2B02               OR      R16, R18\r
+   \   00000036   8301               STD     Z+1, R16\r
+    395          \r
+    396                ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
+   \   00000038   E516               LDI     R17, 86\r
+   \   0000003A   B917               OUT     0x07, R17\r
+    397                \r
+    398                // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
+    399                ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+   \   0000003C   EC17               LDI     R17, 199\r
+   \   0000003E   B916               OUT     0x06, R17\r
+    400          \r
+    401                do { // Wait for conversion to finish.\r
+    402                } while (!(ADCSRA & (1<<ADIF)));\r
+   \                     ??ADC_Init_1:\r
+   \   00000040   9B34               SBIS    0x06, 0x04\r
+   \   00000042   CFFE               RJMP    ??ADC_Init_1\r
+    403          \r
+    404                ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
+   \   00000044   9A34               SBI     0x06, 0x04\r
+    405          \r
+    406                ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
+   \   00000046   700F               ANDI    R16, 0x0F\r
+   \   00000048   B124               IN      R18, 0x04\r
+   \   0000004A   B135               IN      R19, 0x05\r
+   \   0000004C   9522               SWAP    R18\r
+   \   0000004E   7F20               ANDI    R18, 0xF0\r
+   \   00000050   2B20               OR      R18, R16\r
+   \   00000052   8321               STD     Z+1, R18\r
+    407          \r
+    408                // Reset the ADC-cycle.\r
+    409                ADCS.Flag = FALSE;      \r
+    410                ADCS.MUX = 0x01;                    \r
+   \   00000054   8100               LD      R16, Z\r
+   \   00000056   7C00               ANDI    R16, 0xC0\r
+   \   00000058   6001               ORI     R16, 0x01\r
+   \   0000005A   8300               ST      Z, R16\r
+    411                ADMUX = (1<<REFS0) | ADCS.MUX;      \r
+   \   0000005C   E401               LDI     R16, 65\r
+   \   0000005E   B907               OUT     0x07, R16\r
+    412          \r
+    413                // Clear averaged battery current and the discrete readings.\r
+    414                ADCS.avgIBAT = 0;\r
+   \   00000060   E000               LDI     R16, 0\r
+   \   00000062   8B06               STD     Z+22, R16\r
+   \   00000064   8B07               STD     Z+23, R16\r
+    415                \r
+    416                for (i = 0; i < 4; i++) {\r
+   \   00000066   963E               ADIW    R31:R30, 14\r
+   \   00000068   E024               LDI     R18, 4\r
+    417                        ADCS.discIBAT[i] = 0;             \r
+   \                     ??ADC_Init_2:\r
+   \   0000006A   9301               ST      Z+, R16\r
+   \   0000006C   9301               ST      Z+, R16\r
+    418                }\r
+   \   0000006E   952A               DEC     R18\r
+   \   00000070   F7E1               BRNE    ??ADC_Init_2\r
+    419                \r
+    420                // Re-enable the ADC and ISR.\r
+    421                ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
+   \   00000072   EC0F               LDI     R16, 207\r
+   \   00000074   B906               OUT     0x06, R16\r
+    422                \r
+    423                __enable_interrupt();\r
+   \   00000076   9478               SEI\r
+    424          \r
+    425                // Get a complete cycle of data before returning.\r
+    426                ADC_Wait();\r
+   \                     ??ADC_Init_3:\r
+   \   00000078   CFFF               RJMP    ??ADC_Init_3\r
+   \   0000007A                      REQUIRE _A_PORTA\r
+   \   0000007A                      REQUIRE _A_DDRA\r
+   \   0000007A                      REQUIRE _A_ADMUX\r
+   \   0000007A                      REQUIRE _A_ADCSRA\r
+   \   0000007A                      REQUIRE _A_ADC\r
+   \   0000007A                      REQUIRE _A_ADCSRB\r
+    427          }\r
+\r
+   \                                 In  segment INTVEC, offset 0x16, root\r
+   \                     `??ADC_ISR??INTVEC 22`:\r
+   \   00000016   ....               RJMP    ADC_ISR\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function    CSTACK RSTACK\r
+     --------    ------ ------\r
+     ADC_ISR        19      4\r
+       -> ScaleU    19      2\r
+       -> ScaleU    19      2\r
+       -> ScaleI    19      2\r
+       -> ScaleI    19      2\r
+     ADC_Init        0      2\r
+     ADC_Wait        0      2\r
+     ScaleI          3      4\r
+     ScaleU          3      4\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label       Bytes\r
+     --------------       -----\r
+     _A_PORTA                1\r
+     _A_DDRA                 1\r
+     _A_ADMUX                1\r
+     _A_ADCSRA               1\r
+     _A_ADC                  2\r
+     _A_ADCSRB               1\r
+     VBAT_RANGE              1\r
+     ADC_ISR               404\r
+     ADCS                   25\r
+     ScaleU                102\r
+     ScaleI                116\r
+     ??ADC_Wait_0            2\r
+     ADC_Init              122\r
+     ??ADC_ISR??INTVEC 22    2\r
+      Others                 6\r
+\r
\r
+   7 bytes in segment ABSOLUTE\r
+ 746 bytes in segment CODE\r
+   1 byte  in segment EEPROM_I\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment INTVEC\r
+  25 bytes in segment NEAR_Z\r
\r
+ 746 bytes of CODE  memory (+ 8 bytes shared)\r
+  25 bytes of DATA  memory (+ 7 bytes shared)\r
+   1 byte  of XDATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/ADC.s90 b/BaseTinyFirmware/IAR/Release/List/ADC.s90
new file mode 100644 (file)
index 0000000..d5b2c6b
--- /dev/null
@@ -0,0 +1,1002 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:49:35 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\ADC.c          /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\ADC.c          /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\A /\r
+//                             DC.s90                                         /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME `ADC`\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?SS_DIVMOD_L02\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?US_SHR_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBWEAK `??ADC_ISR??INTVEC 22`\r
+        PUBLIC ADCS\r
+        PUBLIC ADC_ISR\r
+        PUBLIC ADC_Init\r
+        PUBLIC ADC_Wait\r
+        PUBLIC ScaleI\r
+        PUBLIC ScaleU\r
+        PUBLIC VBAT_RANGE\r
+        PUBWEAK _A_ADC\r
+        PUBWEAK _A_ADCSRA\r
+        PUBWEAK _A_ADCSRB\r
+        PUBWEAK _A_ADMUX\r
+        PUBWEAK _A_DDRA\r
+        PUBWEAK _A_PORTA\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+ADC_ISR             SYMBOL "ADC_ISR"\r
+`??ADC_ISR??INTVEC 22` SYMBOL "??INTVEC 22", ADC_ISR\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\ADC.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for use of ADC\r
+//    6  *\r
+//    7  *      Contains high level functions for initializing the ADC, interrupt\r
+//    8  *      handling, and treatment of samples.\n\r
+//    9  *      The ADC is set to free running mode and uses an external reference\r
+//   10  *      voltage.\n\r
+//   11  *      To make all sampling take at least 25 clock cycles the ADC is stopped\r
+//   12  *      and restarted by the ISR.\r
+//   13  *\r
+//   14  * \par Application note:\r
+//   15  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   16  *      AVR463: Charging NiMH Batteries with BC100\r
+//   17  *\r
+//   18  * \par Documentation:\r
+//   19  *      For comprehensive code documentation, supported compilers, compiler\r
+//   20  *      settings and supported devices see readme.html\r
+//   21  *\r
+//   22  * \author\r
+//   23  *      Atmel Corporation: http://www.atmel.com \n\r
+//   24  *      Support email: avr@atmel.com \n\r
+//   25  *      Original author: \n\r
+//   26  *\r
+//   27  * $Name$\r
+//   28  * $Revision: 2299 $\r
+//   29  * $RCSfile$\r
+//   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
+//   31  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   32  ******************************************************************************/\r
+//   33 \r
+//   34 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03bH\r
+// <unnamed> volatile __io _A_PORTA\r
+_A_PORTA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03aH\r
+// <unnamed> volatile __io _A_DDRA\r
+_A_DDRA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,027H\r
+// <unnamed> volatile __io _A_ADMUX\r
+_A_ADMUX:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,026H\r
+// <unnamed> volatile __io _A_ADCSRA\r
+_A_ADCSRA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,024H\r
+// <unnamed> volatile __io _A_ADC\r
+_A_ADC:\r
+        DS 2\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,023H\r
+// <unnamed> volatile __io _A_ADCSRB\r
+_A_ADCSRB:\r
+        DS 1\r
+//   35 #include <inavr.h>\r
+//   36 \r
+//   37 #include "structs.h"\r
+//   38 \r
+//   39 #include "main.h"\r
+//   40 #include "ADC.h"\r
+//   41 \r
+//   42 \r
+//   43 //******************************************************************************\r
+//   44 // Variables\r
+//   45 //******************************************************************************\r
+//   46 // ADC status struct.\r
+//   47 //! \brief Holds sampled data and ADC-status\r
+//   48 ADC_Status_t ADCS;\r
+//   49 \r
+//   50 \r
+//   51 /*! \brief Indicates maximum battery voltage.\r
+//   52  *\r
+//   53  * This variable is stored in EEPROM and indicates how much the battery voltage\r
+//   54  * is downscaled by HW before it is sampled. The amount of downscaling depends\r
+//   55  * on the maximum battery voltage, and is necessary to avoid saturation of the\r
+//   56  * ADC (reference voltage is 2.5 V).\r
+//   57  *\r
+//   58  * \note Used by the ADC ISR when calling ScaleU() and ScaleI().\r
+//   59  *\r
+//   60  * \note Defaults to 1, which means 10 V max battery voltage.\r
+//   61  *\r
+//   62  * \note Table of settings:\r
+//   63  * <pre>\r
+//   64  * VBAT_RANGE | Max battery voltage | Jumper setting\r
+//   65  *         0  |             5V      |        1/2\r
+//   66  *         1  |            10V      |        1/4\r
+//   67  *         2  |            20V      |        1/8\r
+//   68  *         3  |            30V      |       1/12\r
+//   69  *         4  |            40V      |       1/16\r
+//   70  * </pre>\r
+//   71  */\r
+//   72 // Maximum battery voltage (affects scaling of samples).\r
+\r
+        RSEG EEPROM_I:XDATA:NOROOT(0)\r
+//   73 __eeprom unsigned char VBAT_RANGE = 1;\r
+VBAT_RANGE:\r
+        DB 1\r
+//   74 \r
+//   75 \r
+//   76 //******************************************************************************\r
+//   77 // Functions\r
+//   78 //******************************************************************************\r
+//   79 /*! \brief Interrupt Service routine for ADC.\r
+//   80  *\r
+//   81  * This ISR stores the sampled values in the ADC status-struct, then\r
+//   82  * updates the ADC MUX to the next channel in the scanning-sequence.\n\r
+//   83  * Once the sequence is completed, ADCS.Flag is set and unless\r
+//   84  * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC \r
+//   85  * is disabled.\n\r
+//   86  * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE.\r
+//   87  *\r
+//   88  * \note Table of scanning sequence:\r
+//   89  * <pre>\r
+//   90  * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed\r
+//   91  * ----+--------+----------+----------+------+---------+-------\r
+//   92  *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no\r
+//   93  *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no\r
+//   94  *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no\r
+//   95  *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no\r
+//   96  *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no\r
+//   97  *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no\r
+//   98  *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no\r
+//   99  *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes\r
+//  100  * </pre>\r
+//  101  *\r
+//  102  * \todo IIN (#7 in sequence) is never used.\r
+//  103  *\r
+//  104  * \todo Signed is never set. Signed measurements of IBAT will halve the\r
+//  105  * measuring sensitivity, and is therefore not favourable. At the moment,\r
+//  106  * great currents (f.ex. if something happens with the battery) will be\r
+//  107  * interpreted as negative, which might cause unfavourable behaviour during\r
+//  108  * charging (depending on what PWM behaviour is defined), f.ex.\r
+//  109  * ConstantCurrent() will keep increasing the PWM output. This results in an\r
+//  110  * PWM controller error being flagged and the program going into\r
+//  111  * error-state and eventually reinitializing.\r
+//  112  */\r
+//  113 #pragma vector=ADC_vect\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  114 __interrupt void ADC_ISR(void)\r
+ADC_ISR:\r
+//  115 {\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        ST      -Y, R31\r
+        ST      -Y, R30\r
+        ST      -Y, R3\r
+        ST      -Y, R2\r
+        ST      -Y, R1\r
+        ST      -Y, R0\r
+        ST      -Y, R23\r
+        ST      -Y, R22\r
+        ST      -Y, R21\r
+        ST      -Y, R20\r
+        ST      -Y, R19\r
+        ST      -Y, R18\r
+        ST      -Y, R17\r
+        ST      -Y, R16\r
+        IN      R4, 0x3F\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+//  116        static unsigned char avgIndex = 0;\r
+//  117        unsigned char i, Next, Signed;\r
+//  118        signed int  temp = 0;\r
+        LDI     R24, 0\r
+        LDI     R25, 0\r
+//  119        \r
+//  120        Signed = FALSE;  // Presume next conversion is unipolar.\r
+//  121        ADCSRA &= ~(1<<ADEN);  // Stop conversion before handling. This makes all\r
+        CBI     0x06, 0x07\r
+//  122          // conversions take at least 25 ADCCLK. (It is restarted later)\r
+//  123        \r
+//  124        // Handle the conversion, depending on what channel it is from, then\r
+//  125        // switch to the next channel in the sequence.\r
+//  126        switch (ADCS.MUX){\r
+        LDI     R26, LOW(ADCS)\r
+        LDI     R27, (ADCS) >> 8\r
+        LD      R16, X\r
+        ANDI    R16, 0x1F\r
+        DEC     R16\r
+        BREQ    ??ADC_ISR_0\r
+        DEC     R16\r
+        BREQ    ??ADC_ISR_1\r
+        DEC     R16\r
+        BREQ    ??ADC_ISR_2\r
+        SUBI    R16, 2\r
+        BREQ    ??ADC_ISR_3\r
+        SUBI    R16, 18\r
+        BREQ    ??ADC_ISR_4\r
+        RJMP    ??ADC_ISR_5\r
+//  127                // MUX = 0b000001 => ADC1 (PA1) = NTC\r
+//  128                case 0x01:\r
+//  129                        ADCS.rawNTC = ADC;\r
+??ADC_ISR_0:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+4, R16\r
+        STD     Z+5, R17\r
+//  130                        Next=0x02;\r
+        LDI     R16, 2\r
+        RJMP    ??ADC_ISR_6\r
+//  131                break;\r
+//  132 \r
+//  133                \r
+//  134                // MUX = 0b000010 => ADC2 (PA2) = RID\r
+//  135                case 0x02:\r
+//  136                        ADCS.rawRID = ADC;\r
+??ADC_ISR_1:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//  137                        Next=0x03;\r
+        LDI     R16, 3\r
+        RJMP    ??ADC_ISR_6\r
+//  138                break;\r
+//  139 \r
+//  140                \r
+//  141                // MUX = 0b000011 => ADC3 (PA4) = VIN-\r
+//  142                case 0x03:\r
+//  143                        // Supply voltage is always divided by 16.\r
+//  144                        ADCS.VIN = ScaleU(4, (unsigned int)ADC);  // Cast because ADC is short.\r
+??ADC_ISR_2:\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        LDI     R16, 4\r
+        RCALL   ScaleU\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+8, R16\r
+        STD     Z+9, R17\r
+//  145                        \r
+//  146                        // Is mains failing?\r
+//  147                        if (ADCS.VIN < VIN_MIN) {\r
+        CPI     R16, 48\r
+        SBCI    R17, 17\r
+        LD      R16, X\r
+        BRCC    ??ADC_ISR_7\r
+//  148                                ADCS.Mains = FALSE;\r
+        ANDI    R16, 0xBF\r
+        RJMP    ??ADC_ISR_8\r
+//  149                        } else {\r
+//  150                                ADCS.Mains = TRUE;\r
+??ADC_ISR_7:\r
+        ORI     R16, 0x40\r
+??ADC_ISR_8:\r
+        ST      X, R16\r
+//  151                        }\r
+//  152                        \r
+//  153                        Next=0x05;\r
+        LDI     R16, 5\r
+        RJMP    ??ADC_ISR_6\r
+//  154                break;\r
+//  155 \r
+//  156                \r
+//  157                // MUX = 0b000101 => ADC5 (PA6) = VBAT-\r
+//  158                case 0x05:\r
+//  159                        ADCS.rawVBAT = ADC;\r
+??ADC_ISR_3:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+6, R16\r
+        STD     Z+7, R17\r
+//  160                        \r
+//  161                        // Scale voltage according to jumper setting.\r
+//  162                        ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short.\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        LDI     R20, LOW(VBAT_RANGE)\r
+        LDI     R21, (VBAT_RANGE) >> 8\r
+        RCALL   __eeget8_16\r
+        RCALL   ScaleU\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+10, R16\r
+        STD     Z+11, R17\r
+//  163                        Next=0x17;\r
+        LDI     R16, 23\r
+        RJMP    ??ADC_ISR_6\r
+//  164 //                     Signed = TRUE;  // Next conversion is bipolar. Halves sensitivity!\r
+//  165                break;\r
+//  166 \r
+//  167 \r
+//  168                case 0x17:  // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT\r
+//  169                        // If bipolar, from -512 to 0, to 511:\r
+//  170                        // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF\r
+//  171                \r
+//  172                        // Scale sample according to jumper setting, handle negative numbers.\r
+//  173                        if (ADC > 511) {\r
+??ADC_ISR_4:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        CPI     R17, 2\r
+        BRCS    ??ADC_ISR_9\r
+//  174                                ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE,\r
+//  175                                             (1024 - (ADC-ADCS.ADC5_G20_OS)));\r
+        LDI     R16, 0\r
+        LDI     R17, 4\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R18, Z+1\r
+        SWAP    R18\r
+        ANDI    R18, 0x0F\r
+        LDI     R19, 0\r
+        ADD     R18, R16\r
+        ADC     R19, R17\r
+        LDI     R20, LOW(VBAT_RANGE)\r
+        LDI     R21, (VBAT_RANGE) >> 8\r
+        RCALL   __eeget8_16\r
+        RCALL   ScaleI\r
+        NEG     R17\r
+        NEG     R16\r
+        SBCI    R17, 0\r
+??ADC_ISR_10:\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+12, R16\r
+        STD     Z+13, R17\r
+        RJMP    ??ADC_ISR_11\r
+//  176                        } else if (ADC > 0) {\r
+??ADC_ISR_9:\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        OR      R16, R17\r
+        BREQ    ??ADC_ISR_12\r
+//  177                                ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS));\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R16, Z+1\r
+        SWAP    R16\r
+        ANDI    R16, 0x0F\r
+        SUB     R18, R16\r
+        SBCI    R19, 0\r
+        LDI     R20, LOW(VBAT_RANGE)\r
+        LDI     R21, (VBAT_RANGE) >> 8\r
+        RCALL   __eeget8_16\r
+        RCALL   ScaleI\r
+        RJMP    ??ADC_ISR_10\r
+//  178                        } else {\r
+//  179                                ADCS.IBAT = 0;\r
+??ADC_ISR_12:\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+12, R24\r
+        STD     Z+13, R24\r
+//  180                        }\r
+//  181 \r
+//  182                        // Insert sample of battery current into the averaging-array\r
+//  183                        // (overwriting the oldest sample), then recalculate and store the\r
+//  184                        // average. This is the last conversion in the sequence, so\r
+//  185                        // flag a complete ADC-cycle and restart sequence.\r
+//  186                        ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT;\r
+??ADC_ISR_11:\r
+        LDD     R18, Z+12\r
+        LDD     R19, Z+13\r
+        LDD     R16, Z+24\r
+        ANDI    R16, 0x03\r
+        LSL     R16\r
+        ADD     R30, R16\r
+        ADC     R31, R24\r
+        STD     Z+14, R18\r
+        STD     Z+15, R19\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R16, Z+24\r
+        INC     R16\r
+        STD     Z+24, R16\r
+//  187                        for (i = 0; i < 4 ; i++) {\r
+        ADIW    R31:R30, 14\r
+        LDI     R16, 4\r
+//  188                                temp += ADCS.discIBAT[i];\r
+??ADC_ISR_13:\r
+        LD      R18, Z+\r
+        LD      R19, Z+\r
+        ADD     R24, R18\r
+        ADC     R25, R19\r
+//  189                        }\r
+        DEC     R16\r
+        BRNE    ??ADC_ISR_13\r
+//  190                        \r
+//  191                        ADCS.avgIBAT = (temp / 4);\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 4\r
+        LDI     R21, 0\r
+        RCALL   ?SS_DIVMOD_L02\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+22, R16\r
+        STD     Z+23, R17\r
+//  192                        \r
+//  193                        ADCS.Flag = TRUE;\r
+        LD      R16, X\r
+        ORI     R16, 0x20\r
+        ST      X, R16\r
+//  194                        Next=0x01;\r
+//  195                        Signed = FALSE;  // This is the only bipolar conversion.\r
+//  196                break;\r
+//  197 \r
+//  198                \r
+//  199                default:  // Should not happen. (Invalid MUX-channel)\r
+//  200                        Next=0x01;  // Start at the beginning of sequence.\r
+??ADC_ISR_5:\r
+        LDI     R16, 1\r
+//  201                break;\r
+//  202        }\r
+//  203        \r
+//  204        // Update MUX to next channel in sequence, set a bipolar conversion if\r
+//  205        // this has been flagged.\r
+//  206        ADCS.MUX = Next;                    \r
+??ADC_ISR_6:\r
+        LD      R17, X\r
+        ANDI    R17, 0xE0\r
+        ANDI    R16, 0x1F\r
+        OR      R16, R17\r
+        ST      X, R16\r
+//  207        ADMUX = (1<<REFS0) + ADCS.MUX;      \r
+        ANDI    R16, 0x1F\r
+        SUBI    R16, 192\r
+        OUT     0x07, R16\r
+//  208 \r
+//  209        if (Signed)     {\r
+//  210          ADCSRB |= (1<<BIN);               \r
+//  211        } else {\r
+//  212          ADCSRB &= ~(1<<BIN);              \r
+        CBI     0x03, 0x07\r
+//  213        }\r
+//  214 \r
+//  215        // Re-enable the ADC unless a halt has been flagged and a conversion\r
+//  216        // cycle has completed.\r
+//  217        if (!((ADCS.Halt) && (ADCS.Flag))) {\r
+        LD      R16, X\r
+        ANDI    R16, 0xA0\r
+        CPI     R16, 160\r
+        BREQ    ??ADC_ISR_14\r
+//  218          ADCSRA |= (1<<ADEN)|(1<<ADSC);    \r
+        IN      R16, 0x06\r
+        ORI     R16, 0xC0\r
+        OUT     0x06, R16\r
+//  219        }\r
+//  220 }\r
+??ADC_ISR_14:\r
+        OUT     0x3F, R4\r
+        LD      R16, Y+\r
+        LD      R17, Y+\r
+        LD      R18, Y+\r
+        LD      R19, Y+\r
+        LD      R20, Y+\r
+        LD      R21, Y+\r
+        LD      R22, Y+\r
+        LD      R23, Y+\r
+        LD      R0, Y+\r
+        LD      R1, Y+\r
+        LD      R2, Y+\r
+        LD      R3, Y+\r
+        LD      R30, Y+\r
+        LD      R31, Y+\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        RETI\r
+        REQUIRE _A_ADMUX\r
+        REQUIRE _A_ADCSRA\r
+        REQUIRE _A_ADC\r
+        REQUIRE _A_ADCSRB\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+ADCS:\r
+        DS 24\r
+        DS 1\r
+//  221 \r
+//  222 \r
+//  223 /*! \brief Scales sample to represent "actual voltage" in mV.\r
+//  224  *\r
+//  225  * This function returns the actual sampled voltage, scaled according\r
+//  226  * to the jumper settings.\r
+//  227  *\r
+//  228  * \param setting Indicates what downscaling was used.\r
+//  229  * \param data The sampled value.\r
+//  230  *\r
+//  231  * \note Table for setting-parameter:\n\r
+//  232  * <pre>\r
+//  233  * Presume VREF = 2.5V and Gain = 1x.\r
+//  234  * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB\r
+//  235  * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)\r
+//  236  * --------+--------+------+------------+-----------+-------\r
+//  237  *     N/A |        |    - |       -    |   2.441mV |  2.50V\r
+//  238  *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V\r
+//  239  *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V\r
+//  240  *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V\r
+//  241  *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V\r
+//  242  *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V\r
+//  243  *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V\r
+//  244  * </pre>\r
+//  245  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  246 unsigned int ScaleU(unsigned char setting, unsigned int data)\r
+ScaleU:\r
+//  247 {\r
+        MOV     R2, R26\r
+        MOVW    R23:R22, R25:R24\r
+        MOV     R26, R16\r
+        MOVW    R25:R24, R19:R18\r
+//  248        // Temporary variable needed.\r
+//  249        unsigned int scaled = 0;\r
+//  250 \r
+//  251        // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16\r
+//  252        if (setting == 3)       {\r
+        CPI     R16, 3\r
+        MOVW    R21:R20, R19:R18\r
+        BRNE    ??ScaleU_0\r
+//  253                scaled = 29 * data;\r
+//  254                scaled += (data >> 2);\r
+//  255                scaled += (data >> 4);\r
+        LDI     R16, 29\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LSR     R19\r
+        ROR     R18\r
+        LSR     R19\r
+        ROR     R18\r
+        ADD     R18, R0\r
+        ADC     R19, R1\r
+        LSR     R25\r
+        ROR     R24\r
+        LSR     R25\r
+        ROR     R24\r
+        LSR     R25\r
+        ROR     R24\r
+        LSR     R25\r
+        ROR     R24\r
+        ADD     R24, R18\r
+        ADC     R25, R19\r
+        RJMP    ??ScaleU_1\r
+//  256        } else {\r
+//  257                // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16\r
+//  258                scaled = 39 * data;\r
+//  259                scaled += (data >> 4);\r
+??ScaleU_0:\r
+        LDI     R16, 39\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LSR     R25\r
+        ROR     R24\r
+        LSR     R25\r
+        ROR     R24\r
+        LSR     R25\r
+        ROR     R24\r
+        LSR     R25\r
+        ROR     R24\r
+        ADD     R24, R0\r
+        ADC     R25, R1\r
+//  260                \r
+//  261                if (setting <3) {\r
+        CPI     R26, 3\r
+        BRCC    ??ScaleU_1\r
+//  262                        // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8\r
+//  263                        //                1: mV/LSB = 9.766 = 39.06 / 4\r
+//  264                        //                2: mV/LSB = 19.53 = 39.06 / 2\r
+//  265                        scaled = (scaled >> (3-setting));\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 3\r
+        SUB     R20, R26\r
+        RCALL   ?US_SHR_L02\r
+        MOVW    R25:R24, R17:R16\r
+//  266                }\r
+//  267        }\r
+//  268 \r
+//  269        return(scaled);\r
+??ScaleU_1:\r
+        MOVW    R17:R16, R25:R24\r
+        MOVW    R25:R24, R23:R22\r
+        MOV     R26, R2\r
+        RET\r
+//  270 }\r
+//  271 \r
+//  272 \r
+//  273 /*! \brief Scales sample to represent "actual current" in mA.\r
+//  274  *\r
+//  275  * This function returns the actual sampled current, scaled according\r
+//  276  * to the jumper settings.\r
+//  277  *\r
+//  278  * \param setting Indicates what downscaling was used.\r
+//  279  * \param data The sampled value.\r
+//  280  *\r
+//  281  * \note Table for setting-parameter:\n\r
+//  282  * <pre>\r
+//  283  * Presume VREF = 2.5V and Gain = 1x or 20x.\r
+//  284  * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB\r
+//  285  * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07\r
+//  286  * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain\r
+//  287  * --------+------+------------+----------+----------+--------+-----\r
+//  288  *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x\r
+//  289  *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x\r
+//  290  *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x\r
+//  291  *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x\r
+//  292  *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x\r
+//  293  *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x\r
+//  294  *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x\r
+//  295  * </pre>\r
+//  296  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  297 unsigned int ScaleI(unsigned char setting, unsigned int data)\r
+ScaleI:\r
+//  298 {\r
+        MOV     R2, R26\r
+        MOVW    R23:R22, R25:R24\r
+        MOV     R26, R16\r
+        MOVW    R25:R24, R19:R18\r
+//  299        // Temporary variable needed.\r
+//  300        unsigned int  scaled = 0;\r
+//  301        \r
+//  302        // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128\r
+//  303        if (setting == 3) {\r
+        CPI     R16, 3\r
+        MOVW    R21:R20, R19:R18\r
+        BRNE    ??ScaleI_0\r
+//  304                scaled = 21 * data;\r
+//  305                scaled -= (data >> 4);\r
+//  306                scaled += (data >> 7);\r
+        LDI     R16, 21\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        LSR     R19\r
+        ROR     R18\r
+        LSR     R19\r
+        ROR     R18\r
+        LSR     R19\r
+        ROR     R18\r
+        LSR     R19\r
+        ROR     R18\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        LSL     R24\r
+        MOV     R24, R25\r
+        ROL     R24\r
+        LDI     R25, 0\r
+        ROL     R25\r
+        ADD     R24, R16\r
+        ADC     R25, R17\r
+        RJMP    ??ScaleI_1\r
+//  307        }       else    { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32\r
+//  308                scaled = 28 * data;\r
+//  309                scaled -= (data >> 3);\r
+//  310                scaled += (data >> 5);\r
+??ScaleI_0:\r
+        LDI     R16, 28\r
+        LDI     R17, 0\r
+        RCALL   ?S_MUL_L02\r
+        MOVW    R19:R18, R17:R16\r
+        MOVW    R17:R16, R25:R24\r
+        LSR     R17\r
+        ROR     R16\r
+        LSR     R17\r
+        ROR     R16\r
+        LSR     R17\r
+        ROR     R16\r
+        SUB     R18, R16\r
+        SBC     R19, R17\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 5\r
+        RCALL   ?US_SHR_L02\r
+        MOVW    R25:R24, R17:R16\r
+        ADD     R24, R18\r
+        ADC     R25, R19\r
+//  311                \r
+//  312                if (setting <3) {\r
+        CPI     R26, 3\r
+        BRCC    ??ScaleI_1\r
+//  313                        // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8\r
+//  314                        //                1: mA/LSB = 6.978mA = 27.909 / 4\r
+//  315                        //                2: mA/LSB = 13.955mA = 27.909 / 2\r
+//  316                        scaled = (scaled >> (3-setting));\r
+        MOVW    R17:R16, R25:R24\r
+        LDI     R20, 3\r
+        SUB     R20, R26\r
+        RCALL   ?US_SHR_L02\r
+        MOVW    R25:R24, R17:R16\r
+//  317                }\r
+//  318        }\r
+//  319        \r
+//  320        return(scaled);\r
+??ScaleI_1:\r
+        MOVW    R17:R16, R25:R24\r
+        MOVW    R25:R24, R23:R22\r
+        MOV     R26, R2\r
+        RET\r
+//  321 }\r
+//  322 \r
+//  323 \r
+//  324 /*! \brief Waits for two full cycles of ADC-conversions to occur.\r
+//  325  *\r
+//  326  * This function clears the cycle complete-flag, then waits for it to be set\r
+//  327  * again. This is then repeated once before the function exits.\r
+//  328  * \r
+//  329  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  330 void ADC_Wait(void)\r
+ADC_Wait:\r
+??ADC_Wait_0:\r
+//  331 {\r
+//  332        // Clear ADC flag and wait for cycle to complete.\r
+//  333        ADCS.Flag = FALSE;              \r
+//  334        do {\r
+//  335        } while (ADCS.Flag == FALSE);      \r
+        RJMP    ??ADC_Wait_0\r
+//  336        \r
+//  337        // Repeat, so we are sure the data beong to the same cycle.\r
+//  338        ADCS.Flag = FALSE;              \r
+//  339        do {\r
+//  340        } while (ADCS.Flag == FALSE);      \r
+//  341 }\r
+//  342 \r
+//  343 \r
+//  344 /*! \brief Initializes ADC and input pins.\r
+//  345  *\r
+//  346  * This function initializes the ADC to free running mode, sampling from\r
+//  347  * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n\r
+//  348  * It also measures and stores calibration data for offset.\r
+//  349  *\r
+//  350  * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway.\r
+//  351  *\r
+//  352  * \note Table of MUX settings for offset measurement:\r
+//  353  * <pre>\r
+//  354  *    Ch | Pin |    Gain |    MUX\r
+//  355  * ------+-----+---------+-------\r
+//  356  *  ADC1 | PA1 |     20x | 001101\r
+//  357  *  ADC3 | PA4 |     20x | 010001\r
+//  358  *  ADC5 | PA6 |     20x | 010110\r
+//  359  *  ADC9 | PB6 |     20x | 011011\r
+//  360  *  ADC0 | PA0 | 20x/32x | 111000\r
+//  361  *  ADC0 | PA0 |   1x/8x | 111001\r
+//  362  *  ADC1 | PA1 | 20x/32x | 111010\r
+//  363  *  ADC2 | PA2 | 20x/32x | 111011\r
+//  364  *  ADC4 | PA5 | 20x/32x | 111100\r
+//  365  *  ADC5 | PA6 | 20x/32x | 111101\r
+//  366  *  ADC6 | PA7 | 20x/32x | 111110\r
+//  367  * </pre>\r
+//  368  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  369 void ADC_Init(void)\r
+ADC_Init:\r
+//  370 {\r
+//  371        unsigned char i;\r
+//  372 \r
+//  373        __disable_interrupt();\r
+        CLI\r
+//  374 \r
+//  375        ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LD      R16, Z\r
+        ANDI    R16, 0x7F\r
+        ST      Z, R16\r
+//  376 \r
+//  377        // Configure ADC pins (inputs and disabled pull-ups).\r
+//  378        DDRA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+        IN      R16, 0x1A\r
+        ANDI    R16, 0x09\r
+        OUT     0x1A, R16\r
+//  379        PORTA &= ~((1<<PA1)|(1<<PA2)|(1<<PA4)|(1<<PA5)|(1<<PA6)|(1<<PA7));\r
+        IN      R16, 0x1B\r
+        ANDI    R16, 0x09\r
+        OUT     0x1B, R16\r
+//  380 \r
+//  381        // Set ADC3 as reference, and MUX to measure the same pin.\r
+//  382        ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX1);\r
+        LDI     R16, 67\r
+        OUT     0x07, R16\r
+//  383        \r
+//  384        ADCSRB = 0;\r
+        LDI     R16, 0\r
+        OUT     0x03, R16\r
+//  385 \r
+//  386        // Start conversion, no interrupt (disable ADC-ISR).\r
+//  387        ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+        LDI     R16, 199\r
+        OUT     0x06, R16\r
+//  388 \r
+//  389        do { // Wait for conversion to finish.\r
+//  390        } while (!(ADCSRA & (1<<ADIF)));\r
+??ADC_Init_0:\r
+        SBIS    0x06, 0x04\r
+        RJMP    ??ADC_Init_0\r
+//  391 \r
+//  392        ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag manually.\r
+        SBI     0x06, 0x04\r
+//  393 \r
+//  394        ADCS.ADC3_G20_OS = ADC;  // Save the sampled offset.\r
+        LDD     R18, Z+1\r
+        ANDI    R18, 0xF0\r
+        IN      R16, 0x04\r
+        IN      R17, 0x05\r
+        ANDI    R16, 0x0F\r
+        OR      R16, R18\r
+        STD     Z+1, R16\r
+//  395 \r
+//  396        ADMUX = (1<<REFS0) | 0x16;  // ADC5/ADC5 (external ref.), 20x\r
+        LDI     R17, 86\r
+        OUT     0x07, R17\r
+//  397        \r
+//  398        // Start conversion, no interrupt. ADC_PRESCALER is defined in ADC.h.\r
+//  399        ADCSRA = (1<<ADEN) | (1<<ADSC) | ADC_PRESCALER; \r
+        LDI     R17, 199\r
+        OUT     0x06, R17\r
+//  400 \r
+//  401        do { // Wait for conversion to finish.\r
+//  402        } while (!(ADCSRA & (1<<ADIF)));\r
+??ADC_Init_1:\r
+        SBIS    0x06, 0x04\r
+        RJMP    ??ADC_Init_1\r
+//  403 \r
+//  404        ADCSRA |= (1<<ADIF);  // Clear ADC interrupt flag.\r
+        SBI     0x06, 0x04\r
+//  405 \r
+//  406        ADCS.ADC5_G20_OS = ADC;  // Save the sampled offset.\r
+        ANDI    R16, 0x0F\r
+        IN      R18, 0x04\r
+        IN      R19, 0x05\r
+        SWAP    R18\r
+        ANDI    R18, 0xF0\r
+        OR      R18, R16\r
+        STD     Z+1, R18\r
+//  407 \r
+//  408        // Reset the ADC-cycle.\r
+//  409        ADCS.Flag = FALSE;      \r
+//  410        ADCS.MUX = 0x01;                    \r
+        LD      R16, Z\r
+        ANDI    R16, 0xC0\r
+        ORI     R16, 0x01\r
+        ST      Z, R16\r
+//  411        ADMUX = (1<<REFS0) | ADCS.MUX;      \r
+        LDI     R16, 65\r
+        OUT     0x07, R16\r
+//  412 \r
+//  413        // Clear averaged battery current and the discrete readings.\r
+//  414        ADCS.avgIBAT = 0;\r
+        LDI     R16, 0\r
+        STD     Z+22, R16\r
+        STD     Z+23, R16\r
+//  415        \r
+//  416        for (i = 0; i < 4; i++) {\r
+        ADIW    R31:R30, 14\r
+        LDI     R18, 4\r
+//  417                ADCS.discIBAT[i] = 0;             \r
+??ADC_Init_2:\r
+        ST      Z+, R16\r
+        ST      Z+, R16\r
+//  418        }\r
+        DEC     R18\r
+        BRNE    ??ADC_Init_2\r
+//  419        \r
+//  420        // Re-enable the ADC and ISR.\r
+//  421        ADCSRA=(1<<ADEN)|(1<<ADSC)|(1<<ADIE)|ADC_PRESCALER;\r
+        LDI     R16, 207\r
+        OUT     0x06, R16\r
+//  422        \r
+//  423        __enable_interrupt();\r
+        SEI\r
+//  424 \r
+//  425        // Get a complete cycle of data before returning.\r
+//  426        ADC_Wait();\r
+??ADC_Init_3:\r
+        RJMP    ??ADC_Init_3\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+        REQUIRE _A_ADMUX\r
+        REQUIRE _A_ADCSRA\r
+        REQUIRE _A_ADC\r
+        REQUIRE _A_ADCSRB\r
+//  427 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        COMMON INTVEC:CODE:ROOT(1)\r
+        ORG 22\r
+`??ADC_ISR??INTVEC 22`:\r
+        RJMP    ADC_ISR\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   7 bytes in segment ABSOLUTE\r
+// 746 bytes in segment CODE\r
+//   1 byte  in segment EEPROM_I\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment INTVEC\r
+//  25 bytes in segment NEAR_Z\r
+// \r
+// 746 bytes of CODE  memory (+ 8 bytes shared)\r
+//  25 bytes of DATA  memory (+ 7 bytes shared)\r
+//   1 byte  of XDATA memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/BC100_tiny.map b/BaseTinyFirmware/IAR/Release/List/BC100_tiny.map
new file mode 100644 (file)
index 0000000..21cee84
--- /dev/null
@@ -0,0 +1,2087 @@
+################################################################################\r
+#                                                                              #\r
+#      IAR Universal Linker V4.60I/386                                         #\r
+#                                                                              #\r
+#           Link time     =  13/Mar/2008  04:52:03                             #\r
+#           Target CPU    =  A90                                               #\r
+#           List file     =  C:\home\kevin\pub\src\bc100\IAR\Release\List\BC10 #\r
+#                            0_tiny.map                                        #\r
+#           Output file 1 =  C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 #\r
+#                            _tiny.hex                                         #\r
+#                            Format: intel-extended, variant: -y(CODE)         #\r
+#           MISRA C Rules:                                                     #\r
+#             Enabled     =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,38-39, #\r
+#                            42-43,46,50,52-54,56-59,61-62,64-65,68-80,83-84,8 #\r
+#                            7-91,94-95,98-100,103-110,112-126                 #\r
+#             Checked     =  11,25-26                                          #\r
+#           Output file 2 =  C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 #\r
+#                            _tiny_data.hex                                    #\r
+#                            Format: intel-extended, variant: -y(DATA)         #\r
+#           MISRA C Rules:                                                     #\r
+#             Enabled     =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,38-39, #\r
+#                            42-43,46,50,52-54,56-59,61-62,64-65,68-80,83-84,8 #\r
+#                            7-91,94-95,98-100,103-110,112-126                 #\r
+#             Checked     =  11,25-26                                          #\r
+#           Output file 3 =  C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 #\r
+#                            _tiny_eeprom.hex                                  #\r
+#                            Format: intel-extended, variant: -y(XDATA)        #\r
+#           MISRA C Rules:                                                     #\r
+#             Enabled     =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,38-39, #\r
+#                            42-43,46,50,52-54,56-59,61-62,64-65,68-80,83-84,8 #\r
+#                            7-91,94-95,98-100,103-110,112-126                 #\r
+#             Checked     =  11,25-26                                          #\r
+#           Command line  =  -y(CODE)                                          #\r
+#                            -Ointel-extended,(DATA)=C:\home\kevin\pub\src\bc1 #\r
+#                            00\IAR\Release\Exe\BC100_tiny_data.hex            #\r
+#                            -Ointel-extended,(XDATA)=C:\home\kevin\pub\src\bc #\r
+#                            100\IAR\Release\Exe\BC100_tiny_eeprom.hex         #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC.r #\r
+#                            90                                                #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIMHc #\r
+#                            harge.r90                                         #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI.r #\r
+#                            90                                                #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM.r #\r
+#                            90                                                #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI.r #\r
+#                            90                                                #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\batte #\r
+#                            ry.r90                                            #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\charg #\r
+#                            efunc.r90                                         #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\main. #\r
+#                            r90                                               #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\menu. #\r
+#                            r90                                               #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\state #\r
+#                            func.r90                                          #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Obj\time. #\r
+#                            r90                                               #\r
+#                            -o                                                #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 #\r
+#                            _tiny.hex                                         #\r
+#                            -Fintel-extended -B -l                            #\r
+#                            C:\home\kevin\pub\src\bc100\IAR\Release\List\BC10 #\r
+#                            0_tiny.map                                        #\r
+#                            -xmsno                                            #\r
+#                            "-IC:\Program Files\IAR Systems\Embedded Workbenc #\r
+#                            h 4.0\avr\LIB\"                                   #\r
+#                            -f                                                #\r
+#                            "C:\Program Files\IAR Systems\Embedded Workbench  #\r
+#                            4.0\avr\src\template\cfgtiny861.xcl"              #\r
+#                            (-D_..X_INTVEC_SIZE=26 -D_..X_FLASH_END=1FFF      #\r
+#                            -D_..X_SRAM_BASE=60                               #\r
+#                            -D_..X_SRAM_TBASE=_..X_SRAM_BASE                  #\r
+#                            -D_..X_SRAM_TSIZE=(100-_..X_SRAM_BASE)            #\r
+#                            -D_..X_SRAM_END=25F                               #\r
+#                            -D_..X_EXT_SRAM_BASE=_..X_SRAM_END                #\r
+#                            -D_..X_EXT_SRAM_SIZE=0                            #\r
+#                            -D_..X_EXT_ROM_BASE=_..X_SRAM_END                 #\r
+#                            -D_..X_EXT_ROM_SIZE=0                             #\r
+#                            -D_..X_EXT_NV_BASE=_..X_SRAM_END                  #\r
+#                            -D_..X_EXT_NV_SIZE=0 -D_..X_EEPROM_END=1FF        #\r
+#                            -D_..X_EEPROM_START=0) -D_..X_HEAP_SIZE=10        #\r
+#                            -D_..X_TINY_HEAP_SIZE=0 -D_..X_NEAR_HEAP_SIZE=0   #\r
+#                            -D_..X_FAR_HEAP_SIZE=0 -D_..X_HUGE_HEAP_SIZE=0    #\r
+#                            -D_..X_CSTACK_SIZE=40 -D_..X_RSTACK_SIZE=30 -f    #\r
+#                            "C:\Program Files\IAR Systems\Embedded Workbench  #\r
+#                            4.0\avr\src\template\cfg1soim.xcl"                #\r
+#                            (-ca90 -w29 -Z(CODE)INTVEC=0-_..X_INTVEC_SIZE     #\r
+#                            -Z(CODE)TINY_F=_..X_FLASH_BASE-FF                 #\r
+#                            -Z(CODE)NEAR_F=_..X_FLASH_BASE-_..X_FLASH_END     #\r
+#                            -Z(CODE)SWITCH=_..X_FLASH_BASE-_..X_FLASH_END     #\r
+#                            -Z(CODE)INITTAB=_..X_FLASH_BASE-_..X_FLASH_END    #\r
+#                            -Z(CODE)DIFUNCT=_..X_FLASH_BASE-_..X_FLASH_END    #\r
+#                            -Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END       #\r
+#                            -Z(CODE)TINY_ID=_..X_FLASH_BASE-_..X_FLASH_END    #\r
+#                            -Z(CODE)NEAR_ID=_..X_FLASH_BASE-_..X_FLASH_END    #\r
+#                            -Z(CODE)CHECKSUM#_..X_FLASH_END                   #\r
+#                            -Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_TBASE:+_.. #\r
+#                            X_SRAM_TSIZE                                      #\r
+#                            -Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_CSTACK_BASE- #\r
+#                            _..X_CSTACK_END                                   #\r
+#                            -Z(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_BASE-_..X_S #\r
+#                            RAM_END                                           #\r
+#                            -Z(DATA)IOSTREAM_N#_..X_SRAM_BASE-_..X_SRAM_END   #\r
+#                            -Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_B #\r
+#                            ASE-_..X_SRAM_END                                 #\r
+#                            -Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE- #\r
+#                            _..X_RSTACK_END                                   #\r
+#                            -Z(DATA)NEAR_I,NEAR_Z,NEAR_N=_..X_SRAM_BASE-_..X_ #\r
+#                            SRAM_END                                          #\r
+#                            -Z(XDATA)EEPROM_I,EEPROM_N=_..X_EEPROM_START-_..X #\r
+#                            _EEPROM_END)                                      #\r
+#                            -D_..X_FLASH_BASE=_..X_INTVEC_SIZE -H1895         #\r
+#                            -h(CODE)0-(_..X_INTVEC_SIZE-1)                    #\r
+#                            -D_..X_CSTACK_BASE=_..X_SRAM_BASE                 #\r
+#                            -D_..X_CSTACK_END=_..X_SRAM_END                   #\r
+#                            -D_..X_RSTACK_BASE=_..X_SRAM_BASE                 #\r
+#                            -D_..X_RSTACK_END=_..X_SRAM_END -s                #\r
+#                            __program_start                                   #\r
+#                            "C:\Program Files\IAR Systems\Embedded Workbench  #\r
+#                            4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90"               #\r
+#                            -e_small_write=_formatted_write                   #\r
+#                            -e_medium_read=_formatted_read                    #\r
+#                            --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,34- #\r
+#                            35,38-39,42-43,46,50,52-54,56-59,61-62,64-65,68-8 #\r
+#                            0,83-84,87-91,94-95,98-100,103-110,112-126        #\r
+#                                                                              #\r
+#                        Copyright 1987-2007 IAR Systems. All rights reserved. #\r
+################################################################################\r
+\r
+\r
+\r
+\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *           CROSS REFERENCE            *\r
+                *                                      *\r
+                ****************************************\r
+\r
+       Program entry at : CODE      00000000  Relocatable, from module : ?RESET\r
+\r
+\r
+\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *            RUNTIME MODEL             *\r
+                *                                      *\r
+                ****************************************\r
+\r
+  EEPROM_SIZE     = 2\r
+  R4              = REG\r
+  R5              = REG\r
+  R6              = REG\r
+  R7              = REG\r
+  R8              = REG\r
+  R9              = REG\r
+  __64bit_doubles = disabled\r
+  __cpu           = 1\r
+  __cpu_name      = ATtiny861\r
+  __enhanced_core = enabled\r
+  __has_elpm      = false\r
+  __memory_model  = 2\r
+  __rt_version    = 3\r
+\r
+\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *              MODULE MAP              *\r
+                *                                      *\r
+                ****************************************\r
+\r
+\r
+  DEFINED ABSOLUTE ENTRIES\r
+  PROGRAM MODULE, NAME : ?ABS_ENTRY_MOD\r
+\r
+Absolute parts\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _..X_RSTACK_END         0000025F \r
+           _..X_RSTACK_BASE        00000060 \r
+           _..X_CSTACK_END         0000025F \r
+           _..X_CSTACK_BASE        00000060 \r
+           _..X_FLASH_BASE         00000026 \r
+           _..X_RSTACK_SIZE        00000030 \r
+           _..X_CSTACK_SIZE        00000040 \r
+           _..X_HUGE_HEAP_SIZE     00000000 \r
+           _..X_FAR_HEAP_SIZE      00000000 \r
+           _..X_NEAR_HEAP_SIZE     00000000 \r
+           _..X_TINY_HEAP_SIZE     00000000 \r
+           _..X_HEAP_SIZE          00000010 \r
+           _..X_EEPROM_START       00000000 \r
+           _..X_EEPROM_END         000001FF \r
+           _..X_EXT_NV_SIZE        00000000 \r
+           _..X_EXT_NV_BASE        0000025F \r
+           _..X_EXT_ROM_SIZE       00000000 \r
+           _..X_EXT_ROM_BASE       0000025F \r
+           _..X_EXT_SRAM_SIZE      00000000 \r
+           _..X_EXT_SRAM_BASE      0000025F \r
+           _..X_SRAM_END           0000025F \r
+           _..X_SRAM_TSIZE         000000A0 \r
+           _..X_SRAM_TBASE         00000060 \r
+           _..X_SRAM_BASE          00000060 \r
+           _..X_FLASH_END          00001FFF \r
+           _..X_INTVEC_SIZE        00000026 \r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC.r90\r
+  PROGRAM MODULE, NAME : ADC\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000003B - 0000003B (0x1 bytes), align: 0\r
+  Segment part 1.             Intra module refs:   ADC_Init\r
+                                                   OWI_DetectPresence (OWI)\r
+                                                   OWI_Init (OWI)\r
+                                                   OWI_ReadBit (OWI)\r
+                                                   OWI_WriteBit0 (OWI)\r
+                                                   OWI_WriteBit1 (OWI)\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_PORTA                0000003B \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000003A - 0000003A (0x1 bytes), align: 0\r
+  Segment part 2.             Intra module refs:   ADC_Init\r
+                                                   OWI_DetectPresence (OWI)\r
+                                                   OWI_Init (OWI)\r
+                                                   OWI_ReadBit (OWI)\r
+                                                   OWI_WriteBit0 (OWI)\r
+                                                   OWI_WriteBit1 (OWI)\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_DDRA                 0000003A \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000027 - 00000027 (0x1 bytes), align: 0\r
+  Segment part 3.             Intra module refs:   ADC_ISR\r
+                                                   ADC_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_ADMUX                00000027 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000026 - 00000026 (0x1 bytes), align: 0\r
+  Segment part 4.             Intra module refs:   ADC_ISR\r
+                                                   ADC_Init\r
+                                                   Error (statefunc)\r
+                                                   Sleep (statefunc)\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_ADCSRA               00000026 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000024 - 00000025 (0x2 bytes), align: 0\r
+  Segment part 5.             Intra module refs:   ADC_ISR\r
+                                                   ADC_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_ADC                  00000024 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000023 - 00000023 (0x1 bytes), align: 0\r
+  Segment part 6.             Intra module refs:   ADC_ISR\r
+                                                   ADC_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_ADCSRB               00000023 \r
+    -------------------------------------------------------------------------\r
+EEPROM_I\r
+  Relative segment, address: XDATA 00000000 - 00000000 (0x1 bytes), align: 0\r
+  Segment part 16.            Intra module refs:   ADC_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           VBAT_RANGE              00000000 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000050 - 000001E3 (0x194 bytes), align: 1\r
+  Segment part 17.            Intra module refs:   ADC_ISR::??INTVEC 22\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ADC_ISR                 00000050 \r
+               interrupt function\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000013 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+NEAR_Z\r
+  Relative segment, address: DATA 00000144 - 0000015C (0x19 bytes), align: 0\r
+  Segment part 14.            Intra module refs:   ADC_ISR\r
+                                                   ADC_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ADCS                    00000144        BatteryStatusRefresh (battery)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   JumperCheck (statefunc)\r
+                                                   NTCLookUp (battery)\r
+                                                   RIDLookUp (battery)\r
+                                                   USI_OVF_ISR (USI)\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000001E4 - 00000249 (0x66 bytes), align: 1\r
+  Segment part 18.            Intra module refs:   ADC_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ScaleU                  000001E4 \r
+               stack 1 = 00000000 ( 00000003 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 0000024A - 000002BD (0x74 bytes), align: 1\r
+  Segment part 19.            Intra module refs:   ADC_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ScaleI                  0000024A \r
+               stack 1 = 00000000 ( 00000003 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000002BE - 000002BF (0x2 bytes), align: 1\r
+  Segment part 20.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ADC_Wait                000002BE        BatteryControl (statefunc)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   Error (statefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Initialize (statefunc)\r
+                                                   JumperCheck (statefunc)\r
+                                                   Sleep (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000002C0 - 00000339 (0x7a bytes), align: 1\r
+  Segment part 21.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ADC_Init                000002C0        Initialize (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000001C, align: 0\r
+  Segment part 7.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __?EECR                 0000001C        Segment part 0 (?EEPROM_16)\r
+                                                   Segment part 1 (?EEPROM_16)\r
+                                                   Segment part 8 (?EEPROM_16)\r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000001D, align: 0\r
+  Segment part 8.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __?EEDR                 0000001D        __eeget8_16 (?EEPROM_16)\r
+                                                   __eeput8_16 (?EEPROM_16)\r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000001E, align: 0\r
+  Segment part 9.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __?EEARL                0000001E        Segment part 1 (?EEPROM_16)\r
+                                                   Segment part 8 (?EEPROM_16)\r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000001F, align: 0\r
+  Segment part 10.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __?EEARH                0000001F        Segment part 1 (?EEPROM_16)\r
+                                                   Segment part 8 (?EEPROM_16)\r
+    -------------------------------------------------------------------------\r
+INTVEC\r
+  Common segment, address: CODE 00000000 - 00000017 (0x18 bytes), align: 1\r
+  Segment part 11. ROOT.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ADC_ISR::??INTVEC 22    00000016 \r
+    -------------------------------------------------------------------------\r
+INITTAB\r
+  Relative segment, address: CODE 00000044 - 00000049 (0x6 bytes), align: 0\r
+  Segment part 15.            Intra module refs:   ADCS\r
+                                                   BattActive (battery)\r
+                                                   BattData (battery)\r
+                                                   CurrentState (main)\r
+                                                   SPI (USI)\r
+                                                   Segment part 13 (statefunc)\r
+                                                   Segment part 8 (chargefunc)\r
+                                                   timeval (time)\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?<Segment init: NEAR_Z>\r
+                                   00000044 \r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIMHcharge.r90\r
+  PROGRAM MODULE, NAME : NIMHcharge\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 0000033A - 00000445 (0x10c bytes), align: 1\r
+  Segment part 7.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Charge                  0000033A        menu_state (menu)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000002 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI.r90\r
+  PROGRAM MODULE, NAME : OWI\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000039 - 00000039 (0x1 bytes), align: 0\r
+  Segment part 3.             Intra module refs:   OWI_DetectPresence\r
+                                                   OWI_ReadBit\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_PINA                 00000039 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000446 - 00000461 (0x1c bytes), align: 1\r
+  Segment part 10.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_Init                00000446        Initialize (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000462 - 00000493 (0x32 bytes), align: 1\r
+  Segment part 11.            Intra module refs:   OWI_SendByte\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_WriteBit1           00000462 \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000494 - 000004C5 (0x32 bytes), align: 1\r
+  Segment part 12.            Intra module refs:   OWI_SendByte\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_WriteBit0           00000494 \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000004C6 - 00000507 (0x42 bytes), align: 1\r
+  Segment part 13.            Intra module refs:   OWI_ReceiveByte\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_ReadBit             000004C6 \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000508 - 00000551 (0x4a bytes), align: 1\r
+  Segment part 14.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_DetectPresence      00000508        BatteryDataRefresh (battery)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000552 - 00000577 (0x26 bytes), align: 1\r
+  Segment part 15.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_SendByte            00000552        BatteryDataRefresh (battery)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000003 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000578 - 0000059D (0x26 bytes), align: 1\r
+  Segment part 16.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_ReceiveByte         00000578        BatteryDataRefresh (battery)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000003 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 0000059E - 000005C1 (0x24 bytes), align: 1\r
+  Segment part 22.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           OWI_ComputeCRC8         0000059E        BatteryDataRefresh (battery)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM.r90\r
+  PROGRAM MODULE, NAME : PWM\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000050 - 00000050 (0x1 bytes), align: 0\r
+  Segment part 1.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR1A               00000050 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000004F - 0000004F (0x1 bytes), align: 0\r
+  Segment part 2.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR1B               0000004F \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000004D - 0000004D (0x1 bytes), align: 0\r
+  Segment part 3.             Intra module refs:   PWM_Start\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_OCR1A                0000004D \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000004C - 0000004C (0x1 bytes), align: 0\r
+  Segment part 4.             Intra module refs:   BatteryStatusRefresh (battery)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   PWM_DecrementDutyCycle\r
+                                                   PWM_IncrementDutyCycle\r
+                                                   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_OCR1B                0000004C \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000004B - 0000004B (0x1 bytes), align: 0\r
+  Segment part 5.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_OCR1C                0000004B \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000004A - 0000004A (0x1 bytes), align: 0\r
+  Segment part 6.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_OCR1D                0000004A \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000049 - 00000049 (0x1 bytes), align: 0\r
+  Segment part 7.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_PLLCSR               00000049 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000047 - 00000047 (0x1 bytes), align: 0\r
+  Segment part 8.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR1C               00000047 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000046 - 00000046 (0x1 bytes), align: 0\r
+  Segment part 9.             Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR1D               00000046 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000044 - 00000044 (0x1 bytes), align: 0\r
+  Segment part 10.            Intra module refs:   PWM_Start\r
+                                                   PWM_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_DT1                  00000044 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000037 - 00000037 (0x1 bytes), align: 0\r
+  Segment part 11.            Intra module refs:   Initialize (statefunc)\r
+                                                   PWM_Start\r
+                                                   SPI_Init (USI)\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_DDRB                 00000037 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000020 - 00000020 (0x1 bytes), align: 0\r
+  Segment part 12.            Intra module refs:   PWM_Start\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR1E               00000020 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000005C2 - 000005D7 (0x16 bytes), align: 1\r
+  Segment part 19.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           PWM_Stop                000005C2        Charge (NIMHcharge)\r
+                                                   Error (statefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   JumperCheck (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000005D8 - 00000627 (0x50 bytes), align: 1\r
+  Segment part 20.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           PWM_Start               000005D8        Charge (NIMHcharge)\r
+                                                   JumperCheck (statefunc)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000628 - 0000063B (0x14 bytes), align: 1\r
+  Segment part 21.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           PWM_IncrementDutyCycle\r
+                                   00000628        ConstantCurrent (chargefunc)\r
+                                                   JumperCheck (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 0000063C - 0000064F (0x14 bytes), align: 1\r
+  Segment part 22.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           PWM_DecrementDutyCycle\r
+                                   0000063C        ConstantCurrent (chargefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI.r90\r
+  PROGRAM MODULE, NAME : USI\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000038 - 00000038 (0x1 bytes), align: 0\r
+  Segment part 1.             Intra module refs:   DisableBatteries (battery)\r
+                                                   EnableBattery (battery)\r
+                                                   SPI_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_PORTB                00000038 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000002F - 0000002F (0x1 bytes), align: 0\r
+  Segment part 3.             Intra module refs:   SPI_Put\r
+                                                   USI_OVF_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_USIDR                0000002F \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000002E - 0000002E (0x1 bytes), align: 0\r
+  Segment part 4.             Intra module refs:   SPI_Put\r
+                                                   USI_OVF_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_USISR                0000002E \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 0000002D - 0000002D (0x1 bytes), align: 0\r
+  Segment part 5.             Intra module refs:   SPI_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_USICR                0000002D \r
+    -------------------------------------------------------------------------\r
+NEAR_Z\r
+  Relative segment, address: DATA 0000015D - 00000160 (0x4 bytes), align: 0\r
+  Segment part 13.            Intra module refs:   SPI_Init\r
+                                                   SPI_Put\r
+                                                   USI_OVF_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           SPI                     0000015D \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000650 - 000007BD (0x16e bytes), align: 1\r
+  Segment part 15.            Intra module refs:   USI_OVF_ISR::??INTVEC 16\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           USI_OVF_ISR             00000650 \r
+               interrupt function\r
+               calls direct\r
+               stack 1 = 00000000 ( 0000000F )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000007BE - 000007F5 (0x38 bytes), align: 1\r
+  Segment part 16.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           SPI_Init                000007BE        Initialize (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000007F6 - 00000815 (0x20 bytes), align: 1\r
+  Segment part 17.            Intra module refs:   USI_OVF_ISR\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           SPI_Put                 000007F6 \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+INTVEC\r
+  Common segment, address: CODE 00000000 - 00000011 (0x12 bytes), align: 1\r
+  Segment part 10. ROOT.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           USI_OVF_ISR::??INTVEC 16\r
+                                   00000010 \r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\battery.r90\r
+  PROGRAM MODULE, NAME : battery\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+EEPROM_I\r
+  Relative segment, address: XDATA 00000001 - 00000002 (0x2 bytes), align: 0\r
+  Segment part 9.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BattControl             00000001        BatteryControl (statefunc)\r
+                                                   Charge (NIMHcharge)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   USI_OVF_ISR (USI)\r
+    -------------------------------------------------------------------------\r
+NEAR_Z\r
+  Relative segment, address: DATA 00000161 - 0000016C (0xc bytes), align: 0\r
+  Segment part 10.            Intra module refs:   BatteryCheck\r
+                                                   BatteryDataRefresh\r
+                                                   BatteryStatusRefresh\r
+                                                   NTCLookUp\r
+                                                   RIDLookUp\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BattData                00000161        BatteryControl (statefunc)\r
+                                                   Charge (NIMHcharge)\r
+                                                   HaltNow (chargefunc)\r
+                                                   USI_OVF_ISR (USI)\r
+    -------------------------------------------------------------------------\r
+EEPROM_I\r
+  Relative segment, address: XDATA 00000003 - 00000082 (0x80 bytes), align: 0\r
+  Segment part 12.            Intra module refs:   BatteryDataRefresh\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BattEEPROM              00000003        Initialize (statefunc)\r
+    -------------------------------------------------------------------------\r
+NEAR_Z\r
+  Relative segment, address: DATA 0000016D - 0000016D (0x1 bytes), align: 0\r
+  Segment part 13.            Intra module refs:   EnableBattery\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BattActive              0000016D        Charge (NIMHcharge)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Initialize (statefunc)\r
+                                                   USI_OVF_ISR (USI)\r
+    -------------------------------------------------------------------------\r
+NEAR_I\r
+  Relative segment, address: DATA 000000D0 - 00000107 (0x38 bytes), align: 0\r
+  Segment part 14.            Intra module refs:   RIDLookUp\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           RID                     000000D0 \r
+    -------------------------------------------------------------------------\r
+NEAR_I\r
+  Relative segment, address: DATA 00000108 - 00000143 (0x3c bytes), align: 0\r
+  Segment part 17.            Intra module refs:   NTCLookUp\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           NTC                     00000108 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000816 - 00000847 (0x32 bytes), align: 1\r
+  Segment part 19.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BatteryCheck            00000816        HaltNow (chargefunc)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000003 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000848 - 000008E5 (0x9e bytes), align: 1\r
+  Segment part 20.            Intra module refs:   BatteryCheck\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BatteryStatusRefresh    00000848        BatteryControl (statefunc)\r
+                                                   Initialize (statefunc)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000004 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000008E6 - 000009E3 (0xfe bytes), align: 1\r
+  Segment part 21.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BatteryDataRefresh      000008E6        BatteryControl (statefunc)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000009 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000009E4 - 00000A25 (0x42 bytes), align: 1\r
+  Segment part 22.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           EnableBattery           000009E4        BatteryControl (statefunc)\r
+                                                   Initialize (statefunc)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000001 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000A26 - 00000A2D (0x8 bytes), align: 1\r
+  Segment part 23.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           DisableBatteries        00000A26        BatteryControl (statefunc)\r
+                                                   Error (statefunc)\r
+                                                   Initialize (statefunc)\r
+                                                   JumperCheck (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000A2E - 00000AB1 (0x84 bytes), align: 1\r
+  Segment part 24.            Intra module refs:   BatteryStatusRefresh\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           RIDLookUp               00000A2E \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000AB2 - 00000B39 (0x88 bytes), align: 1\r
+  Segment part 25.            Intra module refs:   BatteryStatusRefresh\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           NTCLookUp               00000AB2 \r
+               stack 1 = 00000000 ( 00000003 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+NEAR_ID\r
+  Relative segment, address: CODE 000011FA - 00001231 (0x38 bytes), align: 0\r
+  Segment part 15.            Intra module refs:   RID\r
+    -------------------------------------------------------------------------\r
+INITTAB\r
+  Relative segment, address: CODE 0000004A - 0000004F (0x6 bytes), align: 0\r
+  Segment part 16.            Intra module refs:   NTC\r
+                                                   RID\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?<Segment init: NEAR_I>\r
+                                   0000004A \r
+    -------------------------------------------------------------------------\r
+NEAR_ID\r
+  Relative segment, address: CODE 00001232 - 0000126D (0x3c bytes), align: 0\r
+  Segment part 18.            Intra module refs:   NTC\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\chargefunc.r90\r
+  PROGRAM MODULE, NAME : chargefunc\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+NEAR_Z\r
+  Relative segment, address: DATA 0000016E - 00000183 (0x16 bytes), align: 0\r
+  Segment part 8.             Intra module refs:   ConstantCurrent\r
+                                                   HaltNow\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ChargeParameters        0000017F        Charge (NIMHcharge)\r
+           HaltParameters          0000016E        Charge (NIMHcharge)\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000B3A - 00000BD1 (0x98 bytes), align: 1\r
+  Segment part 10.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ConstantCurrent         00000B3A        Charge (NIMHcharge)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000006 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000BD2 - 00000D79 (0x1a8 bytes), align: 1\r
+  Segment part 12.            Intra module refs:   ConstantCurrent\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           HaltNow                 00000BD2 \r
+               calls direct\r
+               stack 1 = 00000000 ( 0000000A )\r
+               stack 2 = 00000000 ( 00000004 )\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\main.r90\r
+  PROGRAM MODULE, NAME : main\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+NEAR_Z\r
+  Relative segment, address: DATA 00000184 - 00000184 (0x1 bytes), align: 0\r
+  Segment part 7.             Intra module refs:   main\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           CurrentState            00000184        BatteryControl (statefunc)\r
+                                                   Charge (NIMHcharge)\r
+                                                   SetErrorFlag (statefunc)\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000D7A - 00000DFD (0x84 bytes), align: 1\r
+  Segment part 9.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           main                    00000D7A        ?cstartup_call_main (?C_STARTUP)\r
+               calls indirect\r
+               stack 1 = 00000000 ( 00000002 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\menu.r90\r
+  PROGRAM MODULE, NAME : menu\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+NEAR_F\r
+  Relative segment, address: CODE 00000026 - 00000043 (0x1e bytes), align: 0\r
+  Segment part 7.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           menu_state              00000026        main (main)\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\statefunc.r90\r
+  PROGRAM MODULE, NAME : statefunc\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000055 - 00000055 (0x1 bytes), align: 0\r
+  Segment part 1.             Intra module refs:   Error\r
+                                                   Sleep\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_MCUCR                00000055 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000054 - 00000054 (0x1 bytes), align: 0\r
+  Segment part 2.             Intra module refs:   Error\r
+                                                   Sleep\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_MCUSR                00000054 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000048 - 00000048 (0x1 bytes), align: 0\r
+  Segment part 3.             Intra module refs:   Initialize\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_CLKPR                00000048 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000041 - 00000041 (0x1 bytes), align: 0\r
+  Segment part 4.             Intra module refs:   Error\r
+                                                   Sleep\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_WDTCR                00000041 \r
+    -------------------------------------------------------------------------\r
+NEAR_Z\r
+  Relative segment, address: DATA 00000185 - 00000186 (0x2 bytes), align: 0\r
+  Segment part 13.            Intra module refs:   BatteryControl\r
+                                                   Initialize\r
+                                                   SetErrorFlag\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ErrorFlags              00000185 \r
+           ErrorState              00000186 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000DFE - 00000E4F (0x52 bytes), align: 1\r
+  Segment part 15.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Initialize              00000DFE        menu_state (menu)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000001 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000E50 - 00000EC9 (0x7a bytes), align: 1\r
+  Segment part 16.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           BatteryControl          00000E50        menu_state (menu)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000004 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000ECA - 00000ECD (0x4 bytes), align: 1\r
+  Segment part 17.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Discharge               00000ECA        menu_state (menu)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000ECE - 00000ED1 (0x4 bytes), align: 1\r
+  Segment part 18.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Sleep                   00000ECE        menu_state (menu)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000ED2 - 00000ED9 (0x8 bytes), align: 1\r
+  Segment part 20.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Error                   00000ED2        menu_state (menu)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000EDA - 00000EEB (0x12 bytes), align: 1\r
+  Segment part 21.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           SetErrorFlag            00000EDA        ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000EEC - 00000F5F (0x74 bytes), align: 1\r
+  Segment part 22.            Intra module refs:   BatteryControl\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           JumperCheck             00000EEC \r
+               calls direct\r
+               stack 1 = 00000000 ( 00000002 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\time.r90\r
+  PROGRAM MODULE, NAME : time\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000059 - 00000059 (0x1 bytes), align: 0\r
+  Segment part 1.             Intra module refs:   Time_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TIMSK                00000059 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000053 - 00000053 (0x1 bytes), align: 0\r
+  Segment part 2.             Intra module refs:   Time_Init\r
+                                                   Time_Start\r
+                                                   Time_Stop\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR0B               00000053 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000035 - 00000035 (0x1 bytes), align: 0\r
+  Segment part 3.             Intra module refs:   Time_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_TCCR0A               00000035 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000033 - 00000033 (0x1 bytes), align: 0\r
+  Segment part 4.             Intra module refs:   Time_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_OCR0A                00000033 \r
+    -------------------------------------------------------------------------\r
+ABSOLUTE\r
+  Relative segment, address: DATA 00000032 - 00000032 (0x1 bytes), align: 0\r
+  Segment part 5.             Intra module refs:   Time_Init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           _A_OCR0B                00000032 \r
+    -------------------------------------------------------------------------\r
+NEAR_Z\r
+  Relative segment, address: DATA 00000187 - 00000196 (0x10 bytes), align: 0\r
+  Segment part 13.            Intra module refs:   TICK_ISR\r
+                                                   Time_Left\r
+                                                   Time_Set\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           timeval                 00000187        USI_OVF_ISR (USI)\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000F60 - 00000FB5 (0x56 bytes), align: 1\r
+  Segment part 15.            Intra module refs:   TICK_ISR::??INTVEC 28\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           TICK_ISR                00000F60 \r
+               interrupt function\r
+               stack 1 = 00000000 ( 00000009 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000FB6 - 00000FDD (0x28 bytes), align: 1\r
+  Segment part 16.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Time_Left               00000FB6        EnableBattery (battery)\r
+                                                   HaltNow (chargefunc)\r
+                                                   JumperCheck (statefunc)\r
+                                                   PWM_Start (PWM)\r
+                                                   USI_OVF_ISR (USI)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00000FDE - 0000105B (0x7e bytes), align: 1\r
+  Segment part 17.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Time_Set                00000FDE        Charge (NIMHcharge)\r
+                                                   EnableBattery (battery)\r
+                                                   HaltNow (chargefunc)\r
+                                                   JumperCheck (statefunc)\r
+                                                   PWM_Start (PWM)\r
+                                                   USI_OVF_ISR (USI)\r
+               stack 1 = 00000000 ( 00000008 )\r
+               stack 2 = 00000000 ( 00000004 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 0000105C - 00001061 (0x6 bytes), align: 1\r
+  Segment part 18.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Time_Stop               0000105C        ConstantCurrent (chargefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00001062 - 00001067 (0x6 bytes), align: 1\r
+  Segment part 19.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Time_Start              00001062        ConstantCurrent (chargefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00001068 - 00001081 (0x1a bytes), align: 1\r
+  Segment part 20.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           Time_Init               00001068        Initialize (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+INTVEC\r
+  Common segment, address: CODE 00000000 - 0000001D (0x1e bytes), align: 1\r
+  Segment part 10. ROOT.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           TICK_ISR::??INTVEC 28   0000001C \r
+\r
+    *************************************************************************\r
+\r
+  FILE NAME : C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90\r
+  LIBRARY MODULE, NAME : ?__exit\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001082 - 00001087 (0x6 bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __exit                  00001084 \r
+           ?C_EXIT                 00001084 \r
+           ?C_FUNCALL              00001082 \r
+           _exit                   00001082        ?cstartup_call_main (?C_STARTUP)\r
+           exit                    00001082        ?cstartup_call_main (?C_STARTUP)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?abs\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001088 - 00001097 (0x10 bytes), align: 1\r
+  Segment part 3.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           abs                     00001088        JumperCheck (statefunc)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?RESET\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+INTVEC\r
+  Common segment, address: CODE 00000000 - 00000001 (0x2 bytes), align: 1\r
+  Segment part 0. ROOT.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __program_start         00000000        Absolute parts (?ABS_ENTRY_MOD)\r
+           ?RESET                  00000000        Segment part 2 (?C_STARTUP)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?C_STARTUP\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001098, align: 1\r
+  Segment part 2.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?C_STARTUP              00001098        Segment part 0 (?RESET)\r
+           __RESTART               00001098 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 00001098 - 000010A3 (0xc bytes), align: 1\r
+  Segment part 5.             Intra module refs:   Segment part 2\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010A4 - 000010A5 (0x2 bytes), align: 1\r
+  Segment part 7.             Intra module refs:   Segment part 5\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?call_low_level_init    000010A4 \r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010A6 - 000010AB (0x6 bytes), align: 1\r
+  Segment part 8.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?need_segment_init      000010A6        ?<Segment init: NEAR_I> (battery)\r
+                                                   ?<Segment init: NEAR_Z> (ADC)\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010AC - 000010B1 (0x6 bytes), align: 1\r
+  Segment part 9.             Intra module refs:   ?call_low_level_init\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?cstartup_call_main     000010AC \r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?EEPROM_16\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000010B2 - 000010B7 (0x6 bytes), align: 1\r
+  Segment part 0.             Intra module refs:   Segment part 1\r
+                                                   __eeput8_16\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010B8 - 000010C5 (0xe bytes), align: 1\r
+  Segment part 1.             Intra module refs:   __eeget8_16\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010C6 - 000010CB (0x6 bytes), align: 1\r
+  Segment part 3.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __eeget8_16             000010C6        ADC_ISR (ADC)\r
+                                                   BatteryControl (statefunc)\r
+                                                   Charge (NIMHcharge)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   USI_OVF_ISR (USI)\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010CC - 000010DD (0x12 bytes), align: 1\r
+  Segment part 8.             Intra module refs:   __eeput8_16\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000010DE - 000010E5 (0x8 bytes), align: 1\r
+  Segment part 10.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __eeput8_16             000010DE        BatteryDataRefresh (battery)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Initialize (statefunc)\r
+                                                   USI_OVF_ISR (USI)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?S_MUL_L02\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000010E6 - 00001105 (0x20 bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?S_MUL_L02              000010E6        HaltNow (chargefunc)\r
+                                                   ScaleI (ADC)\r
+                                                   ScaleU (ADC)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?S_SHL_L02\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001106 - 00001111 (0xc bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?S_SHL_L02              00001106        EnableBattery (battery)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?US_SHR_L02\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001112 - 0000111D (0xc bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?US_SHR_L02             00001112        ScaleI (ADC)\r
+                                                   ScaleU (ADC)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?US_DIVMOD_L02\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 0000111E - 00001145 (0x28 bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?US_DIVMOD_L02          0000111E        ?SS_DIVMOD_L02 (?SS_DIVMOD_L02)\r
+                                                   Charge (NIMHcharge)\r
+                                                   NTCLookUp (battery)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?SS_DIVMOD_L02\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001146 - 00001173 (0x2e bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?SS_DIVMOD_L02          0000114E        ADC_ISR (ADC)\r
+                                                   Charge (NIMHcharge)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?L_MUL_L03\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 00001174 - 000011A5 (0x32 bytes), align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?L_MUL_L03              00001174        Time_Set (time)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?REGISTER_CGREGR4_L10\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6, align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?Register_R4_is_cg_reg\r
+                                   000011A6        ADC_ISR (ADC)\r
+                                                   BatteryDataRefresh (battery)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Time_Set (time)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?REGISTER_CGREGR5_L10\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6, align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?Register_R5_is_cg_reg\r
+                                   000011A6        BatteryDataRefresh (battery)\r
+                                                   ConstantCurrent (chargefunc)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Time_Set (time)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?REGISTER_CGREGR6_L10\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6, align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?Register_R6_is_cg_reg\r
+                                   000011A6        BatteryDataRefresh (battery)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Time_Set (time)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?REGISTER_CGREGR7_L10\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6, align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?Register_R7_is_cg_reg\r
+                                   000011A6        BatteryDataRefresh (battery)\r
+                                                   HaltNow (chargefunc)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?REGISTER_CGREGR8_L10\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6, align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?Register_R8_is_cg_reg\r
+                                   000011A6        BatteryDataRefresh (battery)\r
+                                                   HaltNow (chargefunc)\r
+                                                   Time_Set (time)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?REGISTER_CGREGR9_L10\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6, align: 1\r
+  Segment part 0.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           ?Register_R9_is_cg_reg\r
+                                   000011A6        HaltNow (chargefunc)\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?low_level_init\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011A6 - 000011A9 (0x4 bytes), align: 1\r
+  Segment part 3.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __low_level_init        000011A6        ?call_low_level_init (?C_STARTUP)\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    -------------------------------------------------------------------------\r
+  LIBRARY MODULE, NAME : ?segment_init\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+CODE\r
+  Relative segment, address: CODE 000011AA - 000011B1 (0x8 bytes), align: 1\r
+  Segment part 3.             Intra module refs:   __segment_init\r
+           LOCAL                   ADDRESS         \r
+           =====                   =======         \r
+           __memclr                000011AA \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000011B2 - 000011B9 (0x8 bytes), align: 1\r
+  Segment part 4.             Intra module refs:   __segment_init\r
+           LOCAL                   ADDRESS         \r
+           =====                   =======         \r
+           __flashcpy              000011B2 \r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000011BA - 000011C5 (0xc bytes), align: 1\r
+  Segment part 5.             Intra module refs:   __flashcpy\r
+                                                   __memclr\r
+    -------------------------------------------------------------------------\r
+CODE\r
+  Relative segment, address: CODE 000011C6 - 000011F9 (0x34 bytes), align: 1\r
+  Segment part 6.\r
+           ENTRY                   ADDRESS         REF BY\r
+           =====                   =======         ======\r
+           __segment_init          000011C6        ?need_segment_init (?C_STARTUP)\r
+               calls direct\r
+               stack 1 = 00000000 ( 00000000 )\r
+               stack 2 = 00000000 ( 00000002 )\r
+\r
+    *************************************************************************\r
+\r
+  DEFINED ABSOLUTE ENTRIES\r
+  PROGRAM MODULE, NAME : ?FILLER_BYTES\r
+\r
+  SEGMENTS IN THE MODULE\r
+  ======================\r
+INTVEC\r
+  Common segment, address: CODE 00000000 - 0000001D (0x1e bytes), align: 0\r
+  Segment part 1.\r
+    -------------------------------------------------------------------------\r
+?FILL1\r
+  Relative segment, address: CODE 0000001E - 00000025 (0x8 bytes), align: 0\r
+  Segment part 0.\r
+\r
+\r
+\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *            MODULE SUMMARY            *\r
+                *                                      *\r
+                ****************************************\r
+\r
+Module               CODE      DATA      XDATA\r
+------               ----      ----      -----\r
+                    (Rel)  (Rel)  (Abs)  (Rel)\r
+?C_STARTUP             26\r
+?EEPROM_16             52\r
+?FILLER_BYTES           8\r
+  + common             30\r
+?L_MUL_L03             50\r
+?RESET\r
+  + common              2\r
+?SS_DIVMOD_L02         46\r
+?S_MUL_L02             32\r
+?S_SHL_L02             12\r
+?US_DIVMOD_L02         40\r
+?US_SHR_L02            12\r
+?__exit                 6\r
+?abs                   16\r
+?low_level_init         4\r
+?segment_init          80\r
+ADC                   746     25      4      1\r
+  + shared              6             3\r
+  + common             24\r
+NIMHcharge            268\r
+OWI                   380             1\r
+PWM                   142            10\r
+  + shared                            2\r
+USI                   454      4      3\r
+  + shared             18             1\r
+  + common\r
+battery               926    129           130\r
+chargefunc            576     22\r
+main                  132      1\r
+menu                   30\r
+statefunc             354      2      4\r
+time                  290     16      5\r
+  + common             30\r
+N/A (command line)           112\r
+N/A (alignment)\r
+----------          -----    ---     --    ---\r
+Total:              4 688    311     33    131\r
+  + common             30\r
+\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *              CALL GRAPH              *\r
+                *                                      *\r
+                ****************************************\r
+\r
+  ->Sub-tree of type: Interrupt function tree that does not make\r
+                    : indirect calls\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000000 00000000\r
+  02    ScaleI\r
+        | Stack used (prev) :  00000000 00000000\r
+        | + function block  :  00000003 00000004\r
+  02    ScaleI\r
+        | Stack used (prev) :  00000000 00000000\r
+        | + function block  :  00000003 00000004\r
+        |  Already listed\r
+  02    ScaleU\r
+        | Stack used (prev) :  00000000 00000000\r
+        | + function block  :  00000003 00000004\r
+  02    ScaleU\r
+        | Stack used (prev) :  00000000 00000000\r
+        | + function block  :  00000003 00000004\r
+        |  Already listed\r
+  01  ADC_ISR\r
+      | Stack used (prev) :  00000003 00000004\r
+      | + function block  :  00000013 00000002\r
+  <-Sub-tree of type: Interrupt function tree that does not make\r
+                    : indirect calls\r
+    | Stack used          :  00000016 00000006\r
+\r
+\r
+  ->Sub-tree of type: Interrupt function tree that does not make\r
+                    : indirect calls\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000016 00000006\r
+  02    Time_Set\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000008 00000004\r
+  02    Time_Left\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    SPI_Put\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  01  USI_OVF_ISR\r
+      | Stack used (prev) :  0000001E 0000000A\r
+      | + function block  :  0000000F 00000002\r
+  <-Sub-tree of type: Interrupt function tree that does not make\r
+                    : indirect calls\r
+    | Stack used          :  0000002D 0000000C\r
+\r
+\r
+  ->Sub-tree of type: Interrupt function tree that does not make\r
+                    : indirect calls\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  0000002D 0000000C\r
+  01  TICK_ISR\r
+      | Stack used (prev) :  0000002D 0000000C\r
+      | + function block  :  00000009 00000002\r
+  <-Sub-tree of type: Interrupt function tree that does not make\r
+                    : indirect calls\r
+    | Stack used          :  00000036 0000000E\r
+\r
+\r
+  ->Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000036 0000000E\r
+  02    Time_Set\r
+        | Stack used (prev) :  00000016 00000006\r
+        | + function block  :  00000008 00000004\r
+        |  Already listed\r
+  03      Time_Start\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  03      Time_Stop\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  03      SetErrorFlag\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  04        Time_Set\r
+            | Stack used (prev) :  00000016 00000006\r
+            | + function block  :  00000008 00000004\r
+            |  Already listed\r
+  04        Time_Left\r
+            | Stack used (prev) :  00000016 00000006\r
+            | + function block  :  00000000 00000002\r
+            |  Already listed\r
+  04        SetErrorFlag\r
+            | Stack used (prev) :  00000036 0000000E\r
+            | + function block  :  00000000 00000002\r
+            |  Already listed\r
+  06            NTCLookUp\r
+                | Stack used (prev) :  00000036 0000000E\r
+                | + function block  :  00000003 00000004\r
+  06            RIDLookUp\r
+                | Stack used (prev) :  00000036 0000000E\r
+                | + function block  :  00000000 00000002\r
+  05          BatteryStatusRefresh\r
+              | Stack used (prev) :  00000039 00000012\r
+              | + function block  :  00000004 00000002\r
+  04        BatteryCheck\r
+            | Stack used (prev) :  0000003D 00000014\r
+            | + function block  :  00000003 00000002\r
+  04        PWM_Stop\r
+            | Stack used (prev) :  00000036 0000000E\r
+            | + function block  :  00000000 00000002\r
+  04        ADC_Wait\r
+            | Stack used (prev) :  00000036 0000000E\r
+            | + function block  :  00000000 00000002\r
+  03      HaltNow\r
+          | Stack used (prev) :  00000040 00000016\r
+          | + function block  :  0000000A 00000002\r
+  03      PWM_DecrementDutyCycle\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  03      PWM_IncrementDutyCycle\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  03      ADC_Wait\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  02    ConstantCurrent\r
+        | Stack used (prev) :  0000004A 00000018\r
+        | + function block  :  00000006 00000002\r
+  03      Time_Set\r
+          | Stack used (prev) :  00000016 00000006\r
+          | + function block  :  00000008 00000004\r
+          |  Already listed\r
+  03      Time_Left\r
+          | Stack used (prev) :  00000016 00000006\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  02    PWM_Start\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+  02    PWM_Stop\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  01  Charge\r
+      | Stack used (prev) :  00000050 0000001A\r
+      | + function block  :  00000002 00000002\r
+  <-Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+    | Stack used          :  00000052 0000001C\r
+\r
+\r
+  ->Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000036 0000000E\r
+  02    Time_Init\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+  02    DisableBatteries\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+  03      Time_Set\r
+          | Stack used (prev) :  00000016 00000006\r
+          | + function block  :  00000008 00000004\r
+          |  Already listed\r
+  03      Time_Left\r
+          | Stack used (prev) :  00000016 00000006\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  02    EnableBattery\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000001 00000004\r
+  02    BatteryStatusRefresh\r
+        | Stack used (prev) :  00000039 00000012\r
+        | + function block  :  00000004 00000002\r
+        |  Already listed\r
+  02    SPI_Init\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+  02    OWI_Init\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+  02    ADC_Init\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+  02    ADC_Wait\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  01  Initialize\r
+      | Stack used (prev) :  0000003D 00000014\r
+      | + function block  :  00000001 00000002\r
+  <-Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+    | Stack used          :  0000003E 00000016\r
+\r
+\r
+  ->Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000036 0000000E\r
+  03      abs\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  03      Time_Set\r
+          | Stack used (prev) :  00000016 00000006\r
+          | + function block  :  00000008 00000004\r
+          |  Already listed\r
+  03      Time_Left\r
+          | Stack used (prev) :  00000016 00000006\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  03      DisableBatteries\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  03      PWM_IncrementDutyCycle\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  03      PWM_Start\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  03      PWM_Stop\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  03      ADC_Wait\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+          |  Already listed\r
+  02    JumperCheck\r
+        | Stack used (prev) :  00000036 00000010\r
+        | + function block  :  00000002 00000002\r
+  02    DisableBatteries\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    EnableBattery\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000001 00000004\r
+        |  Already listed\r
+  03      OWI_ComputeCRC8\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  04        OWI_ReadBit\r
+            | Stack used (prev) :  00000036 0000000E\r
+            | + function block  :  00000000 00000002\r
+  03      OWI_ReceiveByte\r
+          | Stack used (prev) :  00000036 00000010\r
+          | + function block  :  00000003 00000002\r
+  04        OWI_WriteBit0\r
+            | Stack used (prev) :  00000036 0000000E\r
+            | + function block  :  00000000 00000002\r
+  04        OWI_WriteBit1\r
+            | Stack used (prev) :  00000036 0000000E\r
+            | + function block  :  00000000 00000002\r
+  03      OWI_SendByte\r
+          | Stack used (prev) :  00000036 00000010\r
+          | + function block  :  00000003 00000002\r
+  03      OWI_DetectPresence\r
+          | Stack used (prev) :  00000036 0000000E\r
+          | + function block  :  00000000 00000002\r
+  02    BatteryDataRefresh\r
+        | Stack used (prev) :  00000039 00000012\r
+        | + function block  :  00000009 00000002\r
+  02    BatteryStatusRefresh\r
+        | Stack used (prev) :  00000039 00000012\r
+        | + function block  :  00000004 00000002\r
+        |  Already listed\r
+  02    ADC_Wait\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  01  BatteryControl\r
+      | Stack used (prev) :  00000042 00000014\r
+      | + function block  :  00000004 00000002\r
+  <-Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+    | Stack used          :  00000046 00000016\r
+\r
+\r
+  ->Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000036 0000000E\r
+  01  Discharge\r
+      | Stack used (prev) :  00000036 0000000E\r
+      | + function block  :  00000000 00000002\r
+  <-Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+    | Stack used          :  00000036 00000010\r
+\r
+\r
+  ->Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000036 0000000E\r
+  02    ADC_Wait\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  01  Sleep\r
+      | Stack used (prev) :  00000036 00000010\r
+      | + function block  :  00000000 00000002\r
+  <-Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+    | Stack used          :  00000036 00000012\r
+\r
+\r
+  ->Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000036 0000000E\r
+  02    DisableBatteries\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    PWM_Stop\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  02    ADC_Wait\r
+        | Stack used (prev) :  00000036 0000000E\r
+        | + function block  :  00000000 00000002\r
+        |  Already listed\r
+  01  Error\r
+      | Stack used (prev) :  00000036 00000010\r
+      | + function block  :  00000000 00000002\r
+  <-Sub-tree of type: Indirectly called function tree that does not make\r
+                    : indirect calls (Is not an interrupt and is not flagged\r
+                    : as not overlayable)\r
+    | Stack used          :  00000036 00000012\r
+\r
+\r
+  ->Sub-tree of type: Function tree that makes indirect calls\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000052 0000001C\r
+  01  main\r
+      | Stack used (prev) :  00000052 0000001C\r
+      | + function block  :  00000002 00000002\r
+  <-Sub-tree of type: Function tree that makes indirect calls\r
+    | Stack used          :  00000054 0000001E\r
+\r
+\r
+  ->Sub-tree of type: Function tree\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000054 0000001E\r
+  01  __low_level_init\r
+      | Stack used (prev) :  00000054 0000001E\r
+      | + function block  :  00000000 00000002\r
+  <-Sub-tree of type: Function tree\r
+    | Stack used          :  00000054 00000020\r
+\r
+\r
+  ->Sub-tree of type: Function tree\r
+                             CSTACK   RSTACK\r
+    | Stack used (prev) :  00000054 00000020\r
+  02    __flashcpy\r
+        | Stack used (prev) :  00000054 00000020\r
+        | + function block  :  00000000 00000002\r
+  02    __memclr\r
+        | Stack used (prev) :  00000054 00000020\r
+        | + function block  :  00000000 00000002\r
+  01  __segment_init\r
+      | Stack used (prev) :  00000054 00000022\r
+      | + function block  :  00000000 00000002\r
+  <-Sub-tree of type: Function tree\r
+    | Stack used          :  00000054 00000024\r
+\r
+\r
+\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *      SEGMENTS IN ADDRESS ORDER       *\r
+                *                                      *\r
+                ****************************************\r
+\r
+\r
+SEGMENT              SPACE    START ADDRESS   END ADDRESS     SIZE  TYPE  ALIGN\r
+=======              =====    =============   ===========     ====  ====  =====\r
+INTVEC               CODE          00000000 - 0000001D          1E   com    1\r
+?FILL1               CODE          0000001E - 00000025           8   rel    0\r
+NEAR_F               CODE          00000026 - 00000043          1E   rel    0\r
+INITTAB              CODE          00000044 - 0000004F           C   rel    0\r
+CODE                 CODE          00000050 - 000011F9        11AA   rel    1\r
+NEAR_ID              CODE          000011FA - 0000126D          74   rel    0\r
+ABSOLUTE             DATA               0000001C                     rel    0\r
+                     DATA               0000001D                   \r
+                     DATA               0000001E                   \r
+                     DATA               0000001F                   \r
+                     DATA          00000020 - 00000020           1 \r
+                     DATA          00000023 - 00000027           5 \r
+                     DATA          0000002D - 0000002F           3 \r
+                     DATA          00000032 - 00000033           2 \r
+                     DATA          00000035 - 00000035           1 \r
+                     DATA          00000037 - 0000003B           5 \r
+                     DATA          00000041 - 00000041           1 \r
+                     DATA          00000044 - 00000044           1 \r
+                     DATA          00000046 - 0000004D           8 \r
+                     DATA          0000004F - 00000050           2 \r
+                     DATA          00000053 - 00000055           3 \r
+                     DATA          00000059 - 00000059           1 \r
+CSTACK               DATA          00000060 - 0000009F          40   dse    0\r
+RSTACK               DATA          000000A0 - 000000CF          30   dse    0\r
+NEAR_I               DATA          000000D0 - 00000143          74   rel    0\r
+NEAR_Z               DATA          00000144 - 00000196          53   rel    0\r
+EEPROM_I             XDATA         00000000 - 00000082          83   rel    0\r
+\r
+                ****************************************\r
+                *                                      *\r
+                *        END OF CROSS REFERENCE        *\r
+                *                                      *\r
+                ****************************************\r
+\r
+ 4 710 bytes of CODE  memory (+             8 range fill )\r
+   311 bytes of DATA  memory (+ 33 absolute )\r
+   131 bytes of XDATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
+\r
diff --git a/BaseTinyFirmware/IAR/Release/List/NIMHcharge.lst b/BaseTinyFirmware/IAR/Release/List/NIMHcharge.lst
new file mode 100644 (file)
index 0000000..fefe96f
--- /dev/null
@@ -0,0 +1,389 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:02 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c    #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c    #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\NI #\r
+#                             MHcharge.lst                                    #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIM #\r
+#                             Hcharge.r90                                     #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Charge state function for NiMH batteries\r
+      6           *\r
+      7           *      Contains the charge state function, in which the NiMH charging\r
+      8           *      algorithm is, plus the associated functions.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR463: Charging NiMH Batteries with BC100 \n\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2255 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $\r
+     26           * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          #include <ioavr.h>\r
+     30          \r
+     31          #include "enums.h"\r
+     32          #include "structs.h"\r
+     33          \r
+     34          #include "battery.h"\r
+     35          #include "charge.h"\r
+     36          #include "chargefunc.h"\r
+     37          #include "main.h"\r
+     38          #include "menu.h"\r
+     39          #include "NIMHspecs.h"\r
+     40          #include "PWM.h"\r
+     41          #include "time.h"\r
+     42          \r
+     43          #ifndef NIMH\r
+     44          #error NIMH not defined in main.h!\r
+     45          #endif // NIMH\r
+     46          \r
+     47          \r
+     48          //******************************************************************************\r
+     49          // Functions\r
+     50          //******************************************************************************\r
+     51          /*! \brief Controls the charging.\r
+     52           *\r
+     53           * This function contains the charging algorithm itself, divided into stages.\n\r
+     54           * For each stage the PWM may be started/stopped, and the timer, \r
+     55           * halt-requirements and charge parameters may be set.\n\r
+     56           * The charging functions return whatever state is next, and as long as no\r
+     57           * errors occur this is the next charging stage.\r
+     58           *\r
+     59           * \note If more stages are needed simply define more states in menu.h, include\r
+     60           * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+     61           *\r
+     62           * \note This algorithm is for NiMH batteries.\r
+     63           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     64          unsigned char Charge(unsigned char inp)\r
+   \                     Charge:\r
+     65          {\r
+     66                unsigned char NextState;\r
+     67          \r
+     68                switch (CurrentState) {\r
+   \   00000000   9100....           LDS     R16, CurrentState\r
+   \   00000004   510E               SUBI    R16, 30\r
+   \   00000006   F049               BREQ    ??Charge_0\r
+   \   00000008   5104               SUBI    R16, 20\r
+   \   0000000A   F149               BREQ    ??Charge_1\r
+   \   0000000C   500A               SUBI    R16, 10\r
+   \   0000000E   F409               BRNE    $+2+2\r
+   \   00000010   C04A               RJMP    ??Charge_2\r
+   \   00000012   500A               SUBI    R16, 10\r
+   \   00000014   F409               BRNE    $+2+2\r
+   \   00000016   C05E               RJMP    ??Charge_3\r
+   \   00000018   C077               RJMP    ??Charge_4\r
+     69                // First stage is a prequalification. Attempt to charge battery to 1 V,\r
+     70                // using a 0.1 C current, within 2 minutes.\r
+     71                // If this fails, the battery is likely damaged.\r
+     72                // If it succeeds, start a fast charge.\r
+     73                case ST_PREQUAL:\r
+     74                        \r
+     75                        // Set up charge current and next state.\r
+     76                        ChargeParameters.Current = BattData.Capacity / 10;\r
+   \                     ??Charge_0:\r
+   \   0000001A   ....               LDI     R30, LOW(BattData)\r
+   \   0000001C   ....               LDI     R31, (BattData) >> 8\r
+   \   0000001E   8104               LDD     R16, Z+4\r
+   \   00000020   8115               LDD     R17, Z+5\r
+   \   00000022   E04A               LDI     R20, 10\r
+   \   00000024   E050               LDI     R21, 0\r
+   \   00000026   ....               RCALL   ?US_DIVMOD_L02\r
+   \   00000028   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   0000002A   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   0000002C   8302               STD     Z+2, R16\r
+   \   0000002E   8313               STD     Z+3, R17\r
+     77                        ChargeParameters.NextState = ST_FASTCHARGE;\r
+   \   00000030   E302               LDI     R16, 50\r
+   \   00000032   8304               STD     Z+4, R16\r
+     78                        \r
+     79                        // Halt charge on voltage limit or timeout.\r
+     80                        // Timeout means battery exhaustion.\r
+     81                        HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+     82                                                    HALT_FLAG_EXHAUSTION);\r
+   \   00000034   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000036   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000038   8300               ST      Z, R16\r
+     83                        \r
+     84                        // Set up voltage limit and temperature limits.\r
+     85                        HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+   \   0000003A   EB08               LDI     R16, 184\r
+   \   0000003C   E01B               LDI     R17, 11\r
+   \   0000003E   8303               STD     Z+3, R16\r
+   \   00000040   8314               STD     Z+4, R17\r
+     86                        HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+   \   00000042   E005               LDI     R16, 5\r
+   \   00000044   E010               LDI     R17, 0\r
+   \   00000046   8701               STD     Z+9, R16\r
+   \   00000048   8712               STD     Z+10, R17\r
+     87                        HaltParameters.TemperatureMax = 35;\r
+   \   0000004A   E203               LDI     R16, 35\r
+   \   0000004C   8307               STD     Z+7, R16\r
+   \   0000004E   8710               STD     Z+8, R17\r
+     88                        \r
+     89                        // Reset temperature measurement for HaltNow().\r
+     90                        HaltParameters.LastNTC = 0;\r
+   \   00000050   8717               STD     Z+15, R17\r
+   \   00000052   8B10               STD     Z+16, R17\r
+     91                        \r
+     92                        // Start PWM and charge timer before calling the charge function.\r
+     93                        PWM_Start();\r
+   \   00000054   ....               RCALL   PWM_Start\r
+     94                        Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+   \   00000056   E040               LDI     R20, 0\r
+   \   00000058   E010               LDI     R17, 0\r
+   \   0000005A   E022               LDI     R18, 2\r
+   \   0000005C   C037               RJMP    ??Charge_5\r
+     95                        \r
+     96                        // Call charge function, get next state.\r
+     97                        NextState = ConstantCurrent();\r
+     98                break;\r
+     99          \r
+    100          \r
+    101                // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,\r
+    102                // until either rate of temperature increase or voltage reaches limit, or\r
+    103                // the voltage drops sufficiently.\r
+    104                // Timeout doesn't mean battery exhaustion now.\r
+    105                case ST_FASTCHARGE:\r
+    106          \r
+    107                        // Set up charge current and next state.\r
+    108                        ChargeParameters.Current = BattData.Capacity;\r
+   \                     ??Charge_1:\r
+   \   0000005E   ....               LDI     R18, LOW(BattData)\r
+   \   00000060   ....               LDI     R19, (BattData) >> 8\r
+   \   00000062   01F9               MOVW    R31:R30, R19:R18\r
+   \   00000064   8104               LDD     R16, Z+4\r
+   \   00000066   8115               LDD     R17, Z+5\r
+   \   00000068   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   0000006A   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   0000006C   8302               STD     Z+2, R16\r
+   \   0000006E   8313               STD     Z+3, R17\r
+    109                        ChargeParameters.NextState = ST_LOWRATECHARGE;\r
+   \   00000070   E30C               LDI     R16, 60\r
+   \   00000072   8304               STD     Z+4, R16\r
+    110                        \r
+    111                        // Halt charge on voltage limit, timeout, voltage drop or rate of \r
+    112                        // temperature increase.\r
+    113                        HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+    114                                                    HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);\r
+   \   00000074   ....               LDI     R30, LOW(HaltParameters)\r
+   \   00000076   ....               LDI     R31, (HaltParameters) >> 8\r
+   \   00000078   E10B               LDI     R16, 27\r
+   \   0000007A   8300               ST      Z, R16\r
+    115                        \r
+    116                        // Set up limits for voltage, voltage drop, temperature and rate of \r
+    117                        // temperature increase (1 degree C per minute).\r
+    118                        HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+   \   0000007C   EC00               LDI     R16, 192\r
+   \   0000007E   E112               LDI     R17, 18\r
+   \   00000080   8303               STD     Z+3, R16\r
+   \   00000082   8314               STD     Z+4, R17\r
+    119                        HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;\r
+   \   00000084   E20D               LDI     R16, 45\r
+   \   00000086   E010               LDI     R17, 0\r
+   \   00000088   8301               STD     Z+1, R16\r
+   \   0000008A   8312               STD     Z+2, R17\r
+    120                        HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+   \   0000008C   E302               LDI     R16, 50\r
+   \   0000008E   8307               STD     Z+7, R16\r
+   \   00000090   8710               STD     Z+8, R17\r
+    121                        HaltParameters.TemperatureRise = 1;\r
+   \   00000092   E001               LDI     R16, 1\r
+   \   00000094   8703               STD     Z+11, R16\r
+   \   00000096   8714               STD     Z+12, R17\r
+    122                        \r
+    123                        // Reset maximum voltage measurement for HaltNow().\r
+    124                        HaltParameters.VBATMax = 0;\r
+   \   00000098   8715               STD     Z+13, R17\r
+   \   0000009A   8716               STD     Z+14, R17\r
+    125          \r
+    126                        // Start timer, PWM should still be running.\r
+    127                        Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);\r
+   \   0000009C   E040               LDI     R20, 0\r
+   \   0000009E   01F9               MOVW    R31:R30, R19:R18\r
+   \   000000A0   8520               LDD     R18, Z+8\r
+   \   000000A2   8531               LDD     R19, Z+9\r
+   \   000000A4   C015               RJMP    ??Charge_6\r
+    128          \r
+    129                        // Call charge function, get next state.\r
+    130                        NextState = ConstantCurrent();\r
+    131                break;\r
+    132          \r
+    133          \r
+    134                // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,\r
+    135                // until either rate of temperature increase or voltage reaches limit.\r
+    136                case ST_LOWRATECHARGE:\r
+    137                        \r
+    138                        // Set up charge current and next state.\r
+    139                        ChargeParameters.Current = BattData.Capacity / 10;\r
+   \                     ??Charge_2:\r
+   \   000000A6   ....               LDI     R30, LOW(BattData)\r
+   \   000000A8   ....               LDI     R31, (BattData) >> 8\r
+   \   000000AA   8104               LDD     R16, Z+4\r
+   \   000000AC   8115               LDD     R17, Z+5\r
+   \   000000AE   E04A               LDI     R20, 10\r
+   \   000000B0   E050               LDI     R21, 0\r
+   \   000000B2   ....               RCALL   ?US_DIVMOD_L02\r
+   \   000000B4   ....               LDI     R30, LOW(ChargeParameters)\r
+   \   000000B6   ....               LDI     R31, (ChargeParameters) >> 8\r
+   \   000000B8   8302               STD     Z+2, R16\r
+   \   000000BA   8313               STD     Z+3, R17\r
+    140                        ChargeParameters.NextState = ST_ENDCHARGE;\r
+   \   000000BC   E406               LDI     R16, 70\r
+   \   000000BE   8304               STD     Z+4, R16\r
+    141                        \r
+    142                        // Halt charge on voltage limit, timeout or temperature rise.\r
+    143                        // Use the same requirements as during the last stage (ST_FASTCHARGE).\r
+    144                        HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+    145                                                    HALT_TEMPERATURE_RISE);\r
+   \   000000C0   E10A               LDI     R16, 26\r
+   \   000000C2   9300....           STS     HaltParameters, R16\r
+    146          \r
+    147                        // Start timer, 30 minutes.\r
+    148                        Time_Set(TIMER_CHG, 30, 0, 0);\r
+   \   000000C6   E040               LDI     R20, 0\r
+   \   000000C8   E010               LDI     R17, 0\r
+   \   000000CA   E12E               LDI     R18, 30\r
+   \                     ??Charge_5:\r
+   \   000000CC   E030               LDI     R19, 0\r
+   \   000000CE   E001               LDI     R16, 1\r
+   \                     ??Charge_6:\r
+   \   000000D0   ....               RCALL   Time_Set\r
+    149                        \r
+    150                        // Call charge function, get next state.\r
+    151                        NextState = ConstantCurrent();\r
+   \   000000D2   ....               RJMP    ConstantCurrent\r
+    152                break;\r
+    153          \r
+    154          \r
+    155                // Charging is done!\r
+    156                case ST_ENDCHARGE:\r
+    157          \r
+    158                        // Stop the PWM output and flag battery as charged.\r
+    159                        PWM_Stop();\r
+   \                     ??Charge_3:\r
+   \   000000D4   ....               RCALL   PWM_Stop\r
+    160                        BattData.Charged = TRUE;\r
+   \   000000D6   ....               LDI     R30, LOW(BattData)\r
+   \   000000D8   ....               LDI     R31, (BattData) >> 8\r
+   \   000000DA   8100               LD      R16, Z\r
+   \   000000DC   6002               ORI     R16, 0x02\r
+   \   000000DE   8300               ST      Z, R16\r
+    161                        \r
+    162                        // If the other battery is enabled go to ST_BATCON, otherwise\r
+    163                        // go to ST_SLEEP.\r
+    164                        if (BattControl[(BattActive+1)%2].Enabled) {\r
+   \   000000E0   9100....           LDS     R16, BattActive\r
+   \   000000E4   E010               LDI     R17, 0\r
+   \   000000E6   5F0F               SUBI    R16, 255\r
+   \   000000E8   4F1F               SBCI    R17, 255\r
+   \   000000EA   E042               LDI     R20, 2\r
+   \   000000EC   E050               LDI     R21, 0\r
+   \   000000EE   ....               RCALL   ?SS_DIVMOD_L02\r
+   \   000000F0   ....               LDI     R18, LOW(BattControl)\r
+   \   000000F2   ....               LDI     R19, (BattControl) >> 8\r
+   \   000000F4   0F24               ADD     R18, R20\r
+   \   000000F6   1F35               ADC     R19, R21\r
+   \   000000F8   01A9               MOVW    R21:R20, R19:R18\r
+   \   000000FA   ....               RCALL   __eeget8_16\r
+   \   000000FC   7001               ANDI    R16, 0x01\r
+   \   000000FE   F011               BREQ    ??Charge_7\r
+    165                                NextState = ST_BATCON;\r
+   \   00000100   E104               LDI     R16, 20\r
+   \   00000102   9508               RET\r
+    166                        } else {\r
+    167                                NextState = ST_SLEEP;\r
+   \                     ??Charge_7:\r
+   \   00000104   E208               LDI     R16, 40\r
+   \   00000106   9508               RET\r
+    168                        }               \r
+    169                break;\r
+    170          \r
+    171          \r
+    172                default:  // Shouldn't end up here. Reinitialize for safety.\r
+    173                        NextState = ST_INIT;\r
+   \                     ??Charge_4:\r
+   \   00000108   E00A               LDI     R16, 10\r
+    174                        break;\r
+    175                }\r
+    176          \r
+    177                // Return the next state to main().\r
+    178                return(NextState);\r
+   \   0000010A   9508               RET\r
+    179          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function             CSTACK RSTACK\r
+     --------             ------ ------\r
+     Charge                   2      4\r
+       -> PWM_Start           2      2\r
+       -> Time_Set            2      2\r
+       -> ConstantCurrent     2      2\r
+       -> Time_Set            2      2\r
+       -> ConstantCurrent     2      2\r
+       -> Time_Set            2      2\r
+       -> ConstantCurrent     2      2\r
+       -> PWM_Stop            2      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     Charge          268\r
+\r
\r
+ 268 bytes in segment CODE\r
\r
+ 268 bytes of CODE memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/NIMHcharge.s90 b/BaseTinyFirmware/IAR/Release/List/NIMHcharge.s90
new file mode 100644 (file)
index 0000000..a9ad11d
--- /dev/null
@@ -0,0 +1,405 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:02 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c   /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c   /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\N /\r
+//                             IMHcharge.s90                                  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME NIMHcharge\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?SS_DIVMOD_L02\r
+        EXTERN ?US_DIVMOD_L02\r
+        EXTERN __eeget8_16\r
+\r
+        PUBLIC Charge\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN PWM_Start\r
+        EXTERN Time_Set\r
+        EXTERN ConstantCurrent\r
+        EXTERN PWM_Stop\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+        EXTERN ChargeParameters\r
+        EXTERN CurrentState\r
+        EXTERN HaltParameters\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Charge state function for NiMH batteries\r
+//    6  *\r
+//    7  *      Contains the charge state function, in which the NiMH charging\r
+//    8  *      algorithm is, plus the associated functions.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100 \n\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2255 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $\r
+//   26  * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 #include <ioavr.h>\r
+//   30 \r
+//   31 #include "enums.h"\r
+//   32 #include "structs.h"\r
+//   33 \r
+//   34 #include "battery.h"\r
+//   35 #include "charge.h"\r
+//   36 #include "chargefunc.h"\r
+//   37 #include "main.h"\r
+//   38 #include "menu.h"\r
+//   39 #include "NIMHspecs.h"\r
+//   40 #include "PWM.h"\r
+//   41 #include "time.h"\r
+//   42 \r
+//   43 #ifndef NIMH\r
+//   44 #error NIMH not defined in main.h!\r
+//   45 #endif // NIMH\r
+//   46 \r
+//   47 \r
+//   48 //******************************************************************************\r
+//   49 // Functions\r
+//   50 //******************************************************************************\r
+//   51 /*! \brief Controls the charging.\r
+//   52  *\r
+//   53  * This function contains the charging algorithm itself, divided into stages.\n\r
+//   54  * For each stage the PWM may be started/stopped, and the timer, \r
+//   55  * halt-requirements and charge parameters may be set.\n\r
+//   56  * The charging functions return whatever state is next, and as long as no\r
+//   57  * errors occur this is the next charging stage.\r
+//   58  *\r
+//   59  * \note If more stages are needed simply define more states in menu.h, include\r
+//   60  * them in \ref menu_state[] in menu.c, then add the cases to this function.\r
+//   61  *\r
+//   62  * \note This algorithm is for NiMH batteries.\r
+//   63  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   64 unsigned char Charge(unsigned char inp)\r
+Charge:\r
+//   65 {\r
+//   66        unsigned char NextState;\r
+//   67 \r
+//   68        switch (CurrentState) {\r
+        LDS     R16, CurrentState\r
+        SUBI    R16, 30\r
+        BREQ    ??Charge_0\r
+        SUBI    R16, 20\r
+        BREQ    ??Charge_1\r
+        SUBI    R16, 10\r
+        BRNE    $+2+2\r
+        RJMP    ??Charge_2\r
+        SUBI    R16, 10\r
+        BRNE    $+2+2\r
+        RJMP    ??Charge_3\r
+        RJMP    ??Charge_4\r
+//   69        // First stage is a prequalification. Attempt to charge battery to 1 V,\r
+//   70        // using a 0.1 C current, within 2 minutes.\r
+//   71        // If this fails, the battery is likely damaged.\r
+//   72        // If it succeeds, start a fast charge.\r
+//   73        case ST_PREQUAL:\r
+//   74                \r
+//   75                // Set up charge current and next state.\r
+//   76                ChargeParameters.Current = BattData.Capacity / 10;\r
+??Charge_0:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R20, 10\r
+        LDI     R21, 0\r
+        RCALL   ?US_DIVMOD_L02\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//   77                ChargeParameters.NextState = ST_FASTCHARGE;\r
+        LDI     R16, 50\r
+        STD     Z+4, R16\r
+//   78                \r
+//   79                // Halt charge on voltage limit or timeout.\r
+//   80                // Timeout means battery exhaustion.\r
+//   81                HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+//   82                                            HALT_FLAG_EXHAUSTION);\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        ST      Z, R16\r
+//   83                \r
+//   84                // Set up voltage limit and temperature limits.\r
+//   85                HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL;\r
+        LDI     R16, 184\r
+        LDI     R17, 11\r
+        STD     Z+3, R16\r
+        STD     Z+4, R17\r
+//   86                HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN;\r
+        LDI     R16, 5\r
+        LDI     R17, 0\r
+        STD     Z+9, R16\r
+        STD     Z+10, R17\r
+//   87                HaltParameters.TemperatureMax = 35;\r
+        LDI     R16, 35\r
+        STD     Z+7, R16\r
+        STD     Z+8, R17\r
+//   88                \r
+//   89                // Reset temperature measurement for HaltNow().\r
+//   90                HaltParameters.LastNTC = 0;\r
+        STD     Z+15, R17\r
+        STD     Z+16, R17\r
+//   91                \r
+//   92                // Start PWM and charge timer before calling the charge function.\r
+//   93                PWM_Start();\r
+        RCALL   PWM_Start\r
+//   94                Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0);\r
+        LDI     R20, 0\r
+        LDI     R17, 0\r
+        LDI     R18, 2\r
+        RJMP    ??Charge_5\r
+//   95                \r
+//   96                // Call charge function, get next state.\r
+//   97                NextState = ConstantCurrent();\r
+//   98        break;\r
+//   99 \r
+//  100 \r
+//  101        // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours,\r
+//  102        // until either rate of temperature increase or voltage reaches limit, or\r
+//  103        // the voltage drops sufficiently.\r
+//  104        // Timeout doesn't mean battery exhaustion now.\r
+//  105        case ST_FASTCHARGE:\r
+//  106 \r
+//  107                // Set up charge current and next state.\r
+//  108                ChargeParameters.Current = BattData.Capacity;\r
+??Charge_1:\r
+        LDI     R18, LOW(BattData)\r
+        LDI     R19, (BattData) >> 8\r
+        MOVW    R31:R30, R19:R18\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//  109                ChargeParameters.NextState = ST_LOWRATECHARGE;\r
+        LDI     R16, 60\r
+        STD     Z+4, R16\r
+//  110                \r
+//  111                // Halt charge on voltage limit, timeout, voltage drop or rate of \r
+//  112                // temperature increase.\r
+//  113                HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+//  114                                            HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE);\r
+        LDI     R30, LOW(HaltParameters)\r
+        LDI     R31, (HaltParameters) >> 8\r
+        LDI     R16, 27\r
+        ST      Z, R16\r
+//  115                \r
+//  116                // Set up limits for voltage, voltage drop, temperature and rate of \r
+//  117                // temperature increase (1 degree C per minute).\r
+//  118                HaltParameters.VoltageMax = BAT_VOLTAGE_MAX;\r
+        LDI     R16, 192\r
+        LDI     R17, 18\r
+        STD     Z+3, R16\r
+        STD     Z+4, R17\r
+//  119                HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP;\r
+        LDI     R16, 45\r
+        LDI     R17, 0\r
+        STD     Z+1, R16\r
+        STD     Z+2, R17\r
+//  120                HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX;\r
+        LDI     R16, 50\r
+        STD     Z+7, R16\r
+        STD     Z+8, R17\r
+//  121                HaltParameters.TemperatureRise = 1;\r
+        LDI     R16, 1\r
+        STD     Z+11, R16\r
+        STD     Z+12, R17\r
+//  122                \r
+//  123                // Reset maximum voltage measurement for HaltNow().\r
+//  124                HaltParameters.VBATMax = 0;\r
+        STD     Z+13, R17\r
+        STD     Z+14, R17\r
+//  125 \r
+//  126                // Start timer, PWM should still be running.\r
+//  127                Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0);\r
+        LDI     R20, 0\r
+        MOVW    R31:R30, R19:R18\r
+        LDD     R18, Z+8\r
+        LDD     R19, Z+9\r
+        RJMP    ??Charge_6\r
+//  128 \r
+//  129                // Call charge function, get next state.\r
+//  130                NextState = ConstantCurrent();\r
+//  131        break;\r
+//  132 \r
+//  133 \r
+//  134        // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes,\r
+//  135        // until either rate of temperature increase or voltage reaches limit.\r
+//  136        case ST_LOWRATECHARGE:\r
+//  137                \r
+//  138                // Set up charge current and next state.\r
+//  139                ChargeParameters.Current = BattData.Capacity / 10;\r
+??Charge_2:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        LDI     R20, 10\r
+        LDI     R21, 0\r
+        RCALL   ?US_DIVMOD_L02\r
+        LDI     R30, LOW(ChargeParameters)\r
+        LDI     R31, (ChargeParameters) >> 8\r
+        STD     Z+2, R16\r
+        STD     Z+3, R17\r
+//  140                ChargeParameters.NextState = ST_ENDCHARGE;\r
+        LDI     R16, 70\r
+        STD     Z+4, R16\r
+//  141                \r
+//  142                // Halt charge on voltage limit, timeout or temperature rise.\r
+//  143                // Use the same requirements as during the last stage (ST_FASTCHARGE).\r
+//  144                HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME |\r
+//  145                                            HALT_TEMPERATURE_RISE);\r
+        LDI     R16, 26\r
+        STS     HaltParameters, R16\r
+//  146 \r
+//  147                // Start timer, 30 minutes.\r
+//  148                Time_Set(TIMER_CHG, 30, 0, 0);\r
+        LDI     R20, 0\r
+        LDI     R17, 0\r
+        LDI     R18, 30\r
+??Charge_5:\r
+        LDI     R19, 0\r
+        LDI     R16, 1\r
+??Charge_6:\r
+        RCALL   Time_Set\r
+//  149                \r
+//  150                // Call charge function, get next state.\r
+//  151                NextState = ConstantCurrent();\r
+        RJMP    ConstantCurrent\r
+//  152        break;\r
+//  153 \r
+//  154 \r
+//  155        // Charging is done!\r
+//  156        case ST_ENDCHARGE:\r
+//  157 \r
+//  158                // Stop the PWM output and flag battery as charged.\r
+//  159                PWM_Stop();\r
+??Charge_3:\r
+        RCALL   PWM_Stop\r
+//  160                BattData.Charged = TRUE;\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x02\r
+        ST      Z, R16\r
+//  161                \r
+//  162                // If the other battery is enabled go to ST_BATCON, otherwise\r
+//  163                // go to ST_SLEEP.\r
+//  164                if (BattControl[(BattActive+1)%2].Enabled) {\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        SUBI    R16, 255\r
+        SBCI    R17, 255\r
+        LDI     R20, 2\r
+        LDI     R21, 0\r
+        RCALL   ?SS_DIVMOD_L02\r
+        LDI     R18, LOW(BattControl)\r
+        LDI     R19, (BattControl) >> 8\r
+        ADD     R18, R20\r
+        ADC     R19, R21\r
+        MOVW    R21:R20, R19:R18\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        BREQ    ??Charge_7\r
+//  165                        NextState = ST_BATCON;\r
+        LDI     R16, 20\r
+        RET\r
+//  166                } else {\r
+//  167                        NextState = ST_SLEEP;\r
+??Charge_7:\r
+        LDI     R16, 40\r
+        RET\r
+//  168                }               \r
+//  169        break;\r
+//  170 \r
+//  171 \r
+//  172        default:  // Shouldn't end up here. Reinitialize for safety.\r
+//  173                NextState = ST_INIT;\r
+??Charge_4:\r
+        LDI     R16, 10\r
+//  174                break;\r
+//  175        }\r
+//  176 \r
+//  177        // Return the next state to main().\r
+//  178        return(NextState);\r
+        RET\r
+//  179 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+// \r
+// 268 bytes in segment CODE\r
+// \r
+// 268 bytes of CODE memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/OWI.lst b/BaseTinyFirmware/IAR/Release/List/OWI.lst
new file mode 100644 (file)
index 0000000..7eab274
--- /dev/null
@@ -0,0 +1,1082 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:49:36 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\OWI.c           #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\OWI.c           #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\OW #\r
+#                             I.lst                                           #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI #\r
+#                             .r90                                            #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\OWI.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file ********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for 1-Wire(R) bus communication\r
+      6           *\r
+      7           *      High level functions for transmission of full bytes on the 1-Wire(R)\r
+      8           *      bus and implementations of ROM commands.\n\r
+      9           *      Polled software only implementation of the basic bit-level signalling\r
+     10           *      in the 1-Wire(R) protocol.\n\r
+     11           *      Includes functions for computing and checking CRC8 & 16 values of data\r
+     12           *      sets, and of 64 bit ROM identifiers.\r
+     13           *      Supported devices:  All AVRs.\r
+     14           *\r
+     15           * \par Application Note:\r
+     16           *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+     17           *      AVR463: Charging NiMH Batteries with BC100\n\r
+     18           *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+     19           *\r
+     20           * \par Documentation:\r
+     21           *      For comprehensive code documentation, supported compilers, compiler\r
+     22           *      settings and supported devices see readme.html\r
+     23           *\r
+     24           * \author\r
+     25           *      Atmel Corporation: http://www.atmel.com \n\r
+     26           *      Support email: avr@atmel.com \n\r
+     27           *      Original author: \n\r
+     28           *\r
+     29           * $Name$\r
+     30           * $Revision: 2299 $\r
+     31           * $RCSfile$\r
+     32           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
+     33           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     34          ****************************************************************************/\r
+     35          \r
+     36          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3b\r
+   \   <unnamed> volatile __io _A_PORTA\r
+   \                     _A_PORTA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x3a\r
+   \   <unnamed> volatile __io _A_DDRA\r
+   \                     _A_DDRA:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x39\r
+   \   <unnamed> volatile __io _A_PINA\r
+   \                     _A_PINA:\r
+   \   00000000                      DS 1\r
+     37          #include <inavr.h>\r
+     38          \r
+     39          #include "OWI.h"\r
+     40          \r
+     41          \r
+     42          //******************************************************************************\r
+     43          // Functions\r
+     44          //******************************************************************************\r
+     45          /*! \brief Initialization of the one wire bus(es). (Software only driver)\r
+     46           *  \r
+     47           *  This function initializes the 1-Wire bus(es) by releasing it and\r
+     48           *  waiting until any presence signals are finished.\r
+     49           *\r
+     50           *  \param  pins    A bitmask of the buses to initialize.\r
+     51           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     52          void OWI_Init(unsigned char pins){\r
+   \                     OWI_Init:\r
+     53                OWI_RELEASE_BUS(pins);\r
+   \   00000000   9500               COM     R16\r
+   \   00000002   B31A               IN      R17, 0x1A\r
+   \   00000004   2310               AND     R17, R16\r
+   \   00000006   BB1A               OUT     0x1A, R17\r
+   \   00000008   B31B               IN      R17, 0x1B\r
+   \   0000000A   2310               AND     R17, R16\r
+   \   0000000C   BB1B               OUT     0x1B, R17\r
+     54                // The first rising edge can be interpreted by a slave as the end of a\r
+     55                // Reset-pulse. Delay for the required reset recovery time (H) to be \r
+     56                // sure that the real reset is interpreted correctly.\r
+     57                __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+   \   0000000E   EB0C               LDI     R16, 188\r
+   \   00000010   E013               LDI     R17, 3\r
+   \   00000012   5001               SUBI    R16, 1\r
+   \   00000014   4010               SBCI    R17, 0\r
+   \   00000016   F7E9               BRNE    $-4\r
+   \   00000018   C000               RJMP    $+2\r
+     58          }\r
+   \   0000001A   9508               RET\r
+   \   0000001C                      REQUIRE _A_PORTA\r
+   \   0000001C                      REQUIRE _A_DDRA\r
+     59          \r
+     60          \r
+     61          /*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
+     62           *\r
+     63           *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
+     64           *  bus.\r
+     65           *\r
+     66           *  \param  pins    A bitmask of the buses to write to.\r
+     67           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     68          void OWI_WriteBit1(unsigned char pins){\r
+   \                     OWI_WriteBit1:\r
+     69                unsigned char intState;\r
+     70                \r
+     71                // Disable interrupts.\r
+     72                intState = __save_interrupt();\r
+   \   00000000   B71F               IN      R17, 0x3F\r
+     73                __disable_interrupt();\r
+   \   00000002   94F8               CLI\r
+     74                \r
+     75                // Drive bus low and delay.\r
+     76                OWI_PULL_BUS_LOW(pins);\r
+   \   00000004   B32A               IN      R18, 0x1A\r
+   \   00000006   2B20               OR      R18, R16\r
+   \   00000008   BB2A               OUT     0x1A, R18\r
+   \   0000000A   9500               COM     R16\r
+   \   0000000C   B32B               IN      R18, 0x1B\r
+   \   0000000E   2320               AND     R18, R16\r
+   \   00000010   BB2B               OUT     0x1B, R18\r
+     77                __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+   \   00000012   E02B               LDI     R18, 11\r
+   \   00000014   952A               DEC     R18\r
+   \   00000016   F7F1               BRNE    $-2\r
+   \   00000018   C000               RJMP    $+2\r
+     78                \r
+     79                // Release bus and delay.\r
+     80                OWI_RELEASE_BUS(pins);\r
+   \   0000001A   B32A               IN      R18, 0x1A\r
+   \   0000001C   2320               AND     R18, R16\r
+   \   0000001E   BB2A               OUT     0x1A, R18\r
+   \   00000020   B32B               IN      R18, 0x1B\r
+   \   00000022   2320               AND     R18, R16\r
+   \   00000024   BB2B               OUT     0x1B, R18\r
+     81                __delay_cycles(OWI_DELAY_B_STD_MODE);\r
+   \   00000026   EA06               LDI     R16, 166\r
+   \   00000028   950A               DEC     R16\r
+   \   0000002A   F7F1               BRNE    $-2\r
+   \   0000002C   0000               NOP\r
+     82                \r
+     83                // Restore interrupts.\r
+     84                __restore_interrupt(intState);\r
+   \   0000002E   BF1F               OUT     0x3F, R17\r
+     85          }\r
+   \   00000030   9508               RET\r
+   \   00000032                      REQUIRE _A_PORTA\r
+   \   00000032                      REQUIRE _A_DDRA\r
+     86          \r
+     87          /*! \brief  Write a '0' to the bus(es). (Software only driver)\r
+     88           *\r
+     89           *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
+     90           *  bus.\r
+     91           *\r
+     92           *  \param  pins    A bitmask of the buses to write to.\r
+     93           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     94          void OWI_WriteBit0(unsigned char pins)\r
+   \                     OWI_WriteBit0:\r
+     95          {\r
+     96                unsigned char intState;\r
+     97                \r
+     98                // Disable interrupts.\r
+     99                intState = __save_interrupt();\r
+   \   00000000   B71F               IN      R17, 0x3F\r
+    100                __disable_interrupt();\r
+   \   00000002   94F8               CLI\r
+    101                \r
+    102                // Drive bus low and delay.\r
+    103                OWI_PULL_BUS_LOW(pins);\r
+   \   00000004   B32A               IN      R18, 0x1A\r
+   \   00000006   2B20               OR      R18, R16\r
+   \   00000008   BB2A               OUT     0x1A, R18\r
+   \   0000000A   9500               COM     R16\r
+   \   0000000C   B32B               IN      R18, 0x1B\r
+   \   0000000E   2320               AND     R18, R16\r
+   \   00000010   BB2B               OUT     0x1B, R18\r
+    104                __delay_cycles(OWI_DELAY_C_STD_MODE);\r
+   \   00000012   E92B               LDI     R18, 155\r
+   \   00000014   952A               DEC     R18\r
+   \   00000016   F7F1               BRNE    $-2\r
+   \   00000018   C000               RJMP    $+2\r
+    105                \r
+    106                // Release bus and delay.\r
+    107                OWI_RELEASE_BUS(pins);\r
+   \   0000001A   B32A               IN      R18, 0x1A\r
+   \   0000001C   2320               AND     R18, R16\r
+   \   0000001E   BB2A               OUT     0x1A, R18\r
+   \   00000020   B32B               IN      R18, 0x1B\r
+   \   00000022   2320               AND     R18, R16\r
+   \   00000024   BB2B               OUT     0x1B, R18\r
+    108                __delay_cycles(OWI_DELAY_D_STD_MODE);\r
+   \   00000026   E106               LDI     R16, 22\r
+   \   00000028   950A               DEC     R16\r
+   \   0000002A   F7F1               BRNE    $-2\r
+   \   0000002C   0000               NOP\r
+    109                \r
+    110                // Restore interrupts.\r
+    111                __restore_interrupt(intState);\r
+   \   0000002E   BF1F               OUT     0x3F, R17\r
+    112          }\r
+   \   00000030   9508               RET\r
+   \   00000032                      REQUIRE _A_PORTA\r
+   \   00000032                      REQUIRE _A_DDRA\r
+    113          \r
+    114          /*! \brief  Read a bit from the bus(es). (Software only driver)\r
+    115           *\r
+    116           *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
+    117           *\r
+    118           *  \param  pins    A bitmask of the bus(es) to read from.\r
+    119           *\r
+    120           *  \return A bitmask of the buses where a '1' was read.\r
+    121           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    122          unsigned char OWI_ReadBit(unsigned char pins)\r
+   \                     OWI_ReadBit:\r
+    123          {\r
+    124                unsigned char intState;\r
+    125                unsigned char bitsRead;\r
+    126                \r
+    127                // Disable interrupts.\r
+    128                intState = __save_interrupt();\r
+   \   00000000   B72F               IN      R18, 0x3F\r
+    129                __disable_interrupt();\r
+   \   00000002   94F8               CLI\r
+    130                \r
+    131                // Drive bus low and delay.\r
+    132                OWI_PULL_BUS_LOW(pins);\r
+   \   00000004   B31A               IN      R17, 0x1A\r
+   \   00000006   2B10               OR      R17, R16\r
+   \   00000008   BB1A               OUT     0x1A, R17\r
+   \   0000000A   2F10               MOV     R17, R16\r
+   \   0000000C   9510               COM     R17\r
+   \   0000000E   B33B               IN      R19, 0x1B\r
+   \   00000010   2331               AND     R19, R17\r
+   \   00000012   BB3B               OUT     0x1B, R19\r
+    133                __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+   \   00000014   E03B               LDI     R19, 11\r
+   \   00000016   953A               DEC     R19\r
+   \   00000018   F7F1               BRNE    $-2\r
+   \   0000001A   C000               RJMP    $+2\r
+    134                \r
+    135                // Release bus and delay.\r
+    136                OWI_RELEASE_BUS(pins);\r
+   \   0000001C   B33A               IN      R19, 0x1A\r
+   \   0000001E   2331               AND     R19, R17\r
+   \   00000020   BB3A               OUT     0x1A, R19\r
+   \   00000022   B33B               IN      R19, 0x1B\r
+   \   00000024   2331               AND     R19, R17\r
+   \   00000026   BB3B               OUT     0x1B, R19\r
+    137                __delay_cycles(OWI_DELAY_E_STD_MODE);\r
+   \   00000028   E113               LDI     R17, 19\r
+   \   0000002A   951A               DEC     R17\r
+   \   0000002C   F7F1               BRNE    $-2\r
+   \   0000002E   C000               RJMP    $+2\r
+    138                \r
+    139                // Sample bus and delay.\r
+    140                bitsRead = OWI_PIN & pins;\r
+   \   00000030   B319               IN      R17, 0x19\r
+   \   00000032   2310               AND     R17, R16\r
+    141                __delay_cycles(OWI_DELAY_F_STD_MODE);\r
+   \   00000034   E80E               LDI     R16, 142\r
+   \   00000036   950A               DEC     R16\r
+   \   00000038   F7F1               BRNE    $-2\r
+   \   0000003A   0000               NOP\r
+    142                \r
+    143                // Restore interrupts.\r
+    144                __restore_interrupt(intState);\r
+   \   0000003C   BF2F               OUT     0x3F, R18\r
+    145                \r
+    146                return bitsRead;\r
+   \   0000003E   2F01               MOV     R16, R17\r
+   \   00000040   9508               RET\r
+   \   00000042                      REQUIRE _A_PORTA\r
+   \   00000042                      REQUIRE _A_DDRA\r
+   \   00000042                      REQUIRE _A_PINA\r
+    147          }\r
+    148          \r
+    149          \r
+    150          /*! \brief  Send a Reset signal and listen for Presence signal. (software\r
+    151           *  only driver)\r
+    152           *\r
+    153           *  Generates the waveform for transmission of a Reset pulse on the \r
+    154           *  1-Wire(R) bus and listens for presence signals.\r
+    155           *\r
+    156           *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
+    157           *\r
+    158           *  \return A bitmask of the buses where a presence signal was detected.\r
+    159           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    160          unsigned char OWI_DetectPresence(unsigned char pins)\r
+   \                     OWI_DetectPresence:\r
+    161          {\r
+    162                unsigned char intState;\r
+    163                unsigned char presenceDetected;\r
+    164                \r
+    165                // Disable interrupts.\r
+    166                intState = __save_interrupt();\r
+   \   00000000   B72F               IN      R18, 0x3F\r
+    167                __disable_interrupt();\r
+   \   00000002   94F8               CLI\r
+    168                \r
+    169                // Drive bus low and delay.\r
+    170                OWI_PULL_BUS_LOW(pins);\r
+   \   00000004   B31A               IN      R17, 0x1A\r
+   \   00000006   2B10               OR      R17, R16\r
+   \   00000008   BB1A               OUT     0x1A, R17\r
+   \   0000000A   2F10               MOV     R17, R16\r
+   \   0000000C   9510               COM     R17\r
+   \   0000000E   B33B               IN      R19, 0x1B\r
+   \   00000010   2331               AND     R19, R17\r
+   \   00000012   BB3B               OUT     0x1B, R19\r
+    171                __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+   \   00000014   EB4C               LDI     R20, 188\r
+   \   00000016   E053               LDI     R21, 3\r
+   \   00000018   5041               SUBI    R20, 1\r
+   \   0000001A   4050               SBCI    R21, 0\r
+   \   0000001C   F7E9               BRNE    $-4\r
+   \   0000001E   C000               RJMP    $+2\r
+    172                \r
+    173                // Release bus and delay.\r
+    174                OWI_RELEASE_BUS(pins);\r
+   \   00000020   B33A               IN      R19, 0x1A\r
+   \   00000022   2331               AND     R19, R17\r
+   \   00000024   BB3A               OUT     0x1A, R19\r
+   \   00000026   B33B               IN      R19, 0x1B\r
+   \   00000028   2331               AND     R19, R17\r
+   \   0000002A   BB3B               OUT     0x1B, R19\r
+    175                __delay_cycles(OWI_DELAY_I_STD_MODE);\r
+   \   0000002C   EB16               LDI     R17, 182\r
+   \   0000002E   951A               DEC     R17\r
+   \   00000030   F7F1               BRNE    $-2\r
+   \   00000032   0000               NOP\r
+    176                \r
+    177                // Sample bus to detect presence signal and delay.\r
+    178                presenceDetected = ((~OWI_PIN) & pins);\r
+   \   00000034   B319               IN      R17, 0x19\r
+   \   00000036   9510               COM     R17\r
+   \   00000038   2301               AND     R16, R17\r
+    179                __delay_cycles(OWI_DELAY_J_STD_MODE);\r
+   \   0000003A   E340               LDI     R20, 48\r
+   \   0000003C   E053               LDI     R21, 3\r
+   \   0000003E   5041               SUBI    R20, 1\r
+   \   00000040   4050               SBCI    R21, 0\r
+   \   00000042   F7E9               BRNE    $-4\r
+   \   00000044   C000               RJMP    $+2\r
+    180                \r
+    181                // Restore interrupts.\r
+    182                __restore_interrupt(intState);\r
+   \   00000046   BF2F               OUT     0x3F, R18\r
+    183                \r
+    184                return presenceDetected;\r
+   \   00000048   9508               RET\r
+   \   0000004A                      REQUIRE _A_PORTA\r
+   \   0000004A                      REQUIRE _A_DDRA\r
+   \   0000004A                      REQUIRE _A_PINA\r
+    185          }\r
+    186          \r
+    187          \r
+    188          /*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
+    189           *  \r
+    190           *  This function automates the task of sending a complete byte\r
+    191           *  of data on the 1-Wire bus(es).\r
+    192           *\r
+    193           *  \param  data    The data to send on the bus(es).\r
+    194           *  \r
+    195           *  \param  pins    A bitmask of the buses to send the data to.\r
+    196           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    197          void OWI_SendByte(unsigned char data, unsigned char pins)\r
+   \                     OWI_SendByte:\r
+    198          {\r
+   \   00000000   93AA               ST      -Y, R26\r
+   \   00000002   939A               ST      -Y, R25\r
+   \   00000004   938A               ST      -Y, R24\r
+   \   00000006   2FA0               MOV     R26, R16\r
+   \   00000008   2F91               MOV     R25, R17\r
+    199                unsigned char temp;\r
+    200                unsigned char i;\r
+    201                \r
+    202                // Do once for each bit\r
+    203                for (i = 0; i < 8; i++) {\r
+   \   0000000A   E088               LDI     R24, 8\r
+    204                        // Determine if LSB is '0' or '1' and transmit corresponding\r
+    205                        // waveform on the bus.\r
+    206                        temp = data & 0x01;\r
+    207                        \r
+    208                        if (temp) {\r
+   \                     ??OWI_SendByte_0:\r
+   \   0000000C   FBA0               BST     R26, 0\r
+   \   0000000E   2F09               MOV     R16, R25\r
+   \   00000010   F416               BRTC    ??OWI_SendByte_1\r
+    209                                OWI_WriteBit1(pins);\r
+   \   00000012   ....               RCALL   OWI_WriteBit1\r
+   \   00000014   C001               RJMP    ??OWI_SendByte_2\r
+    210                        } else {\r
+    211                                OWI_WriteBit0(pins);\r
+   \                     ??OWI_SendByte_1:\r
+   \   00000016   ....               RCALL   OWI_WriteBit0\r
+    212                        }\r
+    213                \r
+    214                        data >>= 1;  // Right shift the data to get next bit.\r
+   \                     ??OWI_SendByte_2:\r
+   \   00000018   95A6               LSR     R26\r
+    215                }\r
+   \   0000001A   958A               DEC     R24\r
+   \   0000001C   F7B9               BRNE    ??OWI_SendByte_0\r
+    216          }\r
+   \   0000001E   9189               LD      R24, Y+\r
+   \   00000020   9199               LD      R25, Y+\r
+   \   00000022   91A9               LD      R26, Y+\r
+   \   00000024   9508               RET\r
+    217          \r
+    218          \r
+    219          /*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
+    220           *\r
+    221           *  This function automates the task of receiving a complete byte \r
+    222           *  of data from the 1-Wire bus.\r
+    223           *\r
+    224           *  \param  pin     A bitmask of the bus to read from.\r
+    225           *  \r
+    226           *  \return     The byte read from the bus.\r
+    227           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    228          unsigned char OWI_ReceiveByte(unsigned char pin)\r
+   \                     OWI_ReceiveByte:\r
+    229          {\r
+   \   00000000   93AA               ST      -Y, R26\r
+   \   00000002   939A               ST      -Y, R25\r
+   \   00000004   938A               ST      -Y, R24\r
+   \   00000006   2FA0               MOV     R26, R16\r
+    230                unsigned char data;\r
+    231                unsigned char i;\r
+    232                \r
+    233                // Clear the temporary input variable.\r
+    234                data = 0x00;\r
+   \   00000008   E090               LDI     R25, 0\r
+    235                \r
+    236                // Do once for each bit\r
+    237                for (i = 0; i < 8; i++) {\r
+   \   0000000A   E088               LDI     R24, 8\r
+    238                        // Shift temporary input variable right.\r
+    239                        data >>= 1;\r
+   \                     ??OWI_ReceiveByte_0:\r
+   \   0000000C   9596               LSR     R25\r
+    240                        \r
+    241                        // Set the MSB if a '1' value is read from the bus.\r
+    242                        // Leave as it is ('0') else.\r
+    243                        if (OWI_ReadBit(pin)) {\r
+   \   0000000E   2F0A               MOV     R16, R26\r
+   \   00000010   ....               RCALL   OWI_ReadBit\r
+   \   00000012   2300               TST     R16\r
+   \   00000014   F009               BREQ    ??OWI_ReceiveByte_1\r
+    244                                data |= 0x80;\r
+   \   00000016   6890               ORI     R25, 0x80\r
+    245                        }\r
+    246                }\r
+   \                     ??OWI_ReceiveByte_1:\r
+   \   00000018   958A               DEC     R24\r
+   \   0000001A   F7C1               BRNE    ??OWI_ReceiveByte_0\r
+    247                \r
+    248                return data;\r
+   \   0000001C   2F09               MOV     R16, R25\r
+   \   0000001E   9189               LD      R24, Y+\r
+   \   00000020   9199               LD      R25, Y+\r
+   \   00000022   91A9               LD      R26, Y+\r
+   \   00000024   9508               RET\r
+    249          }\r
+    250          \r
+    251          \r
+    252          /*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
+    253           *\r
+    254           *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
+    255           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    256          void OWI_SkipRom(unsigned char pins)\r
+   \                     OWI_SkipRom:\r
+    257          {\r
+    258                // Send the SKIP ROM command on the bus.\r
+    259                OWI_SendByte(OWI_ROM_SKIP, pins);\r
+   \   00000000   2F10               MOV     R17, R16\r
+   \   00000002   EC0C               LDI     R16, 204\r
+   \   00000004   ....               RJMP    OWI_SendByte\r
+    260          }\r
+    261          \r
+    262          \r
+    263          /*! \brief  Sends the READ ROM command and reads back the ROM id.\r
+    264           *\r
+    265           *  \param  romValue    A pointer where the id will be placed.\r
+    266           *\r
+    267           *  \param  pin     A bitmask of the bus to read from.\r
+    268           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    269          void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
+   \                     OWI_ReadRom:\r
+    270          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   939A               ST      -Y, R25\r
+   \   00000006   938A               ST      -Y, R24\r
+   \   00000008   01D8               MOVW    R27:R26, R17:R16\r
+   \   0000000A   2F92               MOV     R25, R18\r
+    271                unsigned char bytesLeft = 8;\r
+    272                \r
+    273                // Send the READ ROM command on the bus.\r
+    274                OWI_SendByte(OWI_ROM_READ, pin);\r
+   \   0000000C   2F12               MOV     R17, R18\r
+   \   0000000E   E303               LDI     R16, 51\r
+   \   00000010   ....               RCALL   OWI_SendByte\r
+   \   00000012   E088               LDI     R24, 8\r
+    275                \r
+    276                // Do 8 times.\r
+    277                while (bytesLeft > 0) {\r
+    278                        // Place the received data in memory.\r
+    279                        *romValue++ = OWI_ReceiveByte(pin);\r
+   \                     ??OWI_ReadRom_0:\r
+   \   00000014   2F09               MOV     R16, R25\r
+   \   00000016   ....               RCALL   OWI_ReceiveByte\r
+   \   00000018   930D               ST      X+, R16\r
+    280                        bytesLeft--;\r
+   \   0000001A   958A               DEC     R24\r
+    281                }\r
+   \   0000001C   F7D9               BRNE    ??OWI_ReadRom_0\r
+    282          }\r
+   \   0000001E                      REQUIRE ?Subroutine0\r
+   \   0000001E                      ;               // Fall through to label ?Subroutine0\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+   \                     ?Subroutine0:\r
+   \   00000000   9189               LD      R24, Y+\r
+   \   00000002   9199               LD      R25, Y+\r
+   \   00000004   91A9               LD      R26, Y+\r
+   \   00000006   91B9               LD      R27, Y+\r
+   \   00000008   9508               RET\r
+    283          \r
+    284          \r
+    285          /*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
+    286           *\r
+    287           *  \param  romValue    A pointer to the ID to match against.\r
+    288           *\r
+    289           *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
+    290           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    291          void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
+   \                     OWI_MatchRom:\r
+    292          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   939A               ST      -Y, R25\r
+   \   00000006   938A               ST      -Y, R24\r
+   \   00000008   01D8               MOVW    R27:R26, R17:R16\r
+   \   0000000A   2F92               MOV     R25, R18\r
+    293                unsigned char bytesLeft = 8;   \r
+    294                \r
+    295                // Send the MATCH ROM command.\r
+    296                OWI_SendByte(OWI_ROM_MATCH, pins);\r
+   \   0000000C   2F12               MOV     R17, R18\r
+   \   0000000E   E505               LDI     R16, 85\r
+   \   00000010   ....               RCALL   OWI_SendByte\r
+   \   00000012   E088               LDI     R24, 8\r
+    297                \r
+    298                // Do once for each byte.\r
+    299                while (bytesLeft > 0) {\r
+    300                        // Transmit 1 byte of the ID to match.\r
+    301                        OWI_SendByte(*romValue++, pins);\r
+   \                     ??OWI_MatchRom_0:\r
+   \   00000014   2F19               MOV     R17, R25\r
+   \   00000016   910D               LD      R16, X+\r
+   \   00000018   ....               RCALL   OWI_SendByte\r
+    302                        bytesLeft--;\r
+   \   0000001A   958A               DEC     R24\r
+    303                }\r
+   \   0000001C   F7D9               BRNE    ??OWI_MatchRom_0\r
+    304          }\r
+   \   0000001E   ....               RJMP    ?Subroutine0\r
+    305          \r
+    306          \r
+    307          /*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
+    308           *          1-Wire(R) bus.\r
+    309           *\r
+    310           *  \param  bitPattern      A pointer to an 8 byte char array where the \r
+    311           *                          discovered identifier will be placed. When \r
+    312           *                          searching for several slaves, a copy of the \r
+    313           *                          last found identifier should be supplied in \r
+    314           *                          the array, or the search will fail.\r
+    315           *\r
+    316           *  \param  lastDeviation   The bit position where the algorithm made a \r
+    317           *                          choice the last time it was run. This argument \r
+    318           *                          should be 0 when a search is initiated. Supplying \r
+    319           *                          the return argument of this function when calling \r
+    320           *                          repeatedly will go through the complete slave \r
+    321           *                          search.\r
+    322           *\r
+    323           *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
+    324           *\r
+    325           *  \return The last bit position where there was a discrepancy between slave\r
+    326           *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
+    327           *  if an error was detected (e.g. a device was connected to the bus during the\r
+    328           *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
+    329           *  discovered.\r
+    330           *\r
+    331           *  \note   See main.c for an example of how to utilize this function.\r
+    332           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    333          unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+   \                     OWI_SearchRom:\r
+    334                                                        unsigned char lastDeviation, unsigned char pin)\r
+    335          {\r
+   \   00000000   927A               ST      -Y, R7\r
+   \   00000002   926A               ST      -Y, R6\r
+   \   00000004   925A               ST      -Y, R5\r
+   \   00000006   924A               ST      -Y, R4\r
+   \   00000008   93BA               ST      -Y, R27\r
+   \   0000000A   93AA               ST      -Y, R26\r
+   \   0000000C   939A               ST      -Y, R25\r
+   \   0000000E   938A               ST      -Y, R24\r
+   \   00000010                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000010                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000010                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000010                      REQUIRE ?Register_R7_is_cg_reg\r
+   \   00000010   01D8               MOVW    R27:R26, R17:R16\r
+   \   00000012   2E62               MOV     R6, R18\r
+   \   00000014   2E43               MOV     R4, R19\r
+    336                unsigned char currentBit = 1;\r
+   \   00000016   E081               LDI     R24, 1\r
+    337                unsigned char newDeviation = 0;\r
+   \   00000018   2455               CLR     R5\r
+    338                unsigned char bitMask = 0x01;\r
+   \   0000001A   E091               LDI     R25, 1\r
+    339                unsigned char bitA;\r
+    340                unsigned char bitB;\r
+    341                \r
+    342                // Send SEARCH ROM command on the bus.\r
+    343                OWI_SendByte(OWI_ROM_SEARCH, pin);\r
+   \   0000001C   2F13               MOV     R17, R19\r
+   \   0000001E   EF00               LDI     R16, 240\r
+   \   00000020   ....               RCALL   OWI_SendByte\r
+    344                \r
+    345                // Walk through all 64 bits.\r
+    346                while (currentBit <= 64) {\r
+    347                        // Read bit from bus twice.\r
+    348                        bitA = OWI_ReadBit(pin);\r
+   \                     ??OWI_SearchRom_0:\r
+   \   00000022   2D04               MOV     R16, R4\r
+   \   00000024   ....               RCALL   OWI_ReadBit\r
+   \   00000026   2E70               MOV     R7, R16\r
+    349                        bitB = OWI_ReadBit(pin);\r
+   \   00000028   2D04               MOV     R16, R4\r
+   \   0000002A   ....               RCALL   OWI_ReadBit\r
+    350                        \r
+    351                        if (bitA && bitB) {\r
+   \   0000002C   2077               TST     R7\r
+   \   0000002E   F021               BREQ    ??OWI_SearchRom_1\r
+   \   00000030   2300               TST     R16\r
+   \   00000032   F011               BREQ    ??OWI_SearchRom_1\r
+    352                                // Both bits 1 (Error).\r
+    353                                newDeviation = OWI_ROM_SEARCH_FAILED;\r
+    354                                return newDeviation;\r
+   \   00000034   EF0F               LDI     R16, 255\r
+   \   00000036   C02C               RJMP    ??OWI_SearchRom_2\r
+    355                        } else if (bitA ^ bitB) {\r
+   \                     ??OWI_SearchRom_1:\r
+   \   00000038   2507               EOR     R16, R7\r
+   \   0000003A   F069               BREQ    ??OWI_SearchRom_3\r
+    356                                // Bits A and B are different. All devices have the same bit here.\r
+    357                                // Set the bit in bitPattern to this value.\r
+    358                                if (bitA) {\r
+   \   0000003C   2077               TST     R7\r
+   \   0000003E   F029               BREQ    ??OWI_SearchRom_4\r
+    359                                        (*bitPattern) |= bitMask;\r
+   \                     ??OWI_SearchRom_5:\r
+   \   00000040   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000042   8100               LD      R16, Z\r
+   \   00000044   2B09               OR      R16, R25\r
+   \   00000046   8300               ST      Z, R16\r
+   \   00000048   C014               RJMP    ??OWI_SearchRom_6\r
+    360                                } else {\r
+    361                                        (*bitPattern) &= ~bitMask;\r
+   \                     ??OWI_SearchRom_4:\r
+   \   0000004A   2F09               MOV     R16, R25\r
+   \   0000004C   9500               COM     R16\r
+   \   0000004E   911C               LD      R17, X\r
+   \   00000050   2310               AND     R17, R16\r
+   \   00000052   931C               ST      X, R17\r
+   \   00000054   C00E               RJMP    ??OWI_SearchRom_6\r
+    362                                }\r
+    363                        } else {\r
+    364                                // If this is where a choice was made the last time,\r
+    365                                // a '1' bit is selected this time.\r
+    366                                if (currentBit == lastDeviation) {\r
+   \                     ??OWI_SearchRom_3:\r
+   \   00000056   1586               CP      R24, R6\r
+   \   00000058   F399               BREQ    ??OWI_SearchRom_5\r
+    367                                        (*bitPattern) |= bitMask;\r
+    368                                }\r
+    369                                \r
+    370                                // For the rest of the id, '0' bits are selected when\r
+    371                                // discrepancies occur.\r
+    372                                else if (currentBit > lastDeviation) {\r
+   \   0000005A   1668               CP      R6, R24\r
+   \   0000005C   F430               BRCC    ??OWI_SearchRom_7\r
+    373                                        (*bitPattern) &= ~bitMask;\r
+   \   0000005E   2F09               MOV     R16, R25\r
+   \   00000060   9500               COM     R16\r
+   \   00000062   911C               LD      R17, X\r
+   \   00000064   2310               AND     R17, R16\r
+   \   00000066   931C               ST      X, R17\r
+    374                                        newDeviation = currentBit;\r
+   \   00000068   C003               RJMP    ??OWI_SearchRom_8\r
+    375                                }\r
+    376                                \r
+    377                                // If current bit in bit pattern = 0, then this is\r
+    378                                // out new deviation.\r
+    379                                else if ( !(*bitPattern & bitMask)) {\r
+   \                     ??OWI_SearchRom_7:\r
+   \   0000006A   910C               LD      R16, X\r
+   \   0000006C   2309               AND     R16, R25\r
+   \   0000006E   F409               BRNE    ??OWI_SearchRom_6\r
+    380                                        newDeviation = currentBit;\r
+   \                     ??OWI_SearchRom_8:\r
+   \   00000070   2E58               MOV     R5, R24\r
+    381                                }\r
+    382                                \r
+    383                        // IF the bit is already 1, do nothing.\r
+    384                                else {\r
+    385                                }\r
+    386                        }\r
+    387                        \r
+    388                        // Send the selected bit to the bus.\r
+    389                        if ((*bitPattern) & bitMask) {\r
+   \                     ??OWI_SearchRom_6:\r
+   \   00000072   910C               LD      R16, X\r
+   \   00000074   2309               AND     R16, R25\r
+   \   00000076   2D04               MOV     R16, R4\r
+   \   00000078   F011               BREQ    ??OWI_SearchRom_9\r
+    390                                OWI_WriteBit1(pin);\r
+   \   0000007A   ....               RCALL   OWI_WriteBit1\r
+   \   0000007C   C001               RJMP    ??OWI_SearchRom_10\r
+    391                        } else {\r
+    392                                OWI_WriteBit0(pin);\r
+   \                     ??OWI_SearchRom_9:\r
+   \   0000007E   ....               RCALL   OWI_WriteBit0\r
+    393                        }\r
+    394                        \r
+    395                        // Increment current bit.    \r
+    396                        currentBit++;\r
+   \                     ??OWI_SearchRom_10:\r
+   \   00000080   9583               INC     R24\r
+    397                        \r
+    398                        // Adjust bitMask and bitPattern pointer.    \r
+    399                        bitMask <<= 1;\r
+   \   00000082   0F99               LSL     R25\r
+    400                        if (!bitMask) {\r
+   \   00000084   F411               BRNE    ??OWI_SearchRom_11\r
+    401                                bitMask = 0x01;\r
+   \   00000086   E091               LDI     R25, 1\r
+    402                                bitPattern++;\r
+   \   00000088   9611               ADIW    R27:R26, 1\r
+    403                        }\r
+    404                }\r
+   \                     ??OWI_SearchRom_11:\r
+   \   0000008A   3481               CPI     R24, 65\r
+   \   0000008C   F250               BRCS    ??OWI_SearchRom_0\r
+    405                \r
+    406                return newDeviation;\r
+   \   0000008E   2D05               MOV     R16, R5\r
+   \                     ??OWI_SearchRom_2:\r
+   \   00000090   9189               LD      R24, Y+\r
+   \   00000092   9199               LD      R25, Y+\r
+   \   00000094   91A9               LD      R26, Y+\r
+   \   00000096   91B9               LD      R27, Y+\r
+   \   00000098   9049               LD      R4, Y+\r
+   \   0000009A   9059               LD      R5, Y+\r
+   \   0000009C   9069               LD      R6, Y+\r
+   \   0000009E   9079               LD      R7, Y+\r
+   \   000000A0   9508               RET\r
+    407          }\r
+    408          \r
+    409          \r
+    410          /* Functions for handling CRC */\r
+    411          /*! \brief  Compute the CRC8 value of a data set.\r
+    412           *\r
+    413           *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
+    414           *  as inital value for the CRC.\r
+    415           *\r
+    416           *  \param  inData  One byte of data to compute CRC from.\r
+    417           *\r
+    418           *  \param  seed    The starting value of the CRC.\r
+    419           *\r
+    420           *  \return The CRC8 of inData with seed as initial value.\r
+    421           *\r
+    422           *  \note   Setting seed to 0 computes the crc8 of the inData.\r
+    423           *\r
+    424           *  \note   Constantly passing the return value of this function \r
+    425           *          As the seed argument computes the CRC8 value of a\r
+    426           *          longer string of data.\r
+    427           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    428          unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
+   \                     OWI_ComputeCRC8:\r
+    429          {\r
+    430                unsigned char bitsLeft;\r
+    431                unsigned char temp;\r
+    432                \r
+    433                for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+   \   00000000   E038               LDI     R19, 8\r
+    434                        temp = ((seed ^ inData) & 0x01);\r
+    435                        \r
+    436                        if (temp == 0) {\r
+   \                     ??OWI_ComputeCRC8_0:\r
+   \   00000002   2F21               MOV     R18, R17\r
+   \   00000004   7021               ANDI    R18, 0x01\r
+   \   00000006   2F40               MOV     R20, R16\r
+   \   00000008   7041               ANDI    R20, 0x01\r
+   \   0000000A   2742               EOR     R20, R18\r
+   \   0000000C   F411               BRNE    ??OWI_ComputeCRC8_1\r
+    437                        seed >>= 1;\r
+   \   0000000E   9516               LSR     R17\r
+   \   00000010   C004               RJMP    ??OWI_ComputeCRC8_2\r
+    438                        } else {\r
+    439                                seed ^= 0x18;\r
+    440                                seed >>= 1;\r
+    441                                seed |= 0x80;\r
+   \                     ??OWI_ComputeCRC8_1:\r
+   \   00000012   E128               LDI     R18, 24\r
+   \   00000014   2712               EOR     R17, R18\r
+   \   00000016   9516               LSR     R17\r
+   \   00000018   6810               ORI     R17, 0x80\r
+    442                        }\r
+    443                        \r
+    444                        inData >>= 1;\r
+   \                     ??OWI_ComputeCRC8_2:\r
+   \   0000001A   9506               LSR     R16\r
+    445                }\r
+   \   0000001C   953A               DEC     R19\r
+   \   0000001E   F789               BRNE    ??OWI_ComputeCRC8_0\r
+    446                return seed;    \r
+   \   00000020   2F01               MOV     R16, R17\r
+   \   00000022   9508               RET\r
+    447          }\r
+    448          \r
+    449          \r
+    450          /*! \brief  Compute the CRC16 value of a data set.\r
+    451           *\r
+    452           *  This function will compute the CRC16 of inData using seed\r
+    453           *  as inital value for the CRC.\r
+    454           *\r
+    455           *  \param  inData  One byte of data to compute CRC from.\r
+    456           *\r
+    457           *  \param  seed    The starting value of the CRC.\r
+    458           *\r
+    459           *  \return The CRC16 of inData with seed as initial value.\r
+    460           *\r
+    461           *  \note   Setting seed to 0 computes the crc16 of the inData.\r
+    462           *\r
+    463           *  \note   Constantly passing the return value of this function \r
+    464           *          As the seed argument computes the CRC16 value of a\r
+    465           *          longer string of data.\r
+    466           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    467          unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
+   \                     OWI_ComputeCRC16:\r
+    468          {\r
+    469                unsigned char bitsLeft;\r
+    470                unsigned char temp;\r
+    471                \r
+    472                for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+   \   00000000   E018               LDI     R17, 8\r
+    473                        temp = ((seed ^ inData) & 0x01);\r
+    474                        \r
+    475                        if (temp == 0) {\r
+   \                     ??OWI_ComputeCRC16_0:\r
+   \   00000002   2F42               MOV     R20, R18\r
+   \   00000004   7041               ANDI    R20, 0x01\r
+   \   00000006   2F50               MOV     R21, R16\r
+   \   00000008   7051               ANDI    R21, 0x01\r
+   \   0000000A   2754               EOR     R21, R20\r
+   \   0000000C   F419               BRNE    ??OWI_ComputeCRC16_1\r
+    476                                seed >>= 1;\r
+   \   0000000E   9536               LSR     R19\r
+   \   00000010   9527               ROR     R18\r
+   \   00000012   C008               RJMP    ??OWI_ComputeCRC16_2\r
+    477                  } else {\r
+    478                                seed ^= 0x4002;\r
+    479                                seed >>= 1;\r
+    480                                seed |= 0x8000;\r
+   \                     ??OWI_ComputeCRC16_1:\r
+   \   00000014   E042               LDI     R20, 2\r
+   \   00000016   E450               LDI     R21, 64\r
+   \   00000018   2742               EOR     R20, R18\r
+   \   0000001A   2753               EOR     R21, R19\r
+   \   0000001C   019A               MOVW    R19:R18, R21:R20\r
+   \   0000001E   9536               LSR     R19\r
+   \   00000020   9527               ROR     R18\r
+   \   00000022   6830               ORI     R19, 0x80\r
+    481                        }\r
+    482          \r
+    483                        inData >>= 1;\r
+   \                     ??OWI_ComputeCRC16_2:\r
+   \   00000024   9506               LSR     R16\r
+    484                }\r
+   \   00000026   951A               DEC     R17\r
+   \   00000028   F761               BRNE    ??OWI_ComputeCRC16_0\r
+    485                \r
+    486                return seed;    \r
+   \   0000002A   0189               MOVW    R17:R16, R19:R18\r
+   \   0000002C   9508               RET\r
+    487          }\r
+    488          \r
+    489          \r
+    490          /*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
+    491           *  \r
+    492           *  This function computes the CRC8 value of the first 56 bits of a\r
+    493           *  64 bit identifier. It then checks the calculated value against the\r
+    494           *  CRC value stored in ROM.\r
+    495           *\r
+    496           *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
+    497           *\r
+    498           *  \retval OWI_CRC_OK      The CRC's matched.\r
+    499           *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
+    500           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    501          unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
+   \                     OWI_CheckRomCRC:\r
+    502          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   938A               ST      -Y, R24\r
+   \   00000006   01D8               MOVW    R27:R26, R17:R16\r
+    503                unsigned char i;\r
+    504                unsigned char crc8 = 0;\r
+   \   00000008   E010               LDI     R17, 0\r
+    505                \r
+    506                for (i = 0; i < 7; i++) {\r
+   \   0000000A   E087               LDI     R24, 7\r
+    507                        crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
+   \                     ??OWI_CheckRomCRC_0:\r
+   \   0000000C   910D               LD      R16, X+\r
+   \   0000000E   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000010   2F10               MOV     R17, R16\r
+    508                        romValue++;\r
+    509                }\r
+   \   00000012   958A               DEC     R24\r
+   \   00000014   F7D9               BRNE    ??OWI_CheckRomCRC_0\r
+    510                \r
+    511                if (crc8 == (*romValue)) {\r
+   \   00000016   910C               LD      R16, X\r
+   \   00000018   1710               CP      R17, R16\r
+   \   0000001A   F411               BRNE    ??OWI_CheckRomCRC_1\r
+    512                        return OWI_CRC_OK;\r
+   \   0000001C   E000               LDI     R16, 0\r
+   \   0000001E   C001               RJMP    ??OWI_CheckRomCRC_2\r
+    513                }\r
+    514                \r
+    515                return OWI_CRC_ERROR;\r
+   \                     ??OWI_CheckRomCRC_1:\r
+   \   00000020   E001               LDI     R16, 1\r
+   \                     ??OWI_CheckRomCRC_2:\r
+   \   00000022   9189               LD      R24, Y+\r
+   \   00000024   91A9               LD      R26, Y+\r
+   \   00000026   91B9               LD      R27, Y+\r
+   \   00000028   9508               RET\r
+    516          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function             CSTACK RSTACK\r
+     --------             ------ ------\r
+     OWI_CheckRomCRC          3      2\r
+       -> OWI_ComputeCRC8     3      2\r
+     OWI_ComputeCRC16         0      2\r
+     OWI_ComputeCRC8          0      2\r
+     OWI_DetectPresence       0      2\r
+     OWI_Init                 0      2\r
+     OWI_MatchRom             4      2\r
+       -> OWI_SendByte        4      2\r
+       -> OWI_SendByte        4      2\r
+     OWI_ReadBit              0      2\r
+     OWI_ReadRom              4      2\r
+       -> OWI_SendByte        4      2\r
+       -> OWI_ReceiveByte     4      2\r
+     OWI_ReceiveByte          3      2\r
+       -> OWI_ReadBit         3      2\r
+     OWI_SearchRom            8      2\r
+       -> OWI_SendByte        8      2\r
+       -> OWI_ReadBit         8      2\r
+       -> OWI_ReadBit         8      2\r
+       -> OWI_WriteBit1       8      2\r
+       -> OWI_WriteBit0       8      2\r
+     OWI_SendByte             3      2\r
+       -> OWI_WriteBit1       3      2\r
+       -> OWI_WriteBit0       3      2\r
+     OWI_SkipRom              0      2\r
+       -> OWI_SendByte        0      2\r
+     OWI_WriteBit0            0      2\r
+     OWI_WriteBit1            0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label     Bytes\r
+     --------------     -----\r
+     _A_PORTA              1\r
+     _A_DDRA               1\r
+     _A_PINA               1\r
+     OWI_Init             28\r
+     OWI_WriteBit1        50\r
+     OWI_WriteBit0        50\r
+     OWI_ReadBit          66\r
+     OWI_DetectPresence   74\r
+     OWI_SendByte         38\r
+     OWI_ReceiveByte      38\r
+     OWI_SkipRom           6\r
+     OWI_ReadRom          30\r
+     ?Subroutine0         10\r
+     OWI_MatchRom         32\r
+     OWI_SearchRom       162\r
+     OWI_ComputeCRC8      36\r
+     OWI_ComputeCRC16     46\r
+     OWI_CheckRomCRC      42\r
+\r
\r
+   3 bytes in segment ABSOLUTE\r
+ 708 bytes in segment CODE\r
\r
+ 708 bytes of CODE memory\r
+   0 bytes of DATA memory (+ 3 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/OWI.s90 b/BaseTinyFirmware/IAR/Release/List/OWI.s90
new file mode 100644 (file)
index 0000000..5bfb792
--- /dev/null
@@ -0,0 +1,1068 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:49:36 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\OWI.c          /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\OWI.c          /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\O /\r
+//                             WI.s90                                         /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME OWI\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?Register_R7_is_cg_reg\r
+\r
+        PUBLIC OWI_CheckRomCRC\r
+        PUBLIC OWI_ComputeCRC16\r
+        PUBLIC OWI_ComputeCRC8\r
+        PUBLIC OWI_DetectPresence\r
+        PUBLIC OWI_Init\r
+        PUBLIC OWI_MatchRom\r
+        PUBLIC OWI_ReadBit\r
+        PUBLIC OWI_ReadRom\r
+        PUBLIC OWI_ReceiveByte\r
+        PUBLIC OWI_SearchRom\r
+        PUBLIC OWI_SendByte\r
+        PUBLIC OWI_SkipRom\r
+        PUBLIC OWI_WriteBit0\r
+        PUBLIC OWI_WriteBit1\r
+        PUBWEAK _A_DDRA\r
+        PUBWEAK _A_PINA\r
+        PUBWEAK _A_PORTA\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\OWI.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file ********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for 1-Wire(R) bus communication\r
+//    6  *\r
+//    7  *      High level functions for transmission of full bytes on the 1-Wire(R)\r
+//    8  *      bus and implementations of ROM commands.\n\r
+//    9  *      Polled software only implementation of the basic bit-level signalling\r
+//   10  *      in the 1-Wire(R) protocol.\n\r
+//   11  *      Includes functions for computing and checking CRC8 & 16 values of data\r
+//   12  *      sets, and of 64 bit ROM identifiers.\r
+//   13  *      Supported devices:  All AVRs.\r
+//   14  *\r
+//   15  * \par Application Note:\r
+//   16  *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+//   17  *      AVR463: Charging NiMH Batteries with BC100\n\r
+//   18  *      One-wire protocol based on AVR318 - Dallas 1-Wire(R) master.\r
+//   19  *\r
+//   20  * \par Documentation:\r
+//   21  *      For comprehensive code documentation, supported compilers, compiler\r
+//   22  *      settings and supported devices see readme.html\r
+//   23  *\r
+//   24  * \author\r
+//   25  *      Atmel Corporation: http://www.atmel.com \n\r
+//   26  *      Support email: avr@atmel.com \n\r
+//   27  *      Original author: \n\r
+//   28  *\r
+//   29  * $Name$\r
+//   30  * $Revision: 2299 $\r
+//   31  * $RCSfile$\r
+//   32  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $\r
+//   33  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   34 ****************************************************************************/\r
+//   35 \r
+//   36 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03bH\r
+// <unnamed> volatile __io _A_PORTA\r
+_A_PORTA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,03aH\r
+// <unnamed> volatile __io _A_DDRA\r
+_A_DDRA:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,039H\r
+// <unnamed> volatile __io _A_PINA\r
+_A_PINA:\r
+        DS 1\r
+//   37 #include <inavr.h>\r
+//   38 \r
+//   39 #include "OWI.h"\r
+//   40 \r
+//   41 \r
+//   42 //******************************************************************************\r
+//   43 // Functions\r
+//   44 //******************************************************************************\r
+//   45 /*! \brief Initialization of the one wire bus(es). (Software only driver)\r
+//   46  *  \r
+//   47  *  This function initializes the 1-Wire bus(es) by releasing it and\r
+//   48  *  waiting until any presence signals are finished.\r
+//   49  *\r
+//   50  *  \param  pins    A bitmask of the buses to initialize.\r
+//   51  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   52 void OWI_Init(unsigned char pins){\r
+OWI_Init:\r
+//   53        OWI_RELEASE_BUS(pins);\r
+        COM     R16\r
+        IN      R17, 0x1A\r
+        AND     R17, R16\r
+        OUT     0x1A, R17\r
+        IN      R17, 0x1B\r
+        AND     R17, R16\r
+        OUT     0x1B, R17\r
+//   54        // The first rising edge can be interpreted by a slave as the end of a\r
+//   55        // Reset-pulse. Delay for the required reset recovery time (H) to be \r
+//   56        // sure that the real reset is interpreted correctly.\r
+//   57        __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+        LDI     R16, 188\r
+        LDI     R17, 3\r
+        SUBI    R16, 1\r
+        SBCI    R17, 0\r
+        BRNE    $-4\r
+        RJMP    $+2\r
+//   58 }\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+//   59 \r
+//   60 \r
+//   61 /*! \brief  Write a '1' bit to the bus(es). (Software only driver)\r
+//   62  *\r
+//   63  *  Generates the waveform for transmission of a '1' bit on the 1-Wire\r
+//   64  *  bus.\r
+//   65  *\r
+//   66  *  \param  pins    A bitmask of the buses to write to.\r
+//   67  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   68 void OWI_WriteBit1(unsigned char pins){\r
+OWI_WriteBit1:\r
+//   69        unsigned char intState;\r
+//   70        \r
+//   71        // Disable interrupts.\r
+//   72        intState = __save_interrupt();\r
+        IN      R17, 0x3F\r
+//   73        __disable_interrupt();\r
+        CLI\r
+//   74        \r
+//   75        // Drive bus low and delay.\r
+//   76        OWI_PULL_BUS_LOW(pins);\r
+        IN      R18, 0x1A\r
+        OR      R18, R16\r
+        OUT     0x1A, R18\r
+        COM     R16\r
+        IN      R18, 0x1B\r
+        AND     R18, R16\r
+        OUT     0x1B, R18\r
+//   77        __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+        LDI     R18, 11\r
+        DEC     R18\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//   78        \r
+//   79        // Release bus and delay.\r
+//   80        OWI_RELEASE_BUS(pins);\r
+        IN      R18, 0x1A\r
+        AND     R18, R16\r
+        OUT     0x1A, R18\r
+        IN      R18, 0x1B\r
+        AND     R18, R16\r
+        OUT     0x1B, R18\r
+//   81        __delay_cycles(OWI_DELAY_B_STD_MODE);\r
+        LDI     R16, 166\r
+        DEC     R16\r
+        BRNE    $-2\r
+        NOP\r
+//   82        \r
+//   83        // Restore interrupts.\r
+//   84        __restore_interrupt(intState);\r
+        OUT     0x3F, R17\r
+//   85 }\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+//   86 \r
+//   87 /*! \brief  Write a '0' to the bus(es). (Software only driver)\r
+//   88  *\r
+//   89  *  Generates the waveform for transmission of a '0' bit on the 1-Wire(R)\r
+//   90  *  bus.\r
+//   91  *\r
+//   92  *  \param  pins    A bitmask of the buses to write to.\r
+//   93  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   94 void OWI_WriteBit0(unsigned char pins)\r
+OWI_WriteBit0:\r
+//   95 {\r
+//   96        unsigned char intState;\r
+//   97        \r
+//   98        // Disable interrupts.\r
+//   99        intState = __save_interrupt();\r
+        IN      R17, 0x3F\r
+//  100        __disable_interrupt();\r
+        CLI\r
+//  101        \r
+//  102        // Drive bus low and delay.\r
+//  103        OWI_PULL_BUS_LOW(pins);\r
+        IN      R18, 0x1A\r
+        OR      R18, R16\r
+        OUT     0x1A, R18\r
+        COM     R16\r
+        IN      R18, 0x1B\r
+        AND     R18, R16\r
+        OUT     0x1B, R18\r
+//  104        __delay_cycles(OWI_DELAY_C_STD_MODE);\r
+        LDI     R18, 155\r
+        DEC     R18\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//  105        \r
+//  106        // Release bus and delay.\r
+//  107        OWI_RELEASE_BUS(pins);\r
+        IN      R18, 0x1A\r
+        AND     R18, R16\r
+        OUT     0x1A, R18\r
+        IN      R18, 0x1B\r
+        AND     R18, R16\r
+        OUT     0x1B, R18\r
+//  108        __delay_cycles(OWI_DELAY_D_STD_MODE);\r
+        LDI     R16, 22\r
+        DEC     R16\r
+        BRNE    $-2\r
+        NOP\r
+//  109        \r
+//  110        // Restore interrupts.\r
+//  111        __restore_interrupt(intState);\r
+        OUT     0x3F, R17\r
+//  112 }\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+//  113 \r
+//  114 /*! \brief  Read a bit from the bus(es). (Software only driver)\r
+//  115  *\r
+//  116  *  Generates the waveform for reception of a bit on the 1-Wire(R) bus(es).\r
+//  117  *\r
+//  118  *  \param  pins    A bitmask of the bus(es) to read from.\r
+//  119  *\r
+//  120  *  \return A bitmask of the buses where a '1' was read.\r
+//  121  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  122 unsigned char OWI_ReadBit(unsigned char pins)\r
+OWI_ReadBit:\r
+//  123 {\r
+//  124        unsigned char intState;\r
+//  125        unsigned char bitsRead;\r
+//  126        \r
+//  127        // Disable interrupts.\r
+//  128        intState = __save_interrupt();\r
+        IN      R18, 0x3F\r
+//  129        __disable_interrupt();\r
+        CLI\r
+//  130        \r
+//  131        // Drive bus low and delay.\r
+//  132        OWI_PULL_BUS_LOW(pins);\r
+        IN      R17, 0x1A\r
+        OR      R17, R16\r
+        OUT     0x1A, R17\r
+        MOV     R17, R16\r
+        COM     R17\r
+        IN      R19, 0x1B\r
+        AND     R19, R17\r
+        OUT     0x1B, R19\r
+//  133        __delay_cycles(OWI_DELAY_A_STD_MODE);\r
+        LDI     R19, 11\r
+        DEC     R19\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//  134        \r
+//  135        // Release bus and delay.\r
+//  136        OWI_RELEASE_BUS(pins);\r
+        IN      R19, 0x1A\r
+        AND     R19, R17\r
+        OUT     0x1A, R19\r
+        IN      R19, 0x1B\r
+        AND     R19, R17\r
+        OUT     0x1B, R19\r
+//  137        __delay_cycles(OWI_DELAY_E_STD_MODE);\r
+        LDI     R17, 19\r
+        DEC     R17\r
+        BRNE    $-2\r
+        RJMP    $+2\r
+//  138        \r
+//  139        // Sample bus and delay.\r
+//  140        bitsRead = OWI_PIN & pins;\r
+        IN      R17, 0x19\r
+        AND     R17, R16\r
+//  141        __delay_cycles(OWI_DELAY_F_STD_MODE);\r
+        LDI     R16, 142\r
+        DEC     R16\r
+        BRNE    $-2\r
+        NOP\r
+//  142        \r
+//  143        // Restore interrupts.\r
+//  144        __restore_interrupt(intState);\r
+        OUT     0x3F, R18\r
+//  145        \r
+//  146        return bitsRead;\r
+        MOV     R16, R17\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+        REQUIRE _A_PINA\r
+//  147 }\r
+//  148 \r
+//  149 \r
+//  150 /*! \brief  Send a Reset signal and listen for Presence signal. (software\r
+//  151  *  only driver)\r
+//  152  *\r
+//  153  *  Generates the waveform for transmission of a Reset pulse on the \r
+//  154  *  1-Wire(R) bus and listens for presence signals.\r
+//  155  *\r
+//  156  *  \param  pins    A bitmask of the buses to send the Reset signal on.\r
+//  157  *\r
+//  158  *  \return A bitmask of the buses where a presence signal was detected.\r
+//  159  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  160 unsigned char OWI_DetectPresence(unsigned char pins)\r
+OWI_DetectPresence:\r
+//  161 {\r
+//  162        unsigned char intState;\r
+//  163        unsigned char presenceDetected;\r
+//  164        \r
+//  165        // Disable interrupts.\r
+//  166        intState = __save_interrupt();\r
+        IN      R18, 0x3F\r
+//  167        __disable_interrupt();\r
+        CLI\r
+//  168        \r
+//  169        // Drive bus low and delay.\r
+//  170        OWI_PULL_BUS_LOW(pins);\r
+        IN      R17, 0x1A\r
+        OR      R17, R16\r
+        OUT     0x1A, R17\r
+        MOV     R17, R16\r
+        COM     R17\r
+        IN      R19, 0x1B\r
+        AND     R19, R17\r
+        OUT     0x1B, R19\r
+//  171        __delay_cycles(OWI_DELAY_H_STD_MODE);\r
+        LDI     R20, 188\r
+        LDI     R21, 3\r
+        SUBI    R20, 1\r
+        SBCI    R21, 0\r
+        BRNE    $-4\r
+        RJMP    $+2\r
+//  172        \r
+//  173        // Release bus and delay.\r
+//  174        OWI_RELEASE_BUS(pins);\r
+        IN      R19, 0x1A\r
+        AND     R19, R17\r
+        OUT     0x1A, R19\r
+        IN      R19, 0x1B\r
+        AND     R19, R17\r
+        OUT     0x1B, R19\r
+//  175        __delay_cycles(OWI_DELAY_I_STD_MODE);\r
+        LDI     R17, 182\r
+        DEC     R17\r
+        BRNE    $-2\r
+        NOP\r
+//  176        \r
+//  177        // Sample bus to detect presence signal and delay.\r
+//  178        presenceDetected = ((~OWI_PIN) & pins);\r
+        IN      R17, 0x19\r
+        COM     R17\r
+        AND     R16, R17\r
+//  179        __delay_cycles(OWI_DELAY_J_STD_MODE);\r
+        LDI     R20, 48\r
+        LDI     R21, 3\r
+        SUBI    R20, 1\r
+        SBCI    R21, 0\r
+        BRNE    $-4\r
+        RJMP    $+2\r
+//  180        \r
+//  181        // Restore interrupts.\r
+//  182        __restore_interrupt(intState);\r
+        OUT     0x3F, R18\r
+//  183        \r
+//  184        return presenceDetected;\r
+        RET\r
+        REQUIRE _A_PORTA\r
+        REQUIRE _A_DDRA\r
+        REQUIRE _A_PINA\r
+//  185 }\r
+//  186 \r
+//  187 \r
+//  188 /*! \brief  Sends one byte of data on the 1-Wire(R) bus(es).\r
+//  189  *  \r
+//  190  *  This function automates the task of sending a complete byte\r
+//  191  *  of data on the 1-Wire bus(es).\r
+//  192  *\r
+//  193  *  \param  data    The data to send on the bus(es).\r
+//  194  *  \r
+//  195  *  \param  pins    A bitmask of the buses to send the data to.\r
+//  196  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  197 void OWI_SendByte(unsigned char data, unsigned char pins)\r
+OWI_SendByte:\r
+//  198 {\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        MOV     R26, R16\r
+        MOV     R25, R17\r
+//  199        unsigned char temp;\r
+//  200        unsigned char i;\r
+//  201        \r
+//  202        // Do once for each bit\r
+//  203        for (i = 0; i < 8; i++) {\r
+        LDI     R24, 8\r
+//  204                // Determine if LSB is '0' or '1' and transmit corresponding\r
+//  205                // waveform on the bus.\r
+//  206                temp = data & 0x01;\r
+//  207                \r
+//  208                if (temp) {\r
+??OWI_SendByte_0:\r
+        BST     R26, 0\r
+        MOV     R16, R25\r
+        BRTC    ??OWI_SendByte_1\r
+//  209                        OWI_WriteBit1(pins);\r
+        RCALL   OWI_WriteBit1\r
+        RJMP    ??OWI_SendByte_2\r
+//  210                } else {\r
+//  211                        OWI_WriteBit0(pins);\r
+??OWI_SendByte_1:\r
+        RCALL   OWI_WriteBit0\r
+//  212                }\r
+//  213        \r
+//  214                data >>= 1;  // Right shift the data to get next bit.\r
+??OWI_SendByte_2:\r
+        LSR     R26\r
+//  215        }\r
+        DEC     R24\r
+        BRNE    ??OWI_SendByte_0\r
+//  216 }\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        RET\r
+//  217 \r
+//  218 \r
+//  219 /*! \brief  Receives one byte of data from the 1-Wire(R) bus.\r
+//  220  *\r
+//  221  *  This function automates the task of receiving a complete byte \r
+//  222  *  of data from the 1-Wire bus.\r
+//  223  *\r
+//  224  *  \param  pin     A bitmask of the bus to read from.\r
+//  225  *  \r
+//  226  *  \return     The byte read from the bus.\r
+//  227  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  228 unsigned char OWI_ReceiveByte(unsigned char pin)\r
+OWI_ReceiveByte:\r
+//  229 {\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        MOV     R26, R16\r
+//  230        unsigned char data;\r
+//  231        unsigned char i;\r
+//  232        \r
+//  233        // Clear the temporary input variable.\r
+//  234        data = 0x00;\r
+        LDI     R25, 0\r
+//  235        \r
+//  236        // Do once for each bit\r
+//  237        for (i = 0; i < 8; i++) {\r
+        LDI     R24, 8\r
+//  238                // Shift temporary input variable right.\r
+//  239                data >>= 1;\r
+??OWI_ReceiveByte_0:\r
+        LSR     R25\r
+//  240                \r
+//  241                // Set the MSB if a '1' value is read from the bus.\r
+//  242                // Leave as it is ('0') else.\r
+//  243                if (OWI_ReadBit(pin)) {\r
+        MOV     R16, R26\r
+        RCALL   OWI_ReadBit\r
+        TST     R16\r
+        BREQ    ??OWI_ReceiveByte_1\r
+//  244                        data |= 0x80;\r
+        ORI     R25, 0x80\r
+//  245                }\r
+//  246        }\r
+??OWI_ReceiveByte_1:\r
+        DEC     R24\r
+        BRNE    ??OWI_ReceiveByte_0\r
+//  247        \r
+//  248        return data;\r
+        MOV     R16, R25\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        RET\r
+//  249 }\r
+//  250 \r
+//  251 \r
+//  252 /*! \brief  Sends the SKIP ROM command to the 1-Wire bus(es).\r
+//  253  *\r
+//  254  *  \param  pins    A bitmask of the buses to send the SKIP ROM command to.\r
+//  255  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  256 void OWI_SkipRom(unsigned char pins)\r
+OWI_SkipRom:\r
+//  257 {\r
+//  258        // Send the SKIP ROM command on the bus.\r
+//  259        OWI_SendByte(OWI_ROM_SKIP, pins);\r
+        MOV     R17, R16\r
+        LDI     R16, 204\r
+        RJMP    OWI_SendByte\r
+//  260 }\r
+//  261 \r
+//  262 \r
+//  263 /*! \brief  Sends the READ ROM command and reads back the ROM id.\r
+//  264  *\r
+//  265  *  \param  romValue    A pointer where the id will be placed.\r
+//  266  *\r
+//  267  *  \param  pin     A bitmask of the bus to read from.\r
+//  268  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin)\r
+OWI_ReadRom:\r
+//  270 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        MOVW    R27:R26, R17:R16\r
+        MOV     R25, R18\r
+//  271        unsigned char bytesLeft = 8;\r
+//  272        \r
+//  273        // Send the READ ROM command on the bus.\r
+//  274        OWI_SendByte(OWI_ROM_READ, pin);\r
+        MOV     R17, R18\r
+        LDI     R16, 51\r
+        RCALL   OWI_SendByte\r
+        LDI     R24, 8\r
+//  275        \r
+//  276        // Do 8 times.\r
+//  277        while (bytesLeft > 0) {\r
+//  278                // Place the received data in memory.\r
+//  279                *romValue++ = OWI_ReceiveByte(pin);\r
+??OWI_ReadRom_0:\r
+        MOV     R16, R25\r
+        RCALL   OWI_ReceiveByte\r
+        ST      X+, R16\r
+//  280                bytesLeft--;\r
+        DEC     R24\r
+//  281        }\r
+        BRNE    ??OWI_ReadRom_0\r
+//  282 }\r
+        REQUIRE ?Subroutine0\r
+        ;               // Fall through to label ?Subroutine0\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+?Subroutine0:\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+//  283 \r
+//  284 \r
+//  285 /*! \brief  Sends the MATCH ROM command and the ROM id to match against.\r
+//  286  *\r
+//  287  *  \param  romValue    A pointer to the ID to match against.\r
+//  288  *\r
+//  289  *  \param  pins    A bitmask of the buses to perform the MATCH ROM command on.\r
+//  290  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins)\r
+OWI_MatchRom:\r
+//  292 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        MOVW    R27:R26, R17:R16\r
+        MOV     R25, R18\r
+//  293        unsigned char bytesLeft = 8;   \r
+//  294        \r
+//  295        // Send the MATCH ROM command.\r
+//  296        OWI_SendByte(OWI_ROM_MATCH, pins);\r
+        MOV     R17, R18\r
+        LDI     R16, 85\r
+        RCALL   OWI_SendByte\r
+        LDI     R24, 8\r
+//  297        \r
+//  298        // Do once for each byte.\r
+//  299        while (bytesLeft > 0) {\r
+//  300                // Transmit 1 byte of the ID to match.\r
+//  301                OWI_SendByte(*romValue++, pins);\r
+??OWI_MatchRom_0:\r
+        MOV     R17, R25\r
+        LD      R16, X+\r
+        RCALL   OWI_SendByte\r
+//  302                bytesLeft--;\r
+        DEC     R24\r
+//  303        }\r
+        BRNE    ??OWI_MatchRom_0\r
+//  304 }\r
+        RJMP    ?Subroutine0\r
+//  305 \r
+//  306 \r
+//  307 /*! \brief  Sends the SEARCH ROM command and returns 1 id found on the \r
+//  308  *          1-Wire(R) bus.\r
+//  309  *\r
+//  310  *  \param  bitPattern      A pointer to an 8 byte char array where the \r
+//  311  *                          discovered identifier will be placed. When \r
+//  312  *                          searching for several slaves, a copy of the \r
+//  313  *                          last found identifier should be supplied in \r
+//  314  *                          the array, or the search will fail.\r
+//  315  *\r
+//  316  *  \param  lastDeviation   The bit position where the algorithm made a \r
+//  317  *                          choice the last time it was run. This argument \r
+//  318  *                          should be 0 when a search is initiated. Supplying \r
+//  319  *                          the return argument of this function when calling \r
+//  320  *                          repeatedly will go through the complete slave \r
+//  321  *                          search.\r
+//  322  *\r
+//  323  *  \param  pin             A bit-mask of the bus to perform a ROM search on.\r
+//  324  *\r
+//  325  *  \return The last bit position where there was a discrepancy between slave\r
+//  326  *  addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED\r
+//  327  *  if an error was detected (e.g. a device was connected to the bus during the\r
+//  328  *  search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be\r
+//  329  *  discovered.\r
+//  330  *\r
+//  331  *  \note   See main.c for an example of how to utilize this function.\r
+//  332  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  333 unsigned char OWI_SearchRom(unsigned char * bitPattern,\r
+OWI_SearchRom:\r
+//  334                                                unsigned char lastDeviation, unsigned char pin)\r
+//  335 {\r
+        ST      -Y, R7\r
+        ST      -Y, R6\r
+        ST      -Y, R5\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        REQUIRE ?Register_R7_is_cg_reg\r
+        MOVW    R27:R26, R17:R16\r
+        MOV     R6, R18\r
+        MOV     R4, R19\r
+//  336        unsigned char currentBit = 1;\r
+        LDI     R24, 1\r
+//  337        unsigned char newDeviation = 0;\r
+        CLR     R5\r
+//  338        unsigned char bitMask = 0x01;\r
+        LDI     R25, 1\r
+//  339        unsigned char bitA;\r
+//  340        unsigned char bitB;\r
+//  341        \r
+//  342        // Send SEARCH ROM command on the bus.\r
+//  343        OWI_SendByte(OWI_ROM_SEARCH, pin);\r
+        MOV     R17, R19\r
+        LDI     R16, 240\r
+        RCALL   OWI_SendByte\r
+//  344        \r
+//  345        // Walk through all 64 bits.\r
+//  346        while (currentBit <= 64) {\r
+//  347                // Read bit from bus twice.\r
+//  348                bitA = OWI_ReadBit(pin);\r
+??OWI_SearchRom_0:\r
+        MOV     R16, R4\r
+        RCALL   OWI_ReadBit\r
+        MOV     R7, R16\r
+//  349                bitB = OWI_ReadBit(pin);\r
+        MOV     R16, R4\r
+        RCALL   OWI_ReadBit\r
+//  350                \r
+//  351                if (bitA && bitB) {\r
+        TST     R7\r
+        BREQ    ??OWI_SearchRom_1\r
+        TST     R16\r
+        BREQ    ??OWI_SearchRom_1\r
+//  352                        // Both bits 1 (Error).\r
+//  353                        newDeviation = OWI_ROM_SEARCH_FAILED;\r
+//  354                        return newDeviation;\r
+        LDI     R16, 255\r
+        RJMP    ??OWI_SearchRom_2\r
+//  355                } else if (bitA ^ bitB) {\r
+??OWI_SearchRom_1:\r
+        EOR     R16, R7\r
+        BREQ    ??OWI_SearchRom_3\r
+//  356                        // Bits A and B are different. All devices have the same bit here.\r
+//  357                        // Set the bit in bitPattern to this value.\r
+//  358                        if (bitA) {\r
+        TST     R7\r
+        BREQ    ??OWI_SearchRom_4\r
+//  359                                (*bitPattern) |= bitMask;\r
+??OWI_SearchRom_5:\r
+        MOVW    R31:R30, R27:R26\r
+        LD      R16, Z\r
+        OR      R16, R25\r
+        ST      Z, R16\r
+        RJMP    ??OWI_SearchRom_6\r
+//  360                        } else {\r
+//  361                                (*bitPattern) &= ~bitMask;\r
+??OWI_SearchRom_4:\r
+        MOV     R16, R25\r
+        COM     R16\r
+        LD      R17, X\r
+        AND     R17, R16\r
+        ST      X, R17\r
+        RJMP    ??OWI_SearchRom_6\r
+//  362                        }\r
+//  363                } else {\r
+//  364                        // If this is where a choice was made the last time,\r
+//  365                        // a '1' bit is selected this time.\r
+//  366                        if (currentBit == lastDeviation) {\r
+??OWI_SearchRom_3:\r
+        CP      R24, R6\r
+        BREQ    ??OWI_SearchRom_5\r
+//  367                                (*bitPattern) |= bitMask;\r
+//  368                        }\r
+//  369                        \r
+//  370                        // For the rest of the id, '0' bits are selected when\r
+//  371                        // discrepancies occur.\r
+//  372                        else if (currentBit > lastDeviation) {\r
+        CP      R6, R24\r
+        BRCC    ??OWI_SearchRom_7\r
+//  373                                (*bitPattern) &= ~bitMask;\r
+        MOV     R16, R25\r
+        COM     R16\r
+        LD      R17, X\r
+        AND     R17, R16\r
+        ST      X, R17\r
+//  374                                newDeviation = currentBit;\r
+        RJMP    ??OWI_SearchRom_8\r
+//  375                        }\r
+//  376                        \r
+//  377                        // If current bit in bit pattern = 0, then this is\r
+//  378                        // out new deviation.\r
+//  379                        else if ( !(*bitPattern & bitMask)) {\r
+??OWI_SearchRom_7:\r
+        LD      R16, X\r
+        AND     R16, R25\r
+        BRNE    ??OWI_SearchRom_6\r
+//  380                                newDeviation = currentBit;\r
+??OWI_SearchRom_8:\r
+        MOV     R5, R24\r
+//  381                        }\r
+//  382                        \r
+//  383                // IF the bit is already 1, do nothing.\r
+//  384                        else {\r
+//  385                        }\r
+//  386                }\r
+//  387                \r
+//  388                // Send the selected bit to the bus.\r
+//  389                if ((*bitPattern) & bitMask) {\r
+??OWI_SearchRom_6:\r
+        LD      R16, X\r
+        AND     R16, R25\r
+        MOV     R16, R4\r
+        BREQ    ??OWI_SearchRom_9\r
+//  390                        OWI_WriteBit1(pin);\r
+        RCALL   OWI_WriteBit1\r
+        RJMP    ??OWI_SearchRom_10\r
+//  391                } else {\r
+//  392                        OWI_WriteBit0(pin);\r
+??OWI_SearchRom_9:\r
+        RCALL   OWI_WriteBit0\r
+//  393                }\r
+//  394                \r
+//  395                // Increment current bit.    \r
+//  396                currentBit++;\r
+??OWI_SearchRom_10:\r
+        INC     R24\r
+//  397                \r
+//  398                // Adjust bitMask and bitPattern pointer.    \r
+//  399                bitMask <<= 1;\r
+        LSL     R25\r
+//  400                if (!bitMask) {\r
+        BRNE    ??OWI_SearchRom_11\r
+//  401                        bitMask = 0x01;\r
+        LDI     R25, 1\r
+//  402                        bitPattern++;\r
+        ADIW    R27:R26, 1\r
+//  403                }\r
+//  404        }\r
+??OWI_SearchRom_11:\r
+        CPI     R24, 65\r
+        BRCS    ??OWI_SearchRom_0\r
+//  405        \r
+//  406        return newDeviation;\r
+        MOV     R16, R5\r
+??OWI_SearchRom_2:\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        LD      R5, Y+\r
+        LD      R6, Y+\r
+        LD      R7, Y+\r
+        RET\r
+//  407 }\r
+//  408 \r
+//  409 \r
+//  410 /* Functions for handling CRC */\r
+//  411 /*! \brief  Compute the CRC8 value of a data set.\r
+//  412  *\r
+//  413  *  This function will compute the CRC8 or DOW-CRC of inData using seed\r
+//  414  *  as inital value for the CRC.\r
+//  415  *\r
+//  416  *  \param  inData  One byte of data to compute CRC from.\r
+//  417  *\r
+//  418  *  \param  seed    The starting value of the CRC.\r
+//  419  *\r
+//  420  *  \return The CRC8 of inData with seed as initial value.\r
+//  421  *\r
+//  422  *  \note   Setting seed to 0 computes the crc8 of the inData.\r
+//  423  *\r
+//  424  *  \note   Constantly passing the return value of this function \r
+//  425  *          As the seed argument computes the CRC8 value of a\r
+//  426  *          longer string of data.\r
+//  427  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed)\r
+OWI_ComputeCRC8:\r
+//  429 {\r
+//  430        unsigned char bitsLeft;\r
+//  431        unsigned char temp;\r
+//  432        \r
+//  433        for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+        LDI     R19, 8\r
+//  434                temp = ((seed ^ inData) & 0x01);\r
+//  435                \r
+//  436                if (temp == 0) {\r
+??OWI_ComputeCRC8_0:\r
+        MOV     R18, R17\r
+        ANDI    R18, 0x01\r
+        MOV     R20, R16\r
+        ANDI    R20, 0x01\r
+        EOR     R20, R18\r
+        BRNE    ??OWI_ComputeCRC8_1\r
+//  437                seed >>= 1;\r
+        LSR     R17\r
+        RJMP    ??OWI_ComputeCRC8_2\r
+//  438                } else {\r
+//  439                        seed ^= 0x18;\r
+//  440                        seed >>= 1;\r
+//  441                        seed |= 0x80;\r
+??OWI_ComputeCRC8_1:\r
+        LDI     R18, 24\r
+        EOR     R17, R18\r
+        LSR     R17\r
+        ORI     R17, 0x80\r
+//  442                }\r
+//  443                \r
+//  444                inData >>= 1;\r
+??OWI_ComputeCRC8_2:\r
+        LSR     R16\r
+//  445        }\r
+        DEC     R19\r
+        BRNE    ??OWI_ComputeCRC8_0\r
+//  446        return seed;    \r
+        MOV     R16, R17\r
+        RET\r
+//  447 }\r
+//  448 \r
+//  449 \r
+//  450 /*! \brief  Compute the CRC16 value of a data set.\r
+//  451  *\r
+//  452  *  This function will compute the CRC16 of inData using seed\r
+//  453  *  as inital value for the CRC.\r
+//  454  *\r
+//  455  *  \param  inData  One byte of data to compute CRC from.\r
+//  456  *\r
+//  457  *  \param  seed    The starting value of the CRC.\r
+//  458  *\r
+//  459  *  \return The CRC16 of inData with seed as initial value.\r
+//  460  *\r
+//  461  *  \note   Setting seed to 0 computes the crc16 of the inData.\r
+//  462  *\r
+//  463  *  \note   Constantly passing the return value of this function \r
+//  464  *          As the seed argument computes the CRC16 value of a\r
+//  465  *          longer string of data.\r
+//  466  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed)\r
+OWI_ComputeCRC16:\r
+//  468 {\r
+//  469        unsigned char bitsLeft;\r
+//  470        unsigned char temp;\r
+//  471        \r
+//  472        for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) {\r
+        LDI     R17, 8\r
+//  473                temp = ((seed ^ inData) & 0x01);\r
+//  474                \r
+//  475                if (temp == 0) {\r
+??OWI_ComputeCRC16_0:\r
+        MOV     R20, R18\r
+        ANDI    R20, 0x01\r
+        MOV     R21, R16\r
+        ANDI    R21, 0x01\r
+        EOR     R21, R20\r
+        BRNE    ??OWI_ComputeCRC16_1\r
+//  476                        seed >>= 1;\r
+        LSR     R19\r
+        ROR     R18\r
+        RJMP    ??OWI_ComputeCRC16_2\r
+//  477          } else {\r
+//  478                        seed ^= 0x4002;\r
+//  479                        seed >>= 1;\r
+//  480                        seed |= 0x8000;\r
+??OWI_ComputeCRC16_1:\r
+        LDI     R20, 2\r
+        LDI     R21, 64\r
+        EOR     R20, R18\r
+        EOR     R21, R19\r
+        MOVW    R19:R18, R21:R20\r
+        LSR     R19\r
+        ROR     R18\r
+        ORI     R19, 0x80\r
+//  481                }\r
+//  482 \r
+//  483                inData >>= 1;\r
+??OWI_ComputeCRC16_2:\r
+        LSR     R16\r
+//  484        }\r
+        DEC     R17\r
+        BRNE    ??OWI_ComputeCRC16_0\r
+//  485        \r
+//  486        return seed;    \r
+        MOVW    R17:R16, R19:R18\r
+        RET\r
+//  487 }\r
+//  488 \r
+//  489 \r
+//  490 /*! \brief  Calculate and check the CRC of a 64 bit ROM identifier.\r
+//  491  *  \r
+//  492  *  This function computes the CRC8 value of the first 56 bits of a\r
+//  493  *  64 bit identifier. It then checks the calculated value against the\r
+//  494  *  CRC value stored in ROM.\r
+//  495  *\r
+//  496  *  \param  *romValue    A pointer to an array holding a 64 bit identifier.\r
+//  497  *\r
+//  498  *  \retval OWI_CRC_OK      The CRC's matched.\r
+//  499  *  \retval OWI_CRC_ERROR   Calculated and stored CRC did not match.\r
+//  500  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  501 unsigned char OWI_CheckRomCRC(unsigned char *romValue)\r
+OWI_CheckRomCRC:\r
+//  502 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R24\r
+        MOVW    R27:R26, R17:R16\r
+//  503        unsigned char i;\r
+//  504        unsigned char crc8 = 0;\r
+        LDI     R17, 0\r
+//  505        \r
+//  506        for (i = 0; i < 7; i++) {\r
+        LDI     R24, 7\r
+//  507                crc8 = OWI_ComputeCRC8(*romValue, crc8);\r
+??OWI_CheckRomCRC_0:\r
+        LD      R16, X+\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R17, R16\r
+//  508                romValue++;\r
+//  509        }\r
+        DEC     R24\r
+        BRNE    ??OWI_CheckRomCRC_0\r
+//  510        \r
+//  511        if (crc8 == (*romValue)) {\r
+        LD      R16, X\r
+        CP      R17, R16\r
+        BRNE    ??OWI_CheckRomCRC_1\r
+//  512                return OWI_CRC_OK;\r
+        LDI     R16, 0\r
+        RJMP    ??OWI_CheckRomCRC_2\r
+//  513        }\r
+//  514        \r
+//  515        return OWI_CRC_ERROR;\r
+??OWI_CheckRomCRC_1:\r
+        LDI     R16, 1\r
+??OWI_CheckRomCRC_2:\r
+        LD      R24, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+//  516 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+// \r
+//   3 bytes in segment ABSOLUTE\r
+// 708 bytes in segment CODE\r
+// \r
+// 708 bytes of CODE memory\r
+//   0 bytes of DATA memory (+ 3 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/PWM.lst b/BaseTinyFirmware/IAR/Release/List/PWM.lst
new file mode 100644 (file)
index 0000000..c523013
--- /dev/null
@@ -0,0 +1,402 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:01 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\PWM.c           #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\PWM.c           #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\PW #\r
+#                             M.lst                                           #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM #\r
+#                             .r90                                            #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\PWM.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for use of PWM\r
+      6           *\r
+      7           *      Contains functions for initializing and controlling PWM output.\r
+      8           *\r
+      9           * \par Application note:\r
+     10           *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+     11           *      AVR463: Charging NiMH Batteries with BC100\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2299 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
+     26           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x50\r
+   \   <unnamed> volatile __io _A_TCCR1A\r
+   \                     _A_TCCR1A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4f\r
+   \   <unnamed> volatile __io _A_TCCR1B\r
+   \                     _A_TCCR1B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4d\r
+   \   <unnamed> volatile __io _A_OCR1A\r
+   \                     _A_OCR1A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4c\r
+   \   <unnamed> volatile __io _A_OCR1B\r
+   \                     _A_OCR1B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4b\r
+   \   <unnamed> volatile __io _A_OCR1C\r
+   \                     _A_OCR1C:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4a\r
+   \   <unnamed> volatile __io _A_OCR1D\r
+   \                     _A_OCR1D:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x49\r
+   \   <unnamed> volatile __io _A_PLLCSR\r
+   \                     _A_PLLCSR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x47\r
+   \   <unnamed> volatile __io _A_TCCR1C\r
+   \                     _A_TCCR1C:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x46\r
+   \   <unnamed> volatile __io _A_TCCR1D\r
+   \                     _A_TCCR1D:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x44\r
+   \   <unnamed> volatile __io _A_DT1\r
+   \                     _A_DT1:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x37\r
+   \   <unnamed> volatile __io _A_DDRB\r
+   \                     _A_DDRB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x20\r
+   \   <unnamed> volatile __io _A_TCCR1E\r
+   \                     _A_TCCR1E:\r
+   \   00000000                      DS 1\r
+     30          \r
+     31          #include "enums.h"\r
+     32          \r
+     33          #include "main.h"\r
+     34          #include "PWM.h"\r
+     35          #include "time.h"\r
+     36          \r
+     37          \r
+     38          //******************************************************************************\r
+     39          // Functions\r
+     40          //******************************************************************************\r
+     41          /*! \brief Stops PWM output\r
+     42           *\r
+     43           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     44          void PWM_Stop(void)\r
+   \                     PWM_Stop:\r
+     45          {\r
+     46                OCR1B = 0;  // Reset compare level.\r
+   \   00000000   E000               LDI     R16, 0\r
+   \   00000002   BD0C               OUT     0x2C, R16\r
+     47                PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
+   \   00000004   BD09               OUT     0x29, R16\r
+     48                TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
+   \   00000006   BF00               OUT     0x30, R16\r
+     49                TCCR1B = 0; // Stop timer/counter1.\r
+   \   00000008   BD0F               OUT     0x2F, R16\r
+     50                TCCR1C = 0; // Set normal port operation.\r
+   \   0000000A   BD07               OUT     0x27, R16\r
+     51                TCCR1D = 0; // No fault protection, normal waveform.\r
+   \   0000000C   BD06               OUT     0x26, R16\r
+     52                OCR1C = 0;  // Reset compare.\r
+   \   0000000E   BD0B               OUT     0x2B, R16\r
+     53                OCR1D = 0;  // Reset compare.\r
+   \   00000010   BD0A               OUT     0x2A, R16\r
+     54                DT1 = 0;    // No dead time values.\r
+   \   00000012   BD04               OUT     0x24, R16\r
+     55          }\r
+   \   00000014   9508               RET\r
+   \   00000016                      REQUIRE _A_TCCR1A\r
+   \   00000016                      REQUIRE _A_TCCR1B\r
+   \   00000016                      REQUIRE _A_OCR1B\r
+   \   00000016                      REQUIRE _A_OCR1C\r
+   \   00000016                      REQUIRE _A_OCR1D\r
+   \   00000016                      REQUIRE _A_PLLCSR\r
+   \   00000016                      REQUIRE _A_TCCR1C\r
+   \   00000016                      REQUIRE _A_TCCR1D\r
+   \   00000016                      REQUIRE _A_DT1\r
+     56          \r
+     57          \r
+     58          /*! \brief Initializes and starts PWM output\r
+     59           *\r
+     60           * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
+     61           * Its comparator is connected to PB3 and will output high until timer1 reaches\r
+     62           * the value of OCR1B. It is then dropped to 0.\n\r
+     63           * The comparator outputs high again when the counter overflows, which will\r
+     64           * happen at a rate of 250 kHz.\r
+     65           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     66          void PWM_Start(void)\r
+   \                     PWM_Start:\r
+     67          {\r
+     68                // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
+     69                TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
+   \   00000000   E201               LDI     R16, 33\r
+   \   00000002   BF00               OUT     0x30, R16\r
+     70                \r
+     71                // Non-inverted PWM, T/C stopped.\r
+     72                TCCR1B = 0;\r
+   \   00000004   E000               LDI     R16, 0\r
+   \   00000006   BD0F               OUT     0x2F, R16\r
+     73                \r
+     74                // Copy shadow bits, disconnect OC1D.\r
+     75                TCCR1C = (TCCR1A & 0xF0);\r
+   \   00000008   B700               IN      R16, 0x30\r
+   \   0000000A   7F00               ANDI    R16, 0xF0\r
+   \   0000000C   BD07               OUT     0x27, R16\r
+     76                \r
+     77                // No fault protection, use phase & frequency correct PWM.\r
+     78                TCCR1D = (0<<WGM11)|(1<WGM10);\r
+   \   0000000E   E000               LDI     R16, 0\r
+   \   00000010   BD06               OUT     0x26, R16\r
+     79                \r
+     80                // Does not matter -- PWM6 mode not used.\r
+     81                TCCR1E = 0;\r
+   \   00000012   B900               OUT     0x00, R16\r
+     82                \r
+     83                // Does not matter -- OC1A is disabled.\r
+     84                OCR1A = 0;\r
+   \   00000014   BD0D               OUT     0x2D, R16\r
+     85                \r
+     86                // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
+     87                OCR1B = PWM_OFFSET;\r
+   \   00000016   E00C               LDI     R16, 12\r
+   \   00000018   BD0C               OUT     0x2C, R16\r
+     88                \r
+     89                // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
+     90                OCR1C = 0xFF;\r
+   \   0000001A   EF0F               LDI     R16, 255\r
+   \   0000001C   BD0B               OUT     0x2B, R16\r
+     91                \r
+     92                // Does not matter -- OC1D is disabled.\r
+     93                OCR1D = 0;\r
+   \   0000001E   E000               LDI     R16, 0\r
+   \   00000020   BD0A               OUT     0x2A, R16\r
+     94                \r
+     95                // No dead time values.\r
+     96                DT1 = 0;\r
+   \   00000022   BD04               OUT     0x24, R16\r
+     97                \r
+     98                // Set PWM port pin to output.\r
+     99                DDRB |= (1<<PB3);\r
+   \   00000024   9ABB               SBI     0x17, 0x03\r
+    100                \r
+    101                // Enable PLL, use full speed mode.\r
+    102                PLLCSR = (0<<LSM) | (1<<PLLE);\r
+   \   00000026   E002               LDI     R16, 2\r
+   \   00000028   BD09               OUT     0x29, R16\r
+    103                \r
+    104                // Use general timer and wait 1 ms for PLL lock to settle.\r
+    105                Time_Set(TIMER_GEN,0,0,1);\r
+   \   0000002A   E041               LDI     R20, 1\r
+   \   0000002C   E010               LDI     R17, 0\r
+   \   0000002E   E020               LDI     R18, 0\r
+   \   00000030   E030               LDI     R19, 0\r
+   \   00000032   ....               RCALL   Time_Set\r
+    106                do{ \r
+    107                }while(Time_Left(TIMER_GEN));\r
+   \                     ??PWM_Start_0:\r
+   \   00000034   E002               LDI     R16, 2\r
+   \   00000036   ....               RCALL   Time_Left\r
+   \   00000038   2300               TST     R16\r
+   \   0000003A   F7E1               BRNE    ??PWM_Start_0\r
+    108                \r
+    109                // Now wait for PLL to lock.\r
+    110                do{ \r
+    111                }while((PLLCSR & (1<<PLOCK)) == 0);\r
+   \                     ??PWM_Start_1:\r
+   \   0000003C   B509               IN      R16, 0x29\r
+   \   0000003E   FF00               SBRS    R16, 0\r
+   \   00000040   CFFD               RJMP    ??PWM_Start_1\r
+    112          \r
+    113                // Use PLL as clock source.\r
+    114                PLLCSR |= (1<<PCKE);\r
+   \   00000042   B509               IN      R16, 0x29\r
+   \   00000044   6004               ORI     R16, 0x04\r
+   \   00000046   BD09               OUT     0x29, R16\r
+    115                \r
+    116                // CLK PCK = 64MHz / 1 = 64MHz.\r
+    117                TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
+   \   00000048   B50F               IN      R16, 0x2F\r
+   \   0000004A   6001               ORI     R16, 0x01\r
+   \   0000004C   BD0F               OUT     0x2F, R16\r
+    118          }\r
+   \   0000004E   9508               RET\r
+   \   00000050                      REQUIRE _A_TCCR1A\r
+   \   00000050                      REQUIRE _A_TCCR1B\r
+   \   00000050                      REQUIRE _A_OCR1A\r
+   \   00000050                      REQUIRE _A_OCR1B\r
+   \   00000050                      REQUIRE _A_OCR1C\r
+   \   00000050                      REQUIRE _A_OCR1D\r
+   \   00000050                      REQUIRE _A_PLLCSR\r
+   \   00000050                      REQUIRE _A_TCCR1C\r
+   \   00000050                      REQUIRE _A_TCCR1D\r
+   \   00000050                      REQUIRE _A_DT1\r
+   \   00000050                      REQUIRE _A_DDRB\r
+   \   00000050                      REQUIRE _A_TCCR1E\r
+    119          \r
+    120          \r
+    121          /*! \brief Increments the PWM duty cycle, if not already at max\r
+    122           *\r
+    123           * \retval TRUE Success, duty cycle could be incremented.\r
+    124           * \retval FALSE Failure, duty cycle already at maximum.\r
+    125           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    126          unsigned char PWM_IncrementDutyCycle(void){\r
+   \                     PWM_IncrementDutyCycle:\r
+    127          \r
+    128                if (OCR1B < PWM_MAX) {\r
+   \   00000000   B50C               IN      R16, 0x2C\r
+   \   00000002   3F0F               CPI     R16, 255\r
+   \   00000004   F029               BREQ    ??PWM_IncrementDutyCycle_0\r
+    129                        OCR1B += 1;\r
+   \   00000006   B50C               IN      R16, 0x2C\r
+   \   00000008   9503               INC     R16\r
+   \   0000000A   BD0C               OUT     0x2C, R16\r
+    130                        return(TRUE);\r
+   \   0000000C   E001               LDI     R16, 1\r
+   \   0000000E   9508               RET\r
+    131                } else {\r
+    132                        return(FALSE);\r
+   \                     ??PWM_IncrementDutyCycle_0:\r
+   \   00000010   E000               LDI     R16, 0\r
+   \   00000012   9508               RET\r
+   \   00000014                      REQUIRE _A_OCR1B\r
+    133                }\r
+    134          }\r
+    135          \r
+    136          \r
+    137          /*! \brief Decrements the PWM duty cycle, if not already at zero.\r
+    138           *\r
+    139           * \retval TRUE Success, duty cycle could be decremented.\r
+    140           * \retval FALSE Failure, duty cycle already at zero.\r
+    141           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    142          unsigned char PWM_DecrementDutyCycle(void){\r
+   \                     PWM_DecrementDutyCycle:\r
+    143                \r
+    144                if (OCR1B > 0)  {\r
+   \   00000000   B50C               IN      R16, 0x2C\r
+   \   00000002   2300               TST     R16\r
+   \   00000004   F029               BREQ    ??PWM_DecrementDutyCycle_0\r
+    145                        OCR1B -= 1;\r
+   \   00000006   B50C               IN      R16, 0x2C\r
+   \   00000008   950A               DEC     R16\r
+   \   0000000A   BD0C               OUT     0x2C, R16\r
+    146                        return(TRUE);\r
+   \   0000000C   E001               LDI     R16, 1\r
+   \   0000000E   9508               RET\r
+    147                } else {\r
+    148                        return(FALSE);\r
+   \                     ??PWM_DecrementDutyCycle_0:\r
+   \   00000010   E000               LDI     R16, 0\r
+   \   00000012   9508               RET\r
+   \   00000014                      REQUIRE _A_OCR1B\r
+    149                }\r
+    150          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function               CSTACK RSTACK\r
+     --------               ------ ------\r
+     PWM_DecrementDutyCycle     0      2\r
+     PWM_IncrementDutyCycle     0      2\r
+     PWM_Start                  0      2\r
+       -> Time_Set              0      2\r
+       -> Time_Left             0      2\r
+     PWM_Stop                   0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label         Bytes\r
+     --------------         -----\r
+     _A_TCCR1A                 1\r
+     _A_TCCR1B                 1\r
+     _A_OCR1A                  1\r
+     _A_OCR1B                  1\r
+     _A_OCR1C                  1\r
+     _A_OCR1D                  1\r
+     _A_PLLCSR                 1\r
+     _A_TCCR1C                 1\r
+     _A_TCCR1D                 1\r
+     _A_DT1                    1\r
+     _A_DDRB                   1\r
+     _A_TCCR1E                 1\r
+     PWM_Stop                 22\r
+     PWM_Start                80\r
+     PWM_IncrementDutyCycle   20\r
+     PWM_DecrementDutyCycle   20\r
+\r
\r
+  12 bytes in segment ABSOLUTE\r
+ 142 bytes in segment CODE\r
\r
+ 142 bytes of CODE memory\r
+   0 bytes of DATA memory (+ 12 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/PWM.s90 b/BaseTinyFirmware/IAR/Release/List/PWM.s90
new file mode 100644 (file)
index 0000000..84e65d6
--- /dev/null
@@ -0,0 +1,409 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:01 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\PWM.c          /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\PWM.c          /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\P /\r
+//                             WM.s90                                         /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME PWM\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        PUBLIC PWM_DecrementDutyCycle\r
+        PUBLIC PWM_IncrementDutyCycle\r
+        PUBLIC PWM_Start\r
+        PUBLIC PWM_Stop\r
+        PUBWEAK _A_DDRB\r
+        PUBWEAK _A_DT1\r
+        PUBWEAK _A_OCR1A\r
+        PUBWEAK _A_OCR1B\r
+        PUBWEAK _A_OCR1C\r
+        PUBWEAK _A_OCR1D\r
+        PUBWEAK _A_PLLCSR\r
+        PUBWEAK _A_TCCR1A\r
+        PUBWEAK _A_TCCR1B\r
+        PUBWEAK _A_TCCR1C\r
+        PUBWEAK _A_TCCR1D\r
+        PUBWEAK _A_TCCR1E\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN Time_Set\r
+        EXTERN Time_Left\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\PWM.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for use of PWM\r
+//    6  *\r
+//    7  *      Contains functions for initializing and controlling PWM output.\r
+//    8  *\r
+//    9  * \par Application note:\r
+//   10  *      AVR458: Charging Li-Ion Batteries with BC100\n\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2299 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $\r
+//   26  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,050H\r
+// <unnamed> volatile __io _A_TCCR1A\r
+_A_TCCR1A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04fH\r
+// <unnamed> volatile __io _A_TCCR1B\r
+_A_TCCR1B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04dH\r
+// <unnamed> volatile __io _A_OCR1A\r
+_A_OCR1A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
+// <unnamed> volatile __io _A_OCR1B\r
+_A_OCR1B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04bH\r
+// <unnamed> volatile __io _A_OCR1C\r
+_A_OCR1C:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04aH\r
+// <unnamed> volatile __io _A_OCR1D\r
+_A_OCR1D:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,049H\r
+// <unnamed> volatile __io _A_PLLCSR\r
+_A_PLLCSR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,047H\r
+// <unnamed> volatile __io _A_TCCR1C\r
+_A_TCCR1C:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,046H\r
+// <unnamed> volatile __io _A_TCCR1D\r
+_A_TCCR1D:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,044H\r
+// <unnamed> volatile __io _A_DT1\r
+_A_DT1:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,037H\r
+// <unnamed> volatile __io _A_DDRB\r
+_A_DDRB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,020H\r
+// <unnamed> volatile __io _A_TCCR1E\r
+_A_TCCR1E:\r
+        DS 1\r
+//   30 \r
+//   31 #include "enums.h"\r
+//   32 \r
+//   33 #include "main.h"\r
+//   34 #include "PWM.h"\r
+//   35 #include "time.h"\r
+//   36 \r
+//   37 \r
+//   38 //******************************************************************************\r
+//   39 // Functions\r
+//   40 //******************************************************************************\r
+//   41 /*! \brief Stops PWM output\r
+//   42  *\r
+//   43  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   44 void PWM_Stop(void)\r
+PWM_Stop:\r
+//   45 {\r
+//   46        OCR1B = 0;  // Reset compare level.\r
+        LDI     R16, 0\r
+        OUT     0x2C, R16\r
+//   47        PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode.\r
+        OUT     0x29, R16\r
+//   48        TCCR1A = 0; // Set normal port operation, disable PWM modes.\r
+        OUT     0x30, R16\r
+//   49        TCCR1B = 0; // Stop timer/counter1.\r
+        OUT     0x2F, R16\r
+//   50        TCCR1C = 0; // Set normal port operation.\r
+        OUT     0x27, R16\r
+//   51        TCCR1D = 0; // No fault protection, normal waveform.\r
+        OUT     0x26, R16\r
+//   52        OCR1C = 0;  // Reset compare.\r
+        OUT     0x2B, R16\r
+//   53        OCR1D = 0;  // Reset compare.\r
+        OUT     0x2A, R16\r
+//   54        DT1 = 0;    // No dead time values.\r
+        OUT     0x24, R16\r
+//   55 }\r
+        RET\r
+        REQUIRE _A_TCCR1A\r
+        REQUIRE _A_TCCR1B\r
+        REQUIRE _A_OCR1B\r
+        REQUIRE _A_OCR1C\r
+        REQUIRE _A_OCR1D\r
+        REQUIRE _A_PLLCSR\r
+        REQUIRE _A_TCCR1C\r
+        REQUIRE _A_TCCR1D\r
+        REQUIRE _A_DT1\r
+//   56 \r
+//   57 \r
+//   58 /*! \brief Initializes and starts PWM output\r
+//   59  *\r
+//   60  * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n\r
+//   61  * Its comparator is connected to PB3 and will output high until timer1 reaches\r
+//   62  * the value of OCR1B. It is then dropped to 0.\n\r
+//   63  * The comparator outputs high again when the counter overflows, which will\r
+//   64  * happen at a rate of 250 kHz.\r
+//   65  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   66 void PWM_Start(void)\r
+PWM_Start:\r
+//   67 {\r
+//   68        // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
+//   69        TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
+        LDI     R16, 33\r
+        OUT     0x30, R16\r
+//   70        \r
+//   71        // Non-inverted PWM, T/C stopped.\r
+//   72        TCCR1B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2F, R16\r
+//   73        \r
+//   74        // Copy shadow bits, disconnect OC1D.\r
+//   75        TCCR1C = (TCCR1A & 0xF0);\r
+        IN      R16, 0x30\r
+        ANDI    R16, 0xF0\r
+        OUT     0x27, R16\r
+//   76        \r
+//   77        // No fault protection, use phase & frequency correct PWM.\r
+//   78        TCCR1D = (0<<WGM11)|(1<WGM10);\r
+        LDI     R16, 0\r
+        OUT     0x26, R16\r
+//   79        \r
+//   80        // Does not matter -- PWM6 mode not used.\r
+//   81        TCCR1E = 0;\r
+        OUT     0x00, R16\r
+//   82        \r
+//   83        // Does not matter -- OC1A is disabled.\r
+//   84        OCR1A = 0;\r
+        OUT     0x2D, R16\r
+//   85        \r
+//   86        // Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
+//   87        OCR1B = PWM_OFFSET;\r
+        LDI     R16, 12\r
+        OUT     0x2C, R16\r
+//   88        \r
+//   89        // TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
+//   90        OCR1C = 0xFF;\r
+        LDI     R16, 255\r
+        OUT     0x2B, R16\r
+//   91        \r
+//   92        // Does not matter -- OC1D is disabled.\r
+//   93        OCR1D = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2A, R16\r
+//   94        \r
+//   95        // No dead time values.\r
+//   96        DT1 = 0;\r
+        OUT     0x24, R16\r
+//   97        \r
+//   98        // Set PWM port pin to output.\r
+//   99        DDRB |= (1<<PB3);\r
+        SBI     0x17, 0x03\r
+//  100        \r
+//  101        // Enable PLL, use full speed mode.\r
+//  102        PLLCSR = (0<<LSM) | (1<<PLLE);\r
+        LDI     R16, 2\r
+        OUT     0x29, R16\r
+//  103        \r
+//  104        // Use general timer and wait 1 ms for PLL lock to settle.\r
+//  105        Time_Set(TIMER_GEN,0,0,1);\r
+        LDI     R20, 1\r
+        LDI     R17, 0\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        RCALL   Time_Set\r
+//  106        do{ \r
+//  107        }while(Time_Left(TIMER_GEN));\r
+??PWM_Start_0:\r
+        LDI     R16, 2\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??PWM_Start_0\r
+//  108        \r
+//  109        // Now wait for PLL to lock.\r
+//  110        do{ \r
+//  111        }while((PLLCSR & (1<<PLOCK)) == 0);\r
+??PWM_Start_1:\r
+        IN      R16, 0x29\r
+        SBRS    R16, 0\r
+        RJMP    ??PWM_Start_1\r
+//  112 \r
+//  113        // Use PLL as clock source.\r
+//  114        PLLCSR |= (1<<PCKE);\r
+        IN      R16, 0x29\r
+        ORI     R16, 0x04\r
+        OUT     0x29, R16\r
+//  115        \r
+//  116        // CLK PCK = 64MHz / 1 = 64MHz.\r
+//  117        TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
+        IN      R16, 0x2F\r
+        ORI     R16, 0x01\r
+        OUT     0x2F, R16\r
+//  118 }\r
+        RET\r
+        REQUIRE _A_TCCR1A\r
+        REQUIRE _A_TCCR1B\r
+        REQUIRE _A_OCR1A\r
+        REQUIRE _A_OCR1B\r
+        REQUIRE _A_OCR1C\r
+        REQUIRE _A_OCR1D\r
+        REQUIRE _A_PLLCSR\r
+        REQUIRE _A_TCCR1C\r
+        REQUIRE _A_TCCR1D\r
+        REQUIRE _A_DT1\r
+        REQUIRE _A_DDRB\r
+        REQUIRE _A_TCCR1E\r
+//  119 \r
+//  120 \r
+//  121 /*! \brief Increments the PWM duty cycle, if not already at max\r
+//  122  *\r
+//  123  * \retval TRUE Success, duty cycle could be incremented.\r
+//  124  * \retval FALSE Failure, duty cycle already at maximum.\r
+//  125  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  126 unsigned char PWM_IncrementDutyCycle(void){\r
+PWM_IncrementDutyCycle:\r
+//  127 \r
+//  128        if (OCR1B < PWM_MAX) {\r
+        IN      R16, 0x2C\r
+        CPI     R16, 255\r
+        BREQ    ??PWM_IncrementDutyCycle_0\r
+//  129                OCR1B += 1;\r
+        IN      R16, 0x2C\r
+        INC     R16\r
+        OUT     0x2C, R16\r
+//  130                return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//  131        } else {\r
+//  132                return(FALSE);\r
+??PWM_IncrementDutyCycle_0:\r
+        LDI     R16, 0\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  133        }\r
+//  134 }\r
+//  135 \r
+//  136 \r
+//  137 /*! \brief Decrements the PWM duty cycle, if not already at zero.\r
+//  138  *\r
+//  139  * \retval TRUE Success, duty cycle could be decremented.\r
+//  140  * \retval FALSE Failure, duty cycle already at zero.\r
+//  141  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  142 unsigned char PWM_DecrementDutyCycle(void){\r
+PWM_DecrementDutyCycle:\r
+//  143        \r
+//  144        if (OCR1B > 0)  {\r
+        IN      R16, 0x2C\r
+        TST     R16\r
+        BREQ    ??PWM_DecrementDutyCycle_0\r
+//  145                OCR1B -= 1;\r
+        IN      R16, 0x2C\r
+        DEC     R16\r
+        OUT     0x2C, R16\r
+//  146                return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//  147        } else {\r
+//  148                return(FALSE);\r
+??PWM_DecrementDutyCycle_0:\r
+        LDI     R16, 0\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  149        }\r
+//  150 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+// \r
+//  12 bytes in segment ABSOLUTE\r
+// 142 bytes in segment CODE\r
+// \r
+// 142 bytes of CODE memory\r
+//   0 bytes of DATA memory (+ 12 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/USI.lst b/BaseTinyFirmware/IAR/Release/List/USI.lst
new file mode 100644 (file)
index 0000000..749b2f7
--- /dev/null
@@ -0,0 +1,713 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:02 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\USI.c           #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\USI.c           #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\US #\r
+#                             I.lst                                           #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI #\r
+#                             .r90                                            #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\USI.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for use of the Universal Serial Interface\r
+      6           *\r
+      7           *      Contains high level functions for initializing the USI as an SPI slave,\r
+      8           *      interrupt handling, sending and receiving single bytes.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13           *\r
+     14           * \par Documentation:\r
+     15           *      For comprehensive code documentation, supported compilers, compiler\r
+     16           *      settings and supported devices see readme.html\r
+     17           *\r
+     18           * \author\r
+     19           *      Atmel Corporation: http://www.atmel.com \n\r
+     20           *      Support email: avr@atmel.com \n\r
+     21           *      Original author: \n\r
+     22           *\r
+     23           * $Name$\r
+     24           * $Revision: 2299 $\r
+     25           * $RCSfile$\r
+     26           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
+     27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     28           ******************************************************************************/\r
+     29          \r
+     30          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x38\r
+   \   <unnamed> volatile __io _A_PORTB\r
+   \                     _A_PORTB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x37\r
+   \   <unnamed> volatile __io _A_DDRB\r
+   \                     _A_DDRB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x2f\r
+   \   <unnamed> volatile __io _A_USIDR\r
+   \                     _A_USIDR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x2e\r
+   \   <unnamed> volatile __io _A_USISR\r
+   \                     _A_USISR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x2d\r
+   \   <unnamed> volatile __io _A_USICR\r
+   \                     _A_USICR:\r
+   \   00000000                      DS 1\r
+     31          #include <inavr.h>\r
+     32          \r
+     33          #include "enums.h"\r
+     34          #include "structs.h"\r
+     35          \r
+     36          #include "main.h"\r
+     37          #include "ADC.h"\r
+     38          #include "battery.h"\r
+     39          #include "time.h"\r
+     40          #include "USI.h"\r
+     41          \r
+     42          \r
+     43          //******************************************************************************\r
+     44          // Variables\r
+     45          //******************************************************************************\r
+     46          //! SPI status struct\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     47          SPI_Status_t SPI;\r
+   \                     SPI:\r
+   \   00000000                      DS 4\r
+     48          \r
+     49          \r
+     50          //******************************************************************************\r
+     51          //Functions\r
+     52          //*****************************************************************************\r
+     53          /*! \brief USI Counter Overflow Interrupt Service Routine\r
+     54           *\r
+     55           * When the USI counter overflows, a byte has been transferred.\n\r
+     56           * The USIDR contents are stored and flags are updated.\r
+     57           *\r
+     58           * The protocol is quite simple and has three sequential states: command,\r
+     59           * address and data.\r
+     60           * (Keep in mind that the Master is in charge of data clocking, which means\r
+     61           * there is a one byte "delay" from when the Slave puts something to SPI till\r
+     62           * the Master can read it.)\r
+     63           *\r
+     64           * 1. If a non-zero byte is received in the command state, the ISR will\r
+     65           * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
+     66           * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
+     67           * If a zero byte (0x00) is received in the command state, it is simply ignored\r
+     68           * because it is an invalid command.\r
+     69           *\r
+     70           * 2. When a byte is received in the address state, it is stored to the SPI\r
+     71           * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
+     72           * \r
+     73           * 3. In the data state, variables are read/written "from back to front" until\r
+     74           * the byte counter reaches zero. Since the Master is in charge of the data\r
+     75           * clocking, the Slave will go to command state before the last byte is\r
+     76           * transferred during reading. This means that the Master should send an \r
+     77           * invalid command when getting each byte, ie 0x00.\r
+     78           *\r
+     79           * If the time between two transfers is 1 second or more, the Slave\r
+     80           * automatically reverts to command state.\r
+     81           *\r
+     82           * \note Battery charging is not automatically halted during SPI communication.\r
+     83           * This means that the current charge state (current and voltage) will\r
+     84           * remain constant during heavy and prolonged serial traffic.\r
+     85           *\r
+     86           * \todo Variable writing not implemented yet.\r
+     87           * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
+     88           */\r
+     89          #pragma vector=USI_OVF_vect\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     90          __interrupt void USI_OVF_ISR(void)\r
+   \                     USI_OVF_ISR:\r
+     91          {\r
+   \   00000000   938A               ST      -Y, R24\r
+   \   00000002   93FA               ST      -Y, R31\r
+   \   00000004   93EA               ST      -Y, R30\r
+   \   00000006   923A               ST      -Y, R3\r
+   \   00000008   922A               ST      -Y, R2\r
+   \   0000000A   921A               ST      -Y, R1\r
+   \   0000000C   920A               ST      -Y, R0\r
+   \   0000000E   937A               ST      -Y, R23\r
+   \   00000010   936A               ST      -Y, R22\r
+   \   00000012   935A               ST      -Y, R21\r
+   \   00000014   934A               ST      -Y, R20\r
+   \   00000016   933A               ST      -Y, R19\r
+   \   00000018   932A               ST      -Y, R18\r
+   \   0000001A   931A               ST      -Y, R17\r
+   \   0000001C   930A               ST      -Y, R16\r
+   \   0000001E   B78F               IN      R24, 0x3F\r
+     92                // If the communication timed out, set ST_CMD as current state.\r
+     93                if (!Time_Left(TIMER_USI)) {\r
+   \   00000020   E000               LDI     R16, 0\r
+   \   00000022   ....               RCALL   Time_Left\r
+   \   00000024   2300               TST     R16\r
+   \   00000026   F431               BRNE    ??USI_OVF_ISR_0\r
+     94                        SPI.State = ST_CMD;\r
+   \   00000028   ....               LDI     R30, LOW(SPI)\r
+   \   0000002A   ....               LDI     R31, (SPI) >> 8\r
+   \   0000002C   8102               LDD     R16, Z+2\r
+   \   0000002E   730F               ANDI    R16, 0x3F\r
+   \   00000030   6400               ORI     R16, 0x40\r
+   \   00000032   8302               STD     Z+2, R16\r
+     95                }\r
+     96          \r
+     97                // Start communication timer. If further communication doesn't happen\r
+     98                // within 1 second, the SPI communication state is reset to CMD.\r
+     99                Time_Set(TIMER_USI, 0, 1, 0);\r
+   \                     ??USI_OVF_ISR_0:\r
+   \   00000034   E040               LDI     R20, 0\r
+   \   00000036   E011               LDI     R17, 1\r
+   \   00000038   E020               LDI     R18, 0\r
+   \   0000003A   E030               LDI     R19, 0\r
+   \   0000003C   E000               LDI     R16, 0\r
+   \   0000003E   ....               RCALL   Time_Set\r
+    100                \r
+    101                // Clear USI counter and flag completed transfer.\r
+    102                USISR = (1<<USIOIF);\r
+   \   00000040   E400               LDI     R16, 64\r
+   \   00000042   B90E               OUT     0x0E, R16\r
+    103                SPI.XferComplete = TRUE;\r
+   \   00000044   ....               LDI     R30, LOW(SPI)\r
+   \   00000046   ....               LDI     R31, (SPI) >> 8\r
+   \   00000048   8103               LDD     R16, Z+3\r
+   \   0000004A   6004               ORI     R16, 0x04\r
+   \   0000004C   8303               STD     Z+3, R16\r
+    104                \r
+    105                // Process incoming data.\r
+    106                switch(SPI.State)       {\r
+   \   0000004E   8112               LDD     R17, Z+2\r
+   \   00000050   2F01               MOV     R16, R17\r
+   \   00000052   0F00               LSL     R16\r
+   \   00000054   1F00               ROL     R16\r
+   \   00000056   1F00               ROL     R16\r
+   \   00000058   7003               ANDI    R16, 0x03\r
+   \   0000005A   5001               SUBI    R16, 1\r
+   \   0000005C   F029               BREQ    ??USI_OVF_ISR_1\r
+   \   0000005E   950A               DEC     R16\r
+   \   00000060   F101               BREQ    ??USI_OVF_ISR_2\r
+   \   00000062   950A               DEC     R16\r
+   \   00000064   F131               BREQ    ??USI_OVF_ISR_3\r
+   \   00000066   C072               RJMP    ??USI_OVF_ISR_4\r
+    107                // A valid SPI transfer starts with a Command Byte sent by the Master.\r
+    108                case ST_CMD:   \r
+    109                        SPI.Data = USIDR;  // Store the transferred byte.\r
+   \                     ??USI_OVF_ISR_1:\r
+   \   00000068   B10F               IN      R16, 0x0F\r
+   \   0000006A   8300               ST      Z, R16\r
+    110                        \r
+    111                        // If the master sent 0, it is trying to get data. Ignore in this state.\r
+    112                        if (SPI.Data != 0) {\r
+   \   0000006C   2300               TST     R16\r
+   \   0000006E   F409               BRNE    $+2+2\r
+   \   00000070   C06D               RJMP    ??USI_OVF_ISR_4\r
+    113                                // Does the master want to read or write?\r
+    114                                if (SPI.Data & 0x40) {\r
+   \   00000072   FF06               SBRS    R16, 6\r
+   \   00000074   C003               RJMP    ??USI_OVF_ISR_5\r
+    115                                        SPI.Read = FALSE;\r
+   \   00000076   8103               LDD     R16, Z+3\r
+   \   00000078   7F0E               ANDI    R16, 0xFE\r
+   \   0000007A   C002               RJMP    ??USI_OVF_ISR_6\r
+    116                                } else {\r
+    117                                        SPI.Read = TRUE;\r
+   \                     ??USI_OVF_ISR_5:\r
+   \   0000007C   8103               LDD     R16, Z+3\r
+   \   0000007E   6001               ORI     R16, 0x01\r
+   \                     ??USI_OVF_ISR_6:\r
+   \   00000080   8303               STD     Z+3, R16\r
+    118                                }\r
+    119          \r
+    120                                        // From/to EEPROM or SRAM?\r
+    121                                if (SPI.Data &0x80) {\r
+   \   00000082   8100               LD      R16, Z\r
+   \   00000084   FF07               SBRS    R16, 7\r
+   \   00000086   C003               RJMP    ??USI_OVF_ISR_7\r
+    122                                        SPI.EEPROM = TRUE;\r
+   \   00000088   8103               LDD     R16, Z+3\r
+   \   0000008A   6002               ORI     R16, 0x02\r
+   \   0000008C   C002               RJMP    ??USI_OVF_ISR_8\r
+    123                                } else {\r
+    124                                        SPI.EEPROM = FALSE;\r
+   \                     ??USI_OVF_ISR_7:\r
+   \   0000008E   8103               LDD     R16, Z+3\r
+   \   00000090   7F0D               ANDI    R16, 0xFD\r
+   \                     ??USI_OVF_ISR_8:\r
+   \   00000092   8303               STD     Z+3, R16\r
+    125                                }\r
+    126          \r
+    127                                SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
+    128                                SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
+   \   00000094   8100               LD      R16, Z\r
+   \   00000096   730F               ANDI    R16, 0x3F\r
+   \   00000098   6800               ORI     R16, 0x80\r
+   \   0000009A   8302               STD     Z+2, R16\r
+    129          \r
+    130                                SPI_Put(0xCC);  // Signal that command was received.\r
+   \   0000009C   EC0C               LDI     R16, 204\r
+   \                     ??USI_OVF_ISR_9:\r
+   \   0000009E   ....               RCALL   SPI_Put\r
+   \   000000A0   C055               RJMP    ??USI_OVF_ISR_4\r
+    131                        }\r
+    132                break;\r
+    133          \r
+    134                                \r
+    135                case ST_ADDR:  \r
+    136                        SPI.Data = USIDR;  // Store the address.\r
+   \                     ??USI_OVF_ISR_2:\r
+   \   000000A2   B10F               IN      R16, 0x0F\r
+   \   000000A4   8300               ST      Z, R16\r
+    137                        SPI.Address = SPI.Data;\r
+   \   000000A6   8301               STD     Z+1, R16\r
+    138                        SPI.State = ST_DATA;  // The master will send/wait for data next.\r
+   \   000000A8   2F01               MOV     R16, R17\r
+   \   000000AA   6C00               ORI     R16, 0xC0\r
+   \   000000AC   8302               STD     Z+2, R16\r
+    139          \r
+    140                        SPI_Put(0xBB);  // Signal that address was received.\r
+   \   000000AE   EB0B               LDI     R16, 187\r
+   \   000000B0   CFF6               RJMP    ??USI_OVF_ISR_9\r
+    141                break;\r
+    142          \r
+    143          \r
+    144                // Note well: this will process at least one byte, regardless of Count.\r
+    145                case ST_DATA:\r
+    146                        if (SPI.Count-- > 0) {\r
+   \                     ??USI_OVF_ISR_3:\r
+   \   000000B2   2F21               MOV     R18, R17\r
+   \   000000B4   7C10               ANDI    R17, 0xC0\r
+   \   000000B6   2F02               MOV     R16, R18\r
+   \   000000B8   950A               DEC     R16\r
+   \   000000BA   730F               ANDI    R16, 0x3F\r
+   \   000000BC   2B01               OR      R16, R17\r
+   \   000000BE   8302               STD     Z+2, R16\r
+   \   000000C0   732F               ANDI    R18, 0x3F\r
+   \   000000C2   F409               BRNE    $+2+2\r
+   \   000000C4   C040               RJMP    ??USI_OVF_ISR_10\r
+    147                                // Write specified variable to SPI, "back to front".\r
+    148                                if (SPI.Read) {\r
+   \   000000C6   8121               LDD     R18, Z+1\r
+   \   000000C8   8113               LDD     R17, Z+3\r
+   \   000000CA   FF10               SBRS    R17, 0\r
+   \   000000CC   C02E               RJMP    ??USI_OVF_ISR_11\r
+    149                                        switch (SPI.Address) {\r
+   \   000000CE   952A               DEC     R18\r
+   \   000000D0   F049               BREQ    ??USI_OVF_ISR_12\r
+   \   000000D2   952A               DEC     R18\r
+   \   000000D4   F071               BREQ    ??USI_OVF_ISR_13\r
+   \   000000D6   952A               DEC     R18\r
+   \   000000D8   F091               BREQ    ??USI_OVF_ISR_14\r
+   \   000000DA   952A               DEC     R18\r
+   \   000000DC   F0B1               BREQ    ??USI_OVF_ISR_15\r
+   \   000000DE   952A               DEC     R18\r
+   \   000000E0   F0E1               BREQ    ??USI_OVF_ISR_16\r
+   \   000000E2   C021               RJMP    ??USI_OVF_ISR_17\r
+    150                                        case ADR_ADCS:\r
+    151                                                SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_12:\r
+   \   000000E4   730F               ANDI    R16, 0x3F\r
+   \   000000E6   E010               LDI     R17, 0\r
+   \   000000E8   01F8               MOVW    R31:R30, R17:R16\r
+   \   000000EA   ....               SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+   \   000000EC   ....               SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+   \                     ??USI_OVF_ISR_18:\r
+   \   000000EE   8100               LD      R16, Z\r
+   \   000000F0   CFD6               RJMP    ??USI_OVF_ISR_9\r
+    152                                        break;\r
+    153                                        \r
+    154                                        \r
+    155                                        case ADR_BATTACTIVE:\r
+    156                                                SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_13:\r
+   \   000000F2   730F               ANDI    R16, 0x3F\r
+   \   000000F4   E010               LDI     R17, 0\r
+   \   000000F6   01F8               MOVW    R31:R30, R17:R16\r
+   \   000000F8   ....               SUBI    R30, LOW((-(BattActive) & 0xFFFF))\r
+   \   000000FA   ....               SBCI    R31, (-(BattActive) & 0xFFFF) >> 8\r
+   \   000000FC   CFF8               RJMP    ??USI_OVF_ISR_18\r
+    157                                        break;\r
+    158                                        \r
+    159                                        \r
+    160                                        case ADR_BATTDATA:\r
+    161                                                SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_14:\r
+   \   000000FE   730F               ANDI    R16, 0x3F\r
+   \   00000100   E010               LDI     R17, 0\r
+   \   00000102   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000104   ....               SUBI    R30, LOW((-(BattData) & 0xFFFF))\r
+   \   00000106   ....               SBCI    R31, (-(BattData) & 0xFFFF) >> 8\r
+   \   00000108   CFF2               RJMP    ??USI_OVF_ISR_18\r
+    162                                        break;\r
+    163                                        \r
+    164                                        \r
+    165                                        case ADR_BATTCTRL:\r
+    166                                                SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_15:\r
+   \   0000010A   730F               ANDI    R16, 0x3F\r
+   \   0000010C   E010               LDI     R17, 0\r
+   \   0000010E   ....               LDI     R20, LOW(BattControl)\r
+   \   00000110   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000112   0F40               ADD     R20, R16\r
+   \   00000114   1F51               ADC     R21, R17\r
+   \   00000116   ....               RCALL   __eeget8_16\r
+   \   00000118   CFC2               RJMP    ??USI_OVF_ISR_9\r
+    167                                        break;\r
+    168                                        \r
+    169                                        case ADR_TIMERS:\r
+    170                                                SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
+   \                     ??USI_OVF_ISR_16:\r
+   \   0000011A   730F               ANDI    R16, 0x3F\r
+   \   0000011C   E010               LDI     R17, 0\r
+   \   0000011E   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000120   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   00000122   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000124   CFE4               RJMP    ??USI_OVF_ISR_18\r
+    171                                        break;\r
+    172          \r
+    173                                        \r
+    174                                        default:\r
+    175                                                SPI_Put(0);\r
+   \                     ??USI_OVF_ISR_17:\r
+   \   00000126   E000               LDI     R16, 0\r
+   \   00000128   CFBA               RJMP    ??USI_OVF_ISR_9\r
+    176                                        break;\r
+    177                                        }\r
+    178                                } else {\r
+    179                                        // Read byte from SPI\r
+    180                                        SPI.Data = USIDR;\r
+   \                     ??USI_OVF_ISR_11:\r
+   \   0000012A   B11F               IN      R17, 0x0F\r
+   \   0000012C   8310               ST      Z, R17\r
+    181          \r
+    182                                        // ********************************************\r
+    183                                        // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
+    184                                        // ********************************************\r
+    185                                                                        \r
+    186                                        // Save byte to specified variable.\r
+    187                                        switch (SPI.Address) {\r
+   \   0000012E   5024               SUBI    R18, 4\r
+   \   00000130   F469               BRNE    ??USI_OVF_ISR_4\r
+    188                                        case ADR_BATTCTRL:\r
+    189                                                *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
+   \   00000132   2F21               MOV     R18, R17\r
+   \   00000134   730F               ANDI    R16, 0x3F\r
+   \   00000136   E010               LDI     R17, 0\r
+   \   00000138   ....               LDI     R20, LOW(BattControl)\r
+   \   0000013A   ....               LDI     R21, (BattControl) >> 8\r
+   \   0000013C   0F40               ADD     R20, R16\r
+   \   0000013E   1F51               ADC     R21, R17\r
+   \   00000140   2F02               MOV     R16, R18\r
+   \   00000142   ....               RCALL   __eeput8_16\r
+   \   00000144   C003               RJMP    ??USI_OVF_ISR_4\r
+    190                                        break;\r
+    191          \r
+    192                                        \r
+    193                                        default:\r
+    194                                        break;\r
+    195                                        }\r
+    196                                }\r
+    197                                \r
+    198          \r
+    199                        } else {\r
+    200                                SPI.State = ST_CMD;\r
+   \                     ??USI_OVF_ISR_10:\r
+   \   00000146   730F               ANDI    R16, 0x3F\r
+   \   00000148   6400               ORI     R16, 0x40\r
+   \   0000014A   8302               STD     Z+2, R16\r
+    201                        }\r
+    202                break;\r
+    203          \r
+    204                default:  // Shouldn't end up here. (Unknown SPI-state)\r
+    205                break;\r
+    206                }\r
+    207          }\r
+   \                     ??USI_OVF_ISR_4:\r
+   \   0000014C   BF8F               OUT     0x3F, R24\r
+   \   0000014E   9109               LD      R16, Y+\r
+   \   00000150   9119               LD      R17, Y+\r
+   \   00000152   9129               LD      R18, Y+\r
+   \   00000154   9139               LD      R19, Y+\r
+   \   00000156   9149               LD      R20, Y+\r
+   \   00000158   9159               LD      R21, Y+\r
+   \   0000015A   9169               LD      R22, Y+\r
+   \   0000015C   9179               LD      R23, Y+\r
+   \   0000015E   9009               LD      R0, Y+\r
+   \   00000160   9019               LD      R1, Y+\r
+   \   00000162   9029               LD      R2, Y+\r
+   \   00000164   9039               LD      R3, Y+\r
+   \   00000166   91E9               LD      R30, Y+\r
+   \   00000168   91F9               LD      R31, Y+\r
+   \   0000016A   9189               LD      R24, Y+\r
+   \   0000016C   9518               RETI\r
+   \   0000016E                      REQUIRE _A_USIDR\r
+   \   0000016E                      REQUIRE _A_USISR\r
+    208          \r
+    209          \r
+    210          /*! \brief Initializes USI as an SPI slave\r
+    211           *\r
+    212           * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
+    213           * I/O and clock, and USI counter overflow interrupts enabled.\n\r
+    214           * Also initializes the SPI status struct.\r
+    215           * \r
+    216           * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
+    217           * (1) edge of clock signal\r
+    218           *\r
+    219           * \note Clears the stored data\r
+    220           *\r
+    221           * \todo Timer should reset SPI protocol on timeout\r
+    222           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    223          void SPI_Init(unsigned char spi_mode)\r
+   \                     SPI_Init:\r
+    224          {\r
+    225                __disable_interrupt();\r
+   \   00000000   94F8               CLI\r
+    226                \r
+    227                // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
+    228                USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
+   \   00000002   9AB9               SBI     0x17, 0x01\r
+    229                USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
+   \   00000004   B317               IN      R17, 0x17\r
+   \   00000006   7F1A               ANDI    R17, 0xFA\r
+   \   00000008   BB17               OUT     0x17, R17\r
+    230                USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
+   \   0000000A   B318               IN      R17, 0x18\r
+   \   0000000C   6015               ORI     R17, 0x05\r
+   \   0000000E   BB18               OUT     0x18, R17\r
+    231                \r
+    232                // Configure USI to 3-wire slave mode with overflow interrupt\r
+    233                USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
+   \   00000010   0F00               LSL     R16\r
+   \   00000012   0F00               LSL     R16\r
+   \   00000014   6508               ORI     R16, 0x58\r
+   \   00000016   B90D               OUT     0x0D, R16\r
+    234          \r
+    235                // Initialize the SPI struct\r
+    236                SPI.Data = 0;                 // Clear data.\r
+   \   00000018   ....               LDI     R30, LOW(SPI)\r
+   \   0000001A   ....               LDI     R31, (SPI) >> 8\r
+   \   0000001C   E000               LDI     R16, 0\r
+   \   0000001E   8300               ST      Z, R16\r
+    237                SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
+    238                SPI.Read = FALSE;             // Doesn't matter right now.\r
+    239                SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
+   \   00000020   8103               LDD     R16, Z+3\r
+   \   00000022   7F0C               ANDI    R16, 0xFC\r
+   \   00000024   8303               STD     Z+3, R16\r
+    240                SPI.Count = 0;                // Doesn't matter right now.\r
+   \   00000026   E400               LDI     R16, 64\r
+   \   00000028   8302               STD     Z+2, R16\r
+    241                SPI.Address = 0;              // Doesn't matter right now.\r
+   \   0000002A   E000               LDI     R16, 0\r
+   \   0000002C   8301               STD     Z+1, R16\r
+    242                SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
+    243                SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
+   \   0000002E   8103               LDD     R16, Z+3\r
+   \   00000030   7F03               ANDI    R16, 0xF3\r
+   \   00000032   8303               STD     Z+3, R16\r
+    244          \r
+    245                __enable_interrupt();\r
+   \   00000034   9478               SEI\r
+    246          }\r
+   \   00000036   9508               RET\r
+   \   00000038                      REQUIRE _A_PORTB\r
+   \   00000038                      REQUIRE _A_DDRB\r
+   \   00000038                      REQUIRE _A_USICR\r
+    247          \r
+    248          \r
+    249          // Put one byte on bus. Use this function like you would write to the SPDR\r
+    250          // register in the native SPI module. Calling this function will prepare a\r
+    251          // byte for the next transfer initiated by the master device. If a transfer\r
+    252          // is in progress, this function will set the write collision flag and return\r
+    253          // without altering the data registers.\r
+    254          //\r
+    255          // Returns 0 if a write collision occurred, 1 otherwise.\r
+    256          /*! \brief Write a byte to SPI bus\r
+    257           *\r
+    258           * This function first checks if a transmission is in progress, and if so, flags\r
+    259           * a write collision, and returns FALSE.\n\r
+    260           * If a transmission is not in progress, the flags for write collision and\r
+    261           * transfer complete are cleared, and the input byte is written to SPDR.\n\r
+    262           *\r
+    263           * \param val The byte to send.\r
+    264           *\r
+    265           * \retval FALSE A write collision happened.\r
+    266           * \retval TRUE Byte written to SPDR.\r
+    267           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    268          unsigned char SPI_Put(unsigned char val)\r
+   \                     SPI_Put:\r
+    269          {\r
+    270                // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
+    271                // If this fails, flag a write collision and return.\r
+    272                if((USISR & 0x0F) != 0) {\r
+   \   00000000   B11E               IN      R17, 0x0E\r
+   \   00000002   701F               ANDI    R17, 0x0F\r
+   \   00000004   ....               LDI     R30, LOW(SPI)\r
+   \   00000006   ....               LDI     R31, (SPI) >> 8\r
+   \   00000008   F029               BREQ    ??SPI_Put_0\r
+    273                        SPI.WriteCollision = TRUE;\r
+   \   0000000A   8103               LDD     R16, Z+3\r
+   \   0000000C   6008               ORI     R16, 0x08\r
+   \   0000000E   8303               STD     Z+3, R16\r
+    274                        return(FALSE);\r
+   \   00000010   E000               LDI     R16, 0\r
+   \   00000012   9508               RET\r
+    275                }\r
+    276          \r
+    277                // Reinitialize flags.\r
+    278                SPI.XferComplete = FALSE;\r
+    279                SPI.WriteCollision = FALSE;\r
+   \                     ??SPI_Put_0:\r
+   \   00000014   8113               LDD     R17, Z+3\r
+   \   00000016   7F13               ANDI    R17, 0xF3\r
+   \   00000018   8313               STD     Z+3, R17\r
+    280          \r
+    281                USIDR = val;  // Put data in USI data register.\r
+   \   0000001A   B90F               OUT     0x0F, R16\r
+    282          \r
+    283                return (TRUE);\r
+   \   0000001C   E001               LDI     R16, 1\r
+   \   0000001E   9508               RET\r
+   \   00000020                      REQUIRE _A_USIDR\r
+   \   00000020                      REQUIRE _A_USISR\r
+    284          }\r
+    285          \r
+    286          \r
+    287          // Get one byte from bus. This function only returns the previous stored\r
+    288          // USIDR value. The transfer complete flag is not checked. Use this function\r
+    289          // like you would read from the SPDR register in the native SPI module.\r
+    290          /*! \brief Get the last byte received from SPI bus\r
+    291           *\r
+    292           * This function simply returns the last byte stored to the SPI status struct,\r
+    293           * without checking if a completed transfer is flagged.\r
+    294           *\r
+    295           * \retval SPI.Data The last byte read from SPI.\r
+    296           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    297          unsigned char SPI_Get(void)\r
+   \                     SPI_Get:\r
+    298          {\r
+    299                return SPI.Data;\r
+   \   00000000   9100....           LDS     R16, SPI\r
+   \   00000004   9508               RET\r
+    300          }\r
+    301          \r
+    302          \r
+    303          /*! \brief Wait for SPI transfer to complete\r
+    304           *\r
+    305           * This function waits for a transfer complete to be flagged.\r
+    306           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    307          void SPI_Wait(void)\r
+   \                     SPI_Wait:\r
+    308          {\r
+   \   00000000   9100....           LDS     R16, (SPI + 3)\r
+   \   00000004   FF02               SBRS    R16, 2\r
+    309                do {  // Wait for transfer complete.\r
+    310                } while (SPI.XferComplete == FALSE);\r
+   \                     ??SPI_Wait_0:\r
+   \   00000006   CFFF               RJMP    ??SPI_Wait_0\r
+    311          }\r
+   \                     ??SPI_Wait_1:\r
+   \   00000008   9508               RET\r
+\r
+   \                                 In  segment INTVEC, offset 0x10, root\r
+   \                     `??USI_OVF_ISR??INTVEC 16`:\r
+   \   00000010   ....               RJMP    USI_OVF_ISR\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function       CSTACK RSTACK\r
+     --------       ------ ------\r
+     SPI_Get            0      2\r
+     SPI_Init           0      2\r
+     SPI_Put            0      2\r
+     SPI_Wait           0      2\r
+     USI_OVF_ISR       15      4\r
+       -> Time_Left    15      2\r
+       -> Time_Set     15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+       -> SPI_Put      15      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label           Bytes\r
+     --------------           -----\r
+     _A_PORTB                    1\r
+     _A_DDRB                     1\r
+     _A_USIDR                    1\r
+     _A_USISR                    1\r
+     _A_USICR                    1\r
+     SPI                         4\r
+     USI_OVF_ISR               366\r
+     SPI_Init                   56\r
+     SPI_Put                    32\r
+     SPI_Get                     6\r
+     SPI_Wait                   10\r
+     ??USI_OVF_ISR??INTVEC 16    2\r
+      Others                     6\r
+\r
\r
+   5 bytes in segment ABSOLUTE\r
+ 470 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment INTVEC\r
+   4 bytes in segment NEAR_Z\r
\r
+ 470 bytes of CODE memory (+ 8 bytes shared)\r
+   4 bytes of DATA memory (+ 5 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/USI.s90 b/BaseTinyFirmware/IAR/Release/List/USI.s90
new file mode 100644 (file)
index 0000000..ae4ae09
--- /dev/null
@@ -0,0 +1,731 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:02 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\USI.c          /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\USI.c          /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\U /\r
+//                             SI.s90                                         /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME USI\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBWEAK `??USI_OVF_ISR??INTVEC 16`\r
+        PUBLIC SPI\r
+        PUBLIC SPI_Get\r
+        PUBLIC SPI_Init\r
+        PUBLIC SPI_Put\r
+        PUBLIC SPI_Wait\r
+        PUBLIC USI_OVF_ISR\r
+        PUBWEAK _A_DDRB\r
+        PUBWEAK _A_PORTB\r
+        PUBWEAK _A_USICR\r
+        PUBWEAK _A_USIDR\r
+        PUBWEAK _A_USISR\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+USI_OVF_ISR         SYMBOL "USI_OVF_ISR"\r
+`??USI_OVF_ISR??INTVEC 16` SYMBOL "??INTVEC 16", USI_OVF_ISR\r
+\r
+        EXTERN Time_Left\r
+        EXTERN Time_Set\r
+        EXTERN ADCS\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+        EXTERN timeval\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\USI.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for use of the Universal Serial Interface\r
+//    6  *\r
+//    7  *      Contains high level functions for initializing the USI as an SPI slave,\r
+//    8  *      interrupt handling, sending and receiving single bytes.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13  *\r
+//   14  * \par Documentation:\r
+//   15  *      For comprehensive code documentation, supported compilers, compiler\r
+//   16  *      settings and supported devices see readme.html\r
+//   17  *\r
+//   18  * \author\r
+//   19  *      Atmel Corporation: http://www.atmel.com \n\r
+//   20  *      Support email: avr@atmel.com \n\r
+//   21  *      Original author: \n\r
+//   22  *\r
+//   23  * $Name$\r
+//   24  * $Revision: 2299 $\r
+//   25  * $RCSfile$\r
+//   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
+//   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   28  ******************************************************************************/\r
+//   29 \r
+//   30 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,038H\r
+// <unnamed> volatile __io _A_PORTB\r
+_A_PORTB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,037H\r
+// <unnamed> volatile __io _A_DDRB\r
+_A_DDRB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,02fH\r
+// <unnamed> volatile __io _A_USIDR\r
+_A_USIDR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,02eH\r
+// <unnamed> volatile __io _A_USISR\r
+_A_USISR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,02dH\r
+// <unnamed> volatile __io _A_USICR\r
+_A_USICR:\r
+        DS 1\r
+//   31 #include <inavr.h>\r
+//   32 \r
+//   33 #include "enums.h"\r
+//   34 #include "structs.h"\r
+//   35 \r
+//   36 #include "main.h"\r
+//   37 #include "ADC.h"\r
+//   38 #include "battery.h"\r
+//   39 #include "time.h"\r
+//   40 #include "USI.h"\r
+//   41 \r
+//   42 \r
+//   43 //******************************************************************************\r
+//   44 // Variables\r
+//   45 //******************************************************************************\r
+//   46 //! SPI status struct\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   47 SPI_Status_t SPI;\r
+SPI:\r
+        DS 4\r
+//   48 \r
+//   49 \r
+//   50 //******************************************************************************\r
+//   51 //Functions\r
+//   52 //*****************************************************************************\r
+//   53 /*! \brief USI Counter Overflow Interrupt Service Routine\r
+//   54  *\r
+//   55  * When the USI counter overflows, a byte has been transferred.\n\r
+//   56  * The USIDR contents are stored and flags are updated.\r
+//   57  *\r
+//   58  * The protocol is quite simple and has three sequential states: command,\r
+//   59  * address and data.\r
+//   60  * (Keep in mind that the Master is in charge of data clocking, which means\r
+//   61  * there is a one byte "delay" from when the Slave puts something to SPI till\r
+//   62  * the Master can read it.)\r
+//   63  *\r
+//   64  * 1. If a non-zero byte is received in the command state, the ISR will\r
+//   65  * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
+//   66  * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
+//   67  * If a zero byte (0x00) is received in the command state, it is simply ignored\r
+//   68  * because it is an invalid command.\r
+//   69  *\r
+//   70  * 2. When a byte is received in the address state, it is stored to the SPI\r
+//   71  * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
+//   72  * \r
+//   73  * 3. In the data state, variables are read/written "from back to front" until\r
+//   74  * the byte counter reaches zero. Since the Master is in charge of the data\r
+//   75  * clocking, the Slave will go to command state before the last byte is\r
+//   76  * transferred during reading. This means that the Master should send an \r
+//   77  * invalid command when getting each byte, ie 0x00.\r
+//   78  *\r
+//   79  * If the time between two transfers is 1 second or more, the Slave\r
+//   80  * automatically reverts to command state.\r
+//   81  *\r
+//   82  * \note Battery charging is not automatically halted during SPI communication.\r
+//   83  * This means that the current charge state (current and voltage) will\r
+//   84  * remain constant during heavy and prolonged serial traffic.\r
+//   85  *\r
+//   86  * \todo Variable writing not implemented yet.\r
+//   87  * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
+//   88  */\r
+//   89 #pragma vector=USI_OVF_vect\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   90 __interrupt void USI_OVF_ISR(void)\r
+USI_OVF_ISR:\r
+//   91 {\r
+        ST      -Y, R24\r
+        ST      -Y, R31\r
+        ST      -Y, R30\r
+        ST      -Y, R3\r
+        ST      -Y, R2\r
+        ST      -Y, R1\r
+        ST      -Y, R0\r
+        ST      -Y, R23\r
+        ST      -Y, R22\r
+        ST      -Y, R21\r
+        ST      -Y, R20\r
+        ST      -Y, R19\r
+        ST      -Y, R18\r
+        ST      -Y, R17\r
+        ST      -Y, R16\r
+        IN      R24, 0x3F\r
+//   92        // If the communication timed out, set ST_CMD as current state.\r
+//   93        if (!Time_Left(TIMER_USI)) {\r
+        LDI     R16, 0\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??USI_OVF_ISR_0\r
+//   94                SPI.State = ST_CMD;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+2\r
+        ANDI    R16, 0x3F\r
+        ORI     R16, 0x40\r
+        STD     Z+2, R16\r
+//   95        }\r
+//   96 \r
+//   97        // Start communication timer. If further communication doesn't happen\r
+//   98        // within 1 second, the SPI communication state is reset to CMD.\r
+//   99        Time_Set(TIMER_USI, 0, 1, 0);\r
+??USI_OVF_ISR_0:\r
+        LDI     R20, 0\r
+        LDI     R17, 1\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 0\r
+        RCALL   Time_Set\r
+//  100        \r
+//  101        // Clear USI counter and flag completed transfer.\r
+//  102        USISR = (1<<USIOIF);\r
+        LDI     R16, 64\r
+        OUT     0x0E, R16\r
+//  103        SPI.XferComplete = TRUE;\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x04\r
+        STD     Z+3, R16\r
+//  104        \r
+//  105        // Process incoming data.\r
+//  106        switch(SPI.State)       {\r
+        LDD     R17, Z+2\r
+        MOV     R16, R17\r
+        LSL     R16\r
+        ROL     R16\r
+        ROL     R16\r
+        ANDI    R16, 0x03\r
+        SUBI    R16, 1\r
+        BREQ    ??USI_OVF_ISR_1\r
+        DEC     R16\r
+        BREQ    ??USI_OVF_ISR_2\r
+        DEC     R16\r
+        BREQ    ??USI_OVF_ISR_3\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  107        // A valid SPI transfer starts with a Command Byte sent by the Master.\r
+//  108        case ST_CMD:   \r
+//  109                SPI.Data = USIDR;  // Store the transferred byte.\r
+??USI_OVF_ISR_1:\r
+        IN      R16, 0x0F\r
+        ST      Z, R16\r
+//  110                \r
+//  111                // If the master sent 0, it is trying to get data. Ignore in this state.\r
+//  112                if (SPI.Data != 0) {\r
+        TST     R16\r
+        BRNE    $+2+2\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  113                        // Does the master want to read or write?\r
+//  114                        if (SPI.Data & 0x40) {\r
+        SBRS    R16, 6\r
+        RJMP    ??USI_OVF_ISR_5\r
+//  115                                SPI.Read = FALSE;\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xFE\r
+        RJMP    ??USI_OVF_ISR_6\r
+//  116                        } else {\r
+//  117                                SPI.Read = TRUE;\r
+??USI_OVF_ISR_5:\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x01\r
+??USI_OVF_ISR_6:\r
+        STD     Z+3, R16\r
+//  118                        }\r
+//  119 \r
+//  120                                // From/to EEPROM or SRAM?\r
+//  121                        if (SPI.Data &0x80) {\r
+        LD      R16, Z\r
+        SBRS    R16, 7\r
+        RJMP    ??USI_OVF_ISR_7\r
+//  122                                SPI.EEPROM = TRUE;\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x02\r
+        RJMP    ??USI_OVF_ISR_8\r
+//  123                        } else {\r
+//  124                                SPI.EEPROM = FALSE;\r
+??USI_OVF_ISR_7:\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xFD\r
+??USI_OVF_ISR_8:\r
+        STD     Z+3, R16\r
+//  125                        }\r
+//  126 \r
+//  127                        SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
+//  128                        SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
+        LD      R16, Z\r
+        ANDI    R16, 0x3F\r
+        ORI     R16, 0x80\r
+        STD     Z+2, R16\r
+//  129 \r
+//  130                        SPI_Put(0xCC);  // Signal that command was received.\r
+        LDI     R16, 204\r
+??USI_OVF_ISR_9:\r
+        RCALL   SPI_Put\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  131                }\r
+//  132        break;\r
+//  133 \r
+//  134                        \r
+//  135        case ST_ADDR:  \r
+//  136                SPI.Data = USIDR;  // Store the address.\r
+??USI_OVF_ISR_2:\r
+        IN      R16, 0x0F\r
+        ST      Z, R16\r
+//  137                SPI.Address = SPI.Data;\r
+        STD     Z+1, R16\r
+//  138                SPI.State = ST_DATA;  // The master will send/wait for data next.\r
+        MOV     R16, R17\r
+        ORI     R16, 0xC0\r
+        STD     Z+2, R16\r
+//  139 \r
+//  140                SPI_Put(0xBB);  // Signal that address was received.\r
+        LDI     R16, 187\r
+        RJMP    ??USI_OVF_ISR_9\r
+//  141        break;\r
+//  142 \r
+//  143 \r
+//  144        // Note well: this will process at least one byte, regardless of Count.\r
+//  145        case ST_DATA:\r
+//  146                if (SPI.Count-- > 0) {\r
+??USI_OVF_ISR_3:\r
+        MOV     R18, R17\r
+        ANDI    R17, 0xC0\r
+        MOV     R16, R18\r
+        DEC     R16\r
+        ANDI    R16, 0x3F\r
+        OR      R16, R17\r
+        STD     Z+2, R16\r
+        ANDI    R18, 0x3F\r
+        BRNE    $+2+2\r
+        RJMP    ??USI_OVF_ISR_10\r
+//  147                        // Write specified variable to SPI, "back to front".\r
+//  148                        if (SPI.Read) {\r
+        LDD     R18, Z+1\r
+        LDD     R17, Z+3\r
+        SBRS    R17, 0\r
+        RJMP    ??USI_OVF_ISR_11\r
+//  149                                switch (SPI.Address) {\r
+        DEC     R18\r
+        BREQ    ??USI_OVF_ISR_12\r
+        DEC     R18\r
+        BREQ    ??USI_OVF_ISR_13\r
+        DEC     R18\r
+        BREQ    ??USI_OVF_ISR_14\r
+        DEC     R18\r
+        BREQ    ??USI_OVF_ISR_15\r
+        DEC     R18\r
+        BREQ    ??USI_OVF_ISR_16\r
+        RJMP    ??USI_OVF_ISR_17\r
+//  150                                case ADR_ADCS:\r
+//  151                                        SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
+??USI_OVF_ISR_12:\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(ADCS) & 0xFFFF))\r
+        SBCI    R31, (-(ADCS) & 0xFFFF) >> 8\r
+??USI_OVF_ISR_18:\r
+        LD      R16, Z\r
+        RJMP    ??USI_OVF_ISR_9\r
+//  152                                break;\r
+//  153                                \r
+//  154                                \r
+//  155                                case ADR_BATTACTIVE:\r
+//  156                                        SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
+??USI_OVF_ISR_13:\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(BattActive) & 0xFFFF))\r
+        SBCI    R31, (-(BattActive) & 0xFFFF) >> 8\r
+        RJMP    ??USI_OVF_ISR_18\r
+//  157                                break;\r
+//  158                                \r
+//  159                                \r
+//  160                                case ADR_BATTDATA:\r
+//  161                                        SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
+??USI_OVF_ISR_14:\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(BattData) & 0xFFFF))\r
+        SBCI    R31, (-(BattData) & 0xFFFF) >> 8\r
+        RJMP    ??USI_OVF_ISR_18\r
+//  162                                break;\r
+//  163                                \r
+//  164                                \r
+//  165                                case ADR_BATTCTRL:\r
+//  166                                        SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
+??USI_OVF_ISR_15:\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        RJMP    ??USI_OVF_ISR_9\r
+//  167                                break;\r
+//  168                                \r
+//  169                                case ADR_TIMERS:\r
+//  170                                        SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
+??USI_OVF_ISR_16:\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        RJMP    ??USI_OVF_ISR_18\r
+//  171                                break;\r
+//  172 \r
+//  173                                \r
+//  174                                default:\r
+//  175                                        SPI_Put(0);\r
+??USI_OVF_ISR_17:\r
+        LDI     R16, 0\r
+        RJMP    ??USI_OVF_ISR_9\r
+//  176                                break;\r
+//  177                                }\r
+//  178                        } else {\r
+//  179                                // Read byte from SPI\r
+//  180                                SPI.Data = USIDR;\r
+??USI_OVF_ISR_11:\r
+        IN      R17, 0x0F\r
+        ST      Z, R17\r
+//  181 \r
+//  182                                // ********************************************\r
+//  183                                // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
+//  184                                // ********************************************\r
+//  185                                                                \r
+//  186                                // Save byte to specified variable.\r
+//  187                                switch (SPI.Address) {\r
+        SUBI    R18, 4\r
+        BRNE    ??USI_OVF_ISR_4\r
+//  188                                case ADR_BATTCTRL:\r
+//  189                                        *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
+        MOV     R18, R17\r
+        ANDI    R16, 0x3F\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        MOV     R16, R18\r
+        RCALL   __eeput8_16\r
+        RJMP    ??USI_OVF_ISR_4\r
+//  190                                break;\r
+//  191 \r
+//  192                                \r
+//  193                                default:\r
+//  194                                break;\r
+//  195                                }\r
+//  196                        }\r
+//  197                        \r
+//  198 \r
+//  199                } else {\r
+//  200                        SPI.State = ST_CMD;\r
+??USI_OVF_ISR_10:\r
+        ANDI    R16, 0x3F\r
+        ORI     R16, 0x40\r
+        STD     Z+2, R16\r
+//  201                }\r
+//  202        break;\r
+//  203 \r
+//  204        default:  // Shouldn't end up here. (Unknown SPI-state)\r
+//  205        break;\r
+//  206        }\r
+//  207 }\r
+??USI_OVF_ISR_4:\r
+        OUT     0x3F, R24\r
+        LD      R16, Y+\r
+        LD      R17, Y+\r
+        LD      R18, Y+\r
+        LD      R19, Y+\r
+        LD      R20, Y+\r
+        LD      R21, Y+\r
+        LD      R22, Y+\r
+        LD      R23, Y+\r
+        LD      R0, Y+\r
+        LD      R1, Y+\r
+        LD      R2, Y+\r
+        LD      R3, Y+\r
+        LD      R30, Y+\r
+        LD      R31, Y+\r
+        LD      R24, Y+\r
+        RETI\r
+        REQUIRE _A_USIDR\r
+        REQUIRE _A_USISR\r
+//  208 \r
+//  209 \r
+//  210 /*! \brief Initializes USI as an SPI slave\r
+//  211  *\r
+//  212  * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
+//  213  * I/O and clock, and USI counter overflow interrupts enabled.\n\r
+//  214  * Also initializes the SPI status struct.\r
+//  215  * \r
+//  216  * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
+//  217  * (1) edge of clock signal\r
+//  218  *\r
+//  219  * \note Clears the stored data\r
+//  220  *\r
+//  221  * \todo Timer should reset SPI protocol on timeout\r
+//  222  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  223 void SPI_Init(unsigned char spi_mode)\r
+SPI_Init:\r
+//  224 {\r
+//  225        __disable_interrupt();\r
+        CLI\r
+//  226        \r
+//  227        // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
+//  228        USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
+        SBI     0x17, 0x01\r
+//  229        USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
+        IN      R17, 0x17\r
+        ANDI    R17, 0xFA\r
+        OUT     0x17, R17\r
+//  230        USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
+        IN      R17, 0x18\r
+        ORI     R17, 0x05\r
+        OUT     0x18, R17\r
+//  231        \r
+//  232        // Configure USI to 3-wire slave mode with overflow interrupt\r
+//  233        USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
+        LSL     R16\r
+        LSL     R16\r
+        ORI     R16, 0x58\r
+        OUT     0x0D, R16\r
+//  234 \r
+//  235        // Initialize the SPI struct\r
+//  236        SPI.Data = 0;                 // Clear data.\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        LDI     R16, 0\r
+        ST      Z, R16\r
+//  237        SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
+//  238        SPI.Read = FALSE;             // Doesn't matter right now.\r
+//  239        SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xFC\r
+        STD     Z+3, R16\r
+//  240        SPI.Count = 0;                // Doesn't matter right now.\r
+        LDI     R16, 64\r
+        STD     Z+2, R16\r
+//  241        SPI.Address = 0;              // Doesn't matter right now.\r
+        LDI     R16, 0\r
+        STD     Z+1, R16\r
+//  242        SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
+//  243        SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
+        LDD     R16, Z+3\r
+        ANDI    R16, 0xF3\r
+        STD     Z+3, R16\r
+//  244 \r
+//  245        __enable_interrupt();\r
+        SEI\r
+//  246 }\r
+        RET\r
+        REQUIRE _A_PORTB\r
+        REQUIRE _A_DDRB\r
+        REQUIRE _A_USICR\r
+//  247 \r
+//  248 \r
+//  249 // Put one byte on bus. Use this function like you would write to the SPDR\r
+//  250 // register in the native SPI module. Calling this function will prepare a\r
+//  251 // byte for the next transfer initiated by the master device. If a transfer\r
+//  252 // is in progress, this function will set the write collision flag and return\r
+//  253 // without altering the data registers.\r
+//  254 //\r
+//  255 // Returns 0 if a write collision occurred, 1 otherwise.\r
+//  256 /*! \brief Write a byte to SPI bus\r
+//  257  *\r
+//  258  * This function first checks if a transmission is in progress, and if so, flags\r
+//  259  * a write collision, and returns FALSE.\n\r
+//  260  * If a transmission is not in progress, the flags for write collision and\r
+//  261  * transfer complete are cleared, and the input byte is written to SPDR.\n\r
+//  262  *\r
+//  263  * \param val The byte to send.\r
+//  264  *\r
+//  265  * \retval FALSE A write collision happened.\r
+//  266  * \retval TRUE Byte written to SPDR.\r
+//  267  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  268 unsigned char SPI_Put(unsigned char val)\r
+SPI_Put:\r
+//  269 {\r
+//  270        // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
+//  271        // If this fails, flag a write collision and return.\r
+//  272        if((USISR & 0x0F) != 0) {\r
+        IN      R17, 0x0E\r
+        ANDI    R17, 0x0F\r
+        LDI     R30, LOW(SPI)\r
+        LDI     R31, (SPI) >> 8\r
+        BREQ    ??SPI_Put_0\r
+//  273                SPI.WriteCollision = TRUE;\r
+        LDD     R16, Z+3\r
+        ORI     R16, 0x08\r
+        STD     Z+3, R16\r
+//  274                return(FALSE);\r
+        LDI     R16, 0\r
+        RET\r
+//  275        }\r
+//  276 \r
+//  277        // Reinitialize flags.\r
+//  278        SPI.XferComplete = FALSE;\r
+//  279        SPI.WriteCollision = FALSE;\r
+??SPI_Put_0:\r
+        LDD     R17, Z+3\r
+        ANDI    R17, 0xF3\r
+        STD     Z+3, R17\r
+//  280 \r
+//  281        USIDR = val;  // Put data in USI data register.\r
+        OUT     0x0F, R16\r
+//  282 \r
+//  283        return (TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+        REQUIRE _A_USIDR\r
+        REQUIRE _A_USISR\r
+//  284 }\r
+//  285 \r
+//  286 \r
+//  287 // Get one byte from bus. This function only returns the previous stored\r
+//  288 // USIDR value. The transfer complete flag is not checked. Use this function\r
+//  289 // like you would read from the SPDR register in the native SPI module.\r
+//  290 /*! \brief Get the last byte received from SPI bus\r
+//  291  *\r
+//  292  * This function simply returns the last byte stored to the SPI status struct,\r
+//  293  * without checking if a completed transfer is flagged.\r
+//  294  *\r
+//  295  * \retval SPI.Data The last byte read from SPI.\r
+//  296  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  297 unsigned char SPI_Get(void)\r
+SPI_Get:\r
+//  298 {\r
+//  299        return SPI.Data;\r
+        LDS     R16, SPI\r
+        RET\r
+//  300 }\r
+//  301 \r
+//  302 \r
+//  303 /*! \brief Wait for SPI transfer to complete\r
+//  304  *\r
+//  305  * This function waits for a transfer complete to be flagged.\r
+//  306  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  307 void SPI_Wait(void)\r
+SPI_Wait:\r
+//  308 {\r
+        LDS     R16, (SPI + 3)\r
+        SBRS    R16, 2\r
+//  309        do {  // Wait for transfer complete.\r
+//  310        } while (SPI.XferComplete == FALSE);\r
+??SPI_Wait_0:\r
+        RJMP    ??SPI_Wait_0\r
+//  311 }\r
+??SPI_Wait_1:\r
+        RET\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        COMMON INTVEC:CODE:ROOT(1)\r
+        ORG 16\r
+`??USI_OVF_ISR??INTVEC 16`:\r
+        RJMP    USI_OVF_ISR\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   5 bytes in segment ABSOLUTE\r
+// 470 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment INTVEC\r
+//   4 bytes in segment NEAR_Z\r
+// \r
+// 470 bytes of CODE memory (+ 8 bytes shared)\r
+//   4 bytes of DATA memory (+ 5 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/battery.lst b/BaseTinyFirmware/IAR/Release/List/battery.lst
new file mode 100644 (file)
index 0000000..2bc0dbe
--- /dev/null
@@ -0,0 +1,1104 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:02 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\battery.c       #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\battery.c       #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\ba #\r
+#                             ttery.lst                                       #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\bat #\r
+#                             tery.r90                                        #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\battery.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions related to battery control and data acquisition.\r
+      6           *\r
+      7           *      Contains functions for enabling/disabling batteries, and looking up\r
+      8           *      their status and specifications using the ADC.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13          \r
+     14           *\r
+     15           * \par Documentation\r
+     16           *      For comprehensive code documentation, supported compilers, compiler \r
+     17           *      settings and supported devices see readme.html\r
+     18           *\r
+     19           * \author\r
+     20           *      Atmel Corporation: http://www.atmel.com \n\r
+     21           *      Support email: avr@atmel.com\r
+     22           *\r
+     23           * \r
+     24           * $Name$\r
+     25           * $Revision: 2299 $\r
+     26           * $RCSfile$\r
+     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
+     28           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     29           ******************************************************************************/\r
+     30          \r
+     31          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4c\r
+   \   <unnamed> volatile __io _A_OCR1B\r
+   \                     _A_OCR1B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x38\r
+   \   <unnamed> volatile __io _A_PORTB\r
+   \                     _A_PORTB:\r
+   \   00000000                      DS 1\r
+     32          #include <inavr.h>\r
+     33          \r
+     34          #include "structs.h"\r
+     35          #include "enums.h"\r
+     36          \r
+     37          #include "ADC.h"\r
+     38          #include "battery.h"\r
+     39          #include "main.h"\r
+     40          #include "OWI.h"\r
+     41          #include "time.h"\r
+     42          \r
+     43          #ifdef NIMH\r
+     44          #include "NIMHspecs.h"\r
+     45          #endif // NIMH\r
+     46          \r
+     47          #ifdef LIION\r
+     48          #include "LIIONspecs.h"\r
+     49          #endif // LIION\r
+     50          \r
+     51          \r
+     52          \r
+     53          //******************************************************************************\r
+     54          // Variables\r
+     55          //******************************************************************************\r
+     56          /* Control-struct for batteries */\r
+     57          /*! \brief Holds control data for both batteries\r
+     58           * \note Stored in EEPROM.\r
+     59           */\r
+\r
+   \                                 In  segment EEPROM_I, align 1, keep-with-next\r
+     60          __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},\r
+   \                     BattControl:\r
+   \   00000000   0303               DB 3, 3\r
+     61                                               {TRUE, TRUE, FALSE}};\r
+     62          \r
+     63          /* Data-struct for battery */\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     64          Batteries_t BattData; //!< Holds data for the current battery\r
+   \                     BattData:\r
+   \   00000000                      DS 12\r
+     65          \r
+     66          \r
+     67          /* Storage for battery EPROM */\r
+     68          /*! \brief Storage space for data from the batteries' own EPROMs.\r
+     69           * \note Stored in EEPROM.\r
+     70           */\r
+\r
+   \                                 In  segment EEPROM_I, align 1, keep-with-next\r
+     71          __eeprom unsigned char BattEEPROM[4][32];\r
+   \                     BattEEPROM:\r
+   \   00000000   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000010   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000020   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000030   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000040   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000050   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000060   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+   \   00000070   000000000000       DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+   \              000000000000\r
+   \              00000000    \r
+     72          \r
+     73          \r
+     74          //! Global that indicates current battery (0 = battery A, 1 = B)\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     75          unsigned char BattActive;\r
+   \                     BattActive:\r
+   \   00000000                      DS 1\r
+     76          \r
+     77          \r
+     78          /*! \brief RID lookup-table\r
+     79           *\r
+     80           * Contains Resistor ID data specified by manufacturer.\r
+     81           *\r
+     82           * \note Values have been calculated assuming a +/- 15% tolerance.\r
+     83           */\r
+\r
+   \                                 In  segment NEAR_I, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_I>`\r
+     84          const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
+   \                     RID:\r
+   \   00000000                      DS 56\r
+   \   00000038                      REQUIRE `?<Initializer for RID>`\r
+     85            {558, 659, 3900, 550, 260, 300, 10},\r
+     86            {744, 843, 6800, 750, 360, 300, 14},\r
+     87            {869, 958, 10000, 1000, 475, 300, 19},\r
+     88            {1097, 1153, 24000, 2000, 475, 420, 38}\r
+     89          };\r
+     90          \r
+     91          \r
+     92          /*! \brief NTC lookup-table\r
+     93           *\r
+     94           * The first entry is 0 degrees. For every entry after, temperature increases\r
+     95           * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
+     96           * It must be sorted in descending ADC order.\r
+     97           *\r
+     98           * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
+     99           *\r
+    100           * \note NTCLookUp() must be modified if this table is changed so that:\r
+    101           * - first entry is no longer 0 degrees.\r
+    102           * - temperature difference between entries is no longer 4 degrees.\r
+    103           * - ADCsteps no longer specifies ADC steps per half degree.\r
+    104           */\r
+    105          // FOR VARTA POLYFLEX NTC\r
+\r
+   \                                 In  segment NEAR_I, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_I>`\r
+    106          const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+   \                     NTC:\r
+   \   00000000                      DS 60\r
+   \   0000003C                      REQUIRE `?<Initializer for NTC>`\r
+    107                {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
+    108                {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
+    109                {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
+    110                {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
+    111          };\r
+    112          \r
+    113          \r
+    114          // FOR MITSUBISHI NTC\r
+    115          /*\r
+    116          const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+    117            {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
+    118            {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
+    119            {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
+    120            {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
+    121          };\r
+    122          */\r
+    123          \r
+    124          \r
+    125          //******************************************************************************\r
+    126          // Functions\r
+    127          //******************************************************************************\r
+    128          /*! \brief Checks if battery has changed\r
+    129           *\r
+    130           * Stores current capacity, then attempts to refresh battery status.\n\r
+    131           * If the refresh is successful, old capacity is compared with the new one.\r
+    132           * \r
+    133           * \retval FALSE Battery is disconnected, or capacity has changed.\r
+    134           * \retval TRUE All OK.\r
+    135           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    136          unsigned char BatteryCheck(void)\r
+   \                     BatteryCheck:\r
+    137          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   938A               ST      -Y, R24\r
+    138                unsigned char success = TRUE;\r
+   \   00000006   E081               LDI     R24, 1\r
+    139                unsigned int  oldCapacity;\r
+    140                \r
+    141                // Save to see if battery data has changed.\r
+    142                oldCapacity = BattData.Capacity;  \r
+   \   00000008   ....               LDI     R30, LOW(BattData)\r
+   \   0000000A   ....               LDI     R31, (BattData) >> 8\r
+   \   0000000C   81A4               LDD     R26, Z+4\r
+   \   0000000E   81B5               LDD     R27, Z+5\r
+    143                \r
+    144                if (!BatteryStatusRefresh()) {\r
+   \   00000010   ....               RCALL   BatteryStatusRefresh\r
+   \   00000012   2300               TST     R16\r
+   \   00000014   F409               BRNE    ??BatteryCheck_0\r
+    145                        success = FALSE;              // Battery not present or RID was invalid.\r
+   \   00000016   E080               LDI     R24, 0\r
+    146                }\r
+    147                \r
+    148                if (oldCapacity != BattData.Capacity) {\r
+   \                     ??BatteryCheck_0:\r
+   \   00000018   ....               LDI     R30, LOW(BattData)\r
+   \   0000001A   ....               LDI     R31, (BattData) >> 8\r
+   \   0000001C   8104               LDD     R16, Z+4\r
+   \   0000001E   8115               LDD     R17, Z+5\r
+   \   00000020   17A0               CP      R26, R16\r
+   \   00000022   07B1               CPC     R27, R17\r
+   \   00000024   F009               BREQ    ??BatteryCheck_1\r
+    149                        success = FALSE;              // Battery configuration has changed.\r
+   \   00000026   E080               LDI     R24, 0\r
+    150                }\r
+    151          \r
+    152                return(success);\r
+   \                     ??BatteryCheck_1:\r
+   \   00000028   2F08               MOV     R16, R24\r
+   \   0000002A   9189               LD      R24, Y+\r
+   \   0000002C   91A9               LD      R26, Y+\r
+   \   0000002E   91B9               LD      R27, Y+\r
+   \   00000030   9508               RET\r
+    153          }\r
+    154          \r
+    155          \r
+    156          /*! \brief Refreshes battery status information\r
+    157           *\r
+    158           * Refreshes battery status information, if it is present, based on\r
+    159           * RID and NTC (read by ADC).\n\r
+    160           * The battery must have been enabled and a complete set of ADC data must have\r
+    161           * been collected before calling.\n\r
+    162           *\r
+    163           * \retval FALSE No battery present.\r
+    164           * \retval TRUE Battery present, status refreshed.\r
+    165           *\r
+    166           * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
+    167           * is found in the lookup table. Instead, default battery data will be used.\r
+    168           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    169          unsigned char BatteryStatusRefresh(void)\r
+   \                     BatteryStatusRefresh:\r
+    170          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   939A               ST      -Y, R25\r
+   \   00000006   938A               ST      -Y, R24\r
+    171                // Assume the worst..\r
+    172                unsigned char success = FALSE;\r
+    173                \r
+    174                BattData.Present = FALSE;\r
+    175                BattData.Charged = FALSE;\r
+    176                BattData.Low = TRUE;\r
+   \   00000008   ....               LDI     R26, LOW(BattData)\r
+   \   0000000A   ....               LDI     R27, (BattData) >> 8\r
+   \   0000000C   910C               LD      R16, X\r
+   \   0000000E   7F0C               ANDI    R16, 0xFC\r
+   \   00000010   6004               ORI     R16, 0x04\r
+   \   00000012   930C               ST      X, R16\r
+    177                BattData.Circuit = OW_NONE;\r
+   \   00000014   E000               LDI     R16, 0\r
+   \   00000016   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000018   8301               STD     Z+1, R16\r
+    178                BattData.Temperature = 0;\r
+   \   0000001A   8302               STD     Z+2, R16\r
+    179                BattData.Capacity = 0;\r
+   \   0000001C   8304               STD     Z+4, R16\r
+   \   0000001E   8305               STD     Z+5, R16\r
+    180                BattData.MaxCurrent = 0;\r
+   \   00000020   8306               STD     Z+6, R16\r
+   \   00000022   8307               STD     Z+7, R16\r
+    181                BattData.MaxTime = 0;\r
+   \   00000024   8700               STD     Z+8, R16\r
+   \   00000026   8701               STD     Z+9, R16\r
+    182                BattData.MinCurrent = 0;\r
+   \   00000028   8702               STD     Z+10, R16\r
+   \   0000002A   8703               STD     Z+11, R16\r
+    183          \r
+    184                NTCLookUp();\r
+   \   0000002C   ....               RCALL   NTCLookUp\r
+    185                BattData.HasRID = RIDLookUp();\r
+   \   0000002E   ....               RCALL   RIDLookUp\r
+   \   00000030   2F10               MOV     R17, R16\r
+   \   00000032   7011               ANDI    R17, 0x01\r
+   \   00000034   FB10               BST     R17, 0\r
+   \   00000036   910C               LD      R16, X\r
+   \   00000038   F904               BLD     R16, 4\r
+   \   0000003A   930C               ST      X, R16\r
+    186          \r
+    187                // Is the battery voltage above minimum safe cell voltage?\r
+    188                if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+   \   0000003C   ....               LDI     R30, LOW(ADCS)\r
+   \   0000003E   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000040   8502               LDD     R16, Z+10\r
+   \   00000042   8513               LDD     R17, Z+11\r
+   \   00000044   3600               CPI     R16, 96\r
+   \   00000046   E029               LDI     R18, 9\r
+   \   00000048   0712               CPC     R17, R18\r
+   \   0000004A   F018               BRCS    ??BatteryStatusRefresh_0\r
+    189                        BattData.Low = FALSE;\r
+   \   0000004C   910C               LD      R16, X\r
+   \   0000004E   7F0B               ANDI    R16, 0xFB\r
+   \   00000050   930C               ST      X, R16\r
+    190                }\r
+    191          \r
+    192                // Is the battery charged?\r
+    193                if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+   \                     ??BatteryStatusRefresh_0:\r
+   \   00000052   8502               LDD     R16, Z+10\r
+   \   00000054   3D02               CPI     R16, 210\r
+   \   00000056   401F               SBCI    R17, 15\r
+   \   00000058   F018               BRCS    ??BatteryStatusRefresh_1\r
+    194                        BattData.Charged = TRUE;\r
+   \   0000005A   910C               LD      R16, X\r
+   \   0000005C   6002               ORI     R16, 0x02\r
+   \   0000005E   930C               ST      X, R16\r
+    195                }\r
+    196          \r
+    197                // If we are not charging, yet VBAT is above safe limit, battery is present.\r
+    198                // If we are charging and there's a current flowing, the battery is present.\r
+    199                \r
+    200                /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
+    201                * check is redundant since charging will be aborted due to low current at\r
+    202                * max duty cycle. That is preferrable since the charge current reading is\r
+    203                * not 100% proof.\r
+    204                */\r
+    205                if (((OCR1B == 0) && (!BattData.Low)) ||\r
+    206                    ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+   \                     ??BatteryStatusRefresh_1:\r
+   \   00000060   B50C               IN      R16, 0x2C\r
+   \   00000062   2300               TST     R16\r
+   \   00000064   F419               BRNE    ??BatteryStatusRefresh_2\r
+   \   00000066   910C               LD      R16, X\r
+   \   00000068   FF02               SBRS    R16, 2\r
+   \   0000006A   C008               RJMP    ??BatteryStatusRefresh_3\r
+   \                     ??BatteryStatusRefresh_2:\r
+   \   0000006C   B50C               IN      R16, 0x2C\r
+   \   0000006E   2300               TST     R16\r
+   \   00000070   F051               BREQ    ??BatteryStatusRefresh_4\r
+   \   00000072   8986               LDD     R24, Z+22\r
+   \   00000074   8997               LDD     R25, Z+23\r
+   \   00000076   3081               CPI     R24, 1\r
+   \   00000078   4090               SBCI    R25, 0\r
+   \   0000007A   F02C               BRLT    ??BatteryStatusRefresh_4\r
+    207                        BattData.Present = TRUE;\r
+   \                     ??BatteryStatusRefresh_3:\r
+   \   0000007C   910C               LD      R16, X\r
+   \   0000007E   6001               ORI     R16, 0x01\r
+   \   00000080   930C               ST      X, R16\r
+    208                        success = TRUE;\r
+   \   00000082   E001               LDI     R16, 1\r
+   \   00000084   C004               RJMP    ??BatteryStatusRefresh_5\r
+    209                } else {\r
+    210                        BattData.Low = FALSE;  // (This is just a technicality..)\r
+   \                     ??BatteryStatusRefresh_4:\r
+   \   00000086   910C               LD      R16, X\r
+   \   00000088   7F0B               ANDI    R16, 0xFB\r
+   \   0000008A   930C               ST      X, R16\r
+    211                        success = FALSE;\r
+   \   0000008C   E000               LDI     R16, 0\r
+    212                }\r
+    213          \r
+    214          #ifndef ALLOW_NO_RID\r
+    215                // Return FALSE if no valid RID entry was found, to stop charging.\r
+    216                if(!BattData.HasRID) {\r
+   \                     ??BatteryStatusRefresh_5:\r
+   \   0000008E   911C               LD      R17, X\r
+   \   00000090   FF14               SBRS    R17, 4\r
+    217                        success = FALSE;\r
+   \   00000092   E000               LDI     R16, 0\r
+    218                }\r
+    219          #endif\r
+    220          \r
+    221                return(success);\r
+   \                     ??BatteryStatusRefresh_6:\r
+   \   00000094   9189               LD      R24, Y+\r
+   \   00000096   9199               LD      R25, Y+\r
+   \   00000098   91A9               LD      R26, Y+\r
+   \   0000009A   91B9               LD      R27, Y+\r
+   \   0000009C   9508               RET\r
+   \   0000009E                      REQUIRE _A_OCR1B\r
+    222          }\r
+    223          \r
+    224          \r
+    225          /*! \brief Refreshes battery data in the EEPROM\r
+    226           *\r
+    227           * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
+    228           * these data in on-chip EEPROM.\n\r
+    229           * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
+    230           *\r
+    231           * \todo Updating BattData with these data. Specs needed.\r
+    232           *\r
+    233           * \retval FALSE Refresh failed.\r
+    234           * \retval TRUE Refresh successful.\r
+    235           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    236          unsigned char BatteryDataRefresh(void)\r
+   \                     BatteryDataRefresh:\r
+    237          {\r
+   \   00000000   928A               ST      -Y, R8\r
+   \   00000002   927A               ST      -Y, R7\r
+   \   00000004   926A               ST      -Y, R6\r
+   \   00000006   925A               ST      -Y, R5\r
+   \   00000008   924A               ST      -Y, R4\r
+   \   0000000A   93BA               ST      -Y, R27\r
+   \   0000000C   93AA               ST      -Y, R26\r
+   \   0000000E   939A               ST      -Y, R25\r
+   \   00000010   938A               ST      -Y, R24\r
+   \   00000012                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000012                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000012                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000012                      REQUIRE ?Register_R7_is_cg_reg\r
+   \   00000012                      REQUIRE ?Register_R8_is_cg_reg\r
+    238                unsigned char offset;\r
+    239                unsigned char i, crc, family, temp, page;\r
+    240                unsigned char success;\r
+    241                \r
+    242                // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
+    243                for (page = 0; page < 4; page++)        {\r
+   \   00000012   E090               LDI     R25, 0\r
+   \   00000014   ....               LDI     R26, LOW(BattEEPROM)\r
+   \   00000016   ....               LDI     R27, (BattEEPROM) >> 8\r
+    244                        success = FALSE;\r
+   \                     ??BatteryDataRefresh_0:\r
+   \   00000018   2477               CLR     R7\r
+    245                \r
+    246                        if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
+   \   0000001A   E001               LDI     R16, 1\r
+   \   0000001C   ....               RCALL   OWI_DetectPresence\r
+   \   0000001E   3001               CPI     R16, 1\r
+   \   00000020   F009               BREQ    $+2+2\r
+   \   00000022   C055               RJMP    ??BatteryDataRefresh_1\r
+    247                                \r
+    248                                // Presence detected, check type and CRC.\r
+    249                                OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
+   \   00000024   E011               LDI     R17, 1\r
+   \   00000026   E303               LDI     R16, 51\r
+   \   00000028   ....               RCALL   OWI_SendByte\r
+    250                                family = OWI_ReceiveByte(OWIBUS);\r
+   \   0000002A   E001               LDI     R16, 1\r
+   \   0000002C   ....               RCALL   OWI_ReceiveByte\r
+   \   0000002E   2E50               MOV     R5, R16\r
+    251                                crc = OWI_ComputeCRC8(family,0);\r
+   \   00000030   E010               LDI     R17, 0\r
+   \   00000032   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000034   2F80               MOV     R24, R16\r
+    252          \r
+    253                                for (i = 0; i < 6; i++) {\r
+   \   00000036   E006               LDI     R16, 6\r
+   \   00000038   2E40               MOV     R4, R16\r
+    254                                        crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
+   \                     ??BatteryDataRefresh_2:\r
+   \   0000003A   E001               LDI     R16, 1\r
+   \   0000003C   ....               RCALL   OWI_ReceiveByte\r
+   \   0000003E   2F18               MOV     R17, R24\r
+   \   00000040   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000042   2F80               MOV     R24, R16\r
+    255                                }\r
+   \   00000044   944A               DEC     R4\r
+   \   00000046   F7C9               BRNE    ??BatteryDataRefresh_2\r
+    256          \r
+    257                                // CRC ok, device found.\r
+    258                                if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+   \   00000048   E001               LDI     R16, 1\r
+   \   0000004A   ....               RCALL   OWI_ReceiveByte\r
+   \   0000004C   2F18               MOV     R17, R24\r
+   \   0000004E   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000050   2300               TST     R16\r
+   \   00000052   F5E9               BRNE    ??BatteryDataRefresh_1\r
+    259                                        BattData.Circuit = family;\r
+   \   00000054   9250....           STS     (BattData + 1), R5\r
+    260          \r
+    261                                        // For now, we only read data from DS2505 EPROMs.\r
+    262                                        if (BattData.Circuit == OW_DS2505) {\r
+   \   00000058   9100....           LDS     R16, (BattData + 1)\r
+   \   0000005C   3009               CPI     R16, 9\r
+   \   0000005E   F5B9               BRNE    ??BatteryDataRefresh_1\r
+    263                                                offset = page*32;\r
+   \   00000060   2E49               MOV     R4, R25\r
+   \   00000062   9442               SWAP    R4\r
+   \   00000064   EF00               LDI     R16, 240\r
+   \   00000066   2240               AND     R4, R16\r
+   \   00000068   0C44               LSL     R4\r
+    264                                                OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
+   \   0000006A   E011               LDI     R17, 1\r
+   \   0000006C   EC03               LDI     R16, 195\r
+   \   0000006E   ....               RCALL   OWI_SendByte\r
+    265                                                OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
+   \   00000070   E011               LDI     R17, 1\r
+   \   00000072   2D04               MOV     R16, R4\r
+   \   00000074   ....               RCALL   OWI_SendByte\r
+    266                                                OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
+   \   00000076   E011               LDI     R17, 1\r
+   \   00000078   E000               LDI     R16, 0\r
+   \   0000007A   ....               RCALL   OWI_SendByte\r
+    267          \r
+    268                                                // Calculate checksums.\r
+    269                                                crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
+   \   0000007C   E010               LDI     R17, 0\r
+   \   0000007E   EC03               LDI     R16, 195\r
+   \   00000080   ....               RCALL   OWI_ComputeCRC8\r
+    270                                                crc = OWI_ComputeCRC8(offset,crc);\r
+   \   00000082   2F10               MOV     R17, R16\r
+   \   00000084   2D04               MOV     R16, R4\r
+   \   00000086   ....               RCALL   OWI_ComputeCRC8\r
+    271                                                crc = OWI_ComputeCRC8(0,crc);\r
+   \   00000088   2F10               MOV     R17, R16\r
+   \   0000008A   E000               LDI     R16, 0\r
+   \   0000008C   ....               RCALL   OWI_ComputeCRC8\r
+   \   0000008E   2F80               MOV     R24, R16\r
+    272          \r
+    273                                                // Command received succesfully, now start reading data\r
+    274                                                // and writing it to EEPROM.\r
+    275                                                if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+   \   00000090   E001               LDI     R16, 1\r
+   \   00000092   ....               RCALL   OWI_ReceiveByte\r
+   \   00000094   2F18               MOV     R17, R24\r
+   \   00000096   ....               RCALL   OWI_ComputeCRC8\r
+   \   00000098   2300               TST     R16\r
+   \   0000009A   F4C9               BRNE    ??BatteryDataRefresh_1\r
+    276                                                        crc = 0;\r
+   \   0000009C   E080               LDI     R24, 0\r
+    277                                                        \r
+    278                                                        // Fill page with data.\r
+    279                                                        for (i=0; i<32; i++) {\r
+   \   0000009E   012D               MOVW    R5:R4, R27:R26\r
+   \   000000A0   E200               LDI     R16, 32\r
+   \   000000A2   2E60               MOV     R6, R16\r
+    280                                                                temp = OWI_ReceiveByte(OWIBUS);\r
+   \                     ??BatteryDataRefresh_3:\r
+   \   000000A4   E001               LDI     R16, 1\r
+   \   000000A6   ....               RCALL   OWI_ReceiveByte\r
+   \   000000A8   2E80               MOV     R8, R16\r
+    281                                                                crc = OWI_ComputeCRC8(temp, crc);\r
+   \   000000AA   2F18               MOV     R17, R24\r
+   \   000000AC   ....               RCALL   OWI_ComputeCRC8\r
+   \   000000AE   2F80               MOV     R24, R16\r
+    282                                                                BattEEPROM[page][i] = temp;\r
+   \   000000B0   2D08               MOV     R16, R8\r
+   \   000000B2   01A2               MOVW    R21:R20, R5:R4\r
+   \   000000B4   ....               RCALL   __eeput8_16\r
+    283                                                        }\r
+   \   000000B6   E001               LDI     R16, 1\r
+   \   000000B8   0E40               ADD     R4, R16\r
+   \   000000BA   1C57               ADC     R5, R7\r
+   \   000000BC   946A               DEC     R6\r
+   \   000000BE   F791               BRNE    ??BatteryDataRefresh_3\r
+    284                                                        \r
+    285                                                        if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+   \   000000C0   ....               RCALL   OWI_ReceiveByte\r
+   \   000000C2   2F18               MOV     R17, R24\r
+   \   000000C4   ....               RCALL   OWI_ComputeCRC8\r
+   \   000000C6   2300               TST     R16\r
+   \   000000C8   F411               BRNE    ??BatteryDataRefresh_1\r
+    286                                                                        success = TRUE;  // Data read OK\r
+   \   000000CA   9473               INC     R7\r
+   \   000000CC   C008               RJMP    ??BatteryDataRefresh_4\r
+    287                                                        }\r
+    288                                                } else { // Not able to start reading data.\r
+    289                                                }\r
+    290                                        } else { // Wrong device type.\r
+    291                                        }\r
+    292                                } else { // No device found.             \r
+    293                                }\r
+    294                        } else { // No presence detected on one-wire bus.\r
+    295                        }\r
+    296          \r
+    297                  // Erase local EEPROM page if there were any errors during transfer.\r
+    298                        if (!success) {\r
+    299                                for (i=0; i<32; i++) {\r
+   \                     ??BatteryDataRefresh_1:\r
+   \   000000CE   01AD               MOVW    R21:R20, R27:R26\r
+   \   000000D0   E210               LDI     R17, 32\r
+    300                                        BattEEPROM[page][i] = 0;\r
+   \                     ??BatteryDataRefresh_5:\r
+   \   000000D2   E000               LDI     R16, 0\r
+   \   000000D4   ....               RCALL   __eeput8_16\r
+    301                                }\r
+   \   000000D6   5F4F               SUBI    R20, 255\r
+   \   000000D8   4F5F               SBCI    R21, 255\r
+   \   000000DA   951A               DEC     R17\r
+   \   000000DC   F7D1               BRNE    ??BatteryDataRefresh_5\r
+    302                        }\r
+    303                }\r
+   \                     ??BatteryDataRefresh_4:\r
+   \   000000DE   9593               INC     R25\r
+   \   000000E0   9690               ADIW    R27:R26, 32\r
+   \   000000E2   3094               CPI     R25, 4\r
+   \   000000E4   F408               BRCC    $+2+2\r
+   \   000000E6   CF98               RJMP    ??BatteryDataRefresh_0\r
+    304          \r
+    305                return(success);\r
+   \   000000E8   2D07               MOV     R16, R7\r
+   \   000000EA   9189               LD      R24, Y+\r
+   \   000000EC   9199               LD      R25, Y+\r
+   \   000000EE   91A9               LD      R26, Y+\r
+   \   000000F0   91B9               LD      R27, Y+\r
+   \   000000F2   9049               LD      R4, Y+\r
+   \   000000F4   9059               LD      R5, Y+\r
+   \   000000F6   9069               LD      R6, Y+\r
+   \   000000F8   9079               LD      R7, Y+\r
+   \   000000FA   9089               LD      R8, Y+\r
+   \   000000FC   9508               RET\r
+    306          }\r
+    307          \r
+    308          \r
+    309          /*! \brief Enables specified battery\r
+    310           *\r
+    311           * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
+    312           * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
+    313           * The function takes 100 ms to allow the port switch to settle.\r
+    314           *\r
+    315           * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
+    316           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    317          void EnableBattery(unsigned char bat)\r
+   \                     EnableBattery:\r
+    318          {\r
+   \   00000000   938A               ST      -Y, R24\r
+   \   00000002   2F80               MOV     R24, R16\r
+    319                // Use general timer, set timeout to 100ms.\r
+    320                Time_Set(TIMER_GEN,0,0,100);\r
+   \   00000004   E644               LDI     R20, 100\r
+   \   00000006   E010               LDI     R17, 0\r
+   \   00000008   E020               LDI     R18, 0\r
+   \   0000000A   E030               LDI     R19, 0\r
+   \   0000000C   E002               LDI     R16, 2\r
+   \   0000000E   ....               RCALL   Time_Set\r
+    321          \r
+    322                // Set specified battery as the active one.\r
+    323                BattActive = bat;\r
+   \   00000010   9380....           STS     BattActive, R24\r
+    324          \r
+    325                // Enable current battery in hardware, light LED & connect battery.\r
+    326                PORTB |= (1 << (PB4+bat));\r
+   \   00000014   E001               LDI     R16, 1\r
+   \   00000016   E010               LDI     R17, 0\r
+   \   00000018   2F48               MOV     R20, R24\r
+   \   0000001A   5F4C               SUBI    R20, 252\r
+   \   0000001C   ....               RCALL   ?S_SHL_L02\r
+   \   0000001E   B318               IN      R17, 0x18\r
+   \   00000020   2B10               OR      R17, R16\r
+   \   00000022   BB18               OUT     0x18, R17\r
+    327          \r
+    328                // Disconnect other battery.\r
+    329                PORTB &= ~(1<<(PB5-bat));     \r
+   \   00000024   E001               LDI     R16, 1\r
+   \   00000026   E010               LDI     R17, 0\r
+   \   00000028   E045               LDI     R20, 5\r
+   \   0000002A   1B48               SUB     R20, R24\r
+   \   0000002C   ....               RCALL   ?S_SHL_L02\r
+   \   0000002E   9500               COM     R16\r
+   \   00000030   B318               IN      R17, 0x18\r
+   \   00000032   2310               AND     R17, R16\r
+   \   00000034   BB18               OUT     0x18, R17\r
+    330          \r
+    331                do { // Let port switch settle.\r
+    332                } while (Time_Left(TIMER_GEN));  \r
+   \                     ??EnableBattery_0:\r
+   \   00000036   E002               LDI     R16, 2\r
+   \   00000038   ....               RCALL   Time_Left\r
+   \   0000003A   2300               TST     R16\r
+   \   0000003C   F7E1               BRNE    ??EnableBattery_0\r
+    333          }\r
+   \   0000003E   9189               LD      R24, Y+\r
+   \   00000040   9508               RET\r
+   \   00000042                      REQUIRE _A_PORTB\r
+    334          \r
+    335          \r
+    336          /*! \brief Disables both batteries\r
+    337           *\r
+    338           * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
+    339           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    340          void DisableBatteries(void)\r
+   \                     DisableBatteries:\r
+    341          {\r
+    342                // Turn off LEDs and disconnect batteries.\r
+    343                PORTB &= ~((1<<PB4)|(1<<PB5));  \r
+   \   00000000   B308               IN      R16, 0x18\r
+   \   00000002   7C0F               ANDI    R16, 0xCF\r
+   \   00000004   BB08               OUT     0x18, R16\r
+    344          }\r
+   \   00000006   9508               RET\r
+   \   00000008                      REQUIRE _A_PORTB\r
+    345          \r
+    346          \r
+    347          /*! \brief Looks up battery data from RID table\r
+    348           *\r
+    349           * Attempts to find data for the battery from the RID lookup-table.\n\r
+    350           * If no valid entry is found, default data (defined in battery.h)\r
+    351           * are used.\r
+    352           *\r
+    353           * \retval TRUE Entry found, battery data updated.\r
+    354           * \retval FALSE No entry found, using defaults for battery data.\r
+    355           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    356          unsigned char RIDLookUp (void)\r
+   \                     RIDLookUp:\r
+    357          {\r
+   \   00000000   2F3B               MOV     R19, R27\r
+   \   00000002   2E2A               MOV     R2, R26\r
+    358                unsigned char i, found = FALSE;\r
+   \   00000004   E040               LDI     R20, 0\r
+    359                        \r
+    360                // Lookup in the RID-table. If measured RID is within the limits\r
+    361                // of an entry, those data are used, and TRUE is returned.\r
+    362                for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
+   \   00000006   ....               LDI     R30, LOW(RID)\r
+   \   00000008   ....               LDI     R31, (RID) >> 8\r
+   \   0000000A   E024               LDI     R18, 4\r
+   \   0000000C   ....               LDI     R16, LOW(BattData)\r
+   \   0000000E   ....               LDI     R17, (BattData) >> 8\r
+    363                        if (ADCS.rawRID >= RID[i].Low) {\r
+   \                     ??RIDLookUp_0:\r
+   \   00000010   ....               LDI     R26, LOW((ADCS + 2))\r
+   \   00000012   ....               LDI     R27, HIGH((ADCS + 2))\r
+   \   00000014   916D               LD      R22, X+\r
+   \   00000016   917C               LD      R23, X\r
+   \   00000018   8000               LD      R0, Z\r
+   \   0000001A   8011               LDD     R1, Z+1\r
+   \   0000001C   1560               CP      R22, R0\r
+   \   0000001E   0571               CPC     R23, R1\r
+   \   00000020   F0F0               BRCS    ??RIDLookUp_1\r
+    364                                if (ADCS.rawRID <= RID[i].High) {\r
+   \   00000022   8002               LDD     R0, Z+2\r
+   \   00000024   8013               LDD     R1, Z+3\r
+   \   00000026   1606               CP      R0, R22\r
+   \   00000028   0617               CPC     R1, R23\r
+   \   0000002A   F0C8               BRCS    ??RIDLookUp_1\r
+    365                                        BattData.Capacity = RID[i].Capacity;\r
+   \   0000002C   8146               LDD     R20, Z+6\r
+   \   0000002E   8157               LDD     R21, Z+7\r
+   \   00000030   01D8               MOVW    R27:R26, R17:R16\r
+   \   00000032   9614               ADIW    R27:R26, 4\r
+   \   00000034   934D               ST      X+, R20\r
+   \   00000036   935C               ST      X, R21\r
+    366                                        BattData.MaxCurrent = RID[i].Icharge;\r
+   \   00000038   8540               LDD     R20, Z+8\r
+   \   0000003A   8551               LDD     R21, Z+9\r
+   \   0000003C   01D8               MOVW    R27:R26, R17:R16\r
+   \   0000003E   9616               ADIW    R27:R26, 6\r
+   \   00000040   934D               ST      X+, R20\r
+   \   00000042   935C               ST      X, R21\r
+    367                                        BattData.MaxTime = RID[i].tCutOff;\r
+   \   00000044   8542               LDD     R20, Z+10\r
+   \   00000046   8553               LDD     R21, Z+11\r
+   \   00000048   01D8               MOVW    R27:R26, R17:R16\r
+   \   0000004A   9618               ADIW    R27:R26, 8\r
+   \   0000004C   934D               ST      X+, R20\r
+   \   0000004E   935C               ST      X, R21\r
+    368                                        BattData.MinCurrent = RID[i].ICutOff;\r
+   \   00000050   8544               LDD     R20, Z+12\r
+   \   00000052   8555               LDD     R21, Z+13\r
+   \   00000054   01D8               MOVW    R27:R26, R17:R16\r
+   \   00000056   961A               ADIW    R27:R26, 10\r
+   \   00000058   934D               ST      X+, R20\r
+   \   0000005A   935C               ST      X, R21\r
+    369                                        \r
+    370                                        found = TRUE;\r
+   \   0000005C   E041               LDI     R20, 1\r
+    371                                }\r
+    372                        }\r
+    373                }\r
+   \                     ??RIDLookUp_1:\r
+   \   0000005E   963E               ADIW    R31:R30, 14\r
+   \   00000060   952A               DEC     R18\r
+   \   00000062   F6B1               BRNE    ??RIDLookUp_0\r
+    374                \r
+    375                // If no valid entry is found, use defaults and return FALSE.\r
+    376                if (!found) {\r
+   \   00000064   2344               TST     R20\r
+   \   00000066   F451               BRNE    ??RIDLookUp_2\r
+    377                        BattData.Capacity = DEF_BAT_CAPACITY;\r
+   \   00000068   E020               LDI     R18, 0\r
+   \   0000006A   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000006C   8324               STD     Z+4, R18\r
+   \   0000006E   8325               STD     Z+5, R18\r
+    378                        BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
+   \   00000070   8326               STD     Z+6, R18\r
+   \   00000072   8327               STD     Z+7, R18\r
+    379                        BattData.MaxTime = DEF_BAT_TIME_MAX;\r
+   \   00000074   8720               STD     Z+8, R18\r
+   \   00000076   8721               STD     Z+9, R18\r
+    380                        BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
+   \   00000078   8722               STD     Z+10, R18\r
+   \   0000007A   8723               STD     Z+11, R18\r
+    381                }\r
+    382                \r
+    383                return(found);\r
+   \                     ??RIDLookUp_2:\r
+   \   0000007C   2F04               MOV     R16, R20\r
+   \   0000007E   2DA2               MOV     R26, R2\r
+   \   00000080   2FB3               MOV     R27, R19\r
+   \   00000082   9508               RET\r
+    384          }\r
+    385          \r
+    386          \r
+    387          /*! \brief Calculates temperature from a lookup table\r
+    388           *\r
+    389           * Looks up the highest NTC value below or equal to the measured one.\n\r
+    390           * With the current lookup table, temperature is calculated with the formula:\n\r
+    391           * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
+    392           *\r
+    393           * \note If the NTC-measurement is saturated, with the current lookup table,\r
+    394           * the temperature will be reported as -1 C.\r
+    395           *\r
+    396           * \note If no valid entry is found, battery temperature is set to 80.\r
+    397           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    398          void NTCLookUp (void)\r
+   \                     NTCLookUp:\r
+    399          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   2E3A               MOV     R3, R26\r
+   \   00000004   2E28               MOV     R2, R24\r
+    400                unsigned char i;\r
+    401                unsigned char found = FALSE;\r
+   \   00000006   E000               LDI     R16, 0\r
+    402                \r
+    403                // Lookup in the NTC-table. Use the first entry which is equal or below\r
+    404                // sampled NTC. Calculate temperature by using the index number, and the\r
+    405                // difference between the measured NTC value and the one in the entry.\r
+    406                for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
+   \   00000008   E080               LDI     R24, 0\r
+   \   0000000A   ....               LDI     R26, LOW(BattData)\r
+   \   0000000C   ....               LDI     R27, (BattData) >> 8\r
+    407                        if (ADCS.rawNTC >= NTC[i].ADC) {\r
+   \                     ??NTCLookUp_0:\r
+   \   0000000E   2F48               MOV     R20, R24\r
+   \   00000010   E050               LDI     R21, 0\r
+   \   00000012   019A               MOVW    R19:R18, R21:R20\r
+   \   00000014   0F44               LSL     R20\r
+   \   00000016   1F55               ROL     R21\r
+   \   00000018   0F42               ADD     R20, R18\r
+   \   0000001A   1F53               ADC     R21, R19\r
+   \   0000001C   ....               LDI     R18, LOW(NTC)\r
+   \   0000001E   ....               LDI     R19, (NTC) >> 8\r
+   \   00000020   0F24               ADD     R18, R20\r
+   \   00000022   1F35               ADC     R19, R21\r
+   \   00000024   ....               LDI     R30, LOW(ADCS)\r
+   \   00000026   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000028   8144               LDD     R20, Z+4\r
+   \   0000002A   8155               LDD     R21, Z+5\r
+   \   0000002C   01F9               MOVW    R31:R30, R19:R18\r
+   \   0000002E   8160               LD      R22, Z\r
+   \   00000030   8171               LDD     R23, Z+1\r
+   \   00000032   1746               CP      R20, R22\r
+   \   00000034   0757               CPC     R21, R23\r
+   \   00000036   F0D0               BRCS    ??NTCLookUp_1\r
+    408                                BattData.Temperature = (i<<2) ;\r
+   \   00000038   2F08               MOV     R16, R24\r
+   \   0000003A   0F00               LSL     R16\r
+   \   0000003C   0F00               LSL     R16\r
+   \   0000003E   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000040   8302               STD     Z+2, R16\r
+    409                                BattData.ADCSteps = NTC[i].ADCsteps;  \r
+   \   00000042   01F9               MOVW    R31:R30, R19:R18\r
+   \   00000044   8142               LDD     R20, Z+2\r
+   \   00000046   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000048   8343               STD     Z+3, R20\r
+    410                                BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;\r
+   \   0000004A   9100....           LDS     R16, (ADCS + 4)\r
+   \   0000004E   2F15               MOV     R17, R21\r
+   \   00000050   01F9               MOVW    R31:R30, R19:R18\r
+   \   00000052   8120               LD      R18, Z\r
+   \   00000054   8131               LDD     R19, Z+1\r
+   \   00000056   1B02               SUB     R16, R18\r
+   \   00000058   0B13               SBC     R17, R19\r
+   \   0000005A   0F00               LSL     R16\r
+   \   0000005C   1F11               ROL     R17\r
+   \   0000005E   E050               LDI     R21, 0\r
+   \   00000060   ....               RCALL   ?US_DIVMOD_L02\r
+   \   00000062   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000064   8112               LDD     R17, Z+2\r
+   \   00000066   1B10               SUB     R17, R16\r
+   \   00000068   8312               STD     Z+2, R17\r
+    411                                \r
+    412                                found = TRUE;  // Could be done with a break, but that violates MISRA.\r
+   \   0000006A   E001               LDI     R16, 1\r
+    413                        }\r
+    414                }\r
+   \                     ??NTCLookUp_1:\r
+   \   0000006C   9583               INC     R24\r
+   \   0000006E   3184               CPI     R24, 20\r
+   \   00000070   F410               BRCC    ??NTCLookUp_2\r
+   \   00000072   2300               TST     R16\r
+   \   00000074   F261               BREQ    ??NTCLookUp_0\r
+    415                \r
+    416                // For safety, is temperature is greater than the NTC \r
+    417                if (!found) {\r
+   \                     ??NTCLookUp_2:\r
+   \   00000076   2300               TST     R16\r
+   \   00000078   F419               BRNE    ??NTCLookUp_3\r
+    418                        BattData.Temperature = 80;\r
+   \   0000007A   E500               LDI     R16, 80\r
+   \   0000007C   9300....           STS     (BattData + 2), R16\r
+    419                }\r
+    420          }\r
+   \                     ??NTCLookUp_3:\r
+   \   00000080   2D82               MOV     R24, R2\r
+   \   00000082   2DA3               MOV     R26, R3\r
+   \   00000084   91B9               LD      R27, Y+\r
+   \   00000086   9508               RET\r
+\r
+   \                                 In  segment NEAR_ID, align 1, keep-with-next\r
+   \                     `?<Initializer for RID>`:\r
+   \   00000000   022E02930F3C       DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14\r
+   \              02260104012C\r
+   \              000A02E8034B\r
+   \              1A9002EE0168\r
+   \              012C000E    \r
+   \   0000001C   036503BE2710       DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475\r
+   \              03E801DB012C\r
+   \              001304490481\r
+   \              5DC007D001DB\r
+   \   00000034   01A40026           DW 420, 38\r
+\r
+   \                                 In  segment NEAR_ID, align 1, keep-with-next\r
+   \                     `?<Initializer for NTC>`:\r
+   \   00000000   03EA               DW 1002\r
+   \   00000002   17                 DB 23\r
+   \   00000003   03B9               DW 953\r
+   \   00000005   19                 DB 25\r
+   \   00000006   0386               DW 902\r
+   \   00000008   1A                 DB 26\r
+   \   00000009   0351               DW 849\r
+   \   0000000B   1B                 DB 27\r
+   \   0000000C   031C               DW 796\r
+   \   0000000E   1B                 DB 27\r
+   \   0000000F   02E6               DW 742\r
+   \   00000011   1B                 DB 27\r
+   \   00000012   02B1               DW 689\r
+   \   00000014   1A                 DB 26\r
+   \   00000015   027D               DW 637\r
+   \   00000017   1A                 DB 26\r
+   \   00000018   024B               DW 587\r
+   \   0000001A   19                 DB 25\r
+   \   0000001B   021B               DW 539\r
+   \   0000001D   18                 DB 24\r
+   \   0000001E   01EE               DW 494\r
+   \   00000020   16                 DB 22\r
+   \   00000021   01C3               DW 451\r
+   \   00000023   15                 DB 21\r
+   \   00000024   019C               DW 412\r
+   \   00000026   13                 DB 19\r
+   \   00000027   0177               DW 375\r
+   \   00000029   12                 DB 18\r
+   \   0000002A   0155               DW 341\r
+   \   0000002C   11                 DB 17\r
+   \   0000002D   0136               DW 310\r
+   \   0000002F   0F                 DB 15\r
+   \   00000030   011A               DW 282\r
+   \   00000032   0E                 DB 14\r
+   \   00000033   0100               DW 256\r
+   \   00000035   0D                 DB 13\r
+   \   00000036   00E9               DW 233\r
+   \   00000038   0B                 DB 11\r
+   \   00000039   00D4               DW 212\r
+   \   0000003B   0A                 DB 10\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function                  CSTACK RSTACK\r
+     --------                  ------ ------\r
+     BatteryCheck                  3      2\r
+       -> BatteryStatusRefresh     3      2\r
+     BatteryDataRefresh            9      4\r
+       -> OWI_DetectPresence       9      2\r
+       -> OWI_SendByte             9      2\r
+       -> OWI_ReceiveByte          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ReceiveByte          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ReceiveByte          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_SendByte             9      2\r
+       -> OWI_SendByte             9      2\r
+       -> OWI_SendByte             9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ReceiveByte          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ReceiveByte          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+       -> OWI_ReceiveByte          9      2\r
+       -> OWI_ComputeCRC8          9      2\r
+     BatteryStatusRefresh          4      2\r
+       -> NTCLookUp                4      2\r
+       -> RIDLookUp                4      2\r
+     DisableBatteries              0      2\r
+     EnableBattery                 1      4\r
+       -> Time_Set                 1      2\r
+       -> Time_Left                1      2\r
+     NTCLookUp                     3      4\r
+     RIDLookUp                     0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label         Bytes\r
+     --------------         -----\r
+     _A_OCR1B                  1\r
+     _A_PORTB                  1\r
+     BattControl               2\r
+     BattData                 12\r
+     BattEEPROM              128\r
+     BattActive                1\r
+     RID                      56\r
+     NTC                      60\r
+     BatteryCheck             50\r
+     BatteryStatusRefresh    158\r
+     BatteryDataRefresh      254\r
+     EnableBattery            66\r
+     DisableBatteries          8\r
+     RIDLookUp               132\r
+     NTCLookUp               136\r
+     ?<Initializer for RID>   56\r
+     ?<Initializer for NTC>   60\r
+      Others                  12\r
+\r
\r
+   2 bytes in segment ABSOLUTE\r
+ 804 bytes in segment CODE\r
+ 130 bytes in segment EEPROM_I\r
+  12 bytes in segment INITTAB\r
+ 116 bytes in segment NEAR_I\r
+ 116 bytes in segment NEAR_ID\r
+  13 bytes in segment NEAR_Z\r
\r
+ 920 bytes of CODE  memory (+ 12 bytes shared)\r
+ 129 bytes of DATA  memory (+  2 bytes shared)\r
+ 130 bytes of XDATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/battery.s90 b/BaseTinyFirmware/IAR/Release/List/battery.s90
new file mode 100644 (file)
index 0000000..a736f3d
--- /dev/null
@@ -0,0 +1,1090 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:02 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\battery.c      /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\battery.c      /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\b /\r
+//                             attery.s90                                     /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME battery\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?Register_R7_is_cg_reg\r
+        EXTERN ?Register_R8_is_cg_reg\r
+        EXTERN ?S_SHL_L02\r
+        EXTERN ?US_DIVMOD_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_I>`\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC BattActive\r
+        PUBLIC BattControl\r
+        PUBLIC BattData\r
+        PUBLIC BattEEPROM\r
+        PUBLIC BatteryCheck\r
+        PUBLIC BatteryDataRefresh\r
+        PUBLIC BatteryStatusRefresh\r
+        PUBLIC DisableBatteries\r
+        PUBLIC EnableBattery\r
+        PUBLIC NTC\r
+        PUBLIC NTCLookUp\r
+        PUBLIC RID\r
+        PUBLIC RIDLookUp\r
+        PUBWEAK _A_OCR1B\r
+        PUBWEAK _A_PORTB\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN OWI_DetectPresence\r
+        EXTERN OWI_SendByte\r
+        EXTERN OWI_ReceiveByte\r
+        EXTERN OWI_ComputeCRC8\r
+        EXTERN Time_Set\r
+        EXTERN Time_Left\r
+        EXTERN ADCS\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\battery.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions related to battery control and data acquisition.\r
+//    6  *\r
+//    7  *      Contains functions for enabling/disabling batteries, and looking up\r
+//    8  *      their status and specifications using the ADC.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13 \r
+//   14  *\r
+//   15  * \par Documentation\r
+//   16  *      For comprehensive code documentation, supported compilers, compiler \r
+//   17  *      settings and supported devices see readme.html\r
+//   18  *\r
+//   19  * \author\r
+//   20  *      Atmel Corporation: http://www.atmel.com \n\r
+//   21  *      Support email: avr@atmel.com\r
+//   22  *\r
+//   23  * \r
+//   24  * $Name$\r
+//   25  * $Revision: 2299 $\r
+//   26  * $RCSfile$\r
+//   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
+//   28  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   29  ******************************************************************************/\r
+//   30 \r
+//   31 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
+// <unnamed> volatile __io _A_OCR1B\r
+_A_OCR1B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,038H\r
+// <unnamed> volatile __io _A_PORTB\r
+_A_PORTB:\r
+        DS 1\r
+//   32 #include <inavr.h>\r
+//   33 \r
+//   34 #include "structs.h"\r
+//   35 #include "enums.h"\r
+//   36 \r
+//   37 #include "ADC.h"\r
+//   38 #include "battery.h"\r
+//   39 #include "main.h"\r
+//   40 #include "OWI.h"\r
+//   41 #include "time.h"\r
+//   42 \r
+//   43 #ifdef NIMH\r
+//   44 #include "NIMHspecs.h"\r
+//   45 #endif // NIMH\r
+//   46 \r
+//   47 #ifdef LIION\r
+//   48 #include "LIIONspecs.h"\r
+//   49 #endif // LIION\r
+//   50 \r
+//   51 \r
+//   52 \r
+//   53 //******************************************************************************\r
+//   54 // Variables\r
+//   55 //******************************************************************************\r
+//   56 /* Control-struct for batteries */\r
+//   57 /*! \brief Holds control data for both batteries\r
+//   58  * \note Stored in EEPROM.\r
+//   59  */\r
+\r
+        RSEG EEPROM_I:XDATA:NOROOT(0)\r
+//   60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},\r
+BattControl:\r
+        DB 3, 3\r
+//   61                                      {TRUE, TRUE, FALSE}};\r
+//   62 \r
+//   63 /* Data-struct for battery */\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   64 Batteries_t BattData; //!< Holds data for the current battery\r
+BattData:\r
+        DS 12\r
+//   65 \r
+//   66 \r
+//   67 /* Storage for battery EPROM */\r
+//   68 /*! \brief Storage space for data from the batteries' own EPROMs.\r
+//   69  * \note Stored in EEPROM.\r
+//   70  */\r
+\r
+        RSEG EEPROM_I:XDATA:NOROOT(0)\r
+//   71 __eeprom unsigned char BattEEPROM[4][32];\r
+BattEEPROM:\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+        DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+//   72 \r
+//   73 \r
+//   74 //! Global that indicates current battery (0 = battery A, 1 = B)\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   75 unsigned char BattActive;\r
+BattActive:\r
+        DS 1\r
+//   76 \r
+//   77 \r
+//   78 /*! \brief RID lookup-table\r
+//   79  *\r
+//   80  * Contains Resistor ID data specified by manufacturer.\r
+//   81  *\r
+//   82  * \note Values have been calculated assuming a +/- 15% tolerance.\r
+//   83  */\r
+\r
+        RSEG NEAR_I:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_I>`\r
+//   84 const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
+RID:\r
+        DS 56\r
+        REQUIRE `?<Initializer for RID>`\r
+//   85   {558, 659, 3900, 550, 260, 300, 10},\r
+//   86   {744, 843, 6800, 750, 360, 300, 14},\r
+//   87   {869, 958, 10000, 1000, 475, 300, 19},\r
+//   88   {1097, 1153, 24000, 2000, 475, 420, 38}\r
+//   89 };\r
+//   90 \r
+//   91 \r
+//   92 /*! \brief NTC lookup-table\r
+//   93  *\r
+//   94  * The first entry is 0 degrees. For every entry after, temperature increases\r
+//   95  * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
+//   96  * It must be sorted in descending ADC order.\r
+//   97  *\r
+//   98  * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
+//   99  *\r
+//  100  * \note NTCLookUp() must be modified if this table is changed so that:\r
+//  101  * - first entry is no longer 0 degrees.\r
+//  102  * - temperature difference between entries is no longer 4 degrees.\r
+//  103  * - ADCsteps no longer specifies ADC steps per half degree.\r
+//  104  */\r
+//  105 // FOR VARTA POLYFLEX NTC\r
+\r
+        RSEG NEAR_I:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_I>`\r
+//  106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+NTC:\r
+        DS 60\r
+        REQUIRE `?<Initializer for NTC>`\r
+//  107        {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
+//  108        {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
+//  109        {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
+//  110        {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
+//  111 };\r
+//  112 \r
+//  113 \r
+//  114 // FOR MITSUBISHI NTC\r
+//  115 /*\r
+//  116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+//  117   {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
+//  118   {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
+//  119   {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
+//  120   {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
+//  121 };\r
+//  122 */\r
+//  123 \r
+//  124 \r
+//  125 //******************************************************************************\r
+//  126 // Functions\r
+//  127 //******************************************************************************\r
+//  128 /*! \brief Checks if battery has changed\r
+//  129  *\r
+//  130  * Stores current capacity, then attempts to refresh battery status.\n\r
+//  131  * If the refresh is successful, old capacity is compared with the new one.\r
+//  132  * \r
+//  133  * \retval FALSE Battery is disconnected, or capacity has changed.\r
+//  134  * \retval TRUE All OK.\r
+//  135  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  136 unsigned char BatteryCheck(void)\r
+BatteryCheck:\r
+//  137 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R24\r
+//  138        unsigned char success = TRUE;\r
+        LDI     R24, 1\r
+//  139        unsigned int  oldCapacity;\r
+//  140        \r
+//  141        // Save to see if battery data has changed.\r
+//  142        oldCapacity = BattData.Capacity;  \r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R26, Z+4\r
+        LDD     R27, Z+5\r
+//  143        \r
+//  144        if (!BatteryStatusRefresh()) {\r
+        RCALL   BatteryStatusRefresh\r
+        TST     R16\r
+        BRNE    ??BatteryCheck_0\r
+//  145                success = FALSE;              // Battery not present or RID was invalid.\r
+        LDI     R24, 0\r
+//  146        }\r
+//  147        \r
+//  148        if (oldCapacity != BattData.Capacity) {\r
+??BatteryCheck_0:\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        CP      R26, R16\r
+        CPC     R27, R17\r
+        BREQ    ??BatteryCheck_1\r
+//  149                success = FALSE;              // Battery configuration has changed.\r
+        LDI     R24, 0\r
+//  150        }\r
+//  151 \r
+//  152        return(success);\r
+??BatteryCheck_1:\r
+        MOV     R16, R24\r
+        LD      R24, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+//  153 }\r
+//  154 \r
+//  155 \r
+//  156 /*! \brief Refreshes battery status information\r
+//  157  *\r
+//  158  * Refreshes battery status information, if it is present, based on\r
+//  159  * RID and NTC (read by ADC).\n\r
+//  160  * The battery must have been enabled and a complete set of ADC data must have\r
+//  161  * been collected before calling.\n\r
+//  162  *\r
+//  163  * \retval FALSE No battery present.\r
+//  164  * \retval TRUE Battery present, status refreshed.\r
+//  165  *\r
+//  166  * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
+//  167  * is found in the lookup table. Instead, default battery data will be used.\r
+//  168  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  169 unsigned char BatteryStatusRefresh(void)\r
+BatteryStatusRefresh:\r
+//  170 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+//  171        // Assume the worst..\r
+//  172        unsigned char success = FALSE;\r
+//  173        \r
+//  174        BattData.Present = FALSE;\r
+//  175        BattData.Charged = FALSE;\r
+//  176        BattData.Low = TRUE;\r
+        LDI     R26, LOW(BattData)\r
+        LDI     R27, (BattData) >> 8\r
+        LD      R16, X\r
+        ANDI    R16, 0xFC\r
+        ORI     R16, 0x04\r
+        ST      X, R16\r
+//  177        BattData.Circuit = OW_NONE;\r
+        LDI     R16, 0\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+1, R16\r
+//  178        BattData.Temperature = 0;\r
+        STD     Z+2, R16\r
+//  179        BattData.Capacity = 0;\r
+        STD     Z+4, R16\r
+        STD     Z+5, R16\r
+//  180        BattData.MaxCurrent = 0;\r
+        STD     Z+6, R16\r
+        STD     Z+7, R16\r
+//  181        BattData.MaxTime = 0;\r
+        STD     Z+8, R16\r
+        STD     Z+9, R16\r
+//  182        BattData.MinCurrent = 0;\r
+        STD     Z+10, R16\r
+        STD     Z+11, R16\r
+//  183 \r
+//  184        NTCLookUp();\r
+        RCALL   NTCLookUp\r
+//  185        BattData.HasRID = RIDLookUp();\r
+        RCALL   RIDLookUp\r
+        MOV     R17, R16\r
+        ANDI    R17, 0x01\r
+        BST     R17, 0\r
+        LD      R16, X\r
+        BLD     R16, 4\r
+        ST      X, R16\r
+//  186 \r
+//  187        // Is the battery voltage above minimum safe cell voltage?\r
+//  188        if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        CPI     R16, 96\r
+        LDI     R18, 9\r
+        CPC     R17, R18\r
+        BRCS    ??BatteryStatusRefresh_0\r
+//  189                BattData.Low = FALSE;\r
+        LD      R16, X\r
+        ANDI    R16, 0xFB\r
+        ST      X, R16\r
+//  190        }\r
+//  191 \r
+//  192        // Is the battery charged?\r
+//  193        if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+??BatteryStatusRefresh_0:\r
+        LDD     R16, Z+10\r
+        CPI     R16, 210\r
+        SBCI    R17, 15\r
+        BRCS    ??BatteryStatusRefresh_1\r
+//  194                BattData.Charged = TRUE;\r
+        LD      R16, X\r
+        ORI     R16, 0x02\r
+        ST      X, R16\r
+//  195        }\r
+//  196 \r
+//  197        // If we are not charging, yet VBAT is above safe limit, battery is present.\r
+//  198        // If we are charging and there's a current flowing, the battery is present.\r
+//  199        \r
+//  200        /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
+//  201        * check is redundant since charging will be aborted due to low current at\r
+//  202        * max duty cycle. That is preferrable since the charge current reading is\r
+//  203        * not 100% proof.\r
+//  204        */\r
+//  205        if (((OCR1B == 0) && (!BattData.Low)) ||\r
+//  206            ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+??BatteryStatusRefresh_1:\r
+        IN      R16, 0x2C\r
+        TST     R16\r
+        BRNE    ??BatteryStatusRefresh_2\r
+        LD      R16, X\r
+        SBRS    R16, 2\r
+        RJMP    ??BatteryStatusRefresh_3\r
+??BatteryStatusRefresh_2:\r
+        IN      R16, 0x2C\r
+        TST     R16\r
+        BREQ    ??BatteryStatusRefresh_4\r
+        LDD     R24, Z+22\r
+        LDD     R25, Z+23\r
+        CPI     R24, 1\r
+        SBCI    R25, 0\r
+        BRLT    ??BatteryStatusRefresh_4\r
+//  207                BattData.Present = TRUE;\r
+??BatteryStatusRefresh_3:\r
+        LD      R16, X\r
+        ORI     R16, 0x01\r
+        ST      X, R16\r
+//  208                success = TRUE;\r
+        LDI     R16, 1\r
+        RJMP    ??BatteryStatusRefresh_5\r
+//  209        } else {\r
+//  210                BattData.Low = FALSE;  // (This is just a technicality..)\r
+??BatteryStatusRefresh_4:\r
+        LD      R16, X\r
+        ANDI    R16, 0xFB\r
+        ST      X, R16\r
+//  211                success = FALSE;\r
+        LDI     R16, 0\r
+//  212        }\r
+//  213 \r
+//  214 #ifndef ALLOW_NO_RID\r
+//  215        // Return FALSE if no valid RID entry was found, to stop charging.\r
+//  216        if(!BattData.HasRID) {\r
+??BatteryStatusRefresh_5:\r
+        LD      R17, X\r
+        SBRS    R17, 4\r
+//  217                success = FALSE;\r
+        LDI     R16, 0\r
+//  218        }\r
+//  219 #endif\r
+//  220 \r
+//  221        return(success);\r
+??BatteryStatusRefresh_6:\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  222 }\r
+//  223 \r
+//  224 \r
+//  225 /*! \brief Refreshes battery data in the EEPROM\r
+//  226  *\r
+//  227  * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
+//  228  * these data in on-chip EEPROM.\n\r
+//  229  * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
+//  230  *\r
+//  231  * \todo Updating BattData with these data. Specs needed.\r
+//  232  *\r
+//  233  * \retval FALSE Refresh failed.\r
+//  234  * \retval TRUE Refresh successful.\r
+//  235  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  236 unsigned char BatteryDataRefresh(void)\r
+BatteryDataRefresh:\r
+//  237 {\r
+        ST      -Y, R8\r
+        ST      -Y, R7\r
+        ST      -Y, R6\r
+        ST      -Y, R5\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        REQUIRE ?Register_R7_is_cg_reg\r
+        REQUIRE ?Register_R8_is_cg_reg\r
+//  238        unsigned char offset;\r
+//  239        unsigned char i, crc, family, temp, page;\r
+//  240        unsigned char success;\r
+//  241        \r
+//  242        // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
+//  243        for (page = 0; page < 4; page++)        {\r
+        LDI     R25, 0\r
+        LDI     R26, LOW(BattEEPROM)\r
+        LDI     R27, (BattEEPROM) >> 8\r
+//  244                success = FALSE;\r
+??BatteryDataRefresh_0:\r
+        CLR     R7\r
+//  245        \r
+//  246                if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
+        LDI     R16, 1\r
+        RCALL   OWI_DetectPresence\r
+        CPI     R16, 1\r
+        BREQ    $+2+2\r
+        RJMP    ??BatteryDataRefresh_1\r
+//  247                        \r
+//  248                        // Presence detected, check type and CRC.\r
+//  249                        OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
+        LDI     R17, 1\r
+        LDI     R16, 51\r
+        RCALL   OWI_SendByte\r
+//  250                        family = OWI_ReceiveByte(OWIBUS);\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R5, R16\r
+//  251                        crc = OWI_ComputeCRC8(family,0);\r
+        LDI     R17, 0\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R24, R16\r
+//  252 \r
+//  253                        for (i = 0; i < 6; i++) {\r
+        LDI     R16, 6\r
+        MOV     R4, R16\r
+//  254                                crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
+??BatteryDataRefresh_2:\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R24\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R24, R16\r
+//  255                        }\r
+        DEC     R4\r
+        BRNE    ??BatteryDataRefresh_2\r
+//  256 \r
+//  257                        // CRC ok, device found.\r
+//  258                        if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R24\r
+        RCALL   OWI_ComputeCRC8\r
+        TST     R16\r
+        BRNE    ??BatteryDataRefresh_1\r
+//  259                                BattData.Circuit = family;\r
+        STS     (BattData + 1), R5\r
+//  260 \r
+//  261                                // For now, we only read data from DS2505 EPROMs.\r
+//  262                                if (BattData.Circuit == OW_DS2505) {\r
+        LDS     R16, (BattData + 1)\r
+        CPI     R16, 9\r
+        BRNE    ??BatteryDataRefresh_1\r
+//  263                                        offset = page*32;\r
+        MOV     R4, R25\r
+        SWAP    R4\r
+        LDI     R16, 240\r
+        AND     R4, R16\r
+        LSL     R4\r
+//  264                                        OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
+        LDI     R17, 1\r
+        LDI     R16, 195\r
+        RCALL   OWI_SendByte\r
+//  265                                        OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
+        LDI     R17, 1\r
+        MOV     R16, R4\r
+        RCALL   OWI_SendByte\r
+//  266                                        OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
+        LDI     R17, 1\r
+        LDI     R16, 0\r
+        RCALL   OWI_SendByte\r
+//  267 \r
+//  268                                        // Calculate checksums.\r
+//  269                                        crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
+        LDI     R17, 0\r
+        LDI     R16, 195\r
+        RCALL   OWI_ComputeCRC8\r
+//  270                                        crc = OWI_ComputeCRC8(offset,crc);\r
+        MOV     R17, R16\r
+        MOV     R16, R4\r
+        RCALL   OWI_ComputeCRC8\r
+//  271                                        crc = OWI_ComputeCRC8(0,crc);\r
+        MOV     R17, R16\r
+        LDI     R16, 0\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R24, R16\r
+//  272 \r
+//  273                                        // Command received succesfully, now start reading data\r
+//  274                                        // and writing it to EEPROM.\r
+//  275                                        if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R24\r
+        RCALL   OWI_ComputeCRC8\r
+        TST     R16\r
+        BRNE    ??BatteryDataRefresh_1\r
+//  276                                                crc = 0;\r
+        LDI     R24, 0\r
+//  277                                                \r
+//  278                                                // Fill page with data.\r
+//  279                                                for (i=0; i<32; i++) {\r
+        MOVW    R5:R4, R27:R26\r
+        LDI     R16, 32\r
+        MOV     R6, R16\r
+//  280                                                        temp = OWI_ReceiveByte(OWIBUS);\r
+??BatteryDataRefresh_3:\r
+        LDI     R16, 1\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R8, R16\r
+//  281                                                        crc = OWI_ComputeCRC8(temp, crc);\r
+        MOV     R17, R24\r
+        RCALL   OWI_ComputeCRC8\r
+        MOV     R24, R16\r
+//  282                                                        BattEEPROM[page][i] = temp;\r
+        MOV     R16, R8\r
+        MOVW    R21:R20, R5:R4\r
+        RCALL   __eeput8_16\r
+//  283                                                }\r
+        LDI     R16, 1\r
+        ADD     R4, R16\r
+        ADC     R5, R7\r
+        DEC     R6\r
+        BRNE    ??BatteryDataRefresh_3\r
+//  284                                                \r
+//  285                                                if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+        RCALL   OWI_ReceiveByte\r
+        MOV     R17, R24\r
+        RCALL   OWI_ComputeCRC8\r
+        TST     R16\r
+        BRNE    ??BatteryDataRefresh_1\r
+//  286                                                                success = TRUE;  // Data read OK\r
+        INC     R7\r
+        RJMP    ??BatteryDataRefresh_4\r
+//  287                                                }\r
+//  288                                        } else { // Not able to start reading data.\r
+//  289                                        }\r
+//  290                                } else { // Wrong device type.\r
+//  291                                }\r
+//  292                        } else { // No device found.             \r
+//  293                        }\r
+//  294                } else { // No presence detected on one-wire bus.\r
+//  295                }\r
+//  296 \r
+//  297          // Erase local EEPROM page if there were any errors during transfer.\r
+//  298                if (!success) {\r
+//  299                        for (i=0; i<32; i++) {\r
+??BatteryDataRefresh_1:\r
+        MOVW    R21:R20, R27:R26\r
+        LDI     R17, 32\r
+//  300                                BattEEPROM[page][i] = 0;\r
+??BatteryDataRefresh_5:\r
+        LDI     R16, 0\r
+        RCALL   __eeput8_16\r
+//  301                        }\r
+        SUBI    R20, 255\r
+        SBCI    R21, 255\r
+        DEC     R17\r
+        BRNE    ??BatteryDataRefresh_5\r
+//  302                }\r
+//  303        }\r
+??BatteryDataRefresh_4:\r
+        INC     R25\r
+        ADIW    R27:R26, 32\r
+        CPI     R25, 4\r
+        BRCC    $+2+2\r
+        RJMP    ??BatteryDataRefresh_0\r
+//  304 \r
+//  305        return(success);\r
+        MOV     R16, R7\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        LD      R5, Y+\r
+        LD      R6, Y+\r
+        LD      R7, Y+\r
+        LD      R8, Y+\r
+        RET\r
+//  306 }\r
+//  307 \r
+//  308 \r
+//  309 /*! \brief Enables specified battery\r
+//  310  *\r
+//  311  * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
+//  312  * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
+//  313  * The function takes 100 ms to allow the port switch to settle.\r
+//  314  *\r
+//  315  * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
+//  316  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  317 void EnableBattery(unsigned char bat)\r
+EnableBattery:\r
+//  318 {\r
+        ST      -Y, R24\r
+        MOV     R24, R16\r
+//  319        // Use general timer, set timeout to 100ms.\r
+//  320        Time_Set(TIMER_GEN,0,0,100);\r
+        LDI     R20, 100\r
+        LDI     R17, 0\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 2\r
+        RCALL   Time_Set\r
+//  321 \r
+//  322        // Set specified battery as the active one.\r
+//  323        BattActive = bat;\r
+        STS     BattActive, R24\r
+//  324 \r
+//  325        // Enable current battery in hardware, light LED & connect battery.\r
+//  326        PORTB |= (1 << (PB4+bat));\r
+        LDI     R16, 1\r
+        LDI     R17, 0\r
+        MOV     R20, R24\r
+        SUBI    R20, 252\r
+        RCALL   ?S_SHL_L02\r
+        IN      R17, 0x18\r
+        OR      R17, R16\r
+        OUT     0x18, R17\r
+//  327 \r
+//  328        // Disconnect other battery.\r
+//  329        PORTB &= ~(1<<(PB5-bat));     \r
+        LDI     R16, 1\r
+        LDI     R17, 0\r
+        LDI     R20, 5\r
+        SUB     R20, R24\r
+        RCALL   ?S_SHL_L02\r
+        COM     R16\r
+        IN      R17, 0x18\r
+        AND     R17, R16\r
+        OUT     0x18, R17\r
+//  330 \r
+//  331        do { // Let port switch settle.\r
+//  332        } while (Time_Left(TIMER_GEN));  \r
+??EnableBattery_0:\r
+        LDI     R16, 2\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??EnableBattery_0\r
+//  333 }\r
+        LD      R24, Y+\r
+        RET\r
+        REQUIRE _A_PORTB\r
+//  334 \r
+//  335 \r
+//  336 /*! \brief Disables both batteries\r
+//  337  *\r
+//  338  * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
+//  339  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  340 void DisableBatteries(void)\r
+DisableBatteries:\r
+//  341 {\r
+//  342        // Turn off LEDs and disconnect batteries.\r
+//  343        PORTB &= ~((1<<PB4)|(1<<PB5));  \r
+        IN      R16, 0x18\r
+        ANDI    R16, 0xCF\r
+        OUT     0x18, R16\r
+//  344 }\r
+        RET\r
+        REQUIRE _A_PORTB\r
+//  345 \r
+//  346 \r
+//  347 /*! \brief Looks up battery data from RID table\r
+//  348  *\r
+//  349  * Attempts to find data for the battery from the RID lookup-table.\n\r
+//  350  * If no valid entry is found, default data (defined in battery.h)\r
+//  351  * are used.\r
+//  352  *\r
+//  353  * \retval TRUE Entry found, battery data updated.\r
+//  354  * \retval FALSE No entry found, using defaults for battery data.\r
+//  355  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  356 unsigned char RIDLookUp (void)\r
+RIDLookUp:\r
+//  357 {\r
+        MOV     R19, R27\r
+        MOV     R2, R26\r
+//  358        unsigned char i, found = FALSE;\r
+        LDI     R20, 0\r
+//  359                \r
+//  360        // Lookup in the RID-table. If measured RID is within the limits\r
+//  361        // of an entry, those data are used, and TRUE is returned.\r
+//  362        for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
+        LDI     R30, LOW(RID)\r
+        LDI     R31, (RID) >> 8\r
+        LDI     R18, 4\r
+        LDI     R16, LOW(BattData)\r
+        LDI     R17, (BattData) >> 8\r
+//  363                if (ADCS.rawRID >= RID[i].Low) {\r
+??RIDLookUp_0:\r
+        LDI     R26, LOW((ADCS + 2))\r
+        LDI     R27, HIGH((ADCS + 2))\r
+        LD      R22, X+\r
+        LD      R23, X\r
+        LD      R0, Z\r
+        LDD     R1, Z+1\r
+        CP      R22, R0\r
+        CPC     R23, R1\r
+        BRCS    ??RIDLookUp_1\r
+//  364                        if (ADCS.rawRID <= RID[i].High) {\r
+        LDD     R0, Z+2\r
+        LDD     R1, Z+3\r
+        CP      R0, R22\r
+        CPC     R1, R23\r
+        BRCS    ??RIDLookUp_1\r
+//  365                                BattData.Capacity = RID[i].Capacity;\r
+        LDD     R20, Z+6\r
+        LDD     R21, Z+7\r
+        MOVW    R27:R26, R17:R16\r
+        ADIW    R27:R26, 4\r
+        ST      X+, R20\r
+        ST      X, R21\r
+//  366                                BattData.MaxCurrent = RID[i].Icharge;\r
+        LDD     R20, Z+8\r
+        LDD     R21, Z+9\r
+        MOVW    R27:R26, R17:R16\r
+        ADIW    R27:R26, 6\r
+        ST      X+, R20\r
+        ST      X, R21\r
+//  367                                BattData.MaxTime = RID[i].tCutOff;\r
+        LDD     R20, Z+10\r
+        LDD     R21, Z+11\r
+        MOVW    R27:R26, R17:R16\r
+        ADIW    R27:R26, 8\r
+        ST      X+, R20\r
+        ST      X, R21\r
+//  368                                BattData.MinCurrent = RID[i].ICutOff;\r
+        LDD     R20, Z+12\r
+        LDD     R21, Z+13\r
+        MOVW    R27:R26, R17:R16\r
+        ADIW    R27:R26, 10\r
+        ST      X+, R20\r
+        ST      X, R21\r
+//  369                                \r
+//  370                                found = TRUE;\r
+        LDI     R20, 1\r
+//  371                        }\r
+//  372                }\r
+//  373        }\r
+??RIDLookUp_1:\r
+        ADIW    R31:R30, 14\r
+        DEC     R18\r
+        BRNE    ??RIDLookUp_0\r
+//  374        \r
+//  375        // If no valid entry is found, use defaults and return FALSE.\r
+//  376        if (!found) {\r
+        TST     R20\r
+        BRNE    ??RIDLookUp_2\r
+//  377                BattData.Capacity = DEF_BAT_CAPACITY;\r
+        LDI     R18, 0\r
+        MOVW    R31:R30, R17:R16\r
+        STD     Z+4, R18\r
+        STD     Z+5, R18\r
+//  378                BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
+        STD     Z+6, R18\r
+        STD     Z+7, R18\r
+//  379                BattData.MaxTime = DEF_BAT_TIME_MAX;\r
+        STD     Z+8, R18\r
+        STD     Z+9, R18\r
+//  380                BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
+        STD     Z+10, R18\r
+        STD     Z+11, R18\r
+//  381        }\r
+//  382        \r
+//  383        return(found);\r
+??RIDLookUp_2:\r
+        MOV     R16, R20\r
+        MOV     R26, R2\r
+        MOV     R27, R19\r
+        RET\r
+//  384 }\r
+//  385 \r
+//  386 \r
+//  387 /*! \brief Calculates temperature from a lookup table\r
+//  388  *\r
+//  389  * Looks up the highest NTC value below or equal to the measured one.\n\r
+//  390  * With the current lookup table, temperature is calculated with the formula:\n\r
+//  391  * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
+//  392  *\r
+//  393  * \note If the NTC-measurement is saturated, with the current lookup table,\r
+//  394  * the temperature will be reported as -1 C.\r
+//  395  *\r
+//  396  * \note If no valid entry is found, battery temperature is set to 80.\r
+//  397  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  398 void NTCLookUp (void)\r
+NTCLookUp:\r
+//  399 {\r
+        ST      -Y, R27\r
+        MOV     R3, R26\r
+        MOV     R2, R24\r
+//  400        unsigned char i;\r
+//  401        unsigned char found = FALSE;\r
+        LDI     R16, 0\r
+//  402        \r
+//  403        // Lookup in the NTC-table. Use the first entry which is equal or below\r
+//  404        // sampled NTC. Calculate temperature by using the index number, and the\r
+//  405        // difference between the measured NTC value and the one in the entry.\r
+//  406        for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
+        LDI     R24, 0\r
+        LDI     R26, LOW(BattData)\r
+        LDI     R27, (BattData) >> 8\r
+//  407                if (ADCS.rawNTC >= NTC[i].ADC) {\r
+??NTCLookUp_0:\r
+        MOV     R20, R24\r
+        LDI     R21, 0\r
+        MOVW    R19:R18, R21:R20\r
+        LSL     R20\r
+        ROL     R21\r
+        ADD     R20, R18\r
+        ADC     R21, R19\r
+        LDI     R18, LOW(NTC)\r
+        LDI     R19, (NTC) >> 8\r
+        ADD     R18, R20\r
+        ADC     R19, R21\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R20, Z+4\r
+        LDD     R21, Z+5\r
+        MOVW    R31:R30, R19:R18\r
+        LD      R22, Z\r
+        LDD     R23, Z+1\r
+        CP      R20, R22\r
+        CPC     R21, R23\r
+        BRCS    ??NTCLookUp_1\r
+//  408                        BattData.Temperature = (i<<2) ;\r
+        MOV     R16, R24\r
+        LSL     R16\r
+        LSL     R16\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+2, R16\r
+//  409                        BattData.ADCSteps = NTC[i].ADCsteps;  \r
+        MOVW    R31:R30, R19:R18\r
+        LDD     R20, Z+2\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+3, R20\r
+//  410                        BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;\r
+        LDS     R16, (ADCS + 4)\r
+        MOV     R17, R21\r
+        MOVW    R31:R30, R19:R18\r
+        LD      R18, Z\r
+        LDD     R19, Z+1\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        LSL     R16\r
+        ROL     R17\r
+        LDI     R21, 0\r
+        RCALL   ?US_DIVMOD_L02\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R17, Z+2\r
+        SUB     R17, R16\r
+        STD     Z+2, R17\r
+//  411                        \r
+//  412                        found = TRUE;  // Could be done with a break, but that violates MISRA.\r
+        LDI     R16, 1\r
+//  413                }\r
+//  414        }\r
+??NTCLookUp_1:\r
+        INC     R24\r
+        CPI     R24, 20\r
+        BRCC    ??NTCLookUp_2\r
+        TST     R16\r
+        BREQ    ??NTCLookUp_0\r
+//  415        \r
+//  416        // For safety, is temperature is greater than the NTC \r
+//  417        if (!found) {\r
+??NTCLookUp_2:\r
+        TST     R16\r
+        BRNE    ??NTCLookUp_3\r
+//  418                BattData.Temperature = 80;\r
+        LDI     R16, 80\r
+        STS     (BattData + 2), R16\r
+//  419        }\r
+//  420 }\r
+??NTCLookUp_3:\r
+        MOV     R24, R2\r
+        MOV     R26, R3\r
+        LD      R27, Y+\r
+        RET\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        RSEG NEAR_ID:CODE:NOROOT(0)\r
+`?<Initializer for RID>`:\r
+        DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14\r
+        DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475\r
+        DW 420, 38\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_I>`:\r
+        DW      SFE(NEAR_I) - SFB(NEAR_I)\r
+        DW      SFB(NEAR_I)\r
+        DW      SFB(NEAR_ID)\r
+        REQUIRE ?need_segment_init\r
+\r
+        RSEG NEAR_ID:CODE:NOROOT(0)\r
+`?<Initializer for NTC>`:\r
+        DW 1002\r
+        DB 23\r
+        DW 953\r
+        DB 25\r
+        DW 902\r
+        DB 26\r
+        DW 849\r
+        DB 27\r
+        DW 796\r
+        DB 27\r
+        DW 742\r
+        DB 27\r
+        DW 689\r
+        DB 26\r
+        DW 637\r
+        DB 26\r
+        DW 587\r
+        DB 25\r
+        DW 539\r
+        DB 24\r
+        DW 494\r
+        DB 22\r
+        DW 451\r
+        DB 21\r
+        DW 412\r
+        DB 19\r
+        DW 375\r
+        DB 18\r
+        DW 341\r
+        DB 17\r
+        DW 310\r
+        DB 15\r
+        DW 282\r
+        DB 14\r
+        DW 256\r
+        DB 13\r
+        DW 233\r
+        DB 11\r
+        DW 212\r
+        DB 10\r
+\r
+        END\r
+// \r
+//   2 bytes in segment ABSOLUTE\r
+// 804 bytes in segment CODE\r
+// 130 bytes in segment EEPROM_I\r
+//  12 bytes in segment INITTAB\r
+// 116 bytes in segment NEAR_I\r
+// 116 bytes in segment NEAR_ID\r
+//  13 bytes in segment NEAR_Z\r
+// \r
+// 920 bytes of CODE  memory (+ 12 bytes shared)\r
+// 129 bytes of DATA  memory (+  2 bytes shared)\r
+// 130 bytes of XDATA memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/chargefunc.lst b/BaseTinyFirmware/IAR/Release/List/chargefunc.lst
new file mode 100644 (file)
index 0000000..1bc2244
--- /dev/null
@@ -0,0 +1,870 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:01 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\chargefunc.c    #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\chargefunc.c    #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\ch #\r
+#                             argefunc.lst                                    #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\cha #\r
+#                             rgefunc.r90                                     #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\chargefunc.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Charge functions\r
+      6           *\r
+      7           *      Contains the functions for charging with constant current and voltage,\r
+      8           *      and for deciding when to halt.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13           *\r
+     14           * \par Documentation\r
+     15           *      For comprehensive code documentation, supported compilers, compiler \r
+     16           *      settings and supported devices see readme.html\r
+     17           *\r
+     18           * \author\r
+     19           *      Atmel Corporation: http://www.atmel.com \n\r
+     20           *      Support email: avr@atmel.com\r
+     21           *\r
+     22           * \r
+     23           * $Name$\r
+     24           * $Revision: 2299 $\r
+     25           * $RCSfile$\r
+     26           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $\r
+     27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     28           ******************************************************************************/\r
+     29          \r
+     30          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x4c\r
+   \   <unnamed> volatile __io _A_OCR1B\r
+   \                     _A_OCR1B:\r
+   \   00000000                      DS 1\r
+     31          \r
+     32          #include "enums.h"\r
+     33          #include "structs.h"\r
+     34          \r
+     35          #include "ADC.h"\r
+     36          #include "battery.h"\r
+     37          #include "chargefunc.h"\r
+     38          #include "main.h"\r
+     39          #include "menu.h"\r
+     40          #include "PWM.h"\r
+     41          #include "statefunc.h"\r
+     42          #include "time.h"\r
+     43          \r
+     44          #ifdef NIMH\r
+     45          #include "NIMHspecs.h"\r
+     46          #endif // NIMH\r
+     47          \r
+     48          #ifdef LIION\r
+     49          #include "LIIONspecs.h"\r
+     50          #endif // LIION\r
+     51          \r
+     52          \r
+     53          //******************************************************************************\r
+     54          // Variables\r
+     55          //******************************************************************************\r
+     56          //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     57          ChargeParameters_t ChargeParameters;\r
+     58          \r
+     59          //! Struct that holds parameters for HaltNow().\r
+     60          HaltParameters_t HaltParameters;\r
+   \                     HaltParameters:\r
+   \   00000000                      DS 17\r
+   \                     ChargeParameters:\r
+   \   00000011                      DS 5\r
+     61          \r
+     62          \r
+     63          //******************************************************************************\r
+     64          // Functions\r
+     65          //******************************************************************************\r
+     66          /*! \brief Charges battery with a constant current.\r
+     67           *\r
+     68           * This function applies a constant current (set in ChargeParameters.Current)\r
+     69           * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+     70           * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+     71           * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n\r
+     72           * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+     73           * Once the battery is no longer flagged for charge inhibit, timers are\r
+     74           * started again and charging resumed.\r
+     75           *\r
+     76           * \retval ChargeParameters.NextState Next state once this stage is done.\r
+     77           * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+     78           * HaltNow() will have set a new next state.\r
+     79           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     80          unsigned char ConstantCurrent(void)\r
+   \                     ConstantCurrent:\r
+     81          {\r
+   \   00000000   925A               ST      -Y, R5\r
+   \   00000002   924A               ST      -Y, R4\r
+   \   00000004   93BA               ST      -Y, R27\r
+   \   00000006   93AA               ST      -Y, R26\r
+   \   00000008   939A               ST      -Y, R25\r
+   \   0000000A   938A               ST      -Y, R24\r
+   \   0000000C                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   0000000C                      REQUIRE ?Register_R5_is_cg_reg\r
+     82                unsigned char error = FALSE,\r
+   \   0000000C   2455               CLR     R5\r
+     83                              wasStopped = FALSE;\r
+   \   0000000E   2444               CLR     R4\r
+     84                \r
+     85                do      {\r
+     86                // Wait for ADC conversions to complete.\r
+     87                        ADC_Wait();\r
+   \                     ??ConstantCurrent_0:\r
+   \   00000010   ....               RCALL   ADC_Wait\r
+     88          \r
+     89                        // If Master has flagged for a charge inhibit, pause charging.\r
+     90                        // (This is to prevent damage during prolonged serial communication.)\r
+     91                        if (BattControl[BattActive].ChargeInhibit) {\r
+   \   00000012   9100....           LDS     R16, BattActive\r
+   \   00000016   E010               LDI     R17, 0\r
+   \   00000018   ....               LDI     R20, LOW(BattControl)\r
+   \   0000001A   ....               LDI     R21, (BattControl) >> 8\r
+   \   0000001C   0F40               ADD     R20, R16\r
+   \   0000001E   1F51               ADC     R21, R17\r
+   \   00000020   ....               RCALL   __eeget8_16\r
+   \   00000022   7004               ANDI    R16, 0x04\r
+   \   00000024   F031               BREQ    ??ConstantCurrent_1\r
+     92                                wasStopped = TRUE;\r
+   \   00000026   2444               CLR     R4\r
+   \   00000028   9443               INC     R4\r
+     93                                Time_Stop();\r
+   \   0000002A   ....               RCALL   Time_Stop\r
+     94                                OCR1B = 0;\r
+   \   0000002C   E000               LDI     R16, 0\r
+   \   0000002E   BD0C               OUT     0x2C, R16\r
+   \   00000030   C025               RJMP    ??ConstantCurrent_2\r
+     95                        } else {\r
+     96                                // Continue charging!\r
+     97                                if (wasStopped) {\r
+   \                     ??ConstantCurrent_1:\r
+   \   00000032   2044               TST     R4\r
+   \   00000034   F011               BREQ    ??ConstantCurrent_3\r
+     98                                        wasStopped = FALSE;\r
+   \   00000036   2444               CLR     R4\r
+     99                                        \r
+    100                                        // Timer variables are not reset by this.\r
+    101                                        Time_Start();\r
+   \   00000038   ....               RCALL   Time_Start\r
+    102                                }\r
+    103                   \r
+    104                                // Adjust the charge current to within ChargeParameters.Current\r
+    105                                // +/- BAT_CURRENT_HYST.\r
+    106                                if ((ADCS.avgIBAT < 0) ||\r
+    107                                    (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+   \                     ??ConstantCurrent_3:\r
+   \   0000003A   ....               LDI     R30, LOW(ADCS)\r
+   \   0000003C   ....               LDI     R31, (ADCS) >> 8\r
+   \   0000003E   8906               LDD     R16, Z+22\r
+   \   00000040   8917               LDD     R17, Z+23\r
+   \   00000042   2311               TST     R17\r
+   \   00000044   F04A               BRMI    ??ConstantCurrent_4\r
+   \   00000046   ....               LDI     R26, LOW((HaltParameters + 19))\r
+   \   00000048   ....               LDI     R27, HIGH((HaltParameters + 19))\r
+   \   0000004A   91ED               LD      R30, X+\r
+   \   0000004C   91FC               LD      R31, X\r
+   \   0000004E   01CF               MOVW    R25:R24, R31:R30\r
+   \   00000050   9703               SBIW    R25:R24, 3\r
+   \   00000052   1708               CP      R16, R24\r
+   \   00000054   0719               CPC     R17, R25\r
+   \   00000056   F458               BRCC    ??ConstantCurrent_5\r
+    108                                                 \r
+    109                                        if(!PWM_IncrementDutyCycle()) {\r
+   \                     ??ConstantCurrent_4:\r
+   \   00000058   ....               RCALL   PWM_IncrementDutyCycle\r
+   \   0000005A   2300               TST     R16\r
+   \   0000005C   F479               BRNE    ??ConstantCurrent_2\r
+    110          #ifdef ABORT_IF_PWM_MAX\r
+    111                                        // If the duty cycle cannot be incremented, flag error and\r
+    112                                        // go to error state.\r
+    113                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+   \                     ??ConstantCurrent_6:\r
+   \   0000005E   E004               LDI     R16, 4\r
+   \   00000060   ....               RCALL   SetErrorFlag\r
+    114                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   00000062   E50A               LDI     R16, 90\r
+   \   00000064   9300....           STS     (HaltParameters + 21), R16\r
+    115                                                error = TRUE;\r
+   \   00000068   2455               CLR     R5\r
+   \   0000006A   9453               INC     R5\r
+   \   0000006C   C007               RJMP    ??ConstantCurrent_2\r
+    116          #endif\r
+    117                                        }\r
+    118                                } else if ((ADCS.avgIBAT >= 0) &&\r
+   \                     ??ConstantCurrent_5:\r
+   \   0000006E   9633               ADIW    R31:R30, 3\r
+   \   00000070   17E0               CP      R30, R16\r
+   \   00000072   07F1               CPC     R31, R17\r
+   \   00000074   F418               BRCC    ??ConstantCurrent_2\r
+    119                                         (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+    120                                                 \r
+    121                                        if(!PWM_DecrementDutyCycle()) {\r
+   \   00000076   ....               RCALL   PWM_DecrementDutyCycle\r
+   \   00000078   2300               TST     R16\r
+   \   0000007A   F389               BREQ    ??ConstantCurrent_6\r
+    122          #ifdef ABORT_IF_PWM_MIN\r
+    123                                                // If the duty cycle cannot be decremented, flag error and\r
+    124                                                // go to error state.\r
+    125                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+    126                                                ChargeParameters.NextState = ST_ERROR;\r
+    127                                                error = TRUE;\r
+    128          #endif\r
+    129                                        }\r
+    130                                }\r
+    131                        }\r
+    132                } while ((!HaltNow()) && (!error));\r
+   \                     ??ConstantCurrent_2:\r
+   \   0000007C   ....               RCALL   HaltNow\r
+   \   0000007E   2300               TST     R16\r
+   \   00000080   F411               BRNE    ??ConstantCurrent_7\r
+   \   00000082   2055               TST     R5\r
+   \   00000084   F229               BREQ    ??ConstantCurrent_0\r
+    133          \r
+    134                // Return the next state to Charge(). If an error has occured, this will\r
+    135                // point to some other state than the next state of charging.\r
+    136                return(ChargeParameters.NextState);\r
+   \                     ??ConstantCurrent_7:\r
+   \   00000086   9100....           LDS     R16, (HaltParameters + 21)\r
+   \   0000008A   9189               LD      R24, Y+\r
+   \   0000008C   9199               LD      R25, Y+\r
+   \   0000008E   91A9               LD      R26, Y+\r
+   \   00000090   91B9               LD      R27, Y+\r
+   \   00000092   9049               LD      R4, Y+\r
+   \   00000094   9059               LD      R5, Y+\r
+   \   00000096   9508               RET\r
+   \   00000098                      REQUIRE _A_OCR1B\r
+    137          }\r
+    138          \r
+    139          \r
+    140          /*! \brief Charges battery with a constant voltage\r
+    141           *\r
+    142           * This function applies a constant voltage (set in ChargeParameters.Voltage)\r
+    143           * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+    144           * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+    145           * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n\r
+    146           * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+    147           * Once the battery is no longer flagged for charge inhibit, timers are\r
+    148           * started again and charging resumed.\r
+    149           *\r
+    150           * \retval ChargeParameters.NextState Next state once this stage is done.\r
+    151           * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+    152           * HaltNow() will have set a new next state.\r
+    153           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    154          unsigned char ConstantVoltage(void)\r
+   \                     ConstantVoltage:\r
+    155          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   939A               ST      -Y, R25\r
+   \   00000006   938A               ST      -Y, R24\r
+    156                unsigned char error = FALSE,\r
+   \   00000008   E090               LDI     R25, 0\r
+    157                              wasStopped = FALSE;\r
+   \   0000000A   E080               LDI     R24, 0\r
+    158                \r
+    159                do{\r
+    160                        \r
+    161                        // Wait for ADC conversions to complete.\r
+    162                        ADC_Wait();\r
+   \                     ??ConstantVoltage_0:\r
+   \   0000000C   ....               RCALL   ADC_Wait\r
+    163                        \r
+    164                        // If Master has flagged for a charge inhibit, pause charging.\r
+    165                        // (This is to prevent damage during prolonged serial communication.)\r
+    166                        if (BattControl[BattActive].ChargeInhibit) {\r
+   \   0000000E   9100....           LDS     R16, BattActive\r
+   \   00000012   E010               LDI     R17, 0\r
+   \   00000014   ....               LDI     R20, LOW(BattControl)\r
+   \   00000016   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000018   0F40               ADD     R20, R16\r
+   \   0000001A   1F51               ADC     R21, R17\r
+   \   0000001C   ....               RCALL   __eeget8_16\r
+   \   0000001E   7004               ANDI    R16, 0x04\r
+   \   00000020   F029               BREQ    ??ConstantVoltage_1\r
+    167                                wasStopped = TRUE;\r
+   \   00000022   E081               LDI     R24, 1\r
+    168                                Time_Stop();\r
+   \   00000024   ....               RCALL   Time_Stop\r
+    169                                OCR1B = 0;\r
+   \   00000026   E000               LDI     R16, 0\r
+   \   00000028   BD0C               OUT     0x2C, R16\r
+   \   0000002A   C024               RJMP    ??ConstantVoltage_2\r
+    170                        }\r
+    171                        \r
+    172                        else {\r
+    173                                // Continue charging!\r
+    174                                if (wasStopped) {\r
+   \                     ??ConstantVoltage_1:\r
+   \   0000002C   2388               TST     R24\r
+   \   0000002E   F011               BREQ    ??ConstantVoltage_3\r
+    175                                        wasStopped = FALSE;\r
+   \   00000030   E080               LDI     R24, 0\r
+    176                                        \r
+    177                                        // Timer variables aren't reset by this.\r
+    178                                        Time_Start();\r
+   \   00000032   ....               RCALL   Time_Start\r
+    179                                }\r
+    180                                \r
+    181                                // Adjust the charge voltage to within ChargeParameters.Voltage\r
+    182                                // +/- BAT_VOLTAGE_HYST.\r
+    183                                if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+   \                     ??ConstantVoltage_3:\r
+   \   00000034   ....               LDI     R26, LOW(HaltParameters)\r
+   \   00000036   ....               LDI     R27, (HaltParameters) >> 8\r
+   \   00000038   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000003A   8901               LDD     R16, Z+17\r
+   \   0000003C   8912               LDD     R17, Z+18\r
+   \   0000003E   ....               LDI     R30, LOW(ADCS)\r
+   \   00000040   ....               LDI     R31, (ADCS) >> 8\r
+   \   00000042   8522               LDD     R18, Z+10\r
+   \   00000044   8533               LDD     R19, Z+11\r
+   \   00000046   01F8               MOVW    R31:R30, R17:R16\r
+   \   00000048   973A               SBIW    R31:R30, 10\r
+   \   0000004A   172E               CP      R18, R30\r
+   \   0000004C   073F               CPC     R19, R31\r
+   \   0000004E   F450               BRCC    ??ConstantVoltage_4\r
+    184          \r
+    185                                        if(!PWM_IncrementDutyCycle()) {\r
+   \   00000050   ....               RCALL   PWM_IncrementDutyCycle\r
+   \   00000052   2300               TST     R16\r
+   \   00000054   F479               BRNE    ??ConstantVoltage_2\r
+    186          #ifdef ABORT_IF_PWM_MAX\r
+    187                                        // Flag PWM control error and go to error-state if the duty\r
+    188                                        // cycle cannot be incremented.\r
+    189                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+   \                     ??ConstantVoltage_5:\r
+   \   00000056   E004               LDI     R16, 4\r
+   \   00000058   ....               RCALL   SetErrorFlag\r
+    190                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   0000005A   E50A               LDI     R16, 90\r
+   \   0000005C   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000005E   8B05               STD     Z+21, R16\r
+    191                                                error = TRUE;\r
+   \   00000060   E091               LDI     R25, 1\r
+   \   00000062   C008               RJMP    ??ConstantVoltage_2\r
+    192          #endif\r
+    193                                        }\r
+    194                                } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+   \                     ??ConstantVoltage_4:\r
+   \   00000064   5F06               SUBI    R16, 246\r
+   \   00000066   4F1F               SBCI    R17, 255\r
+   \   00000068   1702               CP      R16, R18\r
+   \   0000006A   0713               CPC     R17, R19\r
+   \   0000006C   F418               BRCC    ??ConstantVoltage_2\r
+    195          \r
+    196                                        if(!PWM_DecrementDutyCycle()) {\r
+   \   0000006E   ....               RCALL   PWM_DecrementDutyCycle\r
+   \   00000070   2300               TST     R16\r
+   \   00000072   F389               BREQ    ??ConstantVoltage_5\r
+    197          #ifdef ABORT_IF_PWM_MIN\r
+    198                                                // Flag PWM control error and go to error-state if duty\r
+    199                                                // cycle cannot be decremented.\r
+    200                                                SetErrorFlag(ERR_PWM_CONTROL);\r
+    201                                                ChargeParameters.NextState = ST_ERROR;\r
+    202                                                error = TRUE;\r
+    203          #endif\r
+    204                                        }\r
+    205                                }\r
+    206                        }\r
+    207          \r
+    208                } while ((!HaltNow()) && (!error));\r
+   \                     ??ConstantVoltage_2:\r
+   \   00000074   ....               RCALL   HaltNow\r
+   \   00000076   2300               TST     R16\r
+   \   00000078   F411               BRNE    ??ConstantVoltage_6\r
+   \   0000007A   2399               TST     R25\r
+   \   0000007C   F239               BREQ    ??ConstantVoltage_0\r
+    209          \r
+    210                // Return the next state to Charge(). If an error has occured, this will\r
+    211                // point to some other state than the next state of charging.\r
+    212                return(ChargeParameters.NextState);\r
+   \                     ??ConstantVoltage_6:\r
+   \   0000007E   9100....           LDS     R16, (HaltParameters + 21)\r
+   \   00000082   9189               LD      R24, Y+\r
+   \   00000084   9199               LD      R25, Y+\r
+   \   00000086   91A9               LD      R26, Y+\r
+   \   00000088   91B9               LD      R27, Y+\r
+   \   0000008A   9508               RET\r
+   \   0000008C                      REQUIRE _A_OCR1B\r
+    213          }\r
+    214          \r
+    215          \r
+    216          /*! \brief Determines when to halt charging.\r
+    217           *\r
+    218           * This function evaluates parameters depending on what has been flagged in\r
+    219           * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should\r
+    220           * halt or not.\n\r
+    221           * In addition, error flagging on timeout (battery exhaustion) can be set.\n\r
+    222           *\r
+    223           * The function also checks if the battery temperature is within limits,\r
+    224           * if mains is OK, and if BatteryCheck() returns TRUE.\r
+    225           * If an error is detected, the associated errorflag is set and \r
+    226           * ChargeParameters.NextState is changed to an appropriate state.\r
+    227           *\r
+    228           * \retval TRUE Halt now.\r
+    229           * \retval FALSE Don't halt now.\r
+    230           *\r
+    231           * \note See chargefunc.h for definitions of halt flags.\r
+    232           * \note It is generally a bad idea not to halt on a timeout.\r
+    233           * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be\r
+    234           * reset in Charge() before calling a charging-function.\r
+    235           *\r
+    236           * \todo "Priorities" of standard error checks OK?\r
+    237           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    238          unsigned char HaltNow(void)\r
+   \                     HaltNow:\r
+    239          {\r
+   \   00000000   929A               ST      -Y, R9\r
+   \   00000002   928A               ST      -Y, R8\r
+   \   00000004   927A               ST      -Y, R7\r
+   \   00000006   926A               ST      -Y, R6\r
+   \   00000008   925A               ST      -Y, R5\r
+   \   0000000A   924A               ST      -Y, R4\r
+   \   0000000C   93BA               ST      -Y, R27\r
+   \   0000000E   93AA               ST      -Y, R26\r
+   \   00000010   939A               ST      -Y, R25\r
+   \   00000012   938A               ST      -Y, R24\r
+   \   00000014                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000014                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000014                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000014                      REQUIRE ?Register_R7_is_cg_reg\r
+   \   00000014                      REQUIRE ?Register_R8_is_cg_reg\r
+   \   00000014                      REQUIRE ?Register_R9_is_cg_reg\r
+    240                unsigned char i, halt = FALSE;\r
+   \   00000014   2477               CLR     R7\r
+    241                \r
+    242                // Wait for a full ADC-cycle to finish.\r
+    243                ADC_Wait();\r
+   \   00000016   ....               RCALL   ADC_Wait\r
+    244          \r
+    245                // Evaluate ADC readings according to HaltFlags. Flag errors if selected.\r
+    246                // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.\r
+    247                // (Gets overridden if either mains is failing, or the battery changes.)\r
+    248                for (i = 0x01; i != 0; i <<= 1) {\r
+   \   00000018   2466               CLR     R6\r
+   \   0000001A   9463               INC     R6\r
+   \   0000001C   ....               LDI     R24, LOW(ADCS)\r
+   \   0000001E   ....               LDI     R25, (ADCS) >> 8\r
+   \   00000020   ....               LDI     R16, LOW(BattData)\r
+   \   00000022   2E40               MOV     R4, R16\r
+   \   00000024   ....               LDI     R16, (BattData) >> 8\r
+   \   00000026   2E50               MOV     R5, R16\r
+   \   00000028   ....               LDI     R26, LOW(HaltParameters)\r
+   \   0000002A   ....               LDI     R27, (HaltParameters) >> 8\r
+    249                        if (HaltParameters.HaltFlags & i) {\r
+   \                     ??HaltNow_0:\r
+   \   0000002C   910C               LD      R16, X\r
+   \   0000002E   2106               AND     R16, R6\r
+   \   00000030   F409               BRNE    $+2+2\r
+   \   00000032   C07C               RJMP    ??HaltNow_1\r
+    250                                switch (i) {\r
+   \   00000034   2D06               MOV     R16, R6\r
+   \   00000036   950A               DEC     R16\r
+   \   00000038   F051               BREQ    ??HaltNow_2\r
+   \   0000003A   950A               DEC     R16\r
+   \   0000003C   F109               BREQ    ??HaltNow_3\r
+   \   0000003E   5002               SUBI    R16, 2\r
+   \   00000040   F151               BREQ    ??HaltNow_4\r
+   \   00000042   5004               SUBI    R16, 4\r
+   \   00000044   F179               BREQ    ??HaltNow_5\r
+   \   00000046   5008               SUBI    R16, 8\r
+   \   00000048   F409               BRNE    $+2+2\r
+   \   0000004A   C053               RJMP    ??HaltNow_6\r
+   \   0000004C   C06F               RJMP    ??HaltNow_1\r
+    251                                // Is VBAT less than the recorded maximum?\r
+    252                                case HALT_VOLTAGE_DROP:\r
+    253          \r
+    254                                        // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
+    255                                        if (ADCS.VBAT > HaltParameters.VBATMax) {\r
+   \                     ??HaltNow_2:\r
+   \   0000004E   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000050   8505               LDD     R16, Z+13\r
+   \   00000052   8516               LDD     R17, Z+14\r
+   \   00000054   01FC               MOVW    R31:R30, R25:R24\r
+   \   00000056   8522               LDD     R18, Z+10\r
+   \   00000058   8533               LDD     R19, Z+11\r
+   \   0000005A   1702               CP      R16, R18\r
+   \   0000005C   0713               CPC     R17, R19\r
+   \   0000005E   F420               BRCC    ??HaltNow_7\r
+    256                                                HaltParameters.VBATMax = ADCS.VBAT;\r
+   \   00000060   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000062   8725               STD     Z+13, R18\r
+   \   00000064   8736               STD     Z+14, R19\r
+   \   00000066   C062               RJMP    ??HaltNow_1\r
+    257                                        } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+    258                                                  HaltParameters.VoltageDrop) {\r
+   \                     ??HaltNow_7:\r
+   \   00000068   1B02               SUB     R16, R18\r
+   \   0000006A   0B13               SBC     R17, R19\r
+   \   0000006C   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000006E   8121               LDD     R18, Z+1\r
+   \   00000070   8132               LDD     R19, Z+2\r
+   \   00000072   1702               CP      R16, R18\r
+   \   00000074   0713               CPC     R17, R19\r
+   \   00000076   F408               BRCC    $+2+2\r
+   \   00000078   C059               RJMP    ??HaltNow_1\r
+    259                                                halt = TRUE;\r
+   \                     ??HaltNow_8:\r
+   \   0000007A   2477               CLR     R7\r
+   \   0000007C   9473               INC     R7\r
+   \   0000007E   C056               RJMP    ??HaltNow_1\r
+    260                                        }\r
+    261                                break;\r
+    262          \r
+    263                                \r
+    264                                // Has VBAT reached the maximum limit?\r
+    265                                case HALT_VOLTAGE_MAX:  \r
+    266                                        \r
+    267                                        if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+   \                     ??HaltNow_3:\r
+   \   00000080   01FC               MOVW    R31:R30, R25:R24\r
+   \   00000082   8502               LDD     R16, Z+10\r
+   \   00000084   8513               LDD     R17, Z+11\r
+   \   00000086   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000088   8123               LDD     R18, Z+3\r
+   \   0000008A   8134               LDD     R19, Z+4\r
+   \                     ??HaltNow_9:\r
+   \   0000008C   1702               CP      R16, R18\r
+   \   0000008E   0713               CPC     R17, R19\r
+   \   00000090   F408               BRCC    $+2+2\r
+   \   00000092   C04C               RJMP    ??HaltNow_1\r
+   \   00000094   CFF2               RJMP    ??HaltNow_8\r
+    268                                                halt = TRUE;\r
+    269                                        }\r
+    270                                        break;\r
+    271          \r
+    272          \r
+    273                                // Has IBAT reached the minimum limit?\r
+    274                                case HALT_CURRENT_MIN:\r
+    275                                        \r
+    276                                        if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+   \                     ??HaltNow_4:\r
+   \   00000096   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000098   8105               LDD     R16, Z+5\r
+   \   0000009A   8116               LDD     R17, Z+6\r
+   \   0000009C   01FC               MOVW    R31:R30, R25:R24\r
+   \   0000009E   8926               LDD     R18, Z+22\r
+   \   000000A0   8937               LDD     R19, Z+23\r
+   \   000000A2   CFF4               RJMP    ??HaltNow_9\r
+    277                                                halt = TRUE;\r
+    278                                        }\r
+    279                                        break;\r
+    280                \r
+    281                                        \r
+    282                                // Is the temperature rising too fast?\r
+    283                                case HALT_TEMPERATURE_RISE:\r
+    284          \r
+    285                                        // If rawNTC has increased, the temperature has dropped.\r
+    286                                        // We can store this value for now, and start the timer.\r
+    287                                        // Otherwise, check if NTC has changed too fast.\r
+    288                                        if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
+   \                     ??HaltNow_5:\r
+   \   000000A4   01FC               MOVW    R31:R30, R25:R24\r
+   \   000000A6   8104               LDD     R16, Z+4\r
+   \   000000A8   8115               LDD     R17, Z+5\r
+   \   000000AA   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000AC   8487               LDD     R8, Z+15\r
+   \   000000AE   8890               LDD     R9, Z+16\r
+   \   000000B0   1680               CP      R8, R16\r
+   \   000000B2   0691               CPC     R9, R17\r
+   \   000000B4   F468               BRCC    ??HaltNow_10\r
+    289                                                HaltParameters.LastNTC = ADCS.rawNTC;\r
+   \                     ??HaltNow_11:\r
+   \   000000B6   01FC               MOVW    R31:R30, R25:R24\r
+   \   000000B8   8104               LDD     R16, Z+4\r
+   \   000000BA   8115               LDD     R17, Z+5\r
+   \   000000BC   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000BE   8707               STD     Z+15, R16\r
+   \   000000C0   8B10               STD     Z+16, R17\r
+    290                                                Time_Set(TIMER_TEMP,0,30,0);\r
+   \   000000C2   E040               LDI     R20, 0\r
+   \   000000C4   E11E               LDI     R17, 30\r
+   \   000000C6   E020               LDI     R18, 0\r
+   \   000000C8   E030               LDI     R19, 0\r
+   \   000000CA   E003               LDI     R16, 3\r
+   \   000000CC   ....               RCALL   Time_Set\r
+   \   000000CE   C02E               RJMP    ??HaltNow_1\r
+    291                                                \r
+    292                                        // Is the increase in temperature greater than the set threshold?\r
+    293                                        } else  if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+    294                                          (BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
+   \                     ??HaltNow_10:\r
+   \   000000D0   1A80               SUB     R8, R16\r
+   \   000000D2   0A91               SBC     R9, R17\r
+   \   000000D4   01F2               MOVW    R31:R30, R5:R4\r
+   \   000000D6   8143               LDD     R20, Z+3\r
+   \   000000D8   E050               LDI     R21, 0\r
+   \   000000DA   01FD               MOVW    R31:R30, R27:R26\r
+   \   000000DC   8503               LDD     R16, Z+11\r
+   \   000000DE   8514               LDD     R17, Z+12\r
+   \   000000E0   ....               RCALL   ?S_MUL_L02\r
+   \   000000E2   1480               CP      R8, R0\r
+   \   000000E4   0491               CPC     R9, R1\r
+   \   000000E6   F110               BRCS    ??HaltNow_1\r
+    295                                                \r
+    296                                                // If this happened within a timeframe of 30 seconds, the \r
+    297                                                // temperature is rising faster than we want.\r
+    298                                                // If not, update LastNTC and reset timer.\r
+    299                                                if (Time_Left(TIMER_TEMP))  {\r
+   \   000000E8   E003               LDI     R16, 3\r
+   \   000000EA   ....               RCALL   Time_Left\r
+   \   000000EC   2300               TST     R16\r
+   \   000000EE   F629               BRNE    ??HaltNow_8\r
+   \   000000F0   CFE2               RJMP    ??HaltNow_11\r
+    300                                                        halt = TRUE;\r
+    301                                                } else {\r
+    302                                                        HaltParameters.LastNTC = ADCS.rawNTC;\r
+    303                                                        Time_Set(TIMER_TEMP,0,30,0);\r
+    304                                                }\r
+    305                                        }\r
+    306                                break;\r
+    307                \r
+    308                                \r
+    309                                // Is there any time left?\r
+    310                                case HALT_TIME:  \r
+    311                                        \r
+    312                                        if (!Time_Left(TIMER_CHG)) {\r
+   \                     ??HaltNow_6:\r
+   \   000000F2   E001               LDI     R16, 1\r
+   \   000000F4   ....               RCALL   Time_Left\r
+   \   000000F6   2300               TST     R16\r
+   \   000000F8   F4C9               BRNE    ??HaltNow_1\r
+    313                                                halt = TRUE;\r
+   \   000000FA   2477               CLR     R7\r
+   \   000000FC   9473               INC     R7\r
+    314                                                \r
+    315                                                // If exhaustion flagging is selected, stop the PWM, disable the \r
+    316                                                // battery and flag it as exhausted. Make ST_ERROR next state.\r
+    317                                                if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
+   \   000000FE   910C               LD      R16, X\r
+   \   00000100   FF05               SBRS    R16, 5\r
+   \   00000102   C014               RJMP    ??HaltNow_1\r
+    318                                                                PWM_Stop();\r
+   \   00000104   ....               RCALL   PWM_Stop\r
+    319                                                                BattControl[BattActive].Enabled = FALSE;\r
+   \   00000106   9100....           LDS     R16, BattActive\r
+   \   0000010A   E010               LDI     R17, 0\r
+   \   0000010C   ....               LDI     R20, LOW(BattControl)\r
+   \   0000010E   ....               LDI     R21, (BattControl) >> 8\r
+   \   00000110   0F40               ADD     R20, R16\r
+   \   00000112   1F51               ADC     R21, R17\r
+   \   00000114   ....               RCALL   __eeget8_16\r
+   \   00000116   7F0E               ANDI    R16, 0xFE\r
+   \   00000118   ....               RCALL   __eeput8_16\r
+    320                                                                BattData.Exhausted = TRUE;\r
+   \   0000011A   01F2               MOVW    R31:R30, R5:R4\r
+   \   0000011C   8100               LD      R16, Z\r
+   \   0000011E   6008               ORI     R16, 0x08\r
+   \   00000120   8300               ST      Z, R16\r
+    321                                                                SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
+   \   00000122   E100               LDI     R16, 16\r
+   \   00000124   ....               RCALL   SetErrorFlag\r
+    322                                                                ChargeParameters.NextState = ST_ERROR;\r
+   \   00000126   E50A               LDI     R16, 90\r
+   \   00000128   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000012A   8B05               STD     Z+21, R16\r
+    323                                                }\r
+    324                                        }\r
+    325                                break;\r
+    326                                \r
+    327                                \r
+    328                                default:  // Shouldn't end up here, but is needed for MISRA compliance.\r
+    329                                break;\r
+    330                                }\r
+    331                        }\r
+    332                }\r
+   \                     ??HaltNow_1:\r
+   \   0000012C   0C66               LSL     R6\r
+   \   0000012E   F009               BREQ    $+2+2\r
+   \   00000130   CF7D               RJMP    ??HaltNow_0\r
+    333          \r
+    334                // Standard checks:\r
+    335          \r
+    336                // Battery too cold or hot?\r
+    337                if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||\r
+    338                    (BattData.Temperature >= HaltParameters.TemperatureMax)) {\r
+   \   00000132   ....               LDI     R30, LOW(BattData)\r
+   \   00000134   ....               LDI     R31, (BattData) >> 8\r
+   \   00000136   8102               LDD     R16, Z+2\r
+   \   00000138   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000013A   8521               LDD     R18, Z+9\r
+   \   0000013C   8532               LDD     R19, Z+10\r
+   \   0000013E   2F10               MOV     R17, R16\r
+   \   00000140   0F11               LSL     R17\r
+   \   00000142   0B11               SBC     R17, R17\r
+   \   00000144   1720               CP      R18, R16\r
+   \   00000146   0731               CPC     R19, R17\r
+   \   00000148   F444               BRGE    ??HaltNow_12\r
+   \   0000014A   2F10               MOV     R17, R16\r
+   \   0000014C   0F11               LSL     R17\r
+   \   0000014E   0B11               SBC     R17, R17\r
+   \   00000150   8127               LDD     R18, Z+7\r
+   \   00000152   8530               LDD     R19, Z+8\r
+   \   00000154   1702               CP      R16, R18\r
+   \   00000156   0713               CPC     R17, R19\r
+   \   00000158   F040               BRCS    ??HaltNow_13\r
+    339                                \r
+    340                        PWM_Stop();\r
+   \                     ??HaltNow_12:\r
+   \   0000015A   ....               RCALL   PWM_Stop\r
+    341                        SetErrorFlag(ERR_BATTERY_TEMPERATURE);\r
+   \   0000015C   E008               LDI     R16, 8\r
+   \   0000015E   ....               RCALL   SetErrorFlag\r
+    342                        ChargeParameters.NextState = ST_ERROR;\r
+   \   00000160   E50A               LDI     R16, 90\r
+   \   00000162   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000164   8B05               STD     Z+21, R16\r
+    343                        halt = TRUE;\r
+   \   00000166   2477               CLR     R7\r
+   \   00000168   9473               INC     R7\r
+    344                }\r
+    345          \r
+    346                // Battery not OK?\r
+    347                if (!BatteryCheck()) {\r
+   \                     ??HaltNow_13:\r
+   \   0000016A   ....               RCALL   BatteryCheck\r
+   \   0000016C   2300               TST     R16\r
+   \   0000016E   F431               BRNE    ??HaltNow_14\r
+    348                        PWM_Stop();\r
+   \   00000170   ....               RCALL   PWM_Stop\r
+    349                        ChargeParameters.NextState = ST_INIT;\r
+   \   00000172   E00A               LDI     R16, 10\r
+   \   00000174   01FD               MOVW    R31:R30, R27:R26\r
+   \   00000176   8B05               STD     Z+21, R16\r
+    350                        halt = TRUE;\r
+   \   00000178   2477               CLR     R7\r
+   \   0000017A   9473               INC     R7\r
+    351                }\r
+    352          \r
+    353                // Is mains voltage OK?\r
+    354                if (!ADCS.Mains) {\r
+   \                     ??HaltNow_14:\r
+   \   0000017C   9100....           LDS     R16, ADCS\r
+   \   00000180   FD06               SBRC    R16, 6\r
+   \   00000182   C006               RJMP    ??HaltNow_15\r
+    355                        PWM_Stop();\r
+   \   00000184   ....               RCALL   PWM_Stop\r
+    356                        ChargeParameters.NextState = ST_SLEEP;\r
+   \   00000186   E208               LDI     R16, 40\r
+   \   00000188   01FD               MOVW    R31:R30, R27:R26\r
+   \   0000018A   8B05               STD     Z+21, R16\r
+    357                        halt = TRUE;\r
+   \   0000018C   2477               CLR     R7\r
+   \   0000018E   9473               INC     R7\r
+    358                }\r
+    359          \r
+    360                return(halt);\r
+   \                     ??HaltNow_15:\r
+   \   00000190   2D07               MOV     R16, R7\r
+   \   00000192   9189               LD      R24, Y+\r
+   \   00000194   9199               LD      R25, Y+\r
+   \   00000196   91A9               LD      R26, Y+\r
+   \   00000198   91B9               LD      R27, Y+\r
+   \   0000019A   9049               LD      R4, Y+\r
+   \   0000019C   9059               LD      R5, Y+\r
+   \   0000019E   9069               LD      R6, Y+\r
+   \   000001A0   9079               LD      R7, Y+\r
+   \   000001A2   9089               LD      R8, Y+\r
+   \   000001A4   9099               LD      R9, Y+\r
+   \   000001A6   9508               RET\r
+    361          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function                    CSTACK RSTACK\r
+     --------                    ------ ------\r
+     ConstantCurrent                 6      4\r
+       -> ADC_Wait                   6      2\r
+       -> Time_Stop                  6      2\r
+       -> Time_Start                 6      2\r
+       -> PWM_IncrementDutyCycle     6      2\r
+       -> SetErrorFlag               6      2\r
+       -> PWM_DecrementDutyCycle     6      2\r
+       -> HaltNow                    6      2\r
+     ConstantVoltage                 4      4\r
+       -> ADC_Wait                   4      2\r
+       -> Time_Stop                  4      2\r
+       -> Time_Start                 4      2\r
+       -> PWM_IncrementDutyCycle     4      2\r
+       -> SetErrorFlag               4      2\r
+       -> PWM_DecrementDutyCycle     4      2\r
+       -> HaltNow                    4      2\r
+     HaltNow                        10      4\r
+       -> ADC_Wait                  10      2\r
+       -> Time_Set                  10      2\r
+       -> Time_Left                 10      2\r
+       -> Time_Left                 10      2\r
+       -> PWM_Stop                  10      2\r
+       -> SetErrorFlag              10      2\r
+       -> PWM_Stop                  10      2\r
+       -> SetErrorFlag              10      2\r
+       -> BatteryCheck              10      2\r
+       -> PWM_Stop                  10      2\r
+       -> PWM_Stop                  10      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label  Bytes\r
+     --------------  -----\r
+     _A_OCR1B           1\r
+     HaltParameters    22\r
+     ConstantCurrent  152\r
+     ConstantVoltage  140\r
+     HaltNow          424\r
+      Others            6\r
+\r
\r
+   1 byte  in segment ABSOLUTE\r
+ 716 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+  22 bytes in segment NEAR_Z\r
\r
+ 716 bytes of CODE memory (+ 6 bytes shared)\r
+  22 bytes of DATA memory (+ 1 byte  shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/chargefunc.s90 b/BaseTinyFirmware/IAR/Release/List/chargefunc.s90
new file mode 100644 (file)
index 0000000..3628818
--- /dev/null
@@ -0,0 +1,886 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:01 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\chargefunc.c   /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\chargefunc.c   /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\c /\r
+//                             hargefunc.s90                                  /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME chargefunc\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?Register_R7_is_cg_reg\r
+        EXTERN ?Register_R8_is_cg_reg\r
+        EXTERN ?Register_R9_is_cg_reg\r
+        EXTERN ?S_MUL_L02\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC ChargeParameters\r
+        PUBLIC ConstantCurrent\r
+        PUBLIC ConstantVoltage\r
+        PUBLIC HaltNow\r
+        PUBLIC HaltParameters\r
+        PUBWEAK _A_OCR1B\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN ADC_Wait\r
+        EXTERN Time_Stop\r
+        EXTERN Time_Start\r
+        EXTERN PWM_IncrementDutyCycle\r
+        EXTERN SetErrorFlag\r
+        EXTERN PWM_DecrementDutyCycle\r
+        EXTERN Time_Set\r
+        EXTERN Time_Left\r
+        EXTERN PWM_Stop\r
+        EXTERN BatteryCheck\r
+        EXTERN ADCS\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\chargefunc.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Charge functions\r
+//    6  *\r
+//    7  *      Contains the functions for charging with constant current and voltage,\r
+//    8  *      and for deciding when to halt.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13  *\r
+//   14  * \par Documentation\r
+//   15  *      For comprehensive code documentation, supported compilers, compiler \r
+//   16  *      settings and supported devices see readme.html\r
+//   17  *\r
+//   18  * \author\r
+//   19  *      Atmel Corporation: http://www.atmel.com \n\r
+//   20  *      Support email: avr@atmel.com\r
+//   21  *\r
+//   22  * \r
+//   23  * $Name$\r
+//   24  * $Revision: 2299 $\r
+//   25  * $RCSfile$\r
+//   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $\r
+//   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   28  ******************************************************************************/\r
+//   29 \r
+//   30 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,04cH\r
+// <unnamed> volatile __io _A_OCR1B\r
+_A_OCR1B:\r
+        DS 1\r
+//   31 \r
+//   32 #include "enums.h"\r
+//   33 #include "structs.h"\r
+//   34 \r
+//   35 #include "ADC.h"\r
+//   36 #include "battery.h"\r
+//   37 #include "chargefunc.h"\r
+//   38 #include "main.h"\r
+//   39 #include "menu.h"\r
+//   40 #include "PWM.h"\r
+//   41 #include "statefunc.h"\r
+//   42 #include "time.h"\r
+//   43 \r
+//   44 #ifdef NIMH\r
+//   45 #include "NIMHspecs.h"\r
+//   46 #endif // NIMH\r
+//   47 \r
+//   48 #ifdef LIION\r
+//   49 #include "LIIONspecs.h"\r
+//   50 #endif // LIION\r
+//   51 \r
+//   52 \r
+//   53 //******************************************************************************\r
+//   54 // Variables\r
+//   55 //******************************************************************************\r
+//   56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   57 ChargeParameters_t ChargeParameters;\r
+//   58 \r
+//   59 //! Struct that holds parameters for HaltNow().\r
+//   60 HaltParameters_t HaltParameters;\r
+HaltParameters:\r
+        DS 17\r
+ChargeParameters:\r
+        DS 5\r
+//   61 \r
+//   62 \r
+//   63 //******************************************************************************\r
+//   64 // Functions\r
+//   65 //******************************************************************************\r
+//   66 /*! \brief Charges battery with a constant current.\r
+//   67  *\r
+//   68  * This function applies a constant current (set in ChargeParameters.Current)\r
+//   69  * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+//   70  * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+//   71  * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n\r
+//   72  * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+//   73  * Once the battery is no longer flagged for charge inhibit, timers are\r
+//   74  * started again and charging resumed.\r
+//   75  *\r
+//   76  * \retval ChargeParameters.NextState Next state once this stage is done.\r
+//   77  * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+//   78  * HaltNow() will have set a new next state.\r
+//   79  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   80 unsigned char ConstantCurrent(void)\r
+ConstantCurrent:\r
+//   81 {\r
+        ST      -Y, R5\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+//   82        unsigned char error = FALSE,\r
+        CLR     R5\r
+//   83                      wasStopped = FALSE;\r
+        CLR     R4\r
+//   84        \r
+//   85        do      {\r
+//   86       // Wait for ADC conversions to complete.\r
+//   87                ADC_Wait();\r
+??ConstantCurrent_0:\r
+        RCALL   ADC_Wait\r
+//   88 \r
+//   89                // If Master has flagged for a charge inhibit, pause charging.\r
+//   90                // (This is to prevent damage during prolonged serial communication.)\r
+//   91                if (BattControl[BattActive].ChargeInhibit) {\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x04\r
+        BREQ    ??ConstantCurrent_1\r
+//   92                        wasStopped = TRUE;\r
+        CLR     R4\r
+        INC     R4\r
+//   93                        Time_Stop();\r
+        RCALL   Time_Stop\r
+//   94                        OCR1B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2C, R16\r
+        RJMP    ??ConstantCurrent_2\r
+//   95                } else {\r
+//   96                        // Continue charging!\r
+//   97                        if (wasStopped) {\r
+??ConstantCurrent_1:\r
+        TST     R4\r
+        BREQ    ??ConstantCurrent_3\r
+//   98                                wasStopped = FALSE;\r
+        CLR     R4\r
+//   99                                \r
+//  100                                // Timer variables are not reset by this.\r
+//  101                                Time_Start();\r
+        RCALL   Time_Start\r
+//  102                        }\r
+//  103          \r
+//  104                        // Adjust the charge current to within ChargeParameters.Current\r
+//  105                        // +/- BAT_CURRENT_HYST.\r
+//  106                        if ((ADCS.avgIBAT < 0) ||\r
+//  107                            (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+??ConstantCurrent_3:\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R16, Z+22\r
+        LDD     R17, Z+23\r
+        TST     R17\r
+        BRMI    ??ConstantCurrent_4\r
+        LDI     R26, LOW((HaltParameters + 19))\r
+        LDI     R27, HIGH((HaltParameters + 19))\r
+        LD      R30, X+\r
+        LD      R31, X\r
+        MOVW    R25:R24, R31:R30\r
+        SBIW    R25:R24, 3\r
+        CP      R16, R24\r
+        CPC     R17, R25\r
+        BRCC    ??ConstantCurrent_5\r
+//  108                                         \r
+//  109                                if(!PWM_IncrementDutyCycle()) {\r
+??ConstantCurrent_4:\r
+        RCALL   PWM_IncrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??ConstantCurrent_2\r
+//  110 #ifdef ABORT_IF_PWM_MAX\r
+//  111                                // If the duty cycle cannot be incremented, flag error and\r
+//  112                                // go to error state.\r
+//  113                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+??ConstantCurrent_6:\r
+        LDI     R16, 4\r
+        RCALL   SetErrorFlag\r
+//  114                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        STS     (HaltParameters + 21), R16\r
+//  115                                        error = TRUE;\r
+        CLR     R5\r
+        INC     R5\r
+        RJMP    ??ConstantCurrent_2\r
+//  116 #endif\r
+//  117                                }\r
+//  118                        } else if ((ADCS.avgIBAT >= 0) &&\r
+??ConstantCurrent_5:\r
+        ADIW    R31:R30, 3\r
+        CP      R30, R16\r
+        CPC     R31, R17\r
+        BRCC    ??ConstantCurrent_2\r
+//  119                                 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+//  120                                         \r
+//  121                                if(!PWM_DecrementDutyCycle()) {\r
+        RCALL   PWM_DecrementDutyCycle\r
+        TST     R16\r
+        BREQ    ??ConstantCurrent_6\r
+//  122 #ifdef ABORT_IF_PWM_MIN\r
+//  123                                        // If the duty cycle cannot be decremented, flag error and\r
+//  124                                        // go to error state.\r
+//  125                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+//  126                                        ChargeParameters.NextState = ST_ERROR;\r
+//  127                                        error = TRUE;\r
+//  128 #endif\r
+//  129                                }\r
+//  130                        }\r
+//  131                }\r
+//  132        } while ((!HaltNow()) && (!error));\r
+??ConstantCurrent_2:\r
+        RCALL   HaltNow\r
+        TST     R16\r
+        BRNE    ??ConstantCurrent_7\r
+        TST     R5\r
+        BREQ    ??ConstantCurrent_0\r
+//  133 \r
+//  134        // Return the next state to Charge(). If an error has occured, this will\r
+//  135        // point to some other state than the next state of charging.\r
+//  136        return(ChargeParameters.NextState);\r
+??ConstantCurrent_7:\r
+        LDS     R16, (HaltParameters + 21)\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        LD      R5, Y+\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  137 }\r
+//  138 \r
+//  139 \r
+//  140 /*! \brief Charges battery with a constant voltage\r
+//  141  *\r
+//  142  * This function applies a constant voltage (set in ChargeParameters.Voltage)\r
+//  143  * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+//  144  * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+//  145  * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n\r
+//  146  * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+//  147  * Once the battery is no longer flagged for charge inhibit, timers are\r
+//  148  * started again and charging resumed.\r
+//  149  *\r
+//  150  * \retval ChargeParameters.NextState Next state once this stage is done.\r
+//  151  * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+//  152  * HaltNow() will have set a new next state.\r
+//  153  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  154 unsigned char ConstantVoltage(void)\r
+ConstantVoltage:\r
+//  155 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+//  156        unsigned char error = FALSE,\r
+        LDI     R25, 0\r
+//  157                      wasStopped = FALSE;\r
+        LDI     R24, 0\r
+//  158        \r
+//  159        do{\r
+//  160                \r
+//  161                // Wait for ADC conversions to complete.\r
+//  162                ADC_Wait();\r
+??ConstantVoltage_0:\r
+        RCALL   ADC_Wait\r
+//  163                \r
+//  164                // If Master has flagged for a charge inhibit, pause charging.\r
+//  165                // (This is to prevent damage during prolonged serial communication.)\r
+//  166                if (BattControl[BattActive].ChargeInhibit) {\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x04\r
+        BREQ    ??ConstantVoltage_1\r
+//  167                        wasStopped = TRUE;\r
+        LDI     R24, 1\r
+//  168                        Time_Stop();\r
+        RCALL   Time_Stop\r
+//  169                        OCR1B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x2C, R16\r
+        RJMP    ??ConstantVoltage_2\r
+//  170                }\r
+//  171                \r
+//  172                else {\r
+//  173                        // Continue charging!\r
+//  174                        if (wasStopped) {\r
+??ConstantVoltage_1:\r
+        TST     R24\r
+        BREQ    ??ConstantVoltage_3\r
+//  175                                wasStopped = FALSE;\r
+        LDI     R24, 0\r
+//  176                                \r
+//  177                                // Timer variables aren't reset by this.\r
+//  178                                Time_Start();\r
+        RCALL   Time_Start\r
+//  179                        }\r
+//  180                        \r
+//  181                        // Adjust the charge voltage to within ChargeParameters.Voltage\r
+//  182                        // +/- BAT_VOLTAGE_HYST.\r
+//  183                        if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+??ConstantVoltage_3:\r
+        LDI     R26, LOW(HaltParameters)\r
+        LDI     R27, (HaltParameters) >> 8\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R16, Z+17\r
+        LDD     R17, Z+18\r
+        LDI     R30, LOW(ADCS)\r
+        LDI     R31, (ADCS) >> 8\r
+        LDD     R18, Z+10\r
+        LDD     R19, Z+11\r
+        MOVW    R31:R30, R17:R16\r
+        SBIW    R31:R30, 10\r
+        CP      R18, R30\r
+        CPC     R19, R31\r
+        BRCC    ??ConstantVoltage_4\r
+//  184 \r
+//  185                                if(!PWM_IncrementDutyCycle()) {\r
+        RCALL   PWM_IncrementDutyCycle\r
+        TST     R16\r
+        BRNE    ??ConstantVoltage_2\r
+//  186 #ifdef ABORT_IF_PWM_MAX\r
+//  187                                // Flag PWM control error and go to error-state if the duty\r
+//  188                                // cycle cannot be incremented.\r
+//  189                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+??ConstantVoltage_5:\r
+        LDI     R16, 4\r
+        RCALL   SetErrorFlag\r
+//  190                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+21, R16\r
+//  191                                        error = TRUE;\r
+        LDI     R25, 1\r
+        RJMP    ??ConstantVoltage_2\r
+//  192 #endif\r
+//  193                                }\r
+//  194                        } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+??ConstantVoltage_4:\r
+        SUBI    R16, 246\r
+        SBCI    R17, 255\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    ??ConstantVoltage_2\r
+//  195 \r
+//  196                                if(!PWM_DecrementDutyCycle()) {\r
+        RCALL   PWM_DecrementDutyCycle\r
+        TST     R16\r
+        BREQ    ??ConstantVoltage_5\r
+//  197 #ifdef ABORT_IF_PWM_MIN\r
+//  198                                        // Flag PWM control error and go to error-state if duty\r
+//  199                                        // cycle cannot be decremented.\r
+//  200                                        SetErrorFlag(ERR_PWM_CONTROL);\r
+//  201                                        ChargeParameters.NextState = ST_ERROR;\r
+//  202                                        error = TRUE;\r
+//  203 #endif\r
+//  204                                }\r
+//  205                        }\r
+//  206                }\r
+//  207 \r
+//  208        } while ((!HaltNow()) && (!error));\r
+??ConstantVoltage_2:\r
+        RCALL   HaltNow\r
+        TST     R16\r
+        BRNE    ??ConstantVoltage_6\r
+        TST     R25\r
+        BREQ    ??ConstantVoltage_0\r
+//  209 \r
+//  210        // Return the next state to Charge(). If an error has occured, this will\r
+//  211        // point to some other state than the next state of charging.\r
+//  212        return(ChargeParameters.NextState);\r
+??ConstantVoltage_6:\r
+        LDS     R16, (HaltParameters + 21)\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+        REQUIRE _A_OCR1B\r
+//  213 }\r
+//  214 \r
+//  215 \r
+//  216 /*! \brief Determines when to halt charging.\r
+//  217  *\r
+//  218  * This function evaluates parameters depending on what has been flagged in\r
+//  219  * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should\r
+//  220  * halt or not.\n\r
+//  221  * In addition, error flagging on timeout (battery exhaustion) can be set.\n\r
+//  222  *\r
+//  223  * The function also checks if the battery temperature is within limits,\r
+//  224  * if mains is OK, and if BatteryCheck() returns TRUE.\r
+//  225  * If an error is detected, the associated errorflag is set and \r
+//  226  * ChargeParameters.NextState is changed to an appropriate state.\r
+//  227  *\r
+//  228  * \retval TRUE Halt now.\r
+//  229  * \retval FALSE Don't halt now.\r
+//  230  *\r
+//  231  * \note See chargefunc.h for definitions of halt flags.\r
+//  232  * \note It is generally a bad idea not to halt on a timeout.\r
+//  233  * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be\r
+//  234  * reset in Charge() before calling a charging-function.\r
+//  235  *\r
+//  236  * \todo "Priorities" of standard error checks OK?\r
+//  237  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  238 unsigned char HaltNow(void)\r
+HaltNow:\r
+//  239 {\r
+        ST      -Y, R9\r
+        ST      -Y, R8\r
+        ST      -Y, R7\r
+        ST      -Y, R6\r
+        ST      -Y, R5\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        REQUIRE ?Register_R7_is_cg_reg\r
+        REQUIRE ?Register_R8_is_cg_reg\r
+        REQUIRE ?Register_R9_is_cg_reg\r
+//  240        unsigned char i, halt = FALSE;\r
+        CLR     R7\r
+//  241        \r
+//  242        // Wait for a full ADC-cycle to finish.\r
+//  243        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  244 \r
+//  245        // Evaluate ADC readings according to HaltFlags. Flag errors if selected.\r
+//  246        // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.\r
+//  247        // (Gets overridden if either mains is failing, or the battery changes.)\r
+//  248        for (i = 0x01; i != 0; i <<= 1) {\r
+        CLR     R6\r
+        INC     R6\r
+        LDI     R24, LOW(ADCS)\r
+        LDI     R25, (ADCS) >> 8\r
+        LDI     R16, LOW(BattData)\r
+        MOV     R4, R16\r
+        LDI     R16, (BattData) >> 8\r
+        MOV     R5, R16\r
+        LDI     R26, LOW(HaltParameters)\r
+        LDI     R27, (HaltParameters) >> 8\r
+//  249                if (HaltParameters.HaltFlags & i) {\r
+??HaltNow_0:\r
+        LD      R16, X\r
+        AND     R16, R6\r
+        BRNE    $+2+2\r
+        RJMP    ??HaltNow_1\r
+//  250                        switch (i) {\r
+        MOV     R16, R6\r
+        DEC     R16\r
+        BREQ    ??HaltNow_2\r
+        DEC     R16\r
+        BREQ    ??HaltNow_3\r
+        SUBI    R16, 2\r
+        BREQ    ??HaltNow_4\r
+        SUBI    R16, 4\r
+        BREQ    ??HaltNow_5\r
+        SUBI    R16, 8\r
+        BRNE    $+2+2\r
+        RJMP    ??HaltNow_6\r
+        RJMP    ??HaltNow_1\r
+//  251                        // Is VBAT less than the recorded maximum?\r
+//  252                        case HALT_VOLTAGE_DROP:\r
+//  253 \r
+//  254                                // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
+//  255                                if (ADCS.VBAT > HaltParameters.VBATMax) {\r
+??HaltNow_2:\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R16, Z+13\r
+        LDD     R17, Z+14\r
+        MOVW    R31:R30, R25:R24\r
+        LDD     R18, Z+10\r
+        LDD     R19, Z+11\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    ??HaltNow_7\r
+//  256                                        HaltParameters.VBATMax = ADCS.VBAT;\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+13, R18\r
+        STD     Z+14, R19\r
+        RJMP    ??HaltNow_1\r
+//  257                                } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+//  258                                          HaltParameters.VoltageDrop) {\r
+??HaltNow_7:\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R18, Z+1\r
+        LDD     R19, Z+2\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    $+2+2\r
+        RJMP    ??HaltNow_1\r
+//  259                                        halt = TRUE;\r
+??HaltNow_8:\r
+        CLR     R7\r
+        INC     R7\r
+        RJMP    ??HaltNow_1\r
+//  260                                }\r
+//  261                        break;\r
+//  262 \r
+//  263                        \r
+//  264                        // Has VBAT reached the maximum limit?\r
+//  265                        case HALT_VOLTAGE_MAX:  \r
+//  266                                \r
+//  267                                if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+??HaltNow_3:\r
+        MOVW    R31:R30, R25:R24\r
+        LDD     R16, Z+10\r
+        LDD     R17, Z+11\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R18, Z+3\r
+        LDD     R19, Z+4\r
+??HaltNow_9:\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCC    $+2+2\r
+        RJMP    ??HaltNow_1\r
+        RJMP    ??HaltNow_8\r
+//  268                                        halt = TRUE;\r
+//  269                                }\r
+//  270                                break;\r
+//  271 \r
+//  272 \r
+//  273                        // Has IBAT reached the minimum limit?\r
+//  274                        case HALT_CURRENT_MIN:\r
+//  275                                \r
+//  276                                if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+??HaltNow_4:\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R16, Z+5\r
+        LDD     R17, Z+6\r
+        MOVW    R31:R30, R25:R24\r
+        LDD     R18, Z+22\r
+        LDD     R19, Z+23\r
+        RJMP    ??HaltNow_9\r
+//  277                                        halt = TRUE;\r
+//  278                                }\r
+//  279                                break;\r
+//  280        \r
+//  281                                \r
+//  282                        // Is the temperature rising too fast?\r
+//  283                        case HALT_TEMPERATURE_RISE:\r
+//  284 \r
+//  285                                // If rawNTC has increased, the temperature has dropped.\r
+//  286                                // We can store this value for now, and start the timer.\r
+//  287                                // Otherwise, check if NTC has changed too fast.\r
+//  288                                if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
+??HaltNow_5:\r
+        MOVW    R31:R30, R25:R24\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R8, Z+15\r
+        LDD     R9, Z+16\r
+        CP      R8, R16\r
+        CPC     R9, R17\r
+        BRCC    ??HaltNow_10\r
+//  289                                        HaltParameters.LastNTC = ADCS.rawNTC;\r
+??HaltNow_11:\r
+        MOVW    R31:R30, R25:R24\r
+        LDD     R16, Z+4\r
+        LDD     R17, Z+5\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+15, R16\r
+        STD     Z+16, R17\r
+//  290                                        Time_Set(TIMER_TEMP,0,30,0);\r
+        LDI     R20, 0\r
+        LDI     R17, 30\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 3\r
+        RCALL   Time_Set\r
+        RJMP    ??HaltNow_1\r
+//  291                                        \r
+//  292                                // Is the increase in temperature greater than the set threshold?\r
+//  293                                } else  if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+//  294                                  (BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
+??HaltNow_10:\r
+        SUB     R8, R16\r
+        SBC     R9, R17\r
+        MOVW    R31:R30, R5:R4\r
+        LDD     R20, Z+3\r
+        LDI     R21, 0\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R16, Z+11\r
+        LDD     R17, Z+12\r
+        RCALL   ?S_MUL_L02\r
+        CP      R8, R0\r
+        CPC     R9, R1\r
+        BRCS    ??HaltNow_1\r
+//  295                                        \r
+//  296                                        // If this happened within a timeframe of 30 seconds, the \r
+//  297                                        // temperature is rising faster than we want.\r
+//  298                                        // If not, update LastNTC and reset timer.\r
+//  299                                        if (Time_Left(TIMER_TEMP))  {\r
+        LDI     R16, 3\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??HaltNow_8\r
+        RJMP    ??HaltNow_11\r
+//  300                                                halt = TRUE;\r
+//  301                                        } else {\r
+//  302                                                HaltParameters.LastNTC = ADCS.rawNTC;\r
+//  303                                                Time_Set(TIMER_TEMP,0,30,0);\r
+//  304                                        }\r
+//  305                                }\r
+//  306                        break;\r
+//  307        \r
+//  308                        \r
+//  309                        // Is there any time left?\r
+//  310                        case HALT_TIME:  \r
+//  311                                \r
+//  312                                if (!Time_Left(TIMER_CHG)) {\r
+??HaltNow_6:\r
+        LDI     R16, 1\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BRNE    ??HaltNow_1\r
+//  313                                        halt = TRUE;\r
+        CLR     R7\r
+        INC     R7\r
+//  314                                        \r
+//  315                                        // If exhaustion flagging is selected, stop the PWM, disable the \r
+//  316                                        // battery and flag it as exhausted. Make ST_ERROR next state.\r
+//  317                                        if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
+        LD      R16, X\r
+        SBRS    R16, 5\r
+        RJMP    ??HaltNow_1\r
+//  318                                                        PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  319                                                        BattControl[BattActive].Enabled = FALSE;\r
+        LDS     R16, BattActive\r
+        LDI     R17, 0\r
+        LDI     R20, LOW(BattControl)\r
+        LDI     R21, (BattControl) >> 8\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0xFE\r
+        RCALL   __eeput8_16\r
+//  320                                                        BattData.Exhausted = TRUE;\r
+        MOVW    R31:R30, R5:R4\r
+        LD      R16, Z\r
+        ORI     R16, 0x08\r
+        ST      Z, R16\r
+//  321                                                        SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
+        LDI     R16, 16\r
+        RCALL   SetErrorFlag\r
+//  322                                                        ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+21, R16\r
+//  323                                        }\r
+//  324                                }\r
+//  325                        break;\r
+//  326                        \r
+//  327                        \r
+//  328                        default:  // Shouldn't end up here, but is needed for MISRA compliance.\r
+//  329                        break;\r
+//  330                        }\r
+//  331                }\r
+//  332        }\r
+??HaltNow_1:\r
+        LSL     R6\r
+        BREQ    $+2+2\r
+        RJMP    ??HaltNow_0\r
+//  333 \r
+//  334        // Standard checks:\r
+//  335 \r
+//  336        // Battery too cold or hot?\r
+//  337        if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||\r
+//  338            (BattData.Temperature >= HaltParameters.TemperatureMax)) {\r
+        LDI     R30, LOW(BattData)\r
+        LDI     R31, (BattData) >> 8\r
+        LDD     R16, Z+2\r
+        MOVW    R31:R30, R27:R26\r
+        LDD     R18, Z+9\r
+        LDD     R19, Z+10\r
+        MOV     R17, R16\r
+        LSL     R17\r
+        SBC     R17, R17\r
+        CP      R18, R16\r
+        CPC     R19, R17\r
+        BRGE    ??HaltNow_12\r
+        MOV     R17, R16\r
+        LSL     R17\r
+        SBC     R17, R17\r
+        LDD     R18, Z+7\r
+        LDD     R19, Z+8\r
+        CP      R16, R18\r
+        CPC     R17, R19\r
+        BRCS    ??HaltNow_13\r
+//  339                        \r
+//  340                PWM_Stop();\r
+??HaltNow_12:\r
+        RCALL   PWM_Stop\r
+//  341                SetErrorFlag(ERR_BATTERY_TEMPERATURE);\r
+        LDI     R16, 8\r
+        RCALL   SetErrorFlag\r
+//  342                ChargeParameters.NextState = ST_ERROR;\r
+        LDI     R16, 90\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+21, R16\r
+//  343                halt = TRUE;\r
+        CLR     R7\r
+        INC     R7\r
+//  344        }\r
+//  345 \r
+//  346        // Battery not OK?\r
+//  347        if (!BatteryCheck()) {\r
+??HaltNow_13:\r
+        RCALL   BatteryCheck\r
+        TST     R16\r
+        BRNE    ??HaltNow_14\r
+//  348                PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  349                ChargeParameters.NextState = ST_INIT;\r
+        LDI     R16, 10\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+21, R16\r
+//  350                halt = TRUE;\r
+        CLR     R7\r
+        INC     R7\r
+//  351        }\r
+//  352 \r
+//  353        // Is mains voltage OK?\r
+//  354        if (!ADCS.Mains) {\r
+??HaltNow_14:\r
+        LDS     R16, ADCS\r
+        SBRC    R16, 6\r
+        RJMP    ??HaltNow_15\r
+//  355                PWM_Stop();\r
+        RCALL   PWM_Stop\r
+//  356                ChargeParameters.NextState = ST_SLEEP;\r
+        LDI     R16, 40\r
+        MOVW    R31:R30, R27:R26\r
+        STD     Z+21, R16\r
+//  357                halt = TRUE;\r
+        CLR     R7\r
+        INC     R7\r
+//  358        }\r
+//  359 \r
+//  360        return(halt);\r
+??HaltNow_15:\r
+        MOV     R16, R7\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        LD      R5, Y+\r
+        LD      R6, Y+\r
+        LD      R7, Y+\r
+        LD      R8, Y+\r
+        LD      R9, Y+\r
+        RET\r
+//  361 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   1 byte  in segment ABSOLUTE\r
+// 716 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//  22 bytes in segment NEAR_Z\r
+// \r
+// 716 bytes of CODE memory (+ 6 bytes shared)\r
+//  22 bytes of DATA memory (+ 1 byte  shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/main.lst b/BaseTinyFirmware/IAR/Release/List/main.lst
new file mode 100644 (file)
index 0000000..b9151aa
--- /dev/null
@@ -0,0 +1,355 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:00 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\main.c          #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\main.c          #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\ma #\r
+#                             in.lst                                          #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\mai #\r
+#                             n.r90                                           #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\main.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Main program file\r
+      6           *\r
+      7           *      Contains the main program, which is a basic state machine.\r
+      8           *\r
+      9           * \par Application note:\r
+     10           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     11           *      AVR463: Charging NiMH Batteries with BC100\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2302 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $\r
+     26           * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          /*! \page License\r
+     30           * Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+     31           *\r
+     32           * Redistribution and use in source and binary forms, with or without\r
+     33           * modification, are permitted provided that the following conditions are met:\r
+     34           *\r
+     35           * 1. Redistributions of source code must retain the above copyright notice,\r
+     36           * this list of conditions and the following disclaimer.\r
+     37           *\r
+     38           * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+     39           * this list of conditions and the following disclaimer in the documentation\r
+     40           * and/or other materials provided with the distribution.\r
+     41           *\r
+     42           * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+     43           * from this software without specific prior written permission.\r
+     44           *\r
+     45           * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+     46           * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+     47           * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+     48           * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+     49           * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+     50           * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+     51           * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+     52           * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+     53           * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+     54           * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+     55           */\r
+     56          \r
+     57          #include <ioavr.h>\r
+     58          #include <inavr.h>\r
+     59          #include <stdlib.h>\r
+     60          \r
+     61          #include "structs.h"\r
+     62          \r
+     63          #include "main.h"\r
+     64          #include "ADC.h"\r
+     65          #include "statefunc.h"\r
+     66          #include "battery.h"\r
+     67          #include "menu.h"\r
+     68          #include "OWI.h"\r
+     69          #include "PWM.h"\r
+     70          #include "time.h"\r
+     71          #include "USI.h"\r
+     72          \r
+     73          \r
+     74          \r
+     75          //******************************************************************************\r
+     76          // Globals\r
+     77          //******************************************************************************\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     78          unsigned char CurrentState;     //!< \brief Global that indicates current state\r
+   \                     CurrentState:\r
+   \   00000000                      DS 1\r
+     79                                          //!<\r
+     80                                          //!< Updated by main().\r
+     81                                          //!< \note See menu.h for definition of states.\r
+     82          \r
+     83          \r
+     84          //******************************************************************************\r
+     85          // Functions\r
+     86          //******************************************************************************\r
+     87          /*! \brief Main program\r
+     88           *\r
+     89           * The main function goes into an infinite loop, keeping track of the current\r
+     90           * state and the next one. If the next state is different from the current, it\r
+     91           * looks up the address to the next state function, in \ref menu_state[], and \r
+     92           * updates \ref CurrentState. The state function is then called and will\r
+     93           * eventually return a new state, and so the loop reiterates.\r
+     94           *\r
+     95           * \todo The variable inp is passed to all state functions, but is not used\r
+     96           * for anything yet. Remove?\r
+     97           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     98          int main( void )\r
+   \                     main:\r
+     99          {\r
+   \   00000000   939A               ST      -Y, R25\r
+   \   00000002   938A               ST      -Y, R24\r
+    100                unsigned char nextstate, inp, i;\r
+    101                unsigned char (*pStateFunc)(unsigned char);   // Function pointer.\r
+    102                \r
+    103                // Initialize local state variables.\r
+    104                inp = ZERO;\r
+    105                CurrentState = nextstate = ST_INIT;\r
+   \   00000004   E02A               LDI     R18, 10\r
+   \   00000006   9320....           STS     CurrentState, R18\r
+    106                pStateFunc = NULL;\r
+   \   0000000A   E080               LDI     R24, 0\r
+   \   0000000C   E090               LDI     R25, 0\r
+    107                \r
+    108                // Look for function associated with current state, get its address.\r
+    109                for (i = 0; menu_state[i].state != 0; i++) {\r
+   \   0000000E   E000               LDI     R16, 0\r
+   \   00000010   C006               RJMP    ??main_0\r
+    110                        if (menu_state[i].state == CurrentState) {\r
+   \                     ??main_1:\r
+   \   00000012   301A               CPI     R17, 10\r
+   \   00000014   F419               BRNE    ??main_2\r
+    111                                pStateFunc = menu_state[i].pFunc;\r
+   \   00000016   9631               ADIW    R31:R30, 1\r
+   \   00000018   9185               LPM     R24, Z+\r
+   \   0000001A   9194               LPM     R25, Z\r
+    112                        }\r
+    113                }\r
+   \                     ??main_2:\r
+   \   0000001C   9503               INC     R16\r
+   \                     ??main_0:\r
+   \   0000001E   2F40               MOV     R20, R16\r
+   \   00000020   E050               LDI     R21, 0\r
+   \   00000022   01BA               MOVW    R23:R22, R21:R20\r
+   \   00000024   0F44               LSL     R20\r
+   \   00000026   1F55               ROL     R21\r
+   \   00000028   0F46               ADD     R20, R22\r
+   \   0000002A   1F57               ADC     R21, R23\r
+   \   0000002C   ....               LDI     R30, LOW(menu_state)\r
+   \   0000002E   ....               LDI     R31, (menu_state) >> 8\r
+   \   00000030   0FE4               ADD     R30, R20\r
+   \   00000032   1FF5               ADC     R31, R21\r
+   \   00000034   9114               LPM     R17, Z\r
+   \   00000036   2311               TST     R17\r
+   \   00000038   F761               BRNE    ??main_1\r
+    114          \r
+    115                while (TRUE) {\r
+    116                        // Run function associated with current state, get next state in return.\r
+    117                        if (pStateFunc != NULL){\r
+   \                     ??main_3:\r
+   \   0000003A   E000               LDI     R16, 0\r
+   \   0000003C   3080               CPI     R24, 0\r
+   \   0000003E   0790               CPC     R25, R16\r
+   \   00000040   F019               BREQ    ??main_4\r
+    118                                nextstate = pStateFunc(inp);\r
+   \   00000042   01FC               MOVW    R31:R30, R25:R24\r
+   \   00000044   9509               ICALL\r
+   \   00000046   2F20               MOV     R18, R16\r
+    119                        }\r
+    120          \r
+    121                        // Look up function for next state, if it differs from the current.\r
+    122                        if (nextstate != CurrentState) {\r
+   \                     ??main_4:\r
+   \   00000048   9100....           LDS     R16, CurrentState\r
+   \   0000004C   1720               CP      R18, R16\r
+   \   0000004E   F3A9               BREQ    ??main_3\r
+    123                                CurrentState = nextstate;\r
+   \   00000050   9320....           STS     CurrentState, R18\r
+    124                                for ( i = 0; menu_state[i].state != 0; i++) {\r
+   \   00000054   E000               LDI     R16, 0\r
+   \                     ??main_5:\r
+   \   00000056   2F40               MOV     R20, R16\r
+   \   00000058   E050               LDI     R21, 0\r
+   \   0000005A   01BA               MOVW    R23:R22, R21:R20\r
+   \   0000005C   0F44               LSL     R20\r
+   \   0000005E   1F55               ROL     R21\r
+   \   00000060   0F46               ADD     R20, R22\r
+   \   00000062   1F57               ADC     R21, R23\r
+   \   00000064   ....               LDI     R30, LOW(menu_state)\r
+   \   00000066   ....               LDI     R31, (menu_state) >> 8\r
+   \   00000068   0FE4               ADD     R30, R20\r
+   \   0000006A   1FF5               ADC     R31, R21\r
+   \   0000006C   9114               LPM     R17, Z\r
+   \   0000006E   2311               TST     R17\r
+   \   00000070   F321               BREQ    ??main_3\r
+    125                                        if (menu_state[i].state == CurrentState) {\r
+   \   00000072   9130....           LDS     R19, CurrentState\r
+   \   00000076   1713               CP      R17, R19\r
+   \   00000078   F419               BRNE    ??main_6\r
+    126                                                pStateFunc = menu_state[i].pFunc;\r
+   \   0000007A   9631               ADIW    R31:R30, 1\r
+   \   0000007C   9185               LPM     R24, Z+\r
+   \   0000007E   9194               LPM     R25, Z\r
+    127                                        }\r
+    128                                }\r
+   \                     ??main_6:\r
+   \   00000080   9503               INC     R16\r
+   \   00000082   CFE9               RJMP    ??main_5\r
+    129                        }\r
+    130                }\r
+    131          }\r
+    132          \r
+    133          \r
+    134          /* Doxygen documentation mainpage ********************************************/\r
+    135          /*! \mainpage\r
+    136           * \section intro Introduction\r
+    137           * This documents the software for application note AVR458. This is a charger\r
+    138           * for Li-Ion batteries, based on ATAVRBC100.\r
+    139           *\r
+    140           * \section compinfo Compilation Info\r
+    141           * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC \r
+    142           * the source have to be modified.\n\r
+    143           * \n\r
+    144           * To make project on IAR EWAVR:\n\r
+    145           * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,\r
+    146           * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,\r
+    147           * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate\r
+    148           * battery data if needed.\n\r
+    149           * \n\r
+    150           * Use device --cpu=tiny861, enable bit definitions in I/O include files,\r
+    151           * optimization low for debug target and high for release, output format: ubrof8\r
+    152           * for Debug and intel_extended for Release. \n\r
+    153           *\r
+    154           * \section deviceinfo Device Info\r
+    155           * This application is based on the ATtiny 861, but it is possible to migrate \r
+    156           * the design to other AVR microcontrollers, such as pin-compatible devices\r
+    157           * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be\r
+    158           * used, but with reduced functionality.\r
+    159           * \r
+    160           * Required fuse bit settings:\r
+    161           *    <pre>\r
+    162           *    FUSE BIT  | SETTING\r
+    163           *    ----------+--------------------\r
+    164           *    CKDIV8    | 1 (unprogrammed)\r
+    165           *    CKSEL3..0 | 0010 (internal osc)\r
+    166           *    </pre>\r
+    167           *\r
+    168           *\r
+    169           * \section todo To Do-list\r
+    170           * \todo\r
+    171           * - Finalize master-slave communication protocol\r
+    172           * - Implement discharge mode\r
+    173           *\r
+    174           * \section contactinfo Contact Info\r
+    175           * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n\r
+    176           * For application notes visit \r
+    177           * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n\r
+    178           * Support mail: avr@atmel.com\r
+    179           */\r
+    180          \r
+    181          \r
+    182          /*! \page misra MISRA C rule violations\r
+    183           *\r
+    184           * \par Rule 1\r
+    185           * <i>"All code shall conform to ISO 9899 standard C, with no extensions\r
+    186           * permitted."</i>\r
+    187           *\r
+    188           * Extensions are necessary because ISO C has no way of specifying that a\r
+    189           * function should be an interrupt service routine, or that we would like data\r
+    190           * members to be stored in f.ex. EEPROM.\r
+    191           *\r
+    192           *\r
+    193           * \par Rule 37\r
+    194           * <i>"Bitwise operations shall not be performed on signed integer types."</i>\r
+    195           *\r
+    196           * The compiler assumes all the 1's we shift around to make bitmasks are signed\r
+    197           * integers. Specifying them all to be (unsigned int), either directly or via a\r
+    198           * definition, would fix the rule violations, but also reduce code readability.\r
+    199           *\r
+    200           *\r
+    201           * \par Rule 45\r
+    202           * <i>"Type casting from any type to or from pointers shall not be used."</i>\r
+    203           *\r
+    204           * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..\r
+    205           *\r
+    206           *\r
+    207           * \par Rule 96\r
+    208           * <i>"In the definition of a function-like macro the whole definition, and each\r
+    209           * instance of a parameter, shall be enclosed in parentheses."</i>\r
+    210           * \r
+    211           * It is difficult to use parentheses with void function-like macros.\r
+    212           */\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function             CSTACK RSTACK\r
+     --------             ------ ------\r
+     main                     2      2\r
+       ->   Indirect call     2      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     CurrentState      1\r
+     main            132\r
+      Others           6\r
+\r
\r
+ 132 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   1 byte  in segment NEAR_Z\r
\r
+ 132 bytes of CODE memory (+ 6 bytes shared)\r
+   1 byte  of DATA memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/main.s90 b/BaseTinyFirmware/IAR/Release/List/main.s90
new file mode 100644 (file)
index 0000000..f6a8396
--- /dev/null
@@ -0,0 +1,374 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:00 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\main.c         /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\main.c         /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\m /\r
+//                             ain.s90                                        /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME main\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?need_segment_init\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC CurrentState\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+        PUBLIC main\r
+\r
+        EXTERN menu_state\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\main.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Main program file\r
+//    6  *\r
+//    7  *      Contains the main program, which is a basic state machine.\r
+//    8  *\r
+//    9  * \par Application note:\r
+//   10  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2302 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $\r
+//   26  * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 /*! \page License\r
+//   30  * Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+//   31  *\r
+//   32  * Redistribution and use in source and binary forms, with or without\r
+//   33  * modification, are permitted provided that the following conditions are met:\r
+//   34  *\r
+//   35  * 1. Redistributions of source code must retain the above copyright notice,\r
+//   36  * this list of conditions and the following disclaimer.\r
+//   37  *\r
+//   38  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+//   39  * this list of conditions and the following disclaimer in the documentation\r
+//   40  * and/or other materials provided with the distribution.\r
+//   41  *\r
+//   42  * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+//   43  * from this software without specific prior written permission.\r
+//   44  *\r
+//   45  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+//   46  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+//   47  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+//   48  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+//   49  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+//   50  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+//   51  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+//   52  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+//   53  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+//   54  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+//   55  */\r
+//   56 \r
+//   57 #include <ioavr.h>\r
+//   58 #include <inavr.h>\r
+//   59 #include <stdlib.h>\r
+//   60 \r
+//   61 #include "structs.h"\r
+//   62 \r
+//   63 #include "main.h"\r
+//   64 #include "ADC.h"\r
+//   65 #include "statefunc.h"\r
+//   66 #include "battery.h"\r
+//   67 #include "menu.h"\r
+//   68 #include "OWI.h"\r
+//   69 #include "PWM.h"\r
+//   70 #include "time.h"\r
+//   71 #include "USI.h"\r
+//   72 \r
+//   73 \r
+//   74 \r
+//   75 //******************************************************************************\r
+//   76 // Globals\r
+//   77 //******************************************************************************\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   78 unsigned char CurrentState;     //!< \brief Global that indicates current state\r
+CurrentState:\r
+        DS 1\r
+//   79                                 //!<\r
+//   80                                 //!< Updated by main().\r
+//   81                                 //!< \note See menu.h for definition of states.\r
+//   82 \r
+//   83 \r
+//   84 //******************************************************************************\r
+//   85 // Functions\r
+//   86 //******************************************************************************\r
+//   87 /*! \brief Main program\r
+//   88  *\r
+//   89  * The main function goes into an infinite loop, keeping track of the current\r
+//   90  * state and the next one. If the next state is different from the current, it\r
+//   91  * looks up the address to the next state function, in \ref menu_state[], and \r
+//   92  * updates \ref CurrentState. The state function is then called and will\r
+//   93  * eventually return a new state, and so the loop reiterates.\r
+//   94  *\r
+//   95  * \todo The variable inp is passed to all state functions, but is not used\r
+//   96  * for anything yet. Remove?\r
+//   97  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   98 int main( void )\r
+main:\r
+//   99 {\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+//  100        unsigned char nextstate, inp, i;\r
+//  101        unsigned char (*pStateFunc)(unsigned char);   // Function pointer.\r
+//  102        \r
+//  103        // Initialize local state variables.\r
+//  104        inp = ZERO;\r
+//  105        CurrentState = nextstate = ST_INIT;\r
+        LDI     R18, 10\r
+        STS     CurrentState, R18\r
+//  106        pStateFunc = NULL;\r
+        LDI     R24, 0\r
+        LDI     R25, 0\r
+//  107        \r
+//  108        // Look for function associated with current state, get its address.\r
+//  109        for (i = 0; menu_state[i].state != 0; i++) {\r
+        LDI     R16, 0\r
+        RJMP    ??main_0\r
+//  110                if (menu_state[i].state == CurrentState) {\r
+??main_1:\r
+        CPI     R17, 10\r
+        BRNE    ??main_2\r
+//  111                        pStateFunc = menu_state[i].pFunc;\r
+        ADIW    R31:R30, 1\r
+        LPM     R24, Z+\r
+        LPM     R25, Z\r
+//  112                }\r
+//  113        }\r
+??main_2:\r
+        INC     R16\r
+??main_0:\r
+        MOV     R20, R16\r
+        LDI     R21, 0\r
+        MOVW    R23:R22, R21:R20\r
+        LSL     R20\r
+        ROL     R21\r
+        ADD     R20, R22\r
+        ADC     R21, R23\r
+        LDI     R30, LOW(menu_state)\r
+        LDI     R31, (menu_state) >> 8\r
+        ADD     R30, R20\r
+        ADC     R31, R21\r
+        LPM     R17, Z\r
+        TST     R17\r
+        BRNE    ??main_1\r
+//  114 \r
+//  115        while (TRUE) {\r
+//  116                // Run function associated with current state, get next state in return.\r
+//  117                if (pStateFunc != NULL){\r
+??main_3:\r
+        LDI     R16, 0\r
+        CPI     R24, 0\r
+        CPC     R25, R16\r
+        BREQ    ??main_4\r
+//  118                        nextstate = pStateFunc(inp);\r
+        MOVW    R31:R30, R25:R24\r
+        ICALL\r
+        MOV     R18, R16\r
+//  119                }\r
+//  120 \r
+//  121                // Look up function for next state, if it differs from the current.\r
+//  122                if (nextstate != CurrentState) {\r
+??main_4:\r
+        LDS     R16, CurrentState\r
+        CP      R18, R16\r
+        BREQ    ??main_3\r
+//  123                        CurrentState = nextstate;\r
+        STS     CurrentState, R18\r
+//  124                        for ( i = 0; menu_state[i].state != 0; i++) {\r
+        LDI     R16, 0\r
+??main_5:\r
+        MOV     R20, R16\r
+        LDI     R21, 0\r
+        MOVW    R23:R22, R21:R20\r
+        LSL     R20\r
+        ROL     R21\r
+        ADD     R20, R22\r
+        ADC     R21, R23\r
+        LDI     R30, LOW(menu_state)\r
+        LDI     R31, (menu_state) >> 8\r
+        ADD     R30, R20\r
+        ADC     R31, R21\r
+        LPM     R17, Z\r
+        TST     R17\r
+        BREQ    ??main_3\r
+//  125                                if (menu_state[i].state == CurrentState) {\r
+        LDS     R19, CurrentState\r
+        CP      R17, R19\r
+        BRNE    ??main_6\r
+//  126                                        pStateFunc = menu_state[i].pFunc;\r
+        ADIW    R31:R30, 1\r
+        LPM     R24, Z+\r
+        LPM     R25, Z\r
+//  127                                }\r
+//  128                        }\r
+??main_6:\r
+        INC     R16\r
+        RJMP    ??main_5\r
+//  129                }\r
+//  130        }\r
+//  131 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+//  132 \r
+//  133 \r
+//  134 /* Doxygen documentation mainpage ********************************************/\r
+//  135 /*! \mainpage\r
+//  136  * \section intro Introduction\r
+//  137  * This documents the software for application note AVR458. This is a charger\r
+//  138  * for Li-Ion batteries, based on ATAVRBC100.\r
+//  139  *\r
+//  140  * \section compinfo Compilation Info\r
+//  141  * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC \r
+//  142  * the source have to be modified.\n\r
+//  143  * \n\r
+//  144  * To make project on IAR EWAVR:\n\r
+//  145  * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,\r
+//  146  * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,\r
+//  147  * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate\r
+//  148  * battery data if needed.\n\r
+//  149  * \n\r
+//  150  * Use device --cpu=tiny861, enable bit definitions in I/O include files,\r
+//  151  * optimization low for debug target and high for release, output format: ubrof8\r
+//  152  * for Debug and intel_extended for Release. \n\r
+//  153  *\r
+//  154  * \section deviceinfo Device Info\r
+//  155  * This application is based on the ATtiny 861, but it is possible to migrate \r
+//  156  * the design to other AVR microcontrollers, such as pin-compatible devices\r
+//  157  * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be\r
+//  158  * used, but with reduced functionality.\r
+//  159  * \r
+//  160  * Required fuse bit settings:\r
+//  161  *    <pre>\r
+//  162  *    FUSE BIT  | SETTING\r
+//  163  *    ----------+--------------------\r
+//  164  *    CKDIV8    | 1 (unprogrammed)\r
+//  165  *    CKSEL3..0 | 0010 (internal osc)\r
+//  166  *    </pre>\r
+//  167  *\r
+//  168  *\r
+//  169  * \section todo To Do-list\r
+//  170  * \todo\r
+//  171  * - Finalize master-slave communication protocol\r
+//  172  * - Implement discharge mode\r
+//  173  *\r
+//  174  * \section contactinfo Contact Info\r
+//  175  * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n\r
+//  176  * For application notes visit \r
+//  177  * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n\r
+//  178  * Support mail: avr@atmel.com\r
+//  179  */\r
+//  180 \r
+//  181 \r
+//  182 /*! \page misra MISRA C rule violations\r
+//  183  *\r
+//  184  * \par Rule 1\r
+//  185  * <i>"All code shall conform to ISO 9899 standard C, with no extensions\r
+//  186  * permitted."</i>\r
+//  187  *\r
+//  188  * Extensions are necessary because ISO C has no way of specifying that a\r
+//  189  * function should be an interrupt service routine, or that we would like data\r
+//  190  * members to be stored in f.ex. EEPROM.\r
+//  191  *\r
+//  192  *\r
+//  193  * \par Rule 37\r
+//  194  * <i>"Bitwise operations shall not be performed on signed integer types."</i>\r
+//  195  *\r
+//  196  * The compiler assumes all the 1's we shift around to make bitmasks are signed\r
+//  197  * integers. Specifying them all to be (unsigned int), either directly or via a\r
+//  198  * definition, would fix the rule violations, but also reduce code readability.\r
+//  199  *\r
+//  200  *\r
+//  201  * \par Rule 45\r
+//  202  * <i>"Type casting from any type to or from pointers shall not be used."</i>\r
+//  203  *\r
+//  204  * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..\r
+//  205  *\r
+//  206  *\r
+//  207  * \par Rule 96\r
+//  208  * <i>"In the definition of a function-like macro the whole definition, and each\r
+//  209  * instance of a parameter, shall be enclosed in parentheses."</i>\r
+//  210  * \r
+//  211  * It is difficult to use parentheses with void function-like macros.\r
+//  212  */\r
+// \r
+// 132 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   1 byte  in segment NEAR_Z\r
+// \r
+// 132 bytes of CODE memory (+ 6 bytes shared)\r
+//   1 byte  of DATA memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/menu.lst b/BaseTinyFirmware/IAR/Release/List/menu.lst
new file mode 100644 (file)
index 0000000..66bc677
--- /dev/null
@@ -0,0 +1,156 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:49:38 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\menu.c          #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\menu.c          #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\me #\r
+#                             nu.lst                                          #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\men #\r
+#                             u.r90                                           #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\menu.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      State menu definition\r
+      6           * \r
+      7           *      Contains the definition of the state menu.\n\r
+      8           *      The state menu contains all states and adresses to associated functions.\r
+      9           *\r
+     10           * \par Application note:\r
+     11           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     12           *      AVR463: Charging NiMH Batteries with BC100\r
+     13           *\r
+     14           * \par Documentation:\r
+     15           *      For comprehensive code documentation, supported compilers, compiler\r
+     16           *      settings and supported devices see readme.html\r
+     17           *\r
+     18           * \author\r
+     19           *      Atmel Corporation: http://www.atmel.com \n\r
+     20           *      Support email: avr@atmel.com\r
+     21           *\r
+     22           *\r
+     23           * $Name$\r
+     24           * $Revision: 2299 $\r
+     25           * $RCSfile$\r
+     26           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $\r
+     27           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     28           ******************************************************************************/\r
+     29          \r
+     30          #include <stdlib.h>\r
+     31          \r
+     32          #include "statefunc.h"\r
+     33          #include "charge.h"\r
+     34          #include "main.h"\r
+     35          #include "menu.h"\r
+     36          \r
+     37          \r
+     38          //******************************************************************************\r
+     39          // State menu (relies on the proper battery type to be defined in main.h!)\r
+     40          //******************************************************************************\r
+     41          #ifdef NIMH\r
+     42          /*! \brief The state menu\r
+     43           *\r
+     44           * Contains all the defined states and addresses to their associated functions.\r
+     45           */\r
+\r
+   \                                 In  segment NEAR_F, align 1, keep-with-next\r
+     46          __flash const MENU_STATE_t menu_state[] = {\r
+   \                     menu_state:\r
+   \   00000000   0A                 DB 10\r
+   \   00000001   ....               DW Initialize/2\r
+   \   00000003   14                 DB 20\r
+   \   00000004   ....               DW BatteryControl/2\r
+   \   00000006   1E                 DB 30\r
+   \   00000007   ....               DW Charge/2\r
+   \   00000009   28                 DB 40\r
+   \   0000000A   ....               DW `Sleep`/2\r
+   \   0000000C   32                 DB 50\r
+   \   0000000D   ....               DW Charge/2\r
+   \   0000000F   3C                 DB 60\r
+   \   00000010   ....               DW Charge/2\r
+   \   00000012   46                 DB 70\r
+   \   00000013   ....               DW Charge/2\r
+   \   00000015   50                 DB 80\r
+   \   00000016   ....               DW Discharge/2\r
+   \   00000018   5A                 DB 90\r
+   \   00000019   ....               DW Error/2\r
+   \   0000001B   00                 DB 0\r
+   \   0000001C   0000               DW 0H\r
+     47          //  State                                     State function\r
+     48            { ST_INIT,            Initialize},\r
+     49            { ST_BATCON,          BatteryControl},\r
+     50            { ST_PREQUAL,         Charge},\r
+     51            { ST_SLEEP,           Sleep},\r
+     52            { ST_FASTCHARGE,      Charge},\r
+     53            { ST_LOWRATECHARGE,   Charge},\r
+     54            { ST_ENDCHARGE,       Charge},      \r
+     55            { ST_DISCHARGE,       Discharge},\r
+     56            { ST_ERROR,           Error},\r
+     57            { 0,                  NULL},\r
+     58          };\r
+     59          #endif // NIMH\r
+     60          \r
+     61          #ifdef LIION\r
+     62          /*! \brief The state menu\r
+     63           *\r
+     64           * Contains all the defined states and addresses to their associated functions.\r
+     65           */\r
+     66          __flash const MENU_STATE_t menu_state[] = {\r
+     67          //  State                                     State function\r
+     68            { ST_INIT,            Initialize},\r
+     69            { ST_BATCON,          BatteryControl},\r
+     70            { ST_PREQUAL,         Charge},\r
+     71            { ST_SLEEP,           Sleep},\r
+     72            { ST_CCURRENT,        Charge},\r
+     73            { ST_CVOLTAGE,        Charge},\r
+     74            { ST_ENDCHARGE,       Charge},      \r
+     75            { ST_DISCHARGE,       Discharge},\r
+     76            { ST_ERROR,           Error},\r
+     77            { 0,                  NULL},\r
+     78          };\r
+     79          #endif // LIION\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     menu_state       30\r
+\r
\r
+ 30 bytes in segment NEAR_F\r
\r
+ 30 bytes of CODE memory\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/menu.s90 b/BaseTinyFirmware/IAR/Release/List/menu.s90
new file mode 100644 (file)
index 0000000..0bbbf82
--- /dev/null
@@ -0,0 +1,178 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:49:38 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\menu.c         /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\menu.c         /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\m /\r
+//                             enu.s90                                        /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME menu\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+        PUBLIC menu_state\r
+\r
+        EXTERN BatteryControl\r
+        EXTERN Charge\r
+        EXTERN Discharge\r
+        EXTERN Error\r
+        EXTERN Initialize\r
+        EXTERN `Sleep`\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\menu.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      State menu definition\r
+//    6  * \r
+//    7  *      Contains the definition of the state menu.\n\r
+//    8  *      The state menu contains all states and adresses to associated functions.\r
+//    9  *\r
+//   10  * \par Application note:\r
+//   11  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   12  *      AVR463: Charging NiMH Batteries with BC100\r
+//   13  *\r
+//   14  * \par Documentation:\r
+//   15  *      For comprehensive code documentation, supported compilers, compiler\r
+//   16  *      settings and supported devices see readme.html\r
+//   17  *\r
+//   18  * \author\r
+//   19  *      Atmel Corporation: http://www.atmel.com \n\r
+//   20  *      Support email: avr@atmel.com\r
+//   21  *\r
+//   22  *\r
+//   23  * $Name$\r
+//   24  * $Revision: 2299 $\r
+//   25  * $RCSfile$\r
+//   26  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $\r
+//   27  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   28  ******************************************************************************/\r
+//   29 \r
+//   30 #include <stdlib.h>\r
+//   31 \r
+//   32 #include "statefunc.h"\r
+//   33 #include "charge.h"\r
+//   34 #include "main.h"\r
+//   35 #include "menu.h"\r
+//   36 \r
+//   37 \r
+//   38 //******************************************************************************\r
+//   39 // State menu (relies on the proper battery type to be defined in main.h!)\r
+//   40 //******************************************************************************\r
+//   41 #ifdef NIMH\r
+//   42 /*! \brief The state menu\r
+//   43  *\r
+//   44  * Contains all the defined states and addresses to their associated functions.\r
+//   45  */\r
+\r
+        RSEG NEAR_F:CODE:NOROOT(0)\r
+//   46 __flash const MENU_STATE_t menu_state[] = {\r
+menu_state:\r
+        DB 10\r
+        DW Initialize/2\r
+        DB 20\r
+        DW BatteryControl/2\r
+        DB 30\r
+        DW Charge/2\r
+        DB 40\r
+        DW `Sleep`/2\r
+        DB 50\r
+        DW Charge/2\r
+        DB 60\r
+        DW Charge/2\r
+        DB 70\r
+        DW Charge/2\r
+        DB 80\r
+        DW Discharge/2\r
+        DB 90\r
+        DW Error/2\r
+        DB 0\r
+        DW 0H\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        END\r
+//   47 //  State                                      State function\r
+//   48   { ST_INIT,            Initialize},\r
+//   49   { ST_BATCON,          BatteryControl},\r
+//   50   { ST_PREQUAL,         Charge},\r
+//   51   { ST_SLEEP,           Sleep},\r
+//   52   { ST_FASTCHARGE,      Charge},\r
+//   53   { ST_LOWRATECHARGE,   Charge},\r
+//   54   { ST_ENDCHARGE,       Charge},       \r
+//   55   { ST_DISCHARGE,       Discharge},\r
+//   56   { ST_ERROR,           Error},\r
+//   57   { 0,                  NULL},\r
+//   58 };\r
+//   59 #endif // NIMH\r
+//   60 \r
+//   61 #ifdef LIION\r
+//   62 /*! \brief The state menu\r
+//   63  *\r
+//   64  * Contains all the defined states and addresses to their associated functions.\r
+//   65  */\r
+//   66 __flash const MENU_STATE_t menu_state[] = {\r
+//   67 //  State                                      State function\r
+//   68   { ST_INIT,            Initialize},\r
+//   69   { ST_BATCON,          BatteryControl},\r
+//   70   { ST_PREQUAL,         Charge},\r
+//   71   { ST_SLEEP,           Sleep},\r
+//   72   { ST_CCURRENT,        Charge},\r
+//   73   { ST_CVOLTAGE,        Charge},\r
+//   74   { ST_ENDCHARGE,       Charge},       \r
+//   75   { ST_DISCHARGE,       Discharge},\r
+//   76   { ST_ERROR,           Error},\r
+//   77   { 0,                  NULL},\r
+//   78 };\r
+//   79 #endif // LIION\r
+// \r
+// 30 bytes in segment NEAR_F\r
+// \r
+// 30 bytes of CODE memory\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/statefunc.lst b/BaseTinyFirmware/IAR/Release/List/statefunc.lst
new file mode 100644 (file)
index 0000000..a5c05c5
--- /dev/null
@@ -0,0 +1,802 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:01 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\statefunc.c     #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\statefunc.c     #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\st #\r
+#                             atefunc.lst                                     #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\sta #\r
+#                             tefunc.r90                                      #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\statefunc.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      State functions\r
+      6           *\r
+      7           *      Contains the functions related to the states defined in menu.h.\n\r
+      8           *      Also contains related functions, i.e. for checking jumpers, setting\r
+      9           *      error flags and "dozing".\r
+     10           *\r
+     11           *      \note The state function Charge() is in a separate file since it\r
+     12           *      should easily be changed with regard to battery type.\r
+     13           *\r
+     14           * \par Application note:\r
+     15           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     16           *      AVR463: Charging NiMH Batteries with BC100\r
+     17           *\r
+     18           * \par Documentation\r
+     19           *      For comprehensive code documentation, supported compilers, compiler \r
+     20           *      settings and supported devices see readme.html\r
+     21           *\r
+     22           * \author\r
+     23           *      Atmel Corporation: http://www.atmel.com \n\r
+     24           *      Support email: avr@atmel.com\r
+     25           *\r
+     26           * \r
+     27           * $Name$\r
+     28           * $Revision: 2299 $\r
+     29           * $RCSfile$\r
+     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
+     31           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     32           ******************************************************************************/\r
+     33          \r
+     34          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x55\r
+   \   <unnamed> volatile __io _A_MCUCR\r
+   \                     _A_MCUCR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x54\r
+   \   <unnamed> volatile __io _A_MCUSR\r
+   \                     _A_MCUSR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x48\r
+   \   <unnamed> volatile __io _A_CLKPR\r
+   \                     _A_CLKPR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x41\r
+   \   <unnamed> volatile __io _A_WDTCR\r
+   \                     _A_WDTCR:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x37\r
+   \   <unnamed> volatile __io _A_DDRB\r
+   \                     _A_DDRB:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x26\r
+   \   <unnamed> volatile __io _A_ADCSRA\r
+   \                     _A_ADCSRA:\r
+   \   00000000                      DS 1\r
+     35          #include <inavr.h>\r
+     36          #include <stdlib.h>\r
+     37          \r
+     38          #include "structs.h"\r
+     39          #include "enums.h"\r
+     40          \r
+     41          #include "ADC.h"\r
+     42          #include "statefunc.h"\r
+     43          #include "battery.h"\r
+     44          #include "charge.h"\r
+     45          #include "main.h"\r
+     46          #include "menu.h"\r
+     47          #include "OWI.h"\r
+     48          #include "PWM.h"\r
+     49          #include "time.h"\r
+     50          #include "USI.h"\r
+     51          \r
+     52          \r
+     53          //******************************************************************************\r
+     54          // Variables\r
+     55          //******************************************************************************\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     56          unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
+   \                     ErrorFlags:\r
+   \   00000000                      DS 1\r
+     57                                     //!< \note See statefunc.h for definitions of flags.\r
+     58          \r
+     59          //! \brief Holds the state in which latest error flag was set.\r
+     60          //! \note See menu.h for definitions of states.\r
+     61          unsigned char ErrorState;\r
+   \                     ErrorState:\r
+   \   00000001                      DS 1\r
+     62          \r
+     63          \r
+     64          //******************************************************************************\r
+     65          // Functions\r
+     66          //******************************************************************************\r
+     67          /*! \brief Initialization\r
+     68           *\r
+     69           * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
+     70           * - Initializes the one-wire interface\r
+     71           * - Clears on-chip EEPROM\r
+     72           * - Sets battery enable pins as outputs, then disables batteries\r
+     73           * - Initializes SPI according to \ref SPIMODE\r
+     74           * - Initializes ADC\r
+     75           * - Initializes timers\r
+     76           * - Reads battery data from both battery inputs (via ADC)\r
+     77           * - Disables batteries again\r
+     78           * - Sets battery A as the current one (\ref BattActive = 0)\r
+     79           * - Clears ErrorFlags\r
+     80           *\r
+     81           * \param inp Not used.\r
+     82           *\r
+     83           * \retval ST_BATCON Next state in the sequence.\r
+     84           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     85          unsigned char Initialize(unsigned char inp)\r
+   \                     Initialize:\r
+     86          {\r
+   \   00000000   938A               ST      -Y, R24\r
+     87                unsigned char i, page;\r
+     88          \r
+     89                // Disable interrupts while setting prescaler.\r
+     90                __disable_interrupt();\r
+   \   00000002   94F8               CLI\r
+     91                \r
+     92                CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
+   \   00000004   E800               LDI     R16, 128\r
+   \   00000006   BD08               OUT     0x28, R16\r
+     93                CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
+   \   00000008   E000               LDI     R16, 0\r
+   \   0000000A   BD08               OUT     0x28, R16\r
+     94                \r
+     95                // Init 1-Wire(R) interface.\r
+     96                OWI_Init(OWIBUS);\r
+   \   0000000C   E001               LDI     R16, 1\r
+   \   0000000E   ....               RCALL   OWI_Init\r
+     97                \r
+     98                // Clear on-chip EEPROM.\r
+     99                for (page = 0; page < 4; page++)        {\r
+   \   00000010   ....               LDI     R20, LOW(BattEEPROM)\r
+   \   00000012   ....               LDI     R21, (BattEEPROM) >> 8\r
+   \   00000014   E810               LDI     R17, 128\r
+    100                        for (i = 0; i < 32; i++) {\r
+    101                                BattEEPROM[page][i] = 0;\r
+   \                     ??Initialize_0:\r
+   \   00000016   E000               LDI     R16, 0\r
+   \   00000018   ....               RCALL   __eeput8_16\r
+    102                        }\r
+   \   0000001A   5F4F               SUBI    R20, 255\r
+   \   0000001C   4F5F               SBCI    R21, 255\r
+    103                }\r
+   \   0000001E   951A               DEC     R17\r
+   \   00000020   F7D1               BRNE    ??Initialize_0\r
+    104          \r
+    105                DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
+   \   00000022   E300               LDI     R16, 48\r
+   \   00000024   BB07               OUT     0x17, R16\r
+    106                DisableBatteries();\r
+   \   00000026   ....               RCALL   DisableBatteries\r
+    107                SPI_Init(SPIMODE);\r
+   \   00000028   E000               LDI     R16, 0\r
+   \   0000002A   ....               RCALL   SPI_Init\r
+    108                ADC_Init();\r
+   \   0000002C   ....               RCALL   ADC_Init\r
+    109                Time_Init();\r
+   \   0000002E   ....               RCALL   Time_Init\r
+    110          \r
+    111                // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
+    112                for (i = 0; i < 2; i++) {\r
+   \   00000030   E080               LDI     R24, 0\r
+    113                        EnableBattery(i);\r
+   \                     ??Initialize_1:\r
+   \   00000032   2F08               MOV     R16, R24\r
+   \   00000034   ....               RCALL   EnableBattery\r
+    114                        ADC_Wait();\r
+   \   00000036   ....               RCALL   ADC_Wait\r
+    115                        BatteryStatusRefresh();\r
+   \   00000038   ....               RCALL   BatteryStatusRefresh\r
+    116                }\r
+   \   0000003A   9583               INC     R24\r
+   \   0000003C   3082               CPI     R24, 2\r
+   \   0000003E   F3C8               BRCS    ??Initialize_1\r
+    117              \r
+    118                DisableBatteries();\r
+   \   00000040   ....               RCALL   DisableBatteries\r
+    119                \r
+    120                BattActive = 0;               // We have to start somewhere..\r
+   \   00000042   E000               LDI     R16, 0\r
+   \   00000044   9300....           STS     BattActive, R16\r
+    121                ErrorFlags = 0;\r
+   \   00000048   9300....           STS     ErrorFlags, R16\r
+    122                \r
+    123                // Init complete! Go to ST_BATCON next.\r
+    124                return(ST_BATCON);\r
+   \   0000004C   E104               LDI     R16, 20\r
+   \   0000004E   9189               LD      R24, Y+\r
+   \   00000050   9508               RET\r
+   \   00000052                      REQUIRE _A_CLKPR\r
+   \   00000052                      REQUIRE _A_DDRB\r
+    125          }\r
+    126          \r
+    127          \r
+    128          /*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
+    129           *\r
+    130           * First, JumperCheck() is called. If successful, the function checks if any\r
+    131           * valid batteries are connected and attempts to charge these, if necessary.\n\r
+    132           * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
+    133           * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
+    134           * batteries. In this last case, the error is also flagged.\r
+    135           *\r
+    136           * \param inp Not used.\r
+    137           *\r
+    138           * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
+    139           * no valid batteries.\r
+    140           * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
+    141           * charged.\r
+    142           * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
+    143           * charged.\r
+    144           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    145          unsigned char BatteryControl(unsigned char inp)\r
+   \                     BatteryControl:\r
+    146          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+   \   00000004   939A               ST      -Y, R25\r
+   \   00000006   938A               ST      -Y, R24\r
+    147                unsigned char i;\r
+    148                \r
+    149                // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
+    150                if (!JumperCheck()) {\r
+   \   00000008   ....               RCALL   JumperCheck\r
+   \   0000000A   2300               TST     R16\r
+   \   0000000C   F411               BRNE    ??BatteryControl_0\r
+    151                        return(ST_ERROR);           // Error. Exit before damage is done!\r
+   \                     ??BatteryControl_1:\r
+   \   0000000E   E50A               LDI     R16, 90\r
+   \   00000010   C02F               RJMP    ??BatteryControl_2\r
+    152                }\r
+    153                \r
+    154                // If neither battery is valid, flag error and go to error state\r
+    155                if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
+   \                     ??BatteryControl_0:\r
+   \   00000012   ....               LDI     R24, LOW(BattControl)\r
+   \   00000014   ....               LDI     R25, (BattControl) >> 8\r
+   \   00000016   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000018   ....               RCALL   __eeget8_16\r
+   \   0000001A   7001               ANDI    R16, 0x01\r
+   \   0000001C   F479               BRNE    ??BatteryControl_3\r
+   \   0000001E   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000020   5F4F               SUBI    R20, 255\r
+   \   00000022   4F5F               SBCI    R21, 255\r
+   \   00000024   ....               RCALL   __eeget8_16\r
+   \   00000026   7001               ANDI    R16, 0x01\r
+   \   00000028   F449               BRNE    ??BatteryControl_3\r
+    156                        SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
+   \   0000002A   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   0000002C   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   0000002E   8100               LD      R16, Z\r
+   \   00000030   6002               ORI     R16, 0x02\r
+   \   00000032   8300               ST      Z, R16\r
+   \   00000034   9100....           LDS     R16, CurrentState\r
+   \   00000038   8301               STD     Z+1, R16\r
+    157                        \r
+    158                        return(ST_ERROR);\r
+   \   0000003A   CFE9               RJMP    ??BatteryControl_1\r
+    159                }\r
+    160          \r
+    161                // Get ADC-readings, try to read EPROM, and start prequalification\r
+    162                // of any uncharged battery.\r
+    163                for (i = 0; i < 2; i++) {\r
+   \                     ??BatteryControl_3:\r
+   \   0000003C   E0A0               LDI     R26, 0\r
+    164                        if (BattControl[i].Enabled) {      \r
+   \                     ??BatteryControl_4:\r
+   \   0000003E   E0B0               LDI     R27, 0\r
+   \   00000040   01AC               MOVW    R21:R20, R25:R24\r
+   \   00000042   0F4A               ADD     R20, R26\r
+   \   00000044   1F5B               ADC     R21, R27\r
+   \   00000046   ....               RCALL   __eeget8_16\r
+   \   00000048   7001               ANDI    R16, 0x01\r
+   \   0000004A   F069               BREQ    ??BatteryControl_5\r
+    165                                EnableBattery(i);\r
+   \   0000004C   2F0A               MOV     R16, R26\r
+   \   0000004E   ....               RCALL   EnableBattery\r
+    166                                ADC_Wait();\r
+   \   00000050   ....               RCALL   ADC_Wait\r
+    167          \r
+    168                                if (BatteryStatusRefresh()) {\r
+   \   00000052   ....               RCALL   BatteryStatusRefresh\r
+   \   00000054   2300               TST     R16\r
+   \   00000056   F039               BREQ    ??BatteryControl_5\r
+    169                                        if (!BattData.Charged) {\r
+   \   00000058   9100....           LDS     R16, BattData\r
+   \   0000005C   FD01               SBRC    R16, 1\r
+   \   0000005E   C003               RJMP    ??BatteryControl_5\r
+    170                                                BatteryDataRefresh();\r
+   \   00000060   ....               RCALL   BatteryDataRefresh\r
+    171          \r
+    172                                                return(ST_PREQUAL);       \r
+   \   00000062   E10E               LDI     R16, 30\r
+   \   00000064   C005               RJMP    ??BatteryControl_2\r
+    173                                        }\r
+    174                                }\r
+    175                        }\r
+    176                }\r
+   \                     ??BatteryControl_5:\r
+   \   00000066   95A3               INC     R26\r
+   \   00000068   30A2               CPI     R26, 2\r
+   \   0000006A   F348               BRCS    ??BatteryControl_4\r
+    177          \r
+    178                // If we end up here, one or two batteries are found and fully charged.\r
+    179                // Disconnect, so we don't drain them, and go to sleep.\r
+    180                DisableBatteries();\r
+   \   0000006C   ....               RCALL   DisableBatteries\r
+    181          \r
+    182                return(ST_SLEEP);\r
+   \   0000006E   E208               LDI     R16, 40\r
+   \                     ??BatteryControl_2:\r
+   \   00000070   9189               LD      R24, Y+\r
+   \   00000072   9199               LD      R25, Y+\r
+   \   00000074   91A9               LD      R26, Y+\r
+   \   00000076   91B9               LD      R27, Y+\r
+   \   00000078   9508               RET\r
+    183          }\r
+    184          \r
+    185          \r
+    186          /*! \brief Start running on batteries\r
+    187           *\r
+    188           * \todo Run on batteries, if battery voltage high enough.\r
+    189           * \todo Jump here when mains voltage drops below threshold\r
+    190           *\r
+    191           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    192          unsigned char Discharge(unsigned char inp)\r
+   \                     Discharge:\r
+    193          {\r
+    194                return(ST_BATCON);  // Supply voltage restored, start charging\r
+   \   00000000   E104               LDI     R16, 20\r
+   \   00000002   9508               RET\r
+    195          }\r
+    196          \r
+    197          \r
+    198          /*! \brief Sleeps until either battery needs charging\r
+    199           *\r
+    200           * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
+    201           * connected batteries are both charged, the function will loop. If not, it's\r
+    202           * back to ST_BATCON.\r
+    203           *\r
+    204           * \param inp Not used.\r
+    205           *\r
+    206           * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
+    207           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    208          unsigned char Sleep(unsigned char inp)\r
+   \                     `Sleep`:\r
+    209          {\r
+    210                unsigned char i;\r
+    211          \r
+    212                do {\r
+    213                        Doze();               // Take a nap (~8 seconds).\r
+   \   00000000   ....               RCALL   ADC_Wait\r
+   \                     ??Sleep_0:\r
+   \   00000002   CFFF               RJMP    ??Sleep_0\r
+   \   00000004                      REQUIRE _A_MCUCR\r
+   \   00000004                      REQUIRE _A_MCUSR\r
+   \   00000004                      REQUIRE _A_WDTCR\r
+   \   00000004                      REQUIRE _A_ADCSRA\r
+    214          \r
+    215                        // If any batteries need charging, go to ST_BATCON.\r
+    216                        // Otherwise, keep sleeping.\r
+    217                        for (i = 0; i < 2; i++) {\r
+    218                                EnableBattery(i);\r
+    219                                ADC_Wait();\r
+    220                                if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
+    221                                        return(ST_BATCON);\r
+    222                                }\r
+    223                        }\r
+    224                        \r
+    225                        DisableBatteries();  // Disable both batteries before Doze()!\r
+    226                } while (TRUE);\r
+    227          }\r
+    228          \r
+    229          \r
+    230          /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
+    231           *\r
+    232           * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
+    233           * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
+    234           * On wakeup, ADC is re-enabled.\r
+    235           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    236          void Doze(void)\r
+   \                     Doze:\r
+    237          {\r
+    238                // Wait for this ADC cycle to complete, then halt after the next one.\r
+    239                ADC_Wait();\r
+   \   00000000   ....               RCALL   ADC_Wait\r
+    240                ADCS.Halt = TRUE;\r
+    241                ADCS.Flag = FALSE;\r
+    242                \r
+    243                do {\r
+    244                } while (ADCS.Flag == FALSE);    \r
+   \                     ??Doze_0:\r
+   \   00000002   CFFF               RJMP    ??Doze_0\r
+   \   00000004                      REQUIRE _A_MCUCR\r
+   \   00000004                      REQUIRE _A_MCUSR\r
+   \   00000004                      REQUIRE _A_WDTCR\r
+   \   00000004                      REQUIRE _A_ADCSRA\r
+    245                \r
+    246                WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
+    247                WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
+    248                MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
+    249                __sleep();                              // Go to sleep, wake up by WDT.\r
+    250                \r
+    251                __watchdog_reset();                     // Clear watchdog reset flag.\r
+    252                MCUSR &= ~(1<<WDRF);          \r
+    253                WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
+    254                WDTCR = 0;                              // Turn off watchdog.\r
+    255                \r
+    256                ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
+    257                ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
+    258                \r
+    259                // Wait for this cycle to complete.\r
+    260                ADC_Wait();                             \r
+    261          }\r
+    262          \r
+    263          \r
+    264          /*! \brief Handles errors\r
+    265           *\r
+    266           * Stops PWM output and disables batteries. The function then goes into a loop\r
+    267           * that starts with a call to Doze(), then attempts to handle each error. The\r
+    268           * loop will reiterate until all flags are cleared.\n\r
+    269           * The charger will reinitialize after this.\r
+    270           *\r
+    271           * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
+    272           * If unsuccessful, the error flag will now have been set again.\n\r
+    273           *\r
+    274           * If there are no valid batteries, the loop will simply reiterate until a\r
+    275           * valid battery is found. The error flag will then be cleared.\n\r
+    276           *\r
+    277           * In the case of PWM controller or battery temperature errors, the error\r
+    278           * flag is simply cleared. This is because the problem may have gone away during\r
+    279           * Doze(), or after reinitializing.\n\r
+    280           *\r
+    281           * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
+    282           * and change batteries before clearing the error flag.\r
+    283           *\r
+    284           * \param inp Not used.\r
+    285           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    286          unsigned char Error(unsigned char inp)\r
+   \                     Error:\r
+    287                {\r
+    288                unsigned char i;\r
+    289                \r
+    290                PWM_Stop();           // Stop charging.\r
+   \   00000000   ....               RCALL   PWM_Stop\r
+    291                DisableBatteries();   // Disable all loads.\r
+   \   00000002   ....               RCALL   DisableBatteries\r
+    292                \r
+    293                do {\r
+    294                        Doze();           // Take a nap.\r
+   \   00000004   ....               RCALL   ADC_Wait\r
+   \                     ??Error_0:\r
+   \   00000006   CFFF               RJMP    ??Error_0\r
+   \   00000008                      REQUIRE _A_MCUCR\r
+   \   00000008                      REQUIRE _A_MCUSR\r
+   \   00000008                      REQUIRE _A_WDTCR\r
+   \   00000008                      REQUIRE _A_ADCSRA\r
+    295          \r
+    296                        // For each bit in ErrorFlags, starting with LSB, handle\r
+    297                        // associated error, if the flag is set.\r
+    298                        for (i = 0x01; i!=0; i<<=1) {\r
+    299                                if(i & ErrorFlags) {\r
+    300                                        switch (i) {\r
+    301                                        \r
+    302                                        case  ERR_JUMPER_MISMATCH:\r
+    303                                                // Clear flag & recheck.\r
+    304                                                ErrorFlags &= ~i;\r
+    305                                                JumperCheck();\r
+    306                                        break;\r
+    307          \r
+    308          \r
+    309                                        case  ERR_NO_BATTERIES_ENABLED:\r
+    310                                                // Clear if any battery gets enabled.\r
+    311                                                if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {\r
+    312                                                                ErrorFlags &= ~i;\r
+    313                                                }\r
+    314                                        break;\r
+    315          \r
+    316          \r
+    317                                        case  ERR_PWM_CONTROL:\r
+    318                                                // Clear flag.\r
+    319                                                ErrorFlags &= ~i;\r
+    320                                        break;\r
+    321          \r
+    322          \r
+    323                                        case  ERR_BATTERY_TEMPERATURE:\r
+    324                                                // Clear flag.\r
+    325                                                ErrorFlags &= ~i;\r
+    326                                        break;\r
+    327          \r
+    328          \r
+    329                                        case  ERR_BATTERY_EXHAUSTED:\r
+    330                                                // Try the other battery.\r
+    331                                                BattData.Exhausted = FALSE;\r
+    332                                                BattActive = (BattActive + 1) % 2;\r
+    333                                                ErrorFlags &= ~i;\r
+    334                                        break;\r
+    335          \r
+    336                                                \r
+    337                                        default:\r
+    338                                        break;\r
+    339                                        }\r
+    340                                }\r
+    341                        }\r
+    342                } while (ErrorFlags);\r
+    343          \r
+    344                return(ST_INIT);\r
+    345          }\r
+    346          \r
+    347          \r
+    348          /*! \brief Sets the specified error-flag and saves the current state\r
+    349           *\r
+    350           * Updates \ref ErrorFlags and \ref ErrorState.\r
+    351           *\r
+    352           * \note Error flags are specified in statefunc.h.\r
+    353           *\r
+    354           * \param Flag Specifies what error to flag.\r
+    355           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    356          void SetErrorFlag(unsigned char Flag)\r
+   \                     SetErrorFlag:\r
+    357          {\r
+    358                ErrorFlags |= Flag;\r
+   \   00000000   ....               LDI     R30, LOW(ErrorFlags)\r
+   \   00000002   ....               LDI     R31, (ErrorFlags) >> 8\r
+   \   00000004   8110               LD      R17, Z\r
+   \   00000006   2B10               OR      R17, R16\r
+   \   00000008   8310               ST      Z, R17\r
+    359                ErrorState = CurrentState;\r
+   \   0000000A   9100....           LDS     R16, CurrentState\r
+   \   0000000E   8301               STD     Z+1, R16\r
+    360          }\r
+   \   00000010   9508               RET\r
+    361          \r
+    362          \r
+    363          /*! \brief Checks on-board jumpers.\r
+    364           *\r
+    365           * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
+    366           * increasing the duty cycle until conditioned output voltage equals conditioned\r
+    367           * input voltage. At low PWM duty and no load buck output should be zero and,\r
+    368           * when increasing PWM duty, should quickly jump to steady state output roughly\r
+    369           * equal to input voltage. Will disable and leave disabled all batteries.\r
+    370           *\r
+    371           * \retval FALSE If jumper or load mismatch.\r
+    372           * \retval TRUE If everything OK.\r
+    373           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    374          unsigned char JumperCheck(void)\r
+   \                     JumperCheck:\r
+    375          {\r
+   \   00000000   93BA               ST      -Y, R27\r
+   \   00000002   93AA               ST      -Y, R26\r
+    376                 DisableBatteries();       // Disconnect, or loads may be destroyed!\r
+   \   00000004   ....               RCALL   DisableBatteries\r
+    377                 \r
+    378                 PWM_Start();              // Start PWM (controls the buck charger).\r
+   \   00000006   ....               RCALL   PWM_Start\r
+    379                \r
+    380                 // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
+    381                 Time_Set(TIMER_GEN,0,1,0);\r
+   \   00000008   E040               LDI     R20, 0\r
+   \   0000000A   E011               LDI     R17, 1\r
+   \   0000000C   E020               LDI     R18, 0\r
+   \   0000000E   E030               LDI     R19, 0\r
+   \   00000010   E002               LDI     R16, 2\r
+   \   00000012   ....               RCALL   Time_Set\r
+   \   00000014   ....               LDI     R26, LOW(ADCS)\r
+   \   00000016   ....               LDI     R27, (ADCS) >> 8\r
+   \   00000018   C010               RJMP    ??JumperCheck_0\r
+    382                \r
+    383                do {\r
+    384                        // If the PWM output voltage saturates the ADC, stop PWM output and\r
+    385                        // report a failure.\r
+    386                        if (ADCS.rawVBAT == 1023) {\r
+    387                                PWM_Stop();\r
+    388                                return(FALSE);\r
+    389                        }\r
+    390          \r
+    391                        // If the absolute difference between measured (VIN - VBAT) and the\r
+    392                        // typical value are below our set maximum, everything is OK.\r
+    393                        if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+    394                                             VIN_VBAT_DIFF_MAX ) {\r
+    395                                         \r
+    396                                PWM_Stop();\r
+    397                                return(TRUE);\r
+    398                        }\r
+    399          \r
+    400                        // Charge current is too high -> check load and jumper J405 and J406.\r
+    401                        if (abs(ADCS.IBAT) > 100) {\r
+   \                     ??JumperCheck_1:\r
+   \   0000001A   961C               ADIW    R27:R26, 12\r
+   \   0000001C   910D               LD      R16, X+\r
+   \   0000001E   911C               LD      R17, X\r
+   \   00000020   971D               SBIW    R27:R26, 13\r
+   \   00000022   ....               RCALL   abs\r
+   \   00000024   3605               CPI     R16, 101\r
+   \   00000026   4010               SBCI    R17, 0\r
+   \   00000028   F47C               BRGE    ??JumperCheck_2\r
+    402                                PWM_Stop();\r
+    403                                return(FALSE);\r
+    404                        }\r
+    405          \r
+    406                        // If the PWM output can't be increased high enough -> check jumpers\r
+    407                        // J400-J404, J407 and J408.\r
+    408                        if (!PWM_IncrementDutyCycle()) {\r
+   \   0000002A   ....               RCALL   PWM_IncrementDutyCycle\r
+   \   0000002C   2300               TST     R16\r
+   \   0000002E   F061               BREQ    ??JumperCheck_2\r
+    409                                PWM_Stop();\r
+    410                                return(FALSE);\r
+    411                        }\r
+    412                        \r
+    413                // Wait for ADC conversions to complete\r
+    414                        ADC_Wait();\r
+   \   00000030   ....               RCALL   ADC_Wait\r
+    415                } while (Time_Left(TIMER_GEN));\r
+   \   00000032   E002               LDI     R16, 2\r
+   \   00000034   ....               RCALL   Time_Left\r
+   \   00000036   2300               TST     R16\r
+   \   00000038   F039               BREQ    ??JumperCheck_2\r
+   \                     ??JumperCheck_0:\r
+   \   0000003A   9616               ADIW    R27:R26, 6\r
+   \   0000003C   910D               LD      R16, X+\r
+   \   0000003E   911C               LD      R17, X\r
+   \   00000040   9717               SBIW    R27:R26, 7\r
+   \   00000042   3F0F               CPI     R16, 255\r
+   \   00000044   4013               SBCI    R17, 3\r
+   \   00000046   F419               BRNE    ??JumperCheck_3\r
+   \                     ??JumperCheck_2:\r
+   \   00000048   ....               RCALL   PWM_Stop\r
+   \   0000004A   E000               LDI     R16, 0\r
+   \   0000004C   C010               RJMP    ??JumperCheck_4\r
+   \                     ??JumperCheck_3:\r
+   \   0000004E   9618               ADIW    R27:R26, 8\r
+   \   00000050   910D               LD      R16, X+\r
+   \   00000052   911D               LD      R17, X+\r
+   \   00000054   5508               SUBI    R16, 88\r
+   \   00000056   4012               SBCI    R17, 2\r
+   \   00000058   912D               LD      R18, X+\r
+   \   0000005A   913C               LD      R19, X\r
+   \   0000005C   971B               SBIW    R27:R26, 11\r
+   \   0000005E   1B02               SUB     R16, R18\r
+   \   00000060   0B13               SBC     R17, R19\r
+   \   00000062   ....               RCALL   abs\r
+   \   00000064   3F04               CPI     R16, 244\r
+   \   00000066   4011               SBCI    R17, 1\r
+   \   00000068   F6C4               BRGE    ??JumperCheck_1\r
+   \   0000006A   ....               RCALL   PWM_Stop\r
+   \   0000006C   E001               LDI     R16, 1\r
+   \                     ??JumperCheck_4:\r
+   \   0000006E   91A9               LD      R26, Y+\r
+   \   00000070   91B9               LD      R27, Y+\r
+   \   00000072   9508               RET\r
+    416                \r
+    417          \r
+    418                // If we end up here, the measurements took too long.\r
+    419                PWM_Stop();\r
+    420                return(FALSE);\r
+    421          }\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function                    CSTACK RSTACK\r
+     --------                    ------ ------\r
+     BatteryControl                  4      4\r
+       -> JumperCheck                4      2\r
+       -> EnableBattery              4      2\r
+       -> ADC_Wait                   4      2\r
+       -> BatteryStatusRefresh       4      2\r
+       -> BatteryDataRefresh         4      2\r
+       -> DisableBatteries           4      2\r
+     Discharge                       0      2\r
+     Doze                            0      2\r
+       -> ADC_Wait                   0      2\r
+     Error                           0      2\r
+       -> PWM_Stop                   0      2\r
+       -> DisableBatteries           0      2\r
+       -> ADC_Wait                   0      2\r
+     Initialize                      1      4\r
+       -> OWI_Init                   1      2\r
+       -> DisableBatteries           1      2\r
+       -> SPI_Init                   1      2\r
+       -> ADC_Init                   1      2\r
+       -> Time_Init                  1      2\r
+       -> EnableBattery              1      2\r
+       -> ADC_Wait                   1      2\r
+       -> BatteryStatusRefresh       1      2\r
+       -> DisableBatteries           1      2\r
+     JumperCheck                     2      2\r
+       -> DisableBatteries           2      2\r
+       -> PWM_Start                  2      2\r
+       -> Time_Set                   2      2\r
+       -> abs                        2      2\r
+       -> PWM_IncrementDutyCycle     2      2\r
+       -> ADC_Wait                   2      2\r
+       -> Time_Left                  2      2\r
+       -> PWM_Stop                   2      2\r
+       -> abs                        2      2\r
+       -> PWM_Stop                   2      2\r
+     SetErrorFlag                    0      2\r
+     Sleep                           0      2\r
+       -> ADC_Wait                   0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label Bytes\r
+     -------------- -----\r
+     _A_MCUCR          1\r
+     _A_MCUSR          1\r
+     _A_CLKPR          1\r
+     _A_WDTCR          1\r
+     _A_DDRB           1\r
+     _A_ADCSRA         1\r
+     ErrorFlags        2\r
+     Initialize       82\r
+     BatteryControl  122\r
+     Discharge         4\r
+     Sleep             4\r
+     Doze              4\r
+     Error             8\r
+     SetErrorFlag     18\r
+     JumperCheck     116\r
+      Others           6\r
+\r
\r
+   6 bytes in segment ABSOLUTE\r
+ 358 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment NEAR_Z\r
\r
+ 358 bytes of CODE memory (+ 6 bytes shared)\r
+   2 bytes of DATA memory (+ 6 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/statefunc.s90 b/BaseTinyFirmware/IAR/Release/List/statefunc.s90
new file mode 100644 (file)
index 0000000..5f7f353
--- /dev/null
@@ -0,0 +1,808 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:01 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\statefunc.c    /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\statefunc.c    /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\s /\r
+//                             tatefunc.s90                                   /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME statefunc\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?need_segment_init\r
+        EXTERN __eeget8_16\r
+        EXTERN __eeput8_16\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBLIC BatteryControl\r
+        PUBLIC Discharge\r
+        PUBLIC Doze\r
+        PUBLIC Error\r
+        PUBLIC ErrorFlags\r
+        PUBLIC ErrorState\r
+        PUBLIC Initialize\r
+        PUBLIC JumperCheck\r
+        PUBLIC SetErrorFlag\r
+        PUBLIC `Sleep`\r
+        PUBWEAK _A_ADCSRA\r
+        PUBWEAK _A_CLKPR\r
+        PUBWEAK _A_DDRB\r
+        PUBWEAK _A_MCUCR\r
+        PUBWEAK _A_MCUSR\r
+        PUBWEAK _A_WDTCR\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+\r
+        EXTERN OWI_Init\r
+        EXTERN DisableBatteries\r
+        EXTERN SPI_Init\r
+        EXTERN ADC_Init\r
+        EXTERN Time_Init\r
+        EXTERN EnableBattery\r
+        EXTERN ADC_Wait\r
+        EXTERN BatteryStatusRefresh\r
+        EXTERN BatteryDataRefresh\r
+        EXTERN PWM_Stop\r
+        EXTERN PWM_Start\r
+        EXTERN Time_Set\r
+        EXTERN abs\r
+        EXTERN PWM_IncrementDutyCycle\r
+        EXTERN Time_Left\r
+        EXTERN ADCS\r
+        EXTERN BattActive\r
+        EXTERN BattControl\r
+        EXTERN BattData\r
+        EXTERN BattEEPROM\r
+        EXTERN CurrentState\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\statefunc.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      State functions\r
+//    6  *\r
+//    7  *      Contains the functions related to the states defined in menu.h.\n\r
+//    8  *      Also contains related functions, i.e. for checking jumpers, setting\r
+//    9  *      error flags and "dozing".\r
+//   10  *\r
+//   11  *      \note The state function Charge() is in a separate file since it\r
+//   12  *      should easily be changed with regard to battery type.\r
+//   13  *\r
+//   14  * \par Application note:\r
+//   15  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   16  *      AVR463: Charging NiMH Batteries with BC100\r
+//   17  *\r
+//   18  * \par Documentation\r
+//   19  *      For comprehensive code documentation, supported compilers, compiler \r
+//   20  *      settings and supported devices see readme.html\r
+//   21  *\r
+//   22  * \author\r
+//   23  *      Atmel Corporation: http://www.atmel.com \n\r
+//   24  *      Support email: avr@atmel.com\r
+//   25  *\r
+//   26  * \r
+//   27  * $Name$\r
+//   28  * $Revision: 2299 $\r
+//   29  * $RCSfile$\r
+//   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
+//   31  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   32  ******************************************************************************/\r
+//   33 \r
+//   34 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,055H\r
+// <unnamed> volatile __io _A_MCUCR\r
+_A_MCUCR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,054H\r
+// <unnamed> volatile __io _A_MCUSR\r
+_A_MCUSR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,048H\r
+// <unnamed> volatile __io _A_CLKPR\r
+_A_CLKPR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,041H\r
+// <unnamed> volatile __io _A_WDTCR\r
+_A_WDTCR:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,037H\r
+// <unnamed> volatile __io _A_DDRB\r
+_A_DDRB:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,026H\r
+// <unnamed> volatile __io _A_ADCSRA\r
+_A_ADCSRA:\r
+        DS 1\r
+//   35 #include <inavr.h>\r
+//   36 #include <stdlib.h>\r
+//   37 \r
+//   38 #include "structs.h"\r
+//   39 #include "enums.h"\r
+//   40 \r
+//   41 #include "ADC.h"\r
+//   42 #include "statefunc.h"\r
+//   43 #include "battery.h"\r
+//   44 #include "charge.h"\r
+//   45 #include "main.h"\r
+//   46 #include "menu.h"\r
+//   47 #include "OWI.h"\r
+//   48 #include "PWM.h"\r
+//   49 #include "time.h"\r
+//   50 #include "USI.h"\r
+//   51 \r
+//   52 \r
+//   53 //******************************************************************************\r
+//   54 // Variables\r
+//   55 //******************************************************************************\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   56 unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
+ErrorFlags:\r
+        DS 1\r
+//   57                            //!< \note See statefunc.h for definitions of flags.\r
+//   58 \r
+//   59 //! \brief Holds the state in which latest error flag was set.\r
+//   60 //! \note See menu.h for definitions of states.\r
+//   61 unsigned char ErrorState;\r
+ErrorState:\r
+        DS 1\r
+//   62 \r
+//   63 \r
+//   64 //******************************************************************************\r
+//   65 // Functions\r
+//   66 //******************************************************************************\r
+//   67 /*! \brief Initialization\r
+//   68  *\r
+//   69  * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
+//   70  * - Initializes the one-wire interface\r
+//   71  * - Clears on-chip EEPROM\r
+//   72  * - Sets battery enable pins as outputs, then disables batteries\r
+//   73  * - Initializes SPI according to \ref SPIMODE\r
+//   74  * - Initializes ADC\r
+//   75  * - Initializes timers\r
+//   76  * - Reads battery data from both battery inputs (via ADC)\r
+//   77  * - Disables batteries again\r
+//   78  * - Sets battery A as the current one (\ref BattActive = 0)\r
+//   79  * - Clears ErrorFlags\r
+//   80  *\r
+//   81  * \param inp Not used.\r
+//   82  *\r
+//   83  * \retval ST_BATCON Next state in the sequence.\r
+//   84  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   85 unsigned char Initialize(unsigned char inp)\r
+Initialize:\r
+//   86 {\r
+        ST      -Y, R24\r
+//   87        unsigned char i, page;\r
+//   88 \r
+//   89        // Disable interrupts while setting prescaler.\r
+//   90        __disable_interrupt();\r
+        CLI\r
+//   91        \r
+//   92        CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
+        LDI     R16, 128\r
+        OUT     0x28, R16\r
+//   93        CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
+        LDI     R16, 0\r
+        OUT     0x28, R16\r
+//   94        \r
+//   95        // Init 1-Wire(R) interface.\r
+//   96        OWI_Init(OWIBUS);\r
+        LDI     R16, 1\r
+        RCALL   OWI_Init\r
+//   97        \r
+//   98        // Clear on-chip EEPROM.\r
+//   99        for (page = 0; page < 4; page++)        {\r
+        LDI     R20, LOW(BattEEPROM)\r
+        LDI     R21, (BattEEPROM) >> 8\r
+        LDI     R17, 128\r
+//  100                for (i = 0; i < 32; i++) {\r
+//  101                        BattEEPROM[page][i] = 0;\r
+??Initialize_0:\r
+        LDI     R16, 0\r
+        RCALL   __eeput8_16\r
+//  102                }\r
+        SUBI    R20, 255\r
+        SBCI    R21, 255\r
+//  103        }\r
+        DEC     R17\r
+        BRNE    ??Initialize_0\r
+//  104 \r
+//  105        DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
+        LDI     R16, 48\r
+        OUT     0x17, R16\r
+//  106        DisableBatteries();\r
+        RCALL   DisableBatteries\r
+//  107        SPI_Init(SPIMODE);\r
+        LDI     R16, 0\r
+        RCALL   SPI_Init\r
+//  108        ADC_Init();\r
+        RCALL   ADC_Init\r
+//  109        Time_Init();\r
+        RCALL   Time_Init\r
+//  110 \r
+//  111        // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
+//  112        for (i = 0; i < 2; i++) {\r
+        LDI     R24, 0\r
+//  113                EnableBattery(i);\r
+??Initialize_1:\r
+        MOV     R16, R24\r
+        RCALL   EnableBattery\r
+//  114                ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  115                BatteryStatusRefresh();\r
+        RCALL   BatteryStatusRefresh\r
+//  116        }\r
+        INC     R24\r
+        CPI     R24, 2\r
+        BRCS    ??Initialize_1\r
+//  117     \r
+//  118        DisableBatteries();\r
+        RCALL   DisableBatteries\r
+//  119        \r
+//  120        BattActive = 0;               // We have to start somewhere..\r
+        LDI     R16, 0\r
+        STS     BattActive, R16\r
+//  121        ErrorFlags = 0;\r
+        STS     ErrorFlags, R16\r
+//  122        \r
+//  123        // Init complete! Go to ST_BATCON next.\r
+//  124        return(ST_BATCON);\r
+        LDI     R16, 20\r
+        LD      R24, Y+\r
+        RET\r
+        REQUIRE _A_CLKPR\r
+        REQUIRE _A_DDRB\r
+//  125 }\r
+//  126 \r
+//  127 \r
+//  128 /*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
+//  129  *\r
+//  130  * First, JumperCheck() is called. If successful, the function checks if any\r
+//  131  * valid batteries are connected and attempts to charge these, if necessary.\n\r
+//  132  * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
+//  133  * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
+//  134  * batteries. In this last case, the error is also flagged.\r
+//  135  *\r
+//  136  * \param inp Not used.\r
+//  137  *\r
+//  138  * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
+//  139  * no valid batteries.\r
+//  140  * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
+//  141  * charged.\r
+//  142  * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
+//  143  * charged.\r
+//  144  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  145 unsigned char BatteryControl(unsigned char inp)\r
+BatteryControl:\r
+//  146 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+//  147        unsigned char i;\r
+//  148        \r
+//  149        // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
+//  150        if (!JumperCheck()) {\r
+        RCALL   JumperCheck\r
+        TST     R16\r
+        BRNE    ??BatteryControl_0\r
+//  151                return(ST_ERROR);           // Error. Exit before damage is done!\r
+??BatteryControl_1:\r
+        LDI     R16, 90\r
+        RJMP    ??BatteryControl_2\r
+//  152        }\r
+//  153        \r
+//  154        // If neither battery is valid, flag error and go to error state\r
+//  155        if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
+??BatteryControl_0:\r
+        LDI     R24, LOW(BattControl)\r
+        LDI     R25, (BattControl) >> 8\r
+        MOVW    R21:R20, R25:R24\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        BRNE    ??BatteryControl_3\r
+        MOVW    R21:R20, R25:R24\r
+        SUBI    R20, 255\r
+        SBCI    R21, 255\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        BRNE    ??BatteryControl_3\r
+//  156                SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R16, Z\r
+        ORI     R16, 0x02\r
+        ST      Z, R16\r
+        LDS     R16, CurrentState\r
+        STD     Z+1, R16\r
+//  157                \r
+//  158                return(ST_ERROR);\r
+        RJMP    ??BatteryControl_1\r
+//  159        }\r
+//  160 \r
+//  161        // Get ADC-readings, try to read EPROM, and start prequalification\r
+//  162        // of any uncharged battery.\r
+//  163        for (i = 0; i < 2; i++) {\r
+??BatteryControl_3:\r
+        LDI     R26, 0\r
+//  164                if (BattControl[i].Enabled) {      \r
+??BatteryControl_4:\r
+        LDI     R27, 0\r
+        MOVW    R21:R20, R25:R24\r
+        ADD     R20, R26\r
+        ADC     R21, R27\r
+        RCALL   __eeget8_16\r
+        ANDI    R16, 0x01\r
+        BREQ    ??BatteryControl_5\r
+//  165                        EnableBattery(i);\r
+        MOV     R16, R26\r
+        RCALL   EnableBattery\r
+//  166                        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  167 \r
+//  168                        if (BatteryStatusRefresh()) {\r
+        RCALL   BatteryStatusRefresh\r
+        TST     R16\r
+        BREQ    ??BatteryControl_5\r
+//  169                                if (!BattData.Charged) {\r
+        LDS     R16, BattData\r
+        SBRC    R16, 1\r
+        RJMP    ??BatteryControl_5\r
+//  170                                        BatteryDataRefresh();\r
+        RCALL   BatteryDataRefresh\r
+//  171 \r
+//  172                                        return(ST_PREQUAL);       \r
+        LDI     R16, 30\r
+        RJMP    ??BatteryControl_2\r
+//  173                                }\r
+//  174                        }\r
+//  175                }\r
+//  176        }\r
+??BatteryControl_5:\r
+        INC     R26\r
+        CPI     R26, 2\r
+        BRCS    ??BatteryControl_4\r
+//  177 \r
+//  178        // If we end up here, one or two batteries are found and fully charged.\r
+//  179        // Disconnect, so we don't drain them, and go to sleep.\r
+//  180        DisableBatteries();\r
+        RCALL   DisableBatteries\r
+//  181 \r
+//  182        return(ST_SLEEP);\r
+        LDI     R16, 40\r
+??BatteryControl_2:\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+//  183 }\r
+//  184 \r
+//  185 \r
+//  186 /*! \brief Start running on batteries\r
+//  187  *\r
+//  188  * \todo Run on batteries, if battery voltage high enough.\r
+//  189  * \todo Jump here when mains voltage drops below threshold\r
+//  190  *\r
+//  191  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  192 unsigned char Discharge(unsigned char inp)\r
+Discharge:\r
+//  193 {\r
+//  194        return(ST_BATCON);  // Supply voltage restored, start charging\r
+        LDI     R16, 20\r
+        RET\r
+//  195 }\r
+//  196 \r
+//  197 \r
+//  198 /*! \brief Sleeps until either battery needs charging\r
+//  199  *\r
+//  200  * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
+//  201  * connected batteries are both charged, the function will loop. If not, it's\r
+//  202  * back to ST_BATCON.\r
+//  203  *\r
+//  204  * \param inp Not used.\r
+//  205  *\r
+//  206  * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
+//  207  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  208 unsigned char Sleep(unsigned char inp)\r
+`Sleep`:\r
+//  209 {\r
+//  210        unsigned char i;\r
+//  211 \r
+//  212        do {\r
+//  213                Doze();               // Take a nap (~8 seconds).\r
+        RCALL   ADC_Wait\r
+??Sleep_0:\r
+        RJMP    ??Sleep_0\r
+        REQUIRE _A_MCUCR\r
+        REQUIRE _A_MCUSR\r
+        REQUIRE _A_WDTCR\r
+        REQUIRE _A_ADCSRA\r
+//  214 \r
+//  215                // If any batteries need charging, go to ST_BATCON.\r
+//  216                // Otherwise, keep sleeping.\r
+//  217                for (i = 0; i < 2; i++) {\r
+//  218                        EnableBattery(i);\r
+//  219                        ADC_Wait();\r
+//  220                        if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
+//  221                                return(ST_BATCON);\r
+//  222                        }\r
+//  223                }\r
+//  224                \r
+//  225                DisableBatteries();  // Disable both batteries before Doze()!\r
+//  226        } while (TRUE);\r
+//  227 }\r
+//  228 \r
+//  229 \r
+//  230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
+//  231  *\r
+//  232  * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
+//  233  * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
+//  234  * On wakeup, ADC is re-enabled.\r
+//  235  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  236 void Doze(void)\r
+Doze:\r
+//  237 {\r
+//  238        // Wait for this ADC cycle to complete, then halt after the next one.\r
+//  239        ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  240        ADCS.Halt = TRUE;\r
+//  241        ADCS.Flag = FALSE;\r
+//  242        \r
+//  243        do {\r
+//  244        } while (ADCS.Flag == FALSE);    \r
+??Doze_0:\r
+        RJMP    ??Doze_0\r
+        REQUIRE _A_MCUCR\r
+        REQUIRE _A_MCUSR\r
+        REQUIRE _A_WDTCR\r
+        REQUIRE _A_ADCSRA\r
+//  245        \r
+//  246        WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
+//  247        WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
+//  248        MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
+//  249        __sleep();                              // Go to sleep, wake up by WDT.\r
+//  250        \r
+//  251        __watchdog_reset();                     // Clear watchdog reset flag.\r
+//  252        MCUSR &= ~(1<<WDRF);          \r
+//  253        WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
+//  254        WDTCR = 0;                              // Turn off watchdog.\r
+//  255        \r
+//  256        ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
+//  257        ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
+//  258        \r
+//  259        // Wait for this cycle to complete.\r
+//  260        ADC_Wait();                             \r
+//  261 }\r
+//  262 \r
+//  263 \r
+//  264 /*! \brief Handles errors\r
+//  265  *\r
+//  266  * Stops PWM output and disables batteries. The function then goes into a loop\r
+//  267  * that starts with a call to Doze(), then attempts to handle each error. The\r
+//  268  * loop will reiterate until all flags are cleared.\n\r
+//  269  * The charger will reinitialize after this.\r
+//  270  *\r
+//  271  * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
+//  272  * If unsuccessful, the error flag will now have been set again.\n\r
+//  273  *\r
+//  274  * If there are no valid batteries, the loop will simply reiterate until a\r
+//  275  * valid battery is found. The error flag will then be cleared.\n\r
+//  276  *\r
+//  277  * In the case of PWM controller or battery temperature errors, the error\r
+//  278  * flag is simply cleared. This is because the problem may have gone away during\r
+//  279  * Doze(), or after reinitializing.\n\r
+//  280  *\r
+//  281  * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
+//  282  * and change batteries before clearing the error flag.\r
+//  283  *\r
+//  284  * \param inp Not used.\r
+//  285  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  286 unsigned char Error(unsigned char inp)\r
+Error:\r
+//  287        {\r
+//  288        unsigned char i;\r
+//  289        \r
+//  290        PWM_Stop();           // Stop charging.\r
+        RCALL   PWM_Stop\r
+//  291        DisableBatteries();   // Disable all loads.\r
+        RCALL   DisableBatteries\r
+//  292        \r
+//  293        do {\r
+//  294                Doze();           // Take a nap.\r
+        RCALL   ADC_Wait\r
+??Error_0:\r
+        RJMP    ??Error_0\r
+        REQUIRE _A_MCUCR\r
+        REQUIRE _A_MCUSR\r
+        REQUIRE _A_WDTCR\r
+        REQUIRE _A_ADCSRA\r
+//  295 \r
+//  296                // For each bit in ErrorFlags, starting with LSB, handle\r
+//  297                // associated error, if the flag is set.\r
+//  298                for (i = 0x01; i!=0; i<<=1) {\r
+//  299                        if(i & ErrorFlags) {\r
+//  300                                switch (i) {\r
+//  301                                \r
+//  302                                case  ERR_JUMPER_MISMATCH:\r
+//  303                                        // Clear flag & recheck.\r
+//  304                                        ErrorFlags &= ~i;\r
+//  305                                        JumperCheck();\r
+//  306                                break;\r
+//  307 \r
+//  308 \r
+//  309                                case  ERR_NO_BATTERIES_ENABLED:\r
+//  310                                        // Clear if any battery gets enabled.\r
+//  311                                        if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {\r
+//  312                                                        ErrorFlags &= ~i;\r
+//  313                                        }\r
+//  314                                break;\r
+//  315 \r
+//  316 \r
+//  317                                case  ERR_PWM_CONTROL:\r
+//  318                                        // Clear flag.\r
+//  319                                        ErrorFlags &= ~i;\r
+//  320                                break;\r
+//  321 \r
+//  322 \r
+//  323                                case  ERR_BATTERY_TEMPERATURE:\r
+//  324                                        // Clear flag.\r
+//  325                                        ErrorFlags &= ~i;\r
+//  326                                break;\r
+//  327 \r
+//  328 \r
+//  329                                case  ERR_BATTERY_EXHAUSTED:\r
+//  330                                        // Try the other battery.\r
+//  331                                        BattData.Exhausted = FALSE;\r
+//  332                                        BattActive = (BattActive + 1) % 2;\r
+//  333                                        ErrorFlags &= ~i;\r
+//  334                                break;\r
+//  335 \r
+//  336                                        \r
+//  337                                default:\r
+//  338                                break;\r
+//  339                                }\r
+//  340                        }\r
+//  341                }\r
+//  342        } while (ErrorFlags);\r
+//  343 \r
+//  344        return(ST_INIT);\r
+//  345 }\r
+//  346 \r
+//  347 \r
+//  348 /*! \brief Sets the specified error-flag and saves the current state\r
+//  349  *\r
+//  350  * Updates \ref ErrorFlags and \ref ErrorState.\r
+//  351  *\r
+//  352  * \note Error flags are specified in statefunc.h.\r
+//  353  *\r
+//  354  * \param Flag Specifies what error to flag.\r
+//  355  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  356 void SetErrorFlag(unsigned char Flag)\r
+SetErrorFlag:\r
+//  357 {\r
+//  358        ErrorFlags |= Flag;\r
+        LDI     R30, LOW(ErrorFlags)\r
+        LDI     R31, (ErrorFlags) >> 8\r
+        LD      R17, Z\r
+        OR      R17, R16\r
+        ST      Z, R17\r
+//  359        ErrorState = CurrentState;\r
+        LDS     R16, CurrentState\r
+        STD     Z+1, R16\r
+//  360 }\r
+        RET\r
+//  361 \r
+//  362 \r
+//  363 /*! \brief Checks on-board jumpers.\r
+//  364  *\r
+//  365  * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
+//  366  * increasing the duty cycle until conditioned output voltage equals conditioned\r
+//  367  * input voltage. At low PWM duty and no load buck output should be zero and,\r
+//  368  * when increasing PWM duty, should quickly jump to steady state output roughly\r
+//  369  * equal to input voltage. Will disable and leave disabled all batteries.\r
+//  370  *\r
+//  371  * \retval FALSE If jumper or load mismatch.\r
+//  372  * \retval TRUE If everything OK.\r
+//  373  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  374 unsigned char JumperCheck(void)\r
+JumperCheck:\r
+//  375 {\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+//  376         DisableBatteries();       // Disconnect, or loads may be destroyed!\r
+        RCALL   DisableBatteries\r
+//  377         \r
+//  378         PWM_Start();              // Start PWM (controls the buck charger).\r
+        RCALL   PWM_Start\r
+//  379        \r
+//  380         // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
+//  381         Time_Set(TIMER_GEN,0,1,0);\r
+        LDI     R20, 0\r
+        LDI     R17, 1\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        LDI     R16, 2\r
+        RCALL   Time_Set\r
+        LDI     R26, LOW(ADCS)\r
+        LDI     R27, (ADCS) >> 8\r
+        RJMP    ??JumperCheck_0\r
+//  382        \r
+//  383        do {\r
+//  384                // If the PWM output voltage saturates the ADC, stop PWM output and\r
+//  385                // report a failure.\r
+//  386                if (ADCS.rawVBAT == 1023) {\r
+//  387                        PWM_Stop();\r
+//  388                        return(FALSE);\r
+//  389                }\r
+//  390 \r
+//  391                // If the absolute difference between measured (VIN - VBAT) and the\r
+//  392                // typical value are below our set maximum, everything is OK.\r
+//  393                if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+//  394                                     VIN_VBAT_DIFF_MAX ) {\r
+//  395                                 \r
+//  396                        PWM_Stop();\r
+//  397                        return(TRUE);\r
+//  398                }\r
+//  399 \r
+//  400                // Charge current is too high -> check load and jumper J405 and J406.\r
+//  401                if (abs(ADCS.IBAT) > 100) {\r
+??JumperCheck_1:\r
+        ADIW    R27:R26, 12\r
+        LD      R16, X+\r
+        LD      R17, X\r
+        SBIW    R27:R26, 13\r
+        RCALL   abs\r
+        CPI     R16, 101\r
+        SBCI    R17, 0\r
+        BRGE    ??JumperCheck_2\r
+//  402                        PWM_Stop();\r
+//  403                        return(FALSE);\r
+//  404                }\r
+//  405 \r
+//  406                // If the PWM output can't be increased high enough -> check jumpers\r
+//  407                // J400-J404, J407 and J408.\r
+//  408                if (!PWM_IncrementDutyCycle()) {\r
+        RCALL   PWM_IncrementDutyCycle\r
+        TST     R16\r
+        BREQ    ??JumperCheck_2\r
+//  409                        PWM_Stop();\r
+//  410                        return(FALSE);\r
+//  411                }\r
+//  412                \r
+//  413       // Wait for ADC conversions to complete\r
+//  414                ADC_Wait();\r
+        RCALL   ADC_Wait\r
+//  415        } while (Time_Left(TIMER_GEN));\r
+        LDI     R16, 2\r
+        RCALL   Time_Left\r
+        TST     R16\r
+        BREQ    ??JumperCheck_2\r
+??JumperCheck_0:\r
+        ADIW    R27:R26, 6\r
+        LD      R16, X+\r
+        LD      R17, X\r
+        SBIW    R27:R26, 7\r
+        CPI     R16, 255\r
+        SBCI    R17, 3\r
+        BRNE    ??JumperCheck_3\r
+??JumperCheck_2:\r
+        RCALL   PWM_Stop\r
+        LDI     R16, 0\r
+        RJMP    ??JumperCheck_4\r
+??JumperCheck_3:\r
+        ADIW    R27:R26, 8\r
+        LD      R16, X+\r
+        LD      R17, X+\r
+        SUBI    R16, 88\r
+        SBCI    R17, 2\r
+        LD      R18, X+\r
+        LD      R19, X\r
+        SBIW    R27:R26, 11\r
+        SUB     R16, R18\r
+        SBC     R17, R19\r
+        RCALL   abs\r
+        CPI     R16, 244\r
+        SBCI    R17, 1\r
+        BRGE    ??JumperCheck_1\r
+        RCALL   PWM_Stop\r
+        LDI     R16, 1\r
+??JumperCheck_4:\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        RET\r
+//  416        \r
+//  417 \r
+//  418        // If we end up here, the measurements took too long.\r
+//  419        PWM_Stop();\r
+//  420        return(FALSE);\r
+//  421 }\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   6 bytes in segment ABSOLUTE\r
+// 358 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment NEAR_Z\r
+// \r
+// 358 bytes of CODE memory (+ 6 bytes shared)\r
+//   2 bytes of DATA memory (+ 6 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/time.lst b/BaseTinyFirmware/IAR/Release/List/time.lst
new file mode 100644 (file)
index 0000000..19a1403
--- /dev/null
@@ -0,0 +1,456 @@
+###############################################################################\r
+#                                                                             #\r
+# IAR Atmel AVR C/C++ Compiler V4.30F/W32               13/Mar/2008  04:52:03 #\r
+# Copyright 1996-2007 IAR Systems. All rights reserved.                       #\r
+#                                                                             #\r
+#    Source file           =  C:\home\kevin\pub\src\bc100\IAR\time.c          #\r
+#    Command line          =  C:\home\kevin\pub\src\bc100\IAR\time.c          #\r
+#                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 #\r
+#                             0\IAR\Release\Obj\ -D NDEBUG -lCN               #\r
+#                             C:\home\kevin\pub\src\bc100\IAR\Release\List\   #\r
+#                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis #\r
+#                             t\ --initializers_in_flash -s9 --no_cross_call  #\r
+#                             --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I        #\r
+#                             "C:\Program Files\IAR Systems\Embedded          #\r
+#                             Workbench 4.0\avr\INC\" -I "C:\Program          #\r
+#                             Files\IAR Systems\Embedded Workbench            #\r
+#                             4.0\avr\INC\CLIB\" --eeprom_size 512            #\r
+#                             --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,  #\r
+#                             34-35,38-39,42-43,46,50,52-54,56-59,61-62,      #\r
+#                             64-65,68-80,83-84,87-91,94-95,98-100,103-110,   #\r
+#                             112-126                                         #\r
+#    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,     #\r
+#                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,      #\r
+#                             68-80,83-84,87-91,94-95,98-100,103-110,112-126  #\r
+#      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,   #\r
+#                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,      #\r
+#                             83-84,87-89,91,94-95,98,100,104-105,108-109,    #\r
+#                             112-115,118-126                                 #\r
+#      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,      #\r
+#                             116-117                                         #\r
+#    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\ti #\r
+#                             me.lst                                          #\r
+#    Object file           =  C:\home\kevin\pub\src\bc100\IAR\Release\Obj\tim #\r
+#                             e.r90                                           #\r
+#                                                                             #\r
+#                                                                             #\r
+###############################################################################\r
+\r
+C:\home\kevin\pub\src\bc100\IAR\time.c\r
+      1          /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+      2          /*! \file *********************************************************************\r
+      3           *\r
+      4           * \brief\r
+      5           *      Functions for timing\r
+      6           *\r
+      7           *      Contains functions to initialize, set, poll and stop timers.\r
+      8           *\r
+      9           * \par Application note:\r
+     10           *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+     11           *      AVR463: Charging NiMH Batteries with BC100\r
+     12           *\r
+     13           * \par Documentation\r
+     14           *      For comprehensive code documentation, supported compilers, compiler \r
+     15           *      settings and supported devices see readme.html\r
+     16           *\r
+     17           * \author\r
+     18           *      Atmel Corporation: http://www.atmel.com \n\r
+     19           *      Support email: avr@atmel.com\r
+     20           *\r
+     21           * \r
+     22           * $Name$\r
+     23           * $Revision: 2299 $\r
+     24           * $RCSfile$\r
+     25           * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $\r
+     26           * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+     27           ******************************************************************************/\r
+     28          \r
+     29          #include <ioavr.h>\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x59\r
+   \   <unnamed> volatile __io _A_TIMSK\r
+   \                     _A_TIMSK:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x53\r
+   \   <unnamed> volatile __io _A_TCCR0B\r
+   \                     _A_TCCR0B:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x35\r
+   \   <unnamed> volatile __io _A_TCCR0A\r
+   \                     _A_TCCR0A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x33\r
+   \   <unnamed> volatile __io _A_OCR0A\r
+   \                     _A_OCR0A:\r
+   \   00000000                      DS 1\r
+\r
+   \                                 In  segment ABSOLUTE, at 0x32\r
+   \   <unnamed> volatile __io _A_OCR0B\r
+   \                     _A_OCR0B:\r
+   \   00000000                      DS 1\r
+     30          #include <inavr.h>\r
+     31          \r
+     32          #include "enums.h"\r
+     33          \r
+     34          #include "main.h"\r
+     35          #include "time.h"\r
+     36          \r
+     37          \r
+     38          //******************************************************************************\r
+     39          // Variables\r
+     40          //******************************************************************************\r
+\r
+   \                                 In  segment NEAR_Z, align 1, keep-with-next\r
+   \   00000000                      REQUIRE `?<Segment init: NEAR_Z>`\r
+     41          unsigned long timeval[TIMERS];  //!< Contains the values for each timer.\r
+   \                     timeval:\r
+   \   00000000                      DS 16\r
+     42          \r
+     43          // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
+     44          //#pragma vector = TIM0_OVF_vect\r
+     45          \r
+     46          \r
+     47          //******************************************************************************\r
+     48          // Functions\r
+     49          //******************************************************************************\r
+     50          /*! \brief Interrupt service routine for timer 0 overflow\r
+     51           *\r
+     52           * Timer 0 runs at 125 kHz and compare match will occur every millisecond\r
+     53           * (125 / 125 kHz = 1.0 ms), which will result in a call to this function.\r
+     54           * When called, this function will decrement the time left for each timer,\r
+     55           * unless they are already at zero.\r
+     56           */\r
+     57          #pragma vector = TIM0_COMPA_vect\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     58          __interrupt void TICK_ISR(void)\r
+   \                     TICK_ISR:\r
+     59          {\r
+   \   00000000   93FA               ST      -Y, R31\r
+   \   00000002   93EA               ST      -Y, R30\r
+   \   00000004   937A               ST      -Y, R23\r
+   \   00000006   936A               ST      -Y, R22\r
+   \   00000008   935A               ST      -Y, R21\r
+   \   0000000A   934A               ST      -Y, R20\r
+   \   0000000C   931A               ST      -Y, R17\r
+   \   0000000E   930A               ST      -Y, R16\r
+   \   00000010   B71F               IN      R17, 0x3F\r
+     60                unsigned char i;\r
+     61          \r
+     62                // 1 ms has passed, decrement all non-zero timers.\r
+     63                for (i = 0; i < TIMERS; i++) {\r
+   \   00000012   ....               LDI     R30, LOW(timeval)\r
+   \   00000014   ....               LDI     R31, (timeval) >> 8\r
+   \   00000016   E004               LDI     R16, 4\r
+     64                        if(timeval[i] > 0) {\r
+   \                     ??TICK_ISR_0:\r
+   \   00000018   8140               LD      R20, Z\r
+   \   0000001A   8151               LDD     R21, Z+1\r
+   \   0000001C   8162               LDD     R22, Z+2\r
+   \   0000001E   8173               LDD     R23, Z+3\r
+   \   00000020   2B45               OR      R20, R21\r
+   \   00000022   2B46               OR      R20, R22\r
+   \   00000024   2B47               OR      R20, R23\r
+   \   00000026   F049               BREQ    ??TICK_ISR_1\r
+     65                                timeval[i]--;\r
+   \   00000028   8140               LD      R20, Z\r
+   \   0000002A   5041               SUBI    R20, 1\r
+   \   0000002C   4050               SBCI    R21, 0\r
+   \   0000002E   4060               SBCI    R22, 0\r
+   \   00000030   4070               SBCI    R23, 0\r
+   \   00000032   8340               ST      Z, R20\r
+   \   00000034   8351               STD     Z+1, R21\r
+   \   00000036   8362               STD     Z+2, R22\r
+   \   00000038   8373               STD     Z+3, R23\r
+     66                        }\r
+     67                }\r
+   \                     ??TICK_ISR_1:\r
+   \   0000003A   9634               ADIW    R31:R30, 4\r
+   \   0000003C   950A               DEC     R16\r
+   \   0000003E   2300               TST     R16\r
+   \   00000040   F759               BRNE    ??TICK_ISR_0\r
+     68          }\r
+   \   00000042   BF1F               OUT     0x3F, R17\r
+   \   00000044   9109               LD      R16, Y+\r
+   \   00000046   9119               LD      R17, Y+\r
+   \   00000048   9149               LD      R20, Y+\r
+   \   0000004A   9159               LD      R21, Y+\r
+   \   0000004C   9169               LD      R22, Y+\r
+   \   0000004E   9179               LD      R23, Y+\r
+   \   00000050   91E9               LD      R30, Y+\r
+   \   00000052   91F9               LD      R31, Y+\r
+   \   00000054   9518               RETI\r
+     69          \r
+     70          \r
+     71          /*! \brief Checks if a specified timer has expired\r
+     72           *\r
+     73           * \param timer Specifies timer\r
+     74           *\r
+     75           * \retval TRUE Timer still going.\r
+     76           * \retval FALSE Timer has expired.\r
+     77           */ \r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     78          unsigned char Time_Left(unsigned char timer)\r
+   \                     Time_Left:\r
+     79          {\r
+     80                if(timeval[timer] > 0) {\r
+   \   00000000   E010               LDI     R17, 0\r
+   \   00000002   0F00               LSL     R16\r
+   \   00000004   1F11               ROL     R17\r
+   \   00000006   0F00               LSL     R16\r
+   \   00000008   1F11               ROL     R17\r
+   \   0000000A   01F8               MOVW    R31:R30, R17:R16\r
+   \   0000000C   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   0000000E   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000010   8100               LD      R16, Z\r
+   \   00000012   8111               LDD     R17, Z+1\r
+   \   00000014   8122               LDD     R18, Z+2\r
+   \   00000016   8133               LDD     R19, Z+3\r
+   \   00000018   2B01               OR      R16, R17\r
+   \   0000001A   2B02               OR      R16, R18\r
+   \   0000001C   2B03               OR      R16, R19\r
+   \   0000001E   F011               BREQ    ??Time_Left_0\r
+     81                        return(TRUE);\r
+   \   00000020   E001               LDI     R16, 1\r
+   \   00000022   9508               RET\r
+     82                } else {\r
+     83                        return(FALSE);\r
+   \                     ??Time_Left_0:\r
+   \   00000024   E000               LDI     R16, 0\r
+   \   00000026   9508               RET\r
+     84                }\r
+     85          }\r
+     86          \r
+     87          \r
+     88          /*! \brief Sets the specified timer\r
+     89           *\r
+     90           * \param timer Specifies timer\r
+     91           * \param min Minutes for timer to count down\r
+     92           * \param sec Seconds for timer to count down\r
+     93           * \param ms Milliseconds for timer to count down\r
+     94           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+     95          void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+   \                     Time_Set:\r
+     96                                          unsigned char ms)\r
+     97          {\r
+   \   00000000   928A               ST      -Y, R8\r
+   \   00000002   926A               ST      -Y, R6\r
+   \   00000004   925A               ST      -Y, R5\r
+   \   00000006   924A               ST      -Y, R4\r
+   \   00000008   93BA               ST      -Y, R27\r
+   \   0000000A   93AA               ST      -Y, R26\r
+   \   0000000C   939A               ST      -Y, R25\r
+   \   0000000E   938A               ST      -Y, R24\r
+   \   00000010                      REQUIRE ?Register_R4_is_cg_reg\r
+   \   00000010                      REQUIRE ?Register_R5_is_cg_reg\r
+   \   00000010                      REQUIRE ?Register_R6_is_cg_reg\r
+   \   00000010                      REQUIRE ?Register_R8_is_cg_reg\r
+   \   00000010   2E40               MOV     R4, R16\r
+   \   00000012   2E81               MOV     R8, R17\r
+   \   00000014   2E64               MOV     R6, R20\r
+     98          //    timeval[i] = 4 * (1000*(sec + 60*min) + ms);   // about 4000 ticks per second\r
+     99          //    timeval[i] = 240000 * (unsigned long)min;\r
+    100          //    timeval[i] += 4000 * (unsigned long)sec;\r
+    101          //    timeval[i] += 4 * (unsigned long)ms;\r
+    102          \r
+    103                timeval[timer] = 60000 * (unsigned long)min;\r
+    104                timeval[timer] += 1000 * (unsigned long)sec;\r
+    105                timeval[timer] += 1 * (unsigned long)ms;\r
+   \   00000016   01A9               MOVW    R21:R20, R19:R18\r
+   \   00000018   E060               LDI     R22, 0\r
+   \   0000001A   E070               LDI     R23, 0\r
+   \   0000001C   E600               LDI     R16, 96\r
+   \   0000001E   EE1A               LDI     R17, 234\r
+   \   00000020   E020               LDI     R18, 0\r
+   \   00000022   E030               LDI     R19, 0\r
+   \   00000024   ....               RCALL   ?L_MUL_L03\r
+   \   00000026   01C8               MOVW    R25:R24, R17:R16\r
+   \   00000028   01D9               MOVW    R27:R26, R19:R18\r
+   \   0000002A   2D48               MOV     R20, R8\r
+   \   0000002C   E050               LDI     R21, 0\r
+   \   0000002E   E060               LDI     R22, 0\r
+   \   00000030   E070               LDI     R23, 0\r
+   \   00000032   EE08               LDI     R16, 232\r
+   \   00000034   E013               LDI     R17, 3\r
+   \   00000036   E020               LDI     R18, 0\r
+   \   00000038   E030               LDI     R19, 0\r
+   \   0000003A   ....               RCALL   ?L_MUL_L03\r
+   \   0000003C   0F08               ADD     R16, R24\r
+   \   0000003E   1F19               ADC     R17, R25\r
+   \   00000040   1F2A               ADC     R18, R26\r
+   \   00000042   1F3B               ADC     R19, R27\r
+   \   00000044   2D46               MOV     R20, R6\r
+   \   00000046   E050               LDI     R21, 0\r
+   \   00000048   E060               LDI     R22, 0\r
+   \   0000004A   E070               LDI     R23, 0\r
+   \   0000004C   0F40               ADD     R20, R16\r
+   \   0000004E   1F51               ADC     R21, R17\r
+   \   00000050   1F62               ADC     R22, R18\r
+   \   00000052   1F73               ADC     R23, R19\r
+   \   00000054   2455               CLR     R5\r
+   \   00000056   0C44               LSL     R4\r
+   \   00000058   1C55               ROL     R5\r
+   \   0000005A   0C44               LSL     R4\r
+   \   0000005C   1C55               ROL     R5\r
+   \   0000005E   01F2               MOVW    R31:R30, R5:R4\r
+   \   00000060   ....               SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+   \   00000062   ....               SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+   \   00000064   8340               ST      Z, R20\r
+   \   00000066   8351               STD     Z+1, R21\r
+   \   00000068   8362               STD     Z+2, R22\r
+   \   0000006A   8373               STD     Z+3, R23\r
+    106          }\r
+   \   0000006C   9189               LD      R24, Y+\r
+   \   0000006E   9199               LD      R25, Y+\r
+   \   00000070   91A9               LD      R26, Y+\r
+   \   00000072   91B9               LD      R27, Y+\r
+   \   00000074   9049               LD      R4, Y+\r
+   \   00000076   9059               LD      R5, Y+\r
+   \   00000078   9069               LD      R6, Y+\r
+   \   0000007A   9089               LD      R8, Y+\r
+   \   0000007C   9508               RET\r
+    107          \r
+    108          \r
+    109          /*! \brief Stops timers\r
+    110           *\r
+    111           * Sets timer0's clock source to none.\r
+    112           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    113          void Time_Stop(void)\r
+   \                     Time_Stop:\r
+    114          {\r
+    115                TCCR0B = 0;\r
+   \   00000000   E000               LDI     R16, 0\r
+   \   00000002   BF03               OUT     0x33, R16\r
+    116          }\r
+   \   00000004   9508               RET\r
+   \   00000006                      REQUIRE _A_TCCR0B\r
+    117          \r
+    118          \r
+    119          /*! \brief Starts timers\r
+    120           *\r
+    121           * Sets timer0's clock source to system clock divided by 64.\r
+    122           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    123          void Time_Start(void)\r
+   \                     Time_Start:\r
+    124          {\r
+    125                TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+   \   00000000   E003               LDI     R16, 3\r
+   \   00000002   BF03               OUT     0x33, R16\r
+    126          }\r
+   \   00000004   9508               RET\r
+   \   00000006                      REQUIRE _A_TCCR0B\r
+    127          \r
+    128          \r
+    129          /*! \brief Initializes timers\r
+    130           *\r
+    131           * Resets all the timer values to 0, then sets up timer 0 for a compare match\r
+    132           * every millisecond.\r
+    133           */\r
+\r
+   \                                 In  segment CODE, align 2, keep-with-next\r
+    134          void Time_Init(void)\r
+   \                     Time_Init:\r
+    135          {\r
+    136                unsigned char i;\r
+    137                \r
+    138                for (i = 0; i<<TIMERS; i++)     {\r
+    139                        timeval[i] = 0;\r
+    140                }\r
+    141          \r
+    142                //    OCR0A = 0;  // Doesn't matter, will run in normal mode.\r
+    143                \r
+    144                OCR0A = 125;  // Will give a compare match every ms.\r
+   \   00000000   E70D               LDI     R16, 125\r
+   \   00000002   BB03               OUT     0x13, R16\r
+    145                \r
+    146                OCR0B = 0;  // Doesn't matter, will run in normal mode.\r
+   \   00000004   E000               LDI     R16, 0\r
+   \   00000006   BB02               OUT     0x12, R16\r
+    147          \r
+    148                        //    TCCR0A = 0;  // Normal 8-bit mode, no input capture.\r
+    149          \r
+    150                TCCR0A = (1<<WGM00);  // 8-bit CTC mode.\r
+   \   00000008   E001               LDI     R16, 1\r
+   \   0000000A   BB05               OUT     0x15, R16\r
+    151                \r
+    152                //    TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00);  // CLKT0 = CLK/8 = 1 MHz.\r
+    153                \r
+    154                TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+   \   0000000C   E003               LDI     R16, 3\r
+   \   0000000E   BF03               OUT     0x33, R16\r
+    155          \r
+    156                //    TIMSK |= (1<<TOIE0);      // Overflow interrupt enabled.\r
+    157          \r
+    158                TIMSK |= (1<<OCIE0A);  // Timer 0, Compare match A interrupt enabled.\r
+   \   00000010   B709               IN      R16, 0x39\r
+   \   00000012   6100               ORI     R16, 0x10\r
+   \   00000014   BF09               OUT     0x39, R16\r
+    159          \r
+    160                // Enable interrupts, just in case they weren't already.\r
+    161                __enable_interrupt();       \r
+   \   00000016   9478               SEI\r
+    162          }\r
+   \   00000018   9508               RET\r
+   \   0000001A                      REQUIRE _A_TIMSK\r
+   \   0000001A                      REQUIRE _A_TCCR0B\r
+   \   0000001A                      REQUIRE _A_TCCR0A\r
+   \   0000001A                      REQUIRE _A_OCR0A\r
+   \   0000001A                      REQUIRE _A_OCR0B\r
+\r
+   \                                 In  segment INTVEC, offset 0x1c, root\r
+   \                     `??TICK_ISR??INTVEC 28`:\r
+   \   0000001C   ....               RJMP    TICK_ISR\r
+\r
+   Maximum stack usage in bytes:\r
+\r
+     Function   CSTACK RSTACK\r
+     --------   ------ ------\r
+     TICK_ISR       9      2\r
+     Time_Init      0      2\r
+     Time_Left      0      2\r
+     Time_Set       8      4\r
+     Time_Start     0      2\r
+     Time_Stop      0      2\r
+\r
+\r
+   Segment part sizes:\r
+\r
+     Function/Label        Bytes\r
+     --------------        -----\r
+     _A_TIMSK                 1\r
+     _A_TCCR0B                1\r
+     _A_TCCR0A                1\r
+     _A_OCR0A                 1\r
+     _A_OCR0B                 1\r
+     timeval                 16\r
+     TICK_ISR                86\r
+     Time_Left               40\r
+     Time_Set               126\r
+     Time_Stop                6\r
+     Time_Start               6\r
+     Time_Init               26\r
+     ??TICK_ISR??INTVEC 28    2\r
+      Others                  6\r
+\r
\r
+   5 bytes in segment ABSOLUTE\r
+ 290 bytes in segment CODE\r
+   6 bytes in segment INITTAB\r
+   2 bytes in segment INTVEC\r
+  16 bytes in segment NEAR_Z\r
\r
+ 290 bytes of CODE memory (+ 8 bytes shared)\r
+  16 bytes of DATA memory (+ 5 bytes shared)\r
+\r
+Errors: none\r
+Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/List/time.s90 b/BaseTinyFirmware/IAR/Release/List/time.s90
new file mode 100644 (file)
index 0000000..2e80721
--- /dev/null
@@ -0,0 +1,478 @@
+///////////////////////////////////////////////////////////////////////////////\r
+//                                                                            /\r
+// IAR Atmel AVR C/C++ Compiler V4.30F/W32              13/Mar/2008  04:52:03 /\r
+// Copyright 1996-2007 IAR Systems. All rights reserved.                      /\r
+//                                                                            /\r
+//    Source file           =  C:\home\kevin\pub\src\bc100\IAR\time.c         /\r
+//    Command line          =  C:\home\kevin\pub\src\bc100\IAR\time.c         /\r
+//                             --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 /\r
+//                             00\IAR\Release\Obj\ -D NDEBUG -lCN             /\r
+//                             C:\home\kevin\pub\src\bc100\IAR\Release\List\  /\r
+//                             -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li /\r
+//                             st\ --initializers_in_flash -s9                /\r
+//                             --no_cross_call --no_tbaa                      /\r
+//                             -DENABLE_BIT_DEFINITIONS -e -I "C:\Program     /\r
+//                             Files\IAR Systems\Embedded Workbench           /\r
+//                             4.0\avr\INC\" -I "C:\Program Files\IAR         /\r
+//                             Systems\Embedded Workbench 4.0\avr\INC\CLIB\"  /\r
+//                             --eeprom_size 512 --misrac=5-9,11-12,14,16-17, /\r
+//                             19-21,24-26,29-32,34-35,38-39,42-43,46,50,     /\r
+//                             52-54,56-59,61-62,64-65,68-80,83-84,87-91,     /\r
+//                             94-95,98-100,103-110,112-126                   /\r
+//    Enabled MISRA C rules =  5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,    /\r
+//                             38-39,42-43,46,50,52-54,56-59,61-62,64-65,     /\r
+//                             68-80,83-84,87-91,94-95,98-100,103-110,112-126 /\r
+//      Checked             =  5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39,  /\r
+//                             42,46,50,52-54,56-59,61-62,64,68-69,71-80,     /\r
+//                             83-84,87-89,91,94-95,98,100,104-105,108-109,   /\r
+//                             112-115,118-126                                /\r
+//      Not checked         =  6,16,25-26,43,65,70,90,99,103,106-107,110,     /\r
+//                             116-117                                        /\r
+//    List file             =  C:\home\kevin\pub\src\bc100\IAR\Release\List\t /\r
+//                             ime.s90                                        /\r
+//                                                                            /\r
+//                                                                            /\r
+///////////////////////////////////////////////////////////////////////////////\r
+\r
+        NAME time\r
+\r
+        RSEG CSTACK:DATA:NOROOT(0)\r
+        RSEG RSTACK:DATA:NOROOT(0)\r
+\r
+        EXTERN ?L_MUL_L03\r
+        EXTERN ?Register_R4_is_cg_reg\r
+        EXTERN ?Register_R5_is_cg_reg\r
+        EXTERN ?Register_R6_is_cg_reg\r
+        EXTERN ?Register_R8_is_cg_reg\r
+        EXTERN ?need_segment_init\r
+\r
+        PUBWEAK `?<Segment init: NEAR_Z>`\r
+        PUBWEAK `??TICK_ISR??INTVEC 28`\r
+        PUBLIC TICK_ISR\r
+        PUBLIC Time_Init\r
+        PUBLIC Time_Left\r
+        PUBLIC Time_Set\r
+        PUBLIC Time_Start\r
+        PUBLIC Time_Stop\r
+        PUBWEAK _A_OCR0A\r
+        PUBWEAK _A_OCR0B\r
+        PUBWEAK _A_TCCR0A\r
+        PUBWEAK _A_TCCR0B\r
+        PUBWEAK _A_TIMSK\r
+        PUBWEAK __?EEARH\r
+        PUBWEAK __?EEARL\r
+        PUBWEAK __?EECR\r
+        PUBWEAK __?EEDR\r
+        PUBLIC timeval\r
+\r
+TICK_ISR            SYMBOL "TICK_ISR"\r
+`??TICK_ISR??INTVEC 28` SYMBOL "??INTVEC 28", TICK_ISR\r
+\r
+// C:\home\kevin\pub\src\bc100\IAR\time.c\r
+//    1 /* This file has been prepared for Doxygen automatic documentation generation.*/\r
+//    2 /*! \file *********************************************************************\r
+//    3  *\r
+//    4  * \brief\r
+//    5  *      Functions for timing\r
+//    6  *\r
+//    7  *      Contains functions to initialize, set, poll and stop timers.\r
+//    8  *\r
+//    9  * \par Application note:\r
+//   10  *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+//   11  *      AVR463: Charging NiMH Batteries with BC100\r
+//   12  *\r
+//   13  * \par Documentation\r
+//   14  *      For comprehensive code documentation, supported compilers, compiler \r
+//   15  *      settings and supported devices see readme.html\r
+//   16  *\r
+//   17  * \author\r
+//   18  *      Atmel Corporation: http://www.atmel.com \n\r
+//   19  *      Support email: avr@atmel.com\r
+//   20  *\r
+//   21  * \r
+//   22  * $Name$\r
+//   23  * $Revision: 2299 $\r
+//   24  * $RCSfile$\r
+//   25  * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $\r
+//   26  * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+//   27  ******************************************************************************/\r
+//   28 \r
+//   29 #include <ioavr.h>\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,059H\r
+// <unnamed> volatile __io _A_TIMSK\r
+_A_TIMSK:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,053H\r
+// <unnamed> volatile __io _A_TCCR0B\r
+_A_TCCR0B:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,035H\r
+// <unnamed> volatile __io _A_TCCR0A\r
+_A_TCCR0A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,033H\r
+// <unnamed> volatile __io _A_OCR0A\r
+_A_OCR0A:\r
+        DS 1\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,032H\r
+// <unnamed> volatile __io _A_OCR0B\r
+_A_OCR0B:\r
+        DS 1\r
+//   30 #include <inavr.h>\r
+//   31 \r
+//   32 #include "enums.h"\r
+//   33 \r
+//   34 #include "main.h"\r
+//   35 #include "time.h"\r
+//   36 \r
+//   37 \r
+//   38 //******************************************************************************\r
+//   39 // Variables\r
+//   40 //******************************************************************************\r
+\r
+        RSEG NEAR_Z:DATA:NOROOT(0)\r
+        REQUIRE `?<Segment init: NEAR_Z>`\r
+//   41 unsigned long timeval[TIMERS];  //!< Contains the values for each timer.\r
+timeval:\r
+        DS 16\r
+//   42 \r
+//   43 // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
+//   44 //#pragma vector = TIM0_OVF_vect\r
+//   45 \r
+//   46 \r
+//   47 //******************************************************************************\r
+//   48 // Functions\r
+//   49 //******************************************************************************\r
+//   50 /*! \brief Interrupt service routine for timer 0 overflow\r
+//   51  *\r
+//   52  * Timer 0 runs at 125 kHz and compare match will occur every millisecond\r
+//   53  * (125 / 125 kHz = 1.0 ms), which will result in a call to this function.\r
+//   54  * When called, this function will decrement the time left for each timer,\r
+//   55  * unless they are already at zero.\r
+//   56  */\r
+//   57 #pragma vector = TIM0_COMPA_vect\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   58 __interrupt void TICK_ISR(void)\r
+TICK_ISR:\r
+//   59 {\r
+        ST      -Y, R31\r
+        ST      -Y, R30\r
+        ST      -Y, R23\r
+        ST      -Y, R22\r
+        ST      -Y, R21\r
+        ST      -Y, R20\r
+        ST      -Y, R17\r
+        ST      -Y, R16\r
+        IN      R17, 0x3F\r
+//   60        unsigned char i;\r
+//   61 \r
+//   62        // 1 ms has passed, decrement all non-zero timers.\r
+//   63        for (i = 0; i < TIMERS; i++) {\r
+        LDI     R30, LOW(timeval)\r
+        LDI     R31, (timeval) >> 8\r
+        LDI     R16, 4\r
+//   64                if(timeval[i] > 0) {\r
+??TICK_ISR_0:\r
+        LD      R20, Z\r
+        LDD     R21, Z+1\r
+        LDD     R22, Z+2\r
+        LDD     R23, Z+3\r
+        OR      R20, R21\r
+        OR      R20, R22\r
+        OR      R20, R23\r
+        BREQ    ??TICK_ISR_1\r
+//   65                        timeval[i]--;\r
+        LD      R20, Z\r
+        SUBI    R20, 1\r
+        SBCI    R21, 0\r
+        SBCI    R22, 0\r
+        SBCI    R23, 0\r
+        ST      Z, R20\r
+        STD     Z+1, R21\r
+        STD     Z+2, R22\r
+        STD     Z+3, R23\r
+//   66                }\r
+//   67        }\r
+??TICK_ISR_1:\r
+        ADIW    R31:R30, 4\r
+        DEC     R16\r
+        TST     R16\r
+        BRNE    ??TICK_ISR_0\r
+//   68 }\r
+        OUT     0x3F, R17\r
+        LD      R16, Y+\r
+        LD      R17, Y+\r
+        LD      R20, Y+\r
+        LD      R21, Y+\r
+        LD      R22, Y+\r
+        LD      R23, Y+\r
+        LD      R30, Y+\r
+        LD      R31, Y+\r
+        RETI\r
+//   69 \r
+//   70 \r
+//   71 /*! \brief Checks if a specified timer has expired\r
+//   72  *\r
+//   73  * \param timer Specifies timer\r
+//   74  *\r
+//   75  * \retval TRUE Timer still going.\r
+//   76  * \retval FALSE Timer has expired.\r
+//   77  */ \r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   78 unsigned char Time_Left(unsigned char timer)\r
+Time_Left:\r
+//   79 {\r
+//   80        if(timeval[timer] > 0) {\r
+        LDI     R17, 0\r
+        LSL     R16\r
+        ROL     R17\r
+        LSL     R16\r
+        ROL     R17\r
+        MOVW    R31:R30, R17:R16\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        LD      R16, Z\r
+        LDD     R17, Z+1\r
+        LDD     R18, Z+2\r
+        LDD     R19, Z+3\r
+        OR      R16, R17\r
+        OR      R16, R18\r
+        OR      R16, R19\r
+        BREQ    ??Time_Left_0\r
+//   81                return(TRUE);\r
+        LDI     R16, 1\r
+        RET\r
+//   82        } else {\r
+//   83                return(FALSE);\r
+??Time_Left_0:\r
+        LDI     R16, 0\r
+        RET\r
+//   84        }\r
+//   85 }\r
+//   86 \r
+//   87 \r
+//   88 /*! \brief Sets the specified timer\r
+//   89  *\r
+//   90  * \param timer Specifies timer\r
+//   91  * \param min Minutes for timer to count down\r
+//   92  * \param sec Seconds for timer to count down\r
+//   93  * \param ms Milliseconds for timer to count down\r
+//   94  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//   95 void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+Time_Set:\r
+//   96                                  unsigned char ms)\r
+//   97 {\r
+        ST      -Y, R8\r
+        ST      -Y, R6\r
+        ST      -Y, R5\r
+        ST      -Y, R4\r
+        ST      -Y, R27\r
+        ST      -Y, R26\r
+        ST      -Y, R25\r
+        ST      -Y, R24\r
+        REQUIRE ?Register_R4_is_cg_reg\r
+        REQUIRE ?Register_R5_is_cg_reg\r
+        REQUIRE ?Register_R6_is_cg_reg\r
+        REQUIRE ?Register_R8_is_cg_reg\r
+        MOV     R4, R16\r
+        MOV     R8, R17\r
+        MOV     R6, R20\r
+//   98 //     timeval[i] = 4 * (1000*(sec + 60*min) + ms);   // about 4000 ticks per second\r
+//   99 //     timeval[i] = 240000 * (unsigned long)min;\r
+//  100 //     timeval[i] += 4000 * (unsigned long)sec;\r
+//  101 //     timeval[i] += 4 * (unsigned long)ms;\r
+//  102 \r
+//  103        timeval[timer] = 60000 * (unsigned long)min;\r
+//  104        timeval[timer] += 1000 * (unsigned long)sec;\r
+//  105        timeval[timer] += 1 * (unsigned long)ms;\r
+        MOVW    R21:R20, R19:R18\r
+        LDI     R22, 0\r
+        LDI     R23, 0\r
+        LDI     R16, 96\r
+        LDI     R17, 234\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        RCALL   ?L_MUL_L03\r
+        MOVW    R25:R24, R17:R16\r
+        MOVW    R27:R26, R19:R18\r
+        MOV     R20, R8\r
+        LDI     R21, 0\r
+        LDI     R22, 0\r
+        LDI     R23, 0\r
+        LDI     R16, 232\r
+        LDI     R17, 3\r
+        LDI     R18, 0\r
+        LDI     R19, 0\r
+        RCALL   ?L_MUL_L03\r
+        ADD     R16, R24\r
+        ADC     R17, R25\r
+        ADC     R18, R26\r
+        ADC     R19, R27\r
+        MOV     R20, R6\r
+        LDI     R21, 0\r
+        LDI     R22, 0\r
+        LDI     R23, 0\r
+        ADD     R20, R16\r
+        ADC     R21, R17\r
+        ADC     R22, R18\r
+        ADC     R23, R19\r
+        CLR     R5\r
+        LSL     R4\r
+        ROL     R5\r
+        LSL     R4\r
+        ROL     R5\r
+        MOVW    R31:R30, R5:R4\r
+        SUBI    R30, LOW((-(timeval) & 0xFFFF))\r
+        SBCI    R31, (-(timeval) & 0xFFFF) >> 8\r
+        ST      Z, R20\r
+        STD     Z+1, R21\r
+        STD     Z+2, R22\r
+        STD     Z+3, R23\r
+//  106 }\r
+        LD      R24, Y+\r
+        LD      R25, Y+\r
+        LD      R26, Y+\r
+        LD      R27, Y+\r
+        LD      R4, Y+\r
+        LD      R5, Y+\r
+        LD      R6, Y+\r
+        LD      R8, Y+\r
+        RET\r
+//  107 \r
+//  108 \r
+//  109 /*! \brief Stops timers\r
+//  110  *\r
+//  111  * Sets timer0's clock source to none.\r
+//  112  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  113 void Time_Stop(void)\r
+Time_Stop:\r
+//  114 {\r
+//  115        TCCR0B = 0;\r
+        LDI     R16, 0\r
+        OUT     0x33, R16\r
+//  116 }\r
+        RET\r
+        REQUIRE _A_TCCR0B\r
+//  117 \r
+//  118 \r
+//  119 /*! \brief Starts timers\r
+//  120  *\r
+//  121  * Sets timer0's clock source to system clock divided by 64.\r
+//  122  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  123 void Time_Start(void)\r
+Time_Start:\r
+//  124 {\r
+//  125        TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+        LDI     R16, 3\r
+        OUT     0x33, R16\r
+//  126 }\r
+        RET\r
+        REQUIRE _A_TCCR0B\r
+//  127 \r
+//  128 \r
+//  129 /*! \brief Initializes timers\r
+//  130  *\r
+//  131  * Resets all the timer values to 0, then sets up timer 0 for a compare match\r
+//  132  * every millisecond.\r
+//  133  */\r
+\r
+        RSEG CODE:CODE:NOROOT(1)\r
+//  134 void Time_Init(void)\r
+Time_Init:\r
+//  135 {\r
+//  136        unsigned char i;\r
+//  137        \r
+//  138        for (i = 0; i<<TIMERS; i++)     {\r
+//  139                timeval[i] = 0;\r
+//  140        }\r
+//  141 \r
+//  142        //    OCR0A = 0;  // Doesn't matter, will run in normal mode.\r
+//  143        \r
+//  144        OCR0A = 125;  // Will give a compare match every ms.\r
+        LDI     R16, 125\r
+        OUT     0x13, R16\r
+//  145        \r
+//  146        OCR0B = 0;  // Doesn't matter, will run in normal mode.\r
+        LDI     R16, 0\r
+        OUT     0x12, R16\r
+//  147 \r
+//  148                //    TCCR0A = 0;  // Normal 8-bit mode, no input capture.\r
+//  149 \r
+//  150        TCCR0A = (1<<WGM00);  // 8-bit CTC mode.\r
+        LDI     R16, 1\r
+        OUT     0x15, R16\r
+//  151        \r
+//  152        //    TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00);  // CLKT0 = CLK/8 = 1 MHz.\r
+//  153        \r
+//  154        TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+        LDI     R16, 3\r
+        OUT     0x33, R16\r
+//  155 \r
+//  156        //    TIMSK |= (1<<TOIE0);      // Overflow interrupt enabled.\r
+//  157 \r
+//  158        TIMSK |= (1<<OCIE0A);  // Timer 0, Compare match A interrupt enabled.\r
+        IN      R16, 0x39\r
+        ORI     R16, 0x10\r
+        OUT     0x39, R16\r
+//  159 \r
+//  160        // Enable interrupts, just in case they weren't already.\r
+//  161        __enable_interrupt();       \r
+        SEI\r
+//  162 }\r
+        RET\r
+        REQUIRE _A_TIMSK\r
+        REQUIRE _A_TCCR0B\r
+        REQUIRE _A_TCCR0A\r
+        REQUIRE _A_OCR0A\r
+        REQUIRE _A_OCR0B\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01cH\r
+__?EECR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01dH\r
+__?EEDR:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01eH\r
+__?EEARL:\r
+\r
+        ASEGN ABSOLUTE:DATA:NOROOT,01fH\r
+__?EEARH:\r
+\r
+        COMMON INTVEC:CODE:ROOT(1)\r
+        ORG 28\r
+`??TICK_ISR??INTVEC 28`:\r
+        RJMP    TICK_ISR\r
+\r
+        RSEG INITTAB:CODE:NOROOT(0)\r
+`?<Segment init: NEAR_Z>`:\r
+        DW      SFE(NEAR_Z) - SFB(NEAR_Z)\r
+        DW      SFB(NEAR_Z)\r
+        DW      0\r
+        REQUIRE ?need_segment_init\r
+\r
+        END\r
+// \r
+//   5 bytes in segment ABSOLUTE\r
+// 290 bytes in segment CODE\r
+//   6 bytes in segment INITTAB\r
+//   2 bytes in segment INTVEC\r
+//  16 bytes in segment NEAR_Z\r
+// \r
+// 290 bytes of CODE memory (+ 8 bytes shared)\r
+//  16 bytes of DATA memory (+ 5 bytes shared)\r
+//\r
+//Errors: none\r
+//Warnings: none\r
diff --git a/BaseTinyFirmware/IAR/Release/Obj/ADC.r90 b/BaseTinyFirmware/IAR/Release/Obj/ADC.r90
new file mode 100644 (file)
index 0000000..279a806
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/ADC.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/BC100_tiny.pbd b/BaseTinyFirmware/IAR/Release/Obj/BC100_tiny.pbd
new file mode 100644 (file)
index 0000000..748e2e2
--- /dev/null
@@ -0,0 +1,13 @@
+This is an internal working file generated by the Source Browser.\r
+04:52 05s\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIMHcharge.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\battery.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\chargefunc.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\main.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\menu.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\statefunc.pbi\r
+C:\home\kevin\pub\src\bc100\IAR\Release\Obj\time.pbi\r
diff --git a/BaseTinyFirmware/IAR/Release/Obj/NIMHcharge.r90 b/BaseTinyFirmware/IAR/Release/Obj/NIMHcharge.r90
new file mode 100644 (file)
index 0000000..b5647b8
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/NIMHcharge.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/OWI.r90 b/BaseTinyFirmware/IAR/Release/Obj/OWI.r90
new file mode 100644 (file)
index 0000000..dc0b7cd
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/OWI.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/PWM.r90 b/BaseTinyFirmware/IAR/Release/Obj/PWM.r90
new file mode 100644 (file)
index 0000000..7aef78f
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/PWM.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/USI.r90 b/BaseTinyFirmware/IAR/Release/Obj/USI.r90
new file mode 100644 (file)
index 0000000..fa32287
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/USI.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/battery.r90 b/BaseTinyFirmware/IAR/Release/Obj/battery.r90
new file mode 100644 (file)
index 0000000..2ce0b15
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/battery.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/chargefunc.r90 b/BaseTinyFirmware/IAR/Release/Obj/chargefunc.r90
new file mode 100644 (file)
index 0000000..bd15d00
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/chargefunc.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/main.r90 b/BaseTinyFirmware/IAR/Release/Obj/main.r90
new file mode 100644 (file)
index 0000000..5a21cad
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/main.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/menu.r90 b/BaseTinyFirmware/IAR/Release/Obj/menu.r90
new file mode 100644 (file)
index 0000000..a929e0b
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/menu.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/statefunc.r90 b/BaseTinyFirmware/IAR/Release/Obj/statefunc.r90
new file mode 100644 (file)
index 0000000..cd118fb
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/statefunc.r90 differ
diff --git a/BaseTinyFirmware/IAR/Release/Obj/time.r90 b/BaseTinyFirmware/IAR/Release/Obj/time.r90
new file mode 100644 (file)
index 0000000..dfb2a26
Binary files /dev/null and b/BaseTinyFirmware/IAR/Release/Obj/time.r90 differ
diff --git a/BaseTinyFirmware/IAR/USI.c b/BaseTinyFirmware/IAR/USI.c
new file mode 100644 (file)
index 0000000..95f9096
--- /dev/null
@@ -0,0 +1,311 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for use of the Universal Serial Interface\r
+ *\r
+ *      Contains high level functions for initializing the USI as an SPI slave,\r
+ *      interrupt handling, sending and receiving single bytes.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "main.h"\r
+#include "ADC.h"\r
+#include "battery.h"\r
+#include "time.h"\r
+#include "USI.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+//! SPI status struct\r
+SPI_Status_t SPI;\r
+\r
+\r
+//******************************************************************************\r
+//Functions\r
+//*****************************************************************************\r
+/*! \brief USI Counter Overflow Interrupt Service Routine\r
+ *\r
+ * When the USI counter overflows, a byte has been transferred.\n\r
+ * The USIDR contents are stored and flags are updated.\r
+ *\r
+ * The protocol is quite simple and has three sequential states: command,\r
+ * address and data.\r
+ * (Keep in mind that the Master is in charge of data clocking, which means\r
+ * there is a one byte "delay" from when the Slave puts something to SPI till\r
+ * the Master can read it.)\r
+ *\r
+ * 1. If a non-zero byte is received in the command state, the ISR will\r
+ * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of\r
+ * bytes). To signal that the command was received, 0xCC is put to the SPI bus.\r
+ * If a zero byte (0x00) is received in the command state, it is simply ignored\r
+ * because it is an invalid command.\r
+ *\r
+ * 2. When a byte is received in the address state, it is stored to the SPI\r
+ * struct. To signal that the address was received, 0xBB is put to SPI bus.\r
+ * \r
+ * 3. In the data state, variables are read/written "from back to front" until\r
+ * the byte counter reaches zero. Since the Master is in charge of the data\r
+ * clocking, the Slave will go to command state before the last byte is\r
+ * transferred during reading. This means that the Master should send an \r
+ * invalid command when getting each byte, ie 0x00.\r
+ *\r
+ * If the time between two transfers is 1 second or more, the Slave\r
+ * automatically reverts to command state.\r
+ *\r
+ * \note Battery charging is not automatically halted during SPI communication.\r
+ * This means that the current charge state (current and voltage) will\r
+ * remain constant during heavy and prolonged serial traffic.\r
+ *\r
+ * \todo Variable writing not implemented yet.\r
+ * \todo EEPROM/SRAM flag doesn't really do anything with this implementation.\r
+ */\r
+#pragma vector=USI_OVF_vect\r
+__interrupt void USI_OVF_ISR(void)\r
+{\r
+       // If the communication timed out, set ST_CMD as current state.\r
+       if (!Time_Left(TIMER_USI)) {\r
+               SPI.State = ST_CMD;\r
+       }\r
+\r
+       // Start communication timer. If further communication doesn't happen\r
+       // within 1 second, the SPI communication state is reset to CMD.\r
+       Time_Set(TIMER_USI, 0, 1, 0);\r
+       \r
+       // Clear USI counter and flag completed transfer.\r
+       USISR = (1<<USIOIF);\r
+       SPI.XferComplete = TRUE;\r
+       \r
+       // Process incoming data.\r
+       switch(SPI.State)       {\r
+       // A valid SPI transfer starts with a Command Byte sent by the Master.\r
+       case ST_CMD:   \r
+               SPI.Data = USIDR;  // Store the transferred byte.\r
+               \r
+               // If the master sent 0, it is trying to get data. Ignore in this state.\r
+               if (SPI.Data != 0) {\r
+                       // Does the master want to read or write?\r
+                       if (SPI.Data & 0x40) {\r
+                               SPI.Read = FALSE;\r
+                       } else {\r
+                               SPI.Read = TRUE;\r
+                       }\r
+\r
+                               // From/to EEPROM or SRAM?\r
+                       if (SPI.Data &0x80) {\r
+                               SPI.EEPROM = TRUE;\r
+                       } else {\r
+                               SPI.EEPROM = FALSE;\r
+                       }\r
+\r
+                       SPI.Count = (SPI.Data & 0x3F);  // Get number of bytes to receive/send.\r
+                       SPI.State = ST_ADDR;  // The Master will send the address byte next.\r
+\r
+                       SPI_Put(0xCC);  // Signal that command was received.\r
+               }\r
+       break;\r
+\r
+                       \r
+       case ST_ADDR:  \r
+               SPI.Data = USIDR;  // Store the address.\r
+               SPI.Address = SPI.Data;\r
+               SPI.State = ST_DATA;  // The master will send/wait for data next.\r
+\r
+               SPI_Put(0xBB);  // Signal that address was received.\r
+       break;\r
+\r
+\r
+       // Note well: this will process at least one byte, regardless of Count.\r
+       case ST_DATA:\r
+               if (SPI.Count-- > 0) {\r
+                       // Write specified variable to SPI, "back to front".\r
+                       if (SPI.Read) {\r
+                               switch (SPI.Address) {\r
+                               case ADR_ADCS:\r
+                                       SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               \r
+                               case ADR_BATTACTIVE:\r
+                                       SPI_Put(*((unsigned char*)&BattActive + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               \r
+                               case ADR_BATTDATA:\r
+                                       SPI_Put(*((unsigned char*)&BattData + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               \r
+                               case ADR_BATTCTRL:\r
+                                       SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count)));\r
+                               break;\r
+                               \r
+                               case ADR_TIMERS:\r
+                                       SPI_Put(*((unsigned char*)&timeval + (SPI.Count)));\r
+                               break;\r
+\r
+                               \r
+                               default:\r
+                                       SPI_Put(0);\r
+                               break;\r
+                               }\r
+                       } else {\r
+                               // Read byte from SPI\r
+                               SPI.Data = USIDR;\r
+\r
+                               // ********************************************\r
+                               // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED\r
+                               // ********************************************\r
+                                                               \r
+                               // Save byte to specified variable.\r
+                               switch (SPI.Address) {\r
+                               case ADR_BATTCTRL:\r
+                                       *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data;\r
+                               break;\r
+\r
+                               \r
+                               default:\r
+                               break;\r
+                               }\r
+                       }\r
+                       \r
+\r
+               } else {\r
+                       SPI.State = ST_CMD;\r
+               }\r
+       break;\r
+\r
+       default:  // Shouldn't end up here. (Unknown SPI-state)\r
+       break;\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Initializes USI as an SPI slave\r
+ *\r
+ * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for\r
+ * I/O and clock, and USI counter overflow interrupts enabled.\n\r
+ * Also initializes the SPI status struct.\r
+ * \r
+ * \param spi_mode Specifies if USI should trigger on positive (0) or negative\r
+ * (1) edge of clock signal\r
+ *\r
+ * \note Clears the stored data\r
+ *\r
+ * \todo Timer should reset SPI protocol on timeout\r
+ */\r
+void SPI_Init(unsigned char spi_mode)\r
+{\r
+       __disable_interrupt();\r
+       \r
+       // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins.\r
+       USI_DIR_REG |= (1<<USI_DATAOUT_PIN);\r
+       USI_DIR_REG &= ~((1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN));\r
+       USI_OUT_REG |= (1<<USI_DATAIN_PIN) | (1<<USI_CLOCK_PIN);\r
+       \r
+       // Configure USI to 3-wire slave mode with overflow interrupt\r
+       USICR = ( (1<<USIOIE) | (1<<USIWM0) | (1<<USICS1) | (spi_mode<<USICS0) );\r
+\r
+       // Initialize the SPI struct\r
+       SPI.Data = 0;                 // Clear data.\r
+       SPI.State = ST_CMD;           // Initial SPI state: wait for command.\r
+       SPI.Read = FALSE;             // Doesn't matter right now.\r
+       SPI.EEPROM = FALSE;           // Doesn't matter right now.\r
+       SPI.Count = 0;                // Doesn't matter right now.\r
+       SPI.Address = 0;              // Doesn't matter right now.\r
+       SPI.XferComplete = FALSE;     // We haven't even started a transfer yet.\r
+       SPI.WriteCollision = FALSE;   // ..And therefore a collision hasn't happened.\r
+\r
+       __enable_interrupt();\r
+}\r
+\r
+\r
+// Put one byte on bus. Use this function like you would write to the SPDR\r
+// register in the native SPI module. Calling this function will prepare a\r
+// byte for the next transfer initiated by the master device. If a transfer\r
+// is in progress, this function will set the write collision flag and return\r
+// without altering the data registers.\r
+//\r
+// Returns 0 if a write collision occurred, 1 otherwise.\r
+/*! \brief Write a byte to SPI bus\r
+ *\r
+ * This function first checks if a transmission is in progress, and if so, flags\r
+ * a write collision, and returns FALSE.\n\r
+ * If a transmission is not in progress, the flags for write collision and\r
+ * transfer complete are cleared, and the input byte is written to SPDR.\n\r
+ *\r
+ * \param val The byte to send.\r
+ *\r
+ * \retval FALSE A write collision happened.\r
+ * \retval TRUE Byte written to SPDR.\r
+ */\r
+unsigned char SPI_Put(unsigned char val)\r
+{\r
+       // Check if transmission in progress, i.e. if USI counter doesn't equal zero.\r
+       // If this fails, flag a write collision and return.\r
+       if((USISR & 0x0F) != 0) {\r
+               SPI.WriteCollision = TRUE;\r
+               return(FALSE);\r
+       }\r
+\r
+       // Reinitialize flags.\r
+       SPI.XferComplete = FALSE;\r
+       SPI.WriteCollision = FALSE;\r
+\r
+       USIDR = val;  // Put data in USI data register.\r
+\r
+       return (TRUE);\r
+}\r
+\r
+\r
+// Get one byte from bus. This function only returns the previous stored\r
+// USIDR value. The transfer complete flag is not checked. Use this function\r
+// like you would read from the SPDR register in the native SPI module.\r
+/*! \brief Get the last byte received from SPI bus\r
+ *\r
+ * This function simply returns the last byte stored to the SPI status struct,\r
+ * without checking if a completed transfer is flagged.\r
+ *\r
+ * \retval SPI.Data The last byte read from SPI.\r
+ */\r
+unsigned char SPI_Get(void)\r
+{\r
+       return SPI.Data;\r
+}\r
+\r
+\r
+/*! \brief Wait for SPI transfer to complete\r
+ *\r
+ * This function waits for a transfer complete to be flagged.\r
+ */\r
+void SPI_Wait(void)\r
+{\r
+       do {  // Wait for transfer complete.\r
+       } while (SPI.XferComplete == FALSE);\r
+}\r
diff --git a/BaseTinyFirmware/IAR/USI.h b/BaseTinyFirmware/IAR/USI.h
new file mode 100644 (file)
index 0000000..86a7cdc
--- /dev/null
@@ -0,0 +1,91 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for USI.c\r
+ *\r
+ *      Contains definitions of which I/O-register and pins to use,\r
+ *      communication states, and a declaration of the SPI status struct.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef USI_H\r
+#define USI_H\r
+\r
+//******************************************************************************\r
+// USI port and pin definitions\r
+//******************************************************************************\r
+#define USI_OUT_REG       PORTB   //!< USI port output register.\r
+#define USI_IN_REG        PINB    //!< USI port input register.\r
+#define USI_DIR_REG       DDRB    //!< USI port direction register.\r
+#define USI_CLOCK_PIN     PB2     //!< USI clock I/O pin.\r
+#define USI_DATAIN_PIN    PB0     //!< USI data input pin.\r
+#define USI_DATAOUT_PIN   PB1     //!< USI data output pin.\r
+\r
+\r
+//******************************************************************************\r
+// USI/SPI states\r
+//******************************************************************************\r
+enum {\r
+       ST_CMD = 1,  //!< USI/SPI command state.\r
+       ST_ADDR,     //!< USI/SPI address state.\r
+       ST_DATA      //!< USI/SPI data state.\r
+};\r
+\r
+\r
+//******************************************************************************\r
+// Struct declarations\r
+//******************************************************************************\r
+//! \brief Holds SPI status and data\r
+struct SPI_Status_struct\r
+{\r
+       unsigned char Data           : 8;  //!< The last received byte.\r
+       unsigned char Address        : 8;  //!< Specifies variable to read/write.\r
+       unsigned char Count          : 6;  //!< The number of bytes to read/write.\r
+       unsigned char State          : 2;  //!< \brief Communication state.\r
+       //!< \note The states are enumerated in USI.h.\r
+               \r
+       \r
+       //! Master wants to read or write? (TRUE/FALSE)\r
+       unsigned char Read           : 1;\r
+       \r
+       //! Read/write from/to EEPROM? (TRUE/FALSE)\r
+       unsigned char EEPROM         : 1;\r
+       \r
+       //! Used by SPI_Put() to determine if last byte was transferred.(TRUE/FALSE)\r
+       unsigned char XferComplete   : 1;\r
+       \r
+       //! Set if SPI_Put() is called before last byte was transferred.(TRUE/FALSE)\r
+       unsigned char WriteCollision : 1; \r
+};\r
+typedef struct SPI_Status_struct SPI_Status_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+#pragma vector = USI_OVF_vect\r
+__interrupt void USI_OVF_ISR(void);\r
+\r
+void SPI_Init(unsigned char spi_mode);\r
+unsigned char SPI_Put(unsigned char val);\r
+unsigned char SPI_Get(void);\r
+void SPI_Wait(void);\r
+\r
+#endif // USI_H\r
diff --git a/BaseTinyFirmware/IAR/atmel.jpg b/BaseTinyFirmware/IAR/atmel.jpg
new file mode 100644 (file)
index 0000000..f163a72
Binary files /dev/null and b/BaseTinyFirmware/IAR/atmel.jpg differ
diff --git a/BaseTinyFirmware/IAR/battery.c b/BaseTinyFirmware/IAR/battery.c
new file mode 100644 (file)
index 0000000..4486197
--- /dev/null
@@ -0,0 +1,420 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions related to battery control and data acquisition.\r
+ *\r
+ *      Contains functions for enabling/disabling batteries, and looking up\r
+ *      their status and specifications using the ADC.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+\r
+#include "structs.h"\r
+#include "enums.h"\r
+\r
+#include "ADC.h"\r
+#include "battery.h"\r
+#include "main.h"\r
+#include "OWI.h"\r
+#include "time.h"\r
+\r
+#ifdef NIMH\r
+#include "NIMHspecs.h"\r
+#endif // NIMH\r
+\r
+#ifdef LIION\r
+#include "LIIONspecs.h"\r
+#endif // LIION\r
+\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+/* Control-struct for batteries */\r
+/*! \brief Holds control data for both batteries\r
+ * \note Stored in EEPROM.\r
+ */\r
+__eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE},\r
+                                     {TRUE, TRUE, FALSE}};\r
+\r
+/* Data-struct for battery */\r
+Batteries_t BattData; //!< Holds data for the current battery\r
+\r
+\r
+/* Storage for battery EPROM */\r
+/*! \brief Storage space for data from the batteries' own EPROMs.\r
+ * \note Stored in EEPROM.\r
+ */\r
+__eeprom unsigned char BattEEPROM[4][32];\r
+\r
+\r
+//! Global that indicates current battery (0 = battery A, 1 = B)\r
+unsigned char BattActive;\r
+\r
+\r
+/*! \brief RID lookup-table\r
+ *\r
+ * Contains Resistor ID data specified by manufacturer.\r
+ *\r
+ * \note Values have been calculated assuming a +/- 15% tolerance.\r
+ */\r
+const RID_Lookup_t RID[RID_TABLE_SIZE] = {\r
+  {558, 659, 3900, 550, 260, 300, 10},\r
+  {744, 843, 6800, 750, 360, 300, 14},\r
+  {869, 958, 10000, 1000, 475, 300, 19},\r
+  {1097, 1153, 24000, 2000, 475, 420, 38}\r
+};\r
+\r
+\r
+/*! \brief NTC lookup-table\r
+ *\r
+ * The first entry is 0 degrees. For every entry after, temperature increases\r
+ * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n\r
+ * It must be sorted in descending ADC order.\r
+ *\r
+ * \note This was calculated for a Mitsubishi RH16-3H103FB NTC.\r
+ *\r
+ * \note NTCLookUp() must be modified if this table is changed so that:\r
+ * - first entry is no longer 0 degrees.\r
+ * - temperature difference between entries is no longer 4 degrees.\r
+ * - ADCsteps no longer specifies ADC steps per half degree.\r
+ */\r
+// FOR VARTA POLYFLEX NTC\r
+const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+       {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27},\r
+       {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24},\r
+       {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17},\r
+       {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10}\r
+};\r
+\r
+\r
+// FOR MITSUBISHI NTC\r
+/*\r
+const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = {\r
+  {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27},\r
+  {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24},\r
+  {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17},\r
+  {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10}\r
+};\r
+*/\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Checks if battery has changed\r
+ *\r
+ * Stores current capacity, then attempts to refresh battery status.\n\r
+ * If the refresh is successful, old capacity is compared with the new one.\r
+ * \r
+ * \retval FALSE Battery is disconnected, or capacity has changed.\r
+ * \retval TRUE All OK.\r
+ */\r
+unsigned char BatteryCheck(void)\r
+{\r
+       unsigned char success = TRUE;\r
+       unsigned int  oldCapacity;\r
+       \r
+       // Save to see if battery data has changed.\r
+       oldCapacity = BattData.Capacity;  \r
+       \r
+       if (!BatteryStatusRefresh()) {\r
+               success = FALSE;              // Battery not present or RID was invalid.\r
+       }\r
+       \r
+       if (oldCapacity != BattData.Capacity) {\r
+               success = FALSE;              // Battery configuration has changed.\r
+       }\r
+\r
+       return(success);\r
+}\r
+\r
+\r
+/*! \brief Refreshes battery status information\r
+ *\r
+ * Refreshes battery status information, if it is present, based on\r
+ * RID and NTC (read by ADC).\n\r
+ * The battery must have been enabled and a complete set of ADC data must have\r
+ * been collected before calling.\n\r
+ *\r
+ * \retval FALSE No battery present.\r
+ * \retval TRUE Battery present, status refreshed.\r
+ *\r
+ * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry\r
+ * is found in the lookup table. Instead, default battery data will be used.\r
+ */\r
+unsigned char BatteryStatusRefresh(void)\r
+{\r
+       // Assume the worst..\r
+       unsigned char success = FALSE;\r
+       \r
+       BattData.Present = FALSE;\r
+       BattData.Charged = FALSE;\r
+       BattData.Low = TRUE;\r
+       BattData.Circuit = OW_NONE;\r
+       BattData.Temperature = 0;\r
+       BattData.Capacity = 0;\r
+       BattData.MaxCurrent = 0;\r
+       BattData.MaxTime = 0;\r
+       BattData.MinCurrent = 0;\r
+\r
+       NTCLookUp();\r
+       BattData.HasRID = RIDLookUp();\r
+\r
+       // Is the battery voltage above minimum safe cell voltage?\r
+       if (ADCS.VBAT >= BAT_VOLTAGE_MIN) {\r
+               BattData.Low = FALSE;\r
+       }\r
+\r
+       // Is the battery charged?\r
+       if (ADCS.VBAT >= BAT_VOLTAGE_LOW) {\r
+               BattData.Charged = TRUE;\r
+       }\r
+\r
+       // If we are not charging, yet VBAT is above safe limit, battery is present.\r
+       // If we are charging and there's a current flowing, the battery is present.\r
+       \r
+       /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence\r
+       * check is redundant since charging will be aborted due to low current at\r
+       * max duty cycle. That is preferrable since the charge current reading is\r
+       * not 100% proof.\r
+       */\r
+       if (((OCR1B == 0) && (!BattData.Low)) ||\r
+           ((OCR1B != 0) && (ADCS.avgIBAT > 0))) {\r
+               BattData.Present = TRUE;\r
+               success = TRUE;\r
+       } else {\r
+               BattData.Low = FALSE;  // (This is just a technicality..)\r
+               success = FALSE;\r
+       }\r
+\r
+#ifndef ALLOW_NO_RID\r
+       // Return FALSE if no valid RID entry was found, to stop charging.\r
+       if(!BattData.HasRID) {\r
+               success = FALSE;\r
+       }\r
+#endif\r
+\r
+       return(success);\r
+}\r
+\r
+\r
+/*! \brief Refreshes battery data in the EEPROM\r
+ *\r
+ * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store\r
+ * these data in on-chip EEPROM.\n\r
+ * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared.\r
+ *\r
+ * \todo Updating BattData with these data. Specs needed.\r
+ *\r
+ * \retval FALSE Refresh failed.\r
+ * \retval TRUE Refresh successful.\r
+ */\r
+unsigned char BatteryDataRefresh(void)\r
+{\r
+       unsigned char offset;\r
+       unsigned char i, crc, family, temp, page;\r
+       unsigned char success;\r
+       \r
+       // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found.\r
+       for (page = 0; page < 4; page++)        {\r
+               success = FALSE;\r
+       \r
+               if (OWI_DetectPresence(OWIBUS) == OWIBUS) {\r
+                       \r
+                       // Presence detected, check type and CRC.\r
+                       OWI_SendByte(OWI_ROM_READ, OWIBUS);\r
+                       family = OWI_ReceiveByte(OWIBUS);\r
+                       crc = OWI_ComputeCRC8(family,0);\r
+\r
+                       for (i = 0; i < 6; i++) {\r
+                               crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc);\r
+                       }\r
+\r
+                       // CRC ok, device found.\r
+                       if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+                               BattData.Circuit = family;\r
+\r
+                               // For now, we only read data from DS2505 EPROMs.\r
+                               if (BattData.Circuit == OW_DS2505) {\r
+                                       offset = page*32;\r
+                                       OWI_SendByte(DS2505_DATA_READ, OWIBUS);  // Command: read data.\r
+                                       OWI_SendByte(offset, OWIBUS);            // Data: low address.\r
+                                       OWI_SendByte(0, OWIBUS);                 // Data: high address.\r
+\r
+                                       // Calculate checksums.\r
+                                       crc = OWI_ComputeCRC8(DS2505_DATA_READ,0);\r
+                                       crc = OWI_ComputeCRC8(offset,crc);\r
+                                       crc = OWI_ComputeCRC8(0,crc);\r
+\r
+                                       // Command received succesfully, now start reading data\r
+                                       // and writing it to EEPROM.\r
+                                       if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+                                               crc = 0;\r
+                                               \r
+                                               // Fill page with data.\r
+                                               for (i=0; i<32; i++) {\r
+                                                       temp = OWI_ReceiveByte(OWIBUS);\r
+                                                       crc = OWI_ComputeCRC8(temp, crc);\r
+                                                       BattEEPROM[page][i] = temp;\r
+                                               }\r
+                                               \r
+                                               if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) {\r
+                                                               success = TRUE;  // Data read OK\r
+                                               }\r
+                                       } else { // Not able to start reading data.\r
+                                       }\r
+                               } else { // Wrong device type.\r
+                               }\r
+                       } else { // No device found.             \r
+                       }\r
+               } else { // No presence detected on one-wire bus.\r
+               }\r
+\r
+         // Erase local EEPROM page if there were any errors during transfer.\r
+               if (!success) {\r
+                       for (i=0; i<32; i++) {\r
+                               BattEEPROM[page][i] = 0;\r
+                       }\r
+               }\r
+       }\r
+\r
+       return(success);\r
+}\r
+\r
+\r
+/*! \brief Enables specified battery\r
+ *\r
+ * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears\r
+ * PB5/PB4 in PORTB, depending on which battery is specified.\n\r
+ * The function takes 100 ms to allow the port switch to settle.\r
+ *\r
+ * \param bat Specifies which battery to enable (0 = battery A, 1 = B)\r
+ */\r
+void EnableBattery(unsigned char bat)\r
+{\r
+       // Use general timer, set timeout to 100ms.\r
+       Time_Set(TIMER_GEN,0,0,100);\r
+\r
+       // Set specified battery as the active one.\r
+       BattActive = bat;\r
+\r
+       // Enable current battery in hardware, light LED & connect battery.\r
+       PORTB |= (1 << (PB4+bat));\r
+\r
+       // Disconnect other battery.\r
+       PORTB &= ~(1<<(PB5-bat));     \r
+\r
+       do { // Let port switch settle.\r
+       } while (Time_Left(TIMER_GEN));  \r
+}\r
+\r
+\r
+/*! \brief Disables both batteries\r
+ *\r
+ * Clears PB4 and PB5 in PORTB, disabling both batteries.\r
+ */\r
+void DisableBatteries(void)\r
+{\r
+       // Turn off LEDs and disconnect batteries.\r
+       PORTB &= ~((1<<PB4)|(1<<PB5));  \r
+}\r
+\r
+\r
+/*! \brief Looks up battery data from RID table\r
+ *\r
+ * Attempts to find data for the battery from the RID lookup-table.\n\r
+ * If no valid entry is found, default data (defined in battery.h)\r
+ * are used.\r
+ *\r
+ * \retval TRUE Entry found, battery data updated.\r
+ * \retval FALSE No entry found, using defaults for battery data.\r
+ */\r
+unsigned char RIDLookUp (void)\r
+{\r
+       unsigned char i, found = FALSE;\r
+               \r
+       // Lookup in the RID-table. If measured RID is within the limits\r
+       // of an entry, those data are used, and TRUE is returned.\r
+       for (i = 0 ; i < RID_TABLE_SIZE; i++) {\r
+               if (ADCS.rawRID >= RID[i].Low) {\r
+                       if (ADCS.rawRID <= RID[i].High) {\r
+                               BattData.Capacity = RID[i].Capacity;\r
+                               BattData.MaxCurrent = RID[i].Icharge;\r
+                               BattData.MaxTime = RID[i].tCutOff;\r
+                               BattData.MinCurrent = RID[i].ICutOff;\r
+                               \r
+                               found = TRUE;\r
+                       }\r
+               }\r
+       }\r
+       \r
+       // If no valid entry is found, use defaults and return FALSE.\r
+       if (!found) {\r
+               BattData.Capacity = DEF_BAT_CAPACITY;\r
+               BattData.MaxCurrent = DEF_BAT_CURRENT_MAX;\r
+               BattData.MaxTime = DEF_BAT_TIME_MAX;\r
+               BattData.MinCurrent = DEF_BAT_CURRENT_MIN;\r
+       }\r
+       \r
+       return(found);\r
+}\r
+\r
+\r
+/*! \brief Calculates temperature from a lookup table\r
+ *\r
+ * Looks up the highest NTC value below or equal to the measured one.\n\r
+ * With the current lookup table, temperature is calculated with the formula:\n\r
+ * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry)\r
+ *\r
+ * \note If the NTC-measurement is saturated, with the current lookup table,\r
+ * the temperature will be reported as -1 C.\r
+ *\r
+ * \note If no valid entry is found, battery temperature is set to 80.\r
+ */\r
+void NTCLookUp (void)\r
+{\r
+       unsigned char i;\r
+       unsigned char found = FALSE;\r
+       \r
+       // Lookup in the NTC-table. Use the first entry which is equal or below\r
+       // sampled NTC. Calculate temperature by using the index number, and the\r
+       // difference between the measured NTC value and the one in the entry.\r
+       for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++)       {\r
+               if (ADCS.rawNTC >= NTC[i].ADC) {\r
+                       BattData.Temperature = (i<<2) ;\r
+                       BattData.ADCSteps = NTC[i].ADCsteps;  \r
+                       BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps;\r
+                       \r
+                       found = TRUE;  // Could be done with a break, but that violates MISRA.\r
+               }\r
+       }\r
+       \r
+       // For safety, is temperature is greater than the NTC \r
+       if (!found) {\r
+               BattData.Temperature = 80;\r
+       }\r
+}\r
diff --git a/BaseTinyFirmware/IAR/battery.h b/BaseTinyFirmware/IAR/battery.h
new file mode 100644 (file)
index 0000000..1fa428a
--- /dev/null
@@ -0,0 +1,113 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for battery.c\r
+ *\r
+ *      Contains definitions for the setup of 1-Wire(R) and behaviour of the\r
+ *      battery data and status refreshing functions.\n\r
+ *      Also contains definitions of default battery data, and declarations\r
+ *      for the RID and NTC lookup tables.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *      Original author: \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+\r
+#ifndef BATTERY_H\r
+#define BATTERY_H\r
+\r
+\r
+//******************************************************************************\r
+// Defines for EEPROM reading\r
+//******************************************************************************\r
+#define OWIBUS  OWI_PIN_0         //!< One-wire bus (pin).\r
+\r
+#define OW_NONE           0x00    //!< One-wire device family code.\r
+#define OW_DS2505         0x09    //!< One-wire device family code.\r
+\r
+#define DS2505_MEM_READ     0xF0  //!< One-wire device command.\r
+#define DS2505_STATUS_READ  0xAA  //!< One-wire device command.\r
+#define DS2505_DATA_READ    0xC3  //!< One-wire device command.\r
+\r
+\r
+//******************************************************************************\r
+// RID-less charging (for BatteryStatusRefresh())\r
+//******************************************************************************\r
+//#define ALLOW_NO_RID  //!< Use default battery data if no matching entry found.\r
+\r
+#define DEF_BAT_CAPACITY               0  //!< Default battery capacity, in mAh.\r
+#define DEF_BAT_CURRENT_MAX    0  //!< Default maximum charge current, in mA.\r
+#define DEF_BAT_TIME_MAX               0  //!< Default maximum charge time, in minutes.\r
+//! Default minimum current to stop charge, in mA.\r
+#define DEF_BAT_CURRENT_MIN    0\r
+\r
+\r
+\r
+//******************************************************************************\r
+// RID and NTC defines and struct declarations\r
+//******************************************************************************\r
+#define RID_TABLE_SIZE        4     //!< Number of entries in RID table.\r
+#define NTC_TABLE_SIZE        20    //!< Number of entries in NTC table.\r
+\r
+//! \brief Struct for an entry in the resistor ID lookup-table\r
+struct RID_Lookup_struct {\r
+  unsigned int  Low;              //!< Lowest acceptable ADC value.\r
+  unsigned int  High;             //!< Highest acceptable ADC value.\r
+  unsigned int  Resistance;       //!< RID resistance, in Ohms.\r
+  unsigned int  Capacity;         //!< Associated battery capacity, in mAh.\r
+  unsigned int  Icharge;          //!< Associated initial charge current, in mA.\r
+  unsigned int  tCutOff;          //!< Associated cut-off time, in minutes.\r
+  unsigned int  ICutOff;          //!< Associated cut-off current, in mA.\r
+};\r
+typedef struct RID_Lookup_struct RID_Lookup_t; //!< For convenience.\r
+\r
+/*! \brief Struct for an entry in the NTC lookup-table\r
+ *\r
+ * \note Must be sorted in descending ADC order.\r
+ */\r
+struct NTC_Lookup_struct\r
+{\r
+  unsigned int  ADC;  //!< Measured NTC.\r
+  unsigned char ADCsteps;  //!< ADC steps per half degree at this temperature.\r
+};\r
+typedef struct NTC_Lookup_struct NTC_Lookup_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern __eeprom Battery_t BattControl[];\r
+extern Batteries_t BattData;\r
+extern __eeprom unsigned char BattEEPROM[][32];\r
+extern unsigned char BattActive;\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char BatteryCheck(void);\r
+unsigned char BatteryStatusRefresh(void);\r
+unsigned char BatteryDataRefresh(void);\r
+void EnableBattery(unsigned char);\r
+void DisableBatteries(void);\r
+unsigned char RIDLookUp(void);\r
+void NTCLookUp(void);\r
+\r
+\r
+#endif // BATTERY_H\r
diff --git a/BaseTinyFirmware/IAR/blue.GIF b/BaseTinyFirmware/IAR/blue.GIF
new file mode 100644 (file)
index 0000000..ddb3000
Binary files /dev/null and b/BaseTinyFirmware/IAR/blue.GIF differ
diff --git a/BaseTinyFirmware/IAR/charge.h b/BaseTinyFirmware/IAR/charge.h
new file mode 100644 (file)
index 0000000..3d387a5
--- /dev/null
@@ -0,0 +1,38 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for NIMHcharge.c and LIIONcharge.c\r
+ *\r
+ *      Contains definitions and declarations related to the charge state.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/charge.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef CHARGE_H\r
+#define CHARGE_H\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char Charge(unsigned char inp);\r
+\r
+\r
+#endif // CHARGE_H\r
diff --git a/BaseTinyFirmware/IAR/chargefunc.c b/BaseTinyFirmware/IAR/chargefunc.c
new file mode 100644 (file)
index 0000000..f620f70
--- /dev/null
@@ -0,0 +1,361 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Charge functions\r
+ *\r
+ *      Contains the functions for charging with constant current and voltage,\r
+ *      and for deciding when to halt.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+\r
+#include "enums.h"\r
+#include "structs.h"\r
+\r
+#include "ADC.h"\r
+#include "battery.h"\r
+#include "chargefunc.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "PWM.h"\r
+#include "statefunc.h"\r
+#include "time.h"\r
+\r
+#ifdef NIMH\r
+#include "NIMHspecs.h"\r
+#endif // NIMH\r
+\r
+#ifdef LIION\r
+#include "LIIONspecs.h"\r
+#endif // LIION\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+//! Struct that holds parameters for ConstantCurrent() and ConstantVoltage().\r
+ChargeParameters_t ChargeParameters;\r
+\r
+//! Struct that holds parameters for HaltNow().\r
+HaltParameters_t HaltParameters;\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Charges battery with a constant current.\r
+ *\r
+ * This function applies a constant current (set in ChargeParameters.Current)\r
+ * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+ * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+ * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n\r
+ * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+ * Once the battery is no longer flagged for charge inhibit, timers are\r
+ * started again and charging resumed.\r
+ *\r
+ * \retval ChargeParameters.NextState Next state once this stage is done.\r
+ * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+ * HaltNow() will have set a new next state.\r
+ */\r
+unsigned char ConstantCurrent(void)\r
+{\r
+       unsigned char error = FALSE,\r
+                     wasStopped = FALSE;\r
+       \r
+       do      {\r
+      // Wait for ADC conversions to complete.\r
+               ADC_Wait();\r
+\r
+               // If Master has flagged for a charge inhibit, pause charging.\r
+               // (This is to prevent damage during prolonged serial communication.)\r
+               if (BattControl[BattActive].ChargeInhibit) {\r
+                       wasStopped = TRUE;\r
+                       Time_Stop();\r
+                       OCR1B = 0;\r
+               } else {\r
+                       // Continue charging!\r
+                       if (wasStopped) {\r
+                               wasStopped = FALSE;\r
+                               \r
+                               // Timer variables are not reset by this.\r
+                               Time_Start();\r
+                       }\r
+         \r
+                       // Adjust the charge current to within ChargeParameters.Current\r
+                       // +/- BAT_CURRENT_HYST.\r
+                       if ((ADCS.avgIBAT < 0) ||\r
+                           (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) {\r
+                                        \r
+                               if(!PWM_IncrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MAX\r
+                               // If the duty cycle cannot be incremented, flag error and\r
+                               // go to error state.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       } else if ((ADCS.avgIBAT >= 0) &&\r
+                                (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) {\r
+                                        \r
+                               if(!PWM_DecrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MIN\r
+                                       // If the duty cycle cannot be decremented, flag error and\r
+                                       // go to error state.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       }\r
+               }\r
+       } while ((!HaltNow()) && (!error));\r
+\r
+       // Return the next state to Charge(). If an error has occured, this will\r
+       // point to some other state than the next state of charging.\r
+       return(ChargeParameters.NextState);\r
+}\r
+\r
+\r
+/*! \brief Charges battery with a constant voltage\r
+ *\r
+ * This function applies a constant voltage (set in ChargeParameters.Voltage)\r
+ * to the battery until HaltNow() returns TRUE, or a PWM error occurs and\r
+ * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n\r
+ * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n\r
+ * If the Master inhibits charging, timers are stopped and PWM output dropped.\r
+ * Once the battery is no longer flagged for charge inhibit, timers are\r
+ * started again and charging resumed.\r
+ *\r
+ * \retval ChargeParameters.NextState Next state once this stage is done.\r
+ * If no errors occured, this will be whatever was set in Charge(). Otherwise,\r
+ * HaltNow() will have set a new next state.\r
+ */\r
+unsigned char ConstantVoltage(void)\r
+{\r
+       unsigned char error = FALSE,\r
+                     wasStopped = FALSE;\r
+       \r
+       do{\r
+               \r
+               // Wait for ADC conversions to complete.\r
+               ADC_Wait();\r
+               \r
+               // If Master has flagged for a charge inhibit, pause charging.\r
+               // (This is to prevent damage during prolonged serial communication.)\r
+               if (BattControl[BattActive].ChargeInhibit) {\r
+                       wasStopped = TRUE;\r
+                       Time_Stop();\r
+                       OCR1B = 0;\r
+               }\r
+               \r
+               else {\r
+                       // Continue charging!\r
+                       if (wasStopped) {\r
+                               wasStopped = FALSE;\r
+                               \r
+                               // Timer variables aren't reset by this.\r
+                               Time_Start();\r
+                       }\r
+                       \r
+                       // Adjust the charge voltage to within ChargeParameters.Voltage\r
+                       // +/- BAT_VOLTAGE_HYST.\r
+                       if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) {\r
+\r
+                               if(!PWM_IncrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MAX\r
+                               // Flag PWM control error and go to error-state if the duty\r
+                               // cycle cannot be incremented.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) {\r
+\r
+                               if(!PWM_DecrementDutyCycle()) {\r
+#ifdef ABORT_IF_PWM_MIN\r
+                                       // Flag PWM control error and go to error-state if duty\r
+                                       // cycle cannot be decremented.\r
+                                       SetErrorFlag(ERR_PWM_CONTROL);\r
+                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       error = TRUE;\r
+#endif\r
+                               }\r
+                       }\r
+               }\r
+\r
+       } while ((!HaltNow()) && (!error));\r
+\r
+       // Return the next state to Charge(). If an error has occured, this will\r
+       // point to some other state than the next state of charging.\r
+       return(ChargeParameters.NextState);\r
+}\r
+\r
+\r
+/*! \brief Determines when to halt charging.\r
+ *\r
+ * This function evaluates parameters depending on what has been flagged in\r
+ * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should\r
+ * halt or not.\n\r
+ * In addition, error flagging on timeout (battery exhaustion) can be set.\n\r
+ *\r
+ * The function also checks if the battery temperature is within limits,\r
+ * if mains is OK, and if BatteryCheck() returns TRUE.\r
+ * If an error is detected, the associated errorflag is set and \r
+ * ChargeParameters.NextState is changed to an appropriate state.\r
+ *\r
+ * \retval TRUE Halt now.\r
+ * \retval FALSE Don't halt now.\r
+ *\r
+ * \note See chargefunc.h for definitions of halt flags.\r
+ * \note It is generally a bad idea not to halt on a timeout.\r
+ * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be\r
+ * reset in Charge() before calling a charging-function.\r
+ *\r
+ * \todo "Priorities" of standard error checks OK?\r
+ */\r
+unsigned char HaltNow(void)\r
+{\r
+       unsigned char i, halt = FALSE;\r
+       \r
+       // Wait for a full ADC-cycle to finish.\r
+       ADC_Wait();\r
+\r
+       // Evaluate ADC readings according to HaltFlags. Flag errors if selected.\r
+       // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR.\r
+       // (Gets overridden if either mains is failing, or the battery changes.)\r
+       for (i = 0x01; i != 0; i <<= 1) {\r
+               if (HaltParameters.HaltFlags & i) {\r
+                       switch (i) {\r
+                       // Is VBAT less than the recorded maximum?\r
+                       case HALT_VOLTAGE_DROP:\r
+\r
+                               // Update VBATMax if VBAT is higher. Evaluate for halt otherwise.\r
+                               if (ADCS.VBAT > HaltParameters.VBATMax) {\r
+                                       HaltParameters.VBATMax = ADCS.VBAT;\r
+                               } else if((HaltParameters.VBATMax - ADCS.VBAT) >= \r
+                                         HaltParameters.VoltageDrop) {\r
+                                       halt = TRUE;\r
+                               }\r
+                       break;\r
+\r
+                       \r
+                       // Has VBAT reached the maximum limit?\r
+                       case HALT_VOLTAGE_MAX:  \r
+                               \r
+                               if (ADCS.VBAT >= HaltParameters.VoltageMax) {\r
+                                       halt = TRUE;\r
+                               }\r
+                               break;\r
+\r
+\r
+                       // Has IBAT reached the minimum limit?\r
+                       case HALT_CURRENT_MIN:\r
+                               \r
+                               if (ADCS.avgIBAT <= HaltParameters.CurrentMin) {\r
+                                       halt = TRUE;\r
+                               }\r
+                               break;\r
+       \r
+                               \r
+                       // Is the temperature rising too fast?\r
+                       case HALT_TEMPERATURE_RISE:\r
+\r
+                               // If rawNTC has increased, the temperature has dropped.\r
+                               // We can store this value for now, and start the timer.\r
+                               // Otherwise, check if NTC has changed too fast.\r
+                               if (ADCS.rawNTC > HaltParameters.LastNTC) {\r
+                                       HaltParameters.LastNTC = ADCS.rawNTC;\r
+                                       Time_Set(TIMER_TEMP,0,30,0);\r
+                                       \r
+                               // Is the increase in temperature greater than the set threshold?\r
+                               } else  if ((HaltParameters.LastNTC - ADCS.rawNTC) >=\r
+                                 (BattData.ADCSteps * HaltParameters.TemperatureRise)) {\r
+                                       \r
+                                       // If this happened within a timeframe of 30 seconds, the \r
+                                       // temperature is rising faster than we want.\r
+                                       // If not, update LastNTC and reset timer.\r
+                                       if (Time_Left(TIMER_TEMP))  {\r
+                                               halt = TRUE;\r
+                                       } else {\r
+                                               HaltParameters.LastNTC = ADCS.rawNTC;\r
+                                               Time_Set(TIMER_TEMP,0,30,0);\r
+                                       }\r
+                               }\r
+                       break;\r
+       \r
+                       \r
+                       // Is there any time left?\r
+                       case HALT_TIME:  \r
+                               \r
+                               if (!Time_Left(TIMER_CHG)) {\r
+                                       halt = TRUE;\r
+                                       \r
+                                       // If exhaustion flagging is selected, stop the PWM, disable the \r
+                                       // battery and flag it as exhausted. Make ST_ERROR next state.\r
+                                       if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) {\r
+                                                       PWM_Stop();\r
+                                                       BattControl[BattActive].Enabled = FALSE;\r
+                                                       BattData.Exhausted = TRUE;\r
+                                                       SetErrorFlag(ERR_BATTERY_EXHAUSTED);\r
+                                                       ChargeParameters.NextState = ST_ERROR;\r
+                                       }\r
+                               }\r
+                       break;\r
+                       \r
+                       \r
+                       default:  // Shouldn't end up here, but is needed for MISRA compliance.\r
+                       break;\r
+                       }\r
+               }\r
+       }\r
+\r
+       // Standard checks:\r
+\r
+       // Battery too cold or hot?\r
+       if ((BattData.Temperature <= HaltParameters.TemperatureMin) ||\r
+           (BattData.Temperature >= HaltParameters.TemperatureMax)) {\r
+                       \r
+               PWM_Stop();\r
+               SetErrorFlag(ERR_BATTERY_TEMPERATURE);\r
+               ChargeParameters.NextState = ST_ERROR;\r
+               halt = TRUE;\r
+       }\r
+\r
+       // Battery not OK?\r
+       if (!BatteryCheck()) {\r
+               PWM_Stop();\r
+               ChargeParameters.NextState = ST_INIT;\r
+               halt = TRUE;\r
+       }\r
+\r
+       // Is mains voltage OK?\r
+       if (!ADCS.Mains) {\r
+               PWM_Stop();\r
+               ChargeParameters.NextState = ST_SLEEP;\r
+               halt = TRUE;\r
+       }\r
+\r
+       return(halt);\r
+}\r
diff --git a/BaseTinyFirmware/IAR/chargefunc.h b/BaseTinyFirmware/IAR/chargefunc.h
new file mode 100644 (file)
index 0000000..88ac473
--- /dev/null
@@ -0,0 +1,134 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for chargefunc.c\r
+ *\r
+ *      Contains definitions to decide PWM error handling and of halt flags,\r
+ *      and declarations of parameter structs for charging.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef CHARGEFUNC_H\r
+#define CHARGEFUNC_H\r
+\r
+\r
+//******************************************************************************\r
+// PWM error handling\r
+//******************************************************************************\r
+//! Report error if maximum duty cycle doesn't give a sufficient charge current.\r
+#define ABORT_IF_PWM_MAX\r
+\r
+//! Report error if minimum duty cycle gives a too great charge current.\r
+#define ABORT_IF_PWM_MIN\r
+\r
+\r
+//******************************************************************************\r
+// Definitions for HaltFlags\r
+//******************************************************************************\r
+//! Halt if VBAT drops more than the set limit.\r
+#define HALT_VOLTAGE_DROP              0x01  \r
+\r
+//! Halt if VBAT reaches the set maximum.\r
+#define HALT_VOLTAGE_MAX               0x02  \r
+\r
+//! Halt if avgIBAT goes below the set minimum.\r
+#define HALT_CURRENT_MIN               0x04  \r
+\r
+//! Halt if BattData.Temperature rises quicker than the set maximum.\r
+#define HALT_TEMPERATURE_RISE  0x08\r
+\r
+//! Halt if TIMER_CHG runs out.\r
+#define HALT_TIME                                      0x10  \r
+\r
+//! Flag battery as exhausted if timeout occurs.\r
+#define HALT_FLAG_EXHAUSTION   0x20\r
+\r
+\r
+//******************************************************************************\r
+// Parameter struct for charging\r
+//******************************************************************************\r
+/*! \brief Holds the parameters for ConstantCurrent() and ConstantVoltage().\r
+ *\r
+ */\r
+struct ChargeParameters_struct {\r
+       unsigned int Voltage;  //!< Voltage to charge with.\r
+       unsigned int Current;  //!< Current to charge with.\r
+       unsigned char NextState;  //!< \brief Next state once charge stage finishes.\r
+                                //!< \note Set in Charge(), but may be changed by\r
+                                //!< HaltNow() if an error occurs!\r
+};\r
+typedef struct ChargeParameters_struct ChargeParameters_t;\r
+\r
+\r
+//******************************************************************************\r
+// Parameter struct for HaltNow()\r
+//******************************************************************************\r
+/*! \brief Holds the parameters for HaltNow();\r
+ *\r
+ */\r
+struct HaltParameters_struct {\r
+       //! \brief Contains flags for what to evaluate. \r
+       //! \note See chargefunc.h for definitions of flags.\r
+       unsigned char HaltFlags;\r
+       \r
+       //! Maximum drop in voltage before halting, in mV.\r
+       unsigned int VoltageDrop;  \r
+       \r
+       //! Maximum limit for output voltage, in mV.\r
+       unsigned int VoltageMax;  \r
+       \r
+       //! Minimum limit for output current, in mA.\r
+       unsigned int CurrentMin;\r
+       \r
+       //! Maximum limit for battery temperature, in degrees centigrade.\r
+       unsigned int TemperatureMax;\r
+       \r
+       //! Minimum limit for battery temperature, in degrees centigrade.\r
+       signed int TemperatureMin;\r
+\r
+       //! Maximum limit for temperature to rise, in degrees centigrade per minute.\r
+       unsigned int TemperatureRise;\r
+\r
+       //! \brief Contains highest VBAT measured, used to calculate voltage drop.\r
+       //! \note Must be manually reset.\r
+       unsigned int VBATMax;\r
+\r
+       //! Used to detect temperature rise.\r
+       unsigned int LastNTC;  \r
+};\r
+typedef struct HaltParameters_struct HaltParameters_t;\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern ChargeParameters_t ChargeParameters;\r
+extern HaltParameters_t HaltParameters;\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char ConstantCurrent(void);\r
+unsigned char ConstantVoltage(void);\r
+unsigned char HaltNow(void);\r
+\r
+#endif // CHARGEFUNC_H\r
diff --git a/BaseTinyFirmware/IAR/config_AVR458.doxygen b/BaseTinyFirmware/IAR/config_AVR458.doxygen
new file mode 100644 (file)
index 0000000..2e5419c
--- /dev/null
@@ -0,0 +1,229 @@
+# Doxyfile 1.5.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "AVR458 Charging Li-Ion Batteries with ATAVRBC100"
+PROJECT_NUMBER         = "<A href=http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 >Atmel AVR Application Notes</A>"
+OUTPUT_DIRECTORY       = doxygen_avr458
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = YES
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+DISTRIBUTE_GROUP_DOC   = YES
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = YES
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = NO
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = 
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.h \
+                         *.cpp
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = NIMH*
+EXCLUDE_SYMBOLS        = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = YES
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = doxygen
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = RTF
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = YES
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/BaseTinyFirmware/IAR/config_AVR463.doxygen b/BaseTinyFirmware/IAR/config_AVR463.doxygen
new file mode 100644 (file)
index 0000000..5ab35da
--- /dev/null
@@ -0,0 +1,229 @@
+# Doxyfile 1.5.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "AVR463 Charging NiMH Batteries with ATAVRBC100"
+PROJECT_NUMBER         = "<A href=http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 >Atmel AVR Application Notes</A>"
+OUTPUT_DIRECTORY       = doxygen_avr463
+CREATE_SUBDIRS         = NO
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = 
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = 
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = NO
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = YES
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 8
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+DISTRIBUTE_GROUP_DOC   = YES
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = YES
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = YES
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = NO
+SHOW_DIRECTORIES       = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = NO
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = 
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.h \
+                         *.cpp
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = LIION*
+EXCLUDE_SYMBOLS        = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = 
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = YES
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = doxygen
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = YES
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = RTF
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = YES
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = YES
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = YES
+CALLER_GRAPH           = NO
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = NO
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
diff --git a/BaseTinyFirmware/IAR/doxygen.png b/BaseTinyFirmware/IAR/doxygen.png
new file mode 100644 (file)
index 0000000..ccabc50
Binary files /dev/null and b/BaseTinyFirmware/IAR/doxygen.png differ
diff --git a/BaseTinyFirmware/IAR/enums.h b/BaseTinyFirmware/IAR/enums.h
new file mode 100644 (file)
index 0000000..b8c92c5
--- /dev/null
@@ -0,0 +1,56 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Enums in common for Slave and Master\r
+ *\r
+ *      Contains enumerations of timers and variable specifiers for\r
+ *      time.c and USI.c.\n\r
+ *      These are also used in the Master, and have therefore been\r
+ *      put in a separate file for convenience.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/enums.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef ENUMS_H\r
+#define ENUMS_H\r
+\r
+//******************************************************************************\r
+// Variable specifiers (for Master-Slave communication)\r
+//******************************************************************************\r
+enum {\r
+       ADR_ADCS = 1,          //!< Indicates that ADCS is read/write target.\r
+       ADR_BATTACTIVE,        //!< Indicates that BattActive is read/write target.\r
+       ADR_BATTDATA,          //!< Indicates that BattData is read/write target.\r
+       ADR_BATTCTRL,          //!< Indicates that BattControl is read/write target.\r
+       ADR_TIMERS             //!< Indicates that timeval is read/write target.\r
+};\r
+\r
+\r
+//******************************************************************************\r
+// Timers\r
+//******************************************************************************\r
+enum {\r
+       TIMER_USI = 0,          //!< Timer meant for USI.\r
+       TIMER_CHG,              //!< Timer meant for charging.\r
+       TIMER_GEN,              //!< Timer meant for general use.\r
+       TIMER_TEMP,             //!< Timer meant for timing of temperature rise.\r
+       TIMERS                  //!< Number of timers used.\r
+};\r
+\r
+#endif // ENUMS_H\r
diff --git a/BaseTinyFirmware/IAR/main.c b/BaseTinyFirmware/IAR/main.c
new file mode 100644 (file)
index 0000000..941f779
--- /dev/null
@@ -0,0 +1,212 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Main program file\r
+ *\r
+ *      Contains the main program, which is a basic state machine.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2302 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $\r
+ * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+/*! \page License\r
+ * Copyright (c) 2007, Atmel Corporation All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above copyright notice,\r
+ * this list of conditions and the following disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above copyright notice,\r
+ * this list of conditions and the following disclaimer in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ *\r
+ * 3. The name of ATMEL may not be used to endorse or promote products derived\r
+ * from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND\r
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,\r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+#include <stdlib.h>\r
+\r
+#include "structs.h"\r
+\r
+#include "main.h"\r
+#include "ADC.h"\r
+#include "statefunc.h"\r
+#include "battery.h"\r
+#include "menu.h"\r
+#include "OWI.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+#include "USI.h"\r
+\r
+\r
+\r
+//******************************************************************************\r
+// Globals\r
+//******************************************************************************\r
+unsigned char CurrentState;     //!< \brief Global that indicates current state\r
+                                //!<\r
+                                //!< Updated by main().\r
+                                //!< \note See menu.h for definition of states.\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Main program\r
+ *\r
+ * The main function goes into an infinite loop, keeping track of the current\r
+ * state and the next one. If the next state is different from the current, it\r
+ * looks up the address to the next state function, in \ref menu_state[], and \r
+ * updates \ref CurrentState. The state function is then called and will\r
+ * eventually return a new state, and so the loop reiterates.\r
+ *\r
+ * \todo The variable inp is passed to all state functions, but is not used\r
+ * for anything yet. Remove?\r
+ */\r
+int main( void )\r
+{\r
+       unsigned char nextstate, inp, i;\r
+       unsigned char (*pStateFunc)(unsigned char);   // Function pointer.\r
+       \r
+       // Initialize local state variables.\r
+       inp = ZERO;\r
+       CurrentState = nextstate = ST_INIT;\r
+       pStateFunc = NULL;\r
+       \r
+       // Look for function associated with current state, get its address.\r
+       for (i = 0; menu_state[i].state != 0; i++) {\r
+               if (menu_state[i].state == CurrentState) {\r
+                       pStateFunc = menu_state[i].pFunc;\r
+               }\r
+       }\r
+\r
+       while (TRUE) {\r
+               // Run function associated with current state, get next state in return.\r
+               if (pStateFunc != NULL){\r
+                       nextstate = pStateFunc(inp);\r
+               }\r
+\r
+               // Look up function for next state, if it differs from the current.\r
+               if (nextstate != CurrentState) {\r
+                       CurrentState = nextstate;\r
+                       for ( i = 0; menu_state[i].state != 0; i++) {\r
+                               if (menu_state[i].state == CurrentState) {\r
+                                       pStateFunc = menu_state[i].pFunc;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/* Doxygen documentation mainpage ********************************************/\r
+/*! \mainpage\r
+ * \section intro Introduction\r
+ * This documents the software for application note AVR458. This is a charger\r
+ * for Li-Ion batteries, based on ATAVRBC100.\r
+ *\r
+ * \section compinfo Compilation Info\r
+ * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC \r
+ * the source have to be modified.\n\r
+ * \n\r
+ * To make project on IAR EWAVR:\n\r
+ * Add the .c files to project (ADC.c, battery.c, main.c, menu.c,\r
+ * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c,\r
+ * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate\r
+ * battery data if needed.\n\r
+ * \n\r
+ * Use device --cpu=tiny861, enable bit definitions in I/O include files,\r
+ * optimization low for debug target and high for release, output format: ubrof8\r
+ * for Debug and intel_extended for Release. \n\r
+ *\r
+ * \section deviceinfo Device Info\r
+ * This application is based on the ATtiny 861, but it is possible to migrate \r
+ * the design to other AVR microcontrollers, such as pin-compatible devices\r
+ * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be\r
+ * used, but with reduced functionality.\r
+ * \r
+ * Required fuse bit settings:\r
+ *    <pre>\r
+ *    FUSE BIT  | SETTING\r
+ *    ----------+--------------------\r
+ *    CKDIV8    | 1 (unprogrammed)\r
+ *    CKSEL3..0 | 0010 (internal osc)\r
+ *    </pre>\r
+ *\r
+ *\r
+ * \section todo To Do-list\r
+ * \todo\r
+ * - Finalize master-slave communication protocol\r
+ * - Implement discharge mode\r
+ *\r
+ * \section contactinfo Contact Info\r
+ * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n\r
+ * For application notes visit \r
+ * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n\r
+ * Support mail: avr@atmel.com\r
+ */\r
+\r
+\r
+/*! \page misra MISRA C rule violations\r
+ *\r
+ * \par Rule 1\r
+ * <i>"All code shall conform to ISO 9899 standard C, with no extensions\r
+ * permitted."</i>\r
+ *\r
+ * Extensions are necessary because ISO C has no way of specifying that a\r
+ * function should be an interrupt service routine, or that we would like data\r
+ * members to be stored in f.ex. EEPROM.\r
+ *\r
+ *\r
+ * \par Rule 37\r
+ * <i>"Bitwise operations shall not be performed on signed integer types."</i>\r
+ *\r
+ * The compiler assumes all the 1's we shift around to make bitmasks are signed\r
+ * integers. Specifying them all to be (unsigned int), either directly or via a\r
+ * definition, would fix the rule violations, but also reduce code readability.\r
+ *\r
+ *\r
+ * \par Rule 45\r
+ * <i>"Type casting from any type to or from pointers shall not be used."</i>\r
+ *\r
+ * Assigning macro NULL, defined in stdlib.h, to a pointer causes this..\r
+ *\r
+ *\r
+ * \par Rule 96\r
+ * <i>"In the definition of a function-like macro the whole definition, and each\r
+ * instance of a parameter, shall be enclosed in parentheses."</i>\r
+ * \r
+ * It is difficult to use parentheses with void function-like macros.\r
+ */\r
diff --git a/BaseTinyFirmware/IAR/main.h b/BaseTinyFirmware/IAR/main.h
new file mode 100644 (file)
index 0000000..31aefa2
--- /dev/null
@@ -0,0 +1,61 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for main.c\r
+ *\r
+ *      Contains some basic definitions (FALSE, TRUE, ZERO) as well as\r
+ *      what battery type (NiMh or Li-Ion) the charger is for.\r
+ * \r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ *\r
+ * $Name$\r
+ * $Revision: 2302 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.h $\r
+ * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef _MAIN_H\r
+#define _MAIN_H\r
+\r
+\r
+//******************************************************************************\r
+// Firmware revision\r
+//******************************************************************************\r
+#define SWHIGH  1\r
+#define SWLOW   0\r
+\r
+\r
+//******************************************************************************\r
+// Battery type (add appropriate *charge.c to project!)\r
+//******************************************************************************\r
+#define NIMH  //!< Use specs and state menu for NIMH.\r
+//#define LIION  //!< Use specs and state menu for LIION.\r
+\r
+\r
+//******************************************************************************\r
+// Basic definitions\r
+//******************************************************************************\r
+#define FALSE   0  //!< We have to define this ourselves.\r
+#define TRUE    (!FALSE)  //!< We have to define this ourselves.\r
+#define ZERO    0  //!< We have to define this ourselves.\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern unsigned char CurrentState;\r
+\r
+\r
+#endif //_MAIN_H\r
diff --git a/BaseTinyFirmware/IAR/menu.c b/BaseTinyFirmware/IAR/menu.c
new file mode 100644 (file)
index 0000000..f8995ec
--- /dev/null
@@ -0,0 +1,79 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      State menu definition\r
+ * \r
+ *      Contains the definition of the state menu.\n\r
+ *      The state menu contains all states and adresses to associated functions.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ *\r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <stdlib.h>\r
+\r
+#include "statefunc.h"\r
+#include "charge.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+\r
+\r
+//******************************************************************************\r
+// State menu (relies on the proper battery type to be defined in main.h!)\r
+//******************************************************************************\r
+#ifdef NIMH\r
+/*! \brief The state menu\r
+ *\r
+ * Contains all the defined states and addresses to their associated functions.\r
+ */\r
+__flash const MENU_STATE_t menu_state[] = {\r
+//  State                                      State function\r
+  { ST_INIT,            Initialize},\r
+  { ST_BATCON,          BatteryControl},\r
+  { ST_PREQUAL,         Charge},\r
+  { ST_SLEEP,           Sleep},\r
+  { ST_FASTCHARGE,      Charge},\r
+  { ST_LOWRATECHARGE,   Charge},\r
+  { ST_ENDCHARGE,       Charge},       \r
+  { ST_DISCHARGE,       Discharge},\r
+  { ST_ERROR,           Error},\r
+  { 0,                  NULL},\r
+};\r
+#endif // NIMH\r
+\r
+#ifdef LIION\r
+/*! \brief The state menu\r
+ *\r
+ * Contains all the defined states and addresses to their associated functions.\r
+ */\r
+__flash const MENU_STATE_t menu_state[] = {\r
+//  State                                      State function\r
+  { ST_INIT,            Initialize},\r
+  { ST_BATCON,          BatteryControl},\r
+  { ST_PREQUAL,         Charge},\r
+  { ST_SLEEP,           Sleep},\r
+  { ST_CCURRENT,        Charge},\r
+  { ST_CVOLTAGE,        Charge},\r
+  { ST_ENDCHARGE,       Charge},       \r
+  { ST_DISCHARGE,       Discharge},\r
+  { ST_ERROR,           Error},\r
+  { 0,                  NULL},\r
+};\r
+#endif // LIION\r
diff --git a/BaseTinyFirmware/IAR/menu.h b/BaseTinyFirmware/IAR/menu.h
new file mode 100644 (file)
index 0000000..9070cd8
--- /dev/null
@@ -0,0 +1,70 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for menu.c\r
+ * \r
+ *      Contains definitions of each state and declaration of the state\r
+ *      menu entry struct.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef MENU_H\r
+#define MENU_H\r
+\r
+//******************************************************************************\r
+// State machine states\r
+//******************************************************************************\r
+// State machine states -- max size and number of states is 255.\r
+// State values must be larger than zero\r
+#define ST_INIT           (10)  //!< Identifies initialization state.\r
+#define ST_BATCON         (20)  //!< Identifies battery control state.\r
+#define ST_PREQUAL        (30)  //!< Identifies prequalification state.\r
+#define ST_SLEEP          (40)  //!< Identifies sleep state.\r
+#define ST_FASTCHARGE     (50)  //!< Identifies fast charge state.\r
+#define ST_LOWRATECHARGE  (60)  //!< Identifies trickle charge state.\r
+#define ST_ENDCHARGE             (70)  //!< Identifies end of charge.\r
+#define ST_DISCHARGE      (80)  //!< Identifies discharge state.\r
+#define ST_ERROR          (90)  //!< Identifies error state.\r
+#define ST_CCURRENT       (100)  //!< Identifies constant current charge state.\r
+#define ST_CVOLTAGE       (110)  //!< Identifies constant voltage charge state.\r
+\r
+\r
+//******************************************************************************\r
+// Struct declarations\r
+//******************************************************************************\r
+/*! \brief Holds an entry in the state menu\r
+ *\r
+ * Contains the ID number of a state, and a pointer to its associated function\r
+ */\r
+struct MENU_STATE_struct\r
+{\r
+  unsigned char state; //!< ID number of state.\r
+  unsigned char (*pFunc)(unsigned char inp);  //!< Associated function.\r
+};\r
+typedef struct MENU_STATE_struct MENU_STATE_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// Global variables\r
+//******************************************************************************\r
+extern __flash const MENU_STATE_t menu_state[];\r
+\r
+#endif // MENU_H\r
diff --git a/BaseTinyFirmware/IAR/readme_AVR458.html b/BaseTinyFirmware/IAR/readme_AVR458.html
new file mode 100644 (file)
index 0000000..7e82c9e
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<title>ATMEL AVR Doxygen Documentation</title>\r
+<style type="text/css">\r
+<!--\r
+h3 {font-family: Arial, Helvetica, sans-serif}\r
+h5 {font-family: Arial, Helvetica, sans-serif}\r
+.legaltext {font-family: Arial, Helvetica, sans-serif; font-size: 10px; color: #999999;}\r
+p {font-family: Arial, Helvetica, sans-serif; font-size: 12px;}\r
+a:link {text-decoration: none; color:#036ab5}\r
+a:visited {text-decoration: none; color:#036ab5}\r
+a:hover {text-decoration: none; color:#036ab5}\r
+a:active {text-decoration: none; color:#036ab5}\r
+-->\r
+</style>\r
+</head>\r
+<body>\r
+<table width="80%" border="0" cellpadding="0" cellspacing="0">\r
+  <tr>\r
+    <td colspan="2"><p><img src="atmel.jpg" /></p><br /></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="2" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+       <td width="5"></td>\r
+    <td><br />\r
+               <h3><span class="h1">\r
+<!-- START INSERT DOCUMENT TITLE HERE -->\r
+               AVR458: Charging Li-Ion Batteries with BC100\r
+<!-- END INSERT DOCUMENT TITLE HERE -->\r
+               </span></h3>\r
+               <h5><span class="h1">\r
+<!-- START INSERT OPTIONAL DESCRIPTION HERE -->\r
+               This application note is based on the ATAVRBC100 Battery Charger reference design (BC100) and focuses on how to use the reference design to charge Lithium-Ion (Li-Ion) batteries. The firmware is written entirely in C language (using IAR® Systems Embedded Workbench) and is easy to port to other AVR® microcontrollers.\r
+This application is based on the ATtiny861 microcontroller but it is possible to migrate the design to other AVR microcontrollers, such as pin-compatible devices ATtiny261 and ATtiny461. Low pin count devices such as ATtiny25/45/85 can also be used, but with reduced functionality.\r
+<!-- END INSERT OPTIONAL DESCRIPTION HERE -->\r
+               </span></h5>            \r
+<!-- START INSERT DOXYGEN LINKS HERE -->\r
+               <p><a href="doxygen_avr458/doxygen/index.html">Code documentation</a> </p>\r
+<!-- END INSERT DOXYGEN LINKS HERE -->\r
+       <br />\r
+       </td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="1" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2">\r
+               <span class="legaltext"><strong>Disclaimer:</strong> The information in this document is provided in connection with Atmel products. No license, express or implied, by estoppel or otherwise, to any intellectual property right is granted by this document or in connection with the sale of Atmel products. <strong>EXCEPT AS SET FORTH IN ATMEL\92S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL\92S WEB SITE, ATMEL ASSUMES NO LIABILITY WHATSOEVER AND DISCLAIMS ANY EXPRESS, IMPLIED OR STATUTORY WARRANTY RELATING TO ITS PRODUCTS INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THIS DOCUMENT, EVEN IF ATMEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</strong> Atmel makes no representations or warranties with respect to the accuracy or completeness of the contents of this document and reserves the right to make changes to specifications and product descriptions at any time without notice. Atmel does not make any commitment to update the information contained herein. Unless specifically provided otherwise, Atmel products are not suitable for, and shall not be used in, automotive applications. Atmel\92s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.<br />\r
+           <br />\r
+               <strong>© 2006 Atmel Corporation. All rights reserved.</strong> ATMEL®, logo and combinations thereof, Everywhere You Are®, AVR®, and others, are registered trademarks or trademarks of Atmel Corporation or its subsidiaries. Other terms and product names may be trademarks of others.</span></td>\r
+  </tr>  \r
+</table>\r
+</body>\r
+</html>\r
diff --git a/BaseTinyFirmware/IAR/readme_AVR463.html b/BaseTinyFirmware/IAR/readme_AVR463.html
new file mode 100644 (file)
index 0000000..523775a
--- /dev/null
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+<head>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />\r
+<title>ATMEL AVR Doxygen Documentation</title>\r
+<style type="text/css">\r
+<!--\r
+h3 {font-family: Arial, Helvetica, sans-serif}\r
+h5 {font-family: Arial, Helvetica, sans-serif}\r
+.legaltext {font-family: Arial, Helvetica, sans-serif; font-size: 10px; color: #999999;}\r
+p {font-family: Arial, Helvetica, sans-serif; font-size: 12px;}\r
+a:link {text-decoration: none; color:#036ab5}\r
+a:visited {text-decoration: none; color:#036ab5}\r
+a:hover {text-decoration: none; color:#036ab5}\r
+a:active {text-decoration: none; color:#036ab5}\r
+-->\r
+</style>\r
+</head>\r
+<body>\r
+<table width="80%" border="0" cellpadding="0" cellspacing="0">\r
+  <tr>\r
+    <td colspan="2"><p><img src="atmel.jpg" /></p><br /></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="2" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+       <td width="5"></td>\r
+    <td><br />\r
+               <h3><span class="h1">\r
+<!-- START INSERT DOCUMENT TITLE HERE -->\r
+               AVR458: Charging Li-Ion Batteries with BC100\r
+<!-- END INSERT DOCUMENT TITLE HERE -->\r
+               </span></h3>\r
+               <h5><span class="h1">\r
+<!-- START INSERT OPTIONAL DESCRIPTION HERE -->\r
+This application note is based on the ATAVRBC100 Battery Charger reference design (BC100) and focuses on how to use the reference design to charge Nickel-Metal Hydride (NiMH) batteries. The firmware is written entirely in C language (using IAR Systems Embedded Workbench) and is easy to port to other AVR microcontrollers.\r
+This application is based on the ATtiny861 microcontroller but it is possible to migrate the design to other AVR microcontrollers, such as pin-compatible devices ATtiny261 and ATtiny461. Low pin count devices such as ATtiny25/45/85 can also be used, but with reduced functionality.\r
+<!-- END INSERT OPTIONAL DESCRIPTION HERE -->\r
+               </span></h5>            \r
+<!-- START INSERT DOXYGEN LINKS HERE -->\r
+               <p><a href="doxygen_avr463/doxygen/index.html">Code documentation</a> </p>\r
+<!-- END INSERT DOXYGEN LINKS HERE -->\r
+       <br />\r
+       </td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2" height="1" background="blue.gif"></td>\r
+  </tr>\r
+  <tr>\r
+    <td colspan="2">\r
+               <span class="legaltext"><strong>Disclaimer:</strong> The information in this document is provided in connection with Atmel products. No license, express or implied, by estoppel or otherwise, to any intellectual property right is granted by this document or in connection with the sale of Atmel products. <strong>EXCEPT AS SET FORTH IN ATMEL\92S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL\92S WEB SITE, ATMEL ASSUMES NO LIABILITY WHATSOEVER AND DISCLAIMS ANY EXPRESS, IMPLIED OR STATUTORY WARRANTY RELATING TO ITS PRODUCTS INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE, SPECIAL OR INCIDENTAL DAMAGES (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THIS DOCUMENT, EVEN IF ATMEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</strong> Atmel makes no representations or warranties with respect to the accuracy or completeness of the contents of this document and reserves the right to make changes to specifications and product descriptions at any time without notice. Atmel does not make any commitment to update the information contained herein. Unless specifically provided otherwise, Atmel products are not suitable for, and shall not be used in, automotive applications. Atmel\92s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.<br />\r
+           <br />\r
+               <strong>© 2006 Atmel Corporation. All rights reserved.</strong> ATMEL®, logo and combinations thereof, Everywhere You Are®, AVR®, and others, are registered trademarks or trademarks of Atmel Corporation or its subsidiaries. Other terms and product names may be trademarks of others.</span></td>\r
+  </tr>  \r
+</table>\r
+</body>\r
+</html>\r
diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.cspy.bat b/BaseTinyFirmware/IAR/settings/BC100_tiny.cspy.bat
new file mode 100644 (file)
index 0000000..7e4fce5
--- /dev/null
@@ -0,0 +1,32 @@
+@REM This bat file has been generated by the IAR Embeddded Workbench\r
+@REM C-SPY interactive debugger,as an aid to preparing a command\r
+@REM line for running the cspybat command line utility with the\r
+@REM appropriate settings.\r
+@REM\r
+@REM After making some adjustments to this file, you can launch cspybat\r
+@REM by typing the name of this file followed by the name of the debug\r
+@REM file (usually an ubrof file). Note that this file is generated\r
+@REM every time a new debug session is initialized, so you may want to\r
+@REM move or rename the file before making changes.\r
+@REM\r
+@REM Note: some command line arguments cannot be properly generated\r
+@REM by this process. Specifically, the plugin which is responsible\r
+@REM for the Terminal I/O window (and other C runtime functionality)\r
+@REM comes in a special version for cspybat, and the name of that\r
+@REM plugin dll is not known when generating this file. It resides in\r
+@REM the $TOOLKIT_DIR$\bin folder and is usually called XXXbat.dll or\r
+@REM XXXlibsupportbat.dll, where XXX is the name of the corresponding\r
+@REM tool chain. Replace the '<libsupport_plugin>' parameter\r
+@REM below with the appropriate file name. Other plugins loaded by\r
+@REM C-SPY are usually not needed by, or will not work in, cspybat\r
+@REM but they are listed at the end of this file for reference.\r
+\r
+\r
+"C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\bin\cspybat" "C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\bin\avrproc.dll" "C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\bin\avrsim.dll"  %1 --plugin "C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\bin\<libsupport_plugin>" --backend -B "--cpu=tiny861" "--enhanced_core" "-p" "C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\Config\iotiny861.ddf" "--eeprom_size" "512" "-d" "sim" \r
+\r
+\r
+@REM Loaded plugins:\r
+@REM    avrlibsupport.dll\r
+@REM    C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\plugins\CodeCoverage\CodeCoverage.dll\r
+@REM    C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\plugins\Profiling\Profiling.dll\r
+@REM    C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\plugins\stack\stack.dll\r
diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.dbgdt b/BaseTinyFirmware/IAR/settings/BC100_tiny.dbgdt
new file mode 100644 (file)
index 0000000..33f4649
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+\r
+<Project/>\r
+\r
+\r
diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.dni b/BaseTinyFirmware/IAR/settings/BC100_tiny.dni
new file mode 100644 (file)
index 0000000..240a111
--- /dev/null
@@ -0,0 +1,15 @@
+[StackPlugin]\r
+Enabled=1\r
+OverflowWarningsEnabled=1\r
+WarningThreshold=90\r
+SpWarningsEnabled=1\r
+WarnHow=1\r
+UseTrigger=1\r
+TriggerName=main\r
+LimitSize=0\r
+ByteLimit=50\r
+[Breakpoints]\r
+Count=0\r
+[TraceHelper]\r
+Enabled=0\r
+ShowSource=1\r
diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.wsdt b/BaseTinyFirmware/IAR/settings/BC100_tiny.wsdt
new file mode 100644 (file)
index 0000000..07c1d5c
--- /dev/null
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="iso-8859-1"?>\r
+\r
+<Workspace>\r
+  <ConfigDictionary>\r
+    \r
+  <CurrentConfigs><Project>BC100_tiny/Release</Project></CurrentConfigs></ConfigDictionary>\r
+  <Desktop>\r
+    <Static>\r
+      <Workspace>\r
+        <ColumnWidths>\r
+          \r
+          \r
+          \r
+          \r
+        <Column0>330</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>\r
+      </Workspace>\r
+      <Build>\r
+        \r
+        \r
+        \r
+        \r
+      <PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows><Window><Factory>Find-in-Files</Factory></Window></Windows></PreferedWindows><ColumnWidth0>16</ColumnWidth0><ColumnWidth1>773</ColumnWidth1><ColumnWidth2>194</ColumnWidth2><ColumnWidth3>48</ColumnWidth3></Build>\r
+    <Find-in-Files><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows><Window><Factory>Build</Factory></Window></Windows></PreferedWindows><ColumnWidth0>350</ColumnWidth0><ColumnWidth1>50</ColumnWidth1><ColumnWidth2>601</ColumnWidth2></Find-in-Files></Static>\r
+    <Windows>\r
+      \r
+      \r
+    <Wnd2>\r
+        <Tabs>\r
+          <Tab>\r
+            <Identity>TabID-30516-32580</Identity>\r
+            <TabName>Workspace</TabName>\r
+            <Factory>Workspace</Factory>\r
+            <Session>\r
+              \r
+            <NodeDict><ExpandedNode>BC100_tiny</ExpandedNode><ExpandedNode>BC100_tiny/Output</ExpandedNode><ExpandedNode>BC100_tiny/chargefunc.c</ExpandedNode><ExpandedNode>BC100_tiny/chargefunc.c/Output</ExpandedNode></NodeDict></Session>\r
+          </Tab>\r
+        </Tabs>\r
+        \r
+      <SelectedTab>0</SelectedTab></Wnd2><Wnd3><Tabs><Tab><Identity>TabID-27761-22755</Identity><TabName>Find in Files</TabName><Factory>Find-in-Files</Factory><Session/></Tab><Tab><Identity>TabID-13095-16835</Identity><TabName>Build</TabName><Factory>Build</Factory><Session/></Tab></Tabs><SelectedTab>1</SelectedTab></Wnd3></Windows>\r
+    <Editor>\r
+      \r
+      \r
+      \r
+      \r
+    <Pane><Tab><Factory>TextEditor</Factory><Filename>C:\home\kevin\pub\src\bc100\IAR\chargefunc.c</Filename><XPos>0</XPos><YPos>180</YPos><SelStart>6407</SelStart><SelEnd>6407</SelEnd></Tab><Tab><Factory>TextEditor</Factory><Filename>C:\home\kevin\pub\src\bc100\IAR\time.c</Filename><XPos>0</XPos><YPos>50</YPos><SelStart>2375</SelStart><SelEnd>2375</SelEnd></Tab><Tab><Factory>TextEditor</Factory><Filename>C:\home\kevin\pub\src\bc100\IAR\time.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>1547</SelStart><SelEnd>1547</SelEnd></Tab><Tab><Factory>TextEditor</Factory><Filename>C:\home\kevin\pub\src\bc100\IAR\Release\List\BC100_tiny.map</Filename><XPos>0</XPos><YPos>2034</YPos><SelStart>102104</SelStart><SelEnd>102104</SelEnd></Tab><Tab><Factory>TextEditor</Factory><Filename>C:\home\kevin\pub\src\bc100\IAR\Release\List\chargefunc.lst</Filename><XPos>0</XPos><YPos>121</YPos><SelStart>9296</SelStart><SelEnd>9296</SelEnd></Tab><ActiveTab>4</ActiveTab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>\r
+    <Positions>\r
+      \r
+      \r
+      \r
+      \r
+      \r
+    <Top><Row0><Sizes><Toolbar-014f2da8><key>iaridepm.enu1</key></Toolbar-014f2da8></Sizes></Row0></Top><Left><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>912</Bottom><Right>404</Right><x>-2</x><y>-2</y><xscreen>307</xscreen><yscreen>268</yscreen><sizeHorzCX>159896</sizeHorzCX><sizeHorzCY>231034</sizeHorzCY><sizeVertCX>211458</sizeVertCX><sizeVertCY>787931</sizeVertCY></Rect></Wnd2></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd3><Rect><Top>-2</Top><Left>-2</Left><Bottom>203</Bottom><Right>1922</Right><x>-2</x><y>-2</y><xscreen>1924</xscreen><yscreen>205</yscreen><sizeHorzCX>1002083</sizeHorzCX><sizeHorzCY>176724</sizeHorzCY><sizeVertCX>125000</sizeVertCX><sizeVertCY>176724</sizeVertCY></Rect></Wnd3></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>\r
+  </Desktop>\r
+</Workspace>\r
+\r
+\r
diff --git a/BaseTinyFirmware/IAR/statefunc.c b/BaseTinyFirmware/IAR/statefunc.c
new file mode 100644 (file)
index 0000000..e34994f
--- /dev/null
@@ -0,0 +1,421 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      State functions\r
+ *\r
+ *      Contains the functions related to the states defined in menu.h.\n\r
+ *      Also contains related functions, i.e. for checking jumpers, setting\r
+ *      error flags and "dozing".\r
+ *\r
+ *      \note The state function Charge() is in a separate file since it\r
+ *      should easily be changed with regard to battery type.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+#include <stdlib.h>\r
+\r
+#include "structs.h"\r
+#include "enums.h"\r
+\r
+#include "ADC.h"\r
+#include "statefunc.h"\r
+#include "battery.h"\r
+#include "charge.h"\r
+#include "main.h"\r
+#include "menu.h"\r
+#include "OWI.h"\r
+#include "PWM.h"\r
+#include "time.h"\r
+#include "USI.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+unsigned char ErrorFlags;  //!< \brief Holds error flags.\r
+                           //!< \note See statefunc.h for definitions of flags.\r
+\r
+//! \brief Holds the state in which latest error flag was set.\r
+//! \note See menu.h for definitions of states.\r
+unsigned char ErrorState;\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Initialization\r
+ *\r
+ * - Sets the system clock prescaler to 1 (run at 8 MHz)\r
+ * - Initializes the one-wire interface\r
+ * - Clears on-chip EEPROM\r
+ * - Sets battery enable pins as outputs, then disables batteries\r
+ * - Initializes SPI according to \ref SPIMODE\r
+ * - Initializes ADC\r
+ * - Initializes timers\r
+ * - Reads battery data from both battery inputs (via ADC)\r
+ * - Disables batteries again\r
+ * - Sets battery A as the current one (\ref BattActive = 0)\r
+ * - Clears ErrorFlags\r
+ *\r
+ * \param inp Not used.\r
+ *\r
+ * \retval ST_BATCON Next state in the sequence.\r
+ */\r
+unsigned char Initialize(unsigned char inp)\r
+{\r
+       unsigned char i, page;\r
+\r
+       // Disable interrupts while setting prescaler.\r
+       __disable_interrupt();\r
+       \r
+       CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
+       CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
+       \r
+       // Init 1-Wire(R) interface.\r
+       OWI_Init(OWIBUS);\r
+       \r
+       // Clear on-chip EEPROM.\r
+       for (page = 0; page < 4; page++)        {\r
+               for (i = 0; i < 32; i++) {\r
+                       BattEEPROM[page][i] = 0;\r
+               }\r
+       }\r
+\r
+       DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.\r
+       DisableBatteries();\r
+       SPI_Init(SPIMODE);\r
+       ADC_Init();\r
+       Time_Init();\r
+\r
+       // Attempt to get ADC-readings (also gets RID-data) from both batteries.\r
+       for (i = 0; i < 2; i++) {\r
+               EnableBattery(i);\r
+               ADC_Wait();\r
+               BatteryStatusRefresh();\r
+       }\r
+    \r
+       DisableBatteries();\r
+       \r
+       BattActive = 0;               // We have to start somewhere..\r
+       ErrorFlags = 0;\r
+       \r
+       // Init complete! Go to ST_BATCON next.\r
+       return(ST_BATCON);\r
+}\r
+\r
+\r
+/*! \brief Tests jumper settings and batteries, starts charging if necessary.\r
+ *\r
+ * First, JumperCheck() is called. If successful, the function checks if any\r
+ * valid batteries are connected and attempts to charge these, if necessary.\n\r
+ * If no charging is necessary, the charger goes to ST_SLEEP next.\n\r
+ * ST_ERROR is next if either JumperCheck() fails or there are no valid\r
+ * batteries. In this last case, the error is also flagged.\r
+ *\r
+ * \param inp Not used.\r
+ *\r
+ * \retval ST_ERROR Next state if either the jumper check failed, or there are\r
+ * no valid batteries.\r
+ * \retval ST_PREQUAL Next state if a battery is found to enabled and not fully\r
+ * charged.\r
+ * \retval ST_SLEEP Next state if battery/batteries are enabled and fully\r
+ * charged.\r
+ */\r
+unsigned char BatteryControl(unsigned char inp)\r
+{\r
+       unsigned char i;\r
+       \r
+       // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
+       if (!JumperCheck()) {\r
+               return(ST_ERROR);           // Error. Exit before damage is done!\r
+       }\r
+       \r
+       // If neither battery is valid, flag error and go to error state\r
+       if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
+               SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
+               \r
+               return(ST_ERROR);\r
+       }\r
+\r
+       // Get ADC-readings, try to read EPROM, and start prequalification\r
+       // of any uncharged battery.\r
+       for (i = 0; i < 2; i++) {\r
+               if (BattControl[i].Enabled) {      \r
+                       EnableBattery(i);\r
+                       ADC_Wait();\r
+\r
+                       if (BatteryStatusRefresh()) {\r
+                               if (!BattData.Charged) {\r
+                                       BatteryDataRefresh();\r
+\r
+                                       return(ST_PREQUAL);       \r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       // If we end up here, one or two batteries are found and fully charged.\r
+       // Disconnect, so we don't drain them, and go to sleep.\r
+       DisableBatteries();\r
+\r
+       return(ST_SLEEP);\r
+}\r
+\r
+\r
+/*! \brief Start running on batteries\r
+ *\r
+ * \todo Run on batteries, if battery voltage high enough.\r
+ * \todo Jump here when mains voltage drops below threshold\r
+ *\r
+ */\r
+unsigned char Discharge(unsigned char inp)\r
+{\r
+       return(ST_BATCON);  // Supply voltage restored, start charging\r
+}\r
+\r
+\r
+/*! \brief Sleeps until either battery needs charging\r
+ *\r
+ * Calls Doze(), then refreshes the status for both batteries on wakeup. If\r
+ * connected batteries are both charged, the function will loop. If not, it's\r
+ * back to ST_BATCON.\r
+ *\r
+ * \param inp Not used.\r
+ *\r
+ * \retval ST_BATCON Next state if a connected battery isn't fully charged.\r
+ */\r
+unsigned char Sleep(unsigned char inp)\r
+{\r
+       unsigned char i;\r
+\r
+       do {\r
+               Doze();               // Take a nap (~8 seconds).\r
+\r
+               // If any batteries need charging, go to ST_BATCON.\r
+               // Otherwise, keep sleeping.\r
+               for (i = 0; i < 2; i++) {\r
+                       EnableBattery(i);\r
+                       ADC_Wait();\r
+                       if ((BatteryStatusRefresh()) && (!BattData.Charged)) {\r
+                               return(ST_BATCON);\r
+                       }\r
+               }\r
+               \r
+               DisableBatteries();  // Disable both batteries before Doze()!\r
+       } while (TRUE);\r
+}\r
+\r
+\r
+/*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
+ *\r
+ * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
+ * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
+ * On wakeup, ADC is re-enabled.\r
+ */\r
+void Doze(void)\r
+{\r
+       // Wait for this ADC cycle to complete, then halt after the next one.\r
+       ADC_Wait();\r
+       ADCS.Halt = TRUE;\r
+       ADCS.Flag = FALSE;\r
+       \r
+       do {\r
+       } while (ADCS.Flag == FALSE);    \r
+       \r
+       WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
+       WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
+       MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
+       __sleep();                              // Go to sleep, wake up by WDT.\r
+       \r
+       __watchdog_reset();                     // Clear watchdog reset flag.\r
+       MCUSR &= ~(1<<WDRF);          \r
+       WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
+       WDTCR = 0;                              // Turn off watchdog.\r
+       \r
+       ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
+       ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
+       \r
+       // Wait for this cycle to complete.\r
+       ADC_Wait();                             \r
+}\r
+\r
+\r
+/*! \brief Handles errors\r
+ *\r
+ * Stops PWM output and disables batteries. The function then goes into a loop\r
+ * that starts with a call to Doze(), then attempts to handle each error. The\r
+ * loop will reiterate until all flags are cleared.\n\r
+ * The charger will reinitialize after this.\r
+ *\r
+ * Jumper errors are handled by clearing the flag, then calling JumperCheck().\r
+ * If unsuccessful, the error flag will now have been set again.\n\r
+ *\r
+ * If there are no valid batteries, the loop will simply reiterate until a\r
+ * valid battery is found. The error flag will then be cleared.\n\r
+ *\r
+ * In the case of PWM controller or battery temperature errors, the error\r
+ * flag is simply cleared. This is because the problem may have gone away during\r
+ * Doze(), or after reinitializing.\n\r
+ *\r
+ * If a battery is exhausted, we clear its exhausted-flag in \ref BattData,\r
+ * and change batteries before clearing the error flag.\r
+ *\r
+ * \param inp Not used.\r
+ */\r
+unsigned char Error(unsigned char inp)\r
+       {\r
+       unsigned char i;\r
+       \r
+       PWM_Stop();           // Stop charging.\r
+       DisableBatteries();   // Disable all loads.\r
+       \r
+       do {\r
+               Doze();           // Take a nap.\r
+\r
+               // For each bit in ErrorFlags, starting with LSB, handle\r
+               // associated error, if the flag is set.\r
+               for (i = 0x01; i!=0; i<<=1) {\r
+                       if(i & ErrorFlags) {\r
+                               switch (i) {\r
+                               \r
+                               case  ERR_JUMPER_MISMATCH:\r
+                                       // Clear flag & recheck.\r
+                                       ErrorFlags &= ~i;\r
+                                       JumperCheck();\r
+                               break;\r
+\r
+\r
+                               case  ERR_NO_BATTERIES_ENABLED:\r
+                                       // Clear if any battery gets enabled.\r
+                                       if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {\r
+                                                       ErrorFlags &= ~i;\r
+                                       }\r
+                               break;\r
+\r
+\r
+                               case  ERR_PWM_CONTROL:\r
+                                       // Clear flag.\r
+                                       ErrorFlags &= ~i;\r
+                               break;\r
+\r
+\r
+                               case  ERR_BATTERY_TEMPERATURE:\r
+                                       // Clear flag.\r
+                                       ErrorFlags &= ~i;\r
+                               break;\r
+\r
+\r
+                               case  ERR_BATTERY_EXHAUSTED:\r
+                                       // Try the other battery.\r
+                                       BattData.Exhausted = FALSE;\r
+                                       BattActive = (BattActive + 1) % 2;\r
+                                       ErrorFlags &= ~i;\r
+                               break;\r
+\r
+                                       \r
+                               default:\r
+                               break;\r
+                               }\r
+                       }\r
+               }\r
+       } while (ErrorFlags);\r
+\r
+       return(ST_INIT);\r
+}\r
+\r
+\r
+/*! \brief Sets the specified error-flag and saves the current state\r
+ *\r
+ * Updates \ref ErrorFlags and \ref ErrorState.\r
+ *\r
+ * \note Error flags are specified in statefunc.h.\r
+ *\r
+ * \param Flag Specifies what error to flag.\r
+ */\r
+void SetErrorFlag(unsigned char Flag)\r
+{\r
+       ErrorFlags |= Flag;\r
+       ErrorState = CurrentState;\r
+}\r
+\r
+\r
+/*! \brief Checks on-board jumpers.\r
+ *\r
+ * Checks on-board jumpers by disconnecting all loads, engaging the PWM and\r
+ * increasing the duty cycle until conditioned output voltage equals conditioned\r
+ * input voltage. At low PWM duty and no load buck output should be zero and,\r
+ * when increasing PWM duty, should quickly jump to steady state output roughly\r
+ * equal to input voltage. Will disable and leave disabled all batteries.\r
+ *\r
+ * \retval FALSE If jumper or load mismatch.\r
+ * \retval TRUE If everything OK.\r
+ */\r
+unsigned char JumperCheck(void)\r
+{\r
+        DisableBatteries();       // Disconnect, or loads may be destroyed!\r
+        \r
+        PWM_Start();              // Start PWM (controls the buck charger).\r
+       \r
+        // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
+        Time_Set(TIMER_GEN,0,1,0);\r
+       \r
+       do {\r
+               // If the PWM output voltage saturates the ADC, stop PWM output and\r
+               // report a failure.\r
+               if (ADCS.rawVBAT == 1023) {\r
+                       PWM_Stop();\r
+                       return(FALSE);\r
+               }\r
+\r
+               // If the absolute difference between measured (VIN - VBAT) and the\r
+               // typical value are below our set maximum, everything is OK.\r
+               if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
+                                    VIN_VBAT_DIFF_MAX ) {\r
+                                \r
+                       PWM_Stop();\r
+                       return(TRUE);\r
+               }\r
+\r
+               // Charge current is too high -> check load and jumper J405 and J406.\r
+               if (abs(ADCS.IBAT) > 100) {\r
+                       PWM_Stop();\r
+                       return(FALSE);\r
+               }\r
+\r
+               // If the PWM output can't be increased high enough -> check jumpers\r
+               // J400-J404, J407 and J408.\r
+               if (!PWM_IncrementDutyCycle()) {\r
+                       PWM_Stop();\r
+                       return(FALSE);\r
+               }\r
+               \r
+      // Wait for ADC conversions to complete\r
+               ADC_Wait();\r
+       } while (Time_Left(TIMER_GEN));\r
+       \r
+\r
+       // If we end up here, the measurements took too long.\r
+       PWM_Stop();\r
+       return(FALSE);\r
+}\r
diff --git a/BaseTinyFirmware/IAR/statefunc.h b/BaseTinyFirmware/IAR/statefunc.h
new file mode 100644 (file)
index 0000000..9594f44
--- /dev/null
@@ -0,0 +1,83 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Headerfile for statefunc.c\r
+ *\r
+ *      Contains definitions for SPI mode and error identifiers.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef STATEFUNC_H\r
+#define STATEFUNC_H\r
+\r
+\r
+//******************************************************************************\r
+// Wanted SPI-mode\r
+//******************************************************************************\r
+//! Sample on leading _rising_ edge, setup on trailing _falling_ edge.\r
+#define SPIMODE 0\r
+\r
+//! Sample on leading _falling_ edge, setup on trailing _rising_ edge.\r
+//#define SPIMODE 1    \r
+\r
+\r
+//******************************************************************************\r
+// Typical and maximum voltage difference between supply and battery\r
+//******************************************************************************\r
+//! Typical difference between VIN and VBAT, in mV.\r
+#define VIN_VBAT_DIFF_TYP     600\r
+\r
+//! Maximum allowed difference between VIN - VIN_VBAT_DIFF_TYP and VBAT, in mV.\r
+#define VIN_VBAT_DIFF_MAX     500\r
+\r
+\r
+//******************************************************************************\r
+// Error-flag bit identifiers\r
+//******************************************************************************\r
+//! Wrong jumper settings.\r
+#define   ERR_JUMPER_MISMATCH                          0x01  \r
+\r
+//! Both batteries disabled.\r
+#define   ERR_NO_BATTERIES_ENABLED             0x02  \r
+\r
+//! PWM output too much/little.\r
+#define   ERR_PWM_CONTROL                                      0x04  \r
+\r
+//! Battery temperature out of limits.\r
+#define   ERR_BATTERY_TEMPERATURE              0x08  \r
+\r
+//! Battery couldn't be charged.\r
+#define   ERR_BATTERY_EXHAUSTED                        0x10  \r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+unsigned char Initialize(unsigned char);\r
+unsigned char BatteryControl(unsigned char);\r
+unsigned char Discharge(unsigned char);\r
+unsigned char Sleep(unsigned char);\r
+void Doze(void);\r
+unsigned char Error(unsigned char);\r
+void SetErrorFlag(unsigned char);\r
+unsigned char JumperCheck(void);\r
+\r
+#endif // STATEFUNC_H\r
diff --git a/BaseTinyFirmware/IAR/structs.h b/BaseTinyFirmware/IAR/structs.h
new file mode 100644 (file)
index 0000000..9b80944
--- /dev/null
@@ -0,0 +1,102 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Structs in common for Slave and Master\r
+ *\r
+ *      Contains struct declarations for ADC.c and battery.c.\n\r
+ *      These are also used in the Master, and have therefore been\r
+ *      put in a separate file for convenience.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation:\r
+ *      For comprehensive code documentation, supported compilers, compiler\r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com \n\r
+ *\r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/structs.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+\r
+#ifndef STRUCTS_H\r
+#define STRUCTS_H\r
+\r
+\r
+//******************************************************************************\r
+// Battery struct declarations\r
+//******************************************************************************\r
+/*! \brief Holds status and various data for a battery\r
+ *\r
+ * These data are updated by BatteryStatusRefresh(), RIDLookUp(),\r
+ * NTCLookUp() and BatteryDataRefresh().\r
+ */\r
+struct Batteries_struct\r
+{\r
+       unsigned char Present   : 1; //!< Battery found. (TRUE/FALSE)\r
+       unsigned char Charged   : 1; //!< Battery fully charged. (TRUE/FALSE)\r
+       unsigned char Low       : 1; //!< Battery low voltage. (TRUE/FALSE)\r
+       unsigned char Exhausted : 1; //!< Battery exhausted. (TRUE/FALSE)\r
+       unsigned char HasRID            : 1; //!< Battery has resistor ID. (TRUE/FALSE)\r
+       unsigned char Circuit;       //!< Battery safety circuit (family id).\r
+       signed char Temperature;     //!< Battery temperature, in centigrade.\r
+       unsigned char ADCSteps;      //!< ADC steps per half degree.\r
+       unsigned int  Capacity;      //!< Capacity, in mAh.\r
+       unsigned int  MaxCurrent;    //!< Charge current, in mA.\r
+       unsigned int  MaxTime;       //!< Charge cut-off time, in minutes.\r
+       unsigned int  MinCurrent;    //!< Cut-off current, in mA.\r
+};\r
+typedef struct Batteries_struct Batteries_t; //!< For convenience.\r
+\r
+\r
+//! \brief Holds control data for a battery\r
+struct Battery_struct\r
+{\r
+       //! Battery valid, enabling allowed. (TRUE/FALSE)\r
+       unsigned char Enabled           : 1;\r
+       \r
+       //! Disconnect allowed. (TRUE/FALSE)\r
+       unsigned char DisconnectAllowed : 1;\r
+       \r
+       //! Inhibit charging. (TRUE/FALSE) \todo Changed by master?\r
+       unsigned char ChargeInhibit     : 1;\r
+};\r
+typedef struct Battery_struct Battery_t; //!< For convenience.\r
+\r
+\r
+//******************************************************************************\r
+// ADC status struct declaration\r
+//******************************************************************************\r
+/*! \brief Holds ADC-status and samples\r
+ *\r
+ * Is updated by ADC_ISR().\r
+ */\r
+struct ADC_Status_struct\r
+{\r
+       unsigned char MUX : 5;  //!< Corresponds to ADMUX low bits MUX4..0.\r
+       unsigned char Flag : 1;  //!< ADC cycle complete (TRUE/FALSE).\r
+       unsigned char Mains : 1;  //!< Mains OK? (TRUE/FALSE).\r
+       unsigned char Halt : 1;  //!< Stop A/D-conversions (TRUE/FALSE).\r
+       unsigned char ADC3_G20_OS : 4;  //!< Offset on ADC3 at 20x gain.\r
+       unsigned char ADC5_G20_OS : 4;  //!< Offset on ADC5 at 20x gain.\r
+       unsigned int rawRID;  //!< Raw, unconditioned resistor ID data.\r
+       unsigned int rawNTC;  //!< Raw, unconditioned thermistor data.\r
+       unsigned int rawVBAT;  //!< Raw, unconditioned battery voltage.\r
+       unsigned int VIN;  //!< Supply voltage, in mV.\r
+       unsigned int VBAT;  //!< Battery voltage, in mV.\r
+       signed int IBAT;  //!< Battery current, in mA.\r
+       signed int discIBAT[4];  //!< Discrete battery current readings, in mA.\r
+       signed int avgIBAT;  //!< Average of the last four IBAT readings, in mA.\r
+};\r
+typedef struct ADC_Status_struct ADC_Status_t; //!< For convenience.\r
+\r
+\r
+#endif // STRUCTS_H\r
diff --git a/BaseTinyFirmware/IAR/time.c b/BaseTinyFirmware/IAR/time.c
new file mode 100644 (file)
index 0000000..7017517
--- /dev/null
@@ -0,0 +1,162 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Functions for timing\r
+ *\r
+ *      Contains functions to initialize, set, poll and stop timers.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100 \n\r
+ *      AVR463: Charging NiMH Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2299 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $\r
+ * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#include <ioavr.h>\r
+#include <inavr.h>\r
+\r
+#include "enums.h"\r
+\r
+#include "main.h"\r
+#include "time.h"\r
+\r
+\r
+//******************************************************************************\r
+// Variables\r
+//******************************************************************************\r
+unsigned long timeval[TIMERS];  //!< Contains the values for each timer.\r
+\r
+// timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms \r
+//#pragma vector = TIM0_OVF_vect\r
+\r
+\r
+//******************************************************************************\r
+// Functions\r
+//******************************************************************************\r
+/*! \brief Interrupt service routine for timer 0 overflow\r
+ *\r
+ * Timer 0 runs at 125 kHz and compare match will occur every millisecond\r
+ * (125 / 125 kHz = 1.0 ms), which will result in a call to this function.\r
+ * When called, this function will decrement the time left for each timer,\r
+ * unless they are already at zero.\r
+ */\r
+#pragma vector = TIM0_COMPA_vect\r
+__interrupt void TICK_ISR(void)\r
+{\r
+       unsigned char i;\r
+\r
+       // 1 ms has passed, decrement all non-zero timers.\r
+       for (i = 0; i < TIMERS; i++) {\r
+               if(timeval[i] > 0) {\r
+                       timeval[i]--;\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Checks if a specified timer has expired\r
+ *\r
+ * \param timer Specifies timer\r
+ *\r
+ * \retval TRUE Timer still going.\r
+ * \retval FALSE Timer has expired.\r
+ */ \r
+unsigned char Time_Left(unsigned char timer)\r
+{\r
+       if(timeval[timer] > 0) {\r
+               return(TRUE);\r
+       } else {\r
+               return(FALSE);\r
+       }\r
+}\r
+\r
+\r
+/*! \brief Sets the specified timer\r
+ *\r
+ * \param timer Specifies timer\r
+ * \param min Minutes for timer to count down\r
+ * \param sec Seconds for timer to count down\r
+ * \param ms Milliseconds for timer to count down\r
+ */\r
+void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+                                 unsigned char ms)\r
+{\r
+//     timeval[i] = 4 * (1000*(sec + 60*min) + ms);   // about 4000 ticks per second\r
+//     timeval[i] = 240000 * (unsigned long)min;\r
+//     timeval[i] += 4000 * (unsigned long)sec;\r
+//     timeval[i] += 4 * (unsigned long)ms;\r
+\r
+       timeval[timer] = 60000 * (unsigned long)min;\r
+       timeval[timer] += 1000 * (unsigned long)sec;\r
+       timeval[timer] += 1 * (unsigned long)ms;\r
+}\r
+\r
+\r
+/*! \brief Stops timers\r
+ *\r
+ * Sets timer0's clock source to none.\r
+ */\r
+void Time_Stop(void)\r
+{\r
+       TCCR0B = 0;\r
+}\r
+\r
+\r
+/*! \brief Starts timers\r
+ *\r
+ * Sets timer0's clock source to system clock divided by 64.\r
+ */\r
+void Time_Start(void)\r
+{\r
+       TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+}\r
+\r
+\r
+/*! \brief Initializes timers\r
+ *\r
+ * Resets all the timer values to 0, then sets up timer 0 for a compare match\r
+ * every millisecond.\r
+ */\r
+void Time_Init(void)\r
+{\r
+       unsigned char i;\r
+       \r
+       for (i = 0; i<<TIMERS; i++)     {\r
+               timeval[i] = 0;\r
+       }\r
+\r
+       //    OCR0A = 0;  // Doesn't matter, will run in normal mode.\r
+       \r
+       OCR0A = 125;  // Will give a compare match every ms.\r
+       \r
+       OCR0B = 0;  // Doesn't matter, will run in normal mode.\r
+\r
+               //    TCCR0A = 0;  // Normal 8-bit mode, no input capture.\r
+\r
+       TCCR0A = (1<<WGM00);  // 8-bit CTC mode.\r
+       \r
+       //    TCCR0B = (0<<CS02)|(1<<CS01)|(0<<CS00);  // CLKT0 = CLK/8 = 1 MHz.\r
+       \r
+       TCCR0B = (0<<CS02)|(1<<CS01)|(1<<CS00);         // CLKT0 = CLK/64 = 125 kHz.\r
+\r
+       //    TIMSK |= (1<<TOIE0);      // Overflow interrupt enabled.\r
+\r
+       TIMSK |= (1<<OCIE0A);  // Timer 0, Compare match A interrupt enabled.\r
+\r
+       // Enable interrupts, just in case they weren't already.\r
+       __enable_interrupt();       \r
+}\r
diff --git a/BaseTinyFirmware/IAR/time.h b/BaseTinyFirmware/IAR/time.h
new file mode 100644 (file)
index 0000000..2cb5a62
--- /dev/null
@@ -0,0 +1,51 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/\r
+/*! \file *********************************************************************\r
+ *\r
+ * \brief\r
+ *      Header file for time.c\r
+ *\r
+ *      Contains definitions of the number of timers used and their names.\r
+ *\r
+ * \par Application note:\r
+ *      AVR458: Charging Li-Ion Batteries with BC100\r
+ *\r
+ * \par Documentation\r
+ *      For comprehensive code documentation, supported compilers, compiler \r
+ *      settings and supported devices see readme.html\r
+ *\r
+ * \author\r
+ *      Atmel Corporation: http://www.atmel.com \n\r
+ *      Support email: avr@atmel.com\r
+ *\r
+ * \r
+ * $Name$\r
+ * $Revision: 2261 $\r
+ * $RCSfile$\r
+ * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.h $\r
+ * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n\r
+ ******************************************************************************/\r
+\r
+#ifndef TIME_H\r
+#define TIME_H\r
+\r
+\r
+//******************************************************************************\r
+// Globals\r
+//******************************************************************************\r
+extern unsigned long timeval[];  // Needed for SPI transfer.\r
+\r
+\r
+//******************************************************************************\r
+// Function prototypes\r
+//******************************************************************************\r
+#pragma vector = TIM0_COMPA_vect\r
+__interrupt void TICK_ISR(void);\r
+\r
+unsigned char Time_Left(unsigned char timer);\r
+void Time_Set(unsigned char timer, unsigned int min, unsigned char sec,\r
+                                 unsigned char ms);\r
+void Time_Stop(void);\r
+void Time_Start(void);\r
+void Time_Init(void);\r
+\r
+#endif // TIME_H\r
diff --git a/BaseTinyFirmware/README b/BaseTinyFirmware/README
new file mode 100644 (file)
index 0000000..f4b04eb
--- /dev/null
@@ -0,0 +1,7 @@
+This is the firmware for the ATTiny controllers on the Atmel BC100\r
+development board. Current, the project files are designed to compile\r
+for the ATTiny861 microcontroller.\r
+\r
+The firmware is based on Atmel's IAR firmware code with a port to\r
+GCC. See README.GCC for more information about the GCC port.\r
+\r
diff --git a/BaseTinyFirmware/README.GCC b/BaseTinyFirmware/README.GCC
new file mode 100644 (file)
index 0000000..06d9344
--- /dev/null
@@ -0,0 +1,6 @@
+The initial port from IAR to GCC was performed on March 12, 2008 based\r
+on code provided by Atmel with an release date of September 4, 2007.\r
+\r
+A log of changes to the GCC code is in the file GCC/ChangeLog\r
+\r
+Please send updates or comments to Kevin Rosenberg <kevin@rosenberg.net>\r
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..937e017
--- /dev/null
+++ b/README
@@ -0,0 +1,15 @@
+This project contains code for Atmel's BC100 development board.\r
+\r
+The initial code in this project is located in the BaseTinyFirmware\r
+directory. That code is based on Atmel's original firmware for the\r
+ATTiny controller on the BC100.\r
+\r
+Other firmware versions developed will be located in other\r
+subdirectories and their contents will be listed in this file.\r
+\r
+The web site for future updates for this package is \r
+http://www.avrcode.com/bc100/\r
+\r
+Kevin Rosenberg <kevin@rosenberg.net>\r
+Fri, 14 Mar 2008 09:38:08 -0600\r
+\r