From: Kevin Rosenberg Date: Fri, 14 Mar 2008 15:39:54 +0000 (-0600) Subject: Initial import X-Git-Url: http://git.kpe.io/?p=avr_bc100.git;a=commitdiff_plain;h=5b95e754a4af80c7389486ee874ac07c166a0867 Initial import --- 5b95e754a4af80c7389486ee874ac07c166a0867 diff --git a/BaseTinyFirmware/GCC/ADC.c b/BaseTinyFirmware/GCC/ADC.c new file mode 100644 index 0000000..004ba8d --- /dev/null +++ b/BaseTinyFirmware/GCC/ADC.c @@ -0,0 +1,426 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for use of ADC + * + * Contains high level functions for initializing the ADC, interrupt + * handling, and treatment of samples.\n + * The ADC is set to free running mode and uses an external reference + * voltage.\n + * To make all sampling take at least 25 clock cycles the ADC is stopped + * and restarted by the ISR. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include + +#include "structs.h" + +#include "main.h" +#include "ADC.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +// ADC status struct. +//! \brief Holds sampled data and ADC-status +ADC_Status_t ADCS; + + +/*! \brief Indicates maximum battery voltage. + * + * This variable is stored in EEPROM and indicates how much the battery voltage + * is downscaled by HW before it is sampled. The amount of downscaling depends + * on the maximum battery voltage, and is necessary to avoid saturation of the + * ADC (reference voltage is 2.5 V). + * + * \note Used by the ADC ISR when calling ScaleU() and ScaleI(). + * + * \note Defaults to 1, which means 10 V max battery voltage. + * + * \note Table of settings: + *
+ * VBAT_RANGE | Max battery voltage | Jumper setting
+ *         0  |             5V      |        1/2
+ *         1  |            10V      |        1/4
+ *         2  |            20V      |        1/8
+ *         3  |            30V      |       1/12
+ *         4  |            40V      |       1/16
+ * 
+ */ +// Maximum battery voltage (affects scaling of samples). +unsigned char EEMEM VBAT_RANGE = 1; + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Interrupt Service routine for ADC. + * + * This ISR stores the sampled values in the ADC status-struct, then + * updates the ADC MUX to the next channel in the scanning-sequence.\n + * Once the sequence is completed, ADCS.Flag is set and unless + * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC + * is disabled.\n + * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. + * + * \note Table of scanning sequence: + *
+ * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed
+ * ----+--------+----------+----------+------+---------+-------
+ *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no
+ *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no
+ *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no
+ *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no
+ *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no
+ *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no
+ *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no
+ *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes
+ * 
+ * + * \todo IIN (#7 in sequence) is never used. + * + * \todo Signed is never set. Signed measurements of IBAT will halve the + * measuring sensitivity, and is therefore not favourable. At the moment, + * great currents (f.ex. if something happens with the battery) will be + * interpreted as negative, which might cause unfavourable behaviour during + * charging (depending on what PWM behaviour is defined), f.ex. + * ConstantCurrent() will keep increasing the PWM output. This results in an + * PWM controller error being flagged and the program going into + * error-state and eventually reinitializing. + */ +ISR(ADC_vect) +{ + static unsigned char avgIndex = 0; + unsigned char i, Next, Signed; + signed int temp = 0; + + Signed = FALSE; // Presume next conversion is unipolar. + ADCSRA &= ~(1< ADC1 (PA1) = NTC + case 0x01: + ADCS.rawNTC = ADC; + Next=0x02; + break; + + + // MUX = 0b000010 => ADC2 (PA2) = RID + case 0x02: + ADCS.rawRID = ADC; + Next=0x03; + break; + + + // MUX = 0b000011 => ADC3 (PA4) = VIN- + case 0x03: + // Supply voltage is always divided by 16. + ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short. + + // Is mains failing? + if (ADCS.VIN < VIN_MIN) { + ADCS.Mains = FALSE; + } else { + ADCS.Mains = TRUE; + } + + Next=0x05; + break; + + + // MUX = 0b000101 => ADC5 (PA6) = VBAT- + case 0x05: + ADCS.rawVBAT = ADC; + + // Scale voltage according to jumper setting. + ADCS.VBAT = ScaleU(eeprom_read_byte(&VBAT_RANGE), (unsigned int)ADC); // ADC is a short. + Next=0x17; +// Signed = TRUE; // Next conversion is bipolar. Halves sensitivity! + break; + + + case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT + // If bipolar, from -512 to 0, to 511: + // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF + + // Scale sample according to jumper setting, handle negative numbers. + if (ADC > 511) { + ADCS.IBAT = -(signed int)ScaleI(eeprom_read_byte(&VBAT_RANGE), + (1024 - (ADC-ADCS.ADC5_G20_OS))); + } else if (ADC > 0) { + ADCS.IBAT = ScaleI(eeprom_read_byte(&VBAT_RANGE), (ADC-ADCS.ADC5_G20_OS)); + } else { + ADCS.IBAT = 0; + } + + // Insert sample of battery current into the averaging-array + // (overwriting the oldest sample), then recalculate and store the + // average. This is the last conversion in the sequence, so + // flag a complete ADC-cycle and restart sequence. + ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT; + for (i = 0; i < 4 ; i++) { + temp += ADCS.discIBAT[i]; + } + + ADCS.avgIBAT = (temp / 4); + + ADCS.Flag = TRUE; + Next=0x01; + Signed = FALSE; // This is the only bipolar conversion. + break; + + + default: // Should not happen. (Invalid MUX-channel) + Next=0x01; // Start at the beginning of sequence. + break; + } + + // Update MUX to next channel in sequence, set a bipolar conversion if + // this has been flagged. + ADCS.MUX = Next; + ADMUX = (1< + * Presume VREF = 2.5V and Gain = 1x. + * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB + * setting | source | R1 | R2/(R1+R2) | UADC(LSB) | U(MAX) + * --------+--------+------+------------+-----------+------- + * N/A | | - | - | 2.441mV | 2.50V + * 0 | VBAT | 10k | 1/2 | 4.883mV | 5.00V + * 1 | VBAT | 30k | 1/4 | 9.766mV | 9.99V + * 2 | VBAT | 70k | 1/8 | 19.53mV | 19.98V + * 3 | VBAT | 110k | 1/12 | 29.30mV | 29.97V + * 4 | VBAT | 150k | 1/16 | 39.06mV | 39.96V + * 4 | VIN | 150k | 1/16 | 39.06mV | 39.96V + * + */ +unsigned int ScaleU(unsigned char setting, unsigned int data) +{ + // Temporary variable needed. + unsigned int scaled = 0; + + // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16 + if (setting == 3) { + scaled = 29 * data; + scaled += (data >> 2); + scaled += (data >> 4); + } else { + // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16 + scaled = 39 * data; + scaled += (data >> 4); + + if (setting <3) { + // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8 + // 1: mV/LSB = 9.766 = 39.06 / 4 + // 2: mV/LSB = 19.53 = 39.06 / 2 + scaled = (scaled >> (3-setting)); + } + } + + return(scaled); +} + + +/*! \brief Scales sample to represent "actual current" in mA. + * + * This function returns the actual sampled current, scaled according + * to the jumper settings. + * + * \param setting Indicates what downscaling was used. + * \param data The sampled value. + * + * \note Table for setting-parameter:\n + *
+ * Presume VREF = 2.5V and Gain = 1x or 20x.
+ * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
+ * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
+ * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain
+ * --------+------+------------+----------+----------+--------+-----
+ *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x
+ *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x
+ *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x
+ *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x
+ *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x
+ *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x
+ *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x
+ * 
+ */ +unsigned int ScaleI(unsigned char setting, unsigned int data) +{ + // Temporary variable needed. + unsigned int scaled = 0; + + // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128 + if (setting == 3) { + scaled = 21 * data; + scaled -= (data >> 4); + scaled += (data >> 7); + } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32 + scaled = 28 * data; + scaled -= (data >> 3); + scaled += (data >> 5); + + if (setting <3) { + // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8 + // 1: mA/LSB = 6.978mA = 27.909 / 4 + // 2: mA/LSB = 13.955mA = 27.909 / 2 + scaled = (scaled >> (3-setting)); + } + } + + return(scaled); +} + + +/*! \brief Waits for two full cycles of ADC-conversions to occur. + * + * This function clears the cycle complete-flag, then waits for it to be set + * again. This is then repeated once before the function exits. + * + */ +void ADC_Wait(void) +{ + // Clear ADC flag and wait for cycle to complete. + ADCS.Flag = FALSE; + do { + } while (ADCS.Flag == FALSE); + + // Repeat, so we are sure the data beong to the same cycle. + ADCS.Flag = FALSE; + do { + } while (ADCS.Flag == FALSE); +} + + +/*! \brief Initializes ADC and input pins. + * + * This function initializes the ADC to free running mode, sampling from + * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n + * It also measures and stores calibration data for offset. + * + * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway. + * + * \note Table of MUX settings for offset measurement: + *
+ *    Ch | Pin |    Gain |    MUX
+ * ------+-----+---------+-------
+ *  ADC1 | PA1 |     20x | 001101
+ *  ADC3 | PA4 |     20x | 010001
+ *  ADC5 | PA6 |     20x | 010110
+ *  ADC9 | PB6 |     20x | 011011
+ *  ADC0 | PA0 | 20x/32x | 111000
+ *  ADC0 | PA0 |   1x/8x | 111001
+ *  ADC1 | PA1 | 20x/32x | 111010
+ *  ADC2 | PA2 | 20x/32x | 111011
+ *  ADC4 | PA5 | 20x/32x | 111100
+ *  ADC5 | PA6 | 20x/32x | 111101
+ *  ADC6 | PA7 | 20x/32x | 111110
+ * 
+ */ +void ADC_Init(void) +{ + unsigned char i; + + cli(); + + ADCS.Halt = FALSE; // Enable consecutive runs of ADC. + + // Configure ADC pins (inputs and disabled pull-ups). + DDRA &= ~((1< + +//****************************************************************************** +// ADC setup +//****************************************************************************** +// 8MHz / (25x128) = 2500 samples/s/ch +#define ADC_PRESCALER 0x07 +/*!< \brief Prescaling of ADC clock. + * + * The ADC will run at 8 MHz (system clock) divided by 128 + * (prescaler), and every sample will takes approximately 25 ticks: + * Sample rate = 8 MHz / (128 * 25 cycles/sample) = 2.5 k samples/sec + */ + + +//****************************************************************************** +// Minimum supply voltage +//****************************************************************************** +//! Minimum supply voltage (at TP101 = VIN+), in mV. +#define VIN_MIN 4400 + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern unsigned char EEMEM VBAT_RANGE; +extern ADC_Status_t ADCS; + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned int ScaleU(unsigned char setting, unsigned int data); +unsigned int ScaleI(unsigned char setting, unsigned int data); +void ADC_Wait(void); +void ADC_Init(void); + +#endif // ADC_H + diff --git a/BaseTinyFirmware/GCC/ChangeLog b/BaseTinyFirmware/GCC/ChangeLog new file mode 100644 index 0000000..93703b7 --- /dev/null +++ b/BaseTinyFirmware/GCC/ChangeLog @@ -0,0 +1,3 @@ +2008-03-12 Kevin Rosenberg + * Initial GCC port performed and compiles without error + * Warning: Not yet tested on BC100 hardware! diff --git a/BaseTinyFirmware/GCC/LIIONspecs.h b/BaseTinyFirmware/GCC/LIIONspecs.h new file mode 100644 index 0000000..e662b1e --- /dev/null +++ b/BaseTinyFirmware/GCC/LIIONspecs.h @@ -0,0 +1,102 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Li-Ion specifications + * + * Contains example definitions of Li-Ion battery specifications. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONspecs.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef LIIONSPECS_H +#define LIIONSPECS_H + + +//****************************************************************************** +// Cell limits +//****************************************************************************** +// This is for common NiMH batteries. +#define CELL_VOLTAGE_SAFETY 0 /*!< \brief Buffer for unmatched batteries. + * + * If we are charging a multicell battery and the cells aren't matched, we + * may risk overcharging at least one. Therefore, we may subtract this constant + * per additional cell in battery to allow for a "buffer". + * + * \note Set to 0 if batteries are properly matched. + * + * \note If this is changed to something higher than (CELL_VOLTAGE_MAX - + * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit + * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause + * the charger to keep trying to charge, but instantly finishing because + * the battery voltage is already at max. + */ +//! Maximum charge voltage for cell, in mV. +#define CELL_VOLTAGE_MAX 4200 + +//! Minimum voltage to consider cell charged at, in mV. +#define CELL_VOLTAGE_LOW 4050 + +//! Minimum voltage to start charging at, in mV. +#define CELL_VOLTAGE_MIN 2750 + +//! Target voltage during prequalification, in mV. +#define CELL_VOLTAGE_PREQUAL 3000 + + +//****************************************************************************** +// Battery limits +//****************************************************************************** +// Battery-definitions. +//! Number of cells in battery. +#define BAT_CELL_NUMBER 1 + +//! Maximum cell temperature (Celsius). +#define BAT_TEMPERATURE_MAX 45 + +//! Minimum Cell temperature (Celsius). +#define BAT_TEMPERATURE_MIN 0 + +//! Maximum time for prequalification, in minutes. +#define BAT_TIME_PREQUAL 9 + +//! \brief Constant charge current, in mA, during prequalification mode. +//! \note This is typically lower than the main charge current. +#define BAT_CURRENT_PREQUAL 150 + +//! Charge current hysteresis, in mA. +#define BAT_CURRENT_HYST 5 + +//! Charge voltage hysteresis, in mV. +#define BAT_VOLTAGE_HYST 10 + +//! Maximum battery voltage, in mV. +#define BAT_VOLTAGE_MAX (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \ + ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY) + +//! Minimum voltage, in mV, to consider battery charged. +#define BAT_VOLTAGE_LOW (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER) + +//! Minimum voltage, in mV, to consider battery safe to charge. +#define BAT_VOLTAGE_MIN (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER) + +//! Charge voltage to achieve, in mV, during prequalification mode. +#define BAT_VOLTAGE_PREQUAL (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER) + +#endif // LIIONSPECS_H diff --git a/BaseTinyFirmware/GCC/NIMHspecs.h b/BaseTinyFirmware/GCC/NIMHspecs.h new file mode 100644 index 0000000..cd27677 --- /dev/null +++ b/BaseTinyFirmware/GCC/NIMHspecs.h @@ -0,0 +1,108 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * NiMH specifications + * + * Contains example definitions of NiMH battery specifications. + * + * \par Application note: + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2255 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHspecs.h $ + * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n + ******************************************************************************/ + +#ifndef NIMHSPECS_H +#define NIMHSPECS_H + + +//****************************************************************************** +// Cell limits +//****************************************************************************** +// This is for common NiMH batteries. +#define CELL_VOLTAGE_SAFETY 0 /*!< \brief Buffer for unmatched batteries. + * + * If we are charging a multicell battery and the cells aren't matched, we + * may risk overcharging at least one. Therefore, we may subtract this constant + * per additional cell in battery to allow for a "buffer". + * + * \note Set to 0 if batteries are properly matched. + * + * \note If this is changed to something higher than (CELL_VOLTAGE_MAX - + * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit + * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause + * the charger to keep trying to charge, but instantly finishing because + * the battery voltage is already at max. + */ +//! Maximum charge voltage for cell, in mV. +#define CELL_VOLTAGE_MAX 1600 + +//! Minimum voltage to consider cell charged at, in mV. +#define CELL_VOLTAGE_LOW 1350 + +//! Minimum voltage to start charging at, in mV. +#define CELL_VOLTAGE_MIN 800 + +//! Target voltage during prequalification, in mV. +#define CELL_VOLTAGE_PREQUAL 1000 + +//! Cell voltage drop when full charge is achieved. +#define CELL_VOLTAGE_DROP 15 + + +//****************************************************************************** +// Battery limits +//****************************************************************************** +// Battery-definitions. +//! Number of cells in battery. +#define BAT_CELL_NUMBER 3 + +//! Maximum cell temperature (Celsius). +#define BAT_TEMPERATURE_MAX 50 + +//! Minimum Cell temperature (Celsius). +#define BAT_TEMPERATURE_MIN 5 + +//! Maximum time for prequalification, in minutes. +#define BAT_TIME_PREQUAL 2 + +//! \brief Constant charge current, in mA, during prequalification mode. +//! \note This is typically lower than the main charge current. +#define BAT_CURRENT_PREQUAL 150 + +//! Charge current hysteresis, in mA. +#define BAT_CURRENT_HYST 3 + +//! Charge voltage hysteresis, in mV. +#define BAT_VOLTAGE_HYST 10 + +//! Maximum battery voltage, in mV. +#define BAT_VOLTAGE_MAX (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \ + ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY) + +//! Minimum voltage, in mV, to consider battery charged. +#define BAT_VOLTAGE_LOW (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER) + +//! Minimum voltage, in mV, to consider battery safe to charge. +#define BAT_VOLTAGE_MIN (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER) + +//! Voltage drop, in mV, when full charge is achieved. +#define BAT_VOLTAGE_DROP (CELL_VOLTAGE_DROP * BAT_CELL_NUMBER) + +//! Charge voltage to achieve, in mV, during prequalification mode. +#define BAT_VOLTAGE_PREQUAL (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER) + +#endif // NIMHSPECS_H diff --git a/BaseTinyFirmware/GCC/OWI.c b/BaseTinyFirmware/GCC/OWI.c new file mode 100644 index 0000000..ef741b9 --- /dev/null +++ b/BaseTinyFirmware/GCC/OWI.c @@ -0,0 +1,524 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ******************************************************************** + * + * \brief + * Functions for 1-Wire(R) bus communication + * + * High level functions for transmission of full bytes on the 1-Wire(R) + * bus and implementations of ROM commands.\n + * Polled software only implementation of the basic bit-level signalling + * in the 1-Wire(R) protocol.\n + * Includes functions for computing and checking CRC8 & 16 values of data + * sets, and of 64 bit ROM identifiers. + * Supported devices: All AVRs. + * + * \par Application Note: + * AVR458: Charging Li-Ion Batteries with BC100\n + * AVR463: Charging NiMH Batteries with BC100\n + * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +****************************************************************************/ + +#include +#include + +// define F_CPU for delay_x_cyles +#define F_CPU ((CPU_FREQUENCY) * 1000000) +#include "delay_x_gcc.h" + +#include "OWI.h" + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Initialization of the one wire bus(es). (Software only driver) + * + * This function initializes the 1-Wire bus(es) by releasing it and + * waiting until any presence signals are finished. + * + * \param pins A bitmask of the buses to initialize. + */ +void OWI_Init(unsigned char pins){ + OWI_RELEASE_BUS(pins); + // The first rising edge can be interpreted by a slave as the end of a + // Reset-pulse. Delay for the required reset recovery time (H) to be + // sure that the real reset is interpreted correctly. + _delay_cycles(OWI_DELAY_H_STD_MODE); +} + + +/*! \brief Write a '1' bit to the bus(es). (Software only driver) + * + * Generates the waveform for transmission of a '1' bit on the 1-Wire + * bus. + * + * \param pins A bitmask of the buses to write to. + */ +void OWI_WriteBit1(unsigned char pins){ + unsigned char intState; + + // Disable interrupts. + intState = SREG & SREG_I; + cli(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + _delay_cycles(OWI_DELAY_A_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + _delay_cycles(OWI_DELAY_B_STD_MODE); + + // Restore interrupts. + if (intState) + sei(); +} + +/*! \brief Write a '0' to the bus(es). (Software only driver) + * + * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) + * bus. + * + * \param pins A bitmask of the buses to write to. + */ +void OWI_WriteBit0(unsigned char pins) +{ + unsigned char intState; + + // Disable interrupts. + intState = SREG & SREG_I; + cli(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + _delay_cycles(OWI_DELAY_C_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + _delay_cycles(OWI_DELAY_D_STD_MODE); + + // Restore interrupts. + if (intState) + sei(); +} + +/*! \brief Read a bit from the bus(es). (Software only driver) + * + * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). + * + * \param pins A bitmask of the bus(es) to read from. + * + * \return A bitmask of the buses where a '1' was read. + */ +unsigned char OWI_ReadBit(unsigned char pins) +{ + unsigned char intState; + unsigned char bitsRead; + + // Disable interrupts. + intState = SREG & SREG_I; + cli(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + _delay_cycles(OWI_DELAY_A_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + _delay_cycles(OWI_DELAY_E_STD_MODE); + + // Sample bus and delay. + bitsRead = OWI_PIN & pins; + _delay_cycles(OWI_DELAY_F_STD_MODE); + + // Restore interrupts. + if (intState) + sei(); + + return bitsRead; +} + + +/*! \brief Send a Reset signal and listen for Presence signal. (software + * only driver) + * + * Generates the waveform for transmission of a Reset pulse on the + * 1-Wire(R) bus and listens for presence signals. + * + * \param pins A bitmask of the buses to send the Reset signal on. + * + * \return A bitmask of the buses where a presence signal was detected. + */ +unsigned char OWI_DetectPresence(unsigned char pins) +{ + unsigned char intState; + unsigned char presenceDetected; + + // Disable interrupts. + intState = SREG & SREG_I; + cli(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + _delay_cycles(OWI_DELAY_H_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + _delay_cycles(OWI_DELAY_I_STD_MODE); + + // Sample bus to detect presence signal and delay. + presenceDetected = ((~OWI_PIN) & pins); + _delay_cycles(OWI_DELAY_J_STD_MODE); + + // Restore interrupts. + if (intState) + sei(); + + return presenceDetected; +} + + +/*! \brief Sends one byte of data on the 1-Wire(R) bus(es). + * + * This function automates the task of sending a complete byte + * of data on the 1-Wire bus(es). + * + * \param data The data to send on the bus(es). + * + * \param pins A bitmask of the buses to send the data to. + */ +void OWI_SendByte(unsigned char data, unsigned char pins) +{ + unsigned char temp; + unsigned char i; + + // Do once for each bit + for (i = 0; i < 8; i++) { + // Determine if LSB is '0' or '1' and transmit corresponding + // waveform on the bus. + temp = data & 0x01; + + if (temp) { + OWI_WriteBit1(pins); + } else { + OWI_WriteBit0(pins); + } + + data >>= 1; // Right shift the data to get next bit. + } +} + + +/*! \brief Receives one byte of data from the 1-Wire(R) bus. + * + * This function automates the task of receiving a complete byte + * of data from the 1-Wire bus. + * + * \param pin A bitmask of the bus to read from. + * + * \return The byte read from the bus. + */ +unsigned char OWI_ReceiveByte(unsigned char pin) +{ + unsigned char data; + unsigned char i; + + // Clear the temporary input variable. + data = 0x00; + + // Do once for each bit + for (i = 0; i < 8; i++) { + // Shift temporary input variable right. + data >>= 1; + + // Set the MSB if a '1' value is read from the bus. + // Leave as it is ('0') else. + if (OWI_ReadBit(pin)) { + data |= 0x80; + } + } + + return data; +} + + +/*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). + * + * \param pins A bitmask of the buses to send the SKIP ROM command to. + */ +void OWI_SkipRom(unsigned char pins) +{ + // Send the SKIP ROM command on the bus. + OWI_SendByte(OWI_ROM_SKIP, pins); +} + + +/*! \brief Sends the READ ROM command and reads back the ROM id. + * + * \param romValue A pointer where the id will be placed. + * + * \param pin A bitmask of the bus to read from. + */ +void OWI_ReadRom(unsigned char * romValue, unsigned char pin) +{ + unsigned char bytesLeft = 8; + + // Send the READ ROM command on the bus. + OWI_SendByte(OWI_ROM_READ, pin); + + // Do 8 times. + while (bytesLeft > 0) { + // Place the received data in memory. + *romValue++ = OWI_ReceiveByte(pin); + bytesLeft--; + } +} + + +/*! \brief Sends the MATCH ROM command and the ROM id to match against. + * + * \param romValue A pointer to the ID to match against. + * + * \param pins A bitmask of the buses to perform the MATCH ROM command on. + */ +void OWI_MatchRom(unsigned char * romValue, unsigned char pins) +{ + unsigned char bytesLeft = 8; + + // Send the MATCH ROM command. + OWI_SendByte(OWI_ROM_MATCH, pins); + + // Do once for each byte. + while (bytesLeft > 0) { + // Transmit 1 byte of the ID to match. + OWI_SendByte(*romValue++, pins); + bytesLeft--; + } +} + + +/*! \brief Sends the SEARCH ROM command and returns 1 id found on the + * 1-Wire(R) bus. + * + * \param bitPattern A pointer to an 8 byte char array where the + * discovered identifier will be placed. When + * searching for several slaves, a copy of the + * last found identifier should be supplied in + * the array, or the search will fail. + * + * \param lastDeviation The bit position where the algorithm made a + * choice the last time it was run. This argument + * should be 0 when a search is initiated. Supplying + * the return argument of this function when calling + * repeatedly will go through the complete slave + * search. + * + * \param pin A bit-mask of the bus to perform a ROM search on. + * + * \return The last bit position where there was a discrepancy between slave + * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED + * if an error was detected (e.g. a device was connected to the bus during the + * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be + * discovered. + * + * \note See main.c for an example of how to utilize this function. + */ +unsigned char OWI_SearchRom(unsigned char * bitPattern, + unsigned char lastDeviation, unsigned char pin) +{ + unsigned char currentBit = 1; + unsigned char newDeviation = 0; + unsigned char bitMask = 0x01; + unsigned char bitA; + unsigned char bitB; + + // Send SEARCH ROM command on the bus. + OWI_SendByte(OWI_ROM_SEARCH, pin); + + // Walk through all 64 bits. + while (currentBit <= 64) { + // Read bit from bus twice. + bitA = OWI_ReadBit(pin); + bitB = OWI_ReadBit(pin); + + if (bitA && bitB) { + // Both bits 1 (Error). + newDeviation = OWI_ROM_SEARCH_FAILED; + return newDeviation; + } else if (bitA ^ bitB) { + // Bits A and B are different. All devices have the same bit here. + // Set the bit in bitPattern to this value. + if (bitA) { + (*bitPattern) |= bitMask; + } else { + (*bitPattern) &= ~bitMask; + } + } else { + // If this is where a choice was made the last time, + // a '1' bit is selected this time. + if (currentBit == lastDeviation) { + (*bitPattern) |= bitMask; + } + + // For the rest of the id, '0' bits are selected when + // discrepancies occur. + else if (currentBit > lastDeviation) { + (*bitPattern) &= ~bitMask; + newDeviation = currentBit; + } + + // If current bit in bit pattern = 0, then this is + // out new deviation. + else if ( !(*bitPattern & bitMask)) { + newDeviation = currentBit; + } + + // IF the bit is already 1, do nothing. + else { + } + } + + // Send the selected bit to the bus. + if ((*bitPattern) & bitMask) { + OWI_WriteBit1(pin); + } else { + OWI_WriteBit0(pin); + } + + // Increment current bit. + currentBit++; + + // Adjust bitMask and bitPattern pointer. + bitMask <<= 1; + if (!bitMask) { + bitMask = 0x01; + bitPattern++; + } + } + + return newDeviation; +} + + +/* Functions for handling CRC */ +/*! \brief Compute the CRC8 value of a data set. + * + * This function will compute the CRC8 or DOW-CRC of inData using seed + * as inital value for the CRC. + * + * \param inData One byte of data to compute CRC from. + * + * \param seed The starting value of the CRC. + * + * \return The CRC8 of inData with seed as initial value. + * + * \note Setting seed to 0 computes the crc8 of the inData. + * + * \note Constantly passing the return value of this function + * As the seed argument computes the CRC8 value of a + * longer string of data. + */ +unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) +{ + unsigned char bitsLeft; + unsigned char temp; + + for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + temp = ((seed ^ inData) & 0x01); + + if (temp == 0) { + seed >>= 1; + } else { + seed ^= 0x18; + seed >>= 1; + seed |= 0x80; + } + + inData >>= 1; + } + return seed; +} + + +/*! \brief Compute the CRC16 value of a data set. + * + * This function will compute the CRC16 of inData using seed + * as inital value for the CRC. + * + * \param inData One byte of data to compute CRC from. + * + * \param seed The starting value of the CRC. + * + * \return The CRC16 of inData with seed as initial value. + * + * \note Setting seed to 0 computes the crc16 of the inData. + * + * \note Constantly passing the return value of this function + * As the seed argument computes the CRC16 value of a + * longer string of data. + */ +unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) +{ + unsigned char bitsLeft; + unsigned char temp; + + for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + temp = ((seed ^ inData) & 0x01); + + if (temp == 0) { + seed >>= 1; + } else { + seed ^= 0x4002; + seed >>= 1; + seed |= 0x8000; + } + + inData >>= 1; + } + + return seed; +} + + +/*! \brief Calculate and check the CRC of a 64 bit ROM identifier. + * + * This function computes the CRC8 value of the first 56 bits of a + * 64 bit identifier. It then checks the calculated value against the + * CRC value stored in ROM. + * + * \param *romValue A pointer to an array holding a 64 bit identifier. + * + * \retval OWI_CRC_OK The CRC's matched. + * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. + */ +unsigned char OWI_CheckRomCRC(unsigned char *romValue) +{ + unsigned char i; + unsigned char crc8 = 0; + + for (i = 0; i < 7; i++) { + crc8 = OWI_ComputeCRC8(*romValue, crc8); + romValue++; + } + + if (crc8 == (*romValue)) { + return OWI_CRC_OK; + } + + return OWI_CRC_ERROR; +} diff --git a/BaseTinyFirmware/GCC/OWI.h b/BaseTinyFirmware/GCC/OWI.h new file mode 100644 index 0000000..86ffba7 --- /dev/null +++ b/BaseTinyFirmware/GCC/OWI.h @@ -0,0 +1,178 @@ +// This file has been prepared for Doxygen automatic documentation generation. +/*! \file ******************************************************************** + * + * \brief + * Header file for OWI.c + * + * Contains definitions used in the polled 1-Wire(R) driver. + * + * \par Application Note: + * AVR458: Charging Li-Ion Batteries with BC100\n + * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n +****************************************************************************/ + +#ifndef OWI_H +#define OWI_H + +#include + + +//****************************************************************************** +// Defines for CRC-functions +//****************************************************************************** +#define OWI_CRC_OK 0x00 //!< CRC check succeded +#define OWI_CRC_ERROR 0x01 //!< CRC check failed + + +//****************************************************************************** +// Defines for OWI-functions +//****************************************************************************** +/*! \brief CPU clock frequency. + * + * This define is used to calculate delays when the software only driver + * is used. The CPU frequency must be at least 2.170 MHz to be able to + * generate the shortest delays. + */ +#define CPU_FREQUENCY 8.000 + + +/*! \brief Use internal pull-up resistor on 1-Wire buses. + * + * If this symbol is defined, the internal pull-up resister on the GPIO pins + * of the AVR will be used to generate the necessary pull-up on the bus. If + * an external pull-up resistor is used, uncomment this define. + */ +//#define OWI_USE_INTERNAL_PULLUP + + +// Port configuration registers for 1-Wire buses. +// Make sure that all three registers belong to the same port. +#define OWI_PORT PORTA //!< 1-Wire PORT Data register. +#define OWI_PIN PINA //!< 1-Wire Input pin register. +#define OWI_DDR DDRA //!< 1-Wire Data direction register. + + +//****************************************************************************** +// Pin bitmasks +//****************************************************************************** +#define OWI_PIN_0 0x01 +#define OWI_PIN_1 0x02 +#define OWI_PIN_2 0x04 +#define OWI_PIN_3 0x08 +#define OWI_PIN_4 0x10 +#define OWI_PIN_5 0x20 +#define OWI_PIN_6 0x40 +#define OWI_PIN_7 0x80 + + +//****************************************************************************** +// Timing parameters +//****************************************************************************** +//! Timing delay when pulling bus low and releasing bus. +#define OWI_DELAY_OFFSET_CYCLES 13 + +// Bit timing delays in clock cycles (= us*clock freq in MHz). +#define OWI_DELAY_A_STD_MODE (unsigned long)((6 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_B_STD_MODE (unsigned long)((64 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_C_STD_MODE (unsigned long)((60 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_D_STD_MODE (unsigned long)((10 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_E_STD_MODE (unsigned long)((9 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_F_STD_MODE (unsigned long)((55 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +//#define OWI_DELAY_G_STD_MODE (unsigned long)((0 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_H_STD_MODE (unsigned long)((480 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_I_STD_MODE (unsigned long)((70 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_J_STD_MODE (unsigned long)((410 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) + + +//****************************************************************************** +// ROM commands +//****************************************************************************** +#define OWI_ROM_READ 0x33 //!< READ ROM command code. +#define OWI_ROM_SKIP 0xcc //!< SKIP ROM command code. +#define OWI_ROM_MATCH 0x55 //!< MATCH ROM command code. +#define OWI_ROM_SEARCH 0xf0 //!< SEARCH ROM command code. + + +//****************************************************************************** +// Return codes +//****************************************************************************** +#define OWI_ROM_SEARCH_FINISHED 0x00 //!< Search finished return code. +#define OWI_ROM_SEARCH_FAILED 0xff //!< Search failed return code. + + +//****************************************************************************** +// Macros +//****************************************************************************** +/*! \brief Pull 1-Wire bus low. + * + * This macro sets the direction of the 1-Wire pin(s) to output and + * pull the line(s) low. + * + * \param bitMask A bitmask of the buses to pull low. + */ +#define OWI_PULL_BUS_LOW(bitMask) \ + OWI_DDR |= (bitMask); \ + OWI_PORT &= ~(bitMask) + + +/*! \def OWI_RELEASE_BUS(bitMask) + * + * \brief Release the bus. + * + * This macro releases the bus and enables the internal pull-up if + * it is used. + * + * \param bitMask A bitmask of the buses to release. + */ +#ifdef OWI_USE_INTERNAL_PULLUP + // Set 1-Wire pin(s) to input and enable internal pull-up resistor. +#define OWI_RELEASE_BUS(bitMask) \ + OWI_DDR &= ~(bitMask); \ + OWI_PORT |= (bitMask) + +#else + // Set 1-Wire pin(s) to input mode. No internal pull-up enabled. +#define OWI_RELEASE_BUS(bitMask) \ + OWI_DDR &= ~(bitMask); \ + OWI_PORT &= ~(bitMask) + +#endif + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +void OWI_SendByte(unsigned char data, unsigned char pins); +unsigned char OWI_ReceiveByte(unsigned char pin); +void OWI_SkipRom(unsigned char pins); +void OWI_ReadRom(unsigned char * romValue, unsigned char pin); +void OWI_MatchRom(unsigned char * romValue, unsigned char pins); +unsigned char OWI_SearchRom(unsigned char * bitPattern, + unsigned char lastDeviation, unsigned char pin); +void OWI_Init(unsigned char pins); +void OWI_WriteBit1(unsigned char pins); +void OWI_WriteBit0(unsigned char pins); +unsigned char OWI_ReadBit(unsigned char pins); +unsigned char OWI_DetectPresence(unsigned char pins); + +unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed); +unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed); +unsigned char OWI_CheckRomCRC(unsigned char *romValue); + +#endif // OWI_H + diff --git a/BaseTinyFirmware/GCC/PWM.c b/BaseTinyFirmware/GCC/PWM.c new file mode 100644 index 0000000..9d205fc --- /dev/null +++ b/BaseTinyFirmware/GCC/PWM.c @@ -0,0 +1,150 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for use of PWM + * + * Contains functions for initializing and controlling PWM output. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100\n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" + +#include "main.h" +#include "PWM.h" +#include "time.h" + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Stops PWM output + * + */ +void PWM_Stop(void) +{ + OCR1B = 0; // Reset compare level. + PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode. + TCCR1A = 0; // Set normal port operation, disable PWM modes. + TCCR1B = 0; // Stop timer/counter1. + TCCR1C = 0; // Set normal port operation. + TCCR1D = 0; // No fault protection, normal waveform. + OCR1C = 0; // Reset compare. + OCR1D = 0; // Reset compare. + DT1 = 0; // No dead time values. +} + + +/*! \brief Initializes and starts PWM output + * + * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n + * Its comparator is connected to PB3 and will output high until timer1 reaches + * the value of OCR1B. It is then dropped to 0.\n + * The comparator outputs high again when the counter overflows, which will + * happen at a rate of 250 kHz. + */ +void PWM_Start(void) +{ + // Clear OC1B on compare match, enable PWM on comparator OCR1B. + TCCR1A = (1< 0) { + OCR1B -= 1; + return(TRUE); + } else { + return(FALSE); + } +} diff --git a/BaseTinyFirmware/GCC/PWM.h b/BaseTinyFirmware/GCC/PWM.h new file mode 100644 index 0000000..bda3a88 --- /dev/null +++ b/BaseTinyFirmware/GCC/PWM.h @@ -0,0 +1,50 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Header file for PWM.c + * + * Contains definitions to control PWM behaviour. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef PWM_H +#define PWM_H + +//****************************************************************************** +// Constants for PWM +//****************************************************************************** +//! Needed for JumperCheck() to succeed. ADC is saturated otherwise! +#define PWM_OFFSET 12 + +//! PWM duty cycle limit (must be less than 256). +#define PWM_MAX 255 + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +void PWM_Start(void); +void PWM_Stop(void); +unsigned char PWM_IncrementDutyCycle(void); +unsigned char PWM_DecrementDutyCycle(void); + +#endif // PWM_H + diff --git a/BaseTinyFirmware/GCC/USI.c b/BaseTinyFirmware/GCC/USI.c new file mode 100644 index 0000000..efc004f --- /dev/null +++ b/BaseTinyFirmware/GCC/USI.c @@ -0,0 +1,310 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for use of the Universal Serial Interface + * + * Contains high level functions for initializing the USI as an SPI slave, + * interrupt handling, sending and receiving single bytes. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include + +#include "enums.h" +#include "structs.h" + +#include "main.h" +#include "ADC.h" +#include "battery.h" +#include "time.h" +#include "USI.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +//! SPI status struct +SPI_Status_t SPI; + + +//****************************************************************************** +//Functions +//***************************************************************************** +/*! \brief USI Counter Overflow Interrupt Service Routine + * + * When the USI counter overflows, a byte has been transferred.\n + * The USIDR contents are stored and flags are updated. + * + * The protocol is quite simple and has three sequential states: command, + * address and data. + * (Keep in mind that the Master is in charge of data clocking, which means + * there is a one byte "delay" from when the Slave puts something to SPI till + * the Master can read it.) + * + * 1. If a non-zero byte is received in the command state, the ISR will + * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of + * bytes). To signal that the command was received, 0xCC is put to the SPI bus. + * If a zero byte (0x00) is received in the command state, it is simply ignored + * because it is an invalid command. + * + * 2. When a byte is received in the address state, it is stored to the SPI + * struct. To signal that the address was received, 0xBB is put to SPI bus. + * + * 3. In the data state, variables are read/written "from back to front" until + * the byte counter reaches zero. Since the Master is in charge of the data + * clocking, the Slave will go to command state before the last byte is + * transferred during reading. This means that the Master should send an + * invalid command when getting each byte, ie 0x00. + * + * If the time between two transfers is 1 second or more, the Slave + * automatically reverts to command state. + * + * \note Battery charging is not automatically halted during SPI communication. + * This means that the current charge state (current and voltage) will + * remain constant during heavy and prolonged serial traffic. + * + * \todo Variable writing not implemented yet. + * \todo EEPROM/SRAM flag doesn't really do anything with this implementation. + */ +ISR(USI_OVF_vect) +{ + // If the communication timed out, set ST_CMD as current state. + if (!Time_Left(TIMER_USI)) { + SPI.State = ST_CMD; + } + + // Start communication timer. If further communication doesn't happen + // within 1 second, the SPI communication state is reset to CMD. + Time_Set(TIMER_USI, 0, 1, 0); + + // Clear USI counter and flag completed transfer. + USISR = (1< 0) { + // Write specified variable to SPI, "back to front". + if (SPI.Read) { + switch (SPI.Address) { + case ADR_ADCS: + SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count))); + break; + + + case ADR_BATTACTIVE: + SPI_Put(*((unsigned char*)&BattActive + (SPI.Count))); + break; + + + case ADR_BATTDATA: + SPI_Put(*((unsigned char*)&BattData + (SPI.Count))); + break; + + + case ADR_BATTCTRL: + SPI_Put(eeprom_read_byte((unsigned char*)&BattControl + (SPI.Count))); + break; + + case ADR_TIMERS: + SPI_Put(*((unsigned char*)&timeval + (SPI.Count))); + break; + + + default: + SPI_Put(0); + break; + } + } else { + // Read byte from SPI + SPI.Data = USIDR; + + // ******************************************** + // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED + // ******************************************** + + // Save byte to specified variable. + switch (SPI.Address) { + case ADR_BATTCTRL: + eeprom_write_byte((unsigned char*)&BattControl + SPI.Count, SPI.Data); + break; + + + default: + break; + } + } + + + } else { + SPI.State = ST_CMD; + } + break; + + default: // Shouldn't end up here. (Unknown SPI-state) + break; + } +} + + +/*! \brief Initializes USI as an SPI slave + * + * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for + * I/O and clock, and USI counter overflow interrupts enabled.\n + * Also initializes the SPI status struct. + * + * \param spi_mode Specifies if USI should trigger on positive (0) or negative + * (1) edge of clock signal + * + * \note Clears the stored data + * + * \todo Timer should reset SPI protocol on timeout + */ +void SPI_Init(unsigned char spi_mode) +{ + cli(); + + // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. + USI_DIR_REG |= (1<avr45813-Mar-2008 01:43:5513-Mar-2008 04:56:33241013-Mar-2008 01:43:5544, 14, 0, 580AVR GCCavr458\avr458.elfC:\Users\kevin\pub\src\bc100\GCC\AVR SimulatorATtiny861.xmlfalseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000ADC.cbattery.cchargefunc.cLIIONcharge.cmain.cmenu.cOWI.cPWM.cstatefunc.ctime.cUSI.cavr458\avr458.lssavr458\avr458.mapavr458NOattiny861111avr458.elfavr458\0-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DLIION -Wall avr4581C:\WinAVR\bin\avr-gcc.exeC:\WinAVR\utils\bin\make.exe diff --git a/BaseTinyFirmware/GCC/avr458.aws b/BaseTinyFirmware/GCC/avr458.aws new file mode 100644 index 0000000..2773bff --- /dev/null +++ b/BaseTinyFirmware/GCC/avr458.aws @@ -0,0 +1 @@ + diff --git a/BaseTinyFirmware/GCC/avr463.aps b/BaseTinyFirmware/GCC/avr463.aps new file mode 100644 index 0000000..0e89be1 --- /dev/null +++ b/BaseTinyFirmware/GCC/avr463.aps @@ -0,0 +1 @@ +avr46313-Mar-2008 01:54:2413-Mar-2008 03:07:11241013-Mar-2008 01:54:2444, 14, 0, 580AVR GCCavr463\avr463.elfC:\Users\kevin\pub\src\bc100\GCC\AVR SimulatorATtiny861.xmlfalseR00R01R02R03R04R05R06R07R08R09R10R11R12R13R14R15R16R17R18R19R20R21R22R23R24R25R26R27R28R29R30R31Auto000ADC.cbattery.cchargefunc.cmain.cmenu.cNIMHcharge.cOWI.cPWM.cstatefunc.ctime.cUSI.cavr463\avr463.lssavr463\avr463.mapavr463NOattiny861111avr463.elfavr463\1-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DNIMH avr4631C:\WinAVR\bin\avr-gcc.exeC:\WinAVR\utils\bin\make.exeC:\Users\kevin\pub\src\bc100\GCC\ADC.cC:\Users\kevin\pub\src\bc100\GCC\battery.cC:\Users\kevin\pub\src\bc100\GCC\chargefunc.cC:\Users\kevin\pub\src\bc100\GCC\main.cC:\Users\kevin\pub\src\bc100\GCC\menu.cC:\Users\kevin\pub\src\bc100\GCC\NIMHcharge.cC:\Users\kevin\pub\src\bc100\GCC\OWI.cC:\Users\kevin\pub\src\bc100\GCC\PWM.cC:\Users\kevin\pub\src\bc100\GCC\statefunc.cC:\Users\kevin\pub\src\bc100\GCC\time.cC:\Users\kevin\pub\src\bc100\GCC\USI.c00000battery.c100001chargefunc.c100002nimhcharge.c100003statefunc.c1 diff --git a/BaseTinyFirmware/GCC/avr463.aws b/BaseTinyFirmware/GCC/avr463.aws new file mode 100644 index 0000000..2773bff --- /dev/null +++ b/BaseTinyFirmware/GCC/avr463.aws @@ -0,0 +1 @@ + diff --git a/BaseTinyFirmware/GCC/battery.c b/BaseTinyFirmware/GCC/battery.c new file mode 100644 index 0000000..e6cacd8 --- /dev/null +++ b/BaseTinyFirmware/GCC/battery.c @@ -0,0 +1,422 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions related to battery control and data acquisition. + * + * Contains functions for enabling/disabling batteries, and looking up + * their status and specifications using the ADC. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include + +#include "structs.h" +#include "enums.h" + +#include "ADC.h" +#include "battery.h" +#include "main.h" +#include "OWI.h" +#include "time.h" + +#ifdef NIMH +#include "NIMHspecs.h" +#endif // NIMH + +#ifdef LIION +#include "LIIONspecs.h" +#endif // LIION + + + +//****************************************************************************** +// Variables +//****************************************************************************** +/* Control-struct for batteries */ +/*! \brief Holds control data for both batteries + * \note Stored in EEPROM. + */ + +Battery_t EEMEM BattControl[2] = {(BIT_BATTERY_ENABLED | BIT_BATTERY_DISCONNECT_ALLOWED | BIT_BATTERY_CHARGE_INHIBIT), + (BIT_BATTERY_ENABLED | BIT_BATTERY_DISCONNECT_ALLOWED | BIT_BATTERY_CHARGE_INHIBIT), +}; + +/* Data-struct for battery */ +Batteries_t BattData; //!< Holds data for the current battery + + +/* Storage for battery EPROM */ +/*! \brief Storage space for data from the batteries' own EPROMs. + * \note Stored in EEPROM. + */ +unsigned char EEMEM BattEEPROM[4][32]; + + +//! Global that indicates current battery (0 = battery A, 1 = B) +unsigned char BattActive; + + +/*! \brief RID lookup-table + * + * Contains Resistor ID data specified by manufacturer. + * + * \note Values have been calculated assuming a +/- 15% tolerance. + */ +const RID_Lookup_t RID[RID_TABLE_SIZE] = { + {558, 659, 3900, 550, 260, 300, 10}, + {744, 843, 6800, 750, 360, 300, 14}, + {869, 958, 10000, 1000, 475, 300, 19}, + {1097, 1153, 24000, 2000, 475, 420, 38} +}; + + +/*! \brief NTC lookup-table + * + * The first entry is 0 degrees. For every entry after, temperature increases + * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n + * It must be sorted in descending ADC order. + * + * \note This was calculated for a Mitsubishi RH16-3H103FB NTC. + * + * \note NTCLookUp() must be modified if this table is changed so that: + * - first entry is no longer 0 degrees. + * - temperature difference between entries is no longer 4 degrees. + * - ADCsteps no longer specifies ADC steps per half degree. + */ +// FOR VARTA POLYFLEX NTC +const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27}, + {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24}, + {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17}, + {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10} +}; + + +// FOR MITSUBISHI NTC +/* +const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27}, + {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24}, + {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17}, + {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10} +}; +*/ + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Checks if battery has changed + * + * Stores current capacity, then attempts to refresh battery status.\n + * If the refresh is successful, old capacity is compared with the new one. + * + * \retval FALSE Battery is disconnected, or capacity has changed. + * \retval TRUE All OK. + */ +unsigned char BatteryCheck(void) +{ + unsigned char success = TRUE; + unsigned int oldCapacity; + + // Save to see if battery data has changed. + oldCapacity = BattData.Capacity; + + if (!BatteryStatusRefresh()) { + success = FALSE; // Battery not present or RID was invalid. + } + + if (oldCapacity != BattData.Capacity) { + success = FALSE; // Battery configuration has changed. + } + + return(success); +} + + +/*! \brief Refreshes battery status information + * + * Refreshes battery status information, if it is present, based on + * RID and NTC (read by ADC).\n + * The battery must have been enabled and a complete set of ADC data must have + * been collected before calling.\n + * + * \retval FALSE No battery present. + * \retval TRUE Battery present, status refreshed. + * + * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry + * is found in the lookup table. Instead, default battery data will be used. + */ +unsigned char BatteryStatusRefresh(void) +{ + // Assume the worst.. + unsigned char success = FALSE; + + BattData.Present = FALSE; + BattData.Charged = FALSE; + BattData.Low = TRUE; + BattData.Circuit = OW_NONE; + BattData.Temperature = 0; + BattData.Capacity = 0; + BattData.MaxCurrent = 0; + BattData.MaxTime = 0; + BattData.MinCurrent = 0; + + NTCLookUp(); + BattData.HasRID = RIDLookUp(); + + // Is the battery voltage above minimum safe cell voltage? + if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + BattData.Low = FALSE; + } + + // Is the battery charged? + if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { + BattData.Charged = TRUE; + } + + // If we are not charging, yet VBAT is above safe limit, battery is present. + // If we are charging and there's a current flowing, the battery is present. + + /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence + * check is redundant since charging will be aborted due to low current at + * max duty cycle. That is preferrable since the charge current reading is + * not 100% proof. + */ + if (((OCR1B == 0) && (!BattData.Low)) || + ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { + BattData.Present = TRUE; + success = TRUE; + } else { + BattData.Low = FALSE; // (This is just a technicality..) + success = FALSE; + } + +#ifndef ALLOW_NO_RID + // Return FALSE if no valid RID entry was found, to stop charging. + if(!BattData.HasRID) { + success = FALSE; + } +#endif + + return(success); +} + + +/*! \brief Refreshes battery data in the EEPROM + * + * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store + * these data in on-chip EEPROM.\n + * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared. + * + * \todo Updating BattData with these data. Specs needed. + * + * \retval FALSE Refresh failed. + * \retval TRUE Refresh successful. + */ +unsigned char BatteryDataRefresh(void) +{ + unsigned char offset; + unsigned char i, crc, family, temp, page; + unsigned char success; + + // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found. + for (page = 0; page < 4; page++) { + success = FALSE; + + if (OWI_DetectPresence(OWIBUS) == OWIBUS) { + + // Presence detected, check type and CRC. + OWI_SendByte(OWI_ROM_READ, OWIBUS); + family = OWI_ReceiveByte(OWIBUS); + crc = OWI_ComputeCRC8(family,0); + + for (i = 0; i < 6; i++) { + crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc); + } + + // CRC ok, device found. + if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + BattData.Circuit = family; + + // For now, we only read data from DS2505 EPROMs. + if (BattData.Circuit == OW_DS2505) { + offset = page*32; + OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data. + OWI_SendByte(offset, OWIBUS); // Data: low address. + OWI_SendByte(0, OWIBUS); // Data: high address. + + // Calculate checksums. + crc = OWI_ComputeCRC8(DS2505_DATA_READ,0); + crc = OWI_ComputeCRC8(offset,crc); + crc = OWI_ComputeCRC8(0,crc); + + // Command received succesfully, now start reading data + // and writing it to EEPROM. + if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + crc = 0; + + // Fill page with data. + for (i=0; i<32; i++) { + temp = OWI_ReceiveByte(OWIBUS); + crc = OWI_ComputeCRC8(temp, crc); + eeprom_write_byte(&BattEEPROM[page][i], temp); + } + + if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + success = TRUE; // Data read OK + } + } else { // Not able to start reading data. + } + } else { // Wrong device type. + } + } else { // No device found. + } + } else { // No presence detected on one-wire bus. + } + + // Erase local EEPROM page if there were any errors during transfer. + if (!success) { + for (i=0; i<32; i++) { + eeprom_write_byte(&BattEEPROM[page][i], 0); + } + } + } + + return(success); +} + + +/*! \brief Enables specified battery + * + * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears + * PB5/PB4 in PORTB, depending on which battery is specified.\n + * The function takes 100 ms to allow the port switch to settle. + * + * \param bat Specifies which battery to enable (0 = battery A, 1 = B) + */ +void EnableBattery(unsigned char bat) +{ + // Use general timer, set timeout to 100ms. + Time_Set(TIMER_GEN,0,0,100); + + // Set specified battery as the active one. + BattActive = bat; + + // Enable current battery in hardware, light LED & connect battery. + PORTB |= (1 << (PB4+bat)); + + // Disconnect other battery. + PORTB &= ~(1<<(PB5-bat)); + + do { // Let port switch settle. + } while (Time_Left(TIMER_GEN)); +} + + +/*! \brief Disables both batteries + * + * Clears PB4 and PB5 in PORTB, disabling both batteries. + */ +void DisableBatteries(void) +{ + // Turn off LEDs and disconnect batteries. + PORTB &= ~((1<= RID[i].Low) { + if (ADCS.rawRID <= RID[i].High) { + BattData.Capacity = RID[i].Capacity; + BattData.MaxCurrent = RID[i].Icharge; + BattData.MaxTime = RID[i].tCutOff; + BattData.MinCurrent = RID[i].ICutOff; + + found = TRUE; + } + } + } + + // If no valid entry is found, use defaults and return FALSE. + if (!found) { + BattData.Capacity = DEF_BAT_CAPACITY; + BattData.MaxCurrent = DEF_BAT_CURRENT_MAX; + BattData.MaxTime = DEF_BAT_TIME_MAX; + BattData.MinCurrent = DEF_BAT_CURRENT_MIN; + } + + return(found); +} + + +/*! \brief Calculates temperature from a lookup table + * + * Looks up the highest NTC value below or equal to the measured one.\n + * With the current lookup table, temperature is calculated with the formula:\n + * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry) + * + * \note If the NTC-measurement is saturated, with the current lookup table, + * the temperature will be reported as -1 C. + * + * \note If no valid entry is found, battery temperature is set to 80. + */ +void NTCLookUp (void) +{ + unsigned char i; + unsigned char found = FALSE; + + // Lookup in the NTC-table. Use the first entry which is equal or below + // sampled NTC. Calculate temperature by using the index number, and the + // difference between the measured NTC value and the one in the entry. + for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { + if (ADCS.rawNTC >= NTC[i].ADCV) { + BattData.Temperature = (i<<2) ; + BattData.ADCSteps = NTC[i].ADCsteps; + BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADCV)<<1) / BattData.ADCSteps; + + found = TRUE; // Could be done with a break, but that violates MISRA. + } + } + + // For safety, is temperature is greater than the NTC + if (!found) { + BattData.Temperature = 80; + } +} diff --git a/BaseTinyFirmware/GCC/battery.h b/BaseTinyFirmware/GCC/battery.h new file mode 100644 index 0000000..bb76eaf --- /dev/null +++ b/BaseTinyFirmware/GCC/battery.h @@ -0,0 +1,115 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for battery.c + * + * Contains definitions for the setup of 1-Wire(R) and behaviour of the + * battery data and status refreshing functions.\n + * Also contains definitions of default battery data, and declarations + * for the RID and NTC lookup tables. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + + +#ifndef BATTERY_H +#define BATTERY_H + +#include + + +//****************************************************************************** +// Defines for EEPROM reading +//****************************************************************************** +#define OWIBUS OWI_PIN_0 //!< One-wire bus (pin). + +#define OW_NONE 0x00 //!< One-wire device family code. +#define OW_DS2505 0x09 //!< One-wire device family code. + +#define DS2505_MEM_READ 0xF0 //!< One-wire device command. +#define DS2505_STATUS_READ 0xAA //!< One-wire device command. +#define DS2505_DATA_READ 0xC3 //!< One-wire device command. + + +//****************************************************************************** +// RID-less charging (for BatteryStatusRefresh()) +//****************************************************************************** +//#define ALLOW_NO_RID //!< Use default battery data if no matching entry found. + +#define DEF_BAT_CAPACITY 0 //!< Default battery capacity, in mAh. +#define DEF_BAT_CURRENT_MAX 0 //!< Default maximum charge current, in mA. +#define DEF_BAT_TIME_MAX 0 //!< Default maximum charge time, in minutes. +//! Default minimum current to stop charge, in mA. +#define DEF_BAT_CURRENT_MIN 0 + + + +//****************************************************************************** +// RID and NTC defines and struct declarations +//****************************************************************************** +#define RID_TABLE_SIZE 4 //!< Number of entries in RID table. +#define NTC_TABLE_SIZE 20 //!< Number of entries in NTC table. + +//! \brief Struct for an entry in the resistor ID lookup-table +struct RID_Lookup_struct { + unsigned int Low; //!< Lowest acceptable ADC value. + unsigned int High; //!< Highest acceptable ADC value. + unsigned int Resistance; //!< RID resistance, in Ohms. + unsigned int Capacity; //!< Associated battery capacity, in mAh. + unsigned int Icharge; //!< Associated initial charge current, in mA. + unsigned int tCutOff; //!< Associated cut-off time, in minutes. + unsigned int ICutOff; //!< Associated cut-off current, in mA. +}; +typedef struct RID_Lookup_struct RID_Lookup_t; //!< For convenience. + +/*! \brief Struct for an entry in the NTC lookup-table + * + * \note Must be sorted in descending ADC order. + */ +struct NTC_Lookup_struct +{ + unsigned int ADCV; //!< Measured NTC. + unsigned char ADCsteps; //!< ADC steps per half degree at this temperature. +}; +typedef struct NTC_Lookup_struct NTC_Lookup_t; //!< For convenience. + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern Battery_t EEMEM BattControl[]; +extern Batteries_t BattData; +extern unsigned char EEMEM BattEEPROM[][32]; +extern unsigned char BattActive; + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char BatteryCheck(void); +unsigned char BatteryStatusRefresh(void); +unsigned char BatteryDataRefresh(void); +void EnableBattery(unsigned char); +void DisableBatteries(void); +unsigned char RIDLookUp(void); +void NTCLookUp(void); + + +#endif // BATTERY_H diff --git a/BaseTinyFirmware/GCC/blue.GIF b/BaseTinyFirmware/GCC/blue.GIF new file mode 100644 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 index 0000000..3d387a5 --- /dev/null +++ b/BaseTinyFirmware/GCC/charge.h @@ -0,0 +1,38 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for NIMHcharge.c and LIIONcharge.c + * + * Contains definitions and declarations related to the charge state. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/charge.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef CHARGE_H +#define CHARGE_H + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char Charge(unsigned char inp); + + +#endif // CHARGE_H diff --git a/BaseTinyFirmware/GCC/chargefunc.c b/BaseTinyFirmware/GCC/chargefunc.c new file mode 100644 index 0000000..2194e56 --- /dev/null +++ b/BaseTinyFirmware/GCC/chargefunc.c @@ -0,0 +1,363 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Charge functions + * + * Contains the functions for charging with constant current and voltage, + * and for deciding when to halt. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" +#include "structs.h" + +#include "ADC.h" +#include "battery.h" +#include "chargefunc.h" +#include "main.h" +#include "menu.h" +#include "PWM.h" +#include "statefunc.h" +#include "time.h" + +#ifdef NIMH +#include "NIMHspecs.h" +#endif // NIMH + +#ifdef LIION +#include "LIIONspecs.h" +#endif // LIION + + +//****************************************************************************** +// Variables +//****************************************************************************** +//! Struct that holds parameters for ConstantCurrent() and ConstantVoltage(). +ChargeParameters_t ChargeParameters; + +//! Struct that holds parameters for HaltNow(). +HaltParameters_t HaltParameters; + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Charges battery with a constant current. + * + * This function applies a constant current (set in ChargeParameters.Current) + * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n + * If the Master inhibits charging, timers are stopped and PWM output dropped. + * Once the battery is no longer flagged for charge inhibit, timers are + * started again and charging resumed. + * + * \retval ChargeParameters.NextState Next state once this stage is done. + * If no errors occured, this will be whatever was set in Charge(). Otherwise, + * HaltNow() will have set a new next state. + */ +unsigned char ConstantCurrent(void) +{ + unsigned char error = FALSE, + wasStopped = FALSE; + + do { + // Wait for ADC conversions to complete. + ADC_Wait(); + + // If Master has flagged for a charge inhibit, pause charging. + // (This is to prevent damage during prolonged serial communication.) + if (eeprom_read_byte(&BattControl[BattActive]) & BIT_BATTERY_CHARGE_INHIBIT) { + wasStopped = TRUE; + Time_Stop(); + OCR1B = 0; + } else { + // Continue charging! + if (wasStopped) { + wasStopped = FALSE; + + // Timer variables are not reset by this. + Time_Start(); + } + + // Adjust the charge current to within ChargeParameters.Current + // +/- BAT_CURRENT_HYST. + if ((ADCS.avgIBAT < 0) || + (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { + + if(!PWM_IncrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MAX + // If the duty cycle cannot be incremented, flag error and + // go to error state. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } else if ((ADCS.avgIBAT >= 0) && + (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { + + if(!PWM_DecrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MIN + // If the duty cycle cannot be decremented, flag error and + // go to error state. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } + } + } while (!HaltNow() && !error); + + // Return the next state to Charge(). If an error has occured, this will + // point to some other state than the next state of charging. + return(ChargeParameters.NextState); +} + + +/*! \brief Charges battery with a constant voltage + * + * This function applies a constant voltage (set in ChargeParameters.Voltage) + * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n + * If the Master inhibits charging, timers are stopped and PWM output dropped. + * Once the battery is no longer flagged for charge inhibit, timers are + * started again and charging resumed. + * + * \retval ChargeParameters.NextState Next state once this stage is done. + * If no errors occured, this will be whatever was set in Charge(). Otherwise, + * HaltNow() will have set a new next state. + */ +unsigned char ConstantVoltage(void) +{ + unsigned char error = FALSE, + wasStopped = FALSE; + + do{ + + // Wait for ADC conversions to complete. + ADC_Wait(); + + // If Master has flagged for a charge inhibit, pause charging. + // (This is to prevent damage during prolonged serial communication.) + if (eeprom_read_byte(&BattControl[BattActive]) & BIT_BATTERY_CHARGE_INHIBIT) { + wasStopped = TRUE; + Time_Stop(); + OCR1B = 0; + } + + else { + // Continue charging! + if (wasStopped) { + wasStopped = FALSE; + + // Timer variables aren't reset by this. + Time_Start(); + } + + // Adjust the charge voltage to within ChargeParameters.Voltage + // +/- BAT_VOLTAGE_HYST. + if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { + + if(!PWM_IncrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MAX + // Flag PWM control error and go to error-state if the duty + // cycle cannot be incremented. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { + + if(!PWM_DecrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MIN + // Flag PWM control error and go to error-state if duty + // cycle cannot be decremented. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } + } + + } while (!HaltNow() && !error); + + // Return the next state to Charge(). If an error has occured, this will + // point to some other state than the next state of charging. + return(ChargeParameters.NextState); +} + + +/*! \brief Determines when to halt charging. + * + * This function evaluates parameters depending on what has been flagged in + * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should + * halt or not.\n + * In addition, error flagging on timeout (battery exhaustion) can be set.\n + * + * The function also checks if the battery temperature is within limits, + * if mains is OK, and if BatteryCheck() returns TRUE. + * If an error is detected, the associated errorflag is set and + * ChargeParameters.NextState is changed to an appropriate state. + * + * \retval TRUE Halt now. + * \retval FALSE Don't halt now. + * + * \note See chargefunc.h for definitions of halt flags. + * \note It is generally a bad idea not to halt on a timeout. + * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be + * reset in Charge() before calling a charging-function. + * + * \todo "Priorities" of standard error checks OK? + */ +unsigned char HaltNow(void) +{ + unsigned char i, halt = FALSE; + + // Wait for a full ADC-cycle to finish. + ADC_Wait(); + + // Evaluate ADC readings according to HaltFlags. Flag errors if selected. + // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR. + // (Gets overridden if either mains is failing, or the battery changes.) + for (i = 0x01; i != 0; i <<= 1) { + if (HaltParameters.HaltFlags & i) { + switch (i) { + // Is VBAT less than the recorded maximum? + case HALT_VOLTAGE_DROP: + + // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. + if (ADCS.VBAT > HaltParameters.VBATMax) { + HaltParameters.VBATMax = ADCS.VBAT; + } else if((HaltParameters.VBATMax - ADCS.VBAT) >= + HaltParameters.VoltageDrop) { + halt = TRUE; + } + break; + + + // Has VBAT reached the maximum limit? + case HALT_VOLTAGE_MAX: + + if (ADCS.VBAT >= HaltParameters.VoltageMax) { + halt = TRUE; + } + break; + + + // Has IBAT reached the minimum limit? + case HALT_CURRENT_MIN: + + if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { + halt = TRUE; + } + break; + + + // Is the temperature rising too fast? + case HALT_TEMPERATURE_RISE: + + // If rawNTC has increased, the temperature has dropped. + // We can store this value for now, and start the timer. + // Otherwise, check if NTC has changed too fast. + if (ADCS.rawNTC > HaltParameters.LastNTC) { + HaltParameters.LastNTC = ADCS.rawNTC; + Time_Set(TIMER_TEMP,0,30,0); + + // Is the increase in temperature greater than the set threshold? + } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= + (BattData.ADCSteps * HaltParameters.TemperatureRise)) { + + // If this happened within a timeframe of 30 seconds, the + // temperature is rising faster than we want. + // If not, update LastNTC and reset timer. + if (Time_Left(TIMER_TEMP)) { + halt = TRUE; + } else { + HaltParameters.LastNTC = ADCS.rawNTC; + Time_Set(TIMER_TEMP,0,30,0); + } + } + break; + + + // Is there any time left? + case HALT_TIME: + + if (!Time_Left(TIMER_CHG)) { + halt = TRUE; + + // If exhaustion flagging is selected, stop the PWM, disable the + // battery and flag it as exhausted. Make ST_ERROR next state. + if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { + PWM_Stop(); + Battery_t tmp = eeprom_read_byte(&BattControl[BattActive]); + tmp &= ~BIT_BATTERY_ENABLED; // Enabled = FALSE; + eeprom_write_byte(&BattControl[BattActive], tmp); + BattData.Exhausted = TRUE; + SetErrorFlag(ERR_BATTERY_EXHAUSTED); + ChargeParameters.NextState = ST_ERROR; + } + } + break; + + + default: // Shouldn't end up here, but is needed for MISRA compliance. + break; + } + } + } + + // Standard checks: + + // Battery too cold or hot? + if ((BattData.Temperature <= HaltParameters.TemperatureMin) || + (BattData.Temperature >= HaltParameters.TemperatureMax)) { + + PWM_Stop(); + SetErrorFlag(ERR_BATTERY_TEMPERATURE); + ChargeParameters.NextState = ST_ERROR; + halt = TRUE; + } + + // Battery not OK? + if (!BatteryCheck()) { + PWM_Stop(); + ChargeParameters.NextState = ST_INIT; + halt = TRUE; + } + + // Is mains voltage OK? + if (!ADCS.Mains) { + PWM_Stop(); + ChargeParameters.NextState = ST_SLEEP; + halt = TRUE; + } + + return(halt); +} diff --git a/BaseTinyFirmware/GCC/chargefunc.h b/BaseTinyFirmware/GCC/chargefunc.h new file mode 100644 index 0000000..88ac473 --- /dev/null +++ b/BaseTinyFirmware/GCC/chargefunc.h @@ -0,0 +1,134 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for chargefunc.c + * + * Contains definitions to decide PWM error handling and of halt flags, + * and declarations of parameter structs for charging. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef CHARGEFUNC_H +#define CHARGEFUNC_H + + +//****************************************************************************** +// PWM error handling +//****************************************************************************** +//! Report error if maximum duty cycle doesn't give a sufficient charge current. +#define ABORT_IF_PWM_MAX + +//! Report error if minimum duty cycle gives a too great charge current. +#define ABORT_IF_PWM_MIN + + +//****************************************************************************** +// Definitions for HaltFlags +//****************************************************************************** +//! Halt if VBAT drops more than the set limit. +#define HALT_VOLTAGE_DROP 0x01 + +//! Halt if VBAT reaches the set maximum. +#define HALT_VOLTAGE_MAX 0x02 + +//! Halt if avgIBAT goes below the set minimum. +#define HALT_CURRENT_MIN 0x04 + +//! Halt if BattData.Temperature rises quicker than the set maximum. +#define HALT_TEMPERATURE_RISE 0x08 + +//! Halt if TIMER_CHG runs out. +#define HALT_TIME 0x10 + +//! Flag battery as exhausted if timeout occurs. +#define HALT_FLAG_EXHAUSTION 0x20 + + +//****************************************************************************** +// Parameter struct for charging +//****************************************************************************** +/*! \brief Holds the parameters for ConstantCurrent() and ConstantVoltage(). + * + */ +struct ChargeParameters_struct { + unsigned int Voltage; //!< Voltage to charge with. + unsigned int Current; //!< Current to charge with. + unsigned char NextState; //!< \brief Next state once charge stage finishes. + //!< \note Set in Charge(), but may be changed by + //!< HaltNow() if an error occurs! +}; +typedef struct ChargeParameters_struct ChargeParameters_t; + + +//****************************************************************************** +// Parameter struct for HaltNow() +//****************************************************************************** +/*! \brief Holds the parameters for HaltNow(); + * + */ +struct HaltParameters_struct { + //! \brief Contains flags for what to evaluate. + //! \note See chargefunc.h for definitions of flags. + unsigned char HaltFlags; + + //! Maximum drop in voltage before halting, in mV. + unsigned int VoltageDrop; + + //! Maximum limit for output voltage, in mV. + unsigned int VoltageMax; + + //! Minimum limit for output current, in mA. + unsigned int CurrentMin; + + //! Maximum limit for battery temperature, in degrees centigrade. + unsigned int TemperatureMax; + + //! Minimum limit for battery temperature, in degrees centigrade. + signed int TemperatureMin; + + //! Maximum limit for temperature to rise, in degrees centigrade per minute. + unsigned int TemperatureRise; + + //! \brief Contains highest VBAT measured, used to calculate voltage drop. + //! \note Must be manually reset. + unsigned int VBATMax; + + //! Used to detect temperature rise. + unsigned int LastNTC; +}; +typedef struct HaltParameters_struct HaltParameters_t; + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern ChargeParameters_t ChargeParameters; +extern HaltParameters_t HaltParameters; + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char ConstantCurrent(void); +unsigned char ConstantVoltage(void); +unsigned char HaltNow(void); + +#endif // CHARGEFUNC_H diff --git a/BaseTinyFirmware/GCC/config_AVR458.doxygen b/BaseTinyFirmware/GCC/config_AVR458.doxygen new file mode 100644 index 0000000..2e5419c --- /dev/null +++ b/BaseTinyFirmware/GCC/config_AVR458.doxygen @@ -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 = "Atmel AVR Application Notes" +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 index 0000000..5ab35da --- /dev/null +++ b/BaseTinyFirmware/GCC/config_AVR463.doxygen @@ -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 = "Atmel AVR Application Notes" +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 index 0000000..8a1abfa --- /dev/null +++ b/BaseTinyFirmware/GCC/delay_x_gcc.h @@ -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 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 + +#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 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 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 index 0000000..b8c92c5 --- /dev/null +++ b/BaseTinyFirmware/GCC/enums.h @@ -0,0 +1,56 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Enums in common for Slave and Master + * + * Contains enumerations of timers and variable specifiers for + * time.c and USI.c.\n + * These are also used in the Master, and have therefore been + * put in a separate file for convenience. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/enums.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef ENUMS_H +#define ENUMS_H + +//****************************************************************************** +// Variable specifiers (for Master-Slave communication) +//****************************************************************************** +enum { + ADR_ADCS = 1, //!< Indicates that ADCS is read/write target. + ADR_BATTACTIVE, //!< Indicates that BattActive is read/write target. + ADR_BATTDATA, //!< Indicates that BattData is read/write target. + ADR_BATTCTRL, //!< Indicates that BattControl is read/write target. + ADR_TIMERS //!< Indicates that timeval is read/write target. +}; + + +//****************************************************************************** +// Timers +//****************************************************************************** +enum { + TIMER_USI = 0, //!< Timer meant for USI. + TIMER_CHG, //!< Timer meant for charging. + TIMER_GEN, //!< Timer meant for general use. + TIMER_TEMP, //!< Timer meant for timing of temperature rise. + TIMERS //!< Number of timers used. +}; + +#endif // ENUMS_H diff --git a/BaseTinyFirmware/GCC/liioncharge.c b/BaseTinyFirmware/GCC/liioncharge.c new file mode 100644 index 0000000..0ce5427 --- /dev/null +++ b/BaseTinyFirmware/GCC/liioncharge.c @@ -0,0 +1,156 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Charge state function for Li-Ion batteries + * + * Contains the charge state function, in which the Li-Ion charging + * algorithm is, plus the associated functions. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONcharge.c $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" +#include "structs.h" + +#include "battery.h" +#include "charge.h" +#include "chargefunc.h" +#include "main.h" +#include "menu.h" +#include "LIIONspecs.h" +#include "PWM.h" +#include "time.h" + +#ifndef LIION +#error LIION not defined in main.h! +#endif // LIION + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Controls the charging. + * + * This function contains the charging algorithm itself, divided into stages.\n + * For each stage the PWM may be started/stopped, and the timer, + * halt-requirements and charge parameters may be set.\n + * The charging functions return whatever state is next, and as long as no + * errors occur this is the next charging stage. + * + * \note If more stages are needed simply define more states in menu.h, include + * them in \ref menu_state[] in menu.c, then add the cases to this function. + * + * \note This algorithm is for Li-Ion batteries. + */ +unsigned char Charge(unsigned char inp) +{ + unsigned char NextState; + + switch (CurrentState) { + case ST_PREQUAL: // First step is prequalification. + + // Charge with the defined prequalifiction-current, and if no errors + // occur return ST_CCURRENT as the next state. + ChargeParameters.Current = BAT_CURRENT_PREQUAL; + ChargeParameters.NextState = ST_CCURRENT; + + // We want charging to halt if voltage reaches a limit or time runs out. + // In case of timeout the battery will be flagged as exhausted, and an + // error will be flagged. + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_FLAG_EXHAUSTION); + + // Set the maximum temperature and charge voltage limit. + HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + + // Start PWM output and charging timer first. + PWM_Start(); + Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + + // Call the constant current charging-function. + // If all goes well, we will get ST_CCURRENT in return. + NextState = ConstantCurrent(); + break; + + + case ST_CCURRENT: // Second step is constant current charging. + + // Set charging timer to the battery's maximum charge time. + Time_Set(TIMER_CHG,BattData.MaxTime,0,0); + + // Charge at the battery's maximum current, go to ST_CVOLTAGE next. + ChargeParameters.Current = BattData.MaxCurrent; + ChargeParameters.NextState = ST_CVOLTAGE; + + + // Charge until the defined BatChargeVoltage is reached. + HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + + // Start charging using constant current. + NextState = ConstantCurrent(); + break; + + + case ST_CVOLTAGE: // Third step is constant voltage charging. + + // Charge with the defined charge-voltage, go to ST_ENDCHARGE next. + ChargeParameters.Voltage = BAT_VOLTAGE_MAX; + ChargeParameters.NextState = ST_ENDCHARGE; + + // We want charging to halt if temperature rises too high, if current + // sinks below limit, or time runs out. Also, flag error if temperature + // limit is reached. Timeout doesn't mean anything is wrong at this point. + HaltParameters.HaltFlags = (HALT_CURRENT_MIN | HALT_TIME); + + HaltParameters.CurrentMin = BattData.MinCurrent; + + // Start charging using constant voltage. We will continue on the + // timer started in ST_CCURRENT. + NextState = ConstantVoltage(); + break; + + + case ST_ENDCHARGE: // Charging is done! + + PWM_Stop(); + BattData.Charged = TRUE; + + // If the other battery is enabled go to ST_BATCON, otherwise + // go to ST_SLEEP. + if (eeprom_read_byte(&BattControl[(BattActive+1)%2]) & BIT_BATTERY_ENABLED) { + NextState = ST_BATCON; + } else { + NextState = ST_SLEEP; + } + break; + + + default: // Shouldn't end up here. Reinitialize for safety. + NextState = ST_INIT; + break; + } + + // Return the next state. + return(NextState); +} diff --git a/BaseTinyFirmware/GCC/main.c b/BaseTinyFirmware/GCC/main.c new file mode 100644 index 0000000..62f46d3 --- /dev/null +++ b/BaseTinyFirmware/GCC/main.c @@ -0,0 +1,213 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Main program file + * + * Contains the main program, which is a basic state machine. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2302 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $ + * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +/*! \page License + * Copyright (c) 2007, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL ``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 EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + */ + +#include +#include + +#include + +#include "structs.h" + +#include "main.h" +#include "ADC.h" +#include "statefunc.h" +#include "battery.h" +#include "menu.h" +#include "OWI.h" +#include "PWM.h" +#include "time.h" +#include "USI.h" + + + +//****************************************************************************** +// Globals +//****************************************************************************** +unsigned char CurrentState; //!< \brief Global that indicates current state + //!< + //!< Updated by main(). + //!< \note See menu.h for definition of states. + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Main program + * + * The main function goes into an infinite loop, keeping track of the current + * state and the next one. If the next state is different from the current, it + * looks up the address to the next state function, in \ref menu_state[], and + * updates \ref CurrentState. The state function is then called and will + * eventually return a new state, and so the loop reiterates. + * + * \todo The variable inp is passed to all state functions, but is not used + * for anything yet. Remove? + */ +int main( void ) +{ + unsigned char nextstate, inp, i; + unsigned char (*pStateFunc)(unsigned char); // Function pointer. + + // Initialize local state variables. + inp = ZERO; + CurrentState = nextstate = ST_INIT; + pStateFunc = NULL; + + // Look for function associated with current state, get its address. + for (i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) { + if (pgm_read_byte(&menu_state[i].state) == CurrentState) { + pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc); + } + } + + while (TRUE) { + // Run function associated with current state, get next state in return. + if (pStateFunc != NULL){ + nextstate = pStateFunc(inp); + } + + // Look up function for next state, if it differs from the current. + if (nextstate != CurrentState) { + CurrentState = nextstate; + for ( i = 0; pgm_read_byte(&menu_state[i].state) != 0; i++) { + if (pgm_read_byte(&menu_state[i].state) == CurrentState) { + pStateFunc = (PGM_VOID_P) pgm_read_word(&menu_state[i].pFunc); + } + } + } + } +} + + +/* Doxygen documentation mainpage ********************************************/ +/*! \mainpage + * \section intro Introduction + * This documents the software for application note AVR458. This is a charger + * for Li-Ion batteries, based on ATAVRBC100. + * + * \section compinfo Compilation Info + * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC + * the source have to be modified.\n + * \n + * To make project on IAR EWAVR:\n + * Add the .c files to project (ADC.c, battery.c, main.c, menu.c, + * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c, + * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate + * battery data if needed.\n + * \n + * Use device --cpu=tiny861, enable bit definitions in I/O include files, + * optimization low for debug target and high for release, output format: ubrof8 + * for Debug and intel_extended for Release. \n + * + * \section deviceinfo Device Info + * This application is based on the ATtiny 861, but it is possible to migrate + * the design to other AVR microcontrollers, such as pin-compatible devices + * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be + * used, but with reduced functionality. + * + * Required fuse bit settings: + *
+ *    FUSE BIT  | SETTING
+ *    ----------+--------------------
+ *    CKDIV8    | 1 (unprogrammed)
+ *    CKSEL3..0 | 0010 (internal osc)
+ *    
+ * + * + * \section todo To Do-list + * \todo + * - Finalize master-slave communication protocol + * - Implement discharge mode + * + * \section contactinfo Contact Info + * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n + * For application notes visit + * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n + * Support mail: avr@atmel.com + */ + + +/*! \page misra MISRA C rule violations + * + * \par Rule 1 + * "All code shall conform to ISO 9899 standard C, with no extensions + * permitted." + * + * Extensions are necessary because ISO C has no way of specifying that a + * function should be an interrupt service routine, or that we would like data + * members to be stored in f.ex. EEPROM. + * + * + * \par Rule 37 + * "Bitwise operations shall not be performed on signed integer types." + * + * The compiler assumes all the 1's we shift around to make bitmasks are signed + * integers. Specifying them all to be (unsigned int), either directly or via a + * definition, would fix the rule violations, but also reduce code readability. + * + * + * \par Rule 45 + * "Type casting from any type to or from pointers shall not be used." + * + * Assigning macro NULL, defined in stdlib.h, to a pointer causes this.. + * + * + * \par Rule 96 + * "In the definition of a function-like macro the whole definition, and each + * instance of a parameter, shall be enclosed in parentheses." + * + * It is difficult to use parentheses with void function-like macros. + */ diff --git a/BaseTinyFirmware/GCC/main.h b/BaseTinyFirmware/GCC/main.h new file mode 100644 index 0000000..545f1ff --- /dev/null +++ b/BaseTinyFirmware/GCC/main.h @@ -0,0 +1,65 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for main.c + * + * Contains some basic definitions (FALSE, TRUE, ZERO) as well as + * what battery type (NiMh or Li-Ion) the charger is for. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2302 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.h $ + * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#ifndef _MAIN_H +#define _MAIN_H + + +//****************************************************************************** +// Firmware revision +//****************************************************************************** +#define SWHIGH 1 +#define SWLOW 0 + + +//****************************************************************************** +// Battery type (add appropriate *charge.c to project!) +//****************************************************************************** +// One or the other needs to be defined in the AVR Studio Project file +//#define NIMH //!< Use specs and state menu for NIMH. +//#define LIION //!< Use specs and state menu for LIION. +#if !defined(NIMH) && !defined(LIION) +#error Need to define NIMH or LIION to select charging scheme +#endif + + +//****************************************************************************** +// Basic definitions +//****************************************************************************** +#define FALSE 0 //!< We have to define this ourselves. +#define TRUE (!FALSE) //!< We have to define this ourselves. +#define ZERO 0 //!< We have to define this ourselves. + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern unsigned char CurrentState; + + +#endif //_MAIN_H diff --git a/BaseTinyFirmware/GCC/menu.c b/BaseTinyFirmware/GCC/menu.c new file mode 100644 index 0000000..824bf20 --- /dev/null +++ b/BaseTinyFirmware/GCC/menu.c @@ -0,0 +1,79 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * State menu definition + * + * Contains the definition of the state menu.\n + * The state menu contains all states and adresses to associated functions. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "statefunc.h" +#include "charge.h" +#include "main.h" +#include "menu.h" + + +//****************************************************************************** +// State menu (relies on the proper battery type to be defined in main.h!) +//****************************************************************************** +#ifdef NIMH +/*! \brief The state menu + * + * Contains all the defined states and addresses to their associated functions. + */ +const MENU_STATE_t PROGMEM menu_state[] = { +// State State function + { ST_INIT, Initialize}, + { ST_BATCON, BatteryControl}, + { ST_PREQUAL, Charge}, + { ST_SLEEP, Sleep}, + { ST_FASTCHARGE, Charge}, + { ST_LOWRATECHARGE, Charge}, + { ST_ENDCHARGE, Charge}, + { ST_DISCHARGE, Discharge}, + { ST_ERROR, Error}, + { 0, NULL}, +}; +#endif // NIMH + +#ifdef LIION +/*! \brief The state menu + * + * Contains all the defined states and addresses to their associated functions. + */ +const MENU_STATE_t PROGMEM menu_state[] = { +// State State function + { ST_INIT, Initialize}, + { ST_BATCON, BatteryControl}, + { ST_PREQUAL, Charge}, + { ST_SLEEP, Sleep}, + { ST_CCURRENT, Charge}, + { ST_CVOLTAGE, Charge}, + { ST_ENDCHARGE, Charge}, + { ST_DISCHARGE, Discharge}, + { ST_ERROR, Error}, + { 0, NULL}, +}; +#endif // LIION diff --git a/BaseTinyFirmware/GCC/menu.h b/BaseTinyFirmware/GCC/menu.h new file mode 100644 index 0000000..d07857c --- /dev/null +++ b/BaseTinyFirmware/GCC/menu.h @@ -0,0 +1,73 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for menu.c + * + * Contains definitions of each state and declaration of the state + * menu entry struct. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef MENU_H +#define MENU_H + +#include + + +//****************************************************************************** +// State machine states +//****************************************************************************** +// State machine states -- max size and number of states is 255. +// State values must be larger than zero +#define ST_INIT (10) //!< Identifies initialization state. +#define ST_BATCON (20) //!< Identifies battery control state. +#define ST_PREQUAL (30) //!< Identifies prequalification state. +#define ST_SLEEP (40) //!< Identifies sleep state. +#define ST_FASTCHARGE (50) //!< Identifies fast charge state. +#define ST_LOWRATECHARGE (60) //!< Identifies trickle charge state. +#define ST_ENDCHARGE (70) //!< Identifies end of charge. +#define ST_DISCHARGE (80) //!< Identifies discharge state. +#define ST_ERROR (90) //!< Identifies error state. +#define ST_CCURRENT (100) //!< Identifies constant current charge state. +#define ST_CVOLTAGE (110) //!< Identifies constant voltage charge state. + + +//****************************************************************************** +// Struct declarations +//****************************************************************************** +/*! \brief Holds an entry in the state menu + * + * Contains the ID number of a state, and a pointer to its associated function + */ +struct MENU_STATE_struct +{ + unsigned char state; //!< ID number of state. + unsigned char (*pFunc)(unsigned char inp); //!< Associated function. +}; +typedef struct MENU_STATE_struct MENU_STATE_t; //!< For convenience. + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern const MENU_STATE_t PROGMEM menu_state[]; + +#endif // MENU_H diff --git a/BaseTinyFirmware/GCC/nimhcharge.c b/BaseTinyFirmware/GCC/nimhcharge.c new file mode 100644 index 0000000..1a436cd --- /dev/null +++ b/BaseTinyFirmware/GCC/nimhcharge.c @@ -0,0 +1,179 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Charge state function for NiMH batteries + * + * Contains the charge state function, in which the NiMH charging + * algorithm is, plus the associated functions. + * + * \par Application note: + * AVR463: Charging NiMH Batteries with BC100 \n + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2255 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $ + * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" +#include "structs.h" + +#include "battery.h" +#include "charge.h" +#include "chargefunc.h" +#include "main.h" +#include "menu.h" +#include "NIMHspecs.h" +#include "PWM.h" +#include "time.h" + +#ifndef NIMH +#error NIMH not defined in main.h! +#endif // NIMH + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Controls the charging. + * + * This function contains the charging algorithm itself, divided into stages.\n + * For each stage the PWM may be started/stopped, and the timer, + * halt-requirements and charge parameters may be set.\n + * The charging functions return whatever state is next, and as long as no + * errors occur this is the next charging stage. + * + * \note If more stages are needed simply define more states in menu.h, include + * them in \ref menu_state[] in menu.c, then add the cases to this function. + * + * \note This algorithm is for NiMH batteries. + */ +unsigned char Charge(unsigned char inp) +{ + unsigned char NextState; + + switch (CurrentState) { + // First stage is a prequalification. Attempt to charge battery to 1 V, + // using a 0.1 C current, within 2 minutes. + // If this fails, the battery is likely damaged. + // If it succeeds, start a fast charge. + case ST_PREQUAL: + + // Set up charge current and next state. + ChargeParameters.Current = BattData.Capacity / 10; + ChargeParameters.NextState = ST_FASTCHARGE; + + // Halt charge on voltage limit or timeout. + // Timeout means battery exhaustion. + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_FLAG_EXHAUSTION); + + // Set up voltage limit and temperature limits. + HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + HaltParameters.TemperatureMax = 35; + + // Reset temperature measurement for HaltNow(). + HaltParameters.LastNTC = 0; + + // Start PWM and charge timer before calling the charge function. + PWM_Start(); + Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + + // Call charge function, get next state. + NextState = ConstantCurrent(); + break; + + + // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours, + // until either rate of temperature increase or voltage reaches limit, or + // the voltage drops sufficiently. + // Timeout doesn't mean battery exhaustion now. + case ST_FASTCHARGE: + + // Set up charge current and next state. + ChargeParameters.Current = BattData.Capacity; + ChargeParameters.NextState = ST_LOWRATECHARGE; + + // Halt charge on voltage limit, timeout, voltage drop or rate of + // temperature increase. + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE); + + // Set up limits for voltage, voltage drop, temperature and rate of + // temperature increase (1 degree C per minute). + HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP; + HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + HaltParameters.TemperatureRise = 1; + + // Reset maximum voltage measurement for HaltNow(). + HaltParameters.VBATMax = 0; + + // Start timer, PWM should still be running. + Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0); + + // Call charge function, get next state. + NextState = ConstantCurrent(); + break; + + + // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes, + // until either rate of temperature increase or voltage reaches limit. + case ST_LOWRATECHARGE: + + // Set up charge current and next state. + ChargeParameters.Current = BattData.Capacity / 10; + ChargeParameters.NextState = ST_ENDCHARGE; + + // Halt charge on voltage limit, timeout or temperature rise. + // Use the same requirements as during the last stage (ST_FASTCHARGE). + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_TEMPERATURE_RISE); + + // Start timer, 30 minutes. + Time_Set(TIMER_CHG, 30, 0, 0); + + // Call charge function, get next state. + NextState = ConstantCurrent(); + break; + + + // Charging is done! + case ST_ENDCHARGE: + + // Stop the PWM output and flag battery as charged. + PWM_Stop(); + BattData.Charged = TRUE; + + // If the other battery is enabled go to ST_BATCON, otherwise + // go to ST_SLEEP. + if (eeprom_read_byte(&BattControl[(BattActive+1)%2]) & BIT_BATTERY_ENABLED) { + NextState = ST_BATCON; + } else { + NextState = ST_SLEEP; + } + break; + + + default: // Shouldn't end up here. Reinitialize for safety. + NextState = ST_INIT; + break; + } + + // Return the next state to main(). + return(NextState); +} diff --git a/BaseTinyFirmware/GCC/readme_AVR458.html b/BaseTinyFirmware/GCC/readme_AVR458.html new file mode 100644 index 0000000..7e82c9e --- /dev/null +++ b/BaseTinyFirmware/GCC/readme_AVR458.html @@ -0,0 +1,58 @@ + + + + +ATMEL AVR Doxygen Documentation + + + + + + + + + + + + + + + + + + + + +



+

+ + AVR458: Charging Li-Ion Batteries with BC100 + +

+
+ + 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. +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. + +
+ +

Code documentation

+ +
+
+ Disclaimer: 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. EXCEPT AS SET FORTH IN ATMEL’S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL’S 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. 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’s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.
+
+ © 2006 Atmel Corporation. All rights reserved. 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.
+ + diff --git a/BaseTinyFirmware/GCC/readme_AVR463.html b/BaseTinyFirmware/GCC/readme_AVR463.html new file mode 100644 index 0000000..523775a --- /dev/null +++ b/BaseTinyFirmware/GCC/readme_AVR463.html @@ -0,0 +1,58 @@ + + + + +ATMEL AVR Doxygen Documentation + + + + + + + + + + + + + + + + + + + + +



+

+ + AVR458: Charging Li-Ion Batteries with BC100 + +

+
+ +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. +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. + +
+ +

Code documentation

+ +
+
+ Disclaimer: 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. EXCEPT AS SET FORTH IN ATMEL’S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL’S 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. 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’s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.
+
+ © 2006 Atmel Corporation. All rights reserved. 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.
+ + diff --git a/BaseTinyFirmware/GCC/statefunc.c b/BaseTinyFirmware/GCC/statefunc.c new file mode 100644 index 0000000..9df2b5c --- /dev/null +++ b/BaseTinyFirmware/GCC/statefunc.c @@ -0,0 +1,426 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * State functions + * + * Contains the functions related to the states defined in menu.h.\n + * Also contains related functions, i.e. for checking jumpers, setting + * error flags and "dozing". + * + * \note The state function Charge() is in a separate file since it + * should easily be changed with regard to battery type. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "structs.h" +#include "enums.h" + +#include "ADC.h" +#include "statefunc.h" +#include "battery.h" +#include "charge.h" +#include "main.h" +#include "menu.h" +#include "OWI.h" +#include "PWM.h" +#include "time.h" +#include "USI.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +unsigned char ErrorFlags; //!< \brief Holds error flags. + //!< \note See statefunc.h for definitions of flags. + +//! \brief Holds the state in which latest error flag was set. +//! \note See menu.h for definitions of states. +unsigned char ErrorState; + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Initialization + * + * - Sets the system clock prescaler to 1 (run at 8 MHz) + * - Initializes the one-wire interface + * - Clears on-chip EEPROM + * - Sets battery enable pins as outputs, then disables batteries + * - Initializes SPI according to \ref SPIMODE + * - Initializes ADC + * - Initializes timers + * - Reads battery data from both battery inputs (via ADC) + * - Disables batteries again + * - Sets battery A as the current one (\ref BattActive = 0) + * - Clears ErrorFlags + * + * \param inp Not used. + * + * \retval ST_BATCON Next state in the sequence. + */ +unsigned char Initialize(unsigned char inp) +{ + unsigned char i, page; + + // Disable interrupts while setting prescaler. + cli(); + + CLKPR = (1< 8 MHz clock frequency. + + // Init 1-Wire(R) interface. + OWI_Init(OWIBUS); + + // Clear on-chip EEPROM. + for (page = 0; page < 4; page++) { + for (i = 0; i < 32; i++) { + eeprom_write_byte(&BattEEPROM[page][i], 0); + } + } + + DDRB = (1< check load and jumper J405 and J406. + if (abs(ADCS.IBAT) > 100) { + PWM_Stop(); + return(FALSE); + } + + // If the PWM output can't be increased high enough -> check jumpers + // J400-J404, J407 and J408. + if (!PWM_IncrementDutyCycle()) { + PWM_Stop(); + return(FALSE); + } + + // Wait for ADC conversions to complete + ADC_Wait(); + } while (Time_Left(TIMER_GEN)); + + + // If we end up here, the measurements took too long. + PWM_Stop(); + return(FALSE); +} diff --git a/BaseTinyFirmware/GCC/statefunc.h b/BaseTinyFirmware/GCC/statefunc.h new file mode 100644 index 0000000..9594f44 --- /dev/null +++ b/BaseTinyFirmware/GCC/statefunc.h @@ -0,0 +1,83 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for statefunc.c + * + * Contains definitions for SPI mode and error identifiers. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef STATEFUNC_H +#define STATEFUNC_H + + +//****************************************************************************** +// Wanted SPI-mode +//****************************************************************************** +//! Sample on leading _rising_ edge, setup on trailing _falling_ edge. +#define SPIMODE 0 + +//! Sample on leading _falling_ edge, setup on trailing _rising_ edge. +//#define SPIMODE 1 + + +//****************************************************************************** +// Typical and maximum voltage difference between supply and battery +//****************************************************************************** +//! Typical difference between VIN and VBAT, in mV. +#define VIN_VBAT_DIFF_TYP 600 + +//! Maximum allowed difference between VIN - VIN_VBAT_DIFF_TYP and VBAT, in mV. +#define VIN_VBAT_DIFF_MAX 500 + + +//****************************************************************************** +// Error-flag bit identifiers +//****************************************************************************** +//! Wrong jumper settings. +#define ERR_JUMPER_MISMATCH 0x01 + +//! Both batteries disabled. +#define ERR_NO_BATTERIES_ENABLED 0x02 + +//! PWM output too much/little. +#define ERR_PWM_CONTROL 0x04 + +//! Battery temperature out of limits. +#define ERR_BATTERY_TEMPERATURE 0x08 + +//! Battery couldn't be charged. +#define ERR_BATTERY_EXHAUSTED 0x10 + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char Initialize(unsigned char); +unsigned char BatteryControl(unsigned char); +unsigned char Discharge(unsigned char); +unsigned char Sleep(unsigned char); +void Doze(void); +unsigned char Error(unsigned char); +void SetErrorFlag(unsigned char); +unsigned char JumperCheck(void); + +#endif // STATEFUNC_H diff --git a/BaseTinyFirmware/GCC/structs.h b/BaseTinyFirmware/GCC/structs.h new file mode 100644 index 0000000..a78b9c1 --- /dev/null +++ b/BaseTinyFirmware/GCC/structs.h @@ -0,0 +1,100 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Structs in common for Slave and Master + * + * Contains struct declarations for ADC.c and battery.c.\n + * These are also used in the Master, and have therefore been + * put in a separate file for convenience. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/structs.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + + +#ifndef STRUCTS_H +#define STRUCTS_H + + +//****************************************************************************** +// Battery struct declarations +//****************************************************************************** +/*! \brief Holds status and various data for a battery + * + * These data are updated by BatteryStatusRefresh(), RIDLookUp(), + * NTCLookUp() and BatteryDataRefresh(). + */ +struct Batteries_struct +{ + unsigned char Present : 1; //!< Battery found. (TRUE/FALSE) + unsigned char Charged : 1; //!< Battery fully charged. (TRUE/FALSE) + unsigned char Low : 1; //!< Battery low voltage. (TRUE/FALSE) + unsigned char Exhausted : 1; //!< Battery exhausted. (TRUE/FALSE) + unsigned char HasRID : 1; //!< Battery has resistor ID. (TRUE/FALSE) + unsigned char Circuit; //!< Battery safety circuit (family id). + signed char Temperature; //!< Battery temperature, in centigrade. + unsigned char ADCSteps; //!< ADC steps per half degree. + unsigned int Capacity; //!< Capacity, in mAh. + unsigned int MaxCurrent; //!< Charge current, in mA. + unsigned int MaxTime; //!< Charge cut-off time, in minutes. + unsigned int MinCurrent; //!< Cut-off current, in mA. +}; +typedef struct Batteries_struct Batteries_t; //!< For convenience. + + +// KMR: These definitions are in structs.h because they are a conversion +// of Atmel's original IAR code which used a bitfield structs for the +// type Battery_t. However, porting to GCC/avr-libc makes the use of a +// bitfield struct for acceessing an EEPROM value cumbersome. +// So, bitmasks on a uint8_t are now used insteads of a bitfield struct. +// These bitmasks could be moved to battery.h, but are left here for easier +// comparison to changes in Atmel's IAR code. +#define BIT_BATTERY_ENABLED 0x01 //! Battery valid, enabling allowed. +#define BIT_BATTERY_DISCONNECT_ALLOWED 0x02 //! Disconnect allowed. +#define BIT_BATTERY_CHARGE_INHIBIT 0x04 //! Inhibit charging. \todo Changed by master? +typedef uint8_t Battery_t; //!< For convenience. + + +//****************************************************************************** +// ADC status struct declaration +//****************************************************************************** +/*! \brief Holds ADC-status and samples + * + * Is updated by ADC_ISR(). + */ +struct ADC_Status_struct +{ + unsigned char MUX : 5; //!< Corresponds to ADMUX low bits MUX4..0. + unsigned char Flag : 1; //!< ADC cycle complete (TRUE/FALSE). + unsigned char Mains : 1; //!< Mains OK? (TRUE/FALSE). + unsigned char Halt : 1; //!< Stop A/D-conversions (TRUE/FALSE). + unsigned char ADC3_G20_OS : 4; //!< Offset on ADC3 at 20x gain. + unsigned char ADC5_G20_OS : 4; //!< Offset on ADC5 at 20x gain. + unsigned int rawRID; //!< Raw, unconditioned resistor ID data. + unsigned int rawNTC; //!< Raw, unconditioned thermistor data. + unsigned int rawVBAT; //!< Raw, unconditioned battery voltage. + unsigned int VIN; //!< Supply voltage, in mV. + unsigned int VBAT; //!< Battery voltage, in mV. + signed int IBAT; //!< Battery current, in mA. + signed int discIBAT[4]; //!< Discrete battery current readings, in mA. + signed int avgIBAT; //!< Average of the last four IBAT readings, in mA. +}; +typedef struct ADC_Status_struct ADC_Status_t; //!< For convenience. + + +#endif // STRUCTS_H diff --git a/BaseTinyFirmware/GCC/time.c b/BaseTinyFirmware/GCC/time.c new file mode 100644 index 0000000..ee738bd --- /dev/null +++ b/BaseTinyFirmware/GCC/time.c @@ -0,0 +1,161 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for timing + * + * Contains functions to initialize, set, poll and stop timers. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include + +#include "enums.h" + +#include "main.h" +#include "time.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +unsigned long timeval[TIMERS]; //!< Contains the values for each timer. + +// timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms +//#pragma vector = TIM0_OVF_vect + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Interrupt service routine for timer 0 overflow + * + * Timer 0 runs at 125 kHz and compare match will occur every millisecond + * (125 / 125 kHz = 1.0 ms), which will result in a call to this function. + * When called, this function will decrement the time left for each timer, + * unless they are already at zero. + */ +ISR(TIMER0_COMPA_vect) +{ + unsigned char i; + + // 1 ms has passed, decrement all non-zero timers. + for (i = 0; i < TIMERS; i++) { + if(timeval[i] > 0) { + timeval[i]--; + } + } +} + + +/*! \brief Checks if a specified timer has expired + * + * \param timer Specifies timer + * + * \retval TRUE Timer still going. + * \retval FALSE Timer has expired. + */ +unsigned char Time_Left(unsigned char timer) +{ + if(timeval[timer] > 0) { + return(TRUE); + } else { + return(FALSE); + } +} + + +/*! \brief Sets the specified timer + * + * \param timer Specifies timer + * \param min Minutes for timer to count down + * \param sec Seconds for timer to count down + * \param ms Milliseconds for timer to count down + */ +void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, + unsigned char ms) +{ +// timeval[i] = 4 * (1000*(sec + 60*min) + ms); // about 4000 ticks per second +// timeval[i] = 240000 * (unsigned long)min; +// timeval[i] += 4000 * (unsigned long)sec; +// timeval[i] += 4 * (unsigned long)ms; + + timeval[timer] = 60000 * (unsigned long)min; + timeval[timer] += 1000 * (unsigned long)sec; + timeval[timer] += 1 * (unsigned long)ms; +} + + +/*! \brief Stops timers + * + * Sets timer0's clock source to none. + */ +void Time_Stop(void) +{ + TCCR0B = 0; +} + + +/*! \brief Starts timers + * + * Sets timer0's clock source to system clock divided by 64. + */ +void Time_Start(void) +{ + TCCR0B = (0< +#include + +#include "structs.h" + +#include "main.h" +#include "ADC.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +// ADC status struct. +//! \brief Holds sampled data and ADC-status +ADC_Status_t ADCS; + + +/*! \brief Indicates maximum battery voltage. + * + * This variable is stored in EEPROM and indicates how much the battery voltage + * is downscaled by HW before it is sampled. The amount of downscaling depends + * on the maximum battery voltage, and is necessary to avoid saturation of the + * ADC (reference voltage is 2.5 V). + * + * \note Used by the ADC ISR when calling ScaleU() and ScaleI(). + * + * \note Defaults to 1, which means 10 V max battery voltage. + * + * \note Table of settings: + *
+ * VBAT_RANGE | Max battery voltage | Jumper setting
+ *         0  |             5V      |        1/2
+ *         1  |            10V      |        1/4
+ *         2  |            20V      |        1/8
+ *         3  |            30V      |       1/12
+ *         4  |            40V      |       1/16
+ * 
+ */ +// Maximum battery voltage (affects scaling of samples). +__eeprom unsigned char VBAT_RANGE = 1; + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Interrupt Service routine for ADC. + * + * This ISR stores the sampled values in the ADC status-struct, then + * updates the ADC MUX to the next channel in the scanning-sequence.\n + * Once the sequence is completed, ADCS.Flag is set and unless + * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC + * is disabled.\n + * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. + * + * \note Table of scanning sequence: + *
+ * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed
+ * ----+--------+----------+----------+------+---------+-------
+ *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no
+ *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no
+ *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no
+ *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no
+ *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no
+ *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no
+ *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no
+ *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes
+ * 
+ * + * \todo IIN (#7 in sequence) is never used. + * + * \todo Signed is never set. Signed measurements of IBAT will halve the + * measuring sensitivity, and is therefore not favourable. At the moment, + * great currents (f.ex. if something happens with the battery) will be + * interpreted as negative, which might cause unfavourable behaviour during + * charging (depending on what PWM behaviour is defined), f.ex. + * ConstantCurrent() will keep increasing the PWM output. This results in an + * PWM controller error being flagged and the program going into + * error-state and eventually reinitializing. + */ +#pragma vector=ADC_vect +__interrupt void ADC_ISR(void) +{ + static unsigned char avgIndex = 0; + unsigned char i, Next, Signed; + signed int temp = 0; + + Signed = FALSE; // Presume next conversion is unipolar. + ADCSRA &= ~(1< ADC1 (PA1) = NTC + case 0x01: + ADCS.rawNTC = ADC; + Next=0x02; + break; + + + // MUX = 0b000010 => ADC2 (PA2) = RID + case 0x02: + ADCS.rawRID = ADC; + Next=0x03; + break; + + + // MUX = 0b000011 => ADC3 (PA4) = VIN- + case 0x03: + // Supply voltage is always divided by 16. + ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short. + + // Is mains failing? + if (ADCS.VIN < VIN_MIN) { + ADCS.Mains = FALSE; + } else { + ADCS.Mains = TRUE; + } + + Next=0x05; + break; + + + // MUX = 0b000101 => ADC5 (PA6) = VBAT- + case 0x05: + ADCS.rawVBAT = ADC; + + // Scale voltage according to jumper setting. + ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short. + Next=0x17; +// Signed = TRUE; // Next conversion is bipolar. Halves sensitivity! + break; + + + case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT + // If bipolar, from -512 to 0, to 511: + // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF + + // Scale sample according to jumper setting, handle negative numbers. + if (ADC > 511) { + ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE, + (1024 - (ADC-ADCS.ADC5_G20_OS))); + } else if (ADC > 0) { + ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS)); + } else { + ADCS.IBAT = 0; + } + + // Insert sample of battery current into the averaging-array + // (overwriting the oldest sample), then recalculate and store the + // average. This is the last conversion in the sequence, so + // flag a complete ADC-cycle and restart sequence. + ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT; + for (i = 0; i < 4 ; i++) { + temp += ADCS.discIBAT[i]; + } + + ADCS.avgIBAT = (temp / 4); + + ADCS.Flag = TRUE; + Next=0x01; + Signed = FALSE; // This is the only bipolar conversion. + break; + + + default: // Should not happen. (Invalid MUX-channel) + Next=0x01; // Start at the beginning of sequence. + break; + } + + // Update MUX to next channel in sequence, set a bipolar conversion if + // this has been flagged. + ADCS.MUX = Next; + ADMUX = (1< + * Presume VREF = 2.5V and Gain = 1x. + * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB + * setting | source | R1 | R2/(R1+R2) | UADC(LSB) | U(MAX) + * --------+--------+------+------------+-----------+------- + * N/A | | - | - | 2.441mV | 2.50V + * 0 | VBAT | 10k | 1/2 | 4.883mV | 5.00V + * 1 | VBAT | 30k | 1/4 | 9.766mV | 9.99V + * 2 | VBAT | 70k | 1/8 | 19.53mV | 19.98V + * 3 | VBAT | 110k | 1/12 | 29.30mV | 29.97V + * 4 | VBAT | 150k | 1/16 | 39.06mV | 39.96V + * 4 | VIN | 150k | 1/16 | 39.06mV | 39.96V + * + */ +unsigned int ScaleU(unsigned char setting, unsigned int data) +{ + // Temporary variable needed. + unsigned int scaled = 0; + + // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16 + if (setting == 3) { + scaled = 29 * data; + scaled += (data >> 2); + scaled += (data >> 4); + } else { + // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16 + scaled = 39 * data; + scaled += (data >> 4); + + if (setting <3) { + // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8 + // 1: mV/LSB = 9.766 = 39.06 / 4 + // 2: mV/LSB = 19.53 = 39.06 / 2 + scaled = (scaled >> (3-setting)); + } + } + + return(scaled); +} + + +/*! \brief Scales sample to represent "actual current" in mA. + * + * This function returns the actual sampled current, scaled according + * to the jumper settings. + * + * \param setting Indicates what downscaling was used. + * \param data The sampled value. + * + * \note Table for setting-parameter:\n + *
+ * Presume VREF = 2.5V and Gain = 1x or 20x.
+ * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
+ * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
+ * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain
+ * --------+------+------------+----------+----------+--------+-----
+ *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x
+ *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x
+ *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x
+ *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x
+ *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x
+ *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x
+ *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x
+ * 
+ */ +unsigned int ScaleI(unsigned char setting, unsigned int data) +{ + // Temporary variable needed. + unsigned int scaled = 0; + + // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128 + if (setting == 3) { + scaled = 21 * data; + scaled -= (data >> 4); + scaled += (data >> 7); + } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32 + scaled = 28 * data; + scaled -= (data >> 3); + scaled += (data >> 5); + + if (setting <3) { + // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8 + // 1: mA/LSB = 6.978mA = 27.909 / 4 + // 2: mA/LSB = 13.955mA = 27.909 / 2 + scaled = (scaled >> (3-setting)); + } + } + + return(scaled); +} + + +/*! \brief Waits for two full cycles of ADC-conversions to occur. + * + * This function clears the cycle complete-flag, then waits for it to be set + * again. This is then repeated once before the function exits. + * + */ +void ADC_Wait(void) +{ + // Clear ADC flag and wait for cycle to complete. + ADCS.Flag = FALSE; + do { + } while (ADCS.Flag == FALSE); + + // Repeat, so we are sure the data beong to the same cycle. + ADCS.Flag = FALSE; + do { + } while (ADCS.Flag == FALSE); +} + + +/*! \brief Initializes ADC and input pins. + * + * This function initializes the ADC to free running mode, sampling from + * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n + * It also measures and stores calibration data for offset. + * + * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway. + * + * \note Table of MUX settings for offset measurement: + *
+ *    Ch | Pin |    Gain |    MUX
+ * ------+-----+---------+-------
+ *  ADC1 | PA1 |     20x | 001101
+ *  ADC3 | PA4 |     20x | 010001
+ *  ADC5 | PA6 |     20x | 010110
+ *  ADC9 | PB6 |     20x | 011011
+ *  ADC0 | PA0 | 20x/32x | 111000
+ *  ADC0 | PA0 |   1x/8x | 111001
+ *  ADC1 | PA1 | 20x/32x | 111010
+ *  ADC2 | PA2 | 20x/32x | 111011
+ *  ADC4 | PA5 | 20x/32x | 111100
+ *  ADC5 | PA6 | 20x/32x | 111101
+ *  ADC6 | PA7 | 20x/32x | 111110
+ * 
+ */ +void ADC_Init(void) +{ + unsigned char i; + + __disable_interrupt(); + + ADCS.Halt = FALSE; // Enable consecutive runs of ADC. + + // Configure ADC pins (inputs and disabled pull-ups). + DDRA &= ~((1< + + + 2 + 373717447 + + Debug + + $PROJ_DIR$\Debug\Obj\USI.r90 + $PROJ_DIR$\Debug\List\NIMHcharge.lst + $PROJ_DIR$\Debug\List\OWIcrc.lst + $PROJ_DIR$\time.h + $PROJ_DIR$\Debug\Obj\LIIONcharge.pbi + $PROJ_DIR$\main.h + $PROJ_DIR$\AVR458.c + $PROJ_DIR$\Debug\List\BC100_tiny.html + $PROJ_DIR$\Debug\List\battery.s90 + $PROJ_DIR$\chargefunc.c + $PROJ_DIR$\charge.c + $PROJ_DIR$\ADC.c + $PROJ_DIR$\battery.c + $PROJ_DIR$\LIIONcharge.c + $PROJ_DIR$\main.c + $PROJ_DIR$\menu.c + $PROJ_DIR$\NIMHcharge.c + $PROJ_DIR$\OWI.c + $PROJ_DIR$\PWM.c + $PROJ_DIR$\statefunc.c + $PROJ_DIR$\time.c + $PROJ_DIR$\USI.c + $PROJ_DIR$\Debug\List\PWM.s90 + $PROJ_DIR$\LIIONspecs.h + $PROJ_DIR$\Debug\Obj\statefunc.r90 + $TOOLKIT_DIR$\src\template\cfg1soim.xcl + $PROJ_DIR$\Debug\List\USI.s90 + $PROJ_DIR$\Debug\Obj\charge.r90 + $PROJ_DIR$\structs.h + $PROJ_DIR$\Debug\List\charge.lst + $PROJ_DIR$\Debug\Exe\BC100_tiny.d90 + $TOOLKIT_DIR$\inc\clib\stdlib.h + $PROJ_DIR$\NIMHspecs.h + $TOOLKIT_DIR$\src\template\cfgtiny861.xcl + $PROJ_DIR$\PWM.h + $PROJ_DIR$\Debug\Obj\ADC.r90 + $PROJ_DIR$\AVR463.c + $PROJ_DIR$\Debug\List\OWI.s90 + $PROJ_DIR$\Debug\List\main.lst + $PROJ_DIR$\Debug\List\USI.lst + $PROJ_DIR$\AVR463.h + $PROJ_DIR$\Debug\Obj\BC100_tiny.pbd + $PROJ_DIR$\Debug\List\main.s90 + $TOOLKIT_DIR$\inc\clib\sysmac.h + $PROJ_DIR$\Debug\Obj\battery.pbi + $PROJ_DIR$\Debug\Obj\NIMHcharge.pbi + $TOOLKIT_DIR$\inc\iomacro.h + $PROJ_DIR$\Debug\Obj\ADC.pbi + $PROJ_DIR$\Debug\Obj\charge.pbi + $PROJ_DIR$\Debug\Obj\OWI.r90 + $PROJ_DIR$\Debug\List\chargefunc.s90 + $PROJ_DIR$\Debug\Obj\time.r90 + $PROJ_DIR$\Debug\Obj\statefunc.pbi + $PROJ_DIR$\Debug\List\menu.s90 + $PROJ_DIR$\OWIcrc.h + $PROJ_DIR$\Debug\List\time.lst + $PROJ_DIR$\Debug\Obj\NIMHcharge.r90 + $PROJ_DIR$\Debug\Obj\OWIcrc.pbi + $PROJ_DIR$\Debug\Obj\AVR463.pbi + $PROJ_DIR$\Debug\List\battery.lst + $PROJ_DIR$\battery.h + $PROJ_DIR$\Debug\Obj\main.r90 + $PROJ_DIR$\Debug\List\statefunc.s90 + $TOOLKIT_DIR$\inc\iotiny861.h + $PROJ_DIR$\USI.h + $PROJ_DIR$\Debug\Obj\time.pbi + $PROJ_DIR$\Debug\Obj\OWI.pbi + $PROJ_DIR$\Debug\List\PWM.lst + $PROJ_DIR$\Debug\List\AVR458.lst + $PROJ_DIR$\Debug\Obj\menu.r90 + $PROJ_DIR$\Debug\Obj\PWM.pbi + $PROJ_DIR$\ADC.h + $PROJ_DIR$\Debug\List\AVR458.s90 + $PROJ_DIR$\Debug\List\menu.lst + $PROJ_DIR$\statefunc.h + $PROJ_DIR$\Debug\List\NIMHcharge.s90 + $TOOLKIT_DIR$\inc\inavr.h + $PROJ_DIR$\Debug\List\ADC.lst + $PROJ_DIR$\Debug\Obj\LIIONcharge.r90 + $PROJ_DIR$\Debug\List\OWIcrc.s90 + $PROJ_DIR$\OWIcrc.c + $PROJ_DIR$\menu.h + $PROJ_DIR$\Debug\Obj\AVR463.r90 + $PROJ_DIR$\Debug\Obj\OWIcrc.r90 + $PROJ_DIR$\Debug\Obj\chargefunc.r90 + $PROJ_DIR$\charge.h + $TOOLKIT_DIR$\inc\ioavr.h + $PROJ_DIR$\Debug\Obj\PWM.r90 + $PROJ_DIR$\Debug\List\OWI.lst + $PROJ_DIR$\Debug\Obj\battery.r90 + $TOOLKIT_DIR$\inc\intrinsics.h + $PROJ_DIR$\Debug\List\ADC.s90 + $PROJ_DIR$\Debug\List\chargefunc.lst + $PROJ_DIR$\enums.h + $PROJ_DIR$\AVR458.h + $PROJ_DIR$\Debug\Obj\AVR458.r90 + $PROJ_DIR$\Debug\List\time.s90 + $PROJ_DIR$\OWI.h + $PROJ_DIR$\Debug\Obj\chargefunc.pbi + $PROJ_DIR$\chargefunc.h + $TOOLKIT_DIR$\lib\clib\cl1s-ec_nomul.r90 + $PROJ_DIR$\Debug\Obj\menu.pbi + $PROJ_DIR$\Debug\List\statefunc.lst + $PROJ_DIR$\Debug\List\charge.s90 + $PROJ_DIR$\Debug\Obj\AVR458.pbi + $PROJ_DIR$\Debug\Obj\USI.pbi + $PROJ_DIR$\Debug\Obj\main.pbi + + + $PROJ_DIR$\AVR458.c + + + ICCAVR + 95 72 68 + + + BICOMP + 104 + + + + + ICCAVR + 86 63 46 76 90 31 43 28 93 71 94 60 5 81 97 34 3 64 + + + BICOMP + 86 63 46 76 90 31 43 28 93 71 94 60 5 81 97 34 3 64 + + + + + $PROJ_DIR$\chargefunc.c + + + ICCAVR + 84 50 92 + + + BICOMP + 98 + + + + + ICCAVR + 86 63 46 93 28 71 60 99 5 81 34 74 3 32 + + + BICOMP + 86 63 46 93 28 71 60 99 5 81 34 74 3 32 + + + + + $PROJ_DIR$\charge.c + + + ICCAVR + 27 103 29 + + + BICOMP + 48 + + + + + ICCAVR + 86 63 46 93 28 71 74 85 60 5 81 34 3 + + + BICOMP + 86 63 46 93 28 71 74 85 60 5 81 34 3 + + + + + $PROJ_DIR$\ADC.c + + + ICCAVR + 35 91 77 + + + BICOMP + 47 + + + + + ICCAVR + 86 63 46 76 90 28 5 71 + + + BICOMP + 86 63 46 76 90 28 5 71 + + + + + $PROJ_DIR$\battery.c + + + ICCAVR + 89 8 59 + + + BICOMP + 44 + + + + + ICCAVR + 86 63 46 76 90 28 93 71 60 5 97 3 32 + + + BICOMP + 86 63 46 76 90 28 93 71 60 5 97 3 32 + + + + + $PROJ_DIR$\LIIONcharge.c + + + ICCAVR + 78 + + + BICOMP + 4 + + + + + ICCAVR + 86 63 46 93 28 60 85 99 5 81 23 34 3 + + + BICOMP + 86 63 46 93 28 60 85 99 5 81 23 34 3 + + + + + $PROJ_DIR$\main.c + + + ICCAVR + 61 42 38 + + + BICOMP + 106 + + + + + ICCAVR + 86 63 46 76 90 31 43 28 5 71 74 60 81 97 34 3 64 + + + BICOMP + 86 63 46 76 90 31 43 28 5 71 74 60 81 97 34 3 64 + + + + + $PROJ_DIR$\menu.c + + + ICCAVR + 69 53 73 + + + BICOMP + 101 + + + + + ICCAVR + 31 43 74 85 5 81 + + + BICOMP + 31 43 74 85 5 81 + + + + + $PROJ_DIR$\NIMHcharge.c + + + ICCAVR + 56 75 1 + + + BICOMP + 45 + + + + + ICCAVR + 86 63 46 93 28 60 85 99 5 81 32 34 3 + + + BICOMP + 86 63 46 93 28 60 85 99 5 81 32 34 3 + + + + + $PROJ_DIR$\OWI.c + + + ICCAVR + 49 37 88 + + + BICOMP + 66 + + + + + ICCAVR + 86 63 46 76 90 97 + + + BICOMP + 86 63 46 76 90 97 + + + + + $PROJ_DIR$\PWM.c + + + ICCAVR + 87 22 67 + + + BICOMP + 70 + + + + + ICCAVR + 86 63 46 93 5 34 3 + + + BICOMP + 86 63 46 93 5 34 3 + + + + + $PROJ_DIR$\statefunc.c + + + ICCAVR + 24 62 102 + + + BICOMP + 52 + + + + + ICCAVR + 86 63 46 76 90 31 43 28 93 71 74 60 85 5 81 97 34 3 64 + + + BICOMP + 86 63 46 76 90 31 43 28 93 71 74 60 85 5 81 97 34 3 64 + + + + + $PROJ_DIR$\time.c + + + ICCAVR + 51 96 55 + + + BICOMP + 65 + + + + + ICCAVR + 86 63 46 76 90 93 5 3 + + + BICOMP + 86 63 46 76 90 93 5 3 + + + + + $PROJ_DIR$\USI.c + + + ICCAVR + 0 26 39 + + + BICOMP + 105 + + + + + ICCAVR + 86 63 46 76 90 93 28 5 71 60 3 64 + + + BICOMP + 86 63 46 76 90 93 28 5 71 60 3 64 + + + + + [ROOT_NODE] + + + XLINK + 30 7 + + + + + $PROJ_DIR$\Debug\Exe\BC100_tiny.d90 + + + XLINK + 7 + + + + + XLINK + 33 25 35 56 49 87 0 89 84 61 69 24 51 100 + + + + + $PROJ_DIR$\AVR463.c + + + ICCAVR + 82 + + + BICOMP + 58 + + + + + BICOMP + 86 63 46 76 90 31 43 28 93 71 40 60 85 5 81 97 34 3 64 + + + + + $PROJ_DIR$\Debug\Obj\BC100_tiny.pbd + + + BILINK + 47 45 66 70 105 44 98 106 101 52 65 + + + + + $PROJ_DIR$\OWIcrc.c + + + ICCAVR + 83 79 2 + + + BICOMP + 57 + + + + + ICCAVR + 54 97 86 63 46 + + + BICOMP + 54 97 86 63 46 + + + + + [MULTI_TOOL] + XLINK + + + + Release + + $PROJ_DIR$\Release\List\main.s90 + $PROJ_DIR$\Release\List\menu.s90 + $PROJ_DIR$\Release\List\time.s90 + $PROJ_DIR$\Release\List\statefunc.s90 + $PROJ_DIR$\Release\List\statefunc.lst + $PROJ_DIR$\Release\List\chargefunc.s90 + $PROJ_DIR$\Release\Obj\chargefunc.pbi + $PROJ_DIR$\Release\List\OWI.s90 + $PROJ_DIR$\Release\List\ADC.s90 + $PROJ_DIR$\Release\List\PWM.s90 + $PROJ_DIR$\Release\Obj\LIIONcharge.pbi + $PROJ_DIR$\Release\List\NIMHcharge.s90 + $PROJ_DIR$\Release\Obj\LIIONcharge.r90 + $PROJ_DIR$\Release\Obj\chargefunc.r90 + $PROJ_DIR$\time.h + $PROJ_DIR$\main.h + $PROJ_DIR$\AVR458.c + $PROJ_DIR$\Release\Obj\main.pbi + $PROJ_DIR$\Release\Exe\BC100_tiny_data.hex + $PROJ_DIR$\Release\Obj\AVR458.r90 + $PROJ_DIR$\Release\Obj\NIMHcharge.pbi + $PROJ_DIR$\Release\Obj\time.pbi + $PROJ_DIR$\Release\Obj\OWIcrc.r90 + $PROJ_DIR$\Release\List\OWI.lst + $PROJ_DIR$\Release\Obj\NIMHcharge.r90 + $PROJ_DIR$\Release\Obj\battery.r90 + $PROJ_DIR$\chargefunc.c + $PROJ_DIR$\ADC.c + $PROJ_DIR$\battery.c + $PROJ_DIR$\LIIONcharge.c + $PROJ_DIR$\main.c + $PROJ_DIR$\menu.c + $PROJ_DIR$\NIMHcharge.c + $PROJ_DIR$\OWI.c + $PROJ_DIR$\PWM.c + $PROJ_DIR$\statefunc.c + $PROJ_DIR$\time.c + $PROJ_DIR$\USI.c + $PROJ_DIR$\Release\List\NIMHcharge.lst + $PROJ_DIR$\Release\List\USI.s90 + $PROJ_DIR$\Release\List\battery.s90 + $PROJ_DIR$\Release\List\chargefunc.lst + $PROJ_DIR$\LIIONspecs.h + $TOOLKIT_DIR$\src\template\cfg1soim.xcl + $PROJ_DIR$\structs.h + $TOOLKIT_DIR$\inc\clib\stdlib.h + $PROJ_DIR$\NIMHspecs.h + $TOOLKIT_DIR$\src\template\cfgtiny861.xcl + $PROJ_DIR$\PWM.h + $PROJ_DIR$\Release\Obj\PWM.r90 + $PROJ_DIR$\Release\List\OWIcrc.lst + $PROJ_DIR$\Release\Obj\ADC.pbi + $PROJ_DIR$\Release\Obj\OWI.pbi + $PROJ_DIR$\Release\Obj\time.r90 + $PROJ_DIR$\Release\Exe\BC100_tiny_eeprom.hex + $PROJ_DIR$\Release\Obj\statefunc.r90 + $PROJ_DIR$\Release\List\USI.lst + $PROJ_DIR$\Release\List\menu.lst + $PROJ_DIR$\Release\List\BC100_tiny.map + $PROJ_DIR$\Release\Obj\ADC.r90 + $PROJ_DIR$\Release\List\time.lst + $PROJ_DIR$\Release\Obj\main.r90 + $PROJ_DIR$\Release\Obj\AVR458.pbi + $PROJ_DIR$\Release\List\PWM.lst + $PROJ_DIR$\Release\Obj\OWI.r90 + $PROJ_DIR$\Release\Obj\battery.pbi + $PROJ_DIR$\Release\Obj\PWM.pbi + $PROJ_DIR$\Release\Obj\menu.pbi + $PROJ_DIR$\Release\Obj\USI.pbi + $PROJ_DIR$\Release\Obj\statefunc.pbi + $PROJ_DIR$\Release\List\ADC.lst + $TOOLKIT_DIR$\inc\clib\sysmac.h + $PROJ_DIR$\Release\List\AVR458.lst + $PROJ_DIR$\Release\Obj\menu.r90 + $TOOLKIT_DIR$\inc\iomacro.h + $PROJ_DIR$\OWIcrc.h + $PROJ_DIR$\battery.h + $TOOLKIT_DIR$\inc\iotiny861.h + $PROJ_DIR$\USI.h + $PROJ_DIR$\ADC.h + $PROJ_DIR$\statefunc.h + $TOOLKIT_DIR$\inc\inavr.h + $PROJ_DIR$\OWIcrc.c + $PROJ_DIR$\menu.h + $PROJ_DIR$\charge.h + $TOOLKIT_DIR$\inc\ioavr.h + $TOOLKIT_DIR$\inc\intrinsics.h + $PROJ_DIR$\enums.h + $PROJ_DIR$\AVR458.h + $PROJ_DIR$\OWI.h + $PROJ_DIR$\chargefunc.h + $TOOLKIT_DIR$\lib\clib\cl1s-ec_nomul.r90 + $PROJ_DIR$\Release\Obj\OWIcrc.pbi + $PROJ_DIR$\Release\List\battery.lst + $PROJ_DIR$\Release\Obj\USI.r90 + $PROJ_DIR$\Release\Exe\BC100_tiny.hex + $PROJ_DIR$\Release\List\main.lst + $PROJ_DIR$\Release\Obj\BC100_tiny.pbd + + + $PROJ_DIR$\AVR458.c + + + ICCAVR + 19 72 + + + BICOMP + 62 + + + + + ICCAVR + 85 77 74 81 86 45 71 79 88 76 15 83 89 48 14 78 + + + BICOMP + 85 77 74 81 86 45 71 79 88 76 15 83 89 48 14 78 + + + + + $PROJ_DIR$\chargefunc.c + + + ICCAVR + 13 5 41 + + + BICOMP + 6 + + + + + ICCAVR + 85 77 74 87 44 79 76 90 15 83 48 80 14 46 + + + BICOMP + 85 77 74 87 44 79 76 90 15 83 48 80 14 46 + + + + + $PROJ_DIR$\ADC.c + + + ICCAVR + 59 8 70 + + + BICOMP + 51 + + + + + ICCAVR + 85 77 74 81 86 44 15 79 + + + BICOMP + 85 77 74 81 86 44 15 79 + + + + + $PROJ_DIR$\battery.c + + + ICCAVR + 25 40 93 + + + BICOMP + 65 + + + + + ICCAVR + 85 77 74 81 86 44 87 79 76 15 89 14 46 + + + BICOMP + 85 77 74 81 86 44 87 79 76 15 89 14 46 + + + + + $PROJ_DIR$\LIIONcharge.c + + + ICCAVR + 12 + + + BICOMP + 10 + + + + + ICCAVR + 85 77 74 87 44 76 84 90 15 83 42 48 14 + + + BICOMP + 85 77 74 87 44 76 84 90 15 83 42 48 14 + + + + + $PROJ_DIR$\main.c + + + ICCAVR + 61 0 96 + + + BICOMP + 17 + + + + + ICCAVR + 85 77 74 81 86 45 71 44 15 79 80 76 83 89 48 14 78 + + + BICOMP + 85 77 74 81 86 45 71 44 15 79 80 76 83 89 48 14 78 + + + + + $PROJ_DIR$\menu.c + + + ICCAVR + 73 1 57 + + + BICOMP + 67 + + + + + ICCAVR + 45 71 80 84 15 83 + + + BICOMP + 45 71 80 84 15 83 + + + + + $PROJ_DIR$\NIMHcharge.c + + + ICCAVR + 24 11 38 + + + BICOMP + 20 + + + + + ICCAVR + 85 77 74 87 44 76 84 90 15 83 46 48 14 + + + BICOMP + 85 77 74 87 44 76 84 90 15 83 46 48 14 + + + + + $PROJ_DIR$\OWI.c + + + ICCAVR + 64 7 23 + + + BICOMP + 52 + + + + + ICCAVR + 85 77 74 81 86 89 + + + BICOMP + 85 77 74 81 86 89 + + + + + $PROJ_DIR$\PWM.c + + + ICCAVR + 49 9 63 + + + BICOMP + 66 + + + + + ICCAVR + 85 77 74 87 15 48 14 + + + BICOMP + 85 77 74 87 15 48 14 + + + + + $PROJ_DIR$\statefunc.c + + + ICCAVR + 55 3 4 + + + BICOMP + 69 + + + + + ICCAVR + 85 77 74 81 86 45 71 44 87 79 80 76 84 15 83 89 48 14 78 + + + BICOMP + 85 77 74 81 86 45 71 44 87 79 80 76 84 15 83 89 48 14 78 + + + + + $PROJ_DIR$\time.c + + + ICCAVR + 53 2 60 + + + BICOMP + 21 + + + + + ICCAVR + 85 77 74 81 86 87 15 14 + + + BICOMP + 85 77 74 81 86 87 15 14 + + + + + $PROJ_DIR$\USI.c + + + ICCAVR + 94 39 56 + + + BICOMP + 68 + + + + + ICCAVR + 85 77 74 81 86 87 44 15 79 76 14 78 + + + BICOMP + 85 77 74 81 86 87 44 15 79 76 14 78 + + + + + [ROOT_NODE] + + + XLINK + 95 58 18 54 + + + + + $PROJ_DIR$\OWIcrc.c + + + ICCAVR + 22 50 + + + BICOMP + 92 + + + + + ICCAVR + 75 89 85 77 74 + + + BICOMP + 75 89 85 77 74 + + + + + $PROJ_DIR$\Release\Exe\BC100_tiny.hex + + + XLINK + 58 18 54 + + + + + XLINK + 47 43 59 24 64 49 94 25 13 61 73 55 53 91 + + + + + $PROJ_DIR$\Release\Obj\BC100_tiny.pbd + + + BILINK + 51 20 52 66 68 65 6 17 67 69 21 + + + + + $PROJ_DIR$\LIIONcharge.c + ICCAVR + + + + + diff --git a/BaseTinyFirmware/IAR/BC100_tiny.ewd b/BaseTinyFirmware/IAR/BC100_tiny.ewd new file mode 100644 index 0000000..8989609 --- /dev/null +++ b/BaseTinyFirmware/IAR/BC100_tiny.ewd @@ -0,0 +1,1291 @@ + + + + 1 + + Debug + + AVR + + 1 + + C-SPY + 3 + + 12 + 1 + 1 + + + + + + + + + + + + + + + + + + + + CCRAVR + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + ICE200AVR + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + JTAGICEAVR + 3 + + 2 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JTAGICEMKIIAVR + 3 + + 5 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SIMAVR + 2 + + 1 + 1 + 1 + + + + + + + THIRDPARTYAVR + 2 + + 1 + 1 + 1 + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\Profiling\Profiling.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Stack\Stack.ENU.ewplugin + 1 + + + + + Release + + AVR + + 0 + + C-SPY + 3 + + 12 + 1 + 0 + + + + + + + + + + + + + + + + + + + + CCRAVR + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + ICE200AVR + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + JTAGICEAVR + 3 + + 2 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JTAGICEMKIIAVR + 3 + + 5 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SIMAVR + 2 + + 1 + 1 + 0 + + + + + + + THIRDPARTYAVR + 2 + + 1 + 1 + 0 + + + + + + + + + + + + + $TOOLKIT_DIR$\plugins\rtos\uCOS-II\uCOS-II-KA-CSpy.ewplugin + 0 + + + $EW_DIR$\common\plugins\CodeCoverage\CodeCoverage.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Orti\Orti.ENU.ewplugin + 0 + + + $EW_DIR$\common\plugins\Profiling\Profiling.ENU.ewplugin + 1 + + + $EW_DIR$\common\plugins\Stack\Stack.ENU.ewplugin + 1 + + + + + + diff --git a/BaseTinyFirmware/IAR/BC100_tiny.ewp b/BaseTinyFirmware/IAR/BC100_tiny.ewp new file mode 100644 index 0000000..1e84451 --- /dev/null +++ b/BaseTinyFirmware/IAR/BC100_tiny.ewp @@ -0,0 +1,1966 @@ + + + + 1 + + Debug + + AVR + + 1 + + General + 4 + + 7 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCAVR + 4 + + 13 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AAVR + 4 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CUSTOM + 3 + + + + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + XLINK + 2 + + 13 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XAR + 2 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Release + + AVR + + 0 + + General + 4 + + 7 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCAVR + 4 + + 13 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AAVR + 4 + + 10 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CUSTOM + 3 + + + + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + XLINK + 2 + + 13 + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + XAR + 2 + + 0 + 1 + 0 + + + + + + + BILINK + 0 + + + + + $PROJ_DIR$\ADC.c + + + $PROJ_DIR$\battery.c + + + $PROJ_DIR$\chargefunc.c + + + $PROJ_DIR$\main.c + + + $PROJ_DIR$\menu.c + + + $PROJ_DIR$\NIMHcharge.c + + + $PROJ_DIR$\OWI.c + + + $PROJ_DIR$\PWM.c + + + $PROJ_DIR$\statefunc.c + + + $PROJ_DIR$\time.c + + + $PROJ_DIR$\USI.c + + + + diff --git a/BaseTinyFirmware/IAR/BC100_tiny.eww b/BaseTinyFirmware/IAR/BC100_tiny.eww new file mode 100644 index 0000000..8ea13f5 --- /dev/null +++ b/BaseTinyFirmware/IAR/BC100_tiny.eww @@ -0,0 +1,10 @@ + + + + + $WS_DIR$\BC100_tiny.ewp + + + + + diff --git a/BaseTinyFirmware/IAR/Debug/Exe/BC100_tiny.d90 b/BaseTinyFirmware/IAR/Debug/Exe/BC100_tiny.d90 new file mode 100644 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 index 0000000..ffe51c1 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/ADC.lst @@ -0,0 +1,1067 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c --cpu=tiny861 # +# -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ # +# -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB # +# C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ # +# --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ADC.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for use of ADC + 6 * + 7 * Contains high level functions for initializing the ADC, interrupt + 8 * handling, and treatment of samples.\n + 9 * The ADC is set to free running mode and uses an external reference + 10 * voltage.\n + 11 * To make all sampling take at least 25 clock cycles the ADC is stopped + 12 * and restarted by the ISR. + 13 * + 14 * \par Application note: + 15 * AVR458: Charging Li-Ion Batteries with BC100 \n + 16 * AVR463: Charging NiMH Batteries with BC100 + 17 * + 18 * \par Documentation: + 19 * For comprehensive code documentation, supported compilers, compiler + 20 * settings and supported devices see readme.html + 21 * + 22 * \author + 23 * Atmel Corporation: http://www.atmel.com \n + 24 * Support email: avr@atmel.com \n + 25 * Original author: \n + 26 * + 27 * $Name$ + 28 * $Revision: 2299 $ + 29 * $RCSfile$ + 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $ + 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 32 ******************************************************************************/ + 33 + 34 #include + + \ In segment ABSOLUTE, at 0x3b + \ volatile __io _A_PORTA + \ _A_PORTA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x3a + \ volatile __io _A_DDRA + \ _A_DDRA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x27 + \ volatile __io _A_ADMUX + \ _A_ADMUX: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x26 + \ volatile __io _A_ADCSRA + \ _A_ADCSRA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x24 + \ volatile __io _A_ADC + \ _A_ADC: + \ 00000000 DS 2 + + \ In segment ABSOLUTE, at 0x23 + \ volatile __io _A_ADCSRB + \ _A_ADCSRB: + \ 00000000 DS 1 + 35 #include + 36 + 37 #include "structs.h" + 38 + 39 #include "main.h" + 40 #include "ADC.h" + 41 + 42 + 43 //****************************************************************************** + 44 // Variables + 45 //****************************************************************************** + 46 // ADC status struct. + 47 //! \brief Holds sampled data and ADC-status + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 48 ADC_Status_t ADCS; + \ ADCS: + \ 00000000 DS 24 + 49 + 50 + 51 /*! \brief Indicates maximum battery voltage. + 52 * + 53 * This variable is stored in EEPROM and indicates how much the battery voltage + 54 * is downscaled by HW before it is sampled. The amount of downscaling depends + 55 * on the maximum battery voltage, and is necessary to avoid saturation of the + 56 * ADC (reference voltage is 2.5 V). + 57 * + 58 * \note Used by the ADC ISR when calling ScaleU() and ScaleI(). + 59 * + 60 * \note Defaults to 1, which means 10 V max battery voltage. + 61 * + 62 * \note Table of settings: + 63 *
+     64           * VBAT_RANGE | Max battery voltage | Jumper setting
+     65           *         0  |             5V      |        1/2
+     66           *         1  |            10V      |        1/4
+     67           *         2  |            20V      |        1/8
+     68           *         3  |            30V      |       1/12
+     69           *         4  |            40V      |       1/16
+     70           * 
+ 71 */ + 72 // Maximum battery voltage (affects scaling of samples). + + \ In segment EEPROM_I, align 1, keep-with-next + 73 __eeprom unsigned char VBAT_RANGE = 1; + \ VBAT_RANGE: + \ 00000000 01 DB 1 + 74 + 75 + 76 //****************************************************************************** + 77 // Functions + 78 //****************************************************************************** + 79 /*! \brief Interrupt Service routine for ADC. + 80 * + 81 * This ISR stores the sampled values in the ADC status-struct, then + 82 * updates the ADC MUX to the next channel in the scanning-sequence.\n + 83 * Once the sequence is completed, ADCS.Flag is set and unless + 84 * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC + 85 * is disabled.\n + 86 * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. + 87 * + 88 * \note Table of scanning sequence: + 89 *
+     90           * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed
+     91           * ----+--------+----------+----------+------+---------+-------
+     92           *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no
+     93           *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no
+     94           *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no
+     95           *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no
+     96           *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no
+     97           *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no
+     98           *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no
+     99           *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes
+    100           * 
+ 101 * + 102 * \todo IIN (#7 in sequence) is never used. + 103 * + 104 * \todo Signed is never set. Signed measurements of IBAT will halve the + 105 * measuring sensitivity, and is therefore not favourable. At the moment, + 106 * great currents (f.ex. if something happens with the battery) will be + 107 * interpreted as negative, which might cause unfavourable behaviour during + 108 * charging (depending on what PWM behaviour is defined), f.ex. + 109 * ConstantCurrent() will keep increasing the PWM output. This results in an + 110 * PWM controller error being flagged and the program going into + 111 * error-state and eventually reinitializing. + 112 */ + 113 #pragma vector=ADC_vect + + \ In segment CODE, align 2, keep-with-next + 114 __interrupt void ADC_ISR(void) + \ ADC_ISR: + 115 { + \ 00000000 925A ST -Y, R5 + \ 00000002 924A ST -Y, R4 + \ 00000004 93BA ST -Y, R27 + \ 00000006 93AA ST -Y, R26 + \ 00000008 939A ST -Y, R25 + \ 0000000A 938A ST -Y, R24 + \ 0000000C 93FA ST -Y, R31 + \ 0000000E 93EA ST -Y, R30 + \ 00000010 923A ST -Y, R3 + \ 00000012 922A ST -Y, R2 + \ 00000014 921A ST -Y, R1 + \ 00000016 920A ST -Y, R0 + \ 00000018 937A ST -Y, R23 + \ 0000001A 936A ST -Y, R22 + \ 0000001C 935A ST -Y, R21 + \ 0000001E 934A ST -Y, R20 + \ 00000020 933A ST -Y, R19 + \ 00000022 932A ST -Y, R18 + \ 00000024 931A ST -Y, R17 + \ 00000026 930A ST -Y, R16 + \ 00000028 B65F IN R5, 0x3F + \ 0000002A REQUIRE ?Register_R4_is_cg_reg + \ 0000002A REQUIRE ?Register_R5_is_cg_reg + 116 static unsigned char avgIndex = 0; + 117 unsigned char i, Next, Signed; + 118 signed int temp = 0; + \ 0000002A E0A0 LDI R26, 0 + \ 0000002C E0B0 LDI R27, 0 + 119 + 120 Signed = FALSE; // Presume next conversion is unipolar. + \ 0000002E 2444 CLR R4 + 121 ADCSRA &= ~(1< ADC1 (PA1) = NTC + 128 case 0x01: + 129 ADCS.rawNTC = ADC; + \ ??ADC_ISR_0: + \ 00000050 B104 IN R16, 0x04 + \ 00000052 B115 IN R17, 0x05 + \ 00000054 .... LDI R30, LOW(ADCS) + \ 00000056 .... LDI R31, (ADCS) >> 8 + \ 00000058 8304 STD Z+4, R16 + \ 0000005A 8315 STD Z+5, R17 + 130 Next=0x02; + \ 0000005C E092 LDI R25, 2 + \ 0000005E C0A8 RJMP ??ADC_ISR_6 + 131 break; + 132 + 133 + 134 // MUX = 0b000010 => ADC2 (PA2) = RID + 135 case 0x02: + 136 ADCS.rawRID = ADC; + \ ??ADC_ISR_1: + \ 00000060 B104 IN R16, 0x04 + \ 00000062 B115 IN R17, 0x05 + \ 00000064 .... LDI R30, LOW(ADCS) + \ 00000066 .... LDI R31, (ADCS) >> 8 + \ 00000068 8302 STD Z+2, R16 + \ 0000006A 8313 STD Z+3, R17 + 137 Next=0x03; + \ 0000006C E093 LDI R25, 3 + \ 0000006E C0A0 RJMP ??ADC_ISR_6 + 138 break; + 139 + 140 + 141 // MUX = 0b000011 => ADC3 (PA4) = VIN- + 142 case 0x03: + 143 // Supply voltage is always divided by 16. + 144 ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short. + \ ??ADC_ISR_2: + \ 00000070 B124 IN R18, 0x04 + \ 00000072 B135 IN R19, 0x05 + \ 00000074 E004 LDI R16, 4 + \ 00000076 .... RCALL ScaleU + \ 00000078 .... LDI R30, LOW(ADCS) + \ 0000007A .... LDI R31, (ADCS) >> 8 + \ 0000007C 8700 STD Z+8, R16 + \ 0000007E 8711 STD Z+9, R17 + 145 + 146 // Is mains failing? + 147 if (ADCS.VIN < VIN_MIN) { + \ 00000080 .... LDI R30, LOW(ADCS) + \ 00000082 .... LDI R31, (ADCS) >> 8 + \ 00000084 8500 LDD R16, Z+8 + \ 00000086 8511 LDD R17, Z+9 + \ 00000088 3300 CPI R16, 48 + \ 0000008A E121 LDI R18, 17 + \ 0000008C 0712 CPC R17, R18 + \ 0000008E F430 BRCC ??ADC_ISR_7 + 148 ADCS.Mains = FALSE; + \ 00000090 .... LDI R30, LOW(ADCS) + \ 00000092 .... LDI R31, (ADCS) >> 8 + \ 00000094 8100 LD R16, Z + \ 00000096 7B0F ANDI R16, 0xBF + \ 00000098 8300 ST Z, R16 + \ 0000009A C005 RJMP ??ADC_ISR_8 + 149 } else { + 150 ADCS.Mains = TRUE; + \ ??ADC_ISR_7: + \ 0000009C .... LDI R30, LOW(ADCS) + \ 0000009E .... LDI R31, (ADCS) >> 8 + \ 000000A0 8100 LD R16, Z + \ 000000A2 6400 ORI R16, 0x40 + \ 000000A4 8300 ST Z, R16 + 151 } + 152 + 153 Next=0x05; + \ ??ADC_ISR_8: + \ 000000A6 E095 LDI R25, 5 + \ 000000A8 C083 RJMP ??ADC_ISR_6 + 154 break; + 155 + 156 + 157 // MUX = 0b000101 => ADC5 (PA6) = VBAT- + 158 case 0x05: + 159 ADCS.rawVBAT = ADC; + \ ??ADC_ISR_3: + \ 000000AA B104 IN R16, 0x04 + \ 000000AC B115 IN R17, 0x05 + \ 000000AE .... LDI R30, LOW(ADCS) + \ 000000B0 .... LDI R31, (ADCS) >> 8 + \ 000000B2 8306 STD Z+6, R16 + \ 000000B4 8317 STD Z+7, R17 + 160 + 161 // Scale voltage according to jumper setting. + 162 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short. + \ 000000B6 B124 IN R18, 0x04 + \ 000000B8 B135 IN R19, 0x05 + \ 000000BA .... LDI R20, LOW(VBAT_RANGE) + \ 000000BC .... LDI R21, (VBAT_RANGE) >> 8 + \ 000000BE .... RCALL __eeget8_16 + \ 000000C0 .... RCALL ScaleU + \ 000000C2 .... LDI R30, LOW(ADCS) + \ 000000C4 .... LDI R31, (ADCS) >> 8 + \ 000000C6 8702 STD Z+10, R16 + \ 000000C8 8713 STD Z+11, R17 + 163 Next=0x17; + \ 000000CA E197 LDI R25, 23 + \ 000000CC C071 RJMP ??ADC_ISR_6 + 164 // Signed = TRUE; // Next conversion is bipolar. Halves sensitivity! + 165 break; + 166 + 167 + 168 case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT + 169 // If bipolar, from -512 to 0, to 511: + 170 // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF + 171 + 172 // Scale sample according to jumper setting, handle negative numbers. + 173 if (ADC > 511) { + \ ??ADC_ISR_4: + \ 000000CE B104 IN R16, 0x04 + \ 000000D0 B115 IN R17, 0x05 + \ 000000D2 3000 CPI R16, 0 + \ 000000D4 E022 LDI R18, 2 + \ 000000D6 0712 CPC R17, R18 + \ 000000D8 F0C8 BRCS ??ADC_ISR_9 + 174 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE, + 175 (1024 - (ADC-ADCS.ADC5_G20_OS))); + \ 000000DA E000 LDI R16, 0 + \ 000000DC E014 LDI R17, 4 + \ 000000DE B124 IN R18, 0x04 + \ 000000E0 B135 IN R19, 0x05 + \ 000000E2 1B02 SUB R16, R18 + \ 000000E4 0B13 SBC R17, R19 + \ 000000E6 9120.... LDS R18, (ADCS + 1) + \ 000000EA 9522 SWAP R18 + \ 000000EC 702F ANDI R18, 0x0F + \ 000000EE E030 LDI R19, 0 + \ 000000F0 0F20 ADD R18, R16 + \ 000000F2 1F31 ADC R19, R17 + \ 000000F4 .... LDI R20, LOW(VBAT_RANGE) + \ 000000F6 .... LDI R21, (VBAT_RANGE) >> 8 + \ 000000F8 .... RCALL __eeget8_16 + \ 000000FA .... RCALL ScaleI + \ 000000FC 9511 NEG R17 + \ 000000FE 9501 NEG R16 + \ 00000100 4010 SBCI R17, 0 + \ 00000102 .... LDI R30, LOW(ADCS) + \ 00000104 .... LDI R31, (ADCS) >> 8 + \ 00000106 8704 STD Z+12, R16 + \ 00000108 8715 STD Z+13, R17 + \ 0000010A C01C RJMP ??ADC_ISR_10 + 176 } else if (ADC > 0) { + \ ??ADC_ISR_9: + \ 0000010C B104 IN R16, 0x04 + \ 0000010E B115 IN R17, 0x05 + \ 00000110 2B01 OR R16, R17 + \ 00000112 F091 BREQ ??ADC_ISR_11 + 177 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS)); + \ 00000114 B124 IN R18, 0x04 + \ 00000116 B135 IN R19, 0x05 + \ 00000118 9100.... LDS R16, (ADCS + 1) + \ 0000011C 9502 SWAP R16 + \ 0000011E 700F ANDI R16, 0x0F + \ 00000120 E010 LDI R17, 0 + \ 00000122 1B20 SUB R18, R16 + \ 00000124 0B31 SBC R19, R17 + \ 00000126 .... LDI R20, LOW(VBAT_RANGE) + \ 00000128 .... LDI R21, (VBAT_RANGE) >> 8 + \ 0000012A .... RCALL __eeget8_16 + \ 0000012C .... RCALL ScaleI + \ 0000012E .... LDI R30, LOW(ADCS) + \ 00000130 .... LDI R31, (ADCS) >> 8 + \ 00000132 8704 STD Z+12, R16 + \ 00000134 8715 STD Z+13, R17 + \ 00000136 C006 RJMP ??ADC_ISR_10 + 178 } else { + 179 ADCS.IBAT = 0; + \ ??ADC_ISR_11: + \ 00000138 E000 LDI R16, 0 + \ 0000013A E010 LDI R17, 0 + \ 0000013C .... LDI R30, LOW(ADCS) + \ 0000013E .... LDI R31, (ADCS) >> 8 + \ 00000140 8704 STD Z+12, R16 + \ 00000142 8715 STD Z+13, R17 + 180 } + 181 + 182 // Insert sample of battery current into the averaging-array + 183 // (overwriting the oldest sample), then recalculate and store the + 184 // average. This is the last conversion in the sequence, so + 185 // flag a complete ADC-cycle and restart sequence. + 186 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT; + \ ??ADC_ISR_10: + \ 00000144 .... LDI R30, LOW(ADCS) + \ 00000146 .... LDI R31, (ADCS) >> 8 + \ 00000148 8524 LDD R18, Z+12 + \ 0000014A 8535 LDD R19, Z+13 + \ 0000014C 9100.... LDS R16, ??avgIndex + \ 00000150 E010 LDI R17, 0 + \ 00000152 7003 ANDI R16, 0x03 + \ 00000154 7010 ANDI R17, 0x00 + \ 00000156 0F00 LSL R16 + \ 00000158 1F11 ROL R17 + \ 0000015A 01F8 MOVW R31:R30, R17:R16 + \ 0000015C .... SUBI R30, LOW((-(ADCS) & 0xFFFF)) + \ 0000015E .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + \ 00000160 8726 STD Z+14, R18 + \ 00000162 8737 STD Z+15, R19 + \ 00000164 .... LDI R30, LOW(??avgIndex) + \ 00000166 .... LDI R31, (??avgIndex) >> 8 + \ 00000168 8100 LD R16, Z + \ 0000016A 9503 INC R16 + \ 0000016C 8300 ST Z, R16 + 187 for (i = 0; i < 4 ; i++) { + \ 0000016E E080 LDI R24, 0 + \ ??ADC_ISR_12: + \ 00000170 3084 CPI R24, 4 + \ 00000172 F468 BRCC ??ADC_ISR_13 + 188 temp += ADCS.discIBAT[i]; + \ 00000174 2F08 MOV R16, R24 + \ 00000176 E010 LDI R17, 0 + \ 00000178 0F00 LSL R16 + \ 0000017A 1F11 ROL R17 + \ 0000017C 01F8 MOVW R31:R30, R17:R16 + \ 0000017E .... SUBI R30, LOW((-(ADCS) & 0xFFFF)) + \ 00000180 .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + \ 00000182 8506 LDD R16, Z+14 + \ 00000184 8517 LDD R17, Z+15 + \ 00000186 0FA0 ADD R26, R16 + \ 00000188 1FB1 ADC R27, R17 + 189 } + \ 0000018A 9583 INC R24 + \ 0000018C CFF1 RJMP ??ADC_ISR_12 + 190 + 191 ADCS.avgIBAT = (temp / 4); + \ ??ADC_ISR_13: + \ 0000018E 018D MOVW R17:R16, R27:R26 + \ 00000190 E044 LDI R20, 4 + \ 00000192 E050 LDI R21, 0 + \ 00000194 .... RCALL ?SS_DIVMOD_L02 + \ 00000196 .... LDI R30, LOW(ADCS) + \ 00000198 .... LDI R31, (ADCS) >> 8 + \ 0000019A 8B06 STD Z+22, R16 + \ 0000019C 8B17 STD Z+23, R17 + 192 + 193 ADCS.Flag = TRUE; + \ 0000019E .... LDI R30, LOW(ADCS) + \ 000001A0 .... LDI R31, (ADCS) >> 8 + \ 000001A2 8100 LD R16, Z + \ 000001A4 6200 ORI R16, 0x20 + \ 000001A6 8300 ST Z, R16 + 194 Next=0x01; + \ 000001A8 E091 LDI R25, 1 + 195 Signed = FALSE; // This is the only bipolar conversion. + \ 000001AA 2444 CLR R4 + \ 000001AC C001 RJMP ??ADC_ISR_6 + 196 break; + 197 + 198 + 199 default: // Should not happen. (Invalid MUX-channel) + 200 Next=0x01; // Start at the beginning of sequence. + \ ??ADC_ISR_5: + \ 000001AE E091 LDI R25, 1 + 201 break; + 202 } + 203 + 204 // Update MUX to next channel in sequence, set a bipolar conversion if + 205 // this has been flagged. + 206 ADCS.MUX = Next; + \ ??ADC_ISR_6: + \ 000001B0 9110.... LDS R17, ADCS + \ 000001B4 7E10 ANDI R17, 0xE0 + \ 000001B6 2F09 MOV R16, R25 + \ 000001B8 710F ANDI R16, 0x1F + \ 000001BA 2B01 OR R16, R17 + \ 000001BC 9300.... STS ADCS, R16 + 207 ADMUX = (1<` + \ ??avgIndex: + \ 00000000 DS 1 + 221 + 222 + 223 /*! \brief Scales sample to represent "actual voltage" in mV. + 224 * + 225 * This function returns the actual sampled voltage, scaled according + 226 * to the jumper settings. + 227 * + 228 * \param setting Indicates what downscaling was used. + 229 * \param data The sampled value. + 230 * + 231 * \note Table for setting-parameter:\n + 232 *
+    233           * Presume VREF = 2.5V and Gain = 1x.
+    234           * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB
+    235           * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)
+    236           * --------+--------+------+------------+-----------+-------
+    237           *     N/A |        |    - |       -    |   2.441mV |  2.50V
+    238           *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V
+    239           *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V
+    240           *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V
+    241           *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V
+    242           *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V
+    243           *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V
+    244           * 
+ 245 */ + + \ In segment CODE, align 2, keep-with-next + 246 unsigned int ScaleU(unsigned char setting, unsigned int data) + \ ScaleU: + 247 { + \ 00000000 .... RCALL ?PROLOGUE6_L09 + \ 00000002 REQUIRE ?Register_R4_is_cg_reg + \ 00000002 REQUIRE ?Register_R5_is_cg_reg + \ 00000002 2FA0 MOV R26, R16 + \ 00000004 01C9 MOVW R25:R24, R19:R18 + 248 // Temporary variable needed. + 249 unsigned int scaled = 0; + \ 00000006 2444 CLR R4 + \ 00000008 2455 CLR R5 + 250 + 251 // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16 + 252 if (setting == 3) { + \ 0000000A 30A3 CPI R26, 3 + \ 0000000C F491 BRNE ??ScaleU_0 + 253 scaled = 29 * data; + \ 0000000E 01AC MOVW R21:R20, R25:R24 + \ 00000010 E10D LDI R16, 29 + \ 00000012 E010 LDI R17, 0 + \ 00000014 .... RCALL ?S_MUL_L02 + \ 00000016 0128 MOVW R5:R4, R17:R16 + 254 scaled += (data >> 2); + \ 00000018 018C MOVW R17:R16, R25:R24 + \ 0000001A 9516 LSR R17 + \ 0000001C 9507 ROR R16 + \ 0000001E 9516 LSR R17 + \ 00000020 9507 ROR R16 + \ 00000022 0E40 ADD R4, R16 + \ 00000024 1E51 ADC R5, R17 + 255 scaled += (data >> 4); + \ 00000026 018C MOVW R17:R16, R25:R24 + \ 00000028 E044 LDI R20, 4 + \ 0000002A .... RCALL ?US_SHR_L02 + \ 0000002C 0E40 ADD R4, R16 + \ 0000002E 1E51 ADC R5, R17 + \ 00000030 C011 RJMP ??ScaleU_1 + 256 } else { + 257 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16 + 258 scaled = 39 * data; + \ ??ScaleU_0: + \ 00000032 01AC MOVW R21:R20, R25:R24 + \ 00000034 E207 LDI R16, 39 + \ 00000036 E010 LDI R17, 0 + \ 00000038 .... RCALL ?S_MUL_L02 + \ 0000003A 0128 MOVW R5:R4, R17:R16 + 259 scaled += (data >> 4); + \ 0000003C 018C MOVW R17:R16, R25:R24 + \ 0000003E E044 LDI R20, 4 + \ 00000040 .... RCALL ?US_SHR_L02 + \ 00000042 0E40 ADD R4, R16 + \ 00000044 1E51 ADC R5, R17 + 260 + 261 if (setting <3) { + \ 00000046 30A3 CPI R26, 3 + \ 00000048 F428 BRCC ??ScaleU_1 + 262 // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8 + 263 // 1: mV/LSB = 9.766 = 39.06 / 4 + 264 // 2: mV/LSB = 19.53 = 39.06 / 2 + 265 scaled = (scaled >> (3-setting)); + \ 0000004A 0182 MOVW R17:R16, R5:R4 + \ 0000004C E043 LDI R20, 3 + \ 0000004E 1B4A SUB R20, R26 + \ 00000050 .... RCALL ?US_SHR_L02 + \ 00000052 0128 MOVW R5:R4, R17:R16 + 266 } + 267 } + 268 + 269 return(scaled); + \ ??ScaleU_1: + \ 00000054 0182 MOVW R17:R16, R5:R4 + \ 00000056 E0E6 LDI R30, 6 + \ 00000058 .... RJMP ?EPILOGUE_B6_L09 + 270 } + 271 + 272 + 273 /*! \brief Scales sample to represent "actual current" in mA. + 274 * + 275 * This function returns the actual sampled current, scaled according + 276 * to the jumper settings. + 277 * + 278 * \param setting Indicates what downscaling was used. + 279 * \param data The sampled value. + 280 * + 281 * \note Table for setting-parameter:\n + 282 *
+    283           * Presume VREF = 2.5V and Gain = 1x or 20x.
+    284           * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
+    285           * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
+    286           * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain
+    287           * --------+------+------------+----------+----------+--------+-----
+    288           *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x
+    289           *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x
+    290           *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x
+    291           *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x
+    292           *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x
+    293           *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x
+    294           *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x
+    295           * 
+ 296 */ + + \ In segment CODE, align 2, keep-with-next + 297 unsigned int ScaleI(unsigned char setting, unsigned int data) + \ ScaleI: + 298 { + \ 00000000 .... RCALL ?PROLOGUE6_L09 + \ 00000002 REQUIRE ?Register_R4_is_cg_reg + \ 00000002 REQUIRE ?Register_R5_is_cg_reg + \ 00000002 2FA0 MOV R26, R16 + \ 00000004 01C9 MOVW R25:R24, R19:R18 + 299 // Temporary variable needed. + 300 unsigned int scaled = 0; + \ 00000006 2444 CLR R4 + \ 00000008 2455 CLR R5 + 301 + 302 // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128 + 303 if (setting == 3) { + \ 0000000A 30A3 CPI R26, 3 + \ 0000000C F499 BRNE ??ScaleI_0 + 304 scaled = 21 * data; + \ 0000000E 01AC MOVW R21:R20, R25:R24 + \ 00000010 E105 LDI R16, 21 + \ 00000012 E010 LDI R17, 0 + \ 00000014 .... RCALL ?S_MUL_L02 + \ 00000016 0128 MOVW R5:R4, R17:R16 + 305 scaled -= (data >> 4); + \ 00000018 018C MOVW R17:R16, R25:R24 + \ 0000001A E044 LDI R20, 4 + \ 0000001C .... RCALL ?US_SHR_L02 + \ 0000001E 1A40 SUB R4, R16 + \ 00000020 0A51 SBC R5, R17 + 306 scaled += (data >> 7); + \ 00000022 018C MOVW R17:R16, R25:R24 + \ 00000024 0F00 LSL R16 + \ 00000026 2F01 MOV R16, R17 + \ 00000028 1F00 ROL R16 + \ 0000002A E010 LDI R17, 0 + \ 0000002C 1F11 ROL R17 + \ 0000002E 0E40 ADD R4, R16 + \ 00000030 1E51 ADC R5, R17 + \ 00000032 C016 RJMP ??ScaleI_1 + 307 } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32 + 308 scaled = 28 * data; + \ ??ScaleI_0: + \ 00000034 01AC MOVW R21:R20, R25:R24 + \ 00000036 E10C LDI R16, 28 + \ 00000038 E010 LDI R17, 0 + \ 0000003A .... RCALL ?S_MUL_L02 + \ 0000003C 0128 MOVW R5:R4, R17:R16 + 309 scaled -= (data >> 3); + \ 0000003E 018C MOVW R17:R16, R25:R24 + \ 00000040 E043 LDI R20, 3 + \ 00000042 .... RCALL ?US_SHR_L02 + \ 00000044 1A40 SUB R4, R16 + \ 00000046 0A51 SBC R5, R17 + 310 scaled += (data >> 5); + \ 00000048 018C MOVW R17:R16, R25:R24 + \ 0000004A E045 LDI R20, 5 + \ 0000004C .... RCALL ?US_SHR_L02 + \ 0000004E 0E40 ADD R4, R16 + \ 00000050 1E51 ADC R5, R17 + 311 + 312 if (setting <3) { + \ 00000052 30A3 CPI R26, 3 + \ 00000054 F428 BRCC ??ScaleI_1 + 313 // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8 + 314 // 1: mA/LSB = 6.978mA = 27.909 / 4 + 315 // 2: mA/LSB = 13.955mA = 27.909 / 2 + 316 scaled = (scaled >> (3-setting)); + \ 00000056 0182 MOVW R17:R16, R5:R4 + \ 00000058 E043 LDI R20, 3 + \ 0000005A 1B4A SUB R20, R26 + \ 0000005C .... RCALL ?US_SHR_L02 + \ 0000005E 0128 MOVW R5:R4, R17:R16 + 317 } + 318 } + 319 + 320 return(scaled); + \ ??ScaleI_1: + \ 00000060 0182 MOVW R17:R16, R5:R4 + \ 00000062 E0E6 LDI R30, 6 + \ 00000064 .... RJMP ?EPILOGUE_B6_L09 + 321 } + 322 + 323 + 324 /*! \brief Waits for two full cycles of ADC-conversions to occur. + 325 * + 326 * This function clears the cycle complete-flag, then waits for it to be set + 327 * again. This is then repeated once before the function exits. + 328 * + 329 */ + + \ In segment CODE, align 2, keep-with-next + 330 void ADC_Wait(void) + \ ADC_Wait: + 331 { + 332 // Clear ADC flag and wait for cycle to complete. + 333 ADCS.Flag = FALSE; + \ 00000000 .... LDI R30, LOW(ADCS) + \ 00000002 .... LDI R31, (ADCS) >> 8 + \ 00000004 8100 LD R16, Z + \ 00000006 7D0F ANDI R16, 0xDF + \ 00000008 8300 ST Z, R16 + 334 do { + 335 } while (ADCS.Flag == FALSE); + \ ??ADC_Wait_0: + \ 0000000A .... LDI R30, LOW(ADCS) + \ 0000000C .... LDI R31, (ADCS) >> 8 + \ 0000000E 8100 LD R16, Z + \ 00000010 FF05 SBRS R16, 5 + \ 00000012 CFFB RJMP ??ADC_Wait_0 + 336 + 337 // Repeat, so we are sure the data beong to the same cycle. + 338 ADCS.Flag = FALSE; + \ 00000014 .... LDI R30, LOW(ADCS) + \ 00000016 .... LDI R31, (ADCS) >> 8 + \ 00000018 8100 LD R16, Z + \ 0000001A 7D0F ANDI R16, 0xDF + \ 0000001C 8300 ST Z, R16 + 339 do { + 340 } while (ADCS.Flag == FALSE); + \ ??ADC_Wait_1: + \ 0000001E .... LDI R30, LOW(ADCS) + \ 00000020 .... LDI R31, (ADCS) >> 8 + \ 00000022 8100 LD R16, Z + \ 00000024 FF05 SBRS R16, 5 + \ 00000026 CFFB RJMP ??ADC_Wait_1 + 341 } + \ 00000028 9508 RET + 342 + 343 + 344 /*! \brief Initializes ADC and input pins. + 345 * + 346 * This function initializes the ADC to free running mode, sampling from + 347 * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n + 348 * It also measures and stores calibration data for offset. + 349 * + 350 * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway. + 351 * + 352 * \note Table of MUX settings for offset measurement: + 353 *
+    354           *    Ch | Pin |    Gain |    MUX
+    355           * ------+-----+---------+-------
+    356           *  ADC1 | PA1 |     20x | 001101
+    357           *  ADC3 | PA4 |     20x | 010001
+    358           *  ADC5 | PA6 |     20x | 010110
+    359           *  ADC9 | PB6 |     20x | 011011
+    360           *  ADC0 | PA0 | 20x/32x | 111000
+    361           *  ADC0 | PA0 |   1x/8x | 111001
+    362           *  ADC1 | PA1 | 20x/32x | 111010
+    363           *  ADC2 | PA2 | 20x/32x | 111011
+    364           *  ADC4 | PA5 | 20x/32x | 111100
+    365           *  ADC5 | PA6 | 20x/32x | 111101
+    366           *  ADC6 | PA7 | 20x/32x | 111110
+    367           * 
+ 368 */ + + \ In segment CODE, align 2, keep-with-next + 369 void ADC_Init(void) + \ ADC_Init: + 370 { + \ 00000000 938A ST -Y, R24 + 371 unsigned char i; + 372 + 373 __disable_interrupt(); + \ 00000002 94F8 CLI + 374 + 375 ADCS.Halt = FALSE; // Enable consecutive runs of ADC. + \ 00000004 .... LDI R30, LOW(ADCS) + \ 00000006 .... LDI R31, (ADCS) >> 8 + \ 00000008 8100 LD R16, Z + \ 0000000A 770F ANDI R16, 0x7F + \ 0000000C 8300 ST Z, R16 + 376 + 377 // Configure ADC pins (inputs and disabled pull-ups). + 378 DDRA &= ~((1<> 8 + \ 00000064 8100 LD R16, Z + \ 00000066 7D0F ANDI R16, 0xDF + \ 00000068 8300 ST Z, R16 + 410 ADCS.MUX = 0x01; + \ 0000006A 9100.... LDS R16, ADCS + \ 0000006E 7E00 ANDI R16, 0xE0 + \ 00000070 6001 ORI R16, 0x01 + \ 00000072 9300.... STS ADCS, R16 + 411 ADMUX = (1<> 8 + \ 00000088 8B06 STD Z+22, R16 + \ 0000008A 8B17 STD Z+23, R17 + 415 + 416 for (i = 0; i < 4; i++) { + \ 0000008C E080 LDI R24, 0 + \ ??ADC_Init_2: + \ 0000008E 3084 CPI R24, 4 + \ 00000090 F468 BRCC ??ADC_Init_3 + 417 ADCS.discIBAT[i] = 0; + \ 00000092 E000 LDI R16, 0 + \ 00000094 E010 LDI R17, 0 + \ 00000096 2F28 MOV R18, R24 + \ 00000098 E030 LDI R19, 0 + \ 0000009A 0F22 LSL R18 + \ 0000009C 1F33 ROL R19 + \ 0000009E 01F9 MOVW R31:R30, R19:R18 + \ 000000A0 .... SUBI R30, LOW((-(ADCS) & 0xFFFF)) + \ 000000A2 .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + \ 000000A4 8706 STD Z+14, R16 + \ 000000A6 8717 STD Z+15, R17 + 418 } + \ 000000A8 9583 INC R24 + \ 000000AA CFF1 RJMP ??ADC_Init_2 + 419 + 420 // Re-enable the ADC and ISR. + 421 ADCSRA=(1< ScaleU 20 2 + -> ScaleU 20 2 + -> ScaleI 20 2 + -> ScaleI 20 2 + ADC_Init 1 2 + -> ADC_Wait 1 2 + ADC_Wait 0 2 + ScaleI 6 4 + ScaleU 6 4 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_PORTA 1 + _A_DDRA 1 + _A_ADMUX 1 + _A_ADCSRA 1 + _A_ADC 2 + _A_ADCSRB 1 + ADCS 24 + VBAT_RANGE 1 + ADC_ISR 528 + avgIndex 1 + ScaleU 90 + ScaleI 102 + ADC_Wait 42 + ADC_Init 184 + ??ADC_ISR??INTVEC 22 2 + Others 6 + + + 7 bytes in segment ABSOLUTE + 946 bytes in segment CODE + 1 byte in segment EEPROM_I + 6 bytes in segment INITTAB + 2 bytes in segment INTVEC + 25 bytes in segment NEAR_Z + + 946 bytes of CODE memory (+ 8 bytes shared) + 25 bytes of DATA memory (+ 7 bytes shared) + 1 byte of XDATA memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/ADC.s90 b/BaseTinyFirmware/IAR/Debug/List/ADC.s90 new file mode 100644 index 0000000..6255bf4 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/ADC.s90 @@ -0,0 +1,1089 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ADC.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME `ADC` + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?EPILOGUE_B6_L09 + EXTERN ?PROLOGUE6_L09 + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?SS_DIVMOD_L02 + EXTERN ?S_MUL_L02 + EXTERN ?US_SHR_L02 + EXTERN ?need_segment_init + EXTERN __eeget8_16 + + PUBWEAK `?` + PUBWEAK `??ADC_ISR??INTVEC 22` + PUBLIC ADCS + PUBLIC ADC_ISR + PUBLIC ADC_Init + PUBLIC ADC_Wait + PUBLIC ScaleI + PUBLIC ScaleU + PUBLIC VBAT_RANGE + PUBWEAK _A_ADC + PUBWEAK _A_ADCSRA + PUBWEAK _A_ADCSRB + PUBWEAK _A_ADMUX + PUBWEAK _A_DDRA + PUBWEAK _A_PORTA + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + +ADC_ISR SYMBOL "ADC_ISR" +`??ADC_ISR??INTVEC 22` SYMBOL "??INTVEC 22", ADC_ISR + +// C:\home\kevin\pub\src\bc100_cal\IAR\ADC.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for use of ADC +// 6 * +// 7 * Contains high level functions for initializing the ADC, interrupt +// 8 * handling, and treatment of samples.\n +// 9 * The ADC is set to free running mode and uses an external reference +// 10 * voltage.\n +// 11 * To make all sampling take at least 25 clock cycles the ADC is stopped +// 12 * and restarted by the ISR. +// 13 * +// 14 * \par Application note: +// 15 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 16 * AVR463: Charging NiMH Batteries with BC100 +// 17 * +// 18 * \par Documentation: +// 19 * For comprehensive code documentation, supported compilers, compiler +// 20 * settings and supported devices see readme.html +// 21 * +// 22 * \author +// 23 * Atmel Corporation: http://www.atmel.com \n +// 24 * Support email: avr@atmel.com \n +// 25 * Original author: \n +// 26 * +// 27 * $Name$ +// 28 * $Revision: 2299 $ +// 29 * $RCSfile$ +// 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $ +// 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 32 ******************************************************************************/ +// 33 +// 34 #include + + ASEGN ABSOLUTE:DATA:NOROOT,03bH +// volatile __io _A_PORTA +_A_PORTA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,03aH +// volatile __io _A_DDRA +_A_DDRA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,027H +// volatile __io _A_ADMUX +_A_ADMUX: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,026H +// volatile __io _A_ADCSRA +_A_ADCSRA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,024H +// volatile __io _A_ADC +_A_ADC: + DS 2 + + ASEGN ABSOLUTE:DATA:NOROOT,023H +// volatile __io _A_ADCSRB +_A_ADCSRB: + DS 1 +// 35 #include +// 36 +// 37 #include "structs.h" +// 38 +// 39 #include "main.h" +// 40 #include "ADC.h" +// 41 +// 42 +// 43 //****************************************************************************** +// 44 // Variables +// 45 //****************************************************************************** +// 46 // ADC status struct. +// 47 //! \brief Holds sampled data and ADC-status + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 48 ADC_Status_t ADCS; +ADCS: + DS 24 +// 49 +// 50 +// 51 /*! \brief Indicates maximum battery voltage. +// 52 * +// 53 * This variable is stored in EEPROM and indicates how much the battery voltage +// 54 * is downscaled by HW before it is sampled. The amount of downscaling depends +// 55 * on the maximum battery voltage, and is necessary to avoid saturation of the +// 56 * ADC (reference voltage is 2.5 V). +// 57 * +// 58 * \note Used by the ADC ISR when calling ScaleU() and ScaleI(). +// 59 * +// 60 * \note Defaults to 1, which means 10 V max battery voltage. +// 61 * +// 62 * \note Table of settings: +// 63 *
+//   64  * VBAT_RANGE | Max battery voltage | Jumper setting
+//   65  *         0  |             5V      |        1/2
+//   66  *         1  |            10V      |        1/4
+//   67  *         2  |            20V      |        1/8
+//   68  *         3  |            30V      |       1/12
+//   69  *         4  |            40V      |       1/16
+//   70  * 
+// 71 */ +// 72 // Maximum battery voltage (affects scaling of samples). + + RSEG EEPROM_I:XDATA:NOROOT(0) +// 73 __eeprom unsigned char VBAT_RANGE = 1; +VBAT_RANGE: + DB 1 +// 74 +// 75 +// 76 //****************************************************************************** +// 77 // Functions +// 78 //****************************************************************************** +// 79 /*! \brief Interrupt Service routine for ADC. +// 80 * +// 81 * This ISR stores the sampled values in the ADC status-struct, then +// 82 * updates the ADC MUX to the next channel in the scanning-sequence.\n +// 83 * Once the sequence is completed, ADCS.Flag is set and unless +// 84 * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC +// 85 * is disabled.\n +// 86 * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. +// 87 * +// 88 * \note Table of scanning sequence: +// 89 *
+//   90  * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed
+//   91  * ----+--------+----------+----------+------+---------+-------
+//   92  *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no
+//   93  *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no
+//   94  *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no
+//   95  *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no
+//   96  *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no
+//   97  *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no
+//   98  *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no
+//   99  *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes
+//  100  * 
+// 101 * +// 102 * \todo IIN (#7 in sequence) is never used. +// 103 * +// 104 * \todo Signed is never set. Signed measurements of IBAT will halve the +// 105 * measuring sensitivity, and is therefore not favourable. At the moment, +// 106 * great currents (f.ex. if something happens with the battery) will be +// 107 * interpreted as negative, which might cause unfavourable behaviour during +// 108 * charging (depending on what PWM behaviour is defined), f.ex. +// 109 * ConstantCurrent() will keep increasing the PWM output. This results in an +// 110 * PWM controller error being flagged and the program going into +// 111 * error-state and eventually reinitializing. +// 112 */ +// 113 #pragma vector=ADC_vect + + RSEG CODE:CODE:NOROOT(1) +// 114 __interrupt void ADC_ISR(void) +ADC_ISR: +// 115 { + ST -Y, R5 + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + ST -Y, R31 + ST -Y, R30 + ST -Y, R3 + ST -Y, R2 + ST -Y, R1 + ST -Y, R0 + ST -Y, R23 + ST -Y, R22 + ST -Y, R21 + ST -Y, R20 + ST -Y, R19 + ST -Y, R18 + ST -Y, R17 + ST -Y, R16 + IN R5, 0x3F + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg +// 116 static unsigned char avgIndex = 0; +// 117 unsigned char i, Next, Signed; +// 118 signed int temp = 0; + LDI R26, 0 + LDI R27, 0 +// 119 +// 120 Signed = FALSE; // Presume next conversion is unipolar. + CLR R4 +// 121 ADCSRA &= ~(1< ADC1 (PA1) = NTC +// 128 case 0x01: +// 129 ADCS.rawNTC = ADC; +??ADC_ISR_0: + IN R16, 0x04 + IN R17, 0x05 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+4, R16 + STD Z+5, R17 +// 130 Next=0x02; + LDI R25, 2 + RJMP ??ADC_ISR_6 +// 131 break; +// 132 +// 133 +// 134 // MUX = 0b000010 => ADC2 (PA2) = RID +// 135 case 0x02: +// 136 ADCS.rawRID = ADC; +??ADC_ISR_1: + IN R16, 0x04 + IN R17, 0x05 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 137 Next=0x03; + LDI R25, 3 + RJMP ??ADC_ISR_6 +// 138 break; +// 139 +// 140 +// 141 // MUX = 0b000011 => ADC3 (PA4) = VIN- +// 142 case 0x03: +// 143 // Supply voltage is always divided by 16. +// 144 ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short. +??ADC_ISR_2: + IN R18, 0x04 + IN R19, 0x05 + LDI R16, 4 + RCALL ScaleU + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+8, R16 + STD Z+9, R17 +// 145 +// 146 // Is mains failing? +// 147 if (ADCS.VIN < VIN_MIN) { + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+8 + LDD R17, Z+9 + CPI R16, 48 + LDI R18, 17 + CPC R17, R18 + BRCC ??ADC_ISR_7 +// 148 ADCS.Mains = FALSE; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ANDI R16, 0xBF + ST Z, R16 + RJMP ??ADC_ISR_8 +// 149 } else { +// 150 ADCS.Mains = TRUE; +??ADC_ISR_7: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ORI R16, 0x40 + ST Z, R16 +// 151 } +// 152 +// 153 Next=0x05; +??ADC_ISR_8: + LDI R25, 5 + RJMP ??ADC_ISR_6 +// 154 break; +// 155 +// 156 +// 157 // MUX = 0b000101 => ADC5 (PA6) = VBAT- +// 158 case 0x05: +// 159 ADCS.rawVBAT = ADC; +??ADC_ISR_3: + IN R16, 0x04 + IN R17, 0x05 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+6, R16 + STD Z+7, R17 +// 160 +// 161 // Scale voltage according to jumper setting. +// 162 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short. + IN R18, 0x04 + IN R19, 0x05 + LDI R20, LOW(VBAT_RANGE) + LDI R21, (VBAT_RANGE) >> 8 + RCALL __eeget8_16 + RCALL ScaleU + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+10, R16 + STD Z+11, R17 +// 163 Next=0x17; + LDI R25, 23 + RJMP ??ADC_ISR_6 +// 164 // Signed = TRUE; // Next conversion is bipolar. Halves sensitivity! +// 165 break; +// 166 +// 167 +// 168 case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT +// 169 // If bipolar, from -512 to 0, to 511: +// 170 // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF +// 171 +// 172 // Scale sample according to jumper setting, handle negative numbers. +// 173 if (ADC > 511) { +??ADC_ISR_4: + IN R16, 0x04 + IN R17, 0x05 + CPI R16, 0 + LDI R18, 2 + CPC R17, R18 + BRCS ??ADC_ISR_9 +// 174 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE, +// 175 (1024 - (ADC-ADCS.ADC5_G20_OS))); + LDI R16, 0 + LDI R17, 4 + IN R18, 0x04 + IN R19, 0x05 + SUB R16, R18 + SBC R17, R19 + LDS R18, (ADCS + 1) + SWAP R18 + ANDI R18, 0x0F + LDI R19, 0 + ADD R18, R16 + ADC R19, R17 + LDI R20, LOW(VBAT_RANGE) + LDI R21, (VBAT_RANGE) >> 8 + RCALL __eeget8_16 + RCALL ScaleI + NEG R17 + NEG R16 + SBCI R17, 0 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+12, R16 + STD Z+13, R17 + RJMP ??ADC_ISR_10 +// 176 } else if (ADC > 0) { +??ADC_ISR_9: + IN R16, 0x04 + IN R17, 0x05 + OR R16, R17 + BREQ ??ADC_ISR_11 +// 177 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS)); + IN R18, 0x04 + IN R19, 0x05 + LDS R16, (ADCS + 1) + SWAP R16 + ANDI R16, 0x0F + LDI R17, 0 + SUB R18, R16 + SBC R19, R17 + LDI R20, LOW(VBAT_RANGE) + LDI R21, (VBAT_RANGE) >> 8 + RCALL __eeget8_16 + RCALL ScaleI + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+12, R16 + STD Z+13, R17 + RJMP ??ADC_ISR_10 +// 178 } else { +// 179 ADCS.IBAT = 0; +??ADC_ISR_11: + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+12, R16 + STD Z+13, R17 +// 180 } +// 181 +// 182 // Insert sample of battery current into the averaging-array +// 183 // (overwriting the oldest sample), then recalculate and store the +// 184 // average. This is the last conversion in the sequence, so +// 185 // flag a complete ADC-cycle and restart sequence. +// 186 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT; +??ADC_ISR_10: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+12 + LDD R19, Z+13 + LDS R16, ??avgIndex + LDI R17, 0 + ANDI R16, 0x03 + ANDI R17, 0x00 + LSL R16 + ROL R17 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(ADCS) & 0xFFFF)) + SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + STD Z+14, R18 + STD Z+15, R19 + LDI R30, LOW(??avgIndex) + LDI R31, (??avgIndex) >> 8 + LD R16, Z + INC R16 + ST Z, R16 +// 187 for (i = 0; i < 4 ; i++) { + LDI R24, 0 +??ADC_ISR_12: + CPI R24, 4 + BRCC ??ADC_ISR_13 +// 188 temp += ADCS.discIBAT[i]; + MOV R16, R24 + LDI R17, 0 + LSL R16 + ROL R17 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(ADCS) & 0xFFFF)) + SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + LDD R16, Z+14 + LDD R17, Z+15 + ADD R26, R16 + ADC R27, R17 +// 189 } + INC R24 + RJMP ??ADC_ISR_12 +// 190 +// 191 ADCS.avgIBAT = (temp / 4); +??ADC_ISR_13: + MOVW R17:R16, R27:R26 + LDI R20, 4 + LDI R21, 0 + RCALL ?SS_DIVMOD_L02 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + STD Z+22, R16 + STD Z+23, R17 +// 192 +// 193 ADCS.Flag = TRUE; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ORI R16, 0x20 + ST Z, R16 +// 194 Next=0x01; + LDI R25, 1 +// 195 Signed = FALSE; // This is the only bipolar conversion. + CLR R4 + RJMP ??ADC_ISR_6 +// 196 break; +// 197 +// 198 +// 199 default: // Should not happen. (Invalid MUX-channel) +// 200 Next=0x01; // Start at the beginning of sequence. +??ADC_ISR_5: + LDI R25, 1 +// 201 break; +// 202 } +// 203 +// 204 // Update MUX to next channel in sequence, set a bipolar conversion if +// 205 // this has been flagged. +// 206 ADCS.MUX = Next; +??ADC_ISR_6: + LDS R17, ADCS + ANDI R17, 0xE0 + MOV R16, R25 + ANDI R16, 0x1F + OR R16, R17 + STS ADCS, R16 +// 207 ADMUX = (1<` +??avgIndex: + DS 1 +// 221 +// 222 +// 223 /*! \brief Scales sample to represent "actual voltage" in mV. +// 224 * +// 225 * This function returns the actual sampled voltage, scaled according +// 226 * to the jumper settings. +// 227 * +// 228 * \param setting Indicates what downscaling was used. +// 229 * \param data The sampled value. +// 230 * +// 231 * \note Table for setting-parameter:\n +// 232 *
+//  233  * Presume VREF = 2.5V and Gain = 1x.
+//  234  * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB
+//  235  * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)
+//  236  * --------+--------+------+------------+-----------+-------
+//  237  *     N/A |        |    - |       -    |   2.441mV |  2.50V
+//  238  *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V
+//  239  *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V
+//  240  *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V
+//  241  *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V
+//  242  *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V
+//  243  *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V
+//  244  * 
+// 245 */ + + RSEG CODE:CODE:NOROOT(1) +// 246 unsigned int ScaleU(unsigned char setting, unsigned int data) +ScaleU: +// 247 { + RCALL ?PROLOGUE6_L09 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + MOV R26, R16 + MOVW R25:R24, R19:R18 +// 248 // Temporary variable needed. +// 249 unsigned int scaled = 0; + CLR R4 + CLR R5 +// 250 +// 251 // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16 +// 252 if (setting == 3) { + CPI R26, 3 + BRNE ??ScaleU_0 +// 253 scaled = 29 * data; + MOVW R21:R20, R25:R24 + LDI R16, 29 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R5:R4, R17:R16 +// 254 scaled += (data >> 2); + MOVW R17:R16, R25:R24 + LSR R17 + ROR R16 + LSR R17 + ROR R16 + ADD R4, R16 + ADC R5, R17 +// 255 scaled += (data >> 4); + MOVW R17:R16, R25:R24 + LDI R20, 4 + RCALL ?US_SHR_L02 + ADD R4, R16 + ADC R5, R17 + RJMP ??ScaleU_1 +// 256 } else { +// 257 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16 +// 258 scaled = 39 * data; +??ScaleU_0: + MOVW R21:R20, R25:R24 + LDI R16, 39 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R5:R4, R17:R16 +// 259 scaled += (data >> 4); + MOVW R17:R16, R25:R24 + LDI R20, 4 + RCALL ?US_SHR_L02 + ADD R4, R16 + ADC R5, R17 +// 260 +// 261 if (setting <3) { + CPI R26, 3 + BRCC ??ScaleU_1 +// 262 // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8 +// 263 // 1: mV/LSB = 9.766 = 39.06 / 4 +// 264 // 2: mV/LSB = 19.53 = 39.06 / 2 +// 265 scaled = (scaled >> (3-setting)); + MOVW R17:R16, R5:R4 + LDI R20, 3 + SUB R20, R26 + RCALL ?US_SHR_L02 + MOVW R5:R4, R17:R16 +// 266 } +// 267 } +// 268 +// 269 return(scaled); +??ScaleU_1: + MOVW R17:R16, R5:R4 + LDI R30, 6 + RJMP ?EPILOGUE_B6_L09 +// 270 } +// 271 +// 272 +// 273 /*! \brief Scales sample to represent "actual current" in mA. +// 274 * +// 275 * This function returns the actual sampled current, scaled according +// 276 * to the jumper settings. +// 277 * +// 278 * \param setting Indicates what downscaling was used. +// 279 * \param data The sampled value. +// 280 * +// 281 * \note Table for setting-parameter:\n +// 282 *
+//  283  * Presume VREF = 2.5V and Gain = 1x or 20x.
+//  284  * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
+//  285  * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
+//  286  * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain
+//  287  * --------+------+------------+----------+----------+--------+-----
+//  288  *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x
+//  289  *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x
+//  290  *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x
+//  291  *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x
+//  292  *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x
+//  293  *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x
+//  294  *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x
+//  295  * 
+// 296 */ + + RSEG CODE:CODE:NOROOT(1) +// 297 unsigned int ScaleI(unsigned char setting, unsigned int data) +ScaleI: +// 298 { + RCALL ?PROLOGUE6_L09 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + MOV R26, R16 + MOVW R25:R24, R19:R18 +// 299 // Temporary variable needed. +// 300 unsigned int scaled = 0; + CLR R4 + CLR R5 +// 301 +// 302 // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128 +// 303 if (setting == 3) { + CPI R26, 3 + BRNE ??ScaleI_0 +// 304 scaled = 21 * data; + MOVW R21:R20, R25:R24 + LDI R16, 21 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R5:R4, R17:R16 +// 305 scaled -= (data >> 4); + MOVW R17:R16, R25:R24 + LDI R20, 4 + RCALL ?US_SHR_L02 + SUB R4, R16 + SBC R5, R17 +// 306 scaled += (data >> 7); + MOVW R17:R16, R25:R24 + LSL R16 + MOV R16, R17 + ROL R16 + LDI R17, 0 + ROL R17 + ADD R4, R16 + ADC R5, R17 + RJMP ??ScaleI_1 +// 307 } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32 +// 308 scaled = 28 * data; +??ScaleI_0: + MOVW R21:R20, R25:R24 + LDI R16, 28 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R5:R4, R17:R16 +// 309 scaled -= (data >> 3); + MOVW R17:R16, R25:R24 + LDI R20, 3 + RCALL ?US_SHR_L02 + SUB R4, R16 + SBC R5, R17 +// 310 scaled += (data >> 5); + MOVW R17:R16, R25:R24 + LDI R20, 5 + RCALL ?US_SHR_L02 + ADD R4, R16 + ADC R5, R17 +// 311 +// 312 if (setting <3) { + CPI R26, 3 + BRCC ??ScaleI_1 +// 313 // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8 +// 314 // 1: mA/LSB = 6.978mA = 27.909 / 4 +// 315 // 2: mA/LSB = 13.955mA = 27.909 / 2 +// 316 scaled = (scaled >> (3-setting)); + MOVW R17:R16, R5:R4 + LDI R20, 3 + SUB R20, R26 + RCALL ?US_SHR_L02 + MOVW R5:R4, R17:R16 +// 317 } +// 318 } +// 319 +// 320 return(scaled); +??ScaleI_1: + MOVW R17:R16, R5:R4 + LDI R30, 6 + RJMP ?EPILOGUE_B6_L09 +// 321 } +// 322 +// 323 +// 324 /*! \brief Waits for two full cycles of ADC-conversions to occur. +// 325 * +// 326 * This function clears the cycle complete-flag, then waits for it to be set +// 327 * again. This is then repeated once before the function exits. +// 328 * +// 329 */ + + RSEG CODE:CODE:NOROOT(1) +// 330 void ADC_Wait(void) +ADC_Wait: +// 331 { +// 332 // Clear ADC flag and wait for cycle to complete. +// 333 ADCS.Flag = FALSE; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ANDI R16, 0xDF + ST Z, R16 +// 334 do { +// 335 } while (ADCS.Flag == FALSE); +??ADC_Wait_0: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + SBRS R16, 5 + RJMP ??ADC_Wait_0 +// 336 +// 337 // Repeat, so we are sure the data beong to the same cycle. +// 338 ADCS.Flag = FALSE; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ANDI R16, 0xDF + ST Z, R16 +// 339 do { +// 340 } while (ADCS.Flag == FALSE); +??ADC_Wait_1: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + SBRS R16, 5 + RJMP ??ADC_Wait_1 +// 341 } + RET +// 342 +// 343 +// 344 /*! \brief Initializes ADC and input pins. +// 345 * +// 346 * This function initializes the ADC to free running mode, sampling from +// 347 * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n +// 348 * It also measures and stores calibration data for offset. +// 349 * +// 350 * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway. +// 351 * +// 352 * \note Table of MUX settings for offset measurement: +// 353 *
+//  354  *    Ch | Pin |    Gain |    MUX
+//  355  * ------+-----+---------+-------
+//  356  *  ADC1 | PA1 |     20x | 001101
+//  357  *  ADC3 | PA4 |     20x | 010001
+//  358  *  ADC5 | PA6 |     20x | 010110
+//  359  *  ADC9 | PB6 |     20x | 011011
+//  360  *  ADC0 | PA0 | 20x/32x | 111000
+//  361  *  ADC0 | PA0 |   1x/8x | 111001
+//  362  *  ADC1 | PA1 | 20x/32x | 111010
+//  363  *  ADC2 | PA2 | 20x/32x | 111011
+//  364  *  ADC4 | PA5 | 20x/32x | 111100
+//  365  *  ADC5 | PA6 | 20x/32x | 111101
+//  366  *  ADC6 | PA7 | 20x/32x | 111110
+//  367  * 
+// 368 */ + + RSEG CODE:CODE:NOROOT(1) +// 369 void ADC_Init(void) +ADC_Init: +// 370 { + ST -Y, R24 +// 371 unsigned char i; +// 372 +// 373 __disable_interrupt(); + CLI +// 374 +// 375 ADCS.Halt = FALSE; // Enable consecutive runs of ADC. + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ANDI R16, 0x7F + ST Z, R16 +// 376 +// 377 // Configure ADC pins (inputs and disabled pull-ups). +// 378 DDRA &= ~((1<> 8 + LD R16, Z + ANDI R16, 0xDF + ST Z, R16 +// 410 ADCS.MUX = 0x01; + LDS R16, ADCS + ANDI R16, 0xE0 + ORI R16, 0x01 + STS ADCS, R16 +// 411 ADMUX = (1<> 8 + STD Z+22, R16 + STD Z+23, R17 +// 415 +// 416 for (i = 0; i < 4; i++) { + LDI R24, 0 +??ADC_Init_2: + CPI R24, 4 + BRCC ??ADC_Init_3 +// 417 ADCS.discIBAT[i] = 0; + LDI R16, 0 + LDI R17, 0 + MOV R18, R24 + LDI R19, 0 + LSL R18 + ROL R19 + MOVW R31:R30, R19:R18 + SUBI R30, LOW((-(ADCS) & 0xFFFF)) + SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + STD Z+14, R16 + STD Z+15, R17 +// 418 } + INC R24 + RJMP ??ADC_Init_2 +// 419 +// 420 // Re-enable the ADC and ISR. +// 421 ADCSRA=(1<`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 7 bytes in segment ABSOLUTE +// 946 bytes in segment CODE +// 1 byte in segment EEPROM_I +// 6 bytes in segment INITTAB +// 2 bytes in segment INTVEC +// 25 bytes in segment NEAR_Z +// +// 946 bytes of CODE memory (+ 8 bytes shared) +// 25 bytes of DATA memory (+ 7 bytes shared) +// 1 byte of XDATA memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/BC100_tiny.html b/BaseTinyFirmware/IAR/Debug/List/BC100_tiny.html new file mode 100644 index 0000000..fe2ce33 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/BC100_tiny.html @@ -0,0 +1,3208 @@ + + + +XLINK Map File for "BC100_tiny" + + +

XLINK Map File for "BC100_tiny"

+

IAR Universal Linker V4.60I/386

+

Copyright 1987-2007 IAR Systems. All rights reserved.

+ +

+Invocation +  Program Entry +  Module Map +  Module Summary +  Call Graph +  Segment Map +  Memory Summary +


+

+ + + + + + + +
Link time + 12/Mar/2008 23:01:40 +
Target CPU + A90 +
List file + C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\BC100_tiny.html +
Output file 1 + C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Exe\BC100_tiny.d90 +
+ Format: ubrof8 +
+ UBROF version 8.0.2 +
Command line + +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\OWI.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\USI.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\battery.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\chargefunc.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\menu.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\statefunc.r90 +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\time.r90 +-o +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Exe\BC100_tiny.d90 +-Fubrof8 +-l +C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\BC100_tiny.html +-xmsnoh +"-"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\" +-f +"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\src\template\cfgtiny861.xcl" +( -D_..X_INTVEC_SIZE=26 +-D_..X_FLASH_END=1FFF +-D_..X_SRAM_BASE=60 +-D_..X_SRAM_TBASE=_..X_SRAM_BASE +-D_..X_SRAM_TSIZE=(100-_..X_SRAM_BASE) +-D_..X_SRAM_END=25F +-D_..X_EXT_SRAM_BASE=_..X_SRAM_END +-D_..X_EXT_SRAM_SIZE=0 +-D_..X_EXT_ROM_BASE=_..X_SRAM_END +-D_..X_EXT_ROM_SIZE=0 +-D_..X_EXT_NV_BASE=_..X_SRAM_END +-D_..X_EXT_NV_SIZE=0 +-D_..X_EEPROM_END=1FF +-D_..X_EEPROM_START=0 +) -D_..X_HEAP_SIZE=10 +-D_..X_TINY_HEAP_SIZE=0 +-D_..X_NEAR_HEAP_SIZE=0 +-D_..X_FAR_HEAP_SIZE=0 +-D_..X_HUGE_HEAP_SIZE=0 +-D_..X_CSTACK_SIZE=40 +-D_..X_RSTACK_SIZE=30 +-f +"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\src\template\cfg1soim.xcl" +( -ca90 +-w29 +-Z(CODE)INTVEC=0-_..X_INTVEC_SIZE +-Z(CODE)TINY_F=_..X_FLASH_BASE-FF +-Z(CODE)NEAR_F=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)SWITCH=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)INITTAB=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)DIFUNCT=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)TINY_ID=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)NEAR_ID=_..X_FLASH_BASE-_..X_FLASH_END +-Z(CODE)CHECKSUM#_..X_FLASH_END +-Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_TBASE:+_..X_SRAM_TSIZE +-Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_CSTACK_BASE-_..X_CSTACK_END +-Z(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END +-Z(DATA)IOSTREAM_N#_..X_SRAM_BASE-_..X_SRAM_END +-Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_BASE-_..X_SRAM_END +-Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE-_..X_RSTACK_END +-Z(DATA)NEAR_I,NEAR_Z,NEAR_N=_..X_SRAM_BASE-_..X_SRAM_END +-Z(XDATA)EEPROM_I,EEPROM_N=_..X_EEPROM_START-_..X_EEPROM_END +) -D_..X_FLASH_BASE=_..X_INTVEC_SIZE +-H1895 +-h(CODE)0-(_..X_INTVEC_SIZE-1) +-D_..X_CSTACK_BASE=_..X_SRAM_BASE +-D_..X_CSTACK_END=_..X_SRAM_END +-D_..X_RSTACK_BASE=_..X_SRAM_BASE +-D_..X_RSTACK_END=_..X_SRAM_END +-s +__program_start +"C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90" +-e_small_write=_formatted_write +-e_medium_read=_formatted_read + +
+ + + +


+ Program entry at : CODE 00000000 Relocatable, from module : ?RESET + + +


+ + + + + + + + + + + + + + + + + +
Runtime Model + +
Attribute + Value +
EEPROM_SIZE + 2 +
R4 + REG +
R5 + REG +
R6 + REG +
R7 + REG +
R8 + REG +
__64bit_doubles + disabled +
__cpu + 1 +
__cpu_name + ATtiny861 +
__enhanced_core + enabled +
__has_elpm + false +
__memory_model + 2 +
__rt_version + 3 +
+


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Module Map + +
File + Module + Segment + Symbol + Address + Ref by +
+ ?ABS_ENTRY_MOD
Program module
+
Absolute parts + _..X_RSTACK_END + + 0000025F + - +
_..X_RSTACK_BASE + + 00000060 + - +
_..X_CSTACK_END + + 0000025F + - +
_..X_CSTACK_BASE + + 00000060 + - +
_..X_FLASH_BASE + + 00000026 + - +
_..X_RSTACK_SIZE + + 00000030 + - +
_..X_CSTACK_SIZE + + 00000040 + - +
_..X_HUGE_HEAP_SIZE + + 00000000 + - +
_..X_FAR_HEAP_SIZE + + 00000000 + - +
_..X_NEAR_HEAP_SIZE + + 00000000 + - +
_..X_TINY_HEAP_SIZE + + 00000000 + - +
_..X_HEAP_SIZE + + 00000010 + - +
_..X_EEPROM_START + + 00000000 + - +
_..X_EEPROM_END + + 000001FF + - +
_..X_EXT_NV_SIZE + + 00000000 + - +
_..X_EXT_NV_BASE + + 0000025F + - +
_..X_EXT_ROM_SIZE + + 00000000 + - +
_..X_EXT_ROM_BASE + + 0000025F + - +
_..X_EXT_SRAM_SIZE + + 00000000 + - +
_..X_EXT_SRAM_BASE + + 0000025F + - +
_..X_SRAM_END + + 0000025F + - +
_..X_SRAM_TSIZE + + 000000A0 + - +
_..X_SRAM_TBASE + + 00000060 + - +
_..X_SRAM_BASE + + 00000060 + - +
_..X_FLASH_END + + 00001FFF + - +
_..X_INTVEC_SIZE + + 00000026 + - +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ADC.r90 + ADC
Program module
+
ABSOLUTE
Relative segment
DATA 0000003B - 0000003B
Segment part 1.
+
Intra module refs +   ADC_Init +
OWI_DetectPresence (OWI) +
OWI_Init (OWI) +
OWI_ReadBit (OWI) +
OWI_WriteBit0 (OWI) +
OWI_WriteBit1 (OWI) +
_A_PORTA + + 0000003B + - +
ABSOLUTE
Relative segment
DATA 0000003A - 0000003A
Segment part 2.
+
Intra module refs +   ADC_Init +
OWI_DetectPresence (OWI) +
OWI_Init (OWI) +
OWI_ReadBit (OWI) +
OWI_WriteBit0 (OWI) +
OWI_WriteBit1 (OWI) +
_A_DDRA + + 0000003A + - +
ABSOLUTE
Relative segment
DATA 00000027 - 00000027
Segment part 3.
+
Intra module refs +   ADC_ISR +
ADC_Init +
_A_ADMUX + + 00000027 + - +
ABSOLUTE
Relative segment
DATA 00000026 - 00000026
Segment part 4.
+
Intra module refs +   ADC_ISR +
ADC_Init +
Doze (statefunc) +
_A_ADCSRA + + 00000026 + - +
ABSOLUTE
Relative segment
DATA 00000024 - 00000025
Segment part 5.
+
Intra module refs +   ADC_ISR +
ADC_Init +
_A_ADC + + 00000024 + - +
ABSOLUTE
Relative segment
DATA 00000023 - 00000023
Segment part 6.
+
Intra module refs +   ADC_ISR +
ADC_Init +
_A_ADCSRB + + 00000023 + - +
NEAR_Z
Relative segment
DATA 00000144 - 0000015B
Segment part 14.
+
Intra module refs +   ADC_ISR +
ADC_Init +
ADC_Wait +
ADCS + + 00000144 + BatteryStatusRefresh (battery) +
ConstantCurrent (chargefunc) +
Doze (statefunc) +
HaltNow (chargefunc) +
JumperCheck (statefunc) +
NTCLookUp (battery) +
RIDLookUp (battery) +
USI_OVF_ISR (USI) +
EEPROM_I
Relative segment
XDATA 00000000 - 00000000
Segment part 16.
+
Intra module refs +   ADC_ISR +
VBAT_RANGE + + 00000000 + - +
CODE
Relative segment
CODE 00000050 - 0000025F
Segment part 18.
+
Intra module refs +   ADC_ISR::??INTVEC 22 +
ADC_ISR +
interrupt function +
calls direct +
stack 1 = 00000000 ( 00000014 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000050 + - +
NEAR_Z
Relative segment
DATA 0000015C - 0000015C
Segment part 17.
+
Intra module refs +   ADC_ISR +
ADC_ISR::avgIndex + + 0000015C +
CODE
Relative segment
CODE 00000260 - 000002B9
Segment part 19.
+
Intra module refs +   ADC_ISR +
ScaleU +
stack 1 = 00000000 ( 00000006 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000260 + - +
CODE
Relative segment
CODE 000002BA - 0000031F
Segment part 20.
+
Intra module refs +   ADC_ISR +
ScaleI +
stack 1 = 00000000 ( 00000006 ) +
stack 2 = 00000000 ( 00000004 ) +
+
000002BA + - +
CODE
Relative segment
CODE 00000320 - 00000349
Segment part 21.
+
Intra module refs +   ADC_Init +
ADC_Wait +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000320 + BatteryControl (statefunc) +
ConstantCurrent (chargefunc) +
Doze (statefunc) +
HaltNow (chargefunc) +
Initialize (statefunc) +
JumperCheck (statefunc) +
Sleep (statefunc) +
CODE
Relative segment
CODE 0000034A - 00000401
Segment part 22.
+
ADC_Init +
calls direct +
stack 1 = 00000000 ( 00000001 ) +
stack 2 = 00000000 ( 00000002 ) +
+
0000034A + Initialize (statefunc) +
ABSOLUTE
Relative segment
DATA 0000001C
Segment part 7.
+
__?EECR + + 0000001C + Segment part 0 (?EEPROM_16) +
Segment part 1 (?EEPROM_16) +
Segment part 8 (?EEPROM_16) +
ABSOLUTE
Relative segment
DATA 0000001D
Segment part 8.
+
__?EEDR + + 0000001D + __eeget8_16 (?EEPROM_16) +
__eeput8_16 (?EEPROM_16) +
ABSOLUTE
Relative segment
DATA 0000001E
Segment part 9.
+
__?EEARL + + 0000001E + Segment part 1 (?EEPROM_16) +
Segment part 8 (?EEPROM_16) +
ABSOLUTE
Relative segment
DATA 0000001F
Segment part 10.
+
__?EEARH + + 0000001F + Segment part 1 (?EEPROM_16) +
Segment part 8 (?EEPROM_16) +
INTVEC
Common segment
CODE 00000000 - 00000017
Segment part 11. ROOT.
+
ADC_ISR::??INTVEC 22 + + 00000016 + - +
INITTAB
Relative segment
CODE 00000044 - 00000049
Segment part 15.
+
Intra module refs +   ADCS +
ADC_ISR::avgIndex +
BattActive (battery) +
BattData (battery) +
ChargeParameters (chargefunc) +
CurrentState (main) +
ErrorFlags (statefunc) +
ErrorState (statefunc) +
HaltParameters (chargefunc) +
SPI (USI) +
timeval (time) +
?<Segment init: NEAR_Z> + + 00000044 + - +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge.r90 + NIMHcharge
Program module
+
CODE
Relative segment
CODE 00000402 - 00000565
Segment part 7.
+
Charge +
calls direct +
stack 1 = 00000000 ( 00000002 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000402 + menu_state (menu) +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\OWI.r90 + OWI
Program module
+
ABSOLUTE
Relative segment
DATA 00000039 - 00000039
Segment part 3.
+
Intra module refs +   OWI_DetectPresence +
OWI_ReadBit +
_A_PINA + + 00000039 + - +
CODE
Relative segment
CODE 00000566 - 00000587
Segment part 10.
+
OWI_Init +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000566 + Initialize (statefunc) +
CODE
Relative segment
CODE 00000588 - 000005C5
Segment part 11.
+
Intra module refs +   OWI_SendByte +
OWI_WriteBit1 +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000588 + - +
CODE
Relative segment
CODE 000005C6 - 00000603
Segment part 12.
+
Intra module refs +   OWI_SendByte +
OWI_WriteBit0 +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000005C6 + - +
CODE
Relative segment
CODE 00000604 - 00000651
Segment part 13.
+
Intra module refs +   OWI_ReceiveByte +
OWI_ReadBit +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000604 + - +
CODE
Relative segment
CODE 00000652 - 000006A9
Segment part 14.
+
OWI_DetectPresence +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000652 + BatteryDataRefresh (battery) +
CODE
Relative segment
CODE 000006AA - 000006D3
Segment part 15.
+
OWI_SendByte +
calls direct +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000006AA + BatteryDataRefresh (battery) +
CODE
Relative segment
CODE 000006D4 - 000006F7
Segment part 16.
+
OWI_ReceiveByte +
calls direct +
stack 1 = 00000000 ( 00000003 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000006D4 + BatteryDataRefresh (battery) +
CODE
Relative segment
CODE 000006F8 - 00000729
Segment part 21.
+
OWI_ComputeCRC8 +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000006F8 + BatteryDataRefresh (battery) +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90 + PWM
Program module
+
ABSOLUTE
Relative segment
DATA 00000050 - 00000050
Segment part 1.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_TCCR1A + + 00000050 + - +
ABSOLUTE
Relative segment
DATA 0000004F - 0000004F
Segment part 2.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_TCCR1B + + 0000004F + - +
ABSOLUTE
Relative segment
DATA 0000004D - 0000004D
Segment part 3.
+
Intra module refs +   PWM_Start +
_A_OCR1A + + 0000004D + - +
ABSOLUTE
Relative segment
DATA 0000004C - 0000004C
Segment part 4.
+
Intra module refs +   BatteryStatusRefresh (battery) +
ConstantCurrent (chargefunc) +
PWM_DecrementDutyCycle +
PWM_IncrementDutyCycle +
PWM_Start +
PWM_Stop +
_A_OCR1B + + 0000004C + - +
ABSOLUTE
Relative segment
DATA 0000004B - 0000004B
Segment part 5.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_OCR1C + + 0000004B + - +
ABSOLUTE
Relative segment
DATA 0000004A - 0000004A
Segment part 6.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_OCR1D + + 0000004A + - +
ABSOLUTE
Relative segment
DATA 00000049 - 00000049
Segment part 7.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_PLLCSR + + 00000049 + - +
ABSOLUTE
Relative segment
DATA 00000047 - 00000047
Segment part 8.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_TCCR1C + + 00000047 + - +
ABSOLUTE
Relative segment
DATA 00000046 - 00000046
Segment part 9.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_TCCR1D + + 00000046 + - +
ABSOLUTE
Relative segment
DATA 00000044 - 00000044
Segment part 10.
+
Intra module refs +   PWM_Start +
PWM_Stop +
_A_DT1 + + 00000044 + - +
ABSOLUTE
Relative segment
DATA 00000037 - 00000037
Segment part 11.
+
Intra module refs +   Initialize (statefunc) +
PWM_Start +
SPI_Init (USI) +
_A_DDRB + + 00000037 + - +
ABSOLUTE
Relative segment
DATA 00000020 - 00000020
Segment part 12.
+
Intra module refs +   PWM_Start +
_A_TCCR1E + + 00000020 + - +
CODE
Relative segment
CODE 0000072A - 0000074F
Segment part 19.
+
PWM_Stop +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
0000072A + Charge (NIMHcharge) +
Error (statefunc) +
HaltNow (chargefunc) +
JumperCheck (statefunc) +
CODE
Relative segment
CODE 00000750 - 000007A9
Segment part 20.
+
PWM_Start +
calls direct +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000750 + Charge (NIMHcharge) +
JumperCheck (statefunc) +
CODE
Relative segment
CODE 000007AA - 000007BD
Segment part 21.
+
PWM_IncrementDutyCycle +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000007AA + ConstantCurrent (chargefunc) +
JumperCheck (statefunc) +
CODE
Relative segment
CODE 000007BE - 000007D1
Segment part 22.
+
PWM_DecrementDutyCycle +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000007BE + ConstantCurrent (chargefunc) +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\USI.r90 + USI
Program module
+
ABSOLUTE
Relative segment
DATA 00000038 - 00000038
Segment part 1.
+
Intra module refs +   DisableBatteries (battery) +
EnableBattery (battery) +
SPI_Init +
_A_PORTB + + 00000038 + - +
ABSOLUTE
Relative segment
DATA 0000002F - 0000002F
Segment part 3.
+
Intra module refs +   SPI_Put +
USI_OVF_ISR +
_A_USIDR + + 0000002F + - +
ABSOLUTE
Relative segment
DATA 0000002E - 0000002E
Segment part 4.
+
Intra module refs +   SPI_Put +
USI_OVF_ISR +
_A_USISR + + 0000002E + - +
ABSOLUTE
Relative segment
DATA 0000002D - 0000002D
Segment part 5.
+
Intra module refs +   SPI_Init +
_A_USICR + + 0000002D + - +
NEAR_Z
Relative segment
DATA 0000015D - 00000160
Segment part 13.
+
Intra module refs +   SPI_Init +
SPI_Put +
USI_OVF_ISR +
SPI + + 0000015D + - +
CODE
Relative segment
CODE 000007D2 - 000009E7
Segment part 15.
+
Intra module refs +   USI_OVF_ISR::??INTVEC 16 +
USI_OVF_ISR +
interrupt function +
calls direct +
stack 1 = 00000000 ( 00000011 ) +
stack 2 = 00000000 ( 00000004 ) +
+
000007D2 + - +
CODE
Relative segment
CODE 000009E8 - 00000A4F
Segment part 16.
+
SPI_Init +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000009E8 + Initialize (statefunc) +
CODE
Relative segment
CODE 00000A50 - 00000A81
Segment part 17.
+
Intra module refs +   USI_OVF_ISR +
SPI_Put +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000A50 + - +
INTVEC
Common segment
CODE 00000000 - 00000011
Segment part 10. ROOT.
+
USI_OVF_ISR::??INTVEC 16 + + 00000010 + - +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\battery.r90 + battery
Program module
+
EEPROM_I
Relative segment
XDATA 00000001 - 00000002
Segment part 9.
+
BattControl + + 00000001 + BatteryControl (statefunc) +
Charge (NIMHcharge) +
ConstantCurrent (chargefunc) +
Error (statefunc) +
HaltNow (chargefunc) +
USI_OVF_ISR (USI) +
NEAR_Z
Relative segment
DATA 00000161 - 0000016C
Segment part 10.
+
Intra module refs +   BatteryCheck +
BatteryDataRefresh +
BatteryStatusRefresh +
NTCLookUp +
RIDLookUp +
BattData + + 00000161 + BatteryControl (statefunc) +
Charge (NIMHcharge) +
Error (statefunc) +
HaltNow (chargefunc) +
Sleep (statefunc) +
USI_OVF_ISR (USI) +
EEPROM_I
Relative segment
XDATA 00000003 - 00000082
Segment part 12.
+
Intra module refs +   BatteryDataRefresh +
BattEEPROM + + 00000003 + Initialize (statefunc) +
NEAR_Z
Relative segment
DATA 0000016D - 0000016D
Segment part 13.
+
Intra module refs +   EnableBattery +
BattActive + + 0000016D + Charge (NIMHcharge) +
ConstantCurrent (chargefunc) +
Error (statefunc) +
HaltNow (chargefunc) +
Initialize (statefunc) +
USI_OVF_ISR (USI) +
NEAR_I
Relative segment
DATA 000000D0 - 00000107
Segment part 14.
+
Intra module refs +   RIDLookUp +
RID + + 000000D0 + - +
NEAR_I
Relative segment
DATA 00000108 - 00000143
Segment part 17.
+
Intra module refs +   NTCLookUp +
NTC + + 00000108 + - +
CODE
Relative segment
CODE 00000A82 - 00000AAD
Segment part 19.
+
BatteryCheck +
calls direct +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000A82 + HaltNow (chargefunc) +
CODE
Relative segment
CODE 00000AAE - 00000BA5
Segment part 20.
+
Intra module refs +   BatteryCheck +
BatteryStatusRefresh +
calls direct +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000AAE + BatteryControl (statefunc) +
Initialize (statefunc) +
Sleep (statefunc) +
CODE
Relative segment
CODE 00000BA6 - 00000CBD
Segment part 21.
+
BatteryDataRefresh +
calls direct +
stack 1 = 00000000 ( 00000008 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000BA6 + BatteryControl (statefunc) +
CODE
Relative segment
CODE 00000CBE - 00000CFF
Segment part 22.
+
EnableBattery +
calls direct +
stack 1 = 00000000 ( 00000001 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000CBE + BatteryControl (statefunc) +
Initialize (statefunc) +
Sleep (statefunc) +
CODE
Relative segment
CODE 00000D00 - 00000D07
Segment part 23.
+
DisableBatteries +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00000D00 + BatteryControl (statefunc) +
Error (statefunc) +
Initialize (statefunc) +
JumperCheck (statefunc) +
Sleep (statefunc) +
CODE
Relative segment
CODE 00000D08 - 00000E09
Segment part 24.
+
Intra module refs +   BatteryStatusRefresh +
RIDLookUp +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000D08 + - +
CODE
Relative segment
CODE 00000E0A - 00000EA9
Segment part 25.
+
Intra module refs +   BatteryStatusRefresh +
NTCLookUp +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000E0A + - +
NEAR_ID
Relative segment
CODE 0000186A - 000018A1
Segment part 15.
+
Intra module refs +   RID +
INITTAB
Relative segment
CODE 0000004A - 0000004F
Segment part 16.
+
Intra module refs +   NTC +
RID +
?<Segment init: NEAR_I> + + 0000004A + - +
NEAR_ID
Relative segment
CODE 000018A2 - 000018DD
Segment part 18.
+
Intra module refs +   NTC +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\chargefunc.r90 + chargefunc
Program module
+
NEAR_Z
Relative segment
DATA 0000016E - 00000172
Segment part 8.
+
Intra module refs +   ConstantCurrent +
HaltNow +
ChargeParameters + + 0000016E + Charge (NIMHcharge) +
NEAR_Z
Relative segment
DATA 00000173 - 00000183
Segment part 10.
+
Intra module refs +   HaltNow +
HaltParameters + + 00000173 + Charge (NIMHcharge) +
CODE
Relative segment
CODE 00000EAA - 00000F5D
Segment part 11.
+
ConstantCurrent +
calls direct +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000EAA + Charge (NIMHcharge) +
CODE
Relative segment
CODE 00000F5E - 0000115B
Segment part 13.
+
Intra module refs +   ConstantCurrent +
HaltNow +
calls direct +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00000F5E + - +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90 + main
Program module
+
NEAR_Z
Relative segment
DATA 00000184 - 00000184
Segment part 7.
+
Intra module refs +   main +
CurrentState + + 00000184 + Charge (NIMHcharge) +
SetErrorFlag (statefunc) +
CODE
Relative segment
CODE 0000115C - 00001237
Segment part 9.
+
main +
calls indirect +
stack 1 = 00000000 ( 00000007 ) +
stack 2 = 00000000 ( 00000004 ) +
+
0000115C + ?cstartup_call_main (?C_STARTUP) +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\menu.r90 + menu
Program module
+
NEAR_F
Relative segment
CODE 00000026 - 00000043
Segment part 7.
+
menu_state + + 00000026 + main (main) +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\statefunc.r90 + statefunc
Program module
+
ABSOLUTE
Relative segment
DATA 00000055 - 00000055
Segment part 1.
+
Intra module refs +   Doze +
_A_MCUCR + + 00000055 + - +
ABSOLUTE
Relative segment
DATA 00000054 - 00000054
Segment part 2.
+
Intra module refs +   Doze +
_A_MCUSR + + 00000054 + - +
ABSOLUTE
Relative segment
DATA 00000048 - 00000048
Segment part 3.
+
Intra module refs +   Initialize +
_A_CLKPR + + 00000048 + - +
ABSOLUTE
Relative segment
DATA 00000041 - 00000041
Segment part 4.
+
Intra module refs +   Doze +
_A_WDTCR + + 00000041 + - +
NEAR_Z
Relative segment
DATA 00000185 - 00000185
Segment part 13.
+
Intra module refs +   Error +
Initialize +
SetErrorFlag +
ErrorFlags + + 00000185 + - +
NEAR_Z
Relative segment
DATA 00000186 - 00000186
Segment part 15.
+
Intra module refs +   SetErrorFlag +
ErrorState + + 00000186 + - +
CODE
Relative segment
CODE 00001238 - 000012B1
Segment part 16.
+
Initialize +
calls direct +
stack 1 = 00000000 ( 00000004 ) +
stack 2 = 00000000 ( 00000004 ) +
+
00001238 + menu_state (menu) +
CODE
Relative segment
CODE 000012B2 - 0000131F
Segment part 17.
+
BatteryControl +
calls direct +
stack 1 = 00000000 ( 00000003 ) +
stack 2 = 00000000 ( 00000004 ) +
+
000012B2 + menu_state (menu) +
CODE
Relative segment
CODE 00001320 - 00001325
Segment part 18.
+
Discharge +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001320 + menu_state (menu) +
CODE
Relative segment
CODE 00001326 - 00001357
Segment part 19.
+
Sleep +
calls direct +
stack 1 = 00000000 ( 00000002 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001326 + menu_state (menu) +
CODE
Relative segment
CODE 00001358 - 000013AF
Segment part 20.
+
Intra module refs +   Error +
Sleep +
Doze +
calls direct +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001358 + - +
CODE
Relative segment
CODE 000013B0 - 0000147F
Segment part 21.
+
Error +
calls direct +
stack 1 = 00000000 ( 00000002 ) +
stack 2 = 00000000 ( 00000004 ) +
+
000013B0 + menu_state (menu) +
CODE
Relative segment
CODE 00001480 - 00001493
Segment part 22.
+
Intra module refs +   BatteryControl +
SetErrorFlag +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001480 + ConstantCurrent (chargefunc) +
HaltNow (chargefunc) +
CODE
Relative segment
CODE 00001494 - 00001515
Segment part 23.
+
Intra module refs +   BatteryControl +
Error +
JumperCheck +
calls direct +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001494 + - +
C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\time.r90 + time
Program module
+
ABSOLUTE
Relative segment
DATA 00000059 - 00000059
Segment part 1.
+
Intra module refs +   Time_Init +
_A_TIMSK + + 00000059 + - +
ABSOLUTE
Relative segment
DATA 00000053 - 00000053
Segment part 2.
+
Intra module refs +   Time_Init +
Time_Start +
Time_Stop +
_A_TCCR0B + + 00000053 + - +
ABSOLUTE
Relative segment
DATA 00000035 - 00000035
Segment part 3.
+
Intra module refs +   Time_Init +
_A_TCCR0A + + 00000035 + - +
ABSOLUTE
Relative segment
DATA 00000033 - 00000033
Segment part 4.
+
Intra module refs +   Time_Init +
_A_OCR0A + + 00000033 + - +
ABSOLUTE
Relative segment
DATA 00000032 - 00000032
Segment part 5.
+
Intra module refs +   Time_Init +
_A_OCR0B + + 00000032 + - +
NEAR_Z
Relative segment
DATA 00000187 - 00000196
Segment part 13.
+
Intra module refs +   TICK_ISR +
Time_Init +
Time_Left +
Time_Set +
timeval + + 00000187 + USI_OVF_ISR (USI) +
CODE
Relative segment
CODE 00001516 - 0000159D
Segment part 15.
+
Intra module refs +   TICK_ISR::??INTVEC 28 +
TICK_ISR +
interrupt function +
stack 1 = 00000000 ( 0000000B ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001516 + - +
CODE
Relative segment
CODE 0000159E - 000015C9
Segment part 16.
+
Time_Left +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
0000159E + EnableBattery (battery) +
HaltNow (chargefunc) +
JumperCheck (statefunc) +
PWM_Start (PWM) +
USI_OVF_ISR (USI) +
CODE
Relative segment
CODE 000015CA - 0000166F
Segment part 17.
+
Time_Set +
stack 1 = 00000000 ( 00000007 ) +
stack 2 = 00000000 ( 00000004 ) +
+
000015CA + Charge (NIMHcharge) +
EnableBattery (battery) +
HaltNow (chargefunc) +
JumperCheck (statefunc) +
PWM_Start (PWM) +
USI_OVF_ISR (USI) +
CODE
Relative segment
CODE 00001670 - 00001675
Segment part 18.
+
Time_Stop +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001670 + ConstantCurrent (chargefunc) +
CODE
Relative segment
CODE 00001676 - 0000167B
Segment part 19.
+
Time_Start +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001676 + ConstantCurrent (chargefunc) +
CODE
Relative segment
CODE 0000167C - 000016C1
Segment part 20.
+
Time_Init +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
0000167C + Initialize (statefunc) +
INTVEC
Common segment
CODE 00000000 - 0000001D
Segment part 10. ROOT.
+
TICK_ISR::??INTVEC 28 + + 0000001C + - +
C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90 + ?__exit
Library module
+
CODE
Relative segment
CODE 000016C2 - 000016C7
Segment part 0.
+
__exit + + 000016C4 + - +
?C_EXIT + + 000016C4 + - +
?C_FUNCALL + + 000016C2 + - +
_exit + + 000016C2 + ?cstartup_call_main (?C_STARTUP) +
exit + + 000016C2 + ?cstartup_call_main (?C_STARTUP) +
?abs
Library module
+
CODE
Relative segment
CODE 000016C8 - 000016D7
Segment part 3.
+
abs +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
000016C8 + JumperCheck (statefunc) +
?RESET
Library module
+
INTVEC
Common segment
CODE 00000000 - 00000001
Segment part 0. ROOT.
+
__program_start + + 00000000 + Absolute parts (?ABS_ENTRY_MOD) +
?RESET + + 00000000 + Segment part 2 (?C_STARTUP) +
?C_STARTUP
Library module
+
CODE
Relative segment
CODE 000016D8
Segment part 2.
+
?C_STARTUP + + 000016D8 + Segment part 0 (?RESET) +
__RESTART + + 000016D8 + - +
CODE
Relative segment
CODE 000016D8 - 000016E3
Segment part 5.
+
Intra module refs +   Segment part 2 +
CODE
Relative segment
CODE 000016E4 - 000016E5
Segment part 7.
+
Intra module refs +   Segment part 5 +
?call_low_level_init + + 000016E4 + - +
CODE
Relative segment
CODE 000016E6 - 000016EB
Segment part 8.
+
?need_segment_init + + 000016E6 + ?<Segment init: NEAR_I> (battery) +
?<Segment init: NEAR_Z> (ADC) +
CODE
Relative segment
CODE 000016EC - 000016F1
Segment part 9.
+
Intra module refs +   ?call_low_level_init +
?cstartup_call_main + + 000016EC + - +
?EEPROM_16
Library module
+
CODE
Relative segment
CODE 000016F2 - 000016F7
Segment part 0.
+
Intra module refs +   Segment part 1 +
__eeput8_16 +
CODE
Relative segment
CODE 000016F8 - 00001705
Segment part 1.
+
Intra module refs +   __eeget8_16 +
CODE
Relative segment
CODE 00001706 - 0000170B
Segment part 3.
+
__eeget8_16 + + 00001706 + ADC_ISR (ADC) +
BatteryControl (statefunc) +
Charge (NIMHcharge) +
ConstantCurrent (chargefunc) +
Error (statefunc) +
HaltNow (chargefunc) +
USI_OVF_ISR (USI) +
CODE
Relative segment
CODE 0000170C - 0000171D
Segment part 8.
+
Intra module refs +   __eeput8_16 +
CODE
Relative segment
CODE 0000171E - 00001725
Segment part 10.
+
__eeput8_16 + + 0000171E + BatteryDataRefresh (battery) +
HaltNow (chargefunc) +
Initialize (statefunc) +
USI_OVF_ISR (USI) +
?S_MUL_L02
Library module
+
CODE
Relative segment
CODE 00001726 - 00001745
Segment part 0.
+
?S_MUL_L02 + + 00001726 + BatteryDataRefresh (battery) +
HaltNow (chargefunc) +
Initialize (statefunc) +
NTCLookUp (battery) +
RIDLookUp (battery) +
ScaleI (ADC) +
ScaleU (ADC) +
main (main) +
?S_SHL_L02
Library module
+
CODE
Relative segment
CODE 00001746 - 00001751
Segment part 0.
+
?S_SHL_L02 + + 00001746 + EnableBattery (battery) +
?US_SHR_L02
Library module
+
CODE
Relative segment
CODE 00001752 - 0000175D
Segment part 0.
+
?US_SHR_L02 + + 00001752 + ScaleI (ADC) +
ScaleU (ADC) +
?US_DIVMOD_L02
Library module
+
CODE
Relative segment
CODE 0000175E - 00001785
Segment part 0.
+
?US_DIVMOD_L02 + + 0000175E + ?SS_DIVMOD_L02 (?SS_DIVMOD_L02) +
Charge (NIMHcharge) +
NTCLookUp (battery) +
?SS_DIVMOD_L02
Library module
+
CODE
Relative segment
CODE 00001786 - 000017B3
Segment part 0.
+
?SS_DIVMOD_L02 + + 0000178E + ADC_ISR (ADC) +
Charge (NIMHcharge) +
Error (statefunc) +
?L_MUL_L03
Library module
+
CODE
Relative segment
CODE 000017B4 - 000017E5
Segment part 0.
+
?L_MUL_L03 + + 000017B4 + Time_Set (time) +
?PROLOGUE_L09
Library module
+
CODE
Relative segment
CODE 000017E6 - 000017E7
Segment part 8.
+
?PROLOGUE8_L09 + + 000017E6 + BatteryDataRefresh (battery) +
CODE
Relative segment
CODE 000017E8 - 000017E9
Segment part 9.
+
Intra module refs +   ?PROLOGUE8_L09 +
?PROLOGUE7_L09 + + 000017E8 + Time_Set (time) +
main (main) +
CODE
Relative segment
CODE 000017EA - 000017EB
Segment part 10.
+
Intra module refs +   ?PROLOGUE7_L09 +
?PROLOGUE6_L09 + + 000017EA + ScaleI (ADC) +
ScaleU (ADC) +
CODE
Relative segment
CODE 000017EC - 000017ED
Segment part 11.
+
Intra module refs +   ?PROLOGUE6_L09 +
?PROLOGUE5_L09 + + 000017EC + - +
CODE
Relative segment
CODE 000017EE - 000017EF
Segment part 12.
+
Intra module refs +   ?PROLOGUE5_L09 +
?PROLOGUE4_L09 + + 000017EE + BatteryCheck (battery) +
BatteryStatusRefresh (battery) +
ConstantCurrent (chargefunc) +
HaltNow (chargefunc) +
Initialize (statefunc) +
NTCLookUp (battery) +
OWI_SendByte (OWI) +
RIDLookUp (battery) +
CODE
Relative segment
CODE 000017F0 - 000017F1
Segment part 13.
+
Intra module refs +   ?PROLOGUE4_L09 +
?PROLOGUE3_L09 + + 000017F0 + BatteryControl (statefunc) +
OWI_ReceiveByte (OWI) +
CODE
Relative segment
CODE 000017F2 - 000017F3
Segment part 14.
+
Intra module refs +   ?PROLOGUE3_L09 +
?PROLOGUE2_L09 + + 000017F2 + Charge (NIMHcharge) +
Error (statefunc) +
Sleep (statefunc) +
CODE
Relative segment
CODE 000017F4 - 000017F5
Segment part 15.
+
Intra module refs +   ?PROLOGUE2_L09 +
?PROLOGUE1_L09 + + 000017F4 + - +
CODE
Relative segment
CODE 000017F6 - 000017F7
Segment part 16.
+
Intra module refs +   ?PROLOGUE1_L09 +
?EPILOGUE_B_L09
Library module
+
CODE
Relative segment
CODE 000017F8 - 000017F9
Segment part 8.
+
?EPILOGUE_B8_L09 + + 000017F8 + BatteryDataRefresh (battery) +
CODE
Relative segment
CODE 000017FA - 000017FB
Segment part 9.
+
Intra module refs +   ?EPILOGUE_B8_L09 +
?EPILOGUE_B7_L09 + + 000017FA + Time_Set (time) +
CODE
Relative segment
CODE 000017FC - 000017FD
Segment part 10.
+
Intra module refs +   ?EPILOGUE_B7_L09 +
?EPILOGUE_B6_L09 + + 000017FC + ScaleI (ADC) +
ScaleU (ADC) +
CODE
Relative segment
CODE 000017FE - 000017FF
Segment part 11.
+
Intra module refs +   ?EPILOGUE_B6_L09 +
?EPILOGUE_B5_L09 + + 000017FE + - +
CODE
Relative segment
CODE 00001800 - 00001801
Segment part 12.
+
Intra module refs +   ?EPILOGUE_B5_L09 +
?EPILOGUE_B4_L09 + + 00001800 + BatteryCheck (battery) +
BatteryStatusRefresh (battery) +
ConstantCurrent (chargefunc) +
HaltNow (chargefunc) +
Initialize (statefunc) +
NTCLookUp (battery) +
OWI_SendByte (OWI) +
RIDLookUp (battery) +
CODE
Relative segment
CODE 00001802 - 00001803
Segment part 13.
+
Intra module refs +   ?EPILOGUE_B4_L09 +
?EPILOGUE_B3_L09 + + 00001802 + BatteryControl (statefunc) +
OWI_ReceiveByte (OWI) +
CODE
Relative segment
CODE 00001804 - 00001805
Segment part 14.
+
Intra module refs +   ?EPILOGUE_B3_L09 +
?EPILOGUE_B2_L09 + + 00001804 + Charge (NIMHcharge) +
Error (statefunc) +
Sleep (statefunc) +
CODE
Relative segment
CODE 00001806 - 00001807
Segment part 15.
+
Intra module refs +   ?EPILOGUE_B2_L09 +
?EPILOGUE_B1_L09 + + 00001806 + - +
CODE
Relative segment
CODE 00001808 - 00001815
Segment part 16.
+
Intra module refs +   ?EPILOGUE_B1_L09 +
?EPILOGUE_B0_L09 + + 00001808 + - +
?REGISTER_CGREGR4_L10
Library module
+
CODE
Relative segment
CODE 00001816
Segment part 0.
+
?Register_R4_is_cg_reg + + 00001816 + ADC_ISR (ADC) +
BatteryDataRefresh (battery) +
ScaleI (ADC) +
ScaleU (ADC) +
Time_Set (time) +
main (main) +
?REGISTER_CGREGR5_L10
Library module
+
CODE
Relative segment
CODE 00001816
Segment part 0.
+
?Register_R5_is_cg_reg + + 00001816 + ADC_ISR (ADC) +
BatteryDataRefresh (battery) +
ScaleI (ADC) +
ScaleU (ADC) +
Time_Set (time) +
main (main) +
?REGISTER_CGREGR6_L10
Library module
+
CODE
Relative segment
CODE 00001816
Segment part 0.
+
?Register_R6_is_cg_reg + + 00001816 + BatteryDataRefresh (battery) +
Time_Set (time) +
main (main) +
?REGISTER_CGREGR7_L10
Library module
+
CODE
Relative segment
CODE 00001816
Segment part 0.
+
?Register_R7_is_cg_reg + + 00001816 + BatteryDataRefresh (battery) +
?low_level_init
Library module
+
CODE
Relative segment
CODE 00001816 - 00001819
Segment part 3.
+
__low_level_init +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001816 + ?call_low_level_init (?C_STARTUP) +
?segment_init
Library module
+
CODE
Relative segment
CODE 0000181A - 00001821
Segment part 3.
+
Intra module refs +   __segment_init +
__memclr +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
0000181A +
CODE
Relative segment
CODE 00001822 - 00001829
Segment part 4.
+
Intra module refs +   __segment_init +
__flashcpy +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001822 +
CODE
Relative segment
CODE 0000182A - 00001835
Segment part 5.
+
Intra module refs +   __flashcpy +
__memclr +
CODE
Relative segment
CODE 00001836 - 00001869
Segment part 6.
+
__segment_init +
calls direct +
stack 1 = 00000000 ( 00000000 ) +
stack 2 = 00000000 ( 00000002 ) +
+
00001836 + ?need_segment_init (?C_STARTUP) +
+ ?FILLER_BYTES
Program module
+
INTVEC
Common segment
CODE 00000000 - 0000001D
Segment part 1.
+
?FILL1
Relative segment
CODE 0000001E - 00000025
Segment part 0.
+
+ + +


+

Module Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ModuleCODEDATAXDATA
 (Rel)(Rel)(Abs)(Rel)
?C_STARTUP26   
?EEPROM_1652   
?EPILOGUE_B_L0930   
?FILLER_BYTES
  + common
8
30
   
?L_MUL_L0350   
?PROLOGUE_L0918   
?RESET
  + common

2
   
?SS_DIVMOD_L0246   
?S_MUL_L0232   
?S_SHL_L0212   
?US_DIVMOD_L0240   
?US_SHR_L0212   
?__exit6   
?abs16   
?low_level_init4   
?segment_init80   
ADC
  + shared
  + common
946
6
24
254
3
1
NIMHcharge356   
OWI452 1 
PWM
  + shared
168 10
2
 
USI
  + shared
  + common
688
18
43
1
 
battery1 186129 130
chargefunc69022  
main2201  
menu30   
statefunc73424 
time
  + common
428
30
165 
N/A (command line) 112  
N/A (alignment)    
Total:
  + common
6 336
30
31133131
+


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Call Graph + +
Sub-tree of type: Interrupt function tree that does not make
indirect calls
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 0 + 0 + + +
2 +     ScaleI * + 0 + 0 + 6 + 4 +
2 +     ScaleI (to first) + 0 + 0 + 6 + 4 +
2 +     ScaleU * + 0 + 0 + 6 + 4 +
2 +     ScaleU (to first) + 0 + 0 + 6 + 4 +
1 +   ADC_ISR * + 6 + 4 + 14 + 2 +
After + 1A + 6 + + +
Sub-tree of type: Interrupt function tree that does not make
indirect calls
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 1A + 6 + + +
2 +     Time_Set * + 1A + 6 + 7 + 4 +
2 +     Time_Left * + 1A + 6 + 0 + 2 +
2 +     SPI_Put * + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
2 +     SPI_Put (to first) + 1A + 6 + 0 + 2 +
1 +   USI_OVF_ISR * + 21 + A + 11 + 2 +
After + 32 + C + + +
Sub-tree of type: Interrupt function tree that does not make
indirect calls
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 32 + C + + +
1 +   TICK_ISR * + 32 + C + B + 2 +
After + 3D + E + + +
Sub-tree of type: Indirectly called function tree that does not make
indirect calls (Is not an interrupt and is not flagged
as not overlayable)
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 3D + E + + +
2 +     Time_Set (to first) + 1A + 6 + 7 + 4 +
3 +       Time_Start * + 3D + E + 0 + 2 +
3 +       Time_Stop * + 3D + E + 0 + 2 +
3 +       SetErrorFlag * + 3D + E + 0 + 2 +
4 +         Time_Set (to first) + 1A + 6 + 7 + 4 +
4 +         Time_Left (to first) + 1A + 6 + 0 + 2 +
4 +         SetErrorFlag (to first) + 3D + E + 0 + 2 +
6 +             NTCLookUp * + 3D + E + 4 + 4 +
6 +             RIDLookUp * + 3D + E + 4 + 4 +
5 +           BatteryStatusRefresh * + 41 + 12 + 4 + 2 +
4 +         BatteryCheck * + 45 + 14 + 4 + 2 +
4 +         PWM_Stop * + 3D + E + 0 + 2 +
4 +         ADC_Wait * + 3D + E + 0 + 2 +
3 +       HaltNow * + 49 + 16 + 4 + 2 +
3 +       PWM_DecrementDutyCycle * + 3D + E + 0 + 2 +
3 +       PWM_IncrementDutyCycle * + 3D + E + 0 + 2 +
3 +       ADC_Wait (to first) + 3D + E + 0 + 2 +
2 +     ConstantCurrent * + 4D + 18 + 4 + 2 +
3 +       Time_Set (to first) + 1A + 6 + 7 + 4 +
3 +       Time_Left (to first) + 1A + 6 + 0 + 2 +
2 +     PWM_Start * + 3D + E + 0 + 2 +
2 +     PWM_Stop (to first) + 3D + E + 0 + 2 +
1 +   Charge * + 51 + 1A + 2 + 2 +
After + 53 + 1C + + +
Sub-tree of type: Indirectly called function tree that does not make
indirect calls (Is not an interrupt and is not flagged
as not overlayable)
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 3D + E + + +
2 +     Time_Init * + 3D + E + 0 + 2 +
2 +     DisableBatteries * + 3D + E + 0 + 2 +
3 +       Time_Set (to first) + 1A + 6 + 7 + 4 +
3 +       Time_Left (to first) + 1A + 6 + 0 + 2 +
2 +     EnableBattery * + 3D + E + 1 + 4 +
2 +     BatteryStatusRefresh (to first) + 41 + 12 + 4 + 2 +
2 +     SPI_Init * + 3D + E + 0 + 2 +
2 +     OWI_Init * + 3D + E + 0 + 2 +
3 +       ADC_Wait (to first) + 3D + E + 0 + 2 +
2 +     ADC_Init * + 3D + 10 + 1 + 2 +
2 +     ADC_Wait (to first) + 3D + E + 0 + 2 +
1 +   Initialize * + 45 + 14 + 4 + 2 +
After + 49 + 16 + + +
Sub-tree of type: Indirectly called function tree that does not make
indirect calls (Is not an interrupt and is not flagged
as not overlayable)
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 3D + E + + +
3 +       abs * + 3D + E + 0 + 2 +
3 +       Time_Set (to first) + 1A + 6 + 7 + 4 +
3 +       Time_Left (to first) + 1A + 6 + 0 + 2 +
3 +       DisableBatteries (to first) + 3D + E + 0 + 2 +
3 +       PWM_IncrementDutyCycle (to first) + 3D + E + 0 + 2 +
3 +       PWM_Start (to first) + 3D + E + 0 + 2 +
3 +       PWM_Stop (to first) + 3D + E + 0 + 2 +
3 +       ADC_Wait (to first) + 3D + E + 0 + 2 +
2 +     JumperCheck * + 3D + 10 + 0 + 2 +
2 +     SetErrorFlag (to first) + 3D + E + 0 + 2 +
2 +     DisableBatteries (to first) + 3D + E + 0 + 2 +
2 +     EnableBattery (to first) + 3D + E + 1 + 4 +
3 +       OWI_ComputeCRC8 * + 3D + E + 0 + 2 +
4 +         OWI_ReadBit * + 3D + E + 0 + 2 +
3 +       OWI_ReceiveByte * + 3D + 10 + 3 + 2 +
4 +         OWI_WriteBit0 * + 3D + E + 0 + 2 +
4 +         OWI_WriteBit1 * + 3D + E + 0 + 2 +
3 +       OWI_SendByte * + 3D + 10 + 4 + 2 +
3 +       OWI_DetectPresence * + 3D + E + 0 + 2 +
2 +     BatteryDataRefresh * + 41 + 12 + 8 + 2 +
2 +     BatteryStatusRefresh (to first) + 41 + 12 + 4 + 2 +
2 +     ADC_Wait (to first) + 3D + E + 0 + 2 +
1 +   BatteryControl * + 49 + 14 + 3 + 2 +
After + 4C + 16 + + +
Sub-tree of type: Indirectly called function tree that does not make
indirect calls (Is not an interrupt and is not flagged
as not overlayable)
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 3D + E + + +
1 +   Discharge * + 3D + E + 0 + 2 +
After + 3D + 10 + + +
Sub-tree of type: Indirectly called function tree that does not make
indirect calls (Is not an interrupt and is not flagged
as not overlayable)
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 3D + E + + +
3 +       ADC_Wait (to first) + 3D + E + 0 + 2 +
2 +     Doze * + 3D + 10 + 0 + 2 +
2 +     DisableBatteries (to first) + 3D + E + 0 + 2 +
2 +     EnableBattery (to first) + 3D + E + 1 + 4 +
2 +     BatteryStatusRefresh (to first) + 41 + 12 + 4 + 2 +
2 +     ADC_Wait (to first) + 3D + E + 0 + 2 +
1 +   Sleep * + 45 + 14 + 2 + 2 +
After + 47 + 16 + + +
Sub-tree of type: Indirectly called function tree that does not make
indirect calls (Is not an interrupt and is not flagged
as not overlayable)
+
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 3D + E + + +
2 +     JumperCheck (to first) + 3D + 10 + 0 + 2 +
2 +     Doze (to first) + 3D + 10 + 0 + 2 +
2 +     DisableBatteries (to first) + 3D + E + 0 + 2 +
2 +     PWM_Stop (to first) + 3D + E + 0 + 2 +
1 +   Error * + 3D + 12 + 2 + 2 +
After + 3F + 14 + + +
Sub-tree of type: Function tree that makes indirect calls +
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 53 + 1C + + +
1 +   main * + 53 + 1C + 7 + 4 +
After + 5A + 20 + + +
Sub-tree of type: Function tree +
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 5A + 20 + + +
1 +   __low_level_init * + 5A + 20 + 0 + 2 +
After + 5A + 22 + + +
Sub-tree of type: Function tree +
Level + Function + Stack prev + Stack locally +
CSTACK + RSTACK + CSTACK + RSTACK +
Before + 5A + 22 + + +
2 +     __flashcpy * + 5A + 22 + 0 + 2 +
2 +     __memclr * + 5A + 22 + 0 + 2 +
1 +   __segment_init * + 5A + 24 + 0 + 2 +
After + 5A + 26 + + +
+


+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Segments in Address Order + +
Segment + Space + Start + End + Size + Kind + Align +
INTVEC + CODE + 00000000 - 0000001D + 1E + Common + 1 +
?FILL1 + CODE + 0000001E - 00000025 + 8 + Relative + 0 +
NEAR_F + CODE + 00000026 - 00000043 + 1E + Relative + 0 +
INITTAB + CODE + 00000044 - 0000004F + C + Relative + 0 +
CODE + CODE + 00000050 - 00001869 + 181A + Relative + 1 +
NEAR_ID + CODE + 0000186A - 000018DD + 74 + Relative + 0 +
ABSOLUTE + DATA + 0000001C + + Relative + 0 +
0000001D + +
0000001E + +
0000001F + +
00000020 - 00000020 + 1 +
00000023 - 00000027 + 5 +
0000002D - 0000002F + 3 +
00000032 - 00000033 + 2 +
00000035 - 00000035 + 1 +
00000037 - 0000003B + 5 +
00000041 - 00000041 + 1 +
00000044 - 00000044 + 1 +
00000046 - 0000004D + 8 +
0000004F - 00000050 + 2 +
00000053 - 00000055 + 3 +
00000059 - 00000059 + 1 +
CSTACK + DATA + 00000060 - 0000009F + 40 + Predefined + 0 +
RSTACK + DATA + 000000A0 - 000000CF + 30 + Predefined + 0 +
NEAR_I + DATA + 000000D0 - 00000143 + 74 + Relative + 0 +
NEAR_Z + DATA + 00000144 - 00000196 + 53 + Relative + 0 +
EEPROM_I + XDATA + 00000000 - 00000082 + 83 + Relative + 0 +
+ +


+ +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
6 358bytesofCODEmemory(+  8range fill)
311bytesofDATAmemory(+33absolute)
131bytesofXDATAmemory
+ +Errors: none +Warnings: none + diff --git a/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.lst b/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.lst new file mode 100644 index 0000000..6ff75c9 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.lst @@ -0,0 +1,414 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\NIMHcharg # +# e.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\NIMHcharge # +# .r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Charge state function for NiMH batteries + 6 * + 7 * Contains the charge state function, in which the NiMH charging + 8 * algorithm is, plus the associated functions. + 9 * + 10 * \par Application note: + 11 * AVR463: Charging NiMH Batteries with BC100 \n + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2255 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $ + 26 * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 #include + 30 + 31 #include "enums.h" + 32 #include "structs.h" + 33 + 34 #include "battery.h" + 35 #include "charge.h" + 36 #include "chargefunc.h" + 37 #include "main.h" + 38 #include "menu.h" + 39 #include "NIMHspecs.h" + 40 #include "PWM.h" + 41 #include "time.h" + 42 + 43 #ifndef NIMH + 44 #error NIMH not defined in main.h! + 45 #endif // NIMH + 46 + 47 + 48 //****************************************************************************** + 49 // Functions + 50 //****************************************************************************** + 51 /*! \brief Controls the charging. + 52 * + 53 * This function contains the charging algorithm itself, divided into stages.\n + 54 * For each stage the PWM may be started/stopped, and the timer, + 55 * halt-requirements and charge parameters may be set.\n + 56 * The charging functions return whatever state is next, and as long as no + 57 * errors occur this is the next charging stage. + 58 * + 59 * \note If more stages are needed simply define more states in menu.h, include + 60 * them in \ref menu_state[] in menu.c, then add the cases to this function. + 61 * + 62 * \note This algorithm is for NiMH batteries. + 63 */ + + \ In segment CODE, align 2, keep-with-next + 64 unsigned char Charge(unsigned char inp) + \ Charge: + 65 { + \ 00000000 .... RCALL ?PROLOGUE2_L09 + \ 00000002 2F90 MOV R25, R16 + 66 unsigned char NextState; + 67 + 68 switch (CurrentState) { + \ 00000004 9100.... LDS R16, CurrentState + \ 00000008 510E SUBI R16, 30 + \ 0000000A F049 BREQ ??Charge_0 + \ 0000000C 5104 SUBI R16, 20 + \ 0000000E F1D1 BREQ ??Charge_1 + \ 00000010 500A SUBI R16, 10 + \ 00000012 F409 BRNE $+2+2 + \ 00000014 C06E RJMP ??Charge_2 + \ 00000016 500A SUBI R16, 10 + \ 00000018 F409 BRNE $+2+2 + \ 0000001A C085 RJMP ??Charge_3 + \ 0000001C C09F RJMP ??Charge_4 + 69 // First stage is a prequalification. Attempt to charge battery to 1 V, + 70 // using a 0.1 C current, within 2 minutes. + 71 // If this fails, the battery is likely damaged. + 72 // If it succeeds, start a fast charge. + 73 case ST_PREQUAL: + 74 + 75 // Set up charge current and next state. + 76 ChargeParameters.Current = BattData.Capacity / 10; + \ ??Charge_0: + \ 0000001E .... LDI R30, LOW(BattData) + \ 00000020 .... LDI R31, (BattData) >> 8 + \ 00000022 8104 LDD R16, Z+4 + \ 00000024 8115 LDD R17, Z+5 + \ 00000026 E04A LDI R20, 10 + \ 00000028 E050 LDI R21, 0 + \ 0000002A .... RCALL ?US_DIVMOD_L02 + \ 0000002C .... LDI R30, LOW(ChargeParameters) + \ 0000002E .... LDI R31, (ChargeParameters) >> 8 + \ 00000030 8302 STD Z+2, R16 + \ 00000032 8313 STD Z+3, R17 + 77 ChargeParameters.NextState = ST_FASTCHARGE; + \ 00000034 E302 LDI R16, 50 + \ 00000036 9300.... STS (ChargeParameters + 4), R16 + 78 + 79 // Halt charge on voltage limit or timeout. + 80 // Timeout means battery exhaustion. + 81 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + 82 HALT_FLAG_EXHAUSTION); + \ 0000003A E302 LDI R16, 50 + \ 0000003C 9300.... STS HaltParameters, R16 + 83 + 84 // Set up voltage limit and temperature limits. + 85 HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + \ 00000040 EB08 LDI R16, 184 + \ 00000042 E01B LDI R17, 11 + \ 00000044 .... LDI R30, LOW(HaltParameters) + \ 00000046 .... LDI R31, (HaltParameters) >> 8 + \ 00000048 8303 STD Z+3, R16 + \ 0000004A 8314 STD Z+4, R17 + 86 HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + \ 0000004C E005 LDI R16, 5 + \ 0000004E E010 LDI R17, 0 + \ 00000050 .... LDI R30, LOW(HaltParameters) + \ 00000052 .... LDI R31, (HaltParameters) >> 8 + \ 00000054 8701 STD Z+9, R16 + \ 00000056 8712 STD Z+10, R17 + 87 HaltParameters.TemperatureMax = 35; + \ 00000058 E203 LDI R16, 35 + \ 0000005A E010 LDI R17, 0 + \ 0000005C .... LDI R30, LOW(HaltParameters) + \ 0000005E .... LDI R31, (HaltParameters) >> 8 + \ 00000060 8307 STD Z+7, R16 + \ 00000062 8710 STD Z+8, R17 + 88 + 89 // Reset temperature measurement for HaltNow(). + 90 HaltParameters.LastNTC = 0; + \ 00000064 E000 LDI R16, 0 + \ 00000066 E010 LDI R17, 0 + \ 00000068 .... LDI R30, LOW(HaltParameters) + \ 0000006A .... LDI R31, (HaltParameters) >> 8 + \ 0000006C 8707 STD Z+15, R16 + \ 0000006E 8B10 STD Z+16, R17 + 91 + 92 // Start PWM and charge timer before calling the charge function. + 93 PWM_Start(); + \ 00000070 .... RCALL PWM_Start + 94 Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + \ 00000072 E040 LDI R20, 0 + \ 00000074 E010 LDI R17, 0 + \ 00000076 E022 LDI R18, 2 + \ 00000078 E030 LDI R19, 0 + \ 0000007A E001 LDI R16, 1 + \ 0000007C .... RCALL Time_Set + 95 + 96 // Call charge function, get next state. + 97 NextState = ConstantCurrent(); + \ 0000007E .... RCALL ConstantCurrent + \ 00000080 2F80 MOV R24, R16 + \ 00000082 C06D RJMP ??Charge_5 + 98 break; + 99 + 100 + 101 // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours, + 102 // until either rate of temperature increase or voltage reaches limit, or + 103 // the voltage drops sufficiently. + 104 // Timeout doesn't mean battery exhaustion now. + 105 case ST_FASTCHARGE: + 106 + 107 // Set up charge current and next state. + 108 ChargeParameters.Current = BattData.Capacity; + \ ??Charge_1: + \ 00000084 .... LDI R30, LOW(BattData) + \ 00000086 .... LDI R31, (BattData) >> 8 + \ 00000088 8104 LDD R16, Z+4 + \ 0000008A 8115 LDD R17, Z+5 + \ 0000008C .... LDI R30, LOW(ChargeParameters) + \ 0000008E .... LDI R31, (ChargeParameters) >> 8 + \ 00000090 8302 STD Z+2, R16 + \ 00000092 8313 STD Z+3, R17 + 109 ChargeParameters.NextState = ST_LOWRATECHARGE; + \ 00000094 E30C LDI R16, 60 + \ 00000096 9300.... STS (ChargeParameters + 4), R16 + 110 + 111 // Halt charge on voltage limit, timeout, voltage drop or rate of + 112 // temperature increase. + 113 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + 114 HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE); + \ 0000009A E10B LDI R16, 27 + \ 0000009C 9300.... STS HaltParameters, R16 + 115 + 116 // Set up limits for voltage, voltage drop, temperature and rate of + 117 // temperature increase (1 degree C per minute). + 118 HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + \ 000000A0 EC00 LDI R16, 192 + \ 000000A2 E112 LDI R17, 18 + \ 000000A4 .... LDI R30, LOW(HaltParameters) + \ 000000A6 .... LDI R31, (HaltParameters) >> 8 + \ 000000A8 8303 STD Z+3, R16 + \ 000000AA 8314 STD Z+4, R17 + 119 HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP; + \ 000000AC E20D LDI R16, 45 + \ 000000AE E010 LDI R17, 0 + \ 000000B0 .... LDI R30, LOW(HaltParameters) + \ 000000B2 .... LDI R31, (HaltParameters) >> 8 + \ 000000B4 8301 STD Z+1, R16 + \ 000000B6 8312 STD Z+2, R17 + 120 HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + \ 000000B8 E302 LDI R16, 50 + \ 000000BA E010 LDI R17, 0 + \ 000000BC .... LDI R30, LOW(HaltParameters) + \ 000000BE .... LDI R31, (HaltParameters) >> 8 + \ 000000C0 8307 STD Z+7, R16 + \ 000000C2 8710 STD Z+8, R17 + 121 HaltParameters.TemperatureRise = 1; + \ 000000C4 E001 LDI R16, 1 + \ 000000C6 E010 LDI R17, 0 + \ 000000C8 .... LDI R30, LOW(HaltParameters) + \ 000000CA .... LDI R31, (HaltParameters) >> 8 + \ 000000CC 8703 STD Z+11, R16 + \ 000000CE 8714 STD Z+12, R17 + 122 + 123 // Reset maximum voltage measurement for HaltNow(). + 124 HaltParameters.VBATMax = 0; + \ 000000D0 E000 LDI R16, 0 + \ 000000D2 E010 LDI R17, 0 + \ 000000D4 .... LDI R30, LOW(HaltParameters) + \ 000000D6 .... LDI R31, (HaltParameters) >> 8 + \ 000000D8 8705 STD Z+13, R16 + \ 000000DA 8716 STD Z+14, R17 + 125 + 126 // Start timer, PWM should still be running. + 127 Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0); + \ 000000DC E040 LDI R20, 0 + \ 000000DE E010 LDI R17, 0 + \ 000000E0 .... LDI R30, LOW(BattData) + \ 000000E2 .... LDI R31, (BattData) >> 8 + \ 000000E4 8520 LDD R18, Z+8 + \ 000000E6 8531 LDD R19, Z+9 + \ 000000E8 E001 LDI R16, 1 + \ 000000EA .... RCALL Time_Set + 128 + 129 // Call charge function, get next state. + 130 NextState = ConstantCurrent(); + \ 000000EC .... RCALL ConstantCurrent + \ 000000EE 2F80 MOV R24, R16 + \ 000000F0 C036 RJMP ??Charge_5 + 131 break; + 132 + 133 + 134 // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes, + 135 // until either rate of temperature increase or voltage reaches limit. + 136 case ST_LOWRATECHARGE: + 137 + 138 // Set up charge current and next state. + 139 ChargeParameters.Current = BattData.Capacity / 10; + \ ??Charge_2: + \ 000000F2 .... LDI R30, LOW(BattData) + \ 000000F4 .... LDI R31, (BattData) >> 8 + \ 000000F6 8104 LDD R16, Z+4 + \ 000000F8 8115 LDD R17, Z+5 + \ 000000FA E04A LDI R20, 10 + \ 000000FC E050 LDI R21, 0 + \ 000000FE .... RCALL ?US_DIVMOD_L02 + \ 00000100 .... LDI R30, LOW(ChargeParameters) + \ 00000102 .... LDI R31, (ChargeParameters) >> 8 + \ 00000104 8302 STD Z+2, R16 + \ 00000106 8313 STD Z+3, R17 + 140 ChargeParameters.NextState = ST_ENDCHARGE; + \ 00000108 E406 LDI R16, 70 + \ 0000010A 9300.... STS (ChargeParameters + 4), R16 + 141 + 142 // Halt charge on voltage limit, timeout or temperature rise. + 143 // Use the same requirements as during the last stage (ST_FASTCHARGE). + 144 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + 145 HALT_TEMPERATURE_RISE); + \ 0000010E E10A LDI R16, 26 + \ 00000110 9300.... STS HaltParameters, R16 + 146 + 147 // Start timer, 30 minutes. + 148 Time_Set(TIMER_CHG, 30, 0, 0); + \ 00000114 E040 LDI R20, 0 + \ 00000116 E010 LDI R17, 0 + \ 00000118 E12E LDI R18, 30 + \ 0000011A E030 LDI R19, 0 + \ 0000011C E001 LDI R16, 1 + \ 0000011E .... RCALL Time_Set + 149 + 150 // Call charge function, get next state. + 151 NextState = ConstantCurrent(); + \ 00000120 .... RCALL ConstantCurrent + \ 00000122 2F80 MOV R24, R16 + \ 00000124 C01C RJMP ??Charge_5 + 152 break; + 153 + 154 + 155 // Charging is done! + 156 case ST_ENDCHARGE: + 157 + 158 // Stop the PWM output and flag battery as charged. + 159 PWM_Stop(); + \ ??Charge_3: + \ 00000126 .... RCALL PWM_Stop + 160 BattData.Charged = TRUE; + \ 00000128 .... LDI R30, LOW(BattData) + \ 0000012A .... LDI R31, (BattData) >> 8 + \ 0000012C 8100 LD R16, Z + \ 0000012E 6002 ORI R16, 0x02 + \ 00000130 8300 ST Z, R16 + 161 + 162 // If the other battery is enabled go to ST_BATCON, otherwise + 163 // go to ST_SLEEP. + 164 if (BattControl[(BattActive+1)%2].Enabled) { + \ 00000132 9100.... LDS R16, BattActive + \ 00000136 E010 LDI R17, 0 + \ 00000138 5F0F SUBI R16, 255 + \ 0000013A 4F1F SBCI R17, 255 + \ 0000013C E042 LDI R20, 2 + \ 0000013E E050 LDI R21, 0 + \ 00000140 .... RCALL ?SS_DIVMOD_L02 + \ 00000142 .... LDI R18, LOW(BattControl) + \ 00000144 .... LDI R19, (BattControl) >> 8 + \ 00000146 0F24 ADD R18, R20 + \ 00000148 1F35 ADC R19, R21 + \ 0000014A 01A9 MOVW R21:R20, R19:R18 + \ 0000014C .... RCALL __eeget8_16 + \ 0000014E 7001 ANDI R16, 0x01 + \ 00000150 2300 TST R16 + \ 00000152 F011 BREQ ??Charge_6 + 165 NextState = ST_BATCON; + \ 00000154 E184 LDI R24, 20 + \ 00000156 C003 RJMP ??Charge_5 + 166 } else { + 167 NextState = ST_SLEEP; + \ ??Charge_6: + \ 00000158 E288 LDI R24, 40 + \ 0000015A C001 RJMP ??Charge_5 + 168 } + 169 break; + 170 + 171 + 172 default: // Shouldn't end up here. Reinitialize for safety. + 173 NextState = ST_INIT; + \ ??Charge_4: + \ 0000015C E08A LDI R24, 10 + 174 break; + 175 } + 176 + 177 // Return the next state to main(). + 178 return(NextState); + \ ??Charge_5: + \ 0000015E 2F08 MOV R16, R24 + \ 00000160 E0E2 LDI R30, 2 + \ 00000162 .... RJMP ?EPILOGUE_B2_L09 + 179 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + Charge 2 4 + -> PWM_Start 2 2 + -> Time_Set 2 2 + -> ConstantCurrent 2 2 + -> Time_Set 2 2 + -> ConstantCurrent 2 2 + -> Time_Set 2 2 + -> ConstantCurrent 2 2 + -> PWM_Stop 2 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + Charge 356 + + + 356 bytes in segment CODE + + 356 bytes of CODE memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.s90 b/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.s90 new file mode 100644 index 0000000..e421005 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/NIMHcharge.s90 @@ -0,0 +1,433 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\NIMHchar / +// ge.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME NIMHcharge + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?EPILOGUE_B2_L09 + EXTERN ?PROLOGUE2_L09 + EXTERN ?SS_DIVMOD_L02 + EXTERN ?US_DIVMOD_L02 + EXTERN __eeget8_16 + + PUBLIC Charge + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN PWM_Start + EXTERN Time_Set + EXTERN ConstantCurrent + EXTERN PWM_Stop + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + EXTERN ChargeParameters + EXTERN CurrentState + EXTERN HaltParameters + +// C:\home\kevin\pub\src\bc100_cal\IAR\NIMHcharge.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Charge state function for NiMH batteries +// 6 * +// 7 * Contains the charge state function, in which the NiMH charging +// 8 * algorithm is, plus the associated functions. +// 9 * +// 10 * \par Application note: +// 11 * AVR463: Charging NiMH Batteries with BC100 \n +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2255 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $ +// 26 * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 #include +// 30 +// 31 #include "enums.h" +// 32 #include "structs.h" +// 33 +// 34 #include "battery.h" +// 35 #include "charge.h" +// 36 #include "chargefunc.h" +// 37 #include "main.h" +// 38 #include "menu.h" +// 39 #include "NIMHspecs.h" +// 40 #include "PWM.h" +// 41 #include "time.h" +// 42 +// 43 #ifndef NIMH +// 44 #error NIMH not defined in main.h! +// 45 #endif // NIMH +// 46 +// 47 +// 48 //****************************************************************************** +// 49 // Functions +// 50 //****************************************************************************** +// 51 /*! \brief Controls the charging. +// 52 * +// 53 * This function contains the charging algorithm itself, divided into stages.\n +// 54 * For each stage the PWM may be started/stopped, and the timer, +// 55 * halt-requirements and charge parameters may be set.\n +// 56 * The charging functions return whatever state is next, and as long as no +// 57 * errors occur this is the next charging stage. +// 58 * +// 59 * \note If more stages are needed simply define more states in menu.h, include +// 60 * them in \ref menu_state[] in menu.c, then add the cases to this function. +// 61 * +// 62 * \note This algorithm is for NiMH batteries. +// 63 */ + + RSEG CODE:CODE:NOROOT(1) +// 64 unsigned char Charge(unsigned char inp) +Charge: +// 65 { + RCALL ?PROLOGUE2_L09 + MOV R25, R16 +// 66 unsigned char NextState; +// 67 +// 68 switch (CurrentState) { + LDS R16, CurrentState + SUBI R16, 30 + BREQ ??Charge_0 + SUBI R16, 20 + BREQ ??Charge_1 + SUBI R16, 10 + BRNE $+2+2 + RJMP ??Charge_2 + SUBI R16, 10 + BRNE $+2+2 + RJMP ??Charge_3 + RJMP ??Charge_4 +// 69 // First stage is a prequalification. Attempt to charge battery to 1 V, +// 70 // using a 0.1 C current, within 2 minutes. +// 71 // If this fails, the battery is likely damaged. +// 72 // If it succeeds, start a fast charge. +// 73 case ST_PREQUAL: +// 74 +// 75 // Set up charge current and next state. +// 76 ChargeParameters.Current = BattData.Capacity / 10; +??Charge_0: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R20, 10 + LDI R21, 0 + RCALL ?US_DIVMOD_L02 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 77 ChargeParameters.NextState = ST_FASTCHARGE; + LDI R16, 50 + STS (ChargeParameters + 4), R16 +// 78 +// 79 // Halt charge on voltage limit or timeout. +// 80 // Timeout means battery exhaustion. +// 81 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | +// 82 HALT_FLAG_EXHAUSTION); + LDI R16, 50 + STS HaltParameters, R16 +// 83 +// 84 // Set up voltage limit and temperature limits. +// 85 HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + LDI R16, 184 + LDI R17, 11 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+3, R16 + STD Z+4, R17 +// 86 HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + LDI R16, 5 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+9, R16 + STD Z+10, R17 +// 87 HaltParameters.TemperatureMax = 35; + LDI R16, 35 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+7, R16 + STD Z+8, R17 +// 88 +// 89 // Reset temperature measurement for HaltNow(). +// 90 HaltParameters.LastNTC = 0; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+15, R16 + STD Z+16, R17 +// 91 +// 92 // Start PWM and charge timer before calling the charge function. +// 93 PWM_Start(); + RCALL PWM_Start +// 94 Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + LDI R20, 0 + LDI R17, 0 + LDI R18, 2 + LDI R19, 0 + LDI R16, 1 + RCALL Time_Set +// 95 +// 96 // Call charge function, get next state. +// 97 NextState = ConstantCurrent(); + RCALL ConstantCurrent + MOV R24, R16 + RJMP ??Charge_5 +// 98 break; +// 99 +// 100 +// 101 // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours, +// 102 // until either rate of temperature increase or voltage reaches limit, or +// 103 // the voltage drops sufficiently. +// 104 // Timeout doesn't mean battery exhaustion now. +// 105 case ST_FASTCHARGE: +// 106 +// 107 // Set up charge current and next state. +// 108 ChargeParameters.Current = BattData.Capacity; +??Charge_1: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 109 ChargeParameters.NextState = ST_LOWRATECHARGE; + LDI R16, 60 + STS (ChargeParameters + 4), R16 +// 110 +// 111 // Halt charge on voltage limit, timeout, voltage drop or rate of +// 112 // temperature increase. +// 113 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | +// 114 HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE); + LDI R16, 27 + STS HaltParameters, R16 +// 115 +// 116 // Set up limits for voltage, voltage drop, temperature and rate of +// 117 // temperature increase (1 degree C per minute). +// 118 HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + LDI R16, 192 + LDI R17, 18 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+3, R16 + STD Z+4, R17 +// 119 HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP; + LDI R16, 45 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+1, R16 + STD Z+2, R17 +// 120 HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + LDI R16, 50 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+7, R16 + STD Z+8, R17 +// 121 HaltParameters.TemperatureRise = 1; + LDI R16, 1 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+11, R16 + STD Z+12, R17 +// 122 +// 123 // Reset maximum voltage measurement for HaltNow(). +// 124 HaltParameters.VBATMax = 0; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+13, R16 + STD Z+14, R17 +// 125 +// 126 // Start timer, PWM should still be running. +// 127 Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0); + LDI R20, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R18, Z+8 + LDD R19, Z+9 + LDI R16, 1 + RCALL Time_Set +// 128 +// 129 // Call charge function, get next state. +// 130 NextState = ConstantCurrent(); + RCALL ConstantCurrent + MOV R24, R16 + RJMP ??Charge_5 +// 131 break; +// 132 +// 133 +// 134 // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes, +// 135 // until either rate of temperature increase or voltage reaches limit. +// 136 case ST_LOWRATECHARGE: +// 137 +// 138 // Set up charge current and next state. +// 139 ChargeParameters.Current = BattData.Capacity / 10; +??Charge_2: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R20, 10 + LDI R21, 0 + RCALL ?US_DIVMOD_L02 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 140 ChargeParameters.NextState = ST_ENDCHARGE; + LDI R16, 70 + STS (ChargeParameters + 4), R16 +// 141 +// 142 // Halt charge on voltage limit, timeout or temperature rise. +// 143 // Use the same requirements as during the last stage (ST_FASTCHARGE). +// 144 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | +// 145 HALT_TEMPERATURE_RISE); + LDI R16, 26 + STS HaltParameters, R16 +// 146 +// 147 // Start timer, 30 minutes. +// 148 Time_Set(TIMER_CHG, 30, 0, 0); + LDI R20, 0 + LDI R17, 0 + LDI R18, 30 + LDI R19, 0 + LDI R16, 1 + RCALL Time_Set +// 149 +// 150 // Call charge function, get next state. +// 151 NextState = ConstantCurrent(); + RCALL ConstantCurrent + MOV R24, R16 + RJMP ??Charge_5 +// 152 break; +// 153 +// 154 +// 155 // Charging is done! +// 156 case ST_ENDCHARGE: +// 157 +// 158 // Stop the PWM output and flag battery as charged. +// 159 PWM_Stop(); +??Charge_3: + RCALL PWM_Stop +// 160 BattData.Charged = TRUE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ORI R16, 0x02 + ST Z, R16 +// 161 +// 162 // If the other battery is enabled go to ST_BATCON, otherwise +// 163 // go to ST_SLEEP. +// 164 if (BattControl[(BattActive+1)%2].Enabled) { + LDS R16, BattActive + LDI R17, 0 + SUBI R16, 255 + SBCI R17, 255 + LDI R20, 2 + LDI R21, 0 + RCALL ?SS_DIVMOD_L02 + LDI R18, LOW(BattControl) + LDI R19, (BattControl) >> 8 + ADD R18, R20 + ADC R19, R21 + MOVW R21:R20, R19:R18 + RCALL __eeget8_16 + ANDI R16, 0x01 + TST R16 + BREQ ??Charge_6 +// 165 NextState = ST_BATCON; + LDI R24, 20 + RJMP ??Charge_5 +// 166 } else { +// 167 NextState = ST_SLEEP; +??Charge_6: + LDI R24, 40 + RJMP ??Charge_5 +// 168 } +// 169 break; +// 170 +// 171 +// 172 default: // Shouldn't end up here. Reinitialize for safety. +// 173 NextState = ST_INIT; +??Charge_4: + LDI R24, 10 +// 174 break; +// 175 } +// 176 +// 177 // Return the next state to main(). +// 178 return(NextState); +??Charge_5: + MOV R16, R24 + LDI R30, 2 + RJMP ?EPILOGUE_B2_L09 +// 179 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// +// 356 bytes in segment CODE +// +// 356 bytes of CODE memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/OWI.lst b/BaseTinyFirmware/IAR/Debug/List/OWI.lst new file mode 100644 index 0000000..7711e61 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/OWI.lst @@ -0,0 +1,1124 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c --cpu=tiny861 # +# -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ # +# -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB # +# C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ # +# --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\OWI.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\OWI.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ******************************************************************** + 3 * + 4 * \brief + 5 * Functions for 1-Wire(R) bus communication + 6 * + 7 * High level functions for transmission of full bytes on the 1-Wire(R) + 8 * bus and implementations of ROM commands.\n + 9 * Polled software only implementation of the basic bit-level signalling + 10 * in the 1-Wire(R) protocol.\n + 11 * Includes functions for computing and checking CRC8 & 16 values of data + 12 * sets, and of 64 bit ROM identifiers. + 13 * Supported devices: All AVRs. + 14 * + 15 * \par Application Note: + 16 * AVR458: Charging Li-Ion Batteries with BC100\n + 17 * AVR463: Charging NiMH Batteries with BC100\n + 18 * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. + 19 * + 20 * \par Documentation: + 21 * For comprehensive code documentation, supported compilers, compiler + 22 * settings and supported devices see readme.html + 23 * + 24 * \author + 25 * Atmel Corporation: http://www.atmel.com \n + 26 * Support email: avr@atmel.com \n + 27 * Original author: \n + 28 * + 29 * $Name$ + 30 * $Revision: 2299 $ + 31 * $RCSfile$ + 32 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ + 33 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 34 ****************************************************************************/ + 35 + 36 #include + + \ In segment ABSOLUTE, at 0x3b + \ volatile __io _A_PORTA + \ _A_PORTA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x3a + \ volatile __io _A_DDRA + \ _A_DDRA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x39 + \ volatile __io _A_PINA + \ _A_PINA: + \ 00000000 DS 1 + 37 #include + 38 + 39 #include "OWI.h" + 40 + 41 + 42 //****************************************************************************** + 43 // Functions + 44 //****************************************************************************** + 45 /*! \brief Initialization of the one wire bus(es). (Software only driver) + 46 * + 47 * This function initializes the 1-Wire bus(es) by releasing it and + 48 * waiting until any presence signals are finished. + 49 * + 50 * \param pins A bitmask of the buses to initialize. + 51 */ + + \ In segment CODE, align 2, keep-with-next + 52 void OWI_Init(unsigned char pins){ + \ OWI_Init: + 53 OWI_RELEASE_BUS(pins); + \ 00000000 2F10 MOV R17, R16 + \ 00000002 9510 COM R17 + \ 00000004 B32A IN R18, 0x1A + \ 00000006 2321 AND R18, R17 + \ 00000008 BB2A OUT 0x1A, R18 + \ 0000000A 2F10 MOV R17, R16 + \ 0000000C 9510 COM R17 + \ 0000000E B32B IN R18, 0x1B + \ 00000010 2321 AND R18, R17 + \ 00000012 BB2B OUT 0x1B, R18 + 54 // The first rising edge can be interpreted by a slave as the end of a + 55 // Reset-pulse. Delay for the required reset recovery time (H) to be + 56 // sure that the real reset is interpreted correctly. + 57 __delay_cycles(OWI_DELAY_H_STD_MODE); + \ 00000014 EB2C LDI R18, 188 + \ 00000016 E033 LDI R19, 3 + \ 00000018 5021 SUBI R18, 1 + \ 0000001A 4030 SBCI R19, 0 + \ 0000001C F7E9 BRNE $-4 + \ 0000001E C000 RJMP $+2 + 58 } + \ 00000020 9508 RET + \ 00000022 REQUIRE _A_PORTA + \ 00000022 REQUIRE _A_DDRA + 59 + 60 + 61 /*! \brief Write a '1' bit to the bus(es). (Software only driver) + 62 * + 63 * Generates the waveform for transmission of a '1' bit on the 1-Wire + 64 * bus. + 65 * + 66 * \param pins A bitmask of the buses to write to. + 67 */ + + \ In segment CODE, align 2, keep-with-next + 68 void OWI_WriteBit1(unsigned char pins){ + \ OWI_WriteBit1: + 69 unsigned char intState; + 70 + 71 // Disable interrupts. + 72 intState = __save_interrupt(); + \ 00000000 B72F IN R18, 0x3F + \ 00000002 2F12 MOV R17, R18 + 73 __disable_interrupt(); + \ 00000004 94F8 CLI + 74 + 75 // Drive bus low and delay. + 76 OWI_PULL_BUS_LOW(pins); + \ 00000006 B32A IN R18, 0x1A + \ 00000008 2B20 OR R18, R16 + \ 0000000A BB2A OUT 0x1A, R18 + \ 0000000C 2F20 MOV R18, R16 + \ 0000000E 9520 COM R18 + \ 00000010 B33B IN R19, 0x1B + \ 00000012 2332 AND R19, R18 + \ 00000014 BB3B OUT 0x1B, R19 + 77 __delay_cycles(OWI_DELAY_A_STD_MODE); + \ 00000016 E02B LDI R18, 11 + \ 00000018 952A DEC R18 + \ 0000001A F7F1 BRNE $-2 + \ 0000001C C000 RJMP $+2 + 78 + 79 // Release bus and delay. + 80 OWI_RELEASE_BUS(pins); + \ 0000001E 2F20 MOV R18, R16 + \ 00000020 9520 COM R18 + \ 00000022 B33A IN R19, 0x1A + \ 00000024 2332 AND R19, R18 + \ 00000026 BB3A OUT 0x1A, R19 + \ 00000028 2F20 MOV R18, R16 + \ 0000002A 9520 COM R18 + \ 0000002C B33B IN R19, 0x1B + \ 0000002E 2332 AND R19, R18 + \ 00000030 BB3B OUT 0x1B, R19 + 81 __delay_cycles(OWI_DELAY_B_STD_MODE); + \ 00000032 EA26 LDI R18, 166 + \ 00000034 952A DEC R18 + \ 00000036 F7F1 BRNE $-2 + \ 00000038 0000 NOP + 82 + 83 // Restore interrupts. + 84 __restore_interrupt(intState); + \ 0000003A BF1F OUT 0x3F, R17 + 85 } + \ 0000003C 9508 RET + \ 0000003E REQUIRE _A_PORTA + \ 0000003E REQUIRE _A_DDRA + 86 + 87 /*! \brief Write a '0' to the bus(es). (Software only driver) + 88 * + 89 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) + 90 * bus. + 91 * + 92 * \param pins A bitmask of the buses to write to. + 93 */ + + \ In segment CODE, align 2, keep-with-next + 94 void OWI_WriteBit0(unsigned char pins) + \ OWI_WriteBit0: + 95 { + 96 unsigned char intState; + 97 + 98 // Disable interrupts. + 99 intState = __save_interrupt(); + \ 00000000 B72F IN R18, 0x3F + \ 00000002 2F12 MOV R17, R18 + 100 __disable_interrupt(); + \ 00000004 94F8 CLI + 101 + 102 // Drive bus low and delay. + 103 OWI_PULL_BUS_LOW(pins); + \ 00000006 B32A IN R18, 0x1A + \ 00000008 2B20 OR R18, R16 + \ 0000000A BB2A OUT 0x1A, R18 + \ 0000000C 2F20 MOV R18, R16 + \ 0000000E 9520 COM R18 + \ 00000010 B33B IN R19, 0x1B + \ 00000012 2332 AND R19, R18 + \ 00000014 BB3B OUT 0x1B, R19 + 104 __delay_cycles(OWI_DELAY_C_STD_MODE); + \ 00000016 E92B LDI R18, 155 + \ 00000018 952A DEC R18 + \ 0000001A F7F1 BRNE $-2 + \ 0000001C C000 RJMP $+2 + 105 + 106 // Release bus and delay. + 107 OWI_RELEASE_BUS(pins); + \ 0000001E 2F20 MOV R18, R16 + \ 00000020 9520 COM R18 + \ 00000022 B33A IN R19, 0x1A + \ 00000024 2332 AND R19, R18 + \ 00000026 BB3A OUT 0x1A, R19 + \ 00000028 2F20 MOV R18, R16 + \ 0000002A 9520 COM R18 + \ 0000002C B33B IN R19, 0x1B + \ 0000002E 2332 AND R19, R18 + \ 00000030 BB3B OUT 0x1B, R19 + 108 __delay_cycles(OWI_DELAY_D_STD_MODE); + \ 00000032 E126 LDI R18, 22 + \ 00000034 952A DEC R18 + \ 00000036 F7F1 BRNE $-2 + \ 00000038 0000 NOP + 109 + 110 // Restore interrupts. + 111 __restore_interrupt(intState); + \ 0000003A BF1F OUT 0x3F, R17 + 112 } + \ 0000003C 9508 RET + \ 0000003E REQUIRE _A_PORTA + \ 0000003E REQUIRE _A_DDRA + 113 + 114 /*! \brief Read a bit from the bus(es). (Software only driver) + 115 * + 116 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). + 117 * + 118 * \param pins A bitmask of the bus(es) to read from. + 119 * + 120 * \return A bitmask of the buses where a '1' was read. + 121 */ + + \ In segment CODE, align 2, keep-with-next + 122 unsigned char OWI_ReadBit(unsigned char pins) + \ OWI_ReadBit: + 123 { + \ 00000000 2F10 MOV R17, R16 + 124 unsigned char intState; + 125 unsigned char bitsRead; + 126 + 127 // Disable interrupts. + 128 intState = __save_interrupt(); + \ 00000002 B73F IN R19, 0x3F + \ 00000004 2F23 MOV R18, R19 + 129 __disable_interrupt(); + \ 00000006 94F8 CLI + 130 + 131 // Drive bus low and delay. + 132 OWI_PULL_BUS_LOW(pins); + \ 00000008 B33A IN R19, 0x1A + \ 0000000A 2B31 OR R19, R17 + \ 0000000C BB3A OUT 0x1A, R19 + \ 0000000E 2F31 MOV R19, R17 + \ 00000010 9530 COM R19 + \ 00000012 B34B IN R20, 0x1B + \ 00000014 2343 AND R20, R19 + \ 00000016 BB4B OUT 0x1B, R20 + 133 __delay_cycles(OWI_DELAY_A_STD_MODE); + \ 00000018 E03B LDI R19, 11 + \ 0000001A 953A DEC R19 + \ 0000001C F7F1 BRNE $-2 + \ 0000001E C000 RJMP $+2 + 134 + 135 // Release bus and delay. + 136 OWI_RELEASE_BUS(pins); + \ 00000020 2F31 MOV R19, R17 + \ 00000022 9530 COM R19 + \ 00000024 B34A IN R20, 0x1A + \ 00000026 2343 AND R20, R19 + \ 00000028 BB4A OUT 0x1A, R20 + \ 0000002A 2F31 MOV R19, R17 + \ 0000002C 9530 COM R19 + \ 0000002E B34B IN R20, 0x1B + \ 00000030 2343 AND R20, R19 + \ 00000032 BB4B OUT 0x1B, R20 + 137 __delay_cycles(OWI_DELAY_E_STD_MODE); + \ 00000034 E133 LDI R19, 19 + \ 00000036 953A DEC R19 + \ 00000038 F7F1 BRNE $-2 + \ 0000003A C000 RJMP $+2 + 138 + 139 // Sample bus and delay. + 140 bitsRead = OWI_PIN & pins; + \ 0000003C B339 IN R19, 0x19 + \ 0000003E 2331 AND R19, R17 + \ 00000040 2F03 MOV R16, R19 + 141 __delay_cycles(OWI_DELAY_F_STD_MODE); + \ 00000042 E83E LDI R19, 142 + \ 00000044 953A DEC R19 + \ 00000046 F7F1 BRNE $-2 + \ 00000048 0000 NOP + 142 + 143 // Restore interrupts. + 144 __restore_interrupt(intState); + \ 0000004A BF2F OUT 0x3F, R18 + 145 + 146 return bitsRead; + \ 0000004C 9508 RET + \ 0000004E REQUIRE _A_PORTA + \ 0000004E REQUIRE _A_DDRA + \ 0000004E REQUIRE _A_PINA + 147 } + 148 + 149 + 150 /*! \brief Send a Reset signal and listen for Presence signal. (software + 151 * only driver) + 152 * + 153 * Generates the waveform for transmission of a Reset pulse on the + 154 * 1-Wire(R) bus and listens for presence signals. + 155 * + 156 * \param pins A bitmask of the buses to send the Reset signal on. + 157 * + 158 * \return A bitmask of the buses where a presence signal was detected. + 159 */ + + \ In segment CODE, align 2, keep-with-next + 160 unsigned char OWI_DetectPresence(unsigned char pins) + \ OWI_DetectPresence: + 161 { + \ 00000000 2F10 MOV R17, R16 + 162 unsigned char intState; + 163 unsigned char presenceDetected; + 164 + 165 // Disable interrupts. + 166 intState = __save_interrupt(); + \ 00000002 B73F IN R19, 0x3F + \ 00000004 2F23 MOV R18, R19 + 167 __disable_interrupt(); + \ 00000006 94F8 CLI + 168 + 169 // Drive bus low and delay. + 170 OWI_PULL_BUS_LOW(pins); + \ 00000008 B33A IN R19, 0x1A + \ 0000000A 2B31 OR R19, R17 + \ 0000000C BB3A OUT 0x1A, R19 + \ 0000000E 2F31 MOV R19, R17 + \ 00000010 9530 COM R19 + \ 00000012 B34B IN R20, 0x1B + \ 00000014 2343 AND R20, R19 + \ 00000016 BB4B OUT 0x1B, R20 + 171 __delay_cycles(OWI_DELAY_H_STD_MODE); + \ 00000018 EB4C LDI R20, 188 + \ 0000001A E053 LDI R21, 3 + \ 0000001C 5041 SUBI R20, 1 + \ 0000001E 4050 SBCI R21, 0 + \ 00000020 F7E9 BRNE $-4 + \ 00000022 C000 RJMP $+2 + 172 + 173 // Release bus and delay. + 174 OWI_RELEASE_BUS(pins); + \ 00000024 2F31 MOV R19, R17 + \ 00000026 9530 COM R19 + \ 00000028 B34A IN R20, 0x1A + \ 0000002A 2343 AND R20, R19 + \ 0000002C BB4A OUT 0x1A, R20 + \ 0000002E 2F31 MOV R19, R17 + \ 00000030 9530 COM R19 + \ 00000032 B34B IN R20, 0x1B + \ 00000034 2343 AND R20, R19 + \ 00000036 BB4B OUT 0x1B, R20 + 175 __delay_cycles(OWI_DELAY_I_STD_MODE); + \ 00000038 EB36 LDI R19, 182 + \ 0000003A 953A DEC R19 + \ 0000003C F7F1 BRNE $-2 + \ 0000003E 0000 NOP + 176 + 177 // Sample bus to detect presence signal and delay. + 178 presenceDetected = ((~OWI_PIN) & pins); + \ 00000040 B339 IN R19, 0x19 + \ 00000042 9530 COM R19 + \ 00000044 2331 AND R19, R17 + \ 00000046 2F03 MOV R16, R19 + 179 __delay_cycles(OWI_DELAY_J_STD_MODE); + \ 00000048 E340 LDI R20, 48 + \ 0000004A E053 LDI R21, 3 + \ 0000004C 5041 SUBI R20, 1 + \ 0000004E 4050 SBCI R21, 0 + \ 00000050 F7E9 BRNE $-4 + \ 00000052 C000 RJMP $+2 + 180 + 181 // Restore interrupts. + 182 __restore_interrupt(intState); + \ 00000054 BF2F OUT 0x3F, R18 + 183 + 184 return presenceDetected; + \ 00000056 9508 RET + \ 00000058 REQUIRE _A_PORTA + \ 00000058 REQUIRE _A_DDRA + \ 00000058 REQUIRE _A_PINA + 185 } + 186 + 187 + 188 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es). + 189 * + 190 * This function automates the task of sending a complete byte + 191 * of data on the 1-Wire bus(es). + 192 * + 193 * \param data The data to send on the bus(es). + 194 * + 195 * \param pins A bitmask of the buses to send the data to. + 196 */ + + \ In segment CODE, align 2, keep-with-next + 197 void OWI_SendByte(unsigned char data, unsigned char pins) + \ OWI_SendByte: + 198 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + \ 00000002 2FA0 MOV R26, R16 + \ 00000004 2F91 MOV R25, R17 + 199 unsigned char temp; + 200 unsigned char i; + 201 + 202 // Do once for each bit + 203 for (i = 0; i < 8; i++) { + \ 00000006 E080 LDI R24, 0 + \ ??OWI_SendByte_0: + \ 00000008 3088 CPI R24, 8 + \ 0000000A F468 BRCC ??OWI_SendByte_1 + 204 // Determine if LSB is '0' or '1' and transmit corresponding + 205 // waveform on the bus. + 206 temp = data & 0x01; + \ 0000000C 2F0A MOV R16, R26 + \ 0000000E 7001 ANDI R16, 0x01 + \ 00000010 2FB0 MOV R27, R16 + 207 + 208 if (temp) { + \ 00000012 23BB TST R27 + \ 00000014 F019 BREQ ??OWI_SendByte_2 + 209 OWI_WriteBit1(pins); + \ 00000016 2F09 MOV R16, R25 + \ 00000018 .... RCALL OWI_WriteBit1 + \ 0000001A C002 RJMP ??OWI_SendByte_3 + 210 } else { + 211 OWI_WriteBit0(pins); + \ ??OWI_SendByte_2: + \ 0000001C 2F09 MOV R16, R25 + \ 0000001E .... RCALL OWI_WriteBit0 + 212 } + 213 + 214 data >>= 1; // Right shift the data to get next bit. + \ ??OWI_SendByte_3: + \ 00000020 95A6 LSR R26 + 215 } + \ 00000022 9583 INC R24 + \ 00000024 CFF1 RJMP ??OWI_SendByte_0 + 216 } + \ ??OWI_SendByte_1: + \ 00000026 E0E4 LDI R30, 4 + \ 00000028 .... RJMP ?EPILOGUE_B4_L09 + 217 + 218 + 219 /*! \brief Receives one byte of data from the 1-Wire(R) bus. + 220 * + 221 * This function automates the task of receiving a complete byte + 222 * of data from the 1-Wire bus. + 223 * + 224 * \param pin A bitmask of the bus to read from. + 225 * + 226 * \return The byte read from the bus. + 227 */ + + \ In segment CODE, align 2, keep-with-next + 228 unsigned char OWI_ReceiveByte(unsigned char pin) + \ OWI_ReceiveByte: + 229 { + \ 00000000 .... RCALL ?PROLOGUE3_L09 + \ 00000002 2FA0 MOV R26, R16 + 230 unsigned char data; + 231 unsigned char i; + 232 + 233 // Clear the temporary input variable. + 234 data = 0x00; + \ 00000004 E090 LDI R25, 0 + 235 + 236 // Do once for each bit + 237 for (i = 0; i < 8; i++) { + \ 00000006 E080 LDI R24, 0 + \ ??OWI_ReceiveByte_0: + \ 00000008 3088 CPI R24, 8 + \ 0000000A F448 BRCC ??OWI_ReceiveByte_1 + 238 // Shift temporary input variable right. + 239 data >>= 1; + \ 0000000C 9596 LSR R25 + 240 + 241 // Set the MSB if a '1' value is read from the bus. + 242 // Leave as it is ('0') else. + 243 if (OWI_ReadBit(pin)) { + \ 0000000E 2F0A MOV R16, R26 + \ 00000010 .... RCALL OWI_ReadBit + \ 00000012 2300 TST R16 + \ 00000014 F011 BREQ ??OWI_ReceiveByte_2 + 244 data |= 0x80; + \ 00000016 6890 ORI R25, 0x80 + \ 00000018 E001 LDI R16, 1 + 245 } + 246 } + \ ??OWI_ReceiveByte_2: + \ 0000001A 9583 INC R24 + \ 0000001C CFF5 RJMP ??OWI_ReceiveByte_0 + 247 + 248 return data; + \ ??OWI_ReceiveByte_1: + \ 0000001E 2F09 MOV R16, R25 + \ 00000020 E0E3 LDI R30, 3 + \ 00000022 .... RJMP ?EPILOGUE_B3_L09 + 249 } + 250 + 251 + 252 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). + 253 * + 254 * \param pins A bitmask of the buses to send the SKIP ROM command to. + 255 */ + + \ In segment CODE, align 2, keep-with-next + 256 void OWI_SkipRom(unsigned char pins) + \ OWI_SkipRom: + 257 { + \ 00000000 938A ST -Y, R24 + \ 00000002 2F80 MOV R24, R16 + 258 // Send the SKIP ROM command on the bus. + 259 OWI_SendByte(OWI_ROM_SKIP, pins); + \ 00000004 2F18 MOV R17, R24 + \ 00000006 EC0C LDI R16, 204 + \ 00000008 .... RCALL OWI_SendByte + 260 } + \ 0000000A 9189 LD R24, Y+ + \ 0000000C 9508 RET + 261 + 262 + 263 /*! \brief Sends the READ ROM command and reads back the ROM id. + 264 * + 265 * \param romValue A pointer where the id will be placed. + 266 * + 267 * \param pin A bitmask of the bus to read from. + 268 */ + + \ In segment CODE, align 2, keep-with-next + 269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin) + \ OWI_ReadRom: + 270 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + \ 00000002 01D8 MOVW R27:R26, R17:R16 + \ 00000004 2F92 MOV R25, R18 + 271 unsigned char bytesLeft = 8; + \ 00000006 E088 LDI R24, 8 + 272 + 273 // Send the READ ROM command on the bus. + 274 OWI_SendByte(OWI_ROM_READ, pin); + \ 00000008 2F19 MOV R17, R25 + \ 0000000A E303 LDI R16, 51 + \ 0000000C .... RCALL OWI_SendByte + 275 + 276 // Do 8 times. + 277 while (bytesLeft > 0) { + \ ??OWI_ReadRom_0: + \ 0000000E 3081 CPI R24, 1 + \ 00000010 F030 BRCS ??OWI_ReadRom_1 + 278 // Place the received data in memory. + 279 *romValue++ = OWI_ReceiveByte(pin); + \ 00000012 2F09 MOV R16, R25 + \ 00000014 .... RCALL OWI_ReceiveByte + \ 00000016 930C ST X, R16 + \ 00000018 9611 ADIW R27:R26, 1 + 280 bytesLeft--; + \ 0000001A 958A DEC R24 + \ 0000001C CFF8 RJMP ??OWI_ReadRom_0 + 281 } + 282 } + \ ??OWI_ReadRom_1: + \ 0000001E E0E4 LDI R30, 4 + \ 00000020 .... RJMP ?EPILOGUE_B4_L09 + 283 + 284 + 285 /*! \brief Sends the MATCH ROM command and the ROM id to match against. + 286 * + 287 * \param romValue A pointer to the ID to match against. + 288 * + 289 * \param pins A bitmask of the buses to perform the MATCH ROM command on. + 290 */ + + \ In segment CODE, align 2, keep-with-next + 291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins) + \ OWI_MatchRom: + 292 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + \ 00000002 01D8 MOVW R27:R26, R17:R16 + \ 00000004 2F92 MOV R25, R18 + 293 unsigned char bytesLeft = 8; + \ 00000006 E088 LDI R24, 8 + 294 + 295 // Send the MATCH ROM command. + 296 OWI_SendByte(OWI_ROM_MATCH, pins); + \ 00000008 2F19 MOV R17, R25 + \ 0000000A E505 LDI R16, 85 + \ 0000000C .... RCALL OWI_SendByte + 297 + 298 // Do once for each byte. + 299 while (bytesLeft > 0) { + \ ??OWI_MatchRom_0: + \ 0000000E 3081 CPI R24, 1 + \ 00000010 F030 BRCS ??OWI_MatchRom_1 + 300 // Transmit 1 byte of the ID to match. + 301 OWI_SendByte(*romValue++, pins); + \ 00000012 2F19 MOV R17, R25 + \ 00000014 910C LD R16, X + \ 00000016 .... RCALL OWI_SendByte + \ 00000018 9611 ADIW R27:R26, 1 + 302 bytesLeft--; + \ 0000001A 958A DEC R24 + \ 0000001C CFF8 RJMP ??OWI_MatchRom_0 + 303 } + 304 } + \ ??OWI_MatchRom_1: + \ 0000001E E0E4 LDI R30, 4 + \ 00000020 .... RJMP ?EPILOGUE_B4_L09 + 305 + 306 + 307 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the + 308 * 1-Wire(R) bus. + 309 * + 310 * \param bitPattern A pointer to an 8 byte char array where the + 311 * discovered identifier will be placed. When + 312 * searching for several slaves, a copy of the + 313 * last found identifier should be supplied in + 314 * the array, or the search will fail. + 315 * + 316 * \param lastDeviation The bit position where the algorithm made a + 317 * choice the last time it was run. This argument + 318 * should be 0 when a search is initiated. Supplying + 319 * the return argument of this function when calling + 320 * repeatedly will go through the complete slave + 321 * search. + 322 * + 323 * \param pin A bit-mask of the bus to perform a ROM search on. + 324 * + 325 * \return The last bit position where there was a discrepancy between slave + 326 * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED + 327 * if an error was detected (e.g. a device was connected to the bus during the + 328 * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be + 329 * discovered. + 330 * + 331 * \note See main.c for an example of how to utilize this function. + 332 */ + + \ In segment CODE, align 2, keep-with-next + 333 unsigned char OWI_SearchRom(unsigned char * bitPattern, + \ OWI_SearchRom: + 334 unsigned char lastDeviation, unsigned char pin) + 335 { + \ 00000000 .... RCALL ?PROLOGUE9_L09 + \ 00000002 REQUIRE ?Register_R4_is_cg_reg + \ 00000002 REQUIRE ?Register_R5_is_cg_reg + \ 00000002 REQUIRE ?Register_R6_is_cg_reg + \ 00000002 REQUIRE ?Register_R7_is_cg_reg + \ 00000002 REQUIRE ?Register_R8_is_cg_reg + \ 00000002 0128 MOVW R5:R4, R17:R16 + \ 00000004 2E82 MOV R8, R18 + \ 00000006 2FB3 MOV R27, R19 + 336 unsigned char currentBit = 1; + \ 00000008 E081 LDI R24, 1 + 337 unsigned char newDeviation = 0; + \ 0000000A E0A0 LDI R26, 0 + 338 unsigned char bitMask = 0x01; + \ 0000000C E091 LDI R25, 1 + 339 unsigned char bitA; + 340 unsigned char bitB; + 341 + 342 // Send SEARCH ROM command on the bus. + 343 OWI_SendByte(OWI_ROM_SEARCH, pin); + \ 0000000E 2F1B MOV R17, R27 + \ 00000010 EF00 LDI R16, 240 + \ 00000012 .... RCALL OWI_SendByte + 344 + 345 // Walk through all 64 bits. + 346 while (currentBit <= 64) { + \ ??OWI_SearchRom_0: + \ 00000014 3481 CPI R24, 65 + \ 00000016 F008 BRCS $+2+2 + \ 00000018 C04B RJMP ??OWI_SearchRom_1 + 347 // Read bit from bus twice. + 348 bitA = OWI_ReadBit(pin); + \ 0000001A 2F0B MOV R16, R27 + \ 0000001C .... RCALL OWI_ReadBit + \ 0000001E 2E60 MOV R6, R16 + 349 bitB = OWI_ReadBit(pin); + \ 00000020 2F0B MOV R16, R27 + \ 00000022 .... RCALL OWI_ReadBit + \ 00000024 2E70 MOV R7, R16 + 350 + 351 if (bitA && bitB) { + \ 00000026 2066 TST R6 + \ 00000028 F029 BREQ ??OWI_SearchRom_2 + \ 0000002A 2077 TST R7 + \ 0000002C F019 BREQ ??OWI_SearchRom_2 + 352 // Both bits 1 (Error). + 353 newDeviation = OWI_ROM_SEARCH_FAILED; + \ 0000002E EFAF LDI R26, 255 + 354 return newDeviation; + \ 00000030 2F0A MOV R16, R26 + \ 00000032 C03F RJMP ??OWI_SearchRom_3 + 355 } else if (bitA ^ bitB) { + \ ??OWI_SearchRom_2: + \ 00000034 2D07 MOV R16, R7 + \ 00000036 2506 EOR R16, R6 + \ 00000038 2300 TST R16 + \ 0000003A F071 BREQ ??OWI_SearchRom_4 + 356 // Bits A and B are different. All devices have the same bit here. + 357 // Set the bit in bitPattern to this value. + 358 if (bitA) { + \ 0000003C 2066 TST R6 + \ 0000003E F029 BREQ ??OWI_SearchRom_5 + 359 (*bitPattern) |= bitMask; + \ 00000040 01F2 MOVW R31:R30, R5:R4 + \ 00000042 8100 LD R16, Z + \ 00000044 2B09 OR R16, R25 + \ 00000046 8300 ST Z, R16 + \ 00000048 C01E RJMP ??OWI_SearchRom_6 + 360 } else { + 361 (*bitPattern) &= ~bitMask; + \ ??OWI_SearchRom_5: + \ 0000004A 2F09 MOV R16, R25 + \ 0000004C 9500 COM R16 + \ 0000004E 01F2 MOVW R31:R30, R5:R4 + \ 00000050 8110 LD R17, Z + \ 00000052 2310 AND R17, R16 + \ 00000054 8310 ST Z, R17 + \ 00000056 C017 RJMP ??OWI_SearchRom_6 + 362 } + 363 } else { + 364 // If this is where a choice was made the last time, + 365 // a '1' bit is selected this time. + 366 if (currentBit == lastDeviation) { + \ ??OWI_SearchRom_4: + \ 00000058 1588 CP R24, R8 + \ 0000005A F429 BRNE ??OWI_SearchRom_7 + 367 (*bitPattern) |= bitMask; + \ 0000005C 01F2 MOVW R31:R30, R5:R4 + \ 0000005E 8100 LD R16, Z + \ 00000060 2B09 OR R16, R25 + \ 00000062 8300 ST Z, R16 + \ 00000064 C010 RJMP ??OWI_SearchRom_6 + 368 } + 369 + 370 // For the rest of the id, '0' bits are selected when + 371 // discrepancies occur. + 372 else if (currentBit > lastDeviation) { + \ ??OWI_SearchRom_7: + \ 00000066 1688 CP R8, R24 + \ 00000068 F440 BRCC ??OWI_SearchRom_8 + 373 (*bitPattern) &= ~bitMask; + \ 0000006A 2F09 MOV R16, R25 + \ 0000006C 9500 COM R16 + \ 0000006E 01F2 MOVW R31:R30, R5:R4 + \ 00000070 8110 LD R17, Z + \ 00000072 2310 AND R17, R16 + \ 00000074 8310 ST Z, R17 + 374 newDeviation = currentBit; + \ 00000076 2FA8 MOV R26, R24 + \ 00000078 C006 RJMP ??OWI_SearchRom_6 + 375 } + 376 + 377 // If current bit in bit pattern = 0, then this is + 378 // out new deviation. + 379 else if ( !(*bitPattern & bitMask)) { + \ ??OWI_SearchRom_8: + \ 0000007A 01F2 MOVW R31:R30, R5:R4 + \ 0000007C 8100 LD R16, Z + \ 0000007E 2309 AND R16, R25 + \ 00000080 2300 TST R16 + \ 00000082 F409 BRNE ??OWI_SearchRom_6 + 380 newDeviation = currentBit; + \ 00000084 2FA8 MOV R26, R24 + 381 } + 382 + 383 // IF the bit is already 1, do nothing. + 384 else { + 385 } + 386 } + 387 + 388 // Send the selected bit to the bus. + 389 if ((*bitPattern) & bitMask) { + \ ??OWI_SearchRom_6: + \ 00000086 01F2 MOVW R31:R30, R5:R4 + \ 00000088 8100 LD R16, Z + \ 0000008A 2309 AND R16, R25 + \ 0000008C 2300 TST R16 + \ 0000008E F019 BREQ ??OWI_SearchRom_9 + 390 OWI_WriteBit1(pin); + \ 00000090 2F0B MOV R16, R27 + \ 00000092 .... RCALL OWI_WriteBit1 + \ 00000094 C002 RJMP ??OWI_SearchRom_10 + 391 } else { + 392 OWI_WriteBit0(pin); + \ ??OWI_SearchRom_9: + \ 00000096 2F0B MOV R16, R27 + \ 00000098 .... RCALL OWI_WriteBit0 + 393 } + 394 + 395 // Increment current bit. + 396 currentBit++; + \ ??OWI_SearchRom_10: + \ 0000009A 9583 INC R24 + 397 + 398 // Adjust bitMask and bitPattern pointer. + 399 bitMask <<= 1; + \ 0000009C 0F99 LSL R25 + 400 if (!bitMask) { + \ 0000009E 2399 TST R25 + \ 000000A0 F009 BREQ $+2+2 + \ 000000A2 CFB8 RJMP ??OWI_SearchRom_0 + 401 bitMask = 0x01; + \ 000000A4 E091 LDI R25, 1 + 402 bitPattern++; + \ 000000A6 E001 LDI R16, 1 + \ 000000A8 0E40 ADD R4, R16 + \ 000000AA E000 LDI R16, 0 + \ 000000AC 1E50 ADC R5, R16 + \ 000000AE CFB2 RJMP ??OWI_SearchRom_0 + 403 } + 404 } + 405 + 406 return newDeviation; + \ ??OWI_SearchRom_1: + \ 000000B0 2F0A MOV R16, R26 + \ ??OWI_SearchRom_3: + \ 000000B2 E0E9 LDI R30, 9 + \ 000000B4 .... RJMP ?EPILOGUE_B9_L09 + 407 } + 408 + 409 + 410 /* Functions for handling CRC */ + 411 /*! \brief Compute the CRC8 value of a data set. + 412 * + 413 * This function will compute the CRC8 or DOW-CRC of inData using seed + 414 * as inital value for the CRC. + 415 * + 416 * \param inData One byte of data to compute CRC from. + 417 * + 418 * \param seed The starting value of the CRC. + 419 * + 420 * \return The CRC8 of inData with seed as initial value. + 421 * + 422 * \note Setting seed to 0 computes the crc8 of the inData. + 423 * + 424 * \note Constantly passing the return value of this function + 425 * As the seed argument computes the CRC8 value of a + 426 * longer string of data. + 427 */ + + \ In segment CODE, align 2, keep-with-next + 428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) + \ OWI_ComputeCRC8: + 429 { + \ 00000000 2F30 MOV R19, R16 + \ 00000002 2F01 MOV R16, R17 + 430 unsigned char bitsLeft; + 431 unsigned char temp; + 432 + 433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + \ 00000004 E018 LDI R17, 8 + \ ??OWI_ComputeCRC8_0: + \ 00000006 3011 CPI R17, 1 + \ 00000008 F098 BRCS ??OWI_ComputeCRC8_1 + 434 temp = ((seed ^ inData) & 0x01); + \ 0000000A 2F50 MOV R21, R16 + \ 0000000C 7051 ANDI R21, 0x01 + \ 0000000E 2F23 MOV R18, R19 + \ 00000010 7021 ANDI R18, 0x01 + \ 00000012 2725 EOR R18, R21 + \ 00000014 7021 ANDI R18, 0x01 + \ 00000016 2F42 MOV R20, R18 + 435 + 436 if (temp == 0) { + \ 00000018 2344 TST R20 + \ 0000001A F411 BRNE ??OWI_ComputeCRC8_2 + 437 seed >>= 1; + \ 0000001C 9506 LSR R16 + \ 0000001E C005 RJMP ??OWI_ComputeCRC8_3 + 438 } else { + 439 seed ^= 0x18; + \ ??OWI_ComputeCRC8_2: + \ 00000020 E128 LDI R18, 24 + \ 00000022 2702 EOR R16, R18 + 440 seed >>= 1; + \ 00000024 9506 LSR R16 + 441 seed |= 0x80; + \ 00000026 6800 ORI R16, 0x80 + \ 00000028 E021 LDI R18, 1 + 442 } + 443 + 444 inData >>= 1; + \ ??OWI_ComputeCRC8_3: + \ 0000002A 9536 LSR R19 + 445 } + \ 0000002C 951A DEC R17 + \ 0000002E CFEB RJMP ??OWI_ComputeCRC8_0 + 446 return seed; + \ ??OWI_ComputeCRC8_1: + \ 00000030 9508 RET + 447 } + 448 + 449 + 450 /*! \brief Compute the CRC16 value of a data set. + 451 * + 452 * This function will compute the CRC16 of inData using seed + 453 * as inital value for the CRC. + 454 * + 455 * \param inData One byte of data to compute CRC from. + 456 * + 457 * \param seed The starting value of the CRC. + 458 * + 459 * \return The CRC16 of inData with seed as initial value. + 460 * + 461 * \note Setting seed to 0 computes the crc16 of the inData. + 462 * + 463 * \note Constantly passing the return value of this function + 464 * As the seed argument computes the CRC16 value of a + 465 * longer string of data. + 466 */ + + \ In segment CODE, align 2, keep-with-next + 467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) + \ OWI_ComputeCRC16: + 468 { + \ 00000000 2F50 MOV R21, R16 + 469 unsigned char bitsLeft; + 470 unsigned char temp; + 471 + 472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + \ 00000002 E048 LDI R20, 8 + \ ??OWI_ComputeCRC16_0: + \ 00000004 3041 CPI R20, 1 + \ 00000006 F0C0 BRCS ??OWI_ComputeCRC16_1 + 473 temp = ((seed ^ inData) & 0x01); + \ 00000008 2F12 MOV R17, R18 + \ 0000000A 7011 ANDI R17, 0x01 + \ 0000000C 2F05 MOV R16, R21 + \ 0000000E 7001 ANDI R16, 0x01 + \ 00000010 2701 EOR R16, R17 + \ 00000012 7001 ANDI R16, 0x01 + \ 00000014 2F60 MOV R22, R16 + 474 + 475 if (temp == 0) { + \ 00000016 2366 TST R22 + \ 00000018 F419 BRNE ??OWI_ComputeCRC16_2 + 476 seed >>= 1; + \ 0000001A 9536 LSR R19 + \ 0000001C 9527 ROR R18 + \ 0000001E C009 RJMP ??OWI_ComputeCRC16_3 + 477 } else { + 478 seed ^= 0x4002; + \ ??OWI_ComputeCRC16_2: + \ 00000020 E002 LDI R16, 2 + \ 00000022 E410 LDI R17, 64 + \ 00000024 2720 EOR R18, R16 + \ 00000026 2731 EOR R19, R17 + 479 seed >>= 1; + \ 00000028 9536 LSR R19 + \ 0000002A 9527 ROR R18 + 480 seed |= 0x8000; + \ 0000002C 6830 ORI R19, 0x80 + \ 0000002E E001 LDI R16, 1 + \ 00000030 E010 LDI R17, 0 + 481 } + 482 + 483 inData >>= 1; + \ ??OWI_ComputeCRC16_3: + \ 00000032 9556 LSR R21 + 484 } + \ 00000034 954A DEC R20 + \ 00000036 CFE6 RJMP ??OWI_ComputeCRC16_0 + 485 + 486 return seed; + \ ??OWI_ComputeCRC16_1: + \ 00000038 0189 MOVW R17:R16, R19:R18 + \ 0000003A 9508 RET + 487 } + 488 + 489 + 490 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier. + 491 * + 492 * This function computes the CRC8 value of the first 56 bits of a + 493 * 64 bit identifier. It then checks the calculated value against the + 494 * CRC value stored in ROM. + 495 * + 496 * \param *romValue A pointer to an array holding a 64 bit identifier. + 497 * + 498 * \retval OWI_CRC_OK The CRC's matched. + 499 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. + 500 */ + + \ In segment CODE, align 2, keep-with-next + 501 unsigned char OWI_CheckRomCRC(unsigned char *romValue) + \ OWI_CheckRomCRC: + 502 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + \ 00000002 01D8 MOVW R27:R26, R17:R16 + 503 unsigned char i; + 504 unsigned char crc8 = 0; + \ 00000004 E090 LDI R25, 0 + 505 + 506 for (i = 0; i < 7; i++) { + \ 00000006 E080 LDI R24, 0 + \ ??OWI_CheckRomCRC_0: + \ 00000008 3087 CPI R24, 7 + \ 0000000A F440 BRCC ??OWI_CheckRomCRC_1 + 507 crc8 = OWI_ComputeCRC8(*romValue, crc8); + \ 0000000C 2F19 MOV R17, R25 + \ 0000000E 01FD MOVW R31:R30, R27:R26 + \ 00000010 8100 LD R16, Z + \ 00000012 .... RCALL OWI_ComputeCRC8 + \ 00000014 2F90 MOV R25, R16 + 508 romValue++; + \ 00000016 9611 ADIW R27:R26, 1 + 509 } + \ 00000018 9583 INC R24 + \ 0000001A CFF6 RJMP ??OWI_CheckRomCRC_0 + 510 + 511 if (crc8 == (*romValue)) { + \ ??OWI_CheckRomCRC_1: + \ 0000001C 910C LD R16, X + \ 0000001E 1790 CP R25, R16 + \ 00000020 F411 BRNE ??OWI_CheckRomCRC_2 + 512 return OWI_CRC_OK; + \ 00000022 E000 LDI R16, 0 + \ 00000024 C001 RJMP ??OWI_CheckRomCRC_3 + 513 } + 514 + 515 return OWI_CRC_ERROR; + \ ??OWI_CheckRomCRC_2: + \ 00000026 E001 LDI R16, 1 + \ ??OWI_CheckRomCRC_3: + \ 00000028 E0E4 LDI R30, 4 + \ 0000002A .... RJMP ?EPILOGUE_B4_L09 + 516 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + OWI_CheckRomCRC 4 2 + -> OWI_ComputeCRC8 4 2 + OWI_ComputeCRC16 0 2 + OWI_ComputeCRC8 0 2 + OWI_DetectPresence 0 2 + OWI_Init 0 2 + OWI_MatchRom 4 2 + -> OWI_SendByte 4 2 + -> OWI_SendByte 4 2 + OWI_ReadBit 0 2 + OWI_ReadRom 4 2 + -> OWI_SendByte 4 2 + -> OWI_ReceiveByte 4 2 + OWI_ReceiveByte 3 2 + -> OWI_ReadBit 3 2 + OWI_SearchRom 9 2 + -> OWI_SendByte 9 2 + -> OWI_ReadBit 9 2 + -> OWI_ReadBit 9 2 + -> OWI_WriteBit1 9 2 + -> OWI_WriteBit0 9 2 + OWI_SendByte 4 2 + -> OWI_WriteBit1 4 2 + -> OWI_WriteBit0 4 2 + OWI_SkipRom 1 2 + -> OWI_SendByte 1 2 + OWI_WriteBit0 0 2 + OWI_WriteBit1 0 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_PORTA 1 + _A_DDRA 1 + _A_PINA 1 + OWI_Init 34 + OWI_WriteBit1 62 + OWI_WriteBit0 62 + OWI_ReadBit 78 + OWI_DetectPresence 88 + OWI_SendByte 42 + OWI_ReceiveByte 36 + OWI_SkipRom 14 + OWI_ReadRom 34 + OWI_MatchRom 34 + OWI_SearchRom 182 + OWI_ComputeCRC8 50 + OWI_ComputeCRC16 60 + OWI_CheckRomCRC 44 + + + 3 bytes in segment ABSOLUTE + 820 bytes in segment CODE + + 820 bytes of CODE memory + 0 bytes of DATA memory (+ 3 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/OWI.s90 b/BaseTinyFirmware/IAR/Debug/List/OWI.s90 new file mode 100644 index 0000000..9a58126 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/OWI.s90 @@ -0,0 +1,1120 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\OWI.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME OWI + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?EPILOGUE_B3_L09 + EXTERN ?EPILOGUE_B4_L09 + EXTERN ?EPILOGUE_B9_L09 + EXTERN ?PROLOGUE3_L09 + EXTERN ?PROLOGUE4_L09 + EXTERN ?PROLOGUE9_L09 + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?Register_R6_is_cg_reg + EXTERN ?Register_R7_is_cg_reg + EXTERN ?Register_R8_is_cg_reg + + PUBLIC OWI_CheckRomCRC + PUBLIC OWI_ComputeCRC16 + PUBLIC OWI_ComputeCRC8 + PUBLIC OWI_DetectPresence + PUBLIC OWI_Init + PUBLIC OWI_MatchRom + PUBLIC OWI_ReadBit + PUBLIC OWI_ReadRom + PUBLIC OWI_ReceiveByte + PUBLIC OWI_SearchRom + PUBLIC OWI_SendByte + PUBLIC OWI_SkipRom + PUBLIC OWI_WriteBit0 + PUBLIC OWI_WriteBit1 + PUBWEAK _A_DDRA + PUBWEAK _A_PINA + PUBWEAK _A_PORTA + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + +// C:\home\kevin\pub\src\bc100_cal\IAR\OWI.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ******************************************************************** +// 3 * +// 4 * \brief +// 5 * Functions for 1-Wire(R) bus communication +// 6 * +// 7 * High level functions for transmission of full bytes on the 1-Wire(R) +// 8 * bus and implementations of ROM commands.\n +// 9 * Polled software only implementation of the basic bit-level signalling +// 10 * in the 1-Wire(R) protocol.\n +// 11 * Includes functions for computing and checking CRC8 & 16 values of data +// 12 * sets, and of 64 bit ROM identifiers. +// 13 * Supported devices: All AVRs. +// 14 * +// 15 * \par Application Note: +// 16 * AVR458: Charging Li-Ion Batteries with BC100\n +// 17 * AVR463: Charging NiMH Batteries with BC100\n +// 18 * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. +// 19 * +// 20 * \par Documentation: +// 21 * For comprehensive code documentation, supported compilers, compiler +// 22 * settings and supported devices see readme.html +// 23 * +// 24 * \author +// 25 * Atmel Corporation: http://www.atmel.com \n +// 26 * Support email: avr@atmel.com \n +// 27 * Original author: \n +// 28 * +// 29 * $Name$ +// 30 * $Revision: 2299 $ +// 31 * $RCSfile$ +// 32 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ +// 33 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 34 ****************************************************************************/ +// 35 +// 36 #include + + ASEGN ABSOLUTE:DATA:NOROOT,03bH +// volatile __io _A_PORTA +_A_PORTA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,03aH +// volatile __io _A_DDRA +_A_DDRA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,039H +// volatile __io _A_PINA +_A_PINA: + DS 1 +// 37 #include +// 38 +// 39 #include "OWI.h" +// 40 +// 41 +// 42 //****************************************************************************** +// 43 // Functions +// 44 //****************************************************************************** +// 45 /*! \brief Initialization of the one wire bus(es). (Software only driver) +// 46 * +// 47 * This function initializes the 1-Wire bus(es) by releasing it and +// 48 * waiting until any presence signals are finished. +// 49 * +// 50 * \param pins A bitmask of the buses to initialize. +// 51 */ + + RSEG CODE:CODE:NOROOT(1) +// 52 void OWI_Init(unsigned char pins){ +OWI_Init: +// 53 OWI_RELEASE_BUS(pins); + MOV R17, R16 + COM R17 + IN R18, 0x1A + AND R18, R17 + OUT 0x1A, R18 + MOV R17, R16 + COM R17 + IN R18, 0x1B + AND R18, R17 + OUT 0x1B, R18 +// 54 // The first rising edge can be interpreted by a slave as the end of a +// 55 // Reset-pulse. Delay for the required reset recovery time (H) to be +// 56 // sure that the real reset is interpreted correctly. +// 57 __delay_cycles(OWI_DELAY_H_STD_MODE); + LDI R18, 188 + LDI R19, 3 + SUBI R18, 1 + SBCI R19, 0 + BRNE $-4 + RJMP $+2 +// 58 } + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA +// 59 +// 60 +// 61 /*! \brief Write a '1' bit to the bus(es). (Software only driver) +// 62 * +// 63 * Generates the waveform for transmission of a '1' bit on the 1-Wire +// 64 * bus. +// 65 * +// 66 * \param pins A bitmask of the buses to write to. +// 67 */ + + RSEG CODE:CODE:NOROOT(1) +// 68 void OWI_WriteBit1(unsigned char pins){ +OWI_WriteBit1: +// 69 unsigned char intState; +// 70 +// 71 // Disable interrupts. +// 72 intState = __save_interrupt(); + IN R18, 0x3F + MOV R17, R18 +// 73 __disable_interrupt(); + CLI +// 74 +// 75 // Drive bus low and delay. +// 76 OWI_PULL_BUS_LOW(pins); + IN R18, 0x1A + OR R18, R16 + OUT 0x1A, R18 + MOV R18, R16 + COM R18 + IN R19, 0x1B + AND R19, R18 + OUT 0x1B, R19 +// 77 __delay_cycles(OWI_DELAY_A_STD_MODE); + LDI R18, 11 + DEC R18 + BRNE $-2 + RJMP $+2 +// 78 +// 79 // Release bus and delay. +// 80 OWI_RELEASE_BUS(pins); + MOV R18, R16 + COM R18 + IN R19, 0x1A + AND R19, R18 + OUT 0x1A, R19 + MOV R18, R16 + COM R18 + IN R19, 0x1B + AND R19, R18 + OUT 0x1B, R19 +// 81 __delay_cycles(OWI_DELAY_B_STD_MODE); + LDI R18, 166 + DEC R18 + BRNE $-2 + NOP +// 82 +// 83 // Restore interrupts. +// 84 __restore_interrupt(intState); + OUT 0x3F, R17 +// 85 } + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA +// 86 +// 87 /*! \brief Write a '0' to the bus(es). (Software only driver) +// 88 * +// 89 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) +// 90 * bus. +// 91 * +// 92 * \param pins A bitmask of the buses to write to. +// 93 */ + + RSEG CODE:CODE:NOROOT(1) +// 94 void OWI_WriteBit0(unsigned char pins) +OWI_WriteBit0: +// 95 { +// 96 unsigned char intState; +// 97 +// 98 // Disable interrupts. +// 99 intState = __save_interrupt(); + IN R18, 0x3F + MOV R17, R18 +// 100 __disable_interrupt(); + CLI +// 101 +// 102 // Drive bus low and delay. +// 103 OWI_PULL_BUS_LOW(pins); + IN R18, 0x1A + OR R18, R16 + OUT 0x1A, R18 + MOV R18, R16 + COM R18 + IN R19, 0x1B + AND R19, R18 + OUT 0x1B, R19 +// 104 __delay_cycles(OWI_DELAY_C_STD_MODE); + LDI R18, 155 + DEC R18 + BRNE $-2 + RJMP $+2 +// 105 +// 106 // Release bus and delay. +// 107 OWI_RELEASE_BUS(pins); + MOV R18, R16 + COM R18 + IN R19, 0x1A + AND R19, R18 + OUT 0x1A, R19 + MOV R18, R16 + COM R18 + IN R19, 0x1B + AND R19, R18 + OUT 0x1B, R19 +// 108 __delay_cycles(OWI_DELAY_D_STD_MODE); + LDI R18, 22 + DEC R18 + BRNE $-2 + NOP +// 109 +// 110 // Restore interrupts. +// 111 __restore_interrupt(intState); + OUT 0x3F, R17 +// 112 } + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA +// 113 +// 114 /*! \brief Read a bit from the bus(es). (Software only driver) +// 115 * +// 116 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). +// 117 * +// 118 * \param pins A bitmask of the bus(es) to read from. +// 119 * +// 120 * \return A bitmask of the buses where a '1' was read. +// 121 */ + + RSEG CODE:CODE:NOROOT(1) +// 122 unsigned char OWI_ReadBit(unsigned char pins) +OWI_ReadBit: +// 123 { + MOV R17, R16 +// 124 unsigned char intState; +// 125 unsigned char bitsRead; +// 126 +// 127 // Disable interrupts. +// 128 intState = __save_interrupt(); + IN R19, 0x3F + MOV R18, R19 +// 129 __disable_interrupt(); + CLI +// 130 +// 131 // Drive bus low and delay. +// 132 OWI_PULL_BUS_LOW(pins); + IN R19, 0x1A + OR R19, R17 + OUT 0x1A, R19 + MOV R19, R17 + COM R19 + IN R20, 0x1B + AND R20, R19 + OUT 0x1B, R20 +// 133 __delay_cycles(OWI_DELAY_A_STD_MODE); + LDI R19, 11 + DEC R19 + BRNE $-2 + RJMP $+2 +// 134 +// 135 // Release bus and delay. +// 136 OWI_RELEASE_BUS(pins); + MOV R19, R17 + COM R19 + IN R20, 0x1A + AND R20, R19 + OUT 0x1A, R20 + MOV R19, R17 + COM R19 + IN R20, 0x1B + AND R20, R19 + OUT 0x1B, R20 +// 137 __delay_cycles(OWI_DELAY_E_STD_MODE); + LDI R19, 19 + DEC R19 + BRNE $-2 + RJMP $+2 +// 138 +// 139 // Sample bus and delay. +// 140 bitsRead = OWI_PIN & pins; + IN R19, 0x19 + AND R19, R17 + MOV R16, R19 +// 141 __delay_cycles(OWI_DELAY_F_STD_MODE); + LDI R19, 142 + DEC R19 + BRNE $-2 + NOP +// 142 +// 143 // Restore interrupts. +// 144 __restore_interrupt(intState); + OUT 0x3F, R18 +// 145 +// 146 return bitsRead; + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA + REQUIRE _A_PINA +// 147 } +// 148 +// 149 +// 150 /*! \brief Send a Reset signal and listen for Presence signal. (software +// 151 * only driver) +// 152 * +// 153 * Generates the waveform for transmission of a Reset pulse on the +// 154 * 1-Wire(R) bus and listens for presence signals. +// 155 * +// 156 * \param pins A bitmask of the buses to send the Reset signal on. +// 157 * +// 158 * \return A bitmask of the buses where a presence signal was detected. +// 159 */ + + RSEG CODE:CODE:NOROOT(1) +// 160 unsigned char OWI_DetectPresence(unsigned char pins) +OWI_DetectPresence: +// 161 { + MOV R17, R16 +// 162 unsigned char intState; +// 163 unsigned char presenceDetected; +// 164 +// 165 // Disable interrupts. +// 166 intState = __save_interrupt(); + IN R19, 0x3F + MOV R18, R19 +// 167 __disable_interrupt(); + CLI +// 168 +// 169 // Drive bus low and delay. +// 170 OWI_PULL_BUS_LOW(pins); + IN R19, 0x1A + OR R19, R17 + OUT 0x1A, R19 + MOV R19, R17 + COM R19 + IN R20, 0x1B + AND R20, R19 + OUT 0x1B, R20 +// 171 __delay_cycles(OWI_DELAY_H_STD_MODE); + LDI R20, 188 + LDI R21, 3 + SUBI R20, 1 + SBCI R21, 0 + BRNE $-4 + RJMP $+2 +// 172 +// 173 // Release bus and delay. +// 174 OWI_RELEASE_BUS(pins); + MOV R19, R17 + COM R19 + IN R20, 0x1A + AND R20, R19 + OUT 0x1A, R20 + MOV R19, R17 + COM R19 + IN R20, 0x1B + AND R20, R19 + OUT 0x1B, R20 +// 175 __delay_cycles(OWI_DELAY_I_STD_MODE); + LDI R19, 182 + DEC R19 + BRNE $-2 + NOP +// 176 +// 177 // Sample bus to detect presence signal and delay. +// 178 presenceDetected = ((~OWI_PIN) & pins); + IN R19, 0x19 + COM R19 + AND R19, R17 + MOV R16, R19 +// 179 __delay_cycles(OWI_DELAY_J_STD_MODE); + LDI R20, 48 + LDI R21, 3 + SUBI R20, 1 + SBCI R21, 0 + BRNE $-4 + RJMP $+2 +// 180 +// 181 // Restore interrupts. +// 182 __restore_interrupt(intState); + OUT 0x3F, R18 +// 183 +// 184 return presenceDetected; + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA + REQUIRE _A_PINA +// 185 } +// 186 +// 187 +// 188 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es). +// 189 * +// 190 * This function automates the task of sending a complete byte +// 191 * of data on the 1-Wire bus(es). +// 192 * +// 193 * \param data The data to send on the bus(es). +// 194 * +// 195 * \param pins A bitmask of the buses to send the data to. +// 196 */ + + RSEG CODE:CODE:NOROOT(1) +// 197 void OWI_SendByte(unsigned char data, unsigned char pins) +OWI_SendByte: +// 198 { + RCALL ?PROLOGUE4_L09 + MOV R26, R16 + MOV R25, R17 +// 199 unsigned char temp; +// 200 unsigned char i; +// 201 +// 202 // Do once for each bit +// 203 for (i = 0; i < 8; i++) { + LDI R24, 0 +??OWI_SendByte_0: + CPI R24, 8 + BRCC ??OWI_SendByte_1 +// 204 // Determine if LSB is '0' or '1' and transmit corresponding +// 205 // waveform on the bus. +// 206 temp = data & 0x01; + MOV R16, R26 + ANDI R16, 0x01 + MOV R27, R16 +// 207 +// 208 if (temp) { + TST R27 + BREQ ??OWI_SendByte_2 +// 209 OWI_WriteBit1(pins); + MOV R16, R25 + RCALL OWI_WriteBit1 + RJMP ??OWI_SendByte_3 +// 210 } else { +// 211 OWI_WriteBit0(pins); +??OWI_SendByte_2: + MOV R16, R25 + RCALL OWI_WriteBit0 +// 212 } +// 213 +// 214 data >>= 1; // Right shift the data to get next bit. +??OWI_SendByte_3: + LSR R26 +// 215 } + INC R24 + RJMP ??OWI_SendByte_0 +// 216 } +??OWI_SendByte_1: + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 217 +// 218 +// 219 /*! \brief Receives one byte of data from the 1-Wire(R) bus. +// 220 * +// 221 * This function automates the task of receiving a complete byte +// 222 * of data from the 1-Wire bus. +// 223 * +// 224 * \param pin A bitmask of the bus to read from. +// 225 * +// 226 * \return The byte read from the bus. +// 227 */ + + RSEG CODE:CODE:NOROOT(1) +// 228 unsigned char OWI_ReceiveByte(unsigned char pin) +OWI_ReceiveByte: +// 229 { + RCALL ?PROLOGUE3_L09 + MOV R26, R16 +// 230 unsigned char data; +// 231 unsigned char i; +// 232 +// 233 // Clear the temporary input variable. +// 234 data = 0x00; + LDI R25, 0 +// 235 +// 236 // Do once for each bit +// 237 for (i = 0; i < 8; i++) { + LDI R24, 0 +??OWI_ReceiveByte_0: + CPI R24, 8 + BRCC ??OWI_ReceiveByte_1 +// 238 // Shift temporary input variable right. +// 239 data >>= 1; + LSR R25 +// 240 +// 241 // Set the MSB if a '1' value is read from the bus. +// 242 // Leave as it is ('0') else. +// 243 if (OWI_ReadBit(pin)) { + MOV R16, R26 + RCALL OWI_ReadBit + TST R16 + BREQ ??OWI_ReceiveByte_2 +// 244 data |= 0x80; + ORI R25, 0x80 + LDI R16, 1 +// 245 } +// 246 } +??OWI_ReceiveByte_2: + INC R24 + RJMP ??OWI_ReceiveByte_0 +// 247 +// 248 return data; +??OWI_ReceiveByte_1: + MOV R16, R25 + LDI R30, 3 + RJMP ?EPILOGUE_B3_L09 +// 249 } +// 250 +// 251 +// 252 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). +// 253 * +// 254 * \param pins A bitmask of the buses to send the SKIP ROM command to. +// 255 */ + + RSEG CODE:CODE:NOROOT(1) +// 256 void OWI_SkipRom(unsigned char pins) +OWI_SkipRom: +// 257 { + ST -Y, R24 + MOV R24, R16 +// 258 // Send the SKIP ROM command on the bus. +// 259 OWI_SendByte(OWI_ROM_SKIP, pins); + MOV R17, R24 + LDI R16, 204 + RCALL OWI_SendByte +// 260 } + LD R24, Y+ + RET +// 261 +// 262 +// 263 /*! \brief Sends the READ ROM command and reads back the ROM id. +// 264 * +// 265 * \param romValue A pointer where the id will be placed. +// 266 * +// 267 * \param pin A bitmask of the bus to read from. +// 268 */ + + RSEG CODE:CODE:NOROOT(1) +// 269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin) +OWI_ReadRom: +// 270 { + RCALL ?PROLOGUE4_L09 + MOVW R27:R26, R17:R16 + MOV R25, R18 +// 271 unsigned char bytesLeft = 8; + LDI R24, 8 +// 272 +// 273 // Send the READ ROM command on the bus. +// 274 OWI_SendByte(OWI_ROM_READ, pin); + MOV R17, R25 + LDI R16, 51 + RCALL OWI_SendByte +// 275 +// 276 // Do 8 times. +// 277 while (bytesLeft > 0) { +??OWI_ReadRom_0: + CPI R24, 1 + BRCS ??OWI_ReadRom_1 +// 278 // Place the received data in memory. +// 279 *romValue++ = OWI_ReceiveByte(pin); + MOV R16, R25 + RCALL OWI_ReceiveByte + ST X, R16 + ADIW R27:R26, 1 +// 280 bytesLeft--; + DEC R24 + RJMP ??OWI_ReadRom_0 +// 281 } +// 282 } +??OWI_ReadRom_1: + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 283 +// 284 +// 285 /*! \brief Sends the MATCH ROM command and the ROM id to match against. +// 286 * +// 287 * \param romValue A pointer to the ID to match against. +// 288 * +// 289 * \param pins A bitmask of the buses to perform the MATCH ROM command on. +// 290 */ + + RSEG CODE:CODE:NOROOT(1) +// 291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins) +OWI_MatchRom: +// 292 { + RCALL ?PROLOGUE4_L09 + MOVW R27:R26, R17:R16 + MOV R25, R18 +// 293 unsigned char bytesLeft = 8; + LDI R24, 8 +// 294 +// 295 // Send the MATCH ROM command. +// 296 OWI_SendByte(OWI_ROM_MATCH, pins); + MOV R17, R25 + LDI R16, 85 + RCALL OWI_SendByte +// 297 +// 298 // Do once for each byte. +// 299 while (bytesLeft > 0) { +??OWI_MatchRom_0: + CPI R24, 1 + BRCS ??OWI_MatchRom_1 +// 300 // Transmit 1 byte of the ID to match. +// 301 OWI_SendByte(*romValue++, pins); + MOV R17, R25 + LD R16, X + RCALL OWI_SendByte + ADIW R27:R26, 1 +// 302 bytesLeft--; + DEC R24 + RJMP ??OWI_MatchRom_0 +// 303 } +// 304 } +??OWI_MatchRom_1: + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 305 +// 306 +// 307 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the +// 308 * 1-Wire(R) bus. +// 309 * +// 310 * \param bitPattern A pointer to an 8 byte char array where the +// 311 * discovered identifier will be placed. When +// 312 * searching for several slaves, a copy of the +// 313 * last found identifier should be supplied in +// 314 * the array, or the search will fail. +// 315 * +// 316 * \param lastDeviation The bit position where the algorithm made a +// 317 * choice the last time it was run. This argument +// 318 * should be 0 when a search is initiated. Supplying +// 319 * the return argument of this function when calling +// 320 * repeatedly will go through the complete slave +// 321 * search. +// 322 * +// 323 * \param pin A bit-mask of the bus to perform a ROM search on. +// 324 * +// 325 * \return The last bit position where there was a discrepancy between slave +// 326 * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED +// 327 * if an error was detected (e.g. a device was connected to the bus during the +// 328 * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be +// 329 * discovered. +// 330 * +// 331 * \note See main.c for an example of how to utilize this function. +// 332 */ + + RSEG CODE:CODE:NOROOT(1) +// 333 unsigned char OWI_SearchRom(unsigned char * bitPattern, +OWI_SearchRom: +// 334 unsigned char lastDeviation, unsigned char pin) +// 335 { + RCALL ?PROLOGUE9_L09 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + REQUIRE ?Register_R7_is_cg_reg + REQUIRE ?Register_R8_is_cg_reg + MOVW R5:R4, R17:R16 + MOV R8, R18 + MOV R27, R19 +// 336 unsigned char currentBit = 1; + LDI R24, 1 +// 337 unsigned char newDeviation = 0; + LDI R26, 0 +// 338 unsigned char bitMask = 0x01; + LDI R25, 1 +// 339 unsigned char bitA; +// 340 unsigned char bitB; +// 341 +// 342 // Send SEARCH ROM command on the bus. +// 343 OWI_SendByte(OWI_ROM_SEARCH, pin); + MOV R17, R27 + LDI R16, 240 + RCALL OWI_SendByte +// 344 +// 345 // Walk through all 64 bits. +// 346 while (currentBit <= 64) { +??OWI_SearchRom_0: + CPI R24, 65 + BRCS $+2+2 + RJMP ??OWI_SearchRom_1 +// 347 // Read bit from bus twice. +// 348 bitA = OWI_ReadBit(pin); + MOV R16, R27 + RCALL OWI_ReadBit + MOV R6, R16 +// 349 bitB = OWI_ReadBit(pin); + MOV R16, R27 + RCALL OWI_ReadBit + MOV R7, R16 +// 350 +// 351 if (bitA && bitB) { + TST R6 + BREQ ??OWI_SearchRom_2 + TST R7 + BREQ ??OWI_SearchRom_2 +// 352 // Both bits 1 (Error). +// 353 newDeviation = OWI_ROM_SEARCH_FAILED; + LDI R26, 255 +// 354 return newDeviation; + MOV R16, R26 + RJMP ??OWI_SearchRom_3 +// 355 } else if (bitA ^ bitB) { +??OWI_SearchRom_2: + MOV R16, R7 + EOR R16, R6 + TST R16 + BREQ ??OWI_SearchRom_4 +// 356 // Bits A and B are different. All devices have the same bit here. +// 357 // Set the bit in bitPattern to this value. +// 358 if (bitA) { + TST R6 + BREQ ??OWI_SearchRom_5 +// 359 (*bitPattern) |= bitMask; + MOVW R31:R30, R5:R4 + LD R16, Z + OR R16, R25 + ST Z, R16 + RJMP ??OWI_SearchRom_6 +// 360 } else { +// 361 (*bitPattern) &= ~bitMask; +??OWI_SearchRom_5: + MOV R16, R25 + COM R16 + MOVW R31:R30, R5:R4 + LD R17, Z + AND R17, R16 + ST Z, R17 + RJMP ??OWI_SearchRom_6 +// 362 } +// 363 } else { +// 364 // If this is where a choice was made the last time, +// 365 // a '1' bit is selected this time. +// 366 if (currentBit == lastDeviation) { +??OWI_SearchRom_4: + CP R24, R8 + BRNE ??OWI_SearchRom_7 +// 367 (*bitPattern) |= bitMask; + MOVW R31:R30, R5:R4 + LD R16, Z + OR R16, R25 + ST Z, R16 + RJMP ??OWI_SearchRom_6 +// 368 } +// 369 +// 370 // For the rest of the id, '0' bits are selected when +// 371 // discrepancies occur. +// 372 else if (currentBit > lastDeviation) { +??OWI_SearchRom_7: + CP R8, R24 + BRCC ??OWI_SearchRom_8 +// 373 (*bitPattern) &= ~bitMask; + MOV R16, R25 + COM R16 + MOVW R31:R30, R5:R4 + LD R17, Z + AND R17, R16 + ST Z, R17 +// 374 newDeviation = currentBit; + MOV R26, R24 + RJMP ??OWI_SearchRom_6 +// 375 } +// 376 +// 377 // If current bit in bit pattern = 0, then this is +// 378 // out new deviation. +// 379 else if ( !(*bitPattern & bitMask)) { +??OWI_SearchRom_8: + MOVW R31:R30, R5:R4 + LD R16, Z + AND R16, R25 + TST R16 + BRNE ??OWI_SearchRom_6 +// 380 newDeviation = currentBit; + MOV R26, R24 +// 381 } +// 382 +// 383 // IF the bit is already 1, do nothing. +// 384 else { +// 385 } +// 386 } +// 387 +// 388 // Send the selected bit to the bus. +// 389 if ((*bitPattern) & bitMask) { +??OWI_SearchRom_6: + MOVW R31:R30, R5:R4 + LD R16, Z + AND R16, R25 + TST R16 + BREQ ??OWI_SearchRom_9 +// 390 OWI_WriteBit1(pin); + MOV R16, R27 + RCALL OWI_WriteBit1 + RJMP ??OWI_SearchRom_10 +// 391 } else { +// 392 OWI_WriteBit0(pin); +??OWI_SearchRom_9: + MOV R16, R27 + RCALL OWI_WriteBit0 +// 393 } +// 394 +// 395 // Increment current bit. +// 396 currentBit++; +??OWI_SearchRom_10: + INC R24 +// 397 +// 398 // Adjust bitMask and bitPattern pointer. +// 399 bitMask <<= 1; + LSL R25 +// 400 if (!bitMask) { + TST R25 + BREQ $+2+2 + RJMP ??OWI_SearchRom_0 +// 401 bitMask = 0x01; + LDI R25, 1 +// 402 bitPattern++; + LDI R16, 1 + ADD R4, R16 + LDI R16, 0 + ADC R5, R16 + RJMP ??OWI_SearchRom_0 +// 403 } +// 404 } +// 405 +// 406 return newDeviation; +??OWI_SearchRom_1: + MOV R16, R26 +??OWI_SearchRom_3: + LDI R30, 9 + RJMP ?EPILOGUE_B9_L09 +// 407 } +// 408 +// 409 +// 410 /* Functions for handling CRC */ +// 411 /*! \brief Compute the CRC8 value of a data set. +// 412 * +// 413 * This function will compute the CRC8 or DOW-CRC of inData using seed +// 414 * as inital value for the CRC. +// 415 * +// 416 * \param inData One byte of data to compute CRC from. +// 417 * +// 418 * \param seed The starting value of the CRC. +// 419 * +// 420 * \return The CRC8 of inData with seed as initial value. +// 421 * +// 422 * \note Setting seed to 0 computes the crc8 of the inData. +// 423 * +// 424 * \note Constantly passing the return value of this function +// 425 * As the seed argument computes the CRC8 value of a +// 426 * longer string of data. +// 427 */ + + RSEG CODE:CODE:NOROOT(1) +// 428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) +OWI_ComputeCRC8: +// 429 { + MOV R19, R16 + MOV R16, R17 +// 430 unsigned char bitsLeft; +// 431 unsigned char temp; +// 432 +// 433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + LDI R17, 8 +??OWI_ComputeCRC8_0: + CPI R17, 1 + BRCS ??OWI_ComputeCRC8_1 +// 434 temp = ((seed ^ inData) & 0x01); + MOV R21, R16 + ANDI R21, 0x01 + MOV R18, R19 + ANDI R18, 0x01 + EOR R18, R21 + ANDI R18, 0x01 + MOV R20, R18 +// 435 +// 436 if (temp == 0) { + TST R20 + BRNE ??OWI_ComputeCRC8_2 +// 437 seed >>= 1; + LSR R16 + RJMP ??OWI_ComputeCRC8_3 +// 438 } else { +// 439 seed ^= 0x18; +??OWI_ComputeCRC8_2: + LDI R18, 24 + EOR R16, R18 +// 440 seed >>= 1; + LSR R16 +// 441 seed |= 0x80; + ORI R16, 0x80 + LDI R18, 1 +// 442 } +// 443 +// 444 inData >>= 1; +??OWI_ComputeCRC8_3: + LSR R19 +// 445 } + DEC R17 + RJMP ??OWI_ComputeCRC8_0 +// 446 return seed; +??OWI_ComputeCRC8_1: + RET +// 447 } +// 448 +// 449 +// 450 /*! \brief Compute the CRC16 value of a data set. +// 451 * +// 452 * This function will compute the CRC16 of inData using seed +// 453 * as inital value for the CRC. +// 454 * +// 455 * \param inData One byte of data to compute CRC from. +// 456 * +// 457 * \param seed The starting value of the CRC. +// 458 * +// 459 * \return The CRC16 of inData with seed as initial value. +// 460 * +// 461 * \note Setting seed to 0 computes the crc16 of the inData. +// 462 * +// 463 * \note Constantly passing the return value of this function +// 464 * As the seed argument computes the CRC16 value of a +// 465 * longer string of data. +// 466 */ + + RSEG CODE:CODE:NOROOT(1) +// 467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) +OWI_ComputeCRC16: +// 468 { + MOV R21, R16 +// 469 unsigned char bitsLeft; +// 470 unsigned char temp; +// 471 +// 472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + LDI R20, 8 +??OWI_ComputeCRC16_0: + CPI R20, 1 + BRCS ??OWI_ComputeCRC16_1 +// 473 temp = ((seed ^ inData) & 0x01); + MOV R17, R18 + ANDI R17, 0x01 + MOV R16, R21 + ANDI R16, 0x01 + EOR R16, R17 + ANDI R16, 0x01 + MOV R22, R16 +// 474 +// 475 if (temp == 0) { + TST R22 + BRNE ??OWI_ComputeCRC16_2 +// 476 seed >>= 1; + LSR R19 + ROR R18 + RJMP ??OWI_ComputeCRC16_3 +// 477 } else { +// 478 seed ^= 0x4002; +??OWI_ComputeCRC16_2: + LDI R16, 2 + LDI R17, 64 + EOR R18, R16 + EOR R19, R17 +// 479 seed >>= 1; + LSR R19 + ROR R18 +// 480 seed |= 0x8000; + ORI R19, 0x80 + LDI R16, 1 + LDI R17, 0 +// 481 } +// 482 +// 483 inData >>= 1; +??OWI_ComputeCRC16_3: + LSR R21 +// 484 } + DEC R20 + RJMP ??OWI_ComputeCRC16_0 +// 485 +// 486 return seed; +??OWI_ComputeCRC16_1: + MOVW R17:R16, R19:R18 + RET +// 487 } +// 488 +// 489 +// 490 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier. +// 491 * +// 492 * This function computes the CRC8 value of the first 56 bits of a +// 493 * 64 bit identifier. It then checks the calculated value against the +// 494 * CRC value stored in ROM. +// 495 * +// 496 * \param *romValue A pointer to an array holding a 64 bit identifier. +// 497 * +// 498 * \retval OWI_CRC_OK The CRC's matched. +// 499 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. +// 500 */ + + RSEG CODE:CODE:NOROOT(1) +// 501 unsigned char OWI_CheckRomCRC(unsigned char *romValue) +OWI_CheckRomCRC: +// 502 { + RCALL ?PROLOGUE4_L09 + MOVW R27:R26, R17:R16 +// 503 unsigned char i; +// 504 unsigned char crc8 = 0; + LDI R25, 0 +// 505 +// 506 for (i = 0; i < 7; i++) { + LDI R24, 0 +??OWI_CheckRomCRC_0: + CPI R24, 7 + BRCC ??OWI_CheckRomCRC_1 +// 507 crc8 = OWI_ComputeCRC8(*romValue, crc8); + MOV R17, R25 + MOVW R31:R30, R27:R26 + LD R16, Z + RCALL OWI_ComputeCRC8 + MOV R25, R16 +// 508 romValue++; + ADIW R27:R26, 1 +// 509 } + INC R24 + RJMP ??OWI_CheckRomCRC_0 +// 510 +// 511 if (crc8 == (*romValue)) { +??OWI_CheckRomCRC_1: + LD R16, X + CP R25, R16 + BRNE ??OWI_CheckRomCRC_2 +// 512 return OWI_CRC_OK; + LDI R16, 0 + RJMP ??OWI_CheckRomCRC_3 +// 513 } +// 514 +// 515 return OWI_CRC_ERROR; +??OWI_CheckRomCRC_2: + LDI R16, 1 +??OWI_CheckRomCRC_3: + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 516 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// +// 3 bytes in segment ABSOLUTE +// 820 bytes in segment CODE +// +// 820 bytes of CODE memory +// 0 bytes of DATA memory (+ 3 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/PWM.lst b/BaseTinyFirmware/IAR/Debug/List/PWM.lst new file mode 100644 index 0000000..f58fee0 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/PWM.lst @@ -0,0 +1,400 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c --cpu=tiny861 # +# -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ # +# -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB # +# C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ # +# --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\PWM.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\PWM.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for use of PWM + 6 * + 7 * Contains functions for initializing and controlling PWM output. + 8 * + 9 * \par Application note: + 10 * AVR458: Charging Li-Ion Batteries with BC100\n + 11 * AVR463: Charging NiMH Batteries with BC100 + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2299 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $ + 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 #include + + \ In segment ABSOLUTE, at 0x50 + \ volatile __io _A_TCCR1A + \ _A_TCCR1A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4f + \ volatile __io _A_TCCR1B + \ _A_TCCR1B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4d + \ volatile __io _A_OCR1A + \ _A_OCR1A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4c + \ volatile __io _A_OCR1B + \ _A_OCR1B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4b + \ volatile __io _A_OCR1C + \ _A_OCR1C: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4a + \ volatile __io _A_OCR1D + \ _A_OCR1D: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x49 + \ volatile __io _A_PLLCSR + \ _A_PLLCSR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x47 + \ volatile __io _A_TCCR1C + \ _A_TCCR1C: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x46 + \ volatile __io _A_TCCR1D + \ _A_TCCR1D: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x44 + \ volatile __io _A_DT1 + \ _A_DT1: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x37 + \ volatile __io _A_DDRB + \ _A_DDRB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x20 + \ volatile __io _A_TCCR1E + \ _A_TCCR1E: + \ 00000000 DS 1 + 30 + 31 #include "enums.h" + 32 + 33 #include "main.h" + 34 #include "PWM.h" + 35 #include "time.h" + 36 + 37 + 38 //****************************************************************************** + 39 // Functions + 40 //****************************************************************************** + 41 /*! \brief Stops PWM output + 42 * + 43 */ + + \ In segment CODE, align 2, keep-with-next + 44 void PWM_Stop(void) + \ PWM_Stop: + 45 { + 46 OCR1B = 0; // Reset compare level. + \ 00000000 E000 LDI R16, 0 + \ 00000002 BD0C OUT 0x2C, R16 + 47 PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode. + \ 00000004 E000 LDI R16, 0 + \ 00000006 BD09 OUT 0x29, R16 + 48 TCCR1A = 0; // Set normal port operation, disable PWM modes. + \ 00000008 E000 LDI R16, 0 + \ 0000000A BF00 OUT 0x30, R16 + 49 TCCR1B = 0; // Stop timer/counter1. + \ 0000000C E000 LDI R16, 0 + \ 0000000E BD0F OUT 0x2F, R16 + 50 TCCR1C = 0; // Set normal port operation. + \ 00000010 E000 LDI R16, 0 + \ 00000012 BD07 OUT 0x27, R16 + 51 TCCR1D = 0; // No fault protection, normal waveform. + \ 00000014 E000 LDI R16, 0 + \ 00000016 BD06 OUT 0x26, R16 + 52 OCR1C = 0; // Reset compare. + \ 00000018 E000 LDI R16, 0 + \ 0000001A BD0B OUT 0x2B, R16 + 53 OCR1D = 0; // Reset compare. + \ 0000001C E000 LDI R16, 0 + \ 0000001E BD0A OUT 0x2A, R16 + 54 DT1 = 0; // No dead time values. + \ 00000020 E000 LDI R16, 0 + \ 00000022 BD04 OUT 0x24, R16 + 55 } + \ 00000024 9508 RET + \ 00000026 REQUIRE _A_TCCR1A + \ 00000026 REQUIRE _A_TCCR1B + \ 00000026 REQUIRE _A_OCR1B + \ 00000026 REQUIRE _A_OCR1C + \ 00000026 REQUIRE _A_OCR1D + \ 00000026 REQUIRE _A_PLLCSR + \ 00000026 REQUIRE _A_TCCR1C + \ 00000026 REQUIRE _A_TCCR1D + \ 00000026 REQUIRE _A_DT1 + 56 + 57 + 58 /*! \brief Initializes and starts PWM output + 59 * + 60 * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n + 61 * Its comparator is connected to PB3 and will output high until timer1 reaches + 62 * the value of OCR1B. It is then dropped to 0.\n + 63 * The comparator outputs high again when the counter overflows, which will + 64 * happen at a rate of 250 kHz. + 65 */ + + \ In segment CODE, align 2, keep-with-next + 66 void PWM_Start(void) + \ PWM_Start: + 67 { + 68 // Clear OC1B on compare match, enable PWM on comparator OCR1B. + 69 TCCR1A = (1< 0) { + \ 00000000 B50C IN R16, 0x2C + \ 00000002 3001 CPI R16, 1 + \ 00000004 F028 BRCS ??PWM_DecrementDutyCycle_0 + 145 OCR1B -= 1; + \ 00000006 B50C IN R16, 0x2C + \ 00000008 950A DEC R16 + \ 0000000A BD0C OUT 0x2C, R16 + 146 return(TRUE); + \ 0000000C E001 LDI R16, 1 + \ 0000000E 9508 RET + 147 } else { + 148 return(FALSE); + \ ??PWM_DecrementDutyCycle_0: + \ 00000010 E000 LDI R16, 0 + \ 00000012 9508 RET + \ 00000014 REQUIRE _A_OCR1B + 149 } + 150 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + PWM_DecrementDutyCycle 0 2 + PWM_IncrementDutyCycle 0 2 + PWM_Start 0 2 + -> Time_Set 0 2 + -> Time_Left 0 2 + PWM_Stop 0 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_TCCR1A 1 + _A_TCCR1B 1 + _A_OCR1A 1 + _A_OCR1B 1 + _A_OCR1C 1 + _A_OCR1D 1 + _A_PLLCSR 1 + _A_TCCR1C 1 + _A_TCCR1D 1 + _A_DT1 1 + _A_DDRB 1 + _A_TCCR1E 1 + PWM_Stop 38 + PWM_Start 90 + PWM_IncrementDutyCycle 20 + PWM_DecrementDutyCycle 20 + + + 12 bytes in segment ABSOLUTE + 168 bytes in segment CODE + + 168 bytes of CODE memory + 0 bytes of DATA memory (+ 12 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/PWM.s90 b/BaseTinyFirmware/IAR/Debug/List/PWM.s90 new file mode 100644 index 0000000..ce1e31a --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/PWM.s90 @@ -0,0 +1,409 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\PWM.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME PWM + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + PUBLIC PWM_DecrementDutyCycle + PUBLIC PWM_IncrementDutyCycle + PUBLIC PWM_Start + PUBLIC PWM_Stop + PUBWEAK _A_DDRB + PUBWEAK _A_DT1 + PUBWEAK _A_OCR1A + PUBWEAK _A_OCR1B + PUBWEAK _A_OCR1C + PUBWEAK _A_OCR1D + PUBWEAK _A_PLLCSR + PUBWEAK _A_TCCR1A + PUBWEAK _A_TCCR1B + PUBWEAK _A_TCCR1C + PUBWEAK _A_TCCR1D + PUBWEAK _A_TCCR1E + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN Time_Set + EXTERN Time_Left + +// C:\home\kevin\pub\src\bc100_cal\IAR\PWM.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for use of PWM +// 6 * +// 7 * Contains functions for initializing and controlling PWM output. +// 8 * +// 9 * \par Application note: +// 10 * AVR458: Charging Li-Ion Batteries with BC100\n +// 11 * AVR463: Charging NiMH Batteries with BC100 +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2299 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $ +// 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 #include + + ASEGN ABSOLUTE:DATA:NOROOT,050H +// volatile __io _A_TCCR1A +_A_TCCR1A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04fH +// volatile __io _A_TCCR1B +_A_TCCR1B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04dH +// volatile __io _A_OCR1A +_A_OCR1A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04cH +// volatile __io _A_OCR1B +_A_OCR1B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04bH +// volatile __io _A_OCR1C +_A_OCR1C: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04aH +// volatile __io _A_OCR1D +_A_OCR1D: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,049H +// volatile __io _A_PLLCSR +_A_PLLCSR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,047H +// volatile __io _A_TCCR1C +_A_TCCR1C: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,046H +// volatile __io _A_TCCR1D +_A_TCCR1D: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,044H +// volatile __io _A_DT1 +_A_DT1: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,037H +// volatile __io _A_DDRB +_A_DDRB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,020H +// volatile __io _A_TCCR1E +_A_TCCR1E: + DS 1 +// 30 +// 31 #include "enums.h" +// 32 +// 33 #include "main.h" +// 34 #include "PWM.h" +// 35 #include "time.h" +// 36 +// 37 +// 38 //****************************************************************************** +// 39 // Functions +// 40 //****************************************************************************** +// 41 /*! \brief Stops PWM output +// 42 * +// 43 */ + + RSEG CODE:CODE:NOROOT(1) +// 44 void PWM_Stop(void) +PWM_Stop: +// 45 { +// 46 OCR1B = 0; // Reset compare level. + LDI R16, 0 + OUT 0x2C, R16 +// 47 PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode. + LDI R16, 0 + OUT 0x29, R16 +// 48 TCCR1A = 0; // Set normal port operation, disable PWM modes. + LDI R16, 0 + OUT 0x30, R16 +// 49 TCCR1B = 0; // Stop timer/counter1. + LDI R16, 0 + OUT 0x2F, R16 +// 50 TCCR1C = 0; // Set normal port operation. + LDI R16, 0 + OUT 0x27, R16 +// 51 TCCR1D = 0; // No fault protection, normal waveform. + LDI R16, 0 + OUT 0x26, R16 +// 52 OCR1C = 0; // Reset compare. + LDI R16, 0 + OUT 0x2B, R16 +// 53 OCR1D = 0; // Reset compare. + LDI R16, 0 + OUT 0x2A, R16 +// 54 DT1 = 0; // No dead time values. + LDI R16, 0 + OUT 0x24, R16 +// 55 } + RET + REQUIRE _A_TCCR1A + REQUIRE _A_TCCR1B + REQUIRE _A_OCR1B + REQUIRE _A_OCR1C + REQUIRE _A_OCR1D + REQUIRE _A_PLLCSR + REQUIRE _A_TCCR1C + REQUIRE _A_TCCR1D + REQUIRE _A_DT1 +// 56 +// 57 +// 58 /*! \brief Initializes and starts PWM output +// 59 * +// 60 * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n +// 61 * Its comparator is connected to PB3 and will output high until timer1 reaches +// 62 * the value of OCR1B. It is then dropped to 0.\n +// 63 * The comparator outputs high again when the counter overflows, which will +// 64 * happen at a rate of 250 kHz. +// 65 */ + + RSEG CODE:CODE:NOROOT(1) +// 66 void PWM_Start(void) +PWM_Start: +// 67 { +// 68 // Clear OC1B on compare match, enable PWM on comparator OCR1B. +// 69 TCCR1A = (1< 0) { + IN R16, 0x2C + CPI R16, 1 + BRCS ??PWM_DecrementDutyCycle_0 +// 145 OCR1B -= 1; + IN R16, 0x2C + DEC R16 + OUT 0x2C, R16 +// 146 return(TRUE); + LDI R16, 1 + RET +// 147 } else { +// 148 return(FALSE); +??PWM_DecrementDutyCycle_0: + LDI R16, 0 + RET + REQUIRE _A_OCR1B +// 149 } +// 150 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// +// 12 bytes in segment ABSOLUTE +// 168 bytes in segment CODE +// +// 168 bytes of CODE memory +// 0 bytes of DATA memory (+ 12 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/USI.lst b/BaseTinyFirmware/IAR/Debug/List/USI.lst new file mode 100644 index 0000000..13a0e12 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/USI.lst @@ -0,0 +1,779 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\USI.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\USI.c --cpu=tiny861 # +# -ms -o C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\ # +# -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ -lB # +# C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\ # +# --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\USI.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\USI.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\USI.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for use of the Universal Serial Interface + 6 * + 7 * Contains high level functions for initializing the USI as an SPI slave, + 8 * interrupt handling, sending and receiving single bytes. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 * + 14 * \par Documentation: + 15 * For comprehensive code documentation, supported compilers, compiler + 16 * settings and supported devices see readme.html + 17 * + 18 * \author + 19 * Atmel Corporation: http://www.atmel.com \n + 20 * Support email: avr@atmel.com \n + 21 * Original author: \n + 22 * + 23 * $Name$ + 24 * $Revision: 2299 $ + 25 * $RCSfile$ + 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $ + 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 28 ******************************************************************************/ + 29 + 30 #include + + \ In segment ABSOLUTE, at 0x38 + \ volatile __io _A_PORTB + \ _A_PORTB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x37 + \ volatile __io _A_DDRB + \ _A_DDRB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x2f + \ volatile __io _A_USIDR + \ _A_USIDR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x2e + \ volatile __io _A_USISR + \ _A_USISR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x2d + \ volatile __io _A_USICR + \ _A_USICR: + \ 00000000 DS 1 + 31 #include + 32 + 33 #include "enums.h" + 34 #include "structs.h" + 35 + 36 #include "main.h" + 37 #include "ADC.h" + 38 #include "battery.h" + 39 #include "time.h" + 40 #include "USI.h" + 41 + 42 + 43 //****************************************************************************** + 44 // Variables + 45 //****************************************************************************** + 46 //! SPI status struct + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 47 SPI_Status_t SPI; + \ SPI: + \ 00000000 DS 4 + 48 + 49 + 50 //****************************************************************************** + 51 //Functions + 52 //***************************************************************************** + 53 /*! \brief USI Counter Overflow Interrupt Service Routine + 54 * + 55 * When the USI counter overflows, a byte has been transferred.\n + 56 * The USIDR contents are stored and flags are updated. + 57 * + 58 * The protocol is quite simple and has three sequential states: command, + 59 * address and data. + 60 * (Keep in mind that the Master is in charge of data clocking, which means + 61 * there is a one byte "delay" from when the Slave puts something to SPI till + 62 * the Master can read it.) + 63 * + 64 * 1. If a non-zero byte is received in the command state, the ISR will + 65 * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of + 66 * bytes). To signal that the command was received, 0xCC is put to the SPI bus. + 67 * If a zero byte (0x00) is received in the command state, it is simply ignored + 68 * because it is an invalid command. + 69 * + 70 * 2. When a byte is received in the address state, it is stored to the SPI + 71 * struct. To signal that the address was received, 0xBB is put to SPI bus. + 72 * + 73 * 3. In the data state, variables are read/written "from back to front" until + 74 * the byte counter reaches zero. Since the Master is in charge of the data + 75 * clocking, the Slave will go to command state before the last byte is + 76 * transferred during reading. This means that the Master should send an + 77 * invalid command when getting each byte, ie 0x00. + 78 * + 79 * If the time between two transfers is 1 second or more, the Slave + 80 * automatically reverts to command state. + 81 * + 82 * \note Battery charging is not automatically halted during SPI communication. + 83 * This means that the current charge state (current and voltage) will + 84 * remain constant during heavy and prolonged serial traffic. + 85 * + 86 * \todo Variable writing not implemented yet. + 87 * \todo EEPROM/SRAM flag doesn't really do anything with this implementation. + 88 */ + 89 #pragma vector=USI_OVF_vect + + \ In segment CODE, align 2, keep-with-next + 90 __interrupt void USI_OVF_ISR(void) + \ USI_OVF_ISR: + 91 { + \ 00000000 93AA ST -Y, R26 + \ 00000002 939A ST -Y, R25 + \ 00000004 938A ST -Y, R24 + \ 00000006 93FA ST -Y, R31 + \ 00000008 93EA ST -Y, R30 + \ 0000000A 923A ST -Y, R3 + \ 0000000C 922A ST -Y, R2 + \ 0000000E 921A ST -Y, R1 + \ 00000010 920A ST -Y, R0 + \ 00000012 937A ST -Y, R23 + \ 00000014 936A ST -Y, R22 + \ 00000016 935A ST -Y, R21 + \ 00000018 934A ST -Y, R20 + \ 0000001A 933A ST -Y, R19 + \ 0000001C 932A ST -Y, R18 + \ 0000001E 931A ST -Y, R17 + \ 00000020 930A ST -Y, R16 + \ 00000022 B7AF IN R26, 0x3F + 92 // If the communication timed out, set ST_CMD as current state. + 93 if (!Time_Left(TIMER_USI)) { + \ 00000024 E000 LDI R16, 0 + \ 00000026 .... RCALL Time_Left + \ 00000028 2300 TST R16 + \ 0000002A F431 BRNE ??USI_OVF_ISR_0 + 94 SPI.State = ST_CMD; + \ 0000002C 9100.... LDS R16, (SPI + 2) + \ 00000030 730F ANDI R16, 0x3F + \ 00000032 6400 ORI R16, 0x40 + \ 00000034 9300.... STS (SPI + 2), R16 + 95 } + 96 + 97 // Start communication timer. If further communication doesn't happen + 98 // within 1 second, the SPI communication state is reset to CMD. + 99 Time_Set(TIMER_USI, 0, 1, 0); + \ ??USI_OVF_ISR_0: + \ 00000038 E040 LDI R20, 0 + \ 0000003A E011 LDI R17, 1 + \ 0000003C E020 LDI R18, 0 + \ 0000003E E030 LDI R19, 0 + \ 00000040 E000 LDI R16, 0 + \ 00000042 .... RCALL Time_Set + 100 + 101 // Clear USI counter and flag completed transfer. + 102 USISR = (1<> 8 + \ 0000004C 8103 LDD R16, Z+3 + \ 0000004E 6004 ORI R16, 0x04 + \ 00000050 8303 STD Z+3, R16 + 104 + 105 // Process incoming data. + 106 switch(SPI.State) { + \ 00000052 9100.... LDS R16, (SPI + 2) + \ 00000056 0F00 LSL R16 + \ 00000058 1F00 ROL R16 + \ 0000005A 1F00 ROL R16 + \ 0000005C 7003 ANDI R16, 0x03 + \ 0000005E 5001 SUBI R16, 1 + \ 00000060 F039 BREQ ??USI_OVF_ISR_1 + \ 00000062 950A DEC R16 + \ 00000064 F409 BRNE $+2+2 + \ 00000066 C040 RJMP ??USI_OVF_ISR_2 + \ 00000068 950A DEC R16 + \ 0000006A F409 BRNE $+2+2 + \ 0000006C C050 RJMP ??USI_OVF_ISR_3 + \ 0000006E C0C0 RJMP ??USI_OVF_ISR_4 + 107 // A valid SPI transfer starts with a Command Byte sent by the Master. + 108 case ST_CMD: + 109 SPI.Data = USIDR; // Store the transferred byte. + \ ??USI_OVF_ISR_1: + \ 00000070 B10F IN R16, 0x0F + \ 00000072 9110.... LDS R17, SPI + \ 00000076 9300.... STS SPI, R16 + 110 + 111 // If the master sent 0, it is trying to get data. Ignore in this state. + 112 if (SPI.Data != 0) { + \ 0000007A 9100.... LDS R16, SPI + \ 0000007E 2300 TST R16 + \ 00000080 F409 BRNE $+2+2 + \ 00000082 C0B6 RJMP ??USI_OVF_ISR_4 + 113 // Does the master want to read or write? + 114 if (SPI.Data & 0x40) { + \ 00000084 .... LDI R30, LOW(SPI) + \ 00000086 .... LDI R31, (SPI) >> 8 + \ 00000088 8100 LD R16, Z + \ 0000008A FF06 SBRS R16, 6 + \ 0000008C C006 RJMP ??USI_OVF_ISR_5 + 115 SPI.Read = FALSE; + \ 0000008E .... LDI R30, LOW(SPI) + \ 00000090 .... LDI R31, (SPI) >> 8 + \ 00000092 8103 LDD R16, Z+3 + \ 00000094 7F0E ANDI R16, 0xFE + \ 00000096 8303 STD Z+3, R16 + \ 00000098 C005 RJMP ??USI_OVF_ISR_6 + 116 } else { + 117 SPI.Read = TRUE; + \ ??USI_OVF_ISR_5: + \ 0000009A .... LDI R30, LOW(SPI) + \ 0000009C .... LDI R31, (SPI) >> 8 + \ 0000009E 8103 LDD R16, Z+3 + \ 000000A0 6001 ORI R16, 0x01 + \ 000000A2 8303 STD Z+3, R16 + 118 } + 119 + 120 // From/to EEPROM or SRAM? + 121 if (SPI.Data &0x80) { + \ ??USI_OVF_ISR_6: + \ 000000A4 .... LDI R30, LOW(SPI) + \ 000000A6 .... LDI R31, (SPI) >> 8 + \ 000000A8 8100 LD R16, Z + \ 000000AA FF07 SBRS R16, 7 + \ 000000AC C006 RJMP ??USI_OVF_ISR_7 + 122 SPI.EEPROM = TRUE; + \ 000000AE .... LDI R30, LOW(SPI) + \ 000000B0 .... LDI R31, (SPI) >> 8 + \ 000000B2 8103 LDD R16, Z+3 + \ 000000B4 6002 ORI R16, 0x02 + \ 000000B6 8303 STD Z+3, R16 + \ 000000B8 C005 RJMP ??USI_OVF_ISR_8 + 123 } else { + 124 SPI.EEPROM = FALSE; + \ ??USI_OVF_ISR_7: + \ 000000BA .... LDI R30, LOW(SPI) + \ 000000BC .... LDI R31, (SPI) >> 8 + \ 000000BE 8103 LDD R16, Z+3 + \ 000000C0 7F0D ANDI R16, 0xFD + \ 000000C2 8303 STD Z+3, R16 + 125 } + 126 + 127 SPI.Count = (SPI.Data & 0x3F); // Get number of bytes to receive/send. + \ ??USI_OVF_ISR_8: + \ 000000C4 9110.... LDS R17, (SPI + 2) + \ 000000C8 7C10 ANDI R17, 0xC0 + \ 000000CA 9100.... LDS R16, SPI + \ 000000CE 730F ANDI R16, 0x3F + \ 000000D0 2B01 OR R16, R17 + \ 000000D2 9300.... STS (SPI + 2), R16 + 128 SPI.State = ST_ADDR; // The Master will send the address byte next. + \ 000000D6 9100.... LDS R16, (SPI + 2) + \ 000000DA 730F ANDI R16, 0x3F + \ 000000DC 6800 ORI R16, 0x80 + \ 000000DE 9300.... STS (SPI + 2), R16 + 129 + 130 SPI_Put(0xCC); // Signal that command was received. + \ 000000E2 EC0C LDI R16, 204 + \ 000000E4 .... RCALL SPI_Put + \ 000000E6 C084 RJMP ??USI_OVF_ISR_4 + 131 } + 132 break; + 133 + 134 + 135 case ST_ADDR: + 136 SPI.Data = USIDR; // Store the address. + \ ??USI_OVF_ISR_2: + \ 000000E8 B10F IN R16, 0x0F + \ 000000EA 9180.... LDS R24, SPI + \ 000000EE 9300.... STS SPI, R16 + 137 SPI.Address = SPI.Data; + \ 000000F2 9190.... LDS R25, (SPI + 1) + \ 000000F6 9100.... LDS R16, SPI + \ 000000FA 9300.... STS (SPI + 1), R16 + 138 SPI.State = ST_DATA; // The master will send/wait for data next. + \ 000000FE .... LDI R30, LOW(SPI) + \ 00000100 .... LDI R31, (SPI) >> 8 + \ 00000102 8102 LDD R16, Z+2 + \ 00000104 6C00 ORI R16, 0xC0 + \ 00000106 8302 STD Z+2, R16 + 139 + 140 SPI_Put(0xBB); // Signal that address was received. + \ 00000108 EB0B LDI R16, 187 + \ 0000010A .... RCALL SPI_Put + \ 0000010C C071 RJMP ??USI_OVF_ISR_4 + 141 break; + 142 + 143 + 144 // Note well: this will process at least one byte, regardless of Count. + 145 case ST_DATA: + 146 if (SPI.Count-- > 0) { + \ ??USI_OVF_ISR_3: + \ 0000010E 9100.... LDS R16, (SPI + 2) + \ 00000112 2F20 MOV R18, R16 + \ 00000114 7C20 ANDI R18, 0xC0 + \ 00000116 2F10 MOV R17, R16 + \ 00000118 951A DEC R17 + \ 0000011A 731F ANDI R17, 0x3F + \ 0000011C 2B12 OR R17, R18 + \ 0000011E 9310.... STS (SPI + 2), R17 + \ 00000122 730F ANDI R16, 0x3F + \ 00000124 3001 CPI R16, 1 + \ 00000126 F408 BRCC $+2+2 + \ 00000128 C05D RJMP ??USI_OVF_ISR_9 + 147 // Write specified variable to SPI, "back to front". + 148 if (SPI.Read) { + \ 0000012A .... LDI R30, LOW(SPI) + \ 0000012C .... LDI R31, (SPI) >> 8 + \ 0000012E 8103 LDD R16, Z+3 + \ 00000130 FF00 SBRS R16, 0 + \ 00000132 C043 RJMP ??USI_OVF_ISR_10 + 149 switch (SPI.Address) { + \ 00000134 9100.... LDS R16, (SPI + 1) + \ 00000138 5001 SUBI R16, 1 + \ 0000013A F049 BREQ ??USI_OVF_ISR_11 + \ 0000013C 950A DEC R16 + \ 0000013E F089 BREQ ??USI_OVF_ISR_12 + \ 00000140 950A DEC R16 + \ 00000142 F0C9 BREQ ??USI_OVF_ISR_13 + \ 00000144 950A DEC R16 + \ 00000146 F109 BREQ ??USI_OVF_ISR_14 + \ 00000148 950A DEC R16 + \ 0000014A F151 BREQ ??USI_OVF_ISR_15 + \ 0000014C C033 RJMP ??USI_OVF_ISR_16 + 150 case ADR_ADCS: + 151 SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count))); + \ ??USI_OVF_ISR_11: + \ 0000014E 9100.... LDS R16, (SPI + 2) + \ 00000152 730F ANDI R16, 0x3F + \ 00000154 E010 LDI R17, 0 + \ 00000156 01F8 MOVW R31:R30, R17:R16 + \ 00000158 .... SUBI R30, LOW((-(ADCS) & 0xFFFF)) + \ 0000015A .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + \ 0000015C 8100 LD R16, Z + \ 0000015E .... RCALL SPI_Put + \ 00000160 C047 RJMP ??USI_OVF_ISR_4 + 152 break; + 153 + 154 + 155 case ADR_BATTACTIVE: + 156 SPI_Put(*((unsigned char*)&BattActive + (SPI.Count))); + \ ??USI_OVF_ISR_12: + \ 00000162 9100.... LDS R16, (SPI + 2) + \ 00000166 730F ANDI R16, 0x3F + \ 00000168 E010 LDI R17, 0 + \ 0000016A 01F8 MOVW R31:R30, R17:R16 + \ 0000016C .... SUBI R30, LOW((-(BattActive) & 0xFFFF)) + \ 0000016E .... SBCI R31, (-(BattActive) & 0xFFFF) >> 8 + \ 00000170 8100 LD R16, Z + \ 00000172 .... RCALL SPI_Put + \ 00000174 C03D RJMP ??USI_OVF_ISR_4 + 157 break; + 158 + 159 + 160 case ADR_BATTDATA: + 161 SPI_Put(*((unsigned char*)&BattData + (SPI.Count))); + \ ??USI_OVF_ISR_13: + \ 00000176 9100.... LDS R16, (SPI + 2) + \ 0000017A 730F ANDI R16, 0x3F + \ 0000017C E010 LDI R17, 0 + \ 0000017E 01F8 MOVW R31:R30, R17:R16 + \ 00000180 .... SUBI R30, LOW((-(BattData) & 0xFFFF)) + \ 00000182 .... SBCI R31, (-(BattData) & 0xFFFF) >> 8 + \ 00000184 8100 LD R16, Z + \ 00000186 .... RCALL SPI_Put + \ 00000188 C033 RJMP ??USI_OVF_ISR_4 + 162 break; + 163 + 164 + 165 case ADR_BATTCTRL: + 166 SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count))); + \ ??USI_OVF_ISR_14: + \ 0000018A 9100.... LDS R16, (SPI + 2) + \ 0000018E 730F ANDI R16, 0x3F + \ 00000190 E010 LDI R17, 0 + \ 00000192 .... LDI R20, LOW(BattControl) + \ 00000194 .... LDI R21, (BattControl) >> 8 + \ 00000196 0F40 ADD R20, R16 + \ 00000198 1F51 ADC R21, R17 + \ 0000019A .... RCALL __eeget8_16 + \ 0000019C .... RCALL SPI_Put + \ 0000019E C028 RJMP ??USI_OVF_ISR_4 + 167 break; + 168 + 169 case ADR_TIMERS: + 170 SPI_Put(*((unsigned char*)&timeval + (SPI.Count))); + \ ??USI_OVF_ISR_15: + \ 000001A0 9100.... LDS R16, (SPI + 2) + \ 000001A4 730F ANDI R16, 0x3F + \ 000001A6 E010 LDI R17, 0 + \ 000001A8 01F8 MOVW R31:R30, R17:R16 + \ 000001AA .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 000001AC .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 000001AE 8100 LD R16, Z + \ 000001B0 .... RCALL SPI_Put + \ 000001B2 C01E RJMP ??USI_OVF_ISR_4 + 171 break; + 172 + 173 + 174 default: + 175 SPI_Put(0); + \ ??USI_OVF_ISR_16: + \ 000001B4 E000 LDI R16, 0 + \ 000001B6 .... RCALL SPI_Put + \ 000001B8 C01B RJMP ??USI_OVF_ISR_4 + 176 break; + 177 } + 178 } else { + 179 // Read byte from SPI + 180 SPI.Data = USIDR; + \ ??USI_OVF_ISR_10: + \ 000001BA B10F IN R16, 0x0F + \ 000001BC 9110.... LDS R17, SPI + \ 000001C0 9300.... STS SPI, R16 + 181 + 182 // ******************************************** + 183 // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED + 184 // ******************************************** + 185 + 186 // Save byte to specified variable. + 187 switch (SPI.Address) { + \ 000001C4 9100.... LDS R16, (SPI + 1) + \ 000001C8 5004 SUBI R16, 4 + \ 000001CA F491 BRNE ??USI_OVF_ISR_4 + 188 case ADR_BATTCTRL: + 189 *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data; + \ 000001CC 9100.... LDS R16, SPI + \ 000001D0 9120.... LDS R18, (SPI + 2) + \ 000001D4 732F ANDI R18, 0x3F + \ 000001D6 E030 LDI R19, 0 + \ 000001D8 .... LDI R20, LOW(BattControl) + \ 000001DA .... LDI R21, (BattControl) >> 8 + \ 000001DC 0F42 ADD R20, R18 + \ 000001DE 1F53 ADC R21, R19 + \ 000001E0 .... RCALL __eeput8_16 + \ 000001E2 C006 RJMP ??USI_OVF_ISR_4 + 190 break; + 191 + 192 + 193 default: + 194 break; + 195 } + 196 } + 197 + 198 + 199 } else { + 200 SPI.State = ST_CMD; + \ ??USI_OVF_ISR_9: + \ 000001E4 9100.... LDS R16, (SPI + 2) + \ 000001E8 730F ANDI R16, 0x3F + \ 000001EA 6400 ORI R16, 0x40 + \ 000001EC 9300.... STS (SPI + 2), R16 + 201 } + 202 break; + 203 + 204 default: // Shouldn't end up here. (Unknown SPI-state) + 205 break; + 206 } + 207 } + \ ??USI_OVF_ISR_4: + \ 000001F0 BFAF OUT 0x3F, R26 + \ 000001F2 9109 LD R16, Y+ + \ 000001F4 9119 LD R17, Y+ + \ 000001F6 9129 LD R18, Y+ + \ 000001F8 9139 LD R19, Y+ + \ 000001FA 9149 LD R20, Y+ + \ 000001FC 9159 LD R21, Y+ + \ 000001FE 9169 LD R22, Y+ + \ 00000200 9179 LD R23, Y+ + \ 00000202 9009 LD R0, Y+ + \ 00000204 9019 LD R1, Y+ + \ 00000206 9029 LD R2, Y+ + \ 00000208 9039 LD R3, Y+ + \ 0000020A 91E9 LD R30, Y+ + \ 0000020C 91F9 LD R31, Y+ + \ 0000020E 9189 LD R24, Y+ + \ 00000210 9199 LD R25, Y+ + \ 00000212 91A9 LD R26, Y+ + \ 00000214 9518 RETI + \ 00000216 REQUIRE _A_USIDR + \ 00000216 REQUIRE _A_USISR + 208 + 209 + 210 /*! \brief Initializes USI as an SPI slave + 211 * + 212 * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for + 213 * I/O and clock, and USI counter overflow interrupts enabled.\n + 214 * Also initializes the SPI status struct. + 215 * + 216 * \param spi_mode Specifies if USI should trigger on positive (0) or negative + 217 * (1) edge of clock signal + 218 * + 219 * \note Clears the stored data + 220 * + 221 * \todo Timer should reset SPI protocol on timeout + 222 */ + + \ In segment CODE, align 2, keep-with-next + 223 void SPI_Init(unsigned char spi_mode) + \ SPI_Init: + 224 { + 225 __disable_interrupt(); + \ 00000000 94F8 CLI + 226 + 227 // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. + 228 USI_DIR_REG |= (1<> 8 + \ 00000030 8113 LDD R17, Z+3 + \ 00000032 7F1E ANDI R17, 0xFE + \ 00000034 8313 STD Z+3, R17 + 239 SPI.EEPROM = FALSE; // Doesn't matter right now. + \ 00000036 .... LDI R30, LOW(SPI) + \ 00000038 .... LDI R31, (SPI) >> 8 + \ 0000003A 8113 LDD R17, Z+3 + \ 0000003C 7F1D ANDI R17, 0xFD + \ 0000003E 8313 STD Z+3, R17 + 240 SPI.Count = 0; // Doesn't matter right now. + \ 00000040 .... LDI R30, LOW(SPI) + \ 00000042 .... LDI R31, (SPI) >> 8 + \ 00000044 8112 LDD R17, Z+2 + \ 00000046 7C10 ANDI R17, 0xC0 + \ 00000048 8312 STD Z+2, R17 + 241 SPI.Address = 0; // Doesn't matter right now. + \ 0000004A E010 LDI R17, 0 + \ 0000004C 9310.... STS (SPI + 1), R17 + 242 SPI.XferComplete = FALSE; // We haven't even started a transfer yet. + \ 00000050 .... LDI R30, LOW(SPI) + \ 00000052 .... LDI R31, (SPI) >> 8 + \ 00000054 8113 LDD R17, Z+3 + \ 00000056 7F1B ANDI R17, 0xFB + \ 00000058 8313 STD Z+3, R17 + 243 SPI.WriteCollision = FALSE; // ..And therefore a collision hasn't happened. + \ 0000005A .... LDI R30, LOW(SPI) + \ 0000005C .... LDI R31, (SPI) >> 8 + \ 0000005E 8113 LDD R17, Z+3 + \ 00000060 7F17 ANDI R17, 0xF7 + \ 00000062 8313 STD Z+3, R17 + 244 + 245 __enable_interrupt(); + \ 00000064 9478 SEI + 246 } + \ 00000066 9508 RET + \ 00000068 REQUIRE _A_PORTB + \ 00000068 REQUIRE _A_DDRB + \ 00000068 REQUIRE _A_USICR + 247 + 248 + 249 // Put one byte on bus. Use this function like you would write to the SPDR + 250 // register in the native SPI module. Calling this function will prepare a + 251 // byte for the next transfer initiated by the master device. If a transfer + 252 // is in progress, this function will set the write collision flag and return + 253 // without altering the data registers. + 254 // + 255 // Returns 0 if a write collision occurred, 1 otherwise. + 256 /*! \brief Write a byte to SPI bus + 257 * + 258 * This function first checks if a transmission is in progress, and if so, flags + 259 * a write collision, and returns FALSE.\n + 260 * If a transmission is not in progress, the flags for write collision and + 261 * transfer complete are cleared, and the input byte is written to SPDR.\n + 262 * + 263 * \param val The byte to send. + 264 * + 265 * \retval FALSE A write collision happened. + 266 * \retval TRUE Byte written to SPDR. + 267 */ + + \ In segment CODE, align 2, keep-with-next + 268 unsigned char SPI_Put(unsigned char val) + \ SPI_Put: + 269 { + \ 00000000 2F10 MOV R17, R16 + 270 // Check if transmission in progress, i.e. if USI counter doesn't equal zero. + 271 // If this fails, flag a write collision and return. + 272 if((USISR & 0x0F) != 0) { + \ 00000002 B10E IN R16, 0x0E + \ 00000004 700F ANDI R16, 0x0F + \ 00000006 2300 TST R16 + \ 00000008 F039 BREQ ??SPI_Put_0 + 273 SPI.WriteCollision = TRUE; + \ 0000000A .... LDI R30, LOW(SPI) + \ 0000000C .... LDI R31, (SPI) >> 8 + \ 0000000E 8103 LDD R16, Z+3 + \ 00000010 6008 ORI R16, 0x08 + \ 00000012 8303 STD Z+3, R16 + 274 return(FALSE); + \ 00000014 E000 LDI R16, 0 + \ 00000016 9508 RET + 275 } + 276 + 277 // Reinitialize flags. + 278 SPI.XferComplete = FALSE; + \ ??SPI_Put_0: + \ 00000018 .... LDI R30, LOW(SPI) + \ 0000001A .... LDI R31, (SPI) >> 8 + \ 0000001C 8103 LDD R16, Z+3 + \ 0000001E 7F0B ANDI R16, 0xFB + \ 00000020 8303 STD Z+3, R16 + 279 SPI.WriteCollision = FALSE; + \ 00000022 .... LDI R30, LOW(SPI) + \ 00000024 .... LDI R31, (SPI) >> 8 + \ 00000026 8103 LDD R16, Z+3 + \ 00000028 7F07 ANDI R16, 0xF7 + \ 0000002A 8303 STD Z+3, R16 + 280 + 281 USIDR = val; // Put data in USI data register. + \ 0000002C B91F OUT 0x0F, R17 + 282 + 283 return (TRUE); + \ 0000002E E001 LDI R16, 1 + \ 00000030 9508 RET + \ 00000032 REQUIRE _A_USIDR + \ 00000032 REQUIRE _A_USISR + 284 } + 285 + 286 + 287 // Get one byte from bus. This function only returns the previous stored + 288 // USIDR value. The transfer complete flag is not checked. Use this function + 289 // like you would read from the SPDR register in the native SPI module. + 290 /*! \brief Get the last byte received from SPI bus + 291 * + 292 * This function simply returns the last byte stored to the SPI status struct, + 293 * without checking if a completed transfer is flagged. + 294 * + 295 * \retval SPI.Data The last byte read from SPI. + 296 */ + + \ In segment CODE, align 2, keep-with-next + 297 unsigned char SPI_Get(void) + \ SPI_Get: + 298 { + 299 return SPI.Data; + \ 00000000 9100.... LDS R16, SPI + \ 00000004 9508 RET + 300 } + 301 + 302 + 303 /*! \brief Wait for SPI transfer to complete + 304 * + 305 * This function waits for a transfer complete to be flagged. + 306 */ + + \ In segment CODE, align 2, keep-with-next + 307 void SPI_Wait(void) + \ SPI_Wait: + \ ??SPI_Wait_0: + 308 { + 309 do { // Wait for transfer complete. + 310 } while (SPI.XferComplete == FALSE); + \ 00000000 .... LDI R30, LOW(SPI) + \ 00000002 .... LDI R31, (SPI) >> 8 + \ 00000004 8103 LDD R16, Z+3 + \ 00000006 FF02 SBRS R16, 2 + \ 00000008 CFFB RJMP ??SPI_Wait_0 + 311 } + \ 0000000A 9508 RET + + \ In segment INTVEC, offset 0x10, root + \ `??USI_OVF_ISR??INTVEC 16`: + \ 00000010 .... RJMP USI_OVF_ISR + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + SPI_Get 0 2 + SPI_Init 0 2 + SPI_Put 0 2 + SPI_Wait 0 2 + USI_OVF_ISR 17 4 + -> Time_Left 17 2 + -> Time_Set 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + -> SPI_Put 17 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_PORTB 1 + _A_DDRB 1 + _A_USIDR 1 + _A_USISR 1 + _A_USICR 1 + SPI 4 + USI_OVF_ISR 534 + SPI_Init 104 + SPI_Put 50 + SPI_Get 6 + ??SPI_Wait_0 12 + ??USI_OVF_ISR??INTVEC 16 2 + Others 6 + + + 5 bytes in segment ABSOLUTE + 706 bytes in segment CODE + 6 bytes in segment INITTAB + 2 bytes in segment INTVEC + 4 bytes in segment NEAR_Z + + 706 bytes of CODE memory (+ 8 bytes shared) + 4 bytes of DATA memory (+ 5 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/USI.s90 b/BaseTinyFirmware/IAR/Debug/List/USI.s90 new file mode 100644 index 0000000..18cf029 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/USI.s90 @@ -0,0 +1,799 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\USI.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\USI.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\USI.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME USI + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?need_segment_init + EXTERN __eeget8_16 + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBWEAK `??USI_OVF_ISR??INTVEC 16` + PUBLIC SPI + PUBLIC SPI_Get + PUBLIC SPI_Init + PUBLIC SPI_Put + PUBLIC SPI_Wait + PUBLIC USI_OVF_ISR + PUBWEAK _A_DDRB + PUBWEAK _A_PORTB + PUBWEAK _A_USICR + PUBWEAK _A_USIDR + PUBWEAK _A_USISR + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + +USI_OVF_ISR SYMBOL "USI_OVF_ISR" +`??USI_OVF_ISR??INTVEC 16` SYMBOL "??INTVEC 16", USI_OVF_ISR + + EXTERN Time_Left + EXTERN Time_Set + EXTERN ADCS + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + EXTERN timeval + +// C:\home\kevin\pub\src\bc100_cal\IAR\USI.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for use of the Universal Serial Interface +// 6 * +// 7 * Contains high level functions for initializing the USI as an SPI slave, +// 8 * interrupt handling, sending and receiving single bytes. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 * +// 14 * \par Documentation: +// 15 * For comprehensive code documentation, supported compilers, compiler +// 16 * settings and supported devices see readme.html +// 17 * +// 18 * \author +// 19 * Atmel Corporation: http://www.atmel.com \n +// 20 * Support email: avr@atmel.com \n +// 21 * Original author: \n +// 22 * +// 23 * $Name$ +// 24 * $Revision: 2299 $ +// 25 * $RCSfile$ +// 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $ +// 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 28 ******************************************************************************/ +// 29 +// 30 #include + + ASEGN ABSOLUTE:DATA:NOROOT,038H +// volatile __io _A_PORTB +_A_PORTB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,037H +// volatile __io _A_DDRB +_A_DDRB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,02fH +// volatile __io _A_USIDR +_A_USIDR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,02eH +// volatile __io _A_USISR +_A_USISR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,02dH +// volatile __io _A_USICR +_A_USICR: + DS 1 +// 31 #include +// 32 +// 33 #include "enums.h" +// 34 #include "structs.h" +// 35 +// 36 #include "main.h" +// 37 #include "ADC.h" +// 38 #include "battery.h" +// 39 #include "time.h" +// 40 #include "USI.h" +// 41 +// 42 +// 43 //****************************************************************************** +// 44 // Variables +// 45 //****************************************************************************** +// 46 //! SPI status struct + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 47 SPI_Status_t SPI; +SPI: + DS 4 +// 48 +// 49 +// 50 //****************************************************************************** +// 51 //Functions +// 52 //***************************************************************************** +// 53 /*! \brief USI Counter Overflow Interrupt Service Routine +// 54 * +// 55 * When the USI counter overflows, a byte has been transferred.\n +// 56 * The USIDR contents are stored and flags are updated. +// 57 * +// 58 * The protocol is quite simple and has three sequential states: command, +// 59 * address and data. +// 60 * (Keep in mind that the Master is in charge of data clocking, which means +// 61 * there is a one byte "delay" from when the Slave puts something to SPI till +// 62 * the Master can read it.) +// 63 * +// 64 * 1. If a non-zero byte is received in the command state, the ISR will +// 65 * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of +// 66 * bytes). To signal that the command was received, 0xCC is put to the SPI bus. +// 67 * If a zero byte (0x00) is received in the command state, it is simply ignored +// 68 * because it is an invalid command. +// 69 * +// 70 * 2. When a byte is received in the address state, it is stored to the SPI +// 71 * struct. To signal that the address was received, 0xBB is put to SPI bus. +// 72 * +// 73 * 3. In the data state, variables are read/written "from back to front" until +// 74 * the byte counter reaches zero. Since the Master is in charge of the data +// 75 * clocking, the Slave will go to command state before the last byte is +// 76 * transferred during reading. This means that the Master should send an +// 77 * invalid command when getting each byte, ie 0x00. +// 78 * +// 79 * If the time between two transfers is 1 second or more, the Slave +// 80 * automatically reverts to command state. +// 81 * +// 82 * \note Battery charging is not automatically halted during SPI communication. +// 83 * This means that the current charge state (current and voltage) will +// 84 * remain constant during heavy and prolonged serial traffic. +// 85 * +// 86 * \todo Variable writing not implemented yet. +// 87 * \todo EEPROM/SRAM flag doesn't really do anything with this implementation. +// 88 */ +// 89 #pragma vector=USI_OVF_vect + + RSEG CODE:CODE:NOROOT(1) +// 90 __interrupt void USI_OVF_ISR(void) +USI_OVF_ISR: +// 91 { + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + ST -Y, R31 + ST -Y, R30 + ST -Y, R3 + ST -Y, R2 + ST -Y, R1 + ST -Y, R0 + ST -Y, R23 + ST -Y, R22 + ST -Y, R21 + ST -Y, R20 + ST -Y, R19 + ST -Y, R18 + ST -Y, R17 + ST -Y, R16 + IN R26, 0x3F +// 92 // If the communication timed out, set ST_CMD as current state. +// 93 if (!Time_Left(TIMER_USI)) { + LDI R16, 0 + RCALL Time_Left + TST R16 + BRNE ??USI_OVF_ISR_0 +// 94 SPI.State = ST_CMD; + LDS R16, (SPI + 2) + ANDI R16, 0x3F + ORI R16, 0x40 + STS (SPI + 2), R16 +// 95 } +// 96 +// 97 // Start communication timer. If further communication doesn't happen +// 98 // within 1 second, the SPI communication state is reset to CMD. +// 99 Time_Set(TIMER_USI, 0, 1, 0); +??USI_OVF_ISR_0: + LDI R20, 0 + LDI R17, 1 + LDI R18, 0 + LDI R19, 0 + LDI R16, 0 + RCALL Time_Set +// 100 +// 101 // Clear USI counter and flag completed transfer. +// 102 USISR = (1<> 8 + LDD R16, Z+3 + ORI R16, 0x04 + STD Z+3, R16 +// 104 +// 105 // Process incoming data. +// 106 switch(SPI.State) { + LDS R16, (SPI + 2) + LSL R16 + ROL R16 + ROL R16 + ANDI R16, 0x03 + SUBI R16, 1 + BREQ ??USI_OVF_ISR_1 + DEC R16 + BRNE $+2+2 + RJMP ??USI_OVF_ISR_2 + DEC R16 + BRNE $+2+2 + RJMP ??USI_OVF_ISR_3 + RJMP ??USI_OVF_ISR_4 +// 107 // A valid SPI transfer starts with a Command Byte sent by the Master. +// 108 case ST_CMD: +// 109 SPI.Data = USIDR; // Store the transferred byte. +??USI_OVF_ISR_1: + IN R16, 0x0F + LDS R17, SPI + STS SPI, R16 +// 110 +// 111 // If the master sent 0, it is trying to get data. Ignore in this state. +// 112 if (SPI.Data != 0) { + LDS R16, SPI + TST R16 + BRNE $+2+2 + RJMP ??USI_OVF_ISR_4 +// 113 // Does the master want to read or write? +// 114 if (SPI.Data & 0x40) { + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LD R16, Z + SBRS R16, 6 + RJMP ??USI_OVF_ISR_5 +// 115 SPI.Read = FALSE; + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ANDI R16, 0xFE + STD Z+3, R16 + RJMP ??USI_OVF_ISR_6 +// 116 } else { +// 117 SPI.Read = TRUE; +??USI_OVF_ISR_5: + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ORI R16, 0x01 + STD Z+3, R16 +// 118 } +// 119 +// 120 // From/to EEPROM or SRAM? +// 121 if (SPI.Data &0x80) { +??USI_OVF_ISR_6: + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LD R16, Z + SBRS R16, 7 + RJMP ??USI_OVF_ISR_7 +// 122 SPI.EEPROM = TRUE; + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ORI R16, 0x02 + STD Z+3, R16 + RJMP ??USI_OVF_ISR_8 +// 123 } else { +// 124 SPI.EEPROM = FALSE; +??USI_OVF_ISR_7: + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ANDI R16, 0xFD + STD Z+3, R16 +// 125 } +// 126 +// 127 SPI.Count = (SPI.Data & 0x3F); // Get number of bytes to receive/send. +??USI_OVF_ISR_8: + LDS R17, (SPI + 2) + ANDI R17, 0xC0 + LDS R16, SPI + ANDI R16, 0x3F + OR R16, R17 + STS (SPI + 2), R16 +// 128 SPI.State = ST_ADDR; // The Master will send the address byte next. + LDS R16, (SPI + 2) + ANDI R16, 0x3F + ORI R16, 0x80 + STS (SPI + 2), R16 +// 129 +// 130 SPI_Put(0xCC); // Signal that command was received. + LDI R16, 204 + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 131 } +// 132 break; +// 133 +// 134 +// 135 case ST_ADDR: +// 136 SPI.Data = USIDR; // Store the address. +??USI_OVF_ISR_2: + IN R16, 0x0F + LDS R24, SPI + STS SPI, R16 +// 137 SPI.Address = SPI.Data; + LDS R25, (SPI + 1) + LDS R16, SPI + STS (SPI + 1), R16 +// 138 SPI.State = ST_DATA; // The master will send/wait for data next. + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+2 + ORI R16, 0xC0 + STD Z+2, R16 +// 139 +// 140 SPI_Put(0xBB); // Signal that address was received. + LDI R16, 187 + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 141 break; +// 142 +// 143 +// 144 // Note well: this will process at least one byte, regardless of Count. +// 145 case ST_DATA: +// 146 if (SPI.Count-- > 0) { +??USI_OVF_ISR_3: + LDS R16, (SPI + 2) + MOV R18, R16 + ANDI R18, 0xC0 + MOV R17, R16 + DEC R17 + ANDI R17, 0x3F + OR R17, R18 + STS (SPI + 2), R17 + ANDI R16, 0x3F + CPI R16, 1 + BRCC $+2+2 + RJMP ??USI_OVF_ISR_9 +// 147 // Write specified variable to SPI, "back to front". +// 148 if (SPI.Read) { + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + SBRS R16, 0 + RJMP ??USI_OVF_ISR_10 +// 149 switch (SPI.Address) { + LDS R16, (SPI + 1) + SUBI R16, 1 + BREQ ??USI_OVF_ISR_11 + DEC R16 + BREQ ??USI_OVF_ISR_12 + DEC R16 + BREQ ??USI_OVF_ISR_13 + DEC R16 + BREQ ??USI_OVF_ISR_14 + DEC R16 + BREQ ??USI_OVF_ISR_15 + RJMP ??USI_OVF_ISR_16 +// 150 case ADR_ADCS: +// 151 SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count))); +??USI_OVF_ISR_11: + LDS R16, (SPI + 2) + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(ADCS) & 0xFFFF)) + SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + LD R16, Z + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 152 break; +// 153 +// 154 +// 155 case ADR_BATTACTIVE: +// 156 SPI_Put(*((unsigned char*)&BattActive + (SPI.Count))); +??USI_OVF_ISR_12: + LDS R16, (SPI + 2) + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(BattActive) & 0xFFFF)) + SBCI R31, (-(BattActive) & 0xFFFF) >> 8 + LD R16, Z + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 157 break; +// 158 +// 159 +// 160 case ADR_BATTDATA: +// 161 SPI_Put(*((unsigned char*)&BattData + (SPI.Count))); +??USI_OVF_ISR_13: + LDS R16, (SPI + 2) + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(BattData) & 0xFFFF)) + SBCI R31, (-(BattData) & 0xFFFF) >> 8 + LD R16, Z + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 162 break; +// 163 +// 164 +// 165 case ADR_BATTCTRL: +// 166 SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count))); +??USI_OVF_ISR_14: + LDS R16, (SPI + 2) + ANDI R16, 0x3F + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 167 break; +// 168 +// 169 case ADR_TIMERS: +// 170 SPI_Put(*((unsigned char*)&timeval + (SPI.Count))); +??USI_OVF_ISR_15: + LDS R16, (SPI + 2) + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R16, Z + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 171 break; +// 172 +// 173 +// 174 default: +// 175 SPI_Put(0); +??USI_OVF_ISR_16: + LDI R16, 0 + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 176 break; +// 177 } +// 178 } else { +// 179 // Read byte from SPI +// 180 SPI.Data = USIDR; +??USI_OVF_ISR_10: + IN R16, 0x0F + LDS R17, SPI + STS SPI, R16 +// 181 +// 182 // ******************************************** +// 183 // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED +// 184 // ******************************************** +// 185 +// 186 // Save byte to specified variable. +// 187 switch (SPI.Address) { + LDS R16, (SPI + 1) + SUBI R16, 4 + BRNE ??USI_OVF_ISR_4 +// 188 case ADR_BATTCTRL: +// 189 *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data; + LDS R16, SPI + LDS R18, (SPI + 2) + ANDI R18, 0x3F + LDI R19, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R18 + ADC R21, R19 + RCALL __eeput8_16 + RJMP ??USI_OVF_ISR_4 +// 190 break; +// 191 +// 192 +// 193 default: +// 194 break; +// 195 } +// 196 } +// 197 +// 198 +// 199 } else { +// 200 SPI.State = ST_CMD; +??USI_OVF_ISR_9: + LDS R16, (SPI + 2) + ANDI R16, 0x3F + ORI R16, 0x40 + STS (SPI + 2), R16 +// 201 } +// 202 break; +// 203 +// 204 default: // Shouldn't end up here. (Unknown SPI-state) +// 205 break; +// 206 } +// 207 } +??USI_OVF_ISR_4: + OUT 0x3F, R26 + LD R16, Y+ + LD R17, Y+ + LD R18, Y+ + LD R19, Y+ + LD R20, Y+ + LD R21, Y+ + LD R22, Y+ + LD R23, Y+ + LD R0, Y+ + LD R1, Y+ + LD R2, Y+ + LD R3, Y+ + LD R30, Y+ + LD R31, Y+ + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + RETI + REQUIRE _A_USIDR + REQUIRE _A_USISR +// 208 +// 209 +// 210 /*! \brief Initializes USI as an SPI slave +// 211 * +// 212 * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for +// 213 * I/O and clock, and USI counter overflow interrupts enabled.\n +// 214 * Also initializes the SPI status struct. +// 215 * +// 216 * \param spi_mode Specifies if USI should trigger on positive (0) or negative +// 217 * (1) edge of clock signal +// 218 * +// 219 * \note Clears the stored data +// 220 * +// 221 * \todo Timer should reset SPI protocol on timeout +// 222 */ + + RSEG CODE:CODE:NOROOT(1) +// 223 void SPI_Init(unsigned char spi_mode) +SPI_Init: +// 224 { +// 225 __disable_interrupt(); + CLI +// 226 +// 227 // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. +// 228 USI_DIR_REG |= (1<> 8 + LDD R17, Z+3 + ANDI R17, 0xFE + STD Z+3, R17 +// 239 SPI.EEPROM = FALSE; // Doesn't matter right now. + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R17, Z+3 + ANDI R17, 0xFD + STD Z+3, R17 +// 240 SPI.Count = 0; // Doesn't matter right now. + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R17, Z+2 + ANDI R17, 0xC0 + STD Z+2, R17 +// 241 SPI.Address = 0; // Doesn't matter right now. + LDI R17, 0 + STS (SPI + 1), R17 +// 242 SPI.XferComplete = FALSE; // We haven't even started a transfer yet. + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R17, Z+3 + ANDI R17, 0xFB + STD Z+3, R17 +// 243 SPI.WriteCollision = FALSE; // ..And therefore a collision hasn't happened. + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R17, Z+3 + ANDI R17, 0xF7 + STD Z+3, R17 +// 244 +// 245 __enable_interrupt(); + SEI +// 246 } + RET + REQUIRE _A_PORTB + REQUIRE _A_DDRB + REQUIRE _A_USICR +// 247 +// 248 +// 249 // Put one byte on bus. Use this function like you would write to the SPDR +// 250 // register in the native SPI module. Calling this function will prepare a +// 251 // byte for the next transfer initiated by the master device. If a transfer +// 252 // is in progress, this function will set the write collision flag and return +// 253 // without altering the data registers. +// 254 // +// 255 // Returns 0 if a write collision occurred, 1 otherwise. +// 256 /*! \brief Write a byte to SPI bus +// 257 * +// 258 * This function first checks if a transmission is in progress, and if so, flags +// 259 * a write collision, and returns FALSE.\n +// 260 * If a transmission is not in progress, the flags for write collision and +// 261 * transfer complete are cleared, and the input byte is written to SPDR.\n +// 262 * +// 263 * \param val The byte to send. +// 264 * +// 265 * \retval FALSE A write collision happened. +// 266 * \retval TRUE Byte written to SPDR. +// 267 */ + + RSEG CODE:CODE:NOROOT(1) +// 268 unsigned char SPI_Put(unsigned char val) +SPI_Put: +// 269 { + MOV R17, R16 +// 270 // Check if transmission in progress, i.e. if USI counter doesn't equal zero. +// 271 // If this fails, flag a write collision and return. +// 272 if((USISR & 0x0F) != 0) { + IN R16, 0x0E + ANDI R16, 0x0F + TST R16 + BREQ ??SPI_Put_0 +// 273 SPI.WriteCollision = TRUE; + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ORI R16, 0x08 + STD Z+3, R16 +// 274 return(FALSE); + LDI R16, 0 + RET +// 275 } +// 276 +// 277 // Reinitialize flags. +// 278 SPI.XferComplete = FALSE; +??SPI_Put_0: + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ANDI R16, 0xFB + STD Z+3, R16 +// 279 SPI.WriteCollision = FALSE; + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + ANDI R16, 0xF7 + STD Z+3, R16 +// 280 +// 281 USIDR = val; // Put data in USI data register. + OUT 0x0F, R17 +// 282 +// 283 return (TRUE); + LDI R16, 1 + RET + REQUIRE _A_USIDR + REQUIRE _A_USISR +// 284 } +// 285 +// 286 +// 287 // Get one byte from bus. This function only returns the previous stored +// 288 // USIDR value. The transfer complete flag is not checked. Use this function +// 289 // like you would read from the SPDR register in the native SPI module. +// 290 /*! \brief Get the last byte received from SPI bus +// 291 * +// 292 * This function simply returns the last byte stored to the SPI status struct, +// 293 * without checking if a completed transfer is flagged. +// 294 * +// 295 * \retval SPI.Data The last byte read from SPI. +// 296 */ + + RSEG CODE:CODE:NOROOT(1) +// 297 unsigned char SPI_Get(void) +SPI_Get: +// 298 { +// 299 return SPI.Data; + LDS R16, SPI + RET +// 300 } +// 301 +// 302 +// 303 /*! \brief Wait for SPI transfer to complete +// 304 * +// 305 * This function waits for a transfer complete to be flagged. +// 306 */ + + RSEG CODE:CODE:NOROOT(1) +// 307 void SPI_Wait(void) +SPI_Wait: +??SPI_Wait_0: +// 308 { +// 309 do { // Wait for transfer complete. +// 310 } while (SPI.XferComplete == FALSE); + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+3 + SBRS R16, 2 + RJMP ??SPI_Wait_0 +// 311 } + RET + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + COMMON INTVEC:CODE:ROOT(1) + ORG 16 +`??USI_OVF_ISR??INTVEC 16`: + RJMP USI_OVF_ISR + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 5 bytes in segment ABSOLUTE +// 706 bytes in segment CODE +// 6 bytes in segment INITTAB +// 2 bytes in segment INTVEC +// 4 bytes in segment NEAR_Z +// +// 706 bytes of CODE memory (+ 8 bytes shared) +// 4 bytes of DATA memory (+ 5 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/battery.lst b/BaseTinyFirmware/IAR/Debug/List/battery.lst new file mode 100644 index 0000000..7c7a96c --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/battery.lst @@ -0,0 +1,1220 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\battery.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\battery.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\battery.l # +# st # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\battery.r9 # +# 0 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\battery.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions related to battery control and data acquisition. + 6 * + 7 * Contains functions for enabling/disabling batteries, and looking up + 8 * their status and specifications using the ADC. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 + 14 * + 15 * \par Documentation + 16 * For comprehensive code documentation, supported compilers, compiler + 17 * settings and supported devices see readme.html + 18 * + 19 * \author + 20 * Atmel Corporation: http://www.atmel.com \n + 21 * Support email: avr@atmel.com + 22 * + 23 * + 24 * $Name$ + 25 * $Revision: 2299 $ + 26 * $RCSfile$ + 27 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $ + 28 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 29 ******************************************************************************/ + 30 + 31 #include + + \ In segment ABSOLUTE, at 0x4c + \ volatile __io _A_OCR1B + \ _A_OCR1B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x38 + \ volatile __io _A_PORTB + \ _A_PORTB: + \ 00000000 DS 1 + 32 #include + 33 + 34 #include "structs.h" + 35 #include "enums.h" + 36 + 37 #include "ADC.h" + 38 #include "battery.h" + 39 #include "main.h" + 40 #include "OWI.h" + 41 #include "time.h" + 42 + 43 #ifdef NIMH + 44 #include "NIMHspecs.h" + 45 #endif // NIMH + 46 + 47 #ifdef LIION + 48 #include "LIIONspecs.h" + 49 #endif // LIION + 50 + 51 + 52 + 53 //****************************************************************************** + 54 // Variables + 55 //****************************************************************************** + 56 /* Control-struct for batteries */ + 57 /*! \brief Holds control data for both batteries + 58 * \note Stored in EEPROM. + 59 */ + + \ In segment EEPROM_I, align 1, keep-with-next + 60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE}, + \ BattControl: + \ 00000000 0303 DB 3, 3 + 61 {TRUE, TRUE, FALSE}}; + 62 + 63 /* Data-struct for battery */ + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 64 Batteries_t BattData; //!< Holds data for the current battery + \ BattData: + \ 00000000 DS 12 + 65 + 66 + 67 /* Storage for battery EPROM */ + 68 /*! \brief Storage space for data from the batteries' own EPROMs. + 69 * \note Stored in EEPROM. + 70 */ + + \ In segment EEPROM_I, align 1, keep-with-next + 71 __eeprom unsigned char BattEEPROM[4][32]; + \ BattEEPROM: + \ 00000000 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000010 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000020 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000030 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000040 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000050 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000060 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000070 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + 72 + 73 + 74 //! Global that indicates current battery (0 = battery A, 1 = B) + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 75 unsigned char BattActive; + \ BattActive: + \ 00000000 DS 1 + 76 + 77 + 78 /*! \brief RID lookup-table + 79 * + 80 * Contains Resistor ID data specified by manufacturer. + 81 * + 82 * \note Values have been calculated assuming a +/- 15% tolerance. + 83 */ + + \ In segment NEAR_I, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 84 const RID_Lookup_t RID[RID_TABLE_SIZE] = { + \ RID: + \ 00000000 DS 56 + \ 00000038 REQUIRE `?` + 85 {558, 659, 3900, 550, 260, 300, 10}, + 86 {744, 843, 6800, 750, 360, 300, 14}, + 87 {869, 958, 10000, 1000, 475, 300, 19}, + 88 {1097, 1153, 24000, 2000, 475, 420, 38} + 89 }; + 90 + 91 + 92 /*! \brief NTC lookup-table + 93 * + 94 * The first entry is 0 degrees. For every entry after, temperature increases + 95 * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n + 96 * It must be sorted in descending ADC order. + 97 * + 98 * \note This was calculated for a Mitsubishi RH16-3H103FB NTC. + 99 * + 100 * \note NTCLookUp() must be modified if this table is changed so that: + 101 * - first entry is no longer 0 degrees. + 102 * - temperature difference between entries is no longer 4 degrees. + 103 * - ADCsteps no longer specifies ADC steps per half degree. + 104 */ + 105 // FOR VARTA POLYFLEX NTC + + \ In segment NEAR_I, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + \ NTC: + \ 00000000 DS 60 + \ 0000003C REQUIRE `?` + 107 {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27}, + 108 {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24}, + 109 {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17}, + 110 {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10} + 111 }; + 112 + 113 + 114 // FOR MITSUBISHI NTC + 115 /* + 116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + 117 {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27}, + 118 {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24}, + 119 {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17}, + 120 {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10} + 121 }; + 122 */ + 123 + 124 + 125 //****************************************************************************** + 126 // Functions + 127 //****************************************************************************** + 128 /*! \brief Checks if battery has changed + 129 * + 130 * Stores current capacity, then attempts to refresh battery status.\n + 131 * If the refresh is successful, old capacity is compared with the new one. + 132 * + 133 * \retval FALSE Battery is disconnected, or capacity has changed. + 134 * \retval TRUE All OK. + 135 */ + + \ In segment CODE, align 2, keep-with-next + 136 unsigned char BatteryCheck(void) + \ BatteryCheck: + 137 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + 138 unsigned char success = TRUE; + \ 00000002 E081 LDI R24, 1 + 139 unsigned int oldCapacity; + 140 + 141 // Save to see if battery data has changed. + 142 oldCapacity = BattData.Capacity; + \ 00000004 .... LDI R30, LOW(BattData) + \ 00000006 .... LDI R31, (BattData) >> 8 + \ 00000008 8104 LDD R16, Z+4 + \ 0000000A 8115 LDD R17, Z+5 + \ 0000000C 01D8 MOVW R27:R26, R17:R16 + 143 + 144 if (!BatteryStatusRefresh()) { + \ 0000000E .... RCALL BatteryStatusRefresh + \ 00000010 2300 TST R16 + \ 00000012 F409 BRNE ??BatteryCheck_0 + 145 success = FALSE; // Battery not present or RID was invalid. + \ 00000014 E080 LDI R24, 0 + 146 } + 147 + 148 if (oldCapacity != BattData.Capacity) { + \ ??BatteryCheck_0: + \ 00000016 .... LDI R30, LOW(BattData) + \ 00000018 .... LDI R31, (BattData) >> 8 + \ 0000001A 8104 LDD R16, Z+4 + \ 0000001C 8115 LDD R17, Z+5 + \ 0000001E 17A0 CP R26, R16 + \ 00000020 07B1 CPC R27, R17 + \ 00000022 F009 BREQ ??BatteryCheck_1 + 149 success = FALSE; // Battery configuration has changed. + \ 00000024 E080 LDI R24, 0 + 150 } + 151 + 152 return(success); + \ ??BatteryCheck_1: + \ 00000026 2F08 MOV R16, R24 + \ 00000028 E0E4 LDI R30, 4 + \ 0000002A .... RJMP ?EPILOGUE_B4_L09 + 153 } + 154 + 155 + 156 /*! \brief Refreshes battery status information + 157 * + 158 * Refreshes battery status information, if it is present, based on + 159 * RID and NTC (read by ADC).\n + 160 * The battery must have been enabled and a complete set of ADC data must have + 161 * been collected before calling.\n + 162 * + 163 * \retval FALSE No battery present. + 164 * \retval TRUE Battery present, status refreshed. + 165 * + 166 * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry + 167 * is found in the lookup table. Instead, default battery data will be used. + 168 */ + + \ In segment CODE, align 2, keep-with-next + 169 unsigned char BatteryStatusRefresh(void) + \ BatteryStatusRefresh: + 170 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + 171 // Assume the worst.. + 172 unsigned char success = FALSE; + \ 00000002 E080 LDI R24, 0 + 173 + 174 BattData.Present = FALSE; + \ 00000004 .... LDI R30, LOW(BattData) + \ 00000006 .... LDI R31, (BattData) >> 8 + \ 00000008 8100 LD R16, Z + \ 0000000A 7F0E ANDI R16, 0xFE + \ 0000000C 8300 ST Z, R16 + 175 BattData.Charged = FALSE; + \ 0000000E .... LDI R30, LOW(BattData) + \ 00000010 .... LDI R31, (BattData) >> 8 + \ 00000012 8100 LD R16, Z + \ 00000014 7F0D ANDI R16, 0xFD + \ 00000016 8300 ST Z, R16 + 176 BattData.Low = TRUE; + \ 00000018 .... LDI R30, LOW(BattData) + \ 0000001A .... LDI R31, (BattData) >> 8 + \ 0000001C 8100 LD R16, Z + \ 0000001E 6004 ORI R16, 0x04 + \ 00000020 8300 ST Z, R16 + 177 BattData.Circuit = OW_NONE; + \ 00000022 E000 LDI R16, 0 + \ 00000024 9300.... STS (BattData + 1), R16 + 178 BattData.Temperature = 0; + \ 00000028 E000 LDI R16, 0 + \ 0000002A 9300.... STS (BattData + 2), R16 + 179 BattData.Capacity = 0; + \ 0000002E E000 LDI R16, 0 + \ 00000030 E010 LDI R17, 0 + \ 00000032 .... LDI R30, LOW(BattData) + \ 00000034 .... LDI R31, (BattData) >> 8 + \ 00000036 8304 STD Z+4, R16 + \ 00000038 8315 STD Z+5, R17 + 180 BattData.MaxCurrent = 0; + \ 0000003A E000 LDI R16, 0 + \ 0000003C E010 LDI R17, 0 + \ 0000003E .... LDI R30, LOW(BattData) + \ 00000040 .... LDI R31, (BattData) >> 8 + \ 00000042 8306 STD Z+6, R16 + \ 00000044 8317 STD Z+7, R17 + 181 BattData.MaxTime = 0; + \ 00000046 E000 LDI R16, 0 + \ 00000048 E010 LDI R17, 0 + \ 0000004A .... LDI R30, LOW(BattData) + \ 0000004C .... LDI R31, (BattData) >> 8 + \ 0000004E 8700 STD Z+8, R16 + \ 00000050 8711 STD Z+9, R17 + 182 BattData.MinCurrent = 0; + \ 00000052 E000 LDI R16, 0 + \ 00000054 E010 LDI R17, 0 + \ 00000056 .... LDI R30, LOW(BattData) + \ 00000058 .... LDI R31, (BattData) >> 8 + \ 0000005A 8702 STD Z+10, R16 + \ 0000005C 8713 STD Z+11, R17 + 183 + 184 NTCLookUp(); + \ 0000005E .... RCALL NTCLookUp + 185 BattData.HasRID = RIDLookUp(); + \ 00000060 .... RCALL RIDLookUp + \ 00000062 2F10 MOV R17, R16 + \ 00000064 7011 ANDI R17, 0x01 + \ 00000066 .... LDI R30, LOW(BattData) + \ 00000068 .... LDI R31, (BattData) >> 8 + \ 0000006A FB10 BST R17, 0 + \ 0000006C 8100 LD R16, Z + \ 0000006E F904 BLD R16, 4 + \ 00000070 8300 ST Z, R16 + \ 00000072 E000 LDI R16, 0 + \ 00000074 F900 BLD R16, 0 + 186 + 187 // Is the battery voltage above minimum safe cell voltage? + 188 if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + \ 00000076 .... LDI R30, LOW(ADCS) + \ 00000078 .... LDI R31, (ADCS) >> 8 + \ 0000007A 8502 LDD R16, Z+10 + \ 0000007C 8513 LDD R17, Z+11 + \ 0000007E 3600 CPI R16, 96 + \ 00000080 E029 LDI R18, 9 + \ 00000082 0712 CPC R17, R18 + \ 00000084 F028 BRCS ??BatteryStatusRefresh_0 + 189 BattData.Low = FALSE; + \ 00000086 .... LDI R30, LOW(BattData) + \ 00000088 .... LDI R31, (BattData) >> 8 + \ 0000008A 8100 LD R16, Z + \ 0000008C 7F0B ANDI R16, 0xFB + \ 0000008E 8300 ST Z, R16 + 190 } + 191 + 192 // Is the battery charged? + 193 if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { + \ ??BatteryStatusRefresh_0: + \ 00000090 .... LDI R30, LOW(ADCS) + \ 00000092 .... LDI R31, (ADCS) >> 8 + \ 00000094 8502 LDD R16, Z+10 + \ 00000096 8513 LDD R17, Z+11 + \ 00000098 3D02 CPI R16, 210 + \ 0000009A E02F LDI R18, 15 + \ 0000009C 0712 CPC R17, R18 + \ 0000009E F028 BRCS ??BatteryStatusRefresh_1 + 194 BattData.Charged = TRUE; + \ 000000A0 .... LDI R30, LOW(BattData) + \ 000000A2 .... LDI R31, (BattData) >> 8 + \ 000000A4 8100 LD R16, Z + \ 000000A6 6002 ORI R16, 0x02 + \ 000000A8 8300 ST Z, R16 + 195 } + 196 + 197 // If we are not charging, yet VBAT is above safe limit, battery is present. + 198 // If we are charging and there's a current flowing, the battery is present. + 199 + 200 /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence + 201 * check is redundant since charging will be aborted due to low current at + 202 * max duty cycle. That is preferrable since the charge current reading is + 203 * not 100% proof. + 204 */ + 205 if (((OCR1B == 0) && (!BattData.Low)) || + 206 ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { + \ ??BatteryStatusRefresh_1: + \ 000000AA B50C IN R16, 0x2C + \ 000000AC 2300 TST R16 + \ 000000AE F429 BRNE ??BatteryStatusRefresh_2 + \ 000000B0 .... LDI R30, LOW(BattData) + \ 000000B2 .... LDI R31, (BattData) >> 8 + \ 000000B4 8100 LD R16, Z + \ 000000B6 FF02 SBRS R16, 2 + \ 000000B8 C00A RJMP ??BatteryStatusRefresh_3 + \ ??BatteryStatusRefresh_2: + \ 000000BA B50C IN R16, 0x2C + \ 000000BC 2300 TST R16 + \ 000000BE F071 BREQ ??BatteryStatusRefresh_4 + \ 000000C0 .... LDI R26, LOW((ADCS + 22)) + \ 000000C2 .... LDI R27, HIGH((ADCS + 22)) + \ 000000C4 91ED LD R30, X+ + \ 000000C6 91FC LD R31, X + \ 000000C8 9711 SBIW R27:R26, 1 + \ 000000CA 9731 SBIW R31:R30, 1 + \ 000000CC F03C BRLT ??BatteryStatusRefresh_4 + 207 BattData.Present = TRUE; + \ ??BatteryStatusRefresh_3: + \ 000000CE .... LDI R30, LOW(BattData) + \ 000000D0 .... LDI R31, (BattData) >> 8 + \ 000000D2 8100 LD R16, Z + \ 000000D4 6001 ORI R16, 0x01 + \ 000000D6 8300 ST Z, R16 + 208 success = TRUE; + \ 000000D8 E081 LDI R24, 1 + \ 000000DA C006 RJMP ??BatteryStatusRefresh_5 + 209 } else { + 210 BattData.Low = FALSE; // (This is just a technicality..) + \ ??BatteryStatusRefresh_4: + \ 000000DC .... LDI R30, LOW(BattData) + \ 000000DE .... LDI R31, (BattData) >> 8 + \ 000000E0 8100 LD R16, Z + \ 000000E2 7F0B ANDI R16, 0xFB + \ 000000E4 8300 ST Z, R16 + 211 success = FALSE; + \ 000000E6 E080 LDI R24, 0 + 212 } + 213 + 214 #ifndef ALLOW_NO_RID + 215 // Return FALSE if no valid RID entry was found, to stop charging. + 216 if(!BattData.HasRID) { + \ ??BatteryStatusRefresh_5: + \ 000000E8 .... LDI R30, LOW(BattData) + \ 000000EA .... LDI R31, (BattData) >> 8 + \ 000000EC 8100 LD R16, Z + \ 000000EE FF04 SBRS R16, 4 + 217 success = FALSE; + \ 000000F0 E080 LDI R24, 0 + 218 } + 219 #endif + 220 + 221 return(success); + \ ??BatteryStatusRefresh_6: + \ 000000F2 2F08 MOV R16, R24 + \ 000000F4 E0E4 LDI R30, 4 + \ 000000F6 .... RJMP ?EPILOGUE_B4_L09 + \ 000000F8 REQUIRE _A_OCR1B + 222 } + 223 + 224 + 225 /*! \brief Refreshes battery data in the EEPROM + 226 * + 227 * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store + 228 * these data in on-chip EEPROM.\n + 229 * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared. + 230 * + 231 * \todo Updating BattData with these data. Specs needed. + 232 * + 233 * \retval FALSE Refresh failed. + 234 * \retval TRUE Refresh successful. + 235 */ + + \ In segment CODE, align 2, keep-with-next + 236 unsigned char BatteryDataRefresh(void) + \ BatteryDataRefresh: + 237 { + \ 00000000 .... RCALL ?PROLOGUE8_L09 + \ 00000002 REQUIRE ?Register_R4_is_cg_reg + \ 00000002 REQUIRE ?Register_R5_is_cg_reg + \ 00000002 REQUIRE ?Register_R6_is_cg_reg + \ 00000002 REQUIRE ?Register_R7_is_cg_reg + 238 unsigned char offset; + 239 unsigned char i, crc, family, temp, page; + 240 unsigned char success; + 241 + 242 // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found. + 243 for (page = 0; page < 4; page++) { + \ 00000002 E090 LDI R25, 0 + \ ??BatteryDataRefresh_0: + \ 00000004 3094 CPI R25, 4 + \ 00000006 F008 BRCS $+2+2 + \ 00000008 C084 RJMP ??BatteryDataRefresh_1 + 244 success = FALSE; + \ 0000000A E0B0 LDI R27, 0 + 245 + 246 if (OWI_DetectPresence(OWIBUS) == OWIBUS) { + \ 0000000C E001 LDI R16, 1 + \ 0000000E .... RCALL OWI_DetectPresence + \ 00000010 3001 CPI R16, 1 + \ 00000012 F009 BREQ $+2+2 + \ 00000014 C065 RJMP ??BatteryDataRefresh_2 + 247 + 248 // Presence detected, check type and CRC. + 249 OWI_SendByte(OWI_ROM_READ, OWIBUS); + \ 00000016 E011 LDI R17, 1 + \ 00000018 E303 LDI R16, 51 + \ 0000001A .... RCALL OWI_SendByte + 250 family = OWI_ReceiveByte(OWIBUS); + \ 0000001C E001 LDI R16, 1 + \ 0000001E .... RCALL OWI_ReceiveByte + \ 00000020 2E60 MOV R6, R16 + 251 crc = OWI_ComputeCRC8(family,0); + \ 00000022 E010 LDI R17, 0 + \ 00000024 2D06 MOV R16, R6 + \ 00000026 .... RCALL OWI_ComputeCRC8 + \ 00000028 2E50 MOV R5, R16 + 252 + 253 for (i = 0; i < 6; i++) { + \ 0000002A E080 LDI R24, 0 + \ ??BatteryDataRefresh_3: + \ 0000002C 3086 CPI R24, 6 + \ 0000002E F438 BRCC ??BatteryDataRefresh_4 + 254 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc); + \ 00000030 E001 LDI R16, 1 + \ 00000032 .... RCALL OWI_ReceiveByte + \ 00000034 2D15 MOV R17, R5 + \ 00000036 .... RCALL OWI_ComputeCRC8 + \ 00000038 2E50 MOV R5, R16 + 255 } + \ 0000003A 9583 INC R24 + \ 0000003C CFF7 RJMP ??BatteryDataRefresh_3 + 256 + 257 // CRC ok, device found. + 258 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + \ ??BatteryDataRefresh_4: + \ 0000003E E001 LDI R16, 1 + \ 00000040 .... RCALL OWI_ReceiveByte + \ 00000042 2D15 MOV R17, R5 + \ 00000044 .... RCALL OWI_ComputeCRC8 + \ 00000046 2300 TST R16 + \ 00000048 F009 BREQ $+2+2 + \ 0000004A C04A RJMP ??BatteryDataRefresh_2 + 259 BattData.Circuit = family; + \ 0000004C 9260.... STS (BattData + 1), R6 + 260 + 261 // For now, we only read data from DS2505 EPROMs. + 262 if (BattData.Circuit == OW_DS2505) { + \ 00000050 9100.... LDS R16, (BattData + 1) + \ 00000054 3009 CPI R16, 9 + \ 00000056 F009 BREQ $+2+2 + \ 00000058 C043 RJMP ??BatteryDataRefresh_2 + 263 offset = page*32; + \ 0000005A 2F09 MOV R16, R25 + \ 0000005C 9502 SWAP R16 + \ 0000005E 7F00 ANDI R16, 0xF0 + \ 00000060 0F00 LSL R16 + \ 00000062 2E40 MOV R4, R16 + 264 OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data. + \ 00000064 E011 LDI R17, 1 + \ 00000066 EC03 LDI R16, 195 + \ 00000068 .... RCALL OWI_SendByte + 265 OWI_SendByte(offset, OWIBUS); // Data: low address. + \ 0000006A E011 LDI R17, 1 + \ 0000006C 2D04 MOV R16, R4 + \ 0000006E .... RCALL OWI_SendByte + 266 OWI_SendByte(0, OWIBUS); // Data: high address. + \ 00000070 E011 LDI R17, 1 + \ 00000072 E000 LDI R16, 0 + \ 00000074 .... RCALL OWI_SendByte + 267 + 268 // Calculate checksums. + 269 crc = OWI_ComputeCRC8(DS2505_DATA_READ,0); + \ 00000076 E010 LDI R17, 0 + \ 00000078 EC03 LDI R16, 195 + \ 0000007A .... RCALL OWI_ComputeCRC8 + \ 0000007C 2E50 MOV R5, R16 + 270 crc = OWI_ComputeCRC8(offset,crc); + \ 0000007E 2D15 MOV R17, R5 + \ 00000080 2D04 MOV R16, R4 + \ 00000082 .... RCALL OWI_ComputeCRC8 + \ 00000084 2E50 MOV R5, R16 + 271 crc = OWI_ComputeCRC8(0,crc); + \ 00000086 2D15 MOV R17, R5 + \ 00000088 E000 LDI R16, 0 + \ 0000008A .... RCALL OWI_ComputeCRC8 + \ 0000008C 2E50 MOV R5, R16 + 272 + 273 // Command received succesfully, now start reading data + 274 // and writing it to EEPROM. + 275 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + \ 0000008E E001 LDI R16, 1 + \ 00000090 .... RCALL OWI_ReceiveByte + \ 00000092 2D15 MOV R17, R5 + \ 00000094 .... RCALL OWI_ComputeCRC8 + \ 00000096 2300 TST R16 + \ 00000098 F519 BRNE ??BatteryDataRefresh_2 + 276 crc = 0; + \ 0000009A 2455 CLR R5 + 277 + 278 // Fill page with data. + 279 for (i=0; i<32; i++) { + \ 0000009C E080 LDI R24, 0 + \ ??BatteryDataRefresh_5: + \ 0000009E 3280 CPI R24, 32 + \ 000000A0 F4C0 BRCC ??BatteryDataRefresh_6 + 280 temp = OWI_ReceiveByte(OWIBUS); + \ 000000A2 E001 LDI R16, 1 + \ 000000A4 .... RCALL OWI_ReceiveByte + \ 000000A6 2E70 MOV R7, R16 + 281 crc = OWI_ComputeCRC8(temp, crc); + \ 000000A8 2D15 MOV R17, R5 + \ 000000AA 2D07 MOV R16, R7 + \ 000000AC .... RCALL OWI_ComputeCRC8 + \ 000000AE 2E50 MOV R5, R16 + 282 BattEEPROM[page][i] = temp; + \ 000000B0 2F49 MOV R20, R25 + \ 000000B2 E050 LDI R21, 0 + \ 000000B4 E200 LDI R16, 32 + \ 000000B6 E010 LDI R17, 0 + \ 000000B8 .... RCALL ?S_MUL_L02 + \ 000000BA .... LDI R20, LOW(BattEEPROM) + \ 000000BC .... LDI R21, (BattEEPROM) >> 8 + \ 000000BE 0F40 ADD R20, R16 + \ 000000C0 1F51 ADC R21, R17 + \ 000000C2 2F08 MOV R16, R24 + \ 000000C4 E010 LDI R17, 0 + \ 000000C6 0F40 ADD R20, R16 + \ 000000C8 1F51 ADC R21, R17 + \ 000000CA 2D07 MOV R16, R7 + \ 000000CC .... RCALL __eeput8_16 + 283 } + \ 000000CE 9583 INC R24 + \ 000000D0 CFE6 RJMP ??BatteryDataRefresh_5 + 284 + 285 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + \ ??BatteryDataRefresh_6: + \ 000000D2 E001 LDI R16, 1 + \ 000000D4 .... RCALL OWI_ReceiveByte + \ 000000D6 2D15 MOV R17, R5 + \ 000000D8 .... RCALL OWI_ComputeCRC8 + \ 000000DA 2300 TST R16 + \ 000000DC F409 BRNE ??BatteryDataRefresh_2 + 286 success = TRUE; // Data read OK + \ 000000DE E0B1 LDI R27, 1 + 287 } + 288 } else { // Not able to start reading data. + 289 } + 290 } else { // Wrong device type. + 291 } + 292 } else { // No device found. + 293 } + 294 } else { // No presence detected on one-wire bus. + 295 } + 296 + 297 // Erase local EEPROM page if there were any errors during transfer. + 298 if (!success) { + \ ??BatteryDataRefresh_2: + \ 000000E0 23BB TST R27 + \ 000000E2 F4A9 BRNE ??BatteryDataRefresh_7 + 299 for (i=0; i<32; i++) { + \ 000000E4 E080 LDI R24, 0 + \ ??BatteryDataRefresh_8: + \ 000000E6 3280 CPI R24, 32 + \ 000000E8 F490 BRCC ??BatteryDataRefresh_7 + 300 BattEEPROM[page][i] = 0; + \ 000000EA E0A0 LDI R26, 0 + \ 000000EC 2F49 MOV R20, R25 + \ 000000EE E050 LDI R21, 0 + \ 000000F0 E200 LDI R16, 32 + \ 000000F2 E010 LDI R17, 0 + \ 000000F4 .... RCALL ?S_MUL_L02 + \ 000000F6 .... LDI R20, LOW(BattEEPROM) + \ 000000F8 .... LDI R21, (BattEEPROM) >> 8 + \ 000000FA 0F40 ADD R20, R16 + \ 000000FC 1F51 ADC R21, R17 + \ 000000FE 2F08 MOV R16, R24 + \ 00000100 E010 LDI R17, 0 + \ 00000102 0F40 ADD R20, R16 + \ 00000104 1F51 ADC R21, R17 + \ 00000106 2F0A MOV R16, R26 + \ 00000108 .... RCALL __eeput8_16 + 301 } + \ 0000010A 9583 INC R24 + \ 0000010C CFEC RJMP ??BatteryDataRefresh_8 + 302 } + 303 } + \ ??BatteryDataRefresh_7: + \ 0000010E 9593 INC R25 + \ 00000110 CF79 RJMP ??BatteryDataRefresh_0 + 304 + 305 return(success); + \ ??BatteryDataRefresh_1: + \ 00000112 2F0B MOV R16, R27 + \ 00000114 E0E8 LDI R30, 8 + \ 00000116 .... RJMP ?EPILOGUE_B8_L09 + 306 } + 307 + 308 + 309 /*! \brief Enables specified battery + 310 * + 311 * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears + 312 * PB5/PB4 in PORTB, depending on which battery is specified.\n + 313 * The function takes 100 ms to allow the port switch to settle. + 314 * + 315 * \param bat Specifies which battery to enable (0 = battery A, 1 = B) + 316 */ + + \ In segment CODE, align 2, keep-with-next + 317 void EnableBattery(unsigned char bat) + \ EnableBattery: + 318 { + \ 00000000 938A ST -Y, R24 + \ 00000002 2F80 MOV R24, R16 + 319 // Use general timer, set timeout to 100ms. + 320 Time_Set(TIMER_GEN,0,0,100); + \ 00000004 E644 LDI R20, 100 + \ 00000006 E010 LDI R17, 0 + \ 00000008 E020 LDI R18, 0 + \ 0000000A E030 LDI R19, 0 + \ 0000000C E002 LDI R16, 2 + \ 0000000E .... RCALL Time_Set + 321 + 322 // Set specified battery as the active one. + 323 BattActive = bat; + \ 00000010 9380.... STS BattActive, R24 + 324 + 325 // Enable current battery in hardware, light LED & connect battery. + 326 PORTB |= (1 << (PB4+bat)); + \ 00000014 E001 LDI R16, 1 + \ 00000016 E010 LDI R17, 0 + \ 00000018 2F48 MOV R20, R24 + \ 0000001A 5F4C SUBI R20, 252 + \ 0000001C .... RCALL ?S_SHL_L02 + \ 0000001E B318 IN R17, 0x18 + \ 00000020 2B10 OR R17, R16 + \ 00000022 BB18 OUT 0x18, R17 + 327 + 328 // Disconnect other battery. + 329 PORTB &= ~(1<<(PB5-bat)); + \ 00000024 E001 LDI R16, 1 + \ 00000026 E010 LDI R17, 0 + \ 00000028 E045 LDI R20, 5 + \ 0000002A 1B48 SUB R20, R24 + \ 0000002C .... RCALL ?S_SHL_L02 + \ 0000002E 9500 COM R16 + \ 00000030 B318 IN R17, 0x18 + \ 00000032 2310 AND R17, R16 + \ 00000034 BB18 OUT 0x18, R17 + 330 + 331 do { // Let port switch settle. + 332 } while (Time_Left(TIMER_GEN)); + \ ??EnableBattery_0: + \ 00000036 E002 LDI R16, 2 + \ 00000038 .... RCALL Time_Left + \ 0000003A 2300 TST R16 + \ 0000003C F7E1 BRNE ??EnableBattery_0 + 333 } + \ 0000003E 9189 LD R24, Y+ + \ 00000040 9508 RET + \ 00000042 REQUIRE _A_PORTB + 334 + 335 + 336 /*! \brief Disables both batteries + 337 * + 338 * Clears PB4 and PB5 in PORTB, disabling both batteries. + 339 */ + + \ In segment CODE, align 2, keep-with-next + 340 void DisableBatteries(void) + \ DisableBatteries: + 341 { + 342 // Turn off LEDs and disconnect batteries. + 343 PORTB &= ~((1<= RID[i].Low) { + \ 0000000C .... LDI R30, LOW(ADCS) + \ 0000000E .... LDI R31, (ADCS) >> 8 + \ 00000010 81A2 LDD R26, Z+2 + \ 00000012 81B3 LDD R27, Z+3 + \ 00000014 2F48 MOV R20, R24 + \ 00000016 E050 LDI R21, 0 + \ 00000018 E00E LDI R16, 14 + \ 0000001A E010 LDI R17, 0 + \ 0000001C .... RCALL ?S_MUL_L02 + \ 0000001E 01F8 MOVW R31:R30, R17:R16 + \ 00000020 .... SUBI R30, LOW((-(RID) & 0xFFFF)) + \ 00000022 .... SBCI R31, (-(RID) & 0xFFFF) >> 8 + \ 00000024 8100 LD R16, Z + \ 00000026 8111 LDD R17, Z+1 + \ 00000028 17A0 CP R26, R16 + \ 0000002A 07B1 CPC R27, R17 + \ 0000002C F408 BRCC $+2+2 + \ 0000002E C04A RJMP ??RIDLookUp_2 + 364 if (ADCS.rawRID <= RID[i].High) { + \ 00000030 2F48 MOV R20, R24 + \ 00000032 E050 LDI R21, 0 + \ 00000034 E00E LDI R16, 14 + \ 00000036 E010 LDI R17, 0 + \ 00000038 .... RCALL ?S_MUL_L02 + \ 0000003A 01F8 MOVW R31:R30, R17:R16 + \ 0000003C .... SUBI R30, LOW((-(RID) & 0xFFFF)) + \ 0000003E .... SBCI R31, (-(RID) & 0xFFFF) >> 8 + \ 00000040 8102 LDD R16, Z+2 + \ 00000042 8113 LDD R17, Z+3 + \ 00000044 .... LDI R30, LOW(ADCS) + \ 00000046 .... LDI R31, (ADCS) >> 8 + \ 00000048 8122 LDD R18, Z+2 + \ 0000004A 8133 LDD R19, Z+3 + \ 0000004C 1702 CP R16, R18 + \ 0000004E 0713 CPC R17, R19 + \ 00000050 F1C8 BRCS ??RIDLookUp_2 + 365 BattData.Capacity = RID[i].Capacity; + \ 00000052 2F48 MOV R20, R24 + \ 00000054 E050 LDI R21, 0 + \ 00000056 E00E LDI R16, 14 + \ 00000058 E010 LDI R17, 0 + \ 0000005A .... RCALL ?S_MUL_L02 + \ 0000005C 01F8 MOVW R31:R30, R17:R16 + \ 0000005E .... SUBI R30, LOW((-(RID) & 0xFFFF)) + \ 00000060 .... SBCI R31, (-(RID) & 0xFFFF) >> 8 + \ 00000062 8106 LDD R16, Z+6 + \ 00000064 8117 LDD R17, Z+7 + \ 00000066 .... LDI R30, LOW(BattData) + \ 00000068 .... LDI R31, (BattData) >> 8 + \ 0000006A 8304 STD Z+4, R16 + \ 0000006C 8315 STD Z+5, R17 + 366 BattData.MaxCurrent = RID[i].Icharge; + \ 0000006E 2F48 MOV R20, R24 + \ 00000070 E050 LDI R21, 0 + \ 00000072 E00E LDI R16, 14 + \ 00000074 E010 LDI R17, 0 + \ 00000076 .... RCALL ?S_MUL_L02 + \ 00000078 01F8 MOVW R31:R30, R17:R16 + \ 0000007A .... SUBI R30, LOW((-(RID) & 0xFFFF)) + \ 0000007C .... SBCI R31, (-(RID) & 0xFFFF) >> 8 + \ 0000007E 8500 LDD R16, Z+8 + \ 00000080 8511 LDD R17, Z+9 + \ 00000082 .... LDI R30, LOW(BattData) + \ 00000084 .... LDI R31, (BattData) >> 8 + \ 00000086 8306 STD Z+6, R16 + \ 00000088 8317 STD Z+7, R17 + 367 BattData.MaxTime = RID[i].tCutOff; + \ 0000008A 2F48 MOV R20, R24 + \ 0000008C E050 LDI R21, 0 + \ 0000008E E00E LDI R16, 14 + \ 00000090 E010 LDI R17, 0 + \ 00000092 .... RCALL ?S_MUL_L02 + \ 00000094 01F8 MOVW R31:R30, R17:R16 + \ 00000096 .... SUBI R30, LOW((-(RID) & 0xFFFF)) + \ 00000098 .... SBCI R31, (-(RID) & 0xFFFF) >> 8 + \ 0000009A 8502 LDD R16, Z+10 + \ 0000009C 8513 LDD R17, Z+11 + \ 0000009E .... LDI R30, LOW(BattData) + \ 000000A0 .... LDI R31, (BattData) >> 8 + \ 000000A2 8700 STD Z+8, R16 + \ 000000A4 8711 STD Z+9, R17 + 368 BattData.MinCurrent = RID[i].ICutOff; + \ 000000A6 2F48 MOV R20, R24 + \ 000000A8 E050 LDI R21, 0 + \ 000000AA E00E LDI R16, 14 + \ 000000AC E010 LDI R17, 0 + \ 000000AE .... RCALL ?S_MUL_L02 + \ 000000B0 01F8 MOVW R31:R30, R17:R16 + \ 000000B2 .... SUBI R30, LOW((-(RID) & 0xFFFF)) + \ 000000B4 .... SBCI R31, (-(RID) & 0xFFFF) >> 8 + \ 000000B6 8504 LDD R16, Z+12 + \ 000000B8 8515 LDD R17, Z+13 + \ 000000BA .... LDI R30, LOW(BattData) + \ 000000BC .... LDI R31, (BattData) >> 8 + \ 000000BE 8702 STD Z+10, R16 + \ 000000C0 8713 STD Z+11, R17 + 369 + 370 found = TRUE; + \ 000000C2 E091 LDI R25, 1 + 371 } + 372 } + 373 } + \ ??RIDLookUp_2: + \ 000000C4 9583 INC R24 + \ 000000C6 CF9F RJMP ??RIDLookUp_0 + 374 + 375 // If no valid entry is found, use defaults and return FALSE. + 376 if (!found) { + \ ??RIDLookUp_1: + \ 000000C8 2399 TST R25 + \ 000000CA F4C1 BRNE ??RIDLookUp_3 + 377 BattData.Capacity = DEF_BAT_CAPACITY; + \ 000000CC E000 LDI R16, 0 + \ 000000CE E010 LDI R17, 0 + \ 000000D0 .... LDI R30, LOW(BattData) + \ 000000D2 .... LDI R31, (BattData) >> 8 + \ 000000D4 8304 STD Z+4, R16 + \ 000000D6 8315 STD Z+5, R17 + 378 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX; + \ 000000D8 E000 LDI R16, 0 + \ 000000DA E010 LDI R17, 0 + \ 000000DC .... LDI R30, LOW(BattData) + \ 000000DE .... LDI R31, (BattData) >> 8 + \ 000000E0 8306 STD Z+6, R16 + \ 000000E2 8317 STD Z+7, R17 + 379 BattData.MaxTime = DEF_BAT_TIME_MAX; + \ 000000E4 E000 LDI R16, 0 + \ 000000E6 E010 LDI R17, 0 + \ 000000E8 .... LDI R30, LOW(BattData) + \ 000000EA .... LDI R31, (BattData) >> 8 + \ 000000EC 8700 STD Z+8, R16 + \ 000000EE 8711 STD Z+9, R17 + 380 BattData.MinCurrent = DEF_BAT_CURRENT_MIN; + \ 000000F0 E000 LDI R16, 0 + \ 000000F2 E010 LDI R17, 0 + \ 000000F4 .... LDI R30, LOW(BattData) + \ 000000F6 .... LDI R31, (BattData) >> 8 + \ 000000F8 8702 STD Z+10, R16 + \ 000000FA 8713 STD Z+11, R17 + 381 } + 382 + 383 return(found); + \ ??RIDLookUp_3: + \ 000000FC 2F09 MOV R16, R25 + \ 000000FE E0E4 LDI R30, 4 + \ 00000100 .... RJMP ?EPILOGUE_B4_L09 + 384 } + 385 + 386 + 387 /*! \brief Calculates temperature from a lookup table + 388 * + 389 * Looks up the highest NTC value below or equal to the measured one.\n + 390 * With the current lookup table, temperature is calculated with the formula:\n + 391 * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry) + 392 * + 393 * \note If the NTC-measurement is saturated, with the current lookup table, + 394 * the temperature will be reported as -1 C. + 395 * + 396 * \note If no valid entry is found, battery temperature is set to 80. + 397 */ + + \ In segment CODE, align 2, keep-with-next + 398 void NTCLookUp (void) + \ NTCLookUp: + 399 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + 400 unsigned char i; + 401 unsigned char found = FALSE; + \ 00000002 E090 LDI R25, 0 + 402 + 403 // Lookup in the NTC-table. Use the first entry which is equal or below + 404 // sampled NTC. Calculate temperature by using the index number, and the + 405 // difference between the measured NTC value and the one in the entry. + 406 for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { + \ 00000004 E080 LDI R24, 0 + \ ??NTCLookUp_0: + \ 00000006 3184 CPI R24, 20 + \ 00000008 F008 BRCS $+2+2 + \ 0000000A C043 RJMP ??NTCLookUp_1 + \ 0000000C 2399 TST R25 + \ 0000000E F009 BREQ $+2+2 + \ 00000010 C040 RJMP ??NTCLookUp_1 + 407 if (ADCS.rawNTC >= NTC[i].ADC) { + \ 00000012 .... LDI R30, LOW(ADCS) + \ 00000014 .... LDI R31, (ADCS) >> 8 + \ 00000016 81A4 LDD R26, Z+4 + \ 00000018 81B5 LDD R27, Z+5 + \ 0000001A 2F48 MOV R20, R24 + \ 0000001C E050 LDI R21, 0 + \ 0000001E E003 LDI R16, 3 + \ 00000020 E010 LDI R17, 0 + \ 00000022 .... RCALL ?S_MUL_L02 + \ 00000024 01F8 MOVW R31:R30, R17:R16 + \ 00000026 .... SUBI R30, LOW((-(NTC) & 0xFFFF)) + \ 00000028 .... SBCI R31, (-(NTC) & 0xFFFF) >> 8 + \ 0000002A 8100 LD R16, Z + \ 0000002C 8111 LDD R17, Z+1 + \ 0000002E 17A0 CP R26, R16 + \ 00000030 07B1 CPC R27, R17 + \ 00000032 F168 BRCS ??NTCLookUp_2 + 408 BattData.Temperature = (i<<2) ; + \ 00000034 2F08 MOV R16, R24 + \ 00000036 0F00 LSL R16 + \ 00000038 0F00 LSL R16 + \ 0000003A 9300.... STS (BattData + 2), R16 + 409 BattData.ADCSteps = NTC[i].ADCsteps; + \ 0000003E 2F48 MOV R20, R24 + \ 00000040 E050 LDI R21, 0 + \ 00000042 E003 LDI R16, 3 + \ 00000044 E010 LDI R17, 0 + \ 00000046 .... RCALL ?S_MUL_L02 + \ 00000048 01F8 MOVW R31:R30, R17:R16 + \ 0000004A .... SUBI R30, LOW((-(NTC) & 0xFFFF)) + \ 0000004C .... SBCI R31, (-(NTC) & 0xFFFF) >> 8 + \ 0000004E 8102 LDD R16, Z+2 + \ 00000050 9300.... STS (BattData + 3), R16 + 410 BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps; + \ 00000054 .... LDI R30, LOW(ADCS) + \ 00000056 .... LDI R31, (ADCS) >> 8 + \ 00000058 81A4 LDD R26, Z+4 + \ 0000005A 81B5 LDD R27, Z+5 + \ 0000005C 2F48 MOV R20, R24 + \ 0000005E E050 LDI R21, 0 + \ 00000060 E003 LDI R16, 3 + \ 00000062 E010 LDI R17, 0 + \ 00000064 .... RCALL ?S_MUL_L02 + \ 00000066 01F8 MOVW R31:R30, R17:R16 + \ 00000068 .... SUBI R30, LOW((-(NTC) & 0xFFFF)) + \ 0000006A .... SBCI R31, (-(NTC) & 0xFFFF) >> 8 + \ 0000006C 8100 LD R16, Z + \ 0000006E 8111 LDD R17, Z+1 + \ 00000070 1BA0 SUB R26, R16 + \ 00000072 0BB1 SBC R27, R17 + \ 00000074 0FAA LSL R26 + \ 00000076 1FBB ROL R27 + \ 00000078 018D MOVW R17:R16, R27:R26 + \ 0000007A 9140.... LDS R20, (BattData + 3) + \ 0000007E E050 LDI R21, 0 + \ 00000080 .... RCALL ?US_DIVMOD_L02 + \ 00000082 .... LDI R30, LOW(BattData) + \ 00000084 .... LDI R31, (BattData) >> 8 + \ 00000086 8112 LDD R17, Z+2 + \ 00000088 1B10 SUB R17, R16 + \ 0000008A 8312 STD Z+2, R17 + 411 + 412 found = TRUE; // Could be done with a break, but that violates MISRA. + \ 0000008C E091 LDI R25, 1 + 413 } + 414 } + \ ??NTCLookUp_2: + \ 0000008E 9583 INC R24 + \ 00000090 CFBA RJMP ??NTCLookUp_0 + 415 + 416 // For safety, is temperature is greater than the NTC + 417 if (!found) { + \ ??NTCLookUp_1: + \ 00000092 2399 TST R25 + \ 00000094 F419 BRNE ??NTCLookUp_3 + 418 BattData.Temperature = 80; + \ 00000096 E500 LDI R16, 80 + \ 00000098 9300.... STS (BattData + 2), R16 + 419 } + 420 } + \ ??NTCLookUp_3: + \ 0000009C E0E4 LDI R30, 4 + \ 0000009E .... RJMP ?EPILOGUE_B4_L09 + + \ In segment NEAR_ID, align 1, keep-with-next + \ `?`: + \ 00000000 022E02930F3C DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14 + \ 02260104012C + \ 000A02E8034B + \ 1A9002EE0168 + \ 012C000E + \ 0000001C 036503BE2710 DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475 + \ 03E801DB012C + \ 001304490481 + \ 5DC007D001DB + \ 00000034 01A40026 DW 420, 38 + + \ In segment NEAR_ID, align 1, keep-with-next + \ `?`: + \ 00000000 03EA DW 1002 + \ 00000002 17 DB 23 + \ 00000003 03B9 DW 953 + \ 00000005 19 DB 25 + \ 00000006 0386 DW 902 + \ 00000008 1A DB 26 + \ 00000009 0351 DW 849 + \ 0000000B 1B DB 27 + \ 0000000C 031C DW 796 + \ 0000000E 1B DB 27 + \ 0000000F 02E6 DW 742 + \ 00000011 1B DB 27 + \ 00000012 02B1 DW 689 + \ 00000014 1A DB 26 + \ 00000015 027D DW 637 + \ 00000017 1A DB 26 + \ 00000018 024B DW 587 + \ 0000001A 19 DB 25 + \ 0000001B 021B DW 539 + \ 0000001D 18 DB 24 + \ 0000001E 01EE DW 494 + \ 00000020 16 DB 22 + \ 00000021 01C3 DW 451 + \ 00000023 15 DB 21 + \ 00000024 019C DW 412 + \ 00000026 13 DB 19 + \ 00000027 0177 DW 375 + \ 00000029 12 DB 18 + \ 0000002A 0155 DW 341 + \ 0000002C 11 DB 17 + \ 0000002D 0136 DW 310 + \ 0000002F 0F DB 15 + \ 00000030 011A DW 282 + \ 00000032 0E DB 14 + \ 00000033 0100 DW 256 + \ 00000035 0D DB 13 + \ 00000036 00E9 DW 233 + \ 00000038 0B DB 11 + \ 00000039 00D4 DW 212 + \ 0000003B 0A DB 10 + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + BatteryCheck 4 2 + -> BatteryStatusRefresh 4 2 + BatteryDataRefresh 8 4 + -> OWI_DetectPresence 8 2 + -> OWI_SendByte 8 2 + -> OWI_ReceiveByte 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ReceiveByte 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ReceiveByte 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_SendByte 8 2 + -> OWI_SendByte 8 2 + -> OWI_SendByte 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ReceiveByte 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ReceiveByte 8 2 + -> OWI_ComputeCRC8 8 2 + -> OWI_ReceiveByte 8 2 + -> OWI_ComputeCRC8 8 2 + BatteryStatusRefresh 4 2 + -> NTCLookUp 4 2 + -> RIDLookUp 4 2 + DisableBatteries 0 2 + EnableBattery 1 4 + -> Time_Set 1 2 + -> Time_Left 1 2 + NTCLookUp 4 4 + RIDLookUp 4 4 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_OCR1B 1 + _A_PORTB 1 + BattControl 2 + BattData 12 + BattEEPROM 128 + BattActive 1 + RID 56 + NTC 60 + BatteryCheck 44 + BatteryStatusRefresh 248 + BatteryDataRefresh 280 + EnableBattery 66 + DisableBatteries 8 + RIDLookUp 258 + NTCLookUp 160 + ? 56 + ? 60 + Others 12 + + + 2 bytes in segment ABSOLUTE + 1 064 bytes in segment CODE + 130 bytes in segment EEPROM_I + 12 bytes in segment INITTAB + 116 bytes in segment NEAR_I + 116 bytes in segment NEAR_ID + 13 bytes in segment NEAR_Z + + 1 180 bytes of CODE memory (+ 12 bytes shared) + 129 bytes of DATA memory (+ 2 bytes shared) + 130 bytes of XDATA memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/battery.s90 b/BaseTinyFirmware/IAR/Debug/List/battery.s90 new file mode 100644 index 0000000..8060a46 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/battery.s90 @@ -0,0 +1,1211 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:38 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\battery.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\battery.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\battery. / +// s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME battery + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?EPILOGUE_B4_L09 + EXTERN ?EPILOGUE_B8_L09 + EXTERN ?PROLOGUE4_L09 + EXTERN ?PROLOGUE8_L09 + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?Register_R6_is_cg_reg + EXTERN ?Register_R7_is_cg_reg + EXTERN ?S_MUL_L02 + EXTERN ?S_SHL_L02 + EXTERN ?US_DIVMOD_L02 + EXTERN ?need_segment_init + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBWEAK `?` + PUBLIC BattActive + PUBLIC BattControl + PUBLIC BattData + PUBLIC BattEEPROM + PUBLIC BatteryCheck + PUBLIC BatteryDataRefresh + PUBLIC BatteryStatusRefresh + PUBLIC DisableBatteries + PUBLIC EnableBattery + PUBLIC NTC + PUBLIC NTCLookUp + PUBLIC RID + PUBLIC RIDLookUp + PUBWEAK _A_OCR1B + PUBWEAK _A_PORTB + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN OWI_DetectPresence + EXTERN OWI_SendByte + EXTERN OWI_ReceiveByte + EXTERN OWI_ComputeCRC8 + EXTERN Time_Set + EXTERN Time_Left + EXTERN ADCS + +// C:\home\kevin\pub\src\bc100_cal\IAR\battery.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions related to battery control and data acquisition. +// 6 * +// 7 * Contains functions for enabling/disabling batteries, and looking up +// 8 * their status and specifications using the ADC. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 +// 14 * +// 15 * \par Documentation +// 16 * For comprehensive code documentation, supported compilers, compiler +// 17 * settings and supported devices see readme.html +// 18 * +// 19 * \author +// 20 * Atmel Corporation: http://www.atmel.com \n +// 21 * Support email: avr@atmel.com +// 22 * +// 23 * +// 24 * $Name$ +// 25 * $Revision: 2299 $ +// 26 * $RCSfile$ +// 27 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $ +// 28 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 29 ******************************************************************************/ +// 30 +// 31 #include + + ASEGN ABSOLUTE:DATA:NOROOT,04cH +// volatile __io _A_OCR1B +_A_OCR1B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,038H +// volatile __io _A_PORTB +_A_PORTB: + DS 1 +// 32 #include +// 33 +// 34 #include "structs.h" +// 35 #include "enums.h" +// 36 +// 37 #include "ADC.h" +// 38 #include "battery.h" +// 39 #include "main.h" +// 40 #include "OWI.h" +// 41 #include "time.h" +// 42 +// 43 #ifdef NIMH +// 44 #include "NIMHspecs.h" +// 45 #endif // NIMH +// 46 +// 47 #ifdef LIION +// 48 #include "LIIONspecs.h" +// 49 #endif // LIION +// 50 +// 51 +// 52 +// 53 //****************************************************************************** +// 54 // Variables +// 55 //****************************************************************************** +// 56 /* Control-struct for batteries */ +// 57 /*! \brief Holds control data for both batteries +// 58 * \note Stored in EEPROM. +// 59 */ + + RSEG EEPROM_I:XDATA:NOROOT(0) +// 60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE}, +BattControl: + DB 3, 3 +// 61 {TRUE, TRUE, FALSE}}; +// 62 +// 63 /* Data-struct for battery */ + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 64 Batteries_t BattData; //!< Holds data for the current battery +BattData: + DS 12 +// 65 +// 66 +// 67 /* Storage for battery EPROM */ +// 68 /*! \brief Storage space for data from the batteries' own EPROMs. +// 69 * \note Stored in EEPROM. +// 70 */ + + RSEG EEPROM_I:XDATA:NOROOT(0) +// 71 __eeprom unsigned char BattEEPROM[4][32]; +BattEEPROM: + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// 72 +// 73 +// 74 //! Global that indicates current battery (0 = battery A, 1 = B) + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 75 unsigned char BattActive; +BattActive: + DS 1 +// 76 +// 77 +// 78 /*! \brief RID lookup-table +// 79 * +// 80 * Contains Resistor ID data specified by manufacturer. +// 81 * +// 82 * \note Values have been calculated assuming a +/- 15% tolerance. +// 83 */ + + RSEG NEAR_I:DATA:NOROOT(0) + REQUIRE `?` +// 84 const RID_Lookup_t RID[RID_TABLE_SIZE] = { +RID: + DS 56 + REQUIRE `?` +// 85 {558, 659, 3900, 550, 260, 300, 10}, +// 86 {744, 843, 6800, 750, 360, 300, 14}, +// 87 {869, 958, 10000, 1000, 475, 300, 19}, +// 88 {1097, 1153, 24000, 2000, 475, 420, 38} +// 89 }; +// 90 +// 91 +// 92 /*! \brief NTC lookup-table +// 93 * +// 94 * The first entry is 0 degrees. For every entry after, temperature increases +// 95 * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n +// 96 * It must be sorted in descending ADC order. +// 97 * +// 98 * \note This was calculated for a Mitsubishi RH16-3H103FB NTC. +// 99 * +// 100 * \note NTCLookUp() must be modified if this table is changed so that: +// 101 * - first entry is no longer 0 degrees. +// 102 * - temperature difference between entries is no longer 4 degrees. +// 103 * - ADCsteps no longer specifies ADC steps per half degree. +// 104 */ +// 105 // FOR VARTA POLYFLEX NTC + + RSEG NEAR_I:DATA:NOROOT(0) + REQUIRE `?` +// 106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { +NTC: + DS 60 + REQUIRE `?` +// 107 {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27}, +// 108 {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24}, +// 109 {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17}, +// 110 {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10} +// 111 }; +// 112 +// 113 +// 114 // FOR MITSUBISHI NTC +// 115 /* +// 116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { +// 117 {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27}, +// 118 {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24}, +// 119 {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17}, +// 120 {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10} +// 121 }; +// 122 */ +// 123 +// 124 +// 125 //****************************************************************************** +// 126 // Functions +// 127 //****************************************************************************** +// 128 /*! \brief Checks if battery has changed +// 129 * +// 130 * Stores current capacity, then attempts to refresh battery status.\n +// 131 * If the refresh is successful, old capacity is compared with the new one. +// 132 * +// 133 * \retval FALSE Battery is disconnected, or capacity has changed. +// 134 * \retval TRUE All OK. +// 135 */ + + RSEG CODE:CODE:NOROOT(1) +// 136 unsigned char BatteryCheck(void) +BatteryCheck: +// 137 { + RCALL ?PROLOGUE4_L09 +// 138 unsigned char success = TRUE; + LDI R24, 1 +// 139 unsigned int oldCapacity; +// 140 +// 141 // Save to see if battery data has changed. +// 142 oldCapacity = BattData.Capacity; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + MOVW R27:R26, R17:R16 +// 143 +// 144 if (!BatteryStatusRefresh()) { + RCALL BatteryStatusRefresh + TST R16 + BRNE ??BatteryCheck_0 +// 145 success = FALSE; // Battery not present or RID was invalid. + LDI R24, 0 +// 146 } +// 147 +// 148 if (oldCapacity != BattData.Capacity) { +??BatteryCheck_0: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + CP R26, R16 + CPC R27, R17 + BREQ ??BatteryCheck_1 +// 149 success = FALSE; // Battery configuration has changed. + LDI R24, 0 +// 150 } +// 151 +// 152 return(success); +??BatteryCheck_1: + MOV R16, R24 + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 153 } +// 154 +// 155 +// 156 /*! \brief Refreshes battery status information +// 157 * +// 158 * Refreshes battery status information, if it is present, based on +// 159 * RID and NTC (read by ADC).\n +// 160 * The battery must have been enabled and a complete set of ADC data must have +// 161 * been collected before calling.\n +// 162 * +// 163 * \retval FALSE No battery present. +// 164 * \retval TRUE Battery present, status refreshed. +// 165 * +// 166 * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry +// 167 * is found in the lookup table. Instead, default battery data will be used. +// 168 */ + + RSEG CODE:CODE:NOROOT(1) +// 169 unsigned char BatteryStatusRefresh(void) +BatteryStatusRefresh: +// 170 { + RCALL ?PROLOGUE4_L09 +// 171 // Assume the worst.. +// 172 unsigned char success = FALSE; + LDI R24, 0 +// 173 +// 174 BattData.Present = FALSE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ANDI R16, 0xFE + ST Z, R16 +// 175 BattData.Charged = FALSE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ANDI R16, 0xFD + ST Z, R16 +// 176 BattData.Low = TRUE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ORI R16, 0x04 + ST Z, R16 +// 177 BattData.Circuit = OW_NONE; + LDI R16, 0 + STS (BattData + 1), R16 +// 178 BattData.Temperature = 0; + LDI R16, 0 + STS (BattData + 2), R16 +// 179 BattData.Capacity = 0; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+4, R16 + STD Z+5, R17 +// 180 BattData.MaxCurrent = 0; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+6, R16 + STD Z+7, R17 +// 181 BattData.MaxTime = 0; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+8, R16 + STD Z+9, R17 +// 182 BattData.MinCurrent = 0; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+10, R16 + STD Z+11, R17 +// 183 +// 184 NTCLookUp(); + RCALL NTCLookUp +// 185 BattData.HasRID = RIDLookUp(); + RCALL RIDLookUp + MOV R17, R16 + ANDI R17, 0x01 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + BST R17, 0 + LD R16, Z + BLD R16, 4 + ST Z, R16 + LDI R16, 0 + BLD R16, 0 +// 186 +// 187 // Is the battery voltage above minimum safe cell voltage? +// 188 if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + CPI R16, 96 + LDI R18, 9 + CPC R17, R18 + BRCS ??BatteryStatusRefresh_0 +// 189 BattData.Low = FALSE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ANDI R16, 0xFB + ST Z, R16 +// 190 } +// 191 +// 192 // Is the battery charged? +// 193 if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { +??BatteryStatusRefresh_0: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + CPI R16, 210 + LDI R18, 15 + CPC R17, R18 + BRCS ??BatteryStatusRefresh_1 +// 194 BattData.Charged = TRUE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ORI R16, 0x02 + ST Z, R16 +// 195 } +// 196 +// 197 // If we are not charging, yet VBAT is above safe limit, battery is present. +// 198 // If we are charging and there's a current flowing, the battery is present. +// 199 +// 200 /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence +// 201 * check is redundant since charging will be aborted due to low current at +// 202 * max duty cycle. That is preferrable since the charge current reading is +// 203 * not 100% proof. +// 204 */ +// 205 if (((OCR1B == 0) && (!BattData.Low)) || +// 206 ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { +??BatteryStatusRefresh_1: + IN R16, 0x2C + TST R16 + BRNE ??BatteryStatusRefresh_2 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + SBRS R16, 2 + RJMP ??BatteryStatusRefresh_3 +??BatteryStatusRefresh_2: + IN R16, 0x2C + TST R16 + BREQ ??BatteryStatusRefresh_4 + LDI R26, LOW((ADCS + 22)) + LDI R27, HIGH((ADCS + 22)) + LD R30, X+ + LD R31, X + SBIW R27:R26, 1 + SBIW R31:R30, 1 + BRLT ??BatteryStatusRefresh_4 +// 207 BattData.Present = TRUE; +??BatteryStatusRefresh_3: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ORI R16, 0x01 + ST Z, R16 +// 208 success = TRUE; + LDI R24, 1 + RJMP ??BatteryStatusRefresh_5 +// 209 } else { +// 210 BattData.Low = FALSE; // (This is just a technicality..) +??BatteryStatusRefresh_4: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ANDI R16, 0xFB + ST Z, R16 +// 211 success = FALSE; + LDI R24, 0 +// 212 } +// 213 +// 214 #ifndef ALLOW_NO_RID +// 215 // Return FALSE if no valid RID entry was found, to stop charging. +// 216 if(!BattData.HasRID) { +??BatteryStatusRefresh_5: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + SBRS R16, 4 +// 217 success = FALSE; + LDI R24, 0 +// 218 } +// 219 #endif +// 220 +// 221 return(success); +??BatteryStatusRefresh_6: + MOV R16, R24 + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 + REQUIRE _A_OCR1B +// 222 } +// 223 +// 224 +// 225 /*! \brief Refreshes battery data in the EEPROM +// 226 * +// 227 * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store +// 228 * these data in on-chip EEPROM.\n +// 229 * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared. +// 230 * +// 231 * \todo Updating BattData with these data. Specs needed. +// 232 * +// 233 * \retval FALSE Refresh failed. +// 234 * \retval TRUE Refresh successful. +// 235 */ + + RSEG CODE:CODE:NOROOT(1) +// 236 unsigned char BatteryDataRefresh(void) +BatteryDataRefresh: +// 237 { + RCALL ?PROLOGUE8_L09 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + REQUIRE ?Register_R7_is_cg_reg +// 238 unsigned char offset; +// 239 unsigned char i, crc, family, temp, page; +// 240 unsigned char success; +// 241 +// 242 // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found. +// 243 for (page = 0; page < 4; page++) { + LDI R25, 0 +??BatteryDataRefresh_0: + CPI R25, 4 + BRCS $+2+2 + RJMP ??BatteryDataRefresh_1 +// 244 success = FALSE; + LDI R27, 0 +// 245 +// 246 if (OWI_DetectPresence(OWIBUS) == OWIBUS) { + LDI R16, 1 + RCALL OWI_DetectPresence + CPI R16, 1 + BREQ $+2+2 + RJMP ??BatteryDataRefresh_2 +// 247 +// 248 // Presence detected, check type and CRC. +// 249 OWI_SendByte(OWI_ROM_READ, OWIBUS); + LDI R17, 1 + LDI R16, 51 + RCALL OWI_SendByte +// 250 family = OWI_ReceiveByte(OWIBUS); + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R6, R16 +// 251 crc = OWI_ComputeCRC8(family,0); + LDI R17, 0 + MOV R16, R6 + RCALL OWI_ComputeCRC8 + MOV R5, R16 +// 252 +// 253 for (i = 0; i < 6; i++) { + LDI R24, 0 +??BatteryDataRefresh_3: + CPI R24, 6 + BRCC ??BatteryDataRefresh_4 +// 254 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc); + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R5 + RCALL OWI_ComputeCRC8 + MOV R5, R16 +// 255 } + INC R24 + RJMP ??BatteryDataRefresh_3 +// 256 +// 257 // CRC ok, device found. +// 258 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { +??BatteryDataRefresh_4: + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R5 + RCALL OWI_ComputeCRC8 + TST R16 + BREQ $+2+2 + RJMP ??BatteryDataRefresh_2 +// 259 BattData.Circuit = family; + STS (BattData + 1), R6 +// 260 +// 261 // For now, we only read data from DS2505 EPROMs. +// 262 if (BattData.Circuit == OW_DS2505) { + LDS R16, (BattData + 1) + CPI R16, 9 + BREQ $+2+2 + RJMP ??BatteryDataRefresh_2 +// 263 offset = page*32; + MOV R16, R25 + SWAP R16 + ANDI R16, 0xF0 + LSL R16 + MOV R4, R16 +// 264 OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data. + LDI R17, 1 + LDI R16, 195 + RCALL OWI_SendByte +// 265 OWI_SendByte(offset, OWIBUS); // Data: low address. + LDI R17, 1 + MOV R16, R4 + RCALL OWI_SendByte +// 266 OWI_SendByte(0, OWIBUS); // Data: high address. + LDI R17, 1 + LDI R16, 0 + RCALL OWI_SendByte +// 267 +// 268 // Calculate checksums. +// 269 crc = OWI_ComputeCRC8(DS2505_DATA_READ,0); + LDI R17, 0 + LDI R16, 195 + RCALL OWI_ComputeCRC8 + MOV R5, R16 +// 270 crc = OWI_ComputeCRC8(offset,crc); + MOV R17, R5 + MOV R16, R4 + RCALL OWI_ComputeCRC8 + MOV R5, R16 +// 271 crc = OWI_ComputeCRC8(0,crc); + MOV R17, R5 + LDI R16, 0 + RCALL OWI_ComputeCRC8 + MOV R5, R16 +// 272 +// 273 // Command received succesfully, now start reading data +// 274 // and writing it to EEPROM. +// 275 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R5 + RCALL OWI_ComputeCRC8 + TST R16 + BRNE ??BatteryDataRefresh_2 +// 276 crc = 0; + CLR R5 +// 277 +// 278 // Fill page with data. +// 279 for (i=0; i<32; i++) { + LDI R24, 0 +??BatteryDataRefresh_5: + CPI R24, 32 + BRCC ??BatteryDataRefresh_6 +// 280 temp = OWI_ReceiveByte(OWIBUS); + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R7, R16 +// 281 crc = OWI_ComputeCRC8(temp, crc); + MOV R17, R5 + MOV R16, R7 + RCALL OWI_ComputeCRC8 + MOV R5, R16 +// 282 BattEEPROM[page][i] = temp; + MOV R20, R25 + LDI R21, 0 + LDI R16, 32 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R20, LOW(BattEEPROM) + LDI R21, (BattEEPROM) >> 8 + ADD R20, R16 + ADC R21, R17 + MOV R16, R24 + LDI R17, 0 + ADD R20, R16 + ADC R21, R17 + MOV R16, R7 + RCALL __eeput8_16 +// 283 } + INC R24 + RJMP ??BatteryDataRefresh_5 +// 284 +// 285 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { +??BatteryDataRefresh_6: + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R5 + RCALL OWI_ComputeCRC8 + TST R16 + BRNE ??BatteryDataRefresh_2 +// 286 success = TRUE; // Data read OK + LDI R27, 1 +// 287 } +// 288 } else { // Not able to start reading data. +// 289 } +// 290 } else { // Wrong device type. +// 291 } +// 292 } else { // No device found. +// 293 } +// 294 } else { // No presence detected on one-wire bus. +// 295 } +// 296 +// 297 // Erase local EEPROM page if there were any errors during transfer. +// 298 if (!success) { +??BatteryDataRefresh_2: + TST R27 + BRNE ??BatteryDataRefresh_7 +// 299 for (i=0; i<32; i++) { + LDI R24, 0 +??BatteryDataRefresh_8: + CPI R24, 32 + BRCC ??BatteryDataRefresh_7 +// 300 BattEEPROM[page][i] = 0; + LDI R26, 0 + MOV R20, R25 + LDI R21, 0 + LDI R16, 32 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R20, LOW(BattEEPROM) + LDI R21, (BattEEPROM) >> 8 + ADD R20, R16 + ADC R21, R17 + MOV R16, R24 + LDI R17, 0 + ADD R20, R16 + ADC R21, R17 + MOV R16, R26 + RCALL __eeput8_16 +// 301 } + INC R24 + RJMP ??BatteryDataRefresh_8 +// 302 } +// 303 } +??BatteryDataRefresh_7: + INC R25 + RJMP ??BatteryDataRefresh_0 +// 304 +// 305 return(success); +??BatteryDataRefresh_1: + MOV R16, R27 + LDI R30, 8 + RJMP ?EPILOGUE_B8_L09 +// 306 } +// 307 +// 308 +// 309 /*! \brief Enables specified battery +// 310 * +// 311 * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears +// 312 * PB5/PB4 in PORTB, depending on which battery is specified.\n +// 313 * The function takes 100 ms to allow the port switch to settle. +// 314 * +// 315 * \param bat Specifies which battery to enable (0 = battery A, 1 = B) +// 316 */ + + RSEG CODE:CODE:NOROOT(1) +// 317 void EnableBattery(unsigned char bat) +EnableBattery: +// 318 { + ST -Y, R24 + MOV R24, R16 +// 319 // Use general timer, set timeout to 100ms. +// 320 Time_Set(TIMER_GEN,0,0,100); + LDI R20, 100 + LDI R17, 0 + LDI R18, 0 + LDI R19, 0 + LDI R16, 2 + RCALL Time_Set +// 321 +// 322 // Set specified battery as the active one. +// 323 BattActive = bat; + STS BattActive, R24 +// 324 +// 325 // Enable current battery in hardware, light LED & connect battery. +// 326 PORTB |= (1 << (PB4+bat)); + LDI R16, 1 + LDI R17, 0 + MOV R20, R24 + SUBI R20, 252 + RCALL ?S_SHL_L02 + IN R17, 0x18 + OR R17, R16 + OUT 0x18, R17 +// 327 +// 328 // Disconnect other battery. +// 329 PORTB &= ~(1<<(PB5-bat)); + LDI R16, 1 + LDI R17, 0 + LDI R20, 5 + SUB R20, R24 + RCALL ?S_SHL_L02 + COM R16 + IN R17, 0x18 + AND R17, R16 + OUT 0x18, R17 +// 330 +// 331 do { // Let port switch settle. +// 332 } while (Time_Left(TIMER_GEN)); +??EnableBattery_0: + LDI R16, 2 + RCALL Time_Left + TST R16 + BRNE ??EnableBattery_0 +// 333 } + LD R24, Y+ + RET + REQUIRE _A_PORTB +// 334 +// 335 +// 336 /*! \brief Disables both batteries +// 337 * +// 338 * Clears PB4 and PB5 in PORTB, disabling both batteries. +// 339 */ + + RSEG CODE:CODE:NOROOT(1) +// 340 void DisableBatteries(void) +DisableBatteries: +// 341 { +// 342 // Turn off LEDs and disconnect batteries. +// 343 PORTB &= ~((1<= RID[i].Low) { + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R26, Z+2 + LDD R27, Z+3 + MOV R20, R24 + LDI R21, 0 + LDI R16, 14 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(RID) & 0xFFFF)) + SBCI R31, (-(RID) & 0xFFFF) >> 8 + LD R16, Z + LDD R17, Z+1 + CP R26, R16 + CPC R27, R17 + BRCC $+2+2 + RJMP ??RIDLookUp_2 +// 364 if (ADCS.rawRID <= RID[i].High) { + MOV R20, R24 + LDI R21, 0 + LDI R16, 14 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(RID) & 0xFFFF)) + SBCI R31, (-(RID) & 0xFFFF) >> 8 + LDD R16, Z+2 + LDD R17, Z+3 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+2 + LDD R19, Z+3 + CP R16, R18 + CPC R17, R19 + BRCS ??RIDLookUp_2 +// 365 BattData.Capacity = RID[i].Capacity; + MOV R20, R24 + LDI R21, 0 + LDI R16, 14 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(RID) & 0xFFFF)) + SBCI R31, (-(RID) & 0xFFFF) >> 8 + LDD R16, Z+6 + LDD R17, Z+7 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+4, R16 + STD Z+5, R17 +// 366 BattData.MaxCurrent = RID[i].Icharge; + MOV R20, R24 + LDI R21, 0 + LDI R16, 14 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(RID) & 0xFFFF)) + SBCI R31, (-(RID) & 0xFFFF) >> 8 + LDD R16, Z+8 + LDD R17, Z+9 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+6, R16 + STD Z+7, R17 +// 367 BattData.MaxTime = RID[i].tCutOff; + MOV R20, R24 + LDI R21, 0 + LDI R16, 14 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(RID) & 0xFFFF)) + SBCI R31, (-(RID) & 0xFFFF) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+8, R16 + STD Z+9, R17 +// 368 BattData.MinCurrent = RID[i].ICutOff; + MOV R20, R24 + LDI R21, 0 + LDI R16, 14 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(RID) & 0xFFFF)) + SBCI R31, (-(RID) & 0xFFFF) >> 8 + LDD R16, Z+12 + LDD R17, Z+13 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+10, R16 + STD Z+11, R17 +// 369 +// 370 found = TRUE; + LDI R25, 1 +// 371 } +// 372 } +// 373 } +??RIDLookUp_2: + INC R24 + RJMP ??RIDLookUp_0 +// 374 +// 375 // If no valid entry is found, use defaults and return FALSE. +// 376 if (!found) { +??RIDLookUp_1: + TST R25 + BRNE ??RIDLookUp_3 +// 377 BattData.Capacity = DEF_BAT_CAPACITY; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+4, R16 + STD Z+5, R17 +// 378 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+6, R16 + STD Z+7, R17 +// 379 BattData.MaxTime = DEF_BAT_TIME_MAX; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+8, R16 + STD Z+9, R17 +// 380 BattData.MinCurrent = DEF_BAT_CURRENT_MIN; + LDI R16, 0 + LDI R17, 0 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + STD Z+10, R16 + STD Z+11, R17 +// 381 } +// 382 +// 383 return(found); +??RIDLookUp_3: + MOV R16, R25 + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 384 } +// 385 +// 386 +// 387 /*! \brief Calculates temperature from a lookup table +// 388 * +// 389 * Looks up the highest NTC value below or equal to the measured one.\n +// 390 * With the current lookup table, temperature is calculated with the formula:\n +// 391 * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry) +// 392 * +// 393 * \note If the NTC-measurement is saturated, with the current lookup table, +// 394 * the temperature will be reported as -1 C. +// 395 * +// 396 * \note If no valid entry is found, battery temperature is set to 80. +// 397 */ + + RSEG CODE:CODE:NOROOT(1) +// 398 void NTCLookUp (void) +NTCLookUp: +// 399 { + RCALL ?PROLOGUE4_L09 +// 400 unsigned char i; +// 401 unsigned char found = FALSE; + LDI R25, 0 +// 402 +// 403 // Lookup in the NTC-table. Use the first entry which is equal or below +// 404 // sampled NTC. Calculate temperature by using the index number, and the +// 405 // difference between the measured NTC value and the one in the entry. +// 406 for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { + LDI R24, 0 +??NTCLookUp_0: + CPI R24, 20 + BRCS $+2+2 + RJMP ??NTCLookUp_1 + TST R25 + BREQ $+2+2 + RJMP ??NTCLookUp_1 +// 407 if (ADCS.rawNTC >= NTC[i].ADC) { + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R26, Z+4 + LDD R27, Z+5 + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(NTC) & 0xFFFF)) + SBCI R31, (-(NTC) & 0xFFFF) >> 8 + LD R16, Z + LDD R17, Z+1 + CP R26, R16 + CPC R27, R17 + BRCS ??NTCLookUp_2 +// 408 BattData.Temperature = (i<<2) ; + MOV R16, R24 + LSL R16 + LSL R16 + STS (BattData + 2), R16 +// 409 BattData.ADCSteps = NTC[i].ADCsteps; + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(NTC) & 0xFFFF)) + SBCI R31, (-(NTC) & 0xFFFF) >> 8 + LDD R16, Z+2 + STS (BattData + 3), R16 +// 410 BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R26, Z+4 + LDD R27, Z+5 + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(NTC) & 0xFFFF)) + SBCI R31, (-(NTC) & 0xFFFF) >> 8 + LD R16, Z + LDD R17, Z+1 + SUB R26, R16 + SBC R27, R17 + LSL R26 + ROL R27 + MOVW R17:R16, R27:R26 + LDS R20, (BattData + 3) + LDI R21, 0 + RCALL ?US_DIVMOD_L02 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R17, Z+2 + SUB R17, R16 + STD Z+2, R17 +// 411 +// 412 found = TRUE; // Could be done with a break, but that violates MISRA. + LDI R25, 1 +// 413 } +// 414 } +??NTCLookUp_2: + INC R24 + RJMP ??NTCLookUp_0 +// 415 +// 416 // For safety, is temperature is greater than the NTC +// 417 if (!found) { +??NTCLookUp_1: + TST R25 + BRNE ??NTCLookUp_3 +// 418 BattData.Temperature = 80; + LDI R16, 80 + STS (BattData + 2), R16 +// 419 } +// 420 } +??NTCLookUp_3: + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + RSEG NEAR_ID:CODE:NOROOT(0) +`?`: + DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14 + DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475 + DW 420, 38 + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_I) - SFB(NEAR_I) + DW SFB(NEAR_I) + DW SFB(NEAR_ID) + REQUIRE ?need_segment_init + + RSEG NEAR_ID:CODE:NOROOT(0) +`?`: + DW 1002 + DB 23 + DW 953 + DB 25 + DW 902 + DB 26 + DW 849 + DB 27 + DW 796 + DB 27 + DW 742 + DB 27 + DW 689 + DB 26 + DW 637 + DB 26 + DW 587 + DB 25 + DW 539 + DB 24 + DW 494 + DB 22 + DW 451 + DB 21 + DW 412 + DB 19 + DW 375 + DB 18 + DW 341 + DB 17 + DW 310 + DB 15 + DW 282 + DB 14 + DW 256 + DB 13 + DW 233 + DB 11 + DW 212 + DB 10 + + END +// +// 2 bytes in segment ABSOLUTE +// 1 064 bytes in segment CODE +// 130 bytes in segment EEPROM_I +// 12 bytes in segment INITTAB +// 116 bytes in segment NEAR_I +// 116 bytes in segment NEAR_ID +// 13 bytes in segment NEAR_Z +// +// 1 180 bytes of CODE memory (+ 12 bytes shared) +// 129 bytes of DATA memory (+ 2 bytes shared) +// 130 bytes of XDATA memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/chargefunc.lst b/BaseTinyFirmware/IAR/Debug/List/chargefunc.lst new file mode 100644 index 0000000..b649880 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/chargefunc.lst @@ -0,0 +1,907 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\chargefun # +# c.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\chargefunc # +# .r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Charge functions + 6 * + 7 * Contains the functions for charging with constant current and voltage, + 8 * and for deciding when to halt. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 * + 14 * \par Documentation + 15 * For comprehensive code documentation, supported compilers, compiler + 16 * settings and supported devices see readme.html + 17 * + 18 * \author + 19 * Atmel Corporation: http://www.atmel.com \n + 20 * Support email: avr@atmel.com + 21 * + 22 * + 23 * $Name$ + 24 * $Revision: 2299 $ + 25 * $RCSfile$ + 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $ + 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 28 ******************************************************************************/ + 29 + 30 #include + + \ In segment ABSOLUTE, at 0x4c + \ volatile __io _A_OCR1B + \ _A_OCR1B: + \ 00000000 DS 1 + 31 + 32 #include "enums.h" + 33 #include "structs.h" + 34 + 35 #include "ADC.h" + 36 #include "battery.h" + 37 #include "chargefunc.h" + 38 #include "main.h" + 39 #include "menu.h" + 40 #include "PWM.h" + 41 #include "statefunc.h" + 42 #include "time.h" + 43 + 44 #ifdef NIMH + 45 #include "NIMHspecs.h" + 46 #endif // NIMH + 47 + 48 #ifdef LIION + 49 #include "LIIONspecs.h" + 50 #endif // LIION + 51 + 52 + 53 //****************************************************************************** + 54 // Variables + 55 //****************************************************************************** + 56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage(). + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 57 ChargeParameters_t ChargeParameters; + \ ChargeParameters: + \ 00000000 DS 5 + 58 + 59 //! Struct that holds parameters for HaltNow(). + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 60 HaltParameters_t HaltParameters; + \ HaltParameters: + \ 00000000 DS 17 + 61 + 62 + 63 //****************************************************************************** + 64 // Functions + 65 //****************************************************************************** + 66 /*! \brief Charges battery with a constant current. + 67 * + 68 * This function applies a constant current (set in ChargeParameters.Current) + 69 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + 70 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + 71 * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n + 72 * If the Master inhibits charging, timers are stopped and PWM output dropped. + 73 * Once the battery is no longer flagged for charge inhibit, timers are + 74 * started again and charging resumed. + 75 * + 76 * \retval ChargeParameters.NextState Next state once this stage is done. + 77 * If no errors occured, this will be whatever was set in Charge(). Otherwise, + 78 * HaltNow() will have set a new next state. + 79 */ + + \ In segment CODE, align 2, keep-with-next + 80 unsigned char ConstantCurrent(void) + \ ConstantCurrent: + 81 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + 82 unsigned char error = FALSE, + \ 00000002 E080 LDI R24, 0 + 83 wasStopped = FALSE; + \ 00000004 E090 LDI R25, 0 + 84 + 85 do { + 86 // Wait for ADC conversions to complete. + 87 ADC_Wait(); + \ ??ConstantCurrent_0: + \ 00000006 .... RCALL ADC_Wait + 88 + 89 // If Master has flagged for a charge inhibit, pause charging. + 90 // (This is to prevent damage during prolonged serial communication.) + 91 if (BattControl[BattActive].ChargeInhibit) { + \ 00000008 9100.... LDS R16, BattActive + \ 0000000C E010 LDI R17, 0 + \ 0000000E .... LDI R20, LOW(BattControl) + \ 00000010 .... LDI R21, (BattControl) >> 8 + \ 00000012 0F40 ADD R20, R16 + \ 00000014 1F51 ADC R21, R17 + \ 00000016 .... RCALL __eeget8_16 + \ 00000018 7004 ANDI R16, 0x04 + \ 0000001A 2300 TST R16 + \ 0000001C F029 BREQ ??ConstantCurrent_1 + 92 wasStopped = TRUE; + \ 0000001E E091 LDI R25, 1 + 93 Time_Stop(); + \ 00000020 .... RCALL Time_Stop + 94 OCR1B = 0; + \ 00000022 E000 LDI R16, 0 + \ 00000024 BD0C OUT 0x2C, R16 + \ 00000026 C03C RJMP ??ConstantCurrent_2 + 95 } else { + 96 // Continue charging! + 97 if (wasStopped) { + \ ??ConstantCurrent_1: + \ 00000028 2399 TST R25 + \ 0000002A F011 BREQ ??ConstantCurrent_3 + 98 wasStopped = FALSE; + \ 0000002C E090 LDI R25, 0 + 99 + 100 // Timer variables are not reset by this. + 101 Time_Start(); + \ 0000002E .... RCALL Time_Start + 102 } + 103 + 104 // Adjust the charge current to within ChargeParameters.Current + 105 // +/- BAT_CURRENT_HYST. + 106 if ((ADCS.avgIBAT < 0) || + 107 (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { + \ ??ConstantCurrent_3: + \ 00000030 .... LDI R30, LOW(ADCS) + \ 00000032 .... LDI R31, (ADCS) >> 8 + \ 00000034 8906 LDD R16, Z+22 + \ 00000036 8917 LDD R17, Z+23 + \ 00000038 2311 TST R17 + \ 0000003A F06A BRMI ??ConstantCurrent_4 + \ 0000003C .... LDI R30, LOW(ADCS) + \ 0000003E .... LDI R31, (ADCS) >> 8 + \ 00000040 8926 LDD R18, Z+22 + \ 00000042 8937 LDD R19, Z+23 + \ 00000044 .... LDI R30, LOW(ChargeParameters) + \ 00000046 .... LDI R31, (ChargeParameters) >> 8 + \ 00000048 8102 LDD R16, Z+2 + \ 0000004A 8113 LDD R17, Z+3 + \ 0000004C 5003 SUBI R16, 3 + \ 0000004E 4010 SBCI R17, 0 + \ 00000050 1720 CP R18, R16 + \ 00000052 0731 CPC R19, R17 + \ 00000054 F450 BRCC ??ConstantCurrent_5 + 108 + 109 if(!PWM_IncrementDutyCycle()) { + \ ??ConstantCurrent_4: + \ 00000056 .... RCALL PWM_IncrementDutyCycle + \ 00000058 2300 TST R16 + \ 0000005A F511 BRNE ??ConstantCurrent_2 + 110 #ifdef ABORT_IF_PWM_MAX + 111 // If the duty cycle cannot be incremented, flag error and + 112 // go to error state. + 113 SetErrorFlag(ERR_PWM_CONTROL); + \ 0000005C E004 LDI R16, 4 + \ 0000005E .... RCALL SetErrorFlag + 114 ChargeParameters.NextState = ST_ERROR; + \ 00000060 E50A LDI R16, 90 + \ 00000062 9300.... STS (ChargeParameters + 4), R16 + 115 error = TRUE; + \ 00000066 E081 LDI R24, 1 + \ 00000068 C01B RJMP ??ConstantCurrent_2 + 116 #endif + 117 } + 118 } else if ((ADCS.avgIBAT >= 0) && + 119 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { + \ ??ConstantCurrent_5: + \ 0000006A .... LDI R30, LOW(ADCS) + \ 0000006C .... LDI R31, (ADCS) >> 8 + \ 0000006E 8906 LDD R16, Z+22 + \ 00000070 8917 LDD R17, Z+23 + \ 00000072 2311 TST R17 + \ 00000074 F0AA BRMI ??ConstantCurrent_2 + \ 00000076 .... LDI R30, LOW(ChargeParameters) + \ 00000078 .... LDI R31, (ChargeParameters) >> 8 + \ 0000007A 81A2 LDD R26, Z+2 + \ 0000007C 81B3 LDD R27, Z+3 + \ 0000007E 9613 ADIW R27:R26, 3 + \ 00000080 .... LDI R30, LOW(ADCS) + \ 00000082 .... LDI R31, (ADCS) >> 8 + \ 00000084 8906 LDD R16, Z+22 + \ 00000086 8917 LDD R17, Z+23 + \ 00000088 17A0 CP R26, R16 + \ 0000008A 07B1 CPC R27, R17 + \ 0000008C F448 BRCC ??ConstantCurrent_2 + 120 + 121 if(!PWM_DecrementDutyCycle()) { + \ 0000008E .... RCALL PWM_DecrementDutyCycle + \ 00000090 2300 TST R16 + \ 00000092 F431 BRNE ??ConstantCurrent_2 + 122 #ifdef ABORT_IF_PWM_MIN + 123 // If the duty cycle cannot be decremented, flag error and + 124 // go to error state. + 125 SetErrorFlag(ERR_PWM_CONTROL); + \ 00000094 E004 LDI R16, 4 + \ 00000096 .... RCALL SetErrorFlag + 126 ChargeParameters.NextState = ST_ERROR; + \ 00000098 E50A LDI R16, 90 + \ 0000009A 9300.... STS (ChargeParameters + 4), R16 + 127 error = TRUE; + \ 0000009E E081 LDI R24, 1 + 128 #endif + 129 } + 130 } + 131 } + 132 } while (!HaltNow() && !error); + \ ??ConstantCurrent_2: + \ 000000A0 .... RCALL HaltNow + \ 000000A2 2300 TST R16 + \ 000000A4 F419 BRNE ??ConstantCurrent_6 + \ 000000A6 2388 TST R24 + \ 000000A8 F409 BRNE $+2+2 + \ 000000AA CFAD RJMP ??ConstantCurrent_0 + 133 + 134 // Return the next state to Charge(). If an error has occured, this will + 135 // point to some other state than the next state of charging. + 136 return(ChargeParameters.NextState); + \ ??ConstantCurrent_6: + \ 000000AC 9100.... LDS R16, (ChargeParameters + 4) + \ 000000B0 E0E4 LDI R30, 4 + \ 000000B2 .... RJMP ?EPILOGUE_B4_L09 + \ 000000B4 REQUIRE _A_OCR1B + 137 } + 138 + 139 + 140 /*! \brief Charges battery with a constant voltage + 141 * + 142 * This function applies a constant voltage (set in ChargeParameters.Voltage) + 143 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + 144 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + 145 * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n + 146 * If the Master inhibits charging, timers are stopped and PWM output dropped. + 147 * Once the battery is no longer flagged for charge inhibit, timers are + 148 * started again and charging resumed. + 149 * + 150 * \retval ChargeParameters.NextState Next state once this stage is done. + 151 * If no errors occured, this will be whatever was set in Charge(). Otherwise, + 152 * HaltNow() will have set a new next state. + 153 */ + + \ In segment CODE, align 2, keep-with-next + 154 unsigned char ConstantVoltage(void) + \ ConstantVoltage: + 155 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + 156 unsigned char error = FALSE, + \ 00000002 E080 LDI R24, 0 + 157 wasStopped = FALSE; + \ 00000004 E090 LDI R25, 0 + 158 + 159 do{ + 160 + 161 // Wait for ADC conversions to complete. + 162 ADC_Wait(); + \ ??ConstantVoltage_0: + \ 00000006 .... RCALL ADC_Wait + 163 + 164 // If Master has flagged for a charge inhibit, pause charging. + 165 // (This is to prevent damage during prolonged serial communication.) + 166 if (BattControl[BattActive].ChargeInhibit) { + \ 00000008 9100.... LDS R16, BattActive + \ 0000000C E010 LDI R17, 0 + \ 0000000E .... LDI R20, LOW(BattControl) + \ 00000010 .... LDI R21, (BattControl) >> 8 + \ 00000012 0F40 ADD R20, R16 + \ 00000014 1F51 ADC R21, R17 + \ 00000016 .... RCALL __eeget8_16 + \ 00000018 7004 ANDI R16, 0x04 + \ 0000001A 2300 TST R16 + \ 0000001C F029 BREQ ??ConstantVoltage_1 + 167 wasStopped = TRUE; + \ 0000001E E091 LDI R25, 1 + 168 Time_Stop(); + \ 00000020 .... RCALL Time_Stop + 169 OCR1B = 0; + \ 00000022 E000 LDI R16, 0 + \ 00000024 BD0C OUT 0x2C, R16 + \ 00000026 C030 RJMP ??ConstantVoltage_2 + 170 } + 171 + 172 else { + 173 // Continue charging! + 174 if (wasStopped) { + \ ??ConstantVoltage_1: + \ 00000028 2399 TST R25 + \ 0000002A F011 BREQ ??ConstantVoltage_3 + 175 wasStopped = FALSE; + \ 0000002C E090 LDI R25, 0 + 176 + 177 // Timer variables aren't reset by this. + 178 Time_Start(); + \ 0000002E .... RCALL Time_Start + 179 } + 180 + 181 // Adjust the charge voltage to within ChargeParameters.Voltage + 182 // +/- BAT_VOLTAGE_HYST. + 183 if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { + \ ??ConstantVoltage_3: + \ 00000030 .... LDI R30, LOW(ADCS) + \ 00000032 .... LDI R31, (ADCS) >> 8 + \ 00000034 8522 LDD R18, Z+10 + \ 00000036 8533 LDD R19, Z+11 + \ 00000038 .... LDI R30, LOW(ChargeParameters) + \ 0000003A .... LDI R31, (ChargeParameters) >> 8 + \ 0000003C 8100 LD R16, Z + \ 0000003E 8111 LDD R17, Z+1 + \ 00000040 500A SUBI R16, 10 + \ 00000042 4010 SBCI R17, 0 + \ 00000044 1720 CP R18, R16 + \ 00000046 0731 CPC R19, R17 + \ 00000048 F450 BRCC ??ConstantVoltage_4 + 184 + 185 if(!PWM_IncrementDutyCycle()) { + \ 0000004A .... RCALL PWM_IncrementDutyCycle + \ 0000004C 2300 TST R16 + \ 0000004E F4E1 BRNE ??ConstantVoltage_2 + 186 #ifdef ABORT_IF_PWM_MAX + 187 // Flag PWM control error and go to error-state if the duty + 188 // cycle cannot be incremented. + 189 SetErrorFlag(ERR_PWM_CONTROL); + \ 00000050 E004 LDI R16, 4 + \ 00000052 .... RCALL SetErrorFlag + 190 ChargeParameters.NextState = ST_ERROR; + \ 00000054 E50A LDI R16, 90 + \ 00000056 9300.... STS (ChargeParameters + 4), R16 + 191 error = TRUE; + \ 0000005A E081 LDI R24, 1 + \ 0000005C C015 RJMP ??ConstantVoltage_2 + 192 #endif + 193 } + 194 } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { + \ ??ConstantVoltage_4: + \ 0000005E .... LDI R30, LOW(ChargeParameters) + \ 00000060 .... LDI R31, (ChargeParameters) >> 8 + \ 00000062 81A0 LD R26, Z + \ 00000064 81B1 LDD R27, Z+1 + \ 00000066 961A ADIW R27:R26, 10 + \ 00000068 .... LDI R30, LOW(ADCS) + \ 0000006A .... LDI R31, (ADCS) >> 8 + \ 0000006C 8502 LDD R16, Z+10 + \ 0000006E 8513 LDD R17, Z+11 + \ 00000070 17A0 CP R26, R16 + \ 00000072 07B1 CPC R27, R17 + \ 00000074 F448 BRCC ??ConstantVoltage_2 + 195 + 196 if(!PWM_DecrementDutyCycle()) { + \ 00000076 .... RCALL PWM_DecrementDutyCycle + \ 00000078 2300 TST R16 + \ 0000007A F431 BRNE ??ConstantVoltage_2 + 197 #ifdef ABORT_IF_PWM_MIN + 198 // Flag PWM control error and go to error-state if duty + 199 // cycle cannot be decremented. + 200 SetErrorFlag(ERR_PWM_CONTROL); + \ 0000007C E004 LDI R16, 4 + \ 0000007E .... RCALL SetErrorFlag + 201 ChargeParameters.NextState = ST_ERROR; + \ 00000080 E50A LDI R16, 90 + \ 00000082 9300.... STS (ChargeParameters + 4), R16 + 202 error = TRUE; + \ 00000086 E081 LDI R24, 1 + 203 #endif + 204 } + 205 } + 206 } + 207 + 208 } while (!HaltNow() && !error); + \ ??ConstantVoltage_2: + \ 00000088 .... RCALL HaltNow + \ 0000008A 2300 TST R16 + \ 0000008C F419 BRNE ??ConstantVoltage_5 + \ 0000008E 2388 TST R24 + \ 00000090 F409 BRNE $+2+2 + \ 00000092 CFB9 RJMP ??ConstantVoltage_0 + 209 + 210 // Return the next state to Charge(). If an error has occured, this will + 211 // point to some other state than the next state of charging. + 212 return(ChargeParameters.NextState); + \ ??ConstantVoltage_5: + \ 00000094 9100.... LDS R16, (ChargeParameters + 4) + \ 00000098 E0E4 LDI R30, 4 + \ 0000009A .... RJMP ?EPILOGUE_B4_L09 + \ 0000009C REQUIRE _A_OCR1B + 213 } + 214 + 215 + 216 /*! \brief Determines when to halt charging. + 217 * + 218 * This function evaluates parameters depending on what has been flagged in + 219 * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should + 220 * halt or not.\n + 221 * In addition, error flagging on timeout (battery exhaustion) can be set.\n + 222 * + 223 * The function also checks if the battery temperature is within limits, + 224 * if mains is OK, and if BatteryCheck() returns TRUE. + 225 * If an error is detected, the associated errorflag is set and + 226 * ChargeParameters.NextState is changed to an appropriate state. + 227 * + 228 * \retval TRUE Halt now. + 229 * \retval FALSE Don't halt now. + 230 * + 231 * \note See chargefunc.h for definitions of halt flags. + 232 * \note It is generally a bad idea not to halt on a timeout. + 233 * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be + 234 * reset in Charge() before calling a charging-function. + 235 * + 236 * \todo "Priorities" of standard error checks OK? + 237 */ + + \ In segment CODE, align 2, keep-with-next + 238 unsigned char HaltNow(void) + \ HaltNow: + 239 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + 240 unsigned char i, halt = FALSE; + \ 00000002 E080 LDI R24, 0 + 241 + 242 // Wait for a full ADC-cycle to finish. + 243 ADC_Wait(); + \ 00000004 .... RCALL ADC_Wait + 244 + 245 // Evaluate ADC readings according to HaltFlags. Flag errors if selected. + 246 // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR. + 247 // (Gets overridden if either mains is failing, or the battery changes.) + 248 for (i = 0x01; i != 0; i <<= 1) { + \ 00000006 E091 LDI R25, 1 + \ ??HaltNow_0: + \ 00000008 2399 TST R25 + \ 0000000A F409 BRNE $+2+2 + \ 0000000C C0C4 RJMP ??HaltNow_1 + 249 if (HaltParameters.HaltFlags & i) { + \ 0000000E 9100.... LDS R16, HaltParameters + \ 00000012 2309 AND R16, R25 + \ 00000014 2300 TST R16 + \ 00000016 F409 BRNE $+2+2 + \ 00000018 C0BC RJMP ??HaltNow_2 + 250 switch (i) { + \ 0000001A 2F09 MOV R16, R25 + \ 0000001C 5001 SUBI R16, 1 + \ 0000001E F059 BREQ ??HaltNow_3 + \ 00000020 950A DEC R16 + \ 00000022 F189 BREQ ??HaltNow_4 + \ 00000024 5002 SUBI R16, 2 + \ 00000026 F1E9 BREQ ??HaltNow_5 + \ 00000028 5004 SUBI R16, 4 + \ 0000002A F409 BRNE $+2+2 + \ 0000002C C048 RJMP ??HaltNow_6 + \ 0000002E 5008 SUBI R16, 8 + \ 00000030 F409 BRNE $+2+2 + \ 00000032 C089 RJMP ??HaltNow_7 + \ 00000034 C0AE RJMP ??HaltNow_2 + 251 // Is VBAT less than the recorded maximum? + 252 case HALT_VOLTAGE_DROP: + 253 + 254 // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. + 255 if (ADCS.VBAT > HaltParameters.VBATMax) { + \ ??HaltNow_3: + \ 00000036 .... LDI R30, LOW(HaltParameters) + \ 00000038 .... LDI R31, (HaltParameters) >> 8 + \ 0000003A 8505 LDD R16, Z+13 + \ 0000003C 8516 LDD R17, Z+14 + \ 0000003E .... LDI R30, LOW(ADCS) + \ 00000040 .... LDI R31, (ADCS) >> 8 + \ 00000042 8522 LDD R18, Z+10 + \ 00000044 8533 LDD R19, Z+11 + \ 00000046 1702 CP R16, R18 + \ 00000048 0713 CPC R17, R19 + \ 0000004A F448 BRCC ??HaltNow_8 + 256 HaltParameters.VBATMax = ADCS.VBAT; + \ 0000004C .... LDI R30, LOW(ADCS) + \ 0000004E .... LDI R31, (ADCS) >> 8 + \ 00000050 8502 LDD R16, Z+10 + \ 00000052 8513 LDD R17, Z+11 + \ 00000054 .... LDI R30, LOW(HaltParameters) + \ 00000056 .... LDI R31, (HaltParameters) >> 8 + \ 00000058 8705 STD Z+13, R16 + \ 0000005A 8716 STD Z+14, R17 + \ 0000005C C09A RJMP ??HaltNow_2 + 257 } else if((HaltParameters.VBATMax - ADCS.VBAT) >= + 258 HaltParameters.VoltageDrop) { + \ ??HaltNow_8: + \ 0000005E .... LDI R30, LOW(HaltParameters) + \ 00000060 .... LDI R31, (HaltParameters) >> 8 + \ 00000062 8505 LDD R16, Z+13 + \ 00000064 8516 LDD R17, Z+14 + \ 00000066 .... LDI R30, LOW(ADCS) + \ 00000068 .... LDI R31, (ADCS) >> 8 + \ 0000006A 8522 LDD R18, Z+10 + \ 0000006C 8533 LDD R19, Z+11 + \ 0000006E 1B02 SUB R16, R18 + \ 00000070 0B13 SBC R17, R19 + \ 00000072 .... LDI R30, LOW(HaltParameters) + \ 00000074 .... LDI R31, (HaltParameters) >> 8 + \ 00000076 8121 LDD R18, Z+1 + \ 00000078 8132 LDD R19, Z+2 + \ 0000007A 1702 CP R16, R18 + \ 0000007C 0713 CPC R17, R19 + \ 0000007E F408 BRCC $+2+2 + \ 00000080 C088 RJMP ??HaltNow_2 + 259 halt = TRUE; + \ 00000082 E081 LDI R24, 1 + \ 00000084 C086 RJMP ??HaltNow_2 + 260 } + 261 break; + 262 + 263 + 264 // Has VBAT reached the maximum limit? + 265 case HALT_VOLTAGE_MAX: + 266 + 267 if (ADCS.VBAT >= HaltParameters.VoltageMax) { + \ ??HaltNow_4: + \ 00000086 .... LDI R30, LOW(ADCS) + \ 00000088 .... LDI R31, (ADCS) >> 8 + \ 0000008A 8502 LDD R16, Z+10 + \ 0000008C 8513 LDD R17, Z+11 + \ 0000008E .... LDI R30, LOW(HaltParameters) + \ 00000090 .... LDI R31, (HaltParameters) >> 8 + \ 00000092 8123 LDD R18, Z+3 + \ 00000094 8134 LDD R19, Z+4 + \ 00000096 1702 CP R16, R18 + \ 00000098 0713 CPC R17, R19 + \ 0000009A F408 BRCC $+2+2 + \ 0000009C C07A RJMP ??HaltNow_2 + 268 halt = TRUE; + \ 0000009E E081 LDI R24, 1 + \ 000000A0 C078 RJMP ??HaltNow_2 + 269 } + 270 break; + 271 + 272 + 273 // Has IBAT reached the minimum limit? + 274 case HALT_CURRENT_MIN: + 275 + 276 if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { + \ ??HaltNow_5: + \ 000000A2 .... LDI R30, LOW(HaltParameters) + \ 000000A4 .... LDI R31, (HaltParameters) >> 8 + \ 000000A6 8105 LDD R16, Z+5 + \ 000000A8 8116 LDD R17, Z+6 + \ 000000AA .... LDI R30, LOW(ADCS) + \ 000000AC .... LDI R31, (ADCS) >> 8 + \ 000000AE 8926 LDD R18, Z+22 + \ 000000B0 8937 LDD R19, Z+23 + \ 000000B2 1702 CP R16, R18 + \ 000000B4 0713 CPC R17, R19 + \ 000000B6 F408 BRCC $+2+2 + \ 000000B8 C06C RJMP ??HaltNow_2 + 277 halt = TRUE; + \ 000000BA E081 LDI R24, 1 + \ 000000BC C06A RJMP ??HaltNow_2 + 278 } + 279 break; + 280 + 281 + 282 // Is the temperature rising too fast? + 283 case HALT_TEMPERATURE_RISE: + 284 + 285 // If rawNTC has increased, the temperature has dropped. + 286 // We can store this value for now, and start the timer. + 287 // Otherwise, check if NTC has changed too fast. + 288 if (ADCS.rawNTC > HaltParameters.LastNTC) { + \ ??HaltNow_6: + \ 000000BE .... LDI R30, LOW(HaltParameters) + \ 000000C0 .... LDI R31, (HaltParameters) >> 8 + \ 000000C2 8507 LDD R16, Z+15 + \ 000000C4 8910 LDD R17, Z+16 + \ 000000C6 .... LDI R30, LOW(ADCS) + \ 000000C8 .... LDI R31, (ADCS) >> 8 + \ 000000CA 8124 LDD R18, Z+4 + \ 000000CC 8135 LDD R19, Z+5 + \ 000000CE 1702 CP R16, R18 + \ 000000D0 0713 CPC R17, R19 + \ 000000D2 F478 BRCC ??HaltNow_9 + 289 HaltParameters.LastNTC = ADCS.rawNTC; + \ 000000D4 .... LDI R30, LOW(ADCS) + \ 000000D6 .... LDI R31, (ADCS) >> 8 + \ 000000D8 8104 LDD R16, Z+4 + \ 000000DA 8115 LDD R17, Z+5 + \ 000000DC .... LDI R30, LOW(HaltParameters) + \ 000000DE .... LDI R31, (HaltParameters) >> 8 + \ 000000E0 8707 STD Z+15, R16 + \ 000000E2 8B10 STD Z+16, R17 + 290 Time_Set(TIMER_TEMP,0,30,0); + \ 000000E4 E040 LDI R20, 0 + \ 000000E6 E11E LDI R17, 30 + \ 000000E8 E020 LDI R18, 0 + \ 000000EA E030 LDI R19, 0 + \ 000000EC E003 LDI R16, 3 + \ 000000EE .... RCALL Time_Set + \ 000000F0 C050 RJMP ??HaltNow_2 + 291 + 292 // Is the increase in temperature greater than the set threshold? + 293 } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= + 294 (BattData.ADCSteps * HaltParameters.TemperatureRise)) { + \ ??HaltNow_9: + \ 000000F2 .... LDI R30, LOW(HaltParameters) + \ 000000F4 .... LDI R31, (HaltParameters) >> 8 + \ 000000F6 85A7 LDD R26, Z+15 + \ 000000F8 89B0 LDD R27, Z+16 + \ 000000FA .... LDI R30, LOW(ADCS) + \ 000000FC .... LDI R31, (ADCS) >> 8 + \ 000000FE 8104 LDD R16, Z+4 + \ 00000100 8115 LDD R17, Z+5 + \ 00000102 1BA0 SUB R26, R16 + \ 00000104 0BB1 SBC R27, R17 + \ 00000106 9140.... LDS R20, (BattData + 3) + \ 0000010A E050 LDI R21, 0 + \ 0000010C .... LDI R30, LOW(HaltParameters) + \ 0000010E .... LDI R31, (HaltParameters) >> 8 + \ 00000110 8503 LDD R16, Z+11 + \ 00000112 8514 LDD R17, Z+12 + \ 00000114 .... RCALL ?S_MUL_L02 + \ 00000116 17A0 CP R26, R16 + \ 00000118 07B1 CPC R27, R17 + \ 0000011A F1D8 BRCS ??HaltNow_2 + 295 + 296 // If this happened within a timeframe of 30 seconds, the + 297 // temperature is rising faster than we want. + 298 // If not, update LastNTC and reset timer. + 299 if (Time_Left(TIMER_TEMP)) { + \ 0000011C E003 LDI R16, 3 + \ 0000011E .... RCALL Time_Left + \ 00000120 2300 TST R16 + \ 00000122 F011 BREQ ??HaltNow_10 + 300 halt = TRUE; + \ 00000124 E081 LDI R24, 1 + \ 00000126 C035 RJMP ??HaltNow_2 + 301 } else { + 302 HaltParameters.LastNTC = ADCS.rawNTC; + \ ??HaltNow_10: + \ 00000128 .... LDI R30, LOW(ADCS) + \ 0000012A .... LDI R31, (ADCS) >> 8 + \ 0000012C 8104 LDD R16, Z+4 + \ 0000012E 8115 LDD R17, Z+5 + \ 00000130 .... LDI R30, LOW(HaltParameters) + \ 00000132 .... LDI R31, (HaltParameters) >> 8 + \ 00000134 8707 STD Z+15, R16 + \ 00000136 8B10 STD Z+16, R17 + 303 Time_Set(TIMER_TEMP,0,30,0); + \ 00000138 E040 LDI R20, 0 + \ 0000013A E11E LDI R17, 30 + \ 0000013C E020 LDI R18, 0 + \ 0000013E E030 LDI R19, 0 + \ 00000140 E003 LDI R16, 3 + \ 00000142 .... RCALL Time_Set + \ 00000144 C026 RJMP ??HaltNow_2 + 304 } + 305 } + 306 break; + 307 + 308 + 309 // Is there any time left? + 310 case HALT_TIME: + 311 + 312 if (!Time_Left(TIMER_CHG)) { + \ ??HaltNow_7: + \ 00000146 E001 LDI R16, 1 + \ 00000148 .... RCALL Time_Left + \ 0000014A 2300 TST R16 + \ 0000014C F511 BRNE ??HaltNow_2 + 313 halt = TRUE; + \ 0000014E E081 LDI R24, 1 + 314 + 315 // If exhaustion flagging is selected, stop the PWM, disable the + 316 // battery and flag it as exhausted. Make ST_ERROR next state. + 317 if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { + \ 00000150 .... LDI R30, LOW(HaltParameters) + \ 00000152 .... LDI R31, (HaltParameters) >> 8 + \ 00000154 8100 LD R16, Z + \ 00000156 FF05 SBRS R16, 5 + \ 00000158 C01C RJMP ??HaltNow_2 + 318 PWM_Stop(); + \ 0000015A .... RCALL PWM_Stop + 319 BattControl[BattActive].Enabled = FALSE; + \ 0000015C 9100.... LDS R16, BattActive + \ 00000160 E010 LDI R17, 0 + \ 00000162 .... LDI R20, LOW(BattControl) + \ 00000164 .... LDI R21, (BattControl) >> 8 + \ 00000166 0F40 ADD R20, R16 + \ 00000168 1F51 ADC R21, R17 + \ 0000016A .... RCALL __eeget8_16 + \ 0000016C 7F0E ANDI R16, 0xFE + \ 0000016E 9120.... LDS R18, BattActive + \ 00000172 E030 LDI R19, 0 + \ 00000174 .... LDI R20, LOW(BattControl) + \ 00000176 .... LDI R21, (BattControl) >> 8 + \ 00000178 0F42 ADD R20, R18 + \ 0000017A 1F53 ADC R21, R19 + \ 0000017C .... RCALL __eeput8_16 + 320 BattData.Exhausted = TRUE; + \ 0000017E .... LDI R30, LOW(BattData) + \ 00000180 .... LDI R31, (BattData) >> 8 + \ 00000182 8100 LD R16, Z + \ 00000184 6008 ORI R16, 0x08 + \ 00000186 8300 ST Z, R16 + 321 SetErrorFlag(ERR_BATTERY_EXHAUSTED); + \ 00000188 E100 LDI R16, 16 + \ 0000018A .... RCALL SetErrorFlag + 322 ChargeParameters.NextState = ST_ERROR; + \ 0000018C E50A LDI R16, 90 + \ 0000018E 9300.... STS (ChargeParameters + 4), R16 + 323 } + 324 } + 325 break; + 326 + 327 + 328 default: // Shouldn't end up here, but is needed for MISRA compliance. + 329 break; + 330 } + 331 } + 332 } + \ ??HaltNow_2: + \ 00000192 0F99 LSL R25 + \ 00000194 CF39 RJMP ??HaltNow_0 + 333 + 334 // Standard checks: + 335 + 336 // Battery too cold or hot? + 337 if ((BattData.Temperature <= HaltParameters.TemperatureMin) || + 338 (BattData.Temperature >= HaltParameters.TemperatureMax)) { + \ ??HaltNow_1: + \ 00000196 .... LDI R30, LOW(HaltParameters) + \ 00000198 .... LDI R31, (HaltParameters) >> 8 + \ 0000019A 8521 LDD R18, Z+9 + \ 0000019C 8532 LDD R19, Z+10 + \ 0000019E 9100.... LDS R16, (BattData + 2) + \ 000001A2 2F10 MOV R17, R16 + \ 000001A4 0F11 LSL R17 + \ 000001A6 0B11 SBC R17, R17 + \ 000001A8 1720 CP R18, R16 + \ 000001AA 0731 CPC R19, R17 + \ 000001AC F464 BRGE ??HaltNow_11 + \ 000001AE 9100.... LDS R16, (BattData + 2) + \ 000001B2 2F10 MOV R17, R16 + \ 000001B4 0F11 LSL R17 + \ 000001B6 0B11 SBC R17, R17 + \ 000001B8 .... LDI R30, LOW(HaltParameters) + \ 000001BA .... LDI R31, (HaltParameters) >> 8 + \ 000001BC 8127 LDD R18, Z+7 + \ 000001BE 8530 LDD R19, Z+8 + \ 000001C0 1702 CP R16, R18 + \ 000001C2 0713 CPC R17, R19 + \ 000001C4 F038 BRCS ??HaltNow_12 + 339 + 340 PWM_Stop(); + \ ??HaltNow_11: + \ 000001C6 .... RCALL PWM_Stop + 341 SetErrorFlag(ERR_BATTERY_TEMPERATURE); + \ 000001C8 E008 LDI R16, 8 + \ 000001CA .... RCALL SetErrorFlag + 342 ChargeParameters.NextState = ST_ERROR; + \ 000001CC E50A LDI R16, 90 + \ 000001CE 9300.... STS (ChargeParameters + 4), R16 + 343 halt = TRUE; + \ 000001D2 E081 LDI R24, 1 + 344 } + 345 + 346 // Battery not OK? + 347 if (!BatteryCheck()) { + \ ??HaltNow_12: + \ 000001D4 .... RCALL BatteryCheck + \ 000001D6 2300 TST R16 + \ 000001D8 F429 BRNE ??HaltNow_13 + 348 PWM_Stop(); + \ 000001DA .... RCALL PWM_Stop + 349 ChargeParameters.NextState = ST_INIT; + \ 000001DC E00A LDI R16, 10 + \ 000001DE 9300.... STS (ChargeParameters + 4), R16 + 350 halt = TRUE; + \ 000001E2 E081 LDI R24, 1 + 351 } + 352 + 353 // Is mains voltage OK? + 354 if (!ADCS.Mains) { + \ ??HaltNow_13: + \ 000001E4 .... LDI R30, LOW(ADCS) + \ 000001E6 .... LDI R31, (ADCS) >> 8 + \ 000001E8 8100 LD R16, Z + \ 000001EA FD06 SBRC R16, 6 + \ 000001EC C005 RJMP ??HaltNow_14 + 355 PWM_Stop(); + \ 000001EE .... RCALL PWM_Stop + 356 ChargeParameters.NextState = ST_SLEEP; + \ 000001F0 E208 LDI R16, 40 + \ 000001F2 9300.... STS (ChargeParameters + 4), R16 + 357 halt = TRUE; + \ 000001F6 E081 LDI R24, 1 + 358 } + 359 + 360 return(halt); + \ ??HaltNow_14: + \ 000001F8 2F08 MOV R16, R24 + \ 000001FA E0E4 LDI R30, 4 + \ 000001FC .... RJMP ?EPILOGUE_B4_L09 + 361 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + ConstantCurrent 4 4 + -> ADC_Wait 4 2 + -> Time_Stop 4 2 + -> Time_Start 4 2 + -> PWM_IncrementDutyCycle 4 2 + -> SetErrorFlag 4 2 + -> PWM_DecrementDutyCycle 4 2 + -> SetErrorFlag 4 2 + -> HaltNow 4 2 + ConstantVoltage 4 4 + -> ADC_Wait 4 2 + -> Time_Stop 4 2 + -> Time_Start 4 2 + -> PWM_IncrementDutyCycle 4 2 + -> SetErrorFlag 4 2 + -> PWM_DecrementDutyCycle 4 2 + -> SetErrorFlag 4 2 + -> HaltNow 4 2 + HaltNow 4 4 + -> ADC_Wait 4 2 + -> Time_Set 4 2 + -> Time_Left 4 2 + -> Time_Set 4 2 + -> Time_Left 4 2 + -> PWM_Stop 4 2 + -> SetErrorFlag 4 2 + -> PWM_Stop 4 2 + -> SetErrorFlag 4 2 + -> BatteryCheck 4 2 + -> PWM_Stop 4 2 + -> PWM_Stop 4 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_OCR1B 1 + ChargeParameters 5 + HaltParameters 17 + ConstantCurrent 180 + ConstantVoltage 156 + HaltNow 510 + Others 6 + + + 1 byte in segment ABSOLUTE + 846 bytes in segment CODE + 6 bytes in segment INITTAB + 22 bytes in segment NEAR_Z + + 846 bytes of CODE memory (+ 6 bytes shared) + 22 bytes of DATA memory (+ 1 byte shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/chargefunc.s90 b/BaseTinyFirmware/IAR/Debug/List/chargefunc.s90 new file mode 100644 index 0000000..d189a26 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/chargefunc.s90 @@ -0,0 +1,916 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\chargefu / +// nc.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME chargefunc + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?EPILOGUE_B4_L09 + EXTERN ?PROLOGUE4_L09 + EXTERN ?S_MUL_L02 + EXTERN ?need_segment_init + EXTERN __eeget8_16 + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBLIC ChargeParameters + PUBLIC ConstantCurrent + PUBLIC ConstantVoltage + PUBLIC HaltNow + PUBLIC HaltParameters + PUBWEAK _A_OCR1B + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN ADC_Wait + EXTERN Time_Stop + EXTERN Time_Start + EXTERN PWM_IncrementDutyCycle + EXTERN SetErrorFlag + EXTERN PWM_DecrementDutyCycle + EXTERN Time_Set + EXTERN Time_Left + EXTERN PWM_Stop + EXTERN BatteryCheck + EXTERN ADCS + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + +// C:\home\kevin\pub\src\bc100_cal\IAR\chargefunc.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Charge functions +// 6 * +// 7 * Contains the functions for charging with constant current and voltage, +// 8 * and for deciding when to halt. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 * +// 14 * \par Documentation +// 15 * For comprehensive code documentation, supported compilers, compiler +// 16 * settings and supported devices see readme.html +// 17 * +// 18 * \author +// 19 * Atmel Corporation: http://www.atmel.com \n +// 20 * Support email: avr@atmel.com +// 21 * +// 22 * +// 23 * $Name$ +// 24 * $Revision: 2299 $ +// 25 * $RCSfile$ +// 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $ +// 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 28 ******************************************************************************/ +// 29 +// 30 #include + + ASEGN ABSOLUTE:DATA:NOROOT,04cH +// volatile __io _A_OCR1B +_A_OCR1B: + DS 1 +// 31 +// 32 #include "enums.h" +// 33 #include "structs.h" +// 34 +// 35 #include "ADC.h" +// 36 #include "battery.h" +// 37 #include "chargefunc.h" +// 38 #include "main.h" +// 39 #include "menu.h" +// 40 #include "PWM.h" +// 41 #include "statefunc.h" +// 42 #include "time.h" +// 43 +// 44 #ifdef NIMH +// 45 #include "NIMHspecs.h" +// 46 #endif // NIMH +// 47 +// 48 #ifdef LIION +// 49 #include "LIIONspecs.h" +// 50 #endif // LIION +// 51 +// 52 +// 53 //****************************************************************************** +// 54 // Variables +// 55 //****************************************************************************** +// 56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage(). + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 57 ChargeParameters_t ChargeParameters; +ChargeParameters: + DS 5 +// 58 +// 59 //! Struct that holds parameters for HaltNow(). + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 60 HaltParameters_t HaltParameters; +HaltParameters: + DS 17 +// 61 +// 62 +// 63 //****************************************************************************** +// 64 // Functions +// 65 //****************************************************************************** +// 66 /*! \brief Charges battery with a constant current. +// 67 * +// 68 * This function applies a constant current (set in ChargeParameters.Current) +// 69 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and +// 70 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n +// 71 * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n +// 72 * If the Master inhibits charging, timers are stopped and PWM output dropped. +// 73 * Once the battery is no longer flagged for charge inhibit, timers are +// 74 * started again and charging resumed. +// 75 * +// 76 * \retval ChargeParameters.NextState Next state once this stage is done. +// 77 * If no errors occured, this will be whatever was set in Charge(). Otherwise, +// 78 * HaltNow() will have set a new next state. +// 79 */ + + RSEG CODE:CODE:NOROOT(1) +// 80 unsigned char ConstantCurrent(void) +ConstantCurrent: +// 81 { + RCALL ?PROLOGUE4_L09 +// 82 unsigned char error = FALSE, + LDI R24, 0 +// 83 wasStopped = FALSE; + LDI R25, 0 +// 84 +// 85 do { +// 86 // Wait for ADC conversions to complete. +// 87 ADC_Wait(); +??ConstantCurrent_0: + RCALL ADC_Wait +// 88 +// 89 // If Master has flagged for a charge inhibit, pause charging. +// 90 // (This is to prevent damage during prolonged serial communication.) +// 91 if (BattControl[BattActive].ChargeInhibit) { + LDS R16, BattActive + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + ANDI R16, 0x04 + TST R16 + BREQ ??ConstantCurrent_1 +// 92 wasStopped = TRUE; + LDI R25, 1 +// 93 Time_Stop(); + RCALL Time_Stop +// 94 OCR1B = 0; + LDI R16, 0 + OUT 0x2C, R16 + RJMP ??ConstantCurrent_2 +// 95 } else { +// 96 // Continue charging! +// 97 if (wasStopped) { +??ConstantCurrent_1: + TST R25 + BREQ ??ConstantCurrent_3 +// 98 wasStopped = FALSE; + LDI R25, 0 +// 99 +// 100 // Timer variables are not reset by this. +// 101 Time_Start(); + RCALL Time_Start +// 102 } +// 103 +// 104 // Adjust the charge current to within ChargeParameters.Current +// 105 // +/- BAT_CURRENT_HYST. +// 106 if ((ADCS.avgIBAT < 0) || +// 107 (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { +??ConstantCurrent_3: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+22 + LDD R17, Z+23 + TST R17 + BRMI ??ConstantCurrent_4 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+22 + LDD R19, Z+23 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + LDD R16, Z+2 + LDD R17, Z+3 + SUBI R16, 3 + SBCI R17, 0 + CP R18, R16 + CPC R19, R17 + BRCC ??ConstantCurrent_5 +// 108 +// 109 if(!PWM_IncrementDutyCycle()) { +??ConstantCurrent_4: + RCALL PWM_IncrementDutyCycle + TST R16 + BRNE ??ConstantCurrent_2 +// 110 #ifdef ABORT_IF_PWM_MAX +// 111 // If the duty cycle cannot be incremented, flag error and +// 112 // go to error state. +// 113 SetErrorFlag(ERR_PWM_CONTROL); + LDI R16, 4 + RCALL SetErrorFlag +// 114 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (ChargeParameters + 4), R16 +// 115 error = TRUE; + LDI R24, 1 + RJMP ??ConstantCurrent_2 +// 116 #endif +// 117 } +// 118 } else if ((ADCS.avgIBAT >= 0) && +// 119 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { +??ConstantCurrent_5: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+22 + LDD R17, Z+23 + TST R17 + BRMI ??ConstantCurrent_2 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + LDD R26, Z+2 + LDD R27, Z+3 + ADIW R27:R26, 3 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+22 + LDD R17, Z+23 + CP R26, R16 + CPC R27, R17 + BRCC ??ConstantCurrent_2 +// 120 +// 121 if(!PWM_DecrementDutyCycle()) { + RCALL PWM_DecrementDutyCycle + TST R16 + BRNE ??ConstantCurrent_2 +// 122 #ifdef ABORT_IF_PWM_MIN +// 123 // If the duty cycle cannot be decremented, flag error and +// 124 // go to error state. +// 125 SetErrorFlag(ERR_PWM_CONTROL); + LDI R16, 4 + RCALL SetErrorFlag +// 126 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (ChargeParameters + 4), R16 +// 127 error = TRUE; + LDI R24, 1 +// 128 #endif +// 129 } +// 130 } +// 131 } +// 132 } while (!HaltNow() && !error); +??ConstantCurrent_2: + RCALL HaltNow + TST R16 + BRNE ??ConstantCurrent_6 + TST R24 + BRNE $+2+2 + RJMP ??ConstantCurrent_0 +// 133 +// 134 // Return the next state to Charge(). If an error has occured, this will +// 135 // point to some other state than the next state of charging. +// 136 return(ChargeParameters.NextState); +??ConstantCurrent_6: + LDS R16, (ChargeParameters + 4) + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 + REQUIRE _A_OCR1B +// 137 } +// 138 +// 139 +// 140 /*! \brief Charges battery with a constant voltage +// 141 * +// 142 * This function applies a constant voltage (set in ChargeParameters.Voltage) +// 143 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and +// 144 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n +// 145 * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n +// 146 * If the Master inhibits charging, timers are stopped and PWM output dropped. +// 147 * Once the battery is no longer flagged for charge inhibit, timers are +// 148 * started again and charging resumed. +// 149 * +// 150 * \retval ChargeParameters.NextState Next state once this stage is done. +// 151 * If no errors occured, this will be whatever was set in Charge(). Otherwise, +// 152 * HaltNow() will have set a new next state. +// 153 */ + + RSEG CODE:CODE:NOROOT(1) +// 154 unsigned char ConstantVoltage(void) +ConstantVoltage: +// 155 { + RCALL ?PROLOGUE4_L09 +// 156 unsigned char error = FALSE, + LDI R24, 0 +// 157 wasStopped = FALSE; + LDI R25, 0 +// 158 +// 159 do{ +// 160 +// 161 // Wait for ADC conversions to complete. +// 162 ADC_Wait(); +??ConstantVoltage_0: + RCALL ADC_Wait +// 163 +// 164 // If Master has flagged for a charge inhibit, pause charging. +// 165 // (This is to prevent damage during prolonged serial communication.) +// 166 if (BattControl[BattActive].ChargeInhibit) { + LDS R16, BattActive + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + ANDI R16, 0x04 + TST R16 + BREQ ??ConstantVoltage_1 +// 167 wasStopped = TRUE; + LDI R25, 1 +// 168 Time_Stop(); + RCALL Time_Stop +// 169 OCR1B = 0; + LDI R16, 0 + OUT 0x2C, R16 + RJMP ??ConstantVoltage_2 +// 170 } +// 171 +// 172 else { +// 173 // Continue charging! +// 174 if (wasStopped) { +??ConstantVoltage_1: + TST R25 + BREQ ??ConstantVoltage_3 +// 175 wasStopped = FALSE; + LDI R25, 0 +// 176 +// 177 // Timer variables aren't reset by this. +// 178 Time_Start(); + RCALL Time_Start +// 179 } +// 180 +// 181 // Adjust the charge voltage to within ChargeParameters.Voltage +// 182 // +/- BAT_VOLTAGE_HYST. +// 183 if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { +??ConstantVoltage_3: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+10 + LDD R19, Z+11 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + LD R16, Z + LDD R17, Z+1 + SUBI R16, 10 + SBCI R17, 0 + CP R18, R16 + CPC R19, R17 + BRCC ??ConstantVoltage_4 +// 184 +// 185 if(!PWM_IncrementDutyCycle()) { + RCALL PWM_IncrementDutyCycle + TST R16 + BRNE ??ConstantVoltage_2 +// 186 #ifdef ABORT_IF_PWM_MAX +// 187 // Flag PWM control error and go to error-state if the duty +// 188 // cycle cannot be incremented. +// 189 SetErrorFlag(ERR_PWM_CONTROL); + LDI R16, 4 + RCALL SetErrorFlag +// 190 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (ChargeParameters + 4), R16 +// 191 error = TRUE; + LDI R24, 1 + RJMP ??ConstantVoltage_2 +// 192 #endif +// 193 } +// 194 } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { +??ConstantVoltage_4: + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + LD R26, Z + LDD R27, Z+1 + ADIW R27:R26, 10 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + CP R26, R16 + CPC R27, R17 + BRCC ??ConstantVoltage_2 +// 195 +// 196 if(!PWM_DecrementDutyCycle()) { + RCALL PWM_DecrementDutyCycle + TST R16 + BRNE ??ConstantVoltage_2 +// 197 #ifdef ABORT_IF_PWM_MIN +// 198 // Flag PWM control error and go to error-state if duty +// 199 // cycle cannot be decremented. +// 200 SetErrorFlag(ERR_PWM_CONTROL); + LDI R16, 4 + RCALL SetErrorFlag +// 201 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (ChargeParameters + 4), R16 +// 202 error = TRUE; + LDI R24, 1 +// 203 #endif +// 204 } +// 205 } +// 206 } +// 207 +// 208 } while (!HaltNow() && !error); +??ConstantVoltage_2: + RCALL HaltNow + TST R16 + BRNE ??ConstantVoltage_5 + TST R24 + BRNE $+2+2 + RJMP ??ConstantVoltage_0 +// 209 +// 210 // Return the next state to Charge(). If an error has occured, this will +// 211 // point to some other state than the next state of charging. +// 212 return(ChargeParameters.NextState); +??ConstantVoltage_5: + LDS R16, (ChargeParameters + 4) + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 + REQUIRE _A_OCR1B +// 213 } +// 214 +// 215 +// 216 /*! \brief Determines when to halt charging. +// 217 * +// 218 * This function evaluates parameters depending on what has been flagged in +// 219 * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should +// 220 * halt or not.\n +// 221 * In addition, error flagging on timeout (battery exhaustion) can be set.\n +// 222 * +// 223 * The function also checks if the battery temperature is within limits, +// 224 * if mains is OK, and if BatteryCheck() returns TRUE. +// 225 * If an error is detected, the associated errorflag is set and +// 226 * ChargeParameters.NextState is changed to an appropriate state. +// 227 * +// 228 * \retval TRUE Halt now. +// 229 * \retval FALSE Don't halt now. +// 230 * +// 231 * \note See chargefunc.h for definitions of halt flags. +// 232 * \note It is generally a bad idea not to halt on a timeout. +// 233 * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be +// 234 * reset in Charge() before calling a charging-function. +// 235 * +// 236 * \todo "Priorities" of standard error checks OK? +// 237 */ + + RSEG CODE:CODE:NOROOT(1) +// 238 unsigned char HaltNow(void) +HaltNow: +// 239 { + RCALL ?PROLOGUE4_L09 +// 240 unsigned char i, halt = FALSE; + LDI R24, 0 +// 241 +// 242 // Wait for a full ADC-cycle to finish. +// 243 ADC_Wait(); + RCALL ADC_Wait +// 244 +// 245 // Evaluate ADC readings according to HaltFlags. Flag errors if selected. +// 246 // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR. +// 247 // (Gets overridden if either mains is failing, or the battery changes.) +// 248 for (i = 0x01; i != 0; i <<= 1) { + LDI R25, 1 +??HaltNow_0: + TST R25 + BRNE $+2+2 + RJMP ??HaltNow_1 +// 249 if (HaltParameters.HaltFlags & i) { + LDS R16, HaltParameters + AND R16, R25 + TST R16 + BRNE $+2+2 + RJMP ??HaltNow_2 +// 250 switch (i) { + MOV R16, R25 + SUBI R16, 1 + BREQ ??HaltNow_3 + DEC R16 + BREQ ??HaltNow_4 + SUBI R16, 2 + BREQ ??HaltNow_5 + SUBI R16, 4 + BRNE $+2+2 + RJMP ??HaltNow_6 + SUBI R16, 8 + BRNE $+2+2 + RJMP ??HaltNow_7 + RJMP ??HaltNow_2 +// 251 // Is VBAT less than the recorded maximum? +// 252 case HALT_VOLTAGE_DROP: +// 253 +// 254 // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. +// 255 if (ADCS.VBAT > HaltParameters.VBATMax) { +??HaltNow_3: + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R16, Z+13 + LDD R17, Z+14 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+10 + LDD R19, Z+11 + CP R16, R18 + CPC R17, R19 + BRCC ??HaltNow_8 +// 256 HaltParameters.VBATMax = ADCS.VBAT; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+13, R16 + STD Z+14, R17 + RJMP ??HaltNow_2 +// 257 } else if((HaltParameters.VBATMax - ADCS.VBAT) >= +// 258 HaltParameters.VoltageDrop) { +??HaltNow_8: + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R16, Z+13 + LDD R17, Z+14 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+10 + LDD R19, Z+11 + SUB R16, R18 + SBC R17, R19 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R18, Z+1 + LDD R19, Z+2 + CP R16, R18 + CPC R17, R19 + BRCC $+2+2 + RJMP ??HaltNow_2 +// 259 halt = TRUE; + LDI R24, 1 + RJMP ??HaltNow_2 +// 260 } +// 261 break; +// 262 +// 263 +// 264 // Has VBAT reached the maximum limit? +// 265 case HALT_VOLTAGE_MAX: +// 266 +// 267 if (ADCS.VBAT >= HaltParameters.VoltageMax) { +??HaltNow_4: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R18, Z+3 + LDD R19, Z+4 + CP R16, R18 + CPC R17, R19 + BRCC $+2+2 + RJMP ??HaltNow_2 +// 268 halt = TRUE; + LDI R24, 1 + RJMP ??HaltNow_2 +// 269 } +// 270 break; +// 271 +// 272 +// 273 // Has IBAT reached the minimum limit? +// 274 case HALT_CURRENT_MIN: +// 275 +// 276 if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { +??HaltNow_5: + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R16, Z+5 + LDD R17, Z+6 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+22 + LDD R19, Z+23 + CP R16, R18 + CPC R17, R19 + BRCC $+2+2 + RJMP ??HaltNow_2 +// 277 halt = TRUE; + LDI R24, 1 + RJMP ??HaltNow_2 +// 278 } +// 279 break; +// 280 +// 281 +// 282 // Is the temperature rising too fast? +// 283 case HALT_TEMPERATURE_RISE: +// 284 +// 285 // If rawNTC has increased, the temperature has dropped. +// 286 // We can store this value for now, and start the timer. +// 287 // Otherwise, check if NTC has changed too fast. +// 288 if (ADCS.rawNTC > HaltParameters.LastNTC) { +??HaltNow_6: + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R16, Z+15 + LDD R17, Z+16 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+4 + LDD R19, Z+5 + CP R16, R18 + CPC R17, R19 + BRCC ??HaltNow_9 +// 289 HaltParameters.LastNTC = ADCS.rawNTC; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+15, R16 + STD Z+16, R17 +// 290 Time_Set(TIMER_TEMP,0,30,0); + LDI R20, 0 + LDI R17, 30 + LDI R18, 0 + LDI R19, 0 + LDI R16, 3 + RCALL Time_Set + RJMP ??HaltNow_2 +// 291 +// 292 // Is the increase in temperature greater than the set threshold? +// 293 } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= +// 294 (BattData.ADCSteps * HaltParameters.TemperatureRise)) { +??HaltNow_9: + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R26, Z+15 + LDD R27, Z+16 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + SUB R26, R16 + SBC R27, R17 + LDS R20, (BattData + 3) + LDI R21, 0 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R16, Z+11 + LDD R17, Z+12 + RCALL ?S_MUL_L02 + CP R26, R16 + CPC R27, R17 + BRCS ??HaltNow_2 +// 295 +// 296 // If this happened within a timeframe of 30 seconds, the +// 297 // temperature is rising faster than we want. +// 298 // If not, update LastNTC and reset timer. +// 299 if (Time_Left(TIMER_TEMP)) { + LDI R16, 3 + RCALL Time_Left + TST R16 + BREQ ??HaltNow_10 +// 300 halt = TRUE; + LDI R24, 1 + RJMP ??HaltNow_2 +// 301 } else { +// 302 HaltParameters.LastNTC = ADCS.rawNTC; +??HaltNow_10: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + STD Z+15, R16 + STD Z+16, R17 +// 303 Time_Set(TIMER_TEMP,0,30,0); + LDI R20, 0 + LDI R17, 30 + LDI R18, 0 + LDI R19, 0 + LDI R16, 3 + RCALL Time_Set + RJMP ??HaltNow_2 +// 304 } +// 305 } +// 306 break; +// 307 +// 308 +// 309 // Is there any time left? +// 310 case HALT_TIME: +// 311 +// 312 if (!Time_Left(TIMER_CHG)) { +??HaltNow_7: + LDI R16, 1 + RCALL Time_Left + TST R16 + BRNE ??HaltNow_2 +// 313 halt = TRUE; + LDI R24, 1 +// 314 +// 315 // If exhaustion flagging is selected, stop the PWM, disable the +// 316 // battery and flag it as exhausted. Make ST_ERROR next state. +// 317 if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LD R16, Z + SBRS R16, 5 + RJMP ??HaltNow_2 +// 318 PWM_Stop(); + RCALL PWM_Stop +// 319 BattControl[BattActive].Enabled = FALSE; + LDS R16, BattActive + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + ANDI R16, 0xFE + LDS R18, BattActive + LDI R19, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R18 + ADC R21, R19 + RCALL __eeput8_16 +// 320 BattData.Exhausted = TRUE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ORI R16, 0x08 + ST Z, R16 +// 321 SetErrorFlag(ERR_BATTERY_EXHAUSTED); + LDI R16, 16 + RCALL SetErrorFlag +// 322 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (ChargeParameters + 4), R16 +// 323 } +// 324 } +// 325 break; +// 326 +// 327 +// 328 default: // Shouldn't end up here, but is needed for MISRA compliance. +// 329 break; +// 330 } +// 331 } +// 332 } +??HaltNow_2: + LSL R25 + RJMP ??HaltNow_0 +// 333 +// 334 // Standard checks: +// 335 +// 336 // Battery too cold or hot? +// 337 if ((BattData.Temperature <= HaltParameters.TemperatureMin) || +// 338 (BattData.Temperature >= HaltParameters.TemperatureMax)) { +??HaltNow_1: + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R18, Z+9 + LDD R19, Z+10 + LDS R16, (BattData + 2) + MOV R17, R16 + LSL R17 + SBC R17, R17 + CP R18, R16 + CPC R19, R17 + BRGE ??HaltNow_11 + LDS R16, (BattData + 2) + MOV R17, R16 + LSL R17 + SBC R17, R17 + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDD R18, Z+7 + LDD R19, Z+8 + CP R16, R18 + CPC R17, R19 + BRCS ??HaltNow_12 +// 339 +// 340 PWM_Stop(); +??HaltNow_11: + RCALL PWM_Stop +// 341 SetErrorFlag(ERR_BATTERY_TEMPERATURE); + LDI R16, 8 + RCALL SetErrorFlag +// 342 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (ChargeParameters + 4), R16 +// 343 halt = TRUE; + LDI R24, 1 +// 344 } +// 345 +// 346 // Battery not OK? +// 347 if (!BatteryCheck()) { +??HaltNow_12: + RCALL BatteryCheck + TST R16 + BRNE ??HaltNow_13 +// 348 PWM_Stop(); + RCALL PWM_Stop +// 349 ChargeParameters.NextState = ST_INIT; + LDI R16, 10 + STS (ChargeParameters + 4), R16 +// 350 halt = TRUE; + LDI R24, 1 +// 351 } +// 352 +// 353 // Is mains voltage OK? +// 354 if (!ADCS.Mains) { +??HaltNow_13: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + SBRC R16, 6 + RJMP ??HaltNow_14 +// 355 PWM_Stop(); + RCALL PWM_Stop +// 356 ChargeParameters.NextState = ST_SLEEP; + LDI R16, 40 + STS (ChargeParameters + 4), R16 +// 357 halt = TRUE; + LDI R24, 1 +// 358 } +// 359 +// 360 return(halt); +??HaltNow_14: + MOV R16, R24 + LDI R30, 4 + RJMP ?EPILOGUE_B4_L09 +// 361 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 1 byte in segment ABSOLUTE +// 846 bytes in segment CODE +// 6 bytes in segment INITTAB +// 22 bytes in segment NEAR_Z +// +// 846 bytes of CODE memory (+ 6 bytes shared) +// 22 bytes of DATA memory (+ 1 byte shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/main.lst b/BaseTinyFirmware/IAR/Debug/List/main.lst new file mode 100644 index 0000000..261a4e6 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/main.lst @@ -0,0 +1,385 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\main.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\main.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\main.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\main.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\main.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Main program file + 6 * + 7 * Contains the main program, which is a basic state machine. + 8 * + 9 * \par Application note: + 10 * AVR458: Charging Li-Ion Batteries with BC100 \n + 11 * AVR463: Charging NiMH Batteries with BC100 + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2302 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $ + 26 * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 /*! \page License + 30 * Copyright (c) 2007, Atmel Corporation All rights reserved. + 31 * + 32 * Redistribution and use in source and binary forms, with or without + 33 * modification, are permitted provided that the following conditions are met: + 34 * + 35 * 1. Redistributions of source code must retain the above copyright notice, + 36 * this list of conditions and the following disclaimer. + 37 * + 38 * 2. Redistributions in binary form must reproduce the above copyright notice, + 39 * this list of conditions and the following disclaimer in the documentation + 40 * and/or other materials provided with the distribution. + 41 * + 42 * 3. The name of ATMEL may not be used to endorse or promote products derived + 43 * from this software without specific prior written permission. + 44 * + 45 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED + 46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + 47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + 48 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + 49 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + 50 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + 51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + 52 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 55 */ + 56 + 57 #include + 58 #include + 59 #include + 60 + 61 #include "structs.h" + 62 + 63 #include "main.h" + 64 #include "ADC.h" + 65 #include "statefunc.h" + 66 #include "battery.h" + 67 #include "menu.h" + 68 #include "OWI.h" + 69 #include "PWM.h" + 70 #include "time.h" + 71 #include "USI.h" + 72 + 73 + 74 + 75 //****************************************************************************** + 76 // Globals + 77 //****************************************************************************** + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 78 unsigned char CurrentState; //!< \brief Global that indicates current state + \ CurrentState: + \ 00000000 DS 1 + 79 //!< + 80 //!< Updated by main(). + 81 //!< \note See menu.h for definition of states. + 82 + 83 + 84 //****************************************************************************** + 85 // Functions + 86 //****************************************************************************** + 87 /*! \brief Main program + 88 * + 89 * The main function goes into an infinite loop, keeping track of the current + 90 * state and the next one. If the next state is different from the current, it + 91 * looks up the address to the next state function, in \ref menu_state[], and + 92 * updates \ref CurrentState. The state function is then called and will + 93 * eventually return a new state, and so the loop reiterates. + 94 * + 95 * \todo The variable inp is passed to all state functions, but is not used + 96 * for anything yet. Remove? + 97 */ + + \ In segment CODE, align 2, keep-with-next + 98 int main( void ) + \ main: + 99 { + \ 00000000 .... RCALL ?PROLOGUE7_L09 + \ 00000002 REQUIRE ?Register_R4_is_cg_reg + \ 00000002 REQUIRE ?Register_R5_is_cg_reg + \ 00000002 REQUIRE ?Register_R6_is_cg_reg + 100 unsigned char nextstate, inp, i; + 101 unsigned char (*pStateFunc)(unsigned char); // Function pointer. + 102 + 103 // Initialize local state variables. + 104 inp = ZERO; + \ 00000002 2466 CLR R6 + 105 CurrentState = nextstate = ST_INIT; + \ 00000004 E00A LDI R16, 10 + \ 00000006 2F90 MOV R25, R16 + \ 00000008 9300.... STS CurrentState, R16 + 106 pStateFunc = NULL; + \ 0000000C E000 LDI R16, 0 + \ 0000000E E010 LDI R17, 0 + \ 00000010 0128 MOVW R5:R4, R17:R16 + 107 + 108 // Look for function associated with current state, get its address. + 109 for (i = 0; menu_state[i].state != 0; i++) { + \ 00000012 E080 LDI R24, 0 + \ ??main_0: + \ 00000014 2F48 MOV R20, R24 + \ 00000016 E050 LDI R21, 0 + \ 00000018 E003 LDI R16, 3 + \ 0000001A E010 LDI R17, 0 + \ 0000001C .... RCALL ?S_MUL_L02 + \ 0000001E .... LDI R30, LOW(menu_state) + \ 00000020 .... LDI R31, (menu_state) >> 8 + \ 00000022 0FE0 ADD R30, R16 + \ 00000024 1FF1 ADC R31, R17 + \ 00000026 9104 LPM R16, Z + \ 00000028 2300 TST R16 + \ 0000002A F0F1 BREQ ??main_1 + 110 if (menu_state[i].state == CurrentState) { + \ 0000002C 2F48 MOV R20, R24 + \ 0000002E E050 LDI R21, 0 + \ 00000030 E003 LDI R16, 3 + \ 00000032 E010 LDI R17, 0 + \ 00000034 .... RCALL ?S_MUL_L02 + \ 00000036 .... LDI R30, LOW(menu_state) + \ 00000038 .... LDI R31, (menu_state) >> 8 + \ 0000003A 0FE0 ADD R30, R16 + \ 0000003C 1FF1 ADC R31, R17 + \ 0000003E 9104 LPM R16, Z + \ 00000040 9110.... LDS R17, CurrentState + \ 00000044 1701 CP R16, R17 + \ 00000046 F471 BRNE ??main_2 + 111 pStateFunc = menu_state[i].pFunc; + \ 00000048 .... LDI R26, LOW((menu_state + 1)) + \ 0000004A .... LDI R27, HIGH((menu_state + 1)) + \ 0000004C 2F48 MOV R20, R24 + \ 0000004E E050 LDI R21, 0 + \ 00000050 E003 LDI R16, 3 + \ 00000052 E010 LDI R17, 0 + \ 00000054 .... RCALL ?S_MUL_L02 + \ 00000056 0FA0 ADD R26, R16 + \ 00000058 1FB1 ADC R27, R17 + \ 0000005A 01FD MOVW R31:R30, R27:R26 + \ 0000005C 9105 LPM R16, Z+ + \ 0000005E 9114 LPM R17, Z + \ 00000060 9731 SBIW R31:R30, 1 + \ 00000062 0128 MOVW R5:R4, R17:R16 + 112 } + 113 } + \ ??main_2: + \ 00000064 9583 INC R24 + \ 00000066 CFD6 RJMP ??main_0 + 114 + 115 while (TRUE) { + 116 // Run function associated with current state, get next state in return. + 117 if (pStateFunc != NULL){ + \ ??main_1: + \ 00000068 E000 LDI R16, 0 + \ 0000006A E010 LDI R17, 0 + \ 0000006C 1640 CP R4, R16 + \ 0000006E 0651 CPC R5, R17 + \ 00000070 F021 BREQ ??main_3 + 118 nextstate = pStateFunc(inp); + \ 00000072 2D06 MOV R16, R6 + \ 00000074 01F2 MOVW R31:R30, R5:R4 + \ 00000076 9509 ICALL + \ 00000078 2F90 MOV R25, R16 + 119 } + 120 + 121 // Look up function for next state, if it differs from the current. + 122 if (nextstate != CurrentState) { + \ ??main_3: + \ 0000007A 9100.... LDS R16, CurrentState + \ 0000007E 1790 CP R25, R16 + \ 00000080 F399 BREQ ??main_1 + 123 CurrentState = nextstate; + \ 00000082 9390.... STS CurrentState, R25 + 124 for ( i = 0; menu_state[i].state != 0; i++) { + \ 00000086 E080 LDI R24, 0 + \ ??main_4: + \ 00000088 2F48 MOV R20, R24 + \ 0000008A E050 LDI R21, 0 + \ 0000008C E003 LDI R16, 3 + \ 0000008E E010 LDI R17, 0 + \ 00000090 .... RCALL ?S_MUL_L02 + \ 00000092 .... LDI R30, LOW(menu_state) + \ 00000094 .... LDI R31, (menu_state) >> 8 + \ 00000096 0FE0 ADD R30, R16 + \ 00000098 1FF1 ADC R31, R17 + \ 0000009A 9104 LPM R16, Z + \ 0000009C 2300 TST R16 + \ 0000009E F321 BREQ ??main_1 + 125 if (menu_state[i].state == CurrentState) { + \ 000000A0 2F48 MOV R20, R24 + \ 000000A2 E050 LDI R21, 0 + \ 000000A4 E003 LDI R16, 3 + \ 000000A6 E010 LDI R17, 0 + \ 000000A8 .... RCALL ?S_MUL_L02 + \ 000000AA .... LDI R30, LOW(menu_state) + \ 000000AC .... LDI R31, (menu_state) >> 8 + \ 000000AE 0FE0 ADD R30, R16 + \ 000000B0 1FF1 ADC R31, R17 + \ 000000B2 9104 LPM R16, Z + \ 000000B4 9110.... LDS R17, CurrentState + \ 000000B8 1701 CP R16, R17 + \ 000000BA F471 BRNE ??main_5 + 126 pStateFunc = menu_state[i].pFunc; + \ 000000BC .... LDI R26, LOW((menu_state + 1)) + \ 000000BE .... LDI R27, HIGH((menu_state + 1)) + \ 000000C0 2F48 MOV R20, R24 + \ 000000C2 E050 LDI R21, 0 + \ 000000C4 E003 LDI R16, 3 + \ 000000C6 E010 LDI R17, 0 + \ 000000C8 .... RCALL ?S_MUL_L02 + \ 000000CA 0FA0 ADD R26, R16 + \ 000000CC 1FB1 ADC R27, R17 + \ 000000CE 01FD MOVW R31:R30, R27:R26 + \ 000000D0 9105 LPM R16, Z+ + \ 000000D2 9114 LPM R17, Z + \ 000000D4 9731 SBIW R31:R30, 1 + \ 000000D6 0128 MOVW R5:R4, R17:R16 + 127 } + 128 } + \ ??main_5: + \ 000000D8 9583 INC R24 + \ 000000DA CFD6 RJMP ??main_4 + 129 } + 130 } + 131 } + 132 + 133 + 134 /* Doxygen documentation mainpage ********************************************/ + 135 /*! \mainpage + 136 * \section intro Introduction + 137 * This documents the software for application note AVR458. This is a charger + 138 * for Li-Ion batteries, based on ATAVRBC100. + 139 * + 140 * \section compinfo Compilation Info + 141 * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC + 142 * the source have to be modified.\n + 143 * \n + 144 * To make project on IAR EWAVR:\n + 145 * Add the .c files to project (ADC.c, battery.c, main.c, menu.c, + 146 * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c, + 147 * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate + 148 * battery data if needed.\n + 149 * \n + 150 * Use device --cpu=tiny861, enable bit definitions in I/O include files, + 151 * optimization low for debug target and high for release, output format: ubrof8 + 152 * for Debug and intel_extended for Release. \n + 153 * + 154 * \section deviceinfo Device Info + 155 * This application is based on the ATtiny 861, but it is possible to migrate + 156 * the design to other AVR microcontrollers, such as pin-compatible devices + 157 * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be + 158 * used, but with reduced functionality. + 159 * + 160 * Required fuse bit settings: + 161 *

+    162           *    FUSE BIT  | SETTING
+    163           *    ----------+--------------------
+    164           *    CKDIV8    | 1 (unprogrammed)
+    165           *    CKSEL3..0 | 0010 (internal osc)
+    166           *    
+ 167 * + 168 * + 169 * \section todo To Do-list + 170 * \todo + 171 * - Finalize master-slave communication protocol + 172 * - Implement discharge mode + 173 * + 174 * \section contactinfo Contact Info + 175 * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n + 176 * For application notes visit + 177 * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n + 178 * Support mail: avr@atmel.com + 179 */ + 180 + 181 + 182 /*! \page misra MISRA C rule violations + 183 * + 184 * \par Rule 1 + 185 * "All code shall conform to ISO 9899 standard C, with no extensions + 186 * permitted." + 187 * + 188 * Extensions are necessary because ISO C has no way of specifying that a + 189 * function should be an interrupt service routine, or that we would like data + 190 * members to be stored in f.ex. EEPROM. + 191 * + 192 * + 193 * \par Rule 37 + 194 * "Bitwise operations shall not be performed on signed integer types." + 195 * + 196 * The compiler assumes all the 1's we shift around to make bitmasks are signed + 197 * integers. Specifying them all to be (unsigned int), either directly or via a + 198 * definition, would fix the rule violations, but also reduce code readability. + 199 * + 200 * + 201 * \par Rule 45 + 202 * "Type casting from any type to or from pointers shall not be used." + 203 * + 204 * Assigning macro NULL, defined in stdlib.h, to a pointer causes this.. + 205 * + 206 * + 207 * \par Rule 96 + 208 * "In the definition of a function-like macro the whole definition, and each + 209 * instance of a parameter, shall be enclosed in parentheses." + 210 * + 211 * It is difficult to use parentheses with void function-like macros. + 212 */ + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + main 7 4 + -> Indirect call 7 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + CurrentState 1 + main 220 + Others 6 + + + 220 bytes in segment CODE + 6 bytes in segment INITTAB + 1 byte in segment NEAR_Z + + 220 bytes of CODE memory (+ 6 bytes shared) + 1 byte of DATA memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/main.s90 b/BaseTinyFirmware/IAR/Debug/List/main.s90 new file mode 100644 index 0000000..b1f8205 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/main.s90 @@ -0,0 +1,411 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\main.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\main.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\main.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME main + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?PROLOGUE7_L09 + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?Register_R6_is_cg_reg + EXTERN ?S_MUL_L02 + EXTERN ?need_segment_init + + PUBWEAK `?` + PUBLIC CurrentState + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + PUBLIC main + + EXTERN menu_state + +// C:\home\kevin\pub\src\bc100_cal\IAR\main.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Main program file +// 6 * +// 7 * Contains the main program, which is a basic state machine. +// 8 * +// 9 * \par Application note: +// 10 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 11 * AVR463: Charging NiMH Batteries with BC100 +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2302 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $ +// 26 * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 /*! \page License +// 30 * Copyright (c) 2007, Atmel Corporation All rights reserved. +// 31 * +// 32 * Redistribution and use in source and binary forms, with or without +// 33 * modification, are permitted provided that the following conditions are met: +// 34 * +// 35 * 1. Redistributions of source code must retain the above copyright notice, +// 36 * this list of conditions and the following disclaimer. +// 37 * +// 38 * 2. Redistributions in binary form must reproduce the above copyright notice, +// 39 * this list of conditions and the following disclaimer in the documentation +// 40 * and/or other materials provided with the distribution. +// 41 * +// 42 * 3. The name of ATMEL may not be used to endorse or promote products derived +// 43 * from this software without specific prior written permission. +// 44 * +// 45 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED +// 46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// 47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND +// 48 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, +// 49 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// 50 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// 51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// 52 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 55 */ +// 56 +// 57 #include +// 58 #include +// 59 #include +// 60 +// 61 #include "structs.h" +// 62 +// 63 #include "main.h" +// 64 #include "ADC.h" +// 65 #include "statefunc.h" +// 66 #include "battery.h" +// 67 #include "menu.h" +// 68 #include "OWI.h" +// 69 #include "PWM.h" +// 70 #include "time.h" +// 71 #include "USI.h" +// 72 +// 73 +// 74 +// 75 //****************************************************************************** +// 76 // Globals +// 77 //****************************************************************************** + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 78 unsigned char CurrentState; //!< \brief Global that indicates current state +CurrentState: + DS 1 +// 79 //!< +// 80 //!< Updated by main(). +// 81 //!< \note See menu.h for definition of states. +// 82 +// 83 +// 84 //****************************************************************************** +// 85 // Functions +// 86 //****************************************************************************** +// 87 /*! \brief Main program +// 88 * +// 89 * The main function goes into an infinite loop, keeping track of the current +// 90 * state and the next one. If the next state is different from the current, it +// 91 * looks up the address to the next state function, in \ref menu_state[], and +// 92 * updates \ref CurrentState. The state function is then called and will +// 93 * eventually return a new state, and so the loop reiterates. +// 94 * +// 95 * \todo The variable inp is passed to all state functions, but is not used +// 96 * for anything yet. Remove? +// 97 */ + + RSEG CODE:CODE:NOROOT(1) +// 98 int main( void ) +main: +// 99 { + RCALL ?PROLOGUE7_L09 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg +// 100 unsigned char nextstate, inp, i; +// 101 unsigned char (*pStateFunc)(unsigned char); // Function pointer. +// 102 +// 103 // Initialize local state variables. +// 104 inp = ZERO; + CLR R6 +// 105 CurrentState = nextstate = ST_INIT; + LDI R16, 10 + MOV R25, R16 + STS CurrentState, R16 +// 106 pStateFunc = NULL; + LDI R16, 0 + LDI R17, 0 + MOVW R5:R4, R17:R16 +// 107 +// 108 // Look for function associated with current state, get its address. +// 109 for (i = 0; menu_state[i].state != 0; i++) { + LDI R24, 0 +??main_0: + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R30, LOW(menu_state) + LDI R31, (menu_state) >> 8 + ADD R30, R16 + ADC R31, R17 + LPM R16, Z + TST R16 + BREQ ??main_1 +// 110 if (menu_state[i].state == CurrentState) { + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R30, LOW(menu_state) + LDI R31, (menu_state) >> 8 + ADD R30, R16 + ADC R31, R17 + LPM R16, Z + LDS R17, CurrentState + CP R16, R17 + BRNE ??main_2 +// 111 pStateFunc = menu_state[i].pFunc; + LDI R26, LOW((menu_state + 1)) + LDI R27, HIGH((menu_state + 1)) + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + ADD R26, R16 + ADC R27, R17 + MOVW R31:R30, R27:R26 + LPM R16, Z+ + LPM R17, Z + SBIW R31:R30, 1 + MOVW R5:R4, R17:R16 +// 112 } +// 113 } +??main_2: + INC R24 + RJMP ??main_0 +// 114 +// 115 while (TRUE) { +// 116 // Run function associated with current state, get next state in return. +// 117 if (pStateFunc != NULL){ +??main_1: + LDI R16, 0 + LDI R17, 0 + CP R4, R16 + CPC R5, R17 + BREQ ??main_3 +// 118 nextstate = pStateFunc(inp); + MOV R16, R6 + MOVW R31:R30, R5:R4 + ICALL + MOV R25, R16 +// 119 } +// 120 +// 121 // Look up function for next state, if it differs from the current. +// 122 if (nextstate != CurrentState) { +??main_3: + LDS R16, CurrentState + CP R25, R16 + BREQ ??main_1 +// 123 CurrentState = nextstate; + STS CurrentState, R25 +// 124 for ( i = 0; menu_state[i].state != 0; i++) { + LDI R24, 0 +??main_4: + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R30, LOW(menu_state) + LDI R31, (menu_state) >> 8 + ADD R30, R16 + ADC R31, R17 + LPM R16, Z + TST R16 + BREQ ??main_1 +// 125 if (menu_state[i].state == CurrentState) { + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R30, LOW(menu_state) + LDI R31, (menu_state) >> 8 + ADD R30, R16 + ADC R31, R17 + LPM R16, Z + LDS R17, CurrentState + CP R16, R17 + BRNE ??main_5 +// 126 pStateFunc = menu_state[i].pFunc; + LDI R26, LOW((menu_state + 1)) + LDI R27, HIGH((menu_state + 1)) + MOV R20, R24 + LDI R21, 0 + LDI R16, 3 + LDI R17, 0 + RCALL ?S_MUL_L02 + ADD R26, R16 + ADC R27, R17 + MOVW R31:R30, R27:R26 + LPM R16, Z+ + LPM R17, Z + SBIW R31:R30, 1 + MOVW R5:R4, R17:R16 +// 127 } +// 128 } +??main_5: + INC R24 + RJMP ??main_4 +// 129 } +// 130 } +// 131 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// 132 +// 133 +// 134 /* Doxygen documentation mainpage ********************************************/ +// 135 /*! \mainpage +// 136 * \section intro Introduction +// 137 * This documents the software for application note AVR458. This is a charger +// 138 * for Li-Ion batteries, based on ATAVRBC100. +// 139 * +// 140 * \section compinfo Compilation Info +// 141 * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC +// 142 * the source have to be modified.\n +// 143 * \n +// 144 * To make project on IAR EWAVR:\n +// 145 * Add the .c files to project (ADC.c, battery.c, main.c, menu.c, +// 146 * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c, +// 147 * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate +// 148 * battery data if needed.\n +// 149 * \n +// 150 * Use device --cpu=tiny861, enable bit definitions in I/O include files, +// 151 * optimization low for debug target and high for release, output format: ubrof8 +// 152 * for Debug and intel_extended for Release. \n +// 153 * +// 154 * \section deviceinfo Device Info +// 155 * This application is based on the ATtiny 861, but it is possible to migrate +// 156 * the design to other AVR microcontrollers, such as pin-compatible devices +// 157 * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be +// 158 * used, but with reduced functionality. +// 159 * +// 160 * Required fuse bit settings: +// 161 *
+//  162  *    FUSE BIT  | SETTING
+//  163  *    ----------+--------------------
+//  164  *    CKDIV8    | 1 (unprogrammed)
+//  165  *    CKSEL3..0 | 0010 (internal osc)
+//  166  *    
+// 167 * +// 168 * +// 169 * \section todo To Do-list +// 170 * \todo +// 171 * - Finalize master-slave communication protocol +// 172 * - Implement discharge mode +// 173 * +// 174 * \section contactinfo Contact Info +// 175 * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n +// 176 * For application notes visit +// 177 * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n +// 178 * Support mail: avr@atmel.com +// 179 */ +// 180 +// 181 +// 182 /*! \page misra MISRA C rule violations +// 183 * +// 184 * \par Rule 1 +// 185 * "All code shall conform to ISO 9899 standard C, with no extensions +// 186 * permitted." +// 187 * +// 188 * Extensions are necessary because ISO C has no way of specifying that a +// 189 * function should be an interrupt service routine, or that we would like data +// 190 * members to be stored in f.ex. EEPROM. +// 191 * +// 192 * +// 193 * \par Rule 37 +// 194 * "Bitwise operations shall not be performed on signed integer types." +// 195 * +// 196 * The compiler assumes all the 1's we shift around to make bitmasks are signed +// 197 * integers. Specifying them all to be (unsigned int), either directly or via a +// 198 * definition, would fix the rule violations, but also reduce code readability. +// 199 * +// 200 * +// 201 * \par Rule 45 +// 202 * "Type casting from any type to or from pointers shall not be used." +// 203 * +// 204 * Assigning macro NULL, defined in stdlib.h, to a pointer causes this.. +// 205 * +// 206 * +// 207 * \par Rule 96 +// 208 * "In the definition of a function-like macro the whole definition, and each +// 209 * instance of a parameter, shall be enclosed in parentheses." +// 210 * +// 211 * It is difficult to use parentheses with void function-like macros. +// 212 */ +// +// 220 bytes in segment CODE +// 6 bytes in segment INITTAB +// 1 byte in segment NEAR_Z +// +// 220 bytes of CODE memory (+ 6 bytes shared) +// 1 byte of DATA memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/menu.lst b/BaseTinyFirmware/IAR/Debug/List/menu.lst new file mode 100644 index 0000000..8b79c7d --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/menu.lst @@ -0,0 +1,141 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\menu.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\menu.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\menu.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\menu.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\menu.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * State menu definition + 6 * + 7 * Contains the definition of the state menu.\n + 8 * The state menu contains all states and adresses to associated functions. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 * + 14 * \par Documentation: + 15 * For comprehensive code documentation, supported compilers, compiler + 16 * settings and supported devices see readme.html + 17 * + 18 * \author + 19 * Atmel Corporation: http://www.atmel.com \n + 20 * Support email: avr@atmel.com + 21 * + 22 * + 23 * $Name$ + 24 * $Revision: 2299 $ + 25 * $RCSfile$ + 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $ + 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 28 ******************************************************************************/ + 29 + 30 #include + 31 + 32 #include "statefunc.h" + 33 #include "charge.h" + 34 #include "main.h" + 35 #include "menu.h" + 36 + 37 + 38 //****************************************************************************** + 39 // State menu (relies on the proper battery type to be defined in main.h!) + 40 //****************************************************************************** + 41 #ifdef NIMH + 42 /*! \brief The state menu + 43 * + 44 * Contains all the defined states and addresses to their associated functions. + 45 */ + + \ In segment NEAR_F, align 1, keep-with-next + 46 __flash const MENU_STATE_t menu_state[] = { + \ menu_state: + \ 00000000 0A DB 10 + \ 00000001 .... DW Initialize/2 + \ 00000003 14 DB 20 + \ 00000004 .... DW BatteryControl/2 + \ 00000006 1E DB 30 + \ 00000007 .... DW Charge/2 + \ 00000009 28 DB 40 + \ 0000000A .... DW `Sleep`/2 + \ 0000000C 32 DB 50 + \ 0000000D .... DW Charge/2 + \ 0000000F 3C DB 60 + \ 00000010 .... DW Charge/2 + \ 00000012 46 DB 70 + \ 00000013 .... DW Charge/2 + \ 00000015 50 DB 80 + \ 00000016 .... DW Discharge/2 + \ 00000018 5A DB 90 + \ 00000019 .... DW Error/2 + \ 0000001B 00 DB 0 + \ 0000001C 0000 DW 0H + 47 // State State function + 48 { ST_INIT, Initialize}, + 49 { ST_BATCON, BatteryControl}, + 50 { ST_PREQUAL, Charge}, + 51 { ST_SLEEP, Sleep}, + 52 { ST_FASTCHARGE, Charge}, + 53 { ST_LOWRATECHARGE, Charge}, + 54 { ST_ENDCHARGE, Charge}, + 55 { ST_DISCHARGE, Discharge}, + 56 { ST_ERROR, Error}, + 57 { 0, NULL}, + 58 }; + 59 #endif // NIMH + 60 + 61 #ifdef LIION + 62 /*! \brief The state menu + 63 * + 64 * Contains all the defined states and addresses to their associated functions. + 65 */ + 66 __flash const MENU_STATE_t menu_state[] = { + 67 // State State function + 68 { ST_INIT, Initialize}, + 69 { ST_BATCON, BatteryControl}, + 70 { ST_PREQUAL, Charge}, + 71 { ST_SLEEP, Sleep}, + 72 { ST_CCURRENT, Charge}, + 73 { ST_CVOLTAGE, Charge}, + 74 { ST_ENDCHARGE, Charge}, + 75 { ST_DISCHARGE, Discharge}, + 76 { ST_ERROR, Error}, + 77 { 0, NULL}, + 78 }; + 79 #endif // LIION + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + menu_state 30 + + + 30 bytes in segment NEAR_F + + 30 bytes of CODE memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/menu.s90 b/BaseTinyFirmware/IAR/Debug/List/menu.s90 new file mode 100644 index 0000000..43a5f51 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/menu.s90 @@ -0,0 +1,165 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\menu.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\menu.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\menu.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME menu + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + PUBLIC menu_state + + EXTERN BatteryControl + EXTERN Charge + EXTERN Discharge + EXTERN Error + EXTERN Initialize + EXTERN `Sleep` + +// C:\home\kevin\pub\src\bc100_cal\IAR\menu.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * State menu definition +// 6 * +// 7 * Contains the definition of the state menu.\n +// 8 * The state menu contains all states and adresses to associated functions. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 * +// 14 * \par Documentation: +// 15 * For comprehensive code documentation, supported compilers, compiler +// 16 * settings and supported devices see readme.html +// 17 * +// 18 * \author +// 19 * Atmel Corporation: http://www.atmel.com \n +// 20 * Support email: avr@atmel.com +// 21 * +// 22 * +// 23 * $Name$ +// 24 * $Revision: 2299 $ +// 25 * $RCSfile$ +// 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $ +// 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 28 ******************************************************************************/ +// 29 +// 30 #include +// 31 +// 32 #include "statefunc.h" +// 33 #include "charge.h" +// 34 #include "main.h" +// 35 #include "menu.h" +// 36 +// 37 +// 38 //****************************************************************************** +// 39 // State menu (relies on the proper battery type to be defined in main.h!) +// 40 //****************************************************************************** +// 41 #ifdef NIMH +// 42 /*! \brief The state menu +// 43 * +// 44 * Contains all the defined states and addresses to their associated functions. +// 45 */ + + RSEG NEAR_F:CODE:NOROOT(0) +// 46 __flash const MENU_STATE_t menu_state[] = { +menu_state: + DB 10 + DW Initialize/2 + DB 20 + DW BatteryControl/2 + DB 30 + DW Charge/2 + DB 40 + DW `Sleep`/2 + DB 50 + DW Charge/2 + DB 60 + DW Charge/2 + DB 70 + DW Charge/2 + DB 80 + DW Discharge/2 + DB 90 + DW Error/2 + DB 0 + DW 0H + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// 47 // State State function +// 48 { ST_INIT, Initialize}, +// 49 { ST_BATCON, BatteryControl}, +// 50 { ST_PREQUAL, Charge}, +// 51 { ST_SLEEP, Sleep}, +// 52 { ST_FASTCHARGE, Charge}, +// 53 { ST_LOWRATECHARGE, Charge}, +// 54 { ST_ENDCHARGE, Charge}, +// 55 { ST_DISCHARGE, Discharge}, +// 56 { ST_ERROR, Error}, +// 57 { 0, NULL}, +// 58 }; +// 59 #endif // NIMH +// 60 +// 61 #ifdef LIION +// 62 /*! \brief The state menu +// 63 * +// 64 * Contains all the defined states and addresses to their associated functions. +// 65 */ +// 66 __flash const MENU_STATE_t menu_state[] = { +// 67 // State State function +// 68 { ST_INIT, Initialize}, +// 69 { ST_BATCON, BatteryControl}, +// 70 { ST_PREQUAL, Charge}, +// 71 { ST_SLEEP, Sleep}, +// 72 { ST_CCURRENT, Charge}, +// 73 { ST_CVOLTAGE, Charge}, +// 74 { ST_ENDCHARGE, Charge}, +// 75 { ST_DISCHARGE, Discharge}, +// 76 { ST_ERROR, Error}, +// 77 { 0, NULL}, +// 78 }; +// 79 #endif // LIION +// +// 30 bytes in segment NEAR_F +// +// 30 bytes of CODE memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/statefunc.lst b/BaseTinyFirmware/IAR/Debug/List/statefunc.lst new file mode 100644 index 0000000..139b867 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/statefunc.lst @@ -0,0 +1,997 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\statefunc # +# .lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\statefunc. # +# r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * State functions + 6 * + 7 * Contains the functions related to the states defined in menu.h.\n + 8 * Also contains related functions, i.e. for checking jumpers, setting + 9 * error flags and "dozing". + 10 * + 11 * \note The state function Charge() is in a separate file since it + 12 * should easily be changed with regard to battery type. + 13 * + 14 * \par Application note: + 15 * AVR458: Charging Li-Ion Batteries with BC100 \n + 16 * AVR463: Charging NiMH Batteries with BC100 + 17 * + 18 * \par Documentation + 19 * For comprehensive code documentation, supported compilers, compiler + 20 * settings and supported devices see readme.html + 21 * + 22 * \author + 23 * Atmel Corporation: http://www.atmel.com \n + 24 * Support email: avr@atmel.com + 25 * + 26 * + 27 * $Name$ + 28 * $Revision: 2299 $ + 29 * $RCSfile$ + 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $ + 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 32 ******************************************************************************/ + 33 + 34 #include + + \ In segment ABSOLUTE, at 0x55 + \ volatile __io _A_MCUCR + \ _A_MCUCR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x54 + \ volatile __io _A_MCUSR + \ _A_MCUSR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x48 + \ volatile __io _A_CLKPR + \ _A_CLKPR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x41 + \ volatile __io _A_WDTCR + \ _A_WDTCR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x37 + \ volatile __io _A_DDRB + \ _A_DDRB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x26 + \ volatile __io _A_ADCSRA + \ _A_ADCSRA: + \ 00000000 DS 1 + 35 #include + 36 #include + 37 + 38 #include "structs.h" + 39 #include "enums.h" + 40 + 41 #include "ADC.h" + 42 #include "statefunc.h" + 43 #include "battery.h" + 44 #include "charge.h" + 45 #include "main.h" + 46 #include "menu.h" + 47 #include "OWI.h" + 48 #include "PWM.h" + 49 #include "time.h" + 50 #include "USI.h" + 51 + 52 + 53 //****************************************************************************** + 54 // Variables + 55 //****************************************************************************** + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 56 unsigned char ErrorFlags; //!< \brief Holds error flags. + \ ErrorFlags: + \ 00000000 DS 1 + 57 //!< \note See statefunc.h for definitions of flags. + 58 + 59 //! \brief Holds the state in which latest error flag was set. + 60 //! \note See menu.h for definitions of states. + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 61 unsigned char ErrorState; + \ ErrorState: + \ 00000000 DS 1 + 62 + 63 + 64 //****************************************************************************** + 65 // Functions + 66 //****************************************************************************** + 67 /*! \brief Initialization + 68 * + 69 * - Sets the system clock prescaler to 1 (run at 8 MHz) + 70 * - Initializes the one-wire interface + 71 * - Clears on-chip EEPROM + 72 * - Sets battery enable pins as outputs, then disables batteries + 73 * - Initializes SPI according to \ref SPIMODE + 74 * - Initializes ADC + 75 * - Initializes timers + 76 * - Reads battery data from both battery inputs (via ADC) + 77 * - Disables batteries again + 78 * - Sets battery A as the current one (\ref BattActive = 0) + 79 * - Clears ErrorFlags + 80 * + 81 * \param inp Not used. + 82 * + 83 * \retval ST_BATCON Next state in the sequence. + 84 */ + + \ In segment CODE, align 2, keep-with-next + 85 unsigned char Initialize(unsigned char inp) + \ Initialize: + 86 { + \ 00000000 .... RCALL ?PROLOGUE4_L09 + \ 00000002 2FB0 MOV R27, R16 + 87 unsigned char i, page; + 88 + 89 // Disable interrupts while setting prescaler. + 90 __disable_interrupt(); + \ 00000004 94F8 CLI + 91 + 92 CLKPR = (1< 8 MHz clock frequency. + \ 0000000A E000 LDI R16, 0 + \ 0000000C BD08 OUT 0x28, R16 + 94 + 95 // Init 1-Wire(R) interface. + 96 OWI_Init(OWIBUS); + \ 0000000E E001 LDI R16, 1 + \ 00000010 .... RCALL OWI_Init + 97 + 98 // Clear on-chip EEPROM. + 99 for (page = 0; page < 4; page++) { + \ 00000012 E090 LDI R25, 0 + \ ??Initialize_0: + \ 00000014 3094 CPI R25, 4 + \ 00000016 F4B8 BRCC ??Initialize_1 + 100 for (i = 0; i < 32; i++) { + \ 00000018 E080 LDI R24, 0 + \ ??Initialize_2: + \ 0000001A 3280 CPI R24, 32 + \ 0000001C F490 BRCC ??Initialize_3 + 101 BattEEPROM[page][i] = 0; + \ 0000001E E0A0 LDI R26, 0 + \ 00000020 2F49 MOV R20, R25 + \ 00000022 E050 LDI R21, 0 + \ 00000024 E200 LDI R16, 32 + \ 00000026 E010 LDI R17, 0 + \ 00000028 .... RCALL ?S_MUL_L02 + \ 0000002A .... LDI R20, LOW(BattEEPROM) + \ 0000002C .... LDI R21, (BattEEPROM) >> 8 + \ 0000002E 0F40 ADD R20, R16 + \ 00000030 1F51 ADC R21, R17 + \ 00000032 2F08 MOV R16, R24 + \ 00000034 E010 LDI R17, 0 + \ 00000036 0F40 ADD R20, R16 + \ 00000038 1F51 ADC R21, R17 + \ 0000003A 2F0A MOV R16, R26 + \ 0000003C .... RCALL __eeput8_16 + 102 } + \ 0000003E 9583 INC R24 + \ 00000040 CFEC RJMP ??Initialize_2 + 103 } + \ ??Initialize_3: + \ 00000042 9593 INC R25 + \ 00000044 CFE7 RJMP ??Initialize_0 + 104 + 105 DDRB = (1<> 8 + \ 00000012 .... RCALL __eeget8_16 + \ 00000014 7001 ANDI R16, 0x01 + \ 00000016 2300 TST R16 + \ 00000018 F451 BRNE ??BatteryControl_2 + \ 0000001A .... LDI R20, LOW((BattControl + 1)) + \ 0000001C .... LDI R21, HIGH((BattControl + 1)) + \ 0000001E .... RCALL __eeget8_16 + \ 00000020 7001 ANDI R16, 0x01 + \ 00000022 2300 TST R16 + \ 00000024 F421 BRNE ??BatteryControl_2 + 156 SetErrorFlag(ERR_NO_BATTERIES_ENABLED); + \ 00000026 E002 LDI R16, 2 + \ 00000028 .... RCALL SetErrorFlag + 157 + 158 return(ST_ERROR); + \ 0000002A E50A LDI R16, 90 + \ 0000002C C01E RJMP ??BatteryControl_1 + 159 } + 160 + 161 // Get ADC-readings, try to read EPROM, and start prequalification + 162 // of any uncharged battery. + 163 for (i = 0; i < 2; i++) { + \ ??BatteryControl_2: + \ 0000002E E080 LDI R24, 0 + \ ??BatteryControl_3: + \ 00000030 3082 CPI R24, 2 + \ 00000032 F4C8 BRCC ??BatteryControl_4 + 164 if (BattControl[i].Enabled) { + \ 00000034 E090 LDI R25, 0 + \ 00000036 .... LDI R20, LOW(BattControl) + \ 00000038 .... LDI R21, (BattControl) >> 8 + \ 0000003A 0F48 ADD R20, R24 + \ 0000003C 1F59 ADC R21, R25 + \ 0000003E .... RCALL __eeget8_16 + \ 00000040 7001 ANDI R16, 0x01 + \ 00000042 2300 TST R16 + \ 00000044 F071 BREQ ??BatteryControl_5 + 165 EnableBattery(i); + \ 00000046 2F08 MOV R16, R24 + \ 00000048 .... RCALL EnableBattery + 166 ADC_Wait(); + \ 0000004A .... RCALL ADC_Wait + 167 + 168 if (BatteryStatusRefresh()) { + \ 0000004C .... RCALL BatteryStatusRefresh + \ 0000004E 2300 TST R16 + \ 00000050 F041 BREQ ??BatteryControl_5 + 169 if (!BattData.Charged) { + \ 00000052 .... LDI R30, LOW(BattData) + \ 00000054 .... LDI R31, (BattData) >> 8 + \ 00000056 8100 LD R16, Z + \ 00000058 FD01 SBRC R16, 1 + \ 0000005A C003 RJMP ??BatteryControl_5 + 170 BatteryDataRefresh(); + \ 0000005C .... RCALL BatteryDataRefresh + 171 + 172 return(ST_PREQUAL); + \ 0000005E E10E LDI R16, 30 + \ 00000060 C004 RJMP ??BatteryControl_1 + 173 } + 174 } + 175 } + 176 } + \ ??BatteryControl_5: + \ 00000062 9583 INC R24 + \ 00000064 CFE5 RJMP ??BatteryControl_3 + 177 + 178 // If we end up here, one or two batteries are found and fully charged. + 179 // Disconnect, so we don't drain them, and go to sleep. + 180 DisableBatteries(); + \ ??BatteryControl_4: + \ 00000066 .... RCALL DisableBatteries + 181 + 182 return(ST_SLEEP); + \ 00000068 E208 LDI R16, 40 + \ ??BatteryControl_1: + \ 0000006A E0E3 LDI R30, 3 + \ 0000006C .... RJMP ?EPILOGUE_B3_L09 + 183 } + 184 + 185 + 186 /*! \brief Start running on batteries + 187 * + 188 * \todo Run on batteries, if battery voltage high enough. + 189 * \todo Jump here when mains voltage drops below threshold + 190 * + 191 */ + + \ In segment CODE, align 2, keep-with-next + 192 unsigned char Discharge(unsigned char inp) + \ Discharge: + 193 { + \ 00000000 2F10 MOV R17, R16 + 194 return(ST_BATCON); // Supply voltage restored, start charging + \ 00000002 E104 LDI R16, 20 + \ 00000004 9508 RET + 195 } + 196 + 197 + 198 /*! \brief Sleeps until either battery needs charging + 199 * + 200 * Calls Doze(), then refreshes the status for both batteries on wakeup. If + 201 * connected batteries are both charged, the function will loop. If not, it's + 202 * back to ST_BATCON. + 203 * + 204 * \param inp Not used. + 205 * + 206 * \retval ST_BATCON Next state if a connected battery isn't fully charged. + 207 */ + + \ In segment CODE, align 2, keep-with-next + 208 unsigned char Sleep(unsigned char inp) + \ `Sleep`: + 209 { + \ 00000000 .... RCALL ?PROLOGUE2_L09 + \ 00000002 2F90 MOV R25, R16 + 210 unsigned char i; + 211 + 212 do { + 213 Doze(); // Take a nap (~8 seconds). + \ ??Sleep_0: + \ 00000004 .... RCALL Doze + 214 + 215 // If any batteries need charging, go to ST_BATCON. + 216 // Otherwise, keep sleeping. + 217 for (i = 0; i < 2; i++) { + \ 00000006 E080 LDI R24, 0 + \ ??Sleep_1: + \ 00000008 3082 CPI R24, 2 + \ 0000000A F478 BRCC ??Sleep_2 + 218 EnableBattery(i); + \ 0000000C 2F08 MOV R16, R24 + \ 0000000E .... RCALL EnableBattery + 219 ADC_Wait(); + \ 00000010 .... RCALL ADC_Wait + 220 if ((BatteryStatusRefresh()) && (!BattData.Charged)) { + \ 00000012 .... RCALL BatteryStatusRefresh + \ 00000014 2300 TST R16 + \ 00000016 F039 BREQ ??Sleep_3 + \ 00000018 .... LDI R30, LOW(BattData) + \ 0000001A .... LDI R31, (BattData) >> 8 + \ 0000001C 8100 LD R16, Z + \ 0000001E FD01 SBRC R16, 1 + \ 00000020 C002 RJMP ??Sleep_3 + 221 return(ST_BATCON); + \ 00000022 E104 LDI R16, 20 + \ 00000024 C004 RJMP ??Sleep_4 + \ ??Sleep_3: + \ 00000026 9583 INC R24 + \ 00000028 CFEF RJMP ??Sleep_1 + 222 } + 223 } + 224 + 225 DisableBatteries(); // Disable both batteries before Doze()! + \ ??Sleep_2: + \ 0000002A .... RCALL DisableBatteries + 226 } while (TRUE); + \ 0000002C CFEB RJMP ??Sleep_0 + \ ??Sleep_4: + \ 0000002E E0E2 LDI R30, 2 + \ 00000030 .... RJMP ?EPILOGUE_B2_L09 + 227 } + 228 + 229 + 230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V) + 231 * + 232 * Waits for ADC-cycles to complete, disables the ADC, then sleeps for + 233 * approx. 8 seconds (Vcc = 5 V) using the watchdog timer. + 234 * On wakeup, ADC is re-enabled. + 235 */ + + \ In segment CODE, align 2, keep-with-next + 236 void Doze(void) + \ Doze: + 237 { + 238 // Wait for this ADC cycle to complete, then halt after the next one. + 239 ADC_Wait(); + \ 00000000 .... RCALL ADC_Wait + 240 ADCS.Halt = TRUE; + \ 00000002 .... LDI R30, LOW(ADCS) + \ 00000004 .... LDI R31, (ADCS) >> 8 + \ 00000006 8100 LD R16, Z + \ 00000008 6800 ORI R16, 0x80 + \ 0000000A 8300 ST Z, R16 + 241 ADCS.Flag = FALSE; + \ 0000000C .... LDI R30, LOW(ADCS) + \ 0000000E .... LDI R31, (ADCS) >> 8 + \ 00000010 8100 LD R16, Z + \ 00000012 7D0F ANDI R16, 0xDF + \ 00000014 8300 ST Z, R16 + 242 + 243 do { + 244 } while (ADCS.Flag == FALSE); + \ ??Doze_0: + \ 00000016 .... LDI R30, LOW(ADCS) + \ 00000018 .... LDI R31, (ADCS) >> 8 + \ 0000001A 8100 LD R16, Z + \ 0000001C FF05 SBRS R16, 5 + \ 0000001E CFFB RJMP ??Doze_0 + 245 + 246 WDTCR = (1<> 8 + \ 00000048 8100 LD R16, Z + \ 0000004A 770F ANDI R16, 0x7F + \ 0000004C 8300 ST Z, R16 + 257 ADCSRA |= (1<> 8 + \ 0000003E 8110 LD R17, Z + \ 00000040 2310 AND R17, R16 + \ 00000042 8310 ST Z, R17 + 305 JumperCheck(); + \ 00000044 .... RCALL JumperCheck + \ 00000046 C03A RJMP ??Error_3 + 306 break; + 307 + 308 + 309 case ERR_NO_BATTERIES_ENABLED: + 310 // Clear if any battery gets enabled. + 311 if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) { + \ ??Error_5: + \ 00000048 .... LDI R20, LOW(BattControl) + \ 0000004A .... LDI R21, (BattControl) >> 8 + \ 0000004C .... RCALL __eeget8_16 + \ 0000004E 7001 ANDI R16, 0x01 + \ 00000050 2300 TST R16 + \ 00000052 F431 BRNE ??Error_9 + \ 00000054 .... LDI R20, LOW((BattControl + 1)) + \ 00000056 .... LDI R21, HIGH((BattControl + 1)) + \ 00000058 .... RCALL __eeget8_16 + \ 0000005A 7001 ANDI R16, 0x01 + \ 0000005C 2300 TST R16 + \ 0000005E F171 BREQ ??Error_3 + 312 ErrorFlags &= ~i; + \ ??Error_9: + \ 00000060 2F08 MOV R16, R24 + \ 00000062 9500 COM R16 + \ 00000064 .... LDI R30, LOW(ErrorFlags) + \ 00000066 .... LDI R31, (ErrorFlags) >> 8 + \ 00000068 8110 LD R17, Z + \ 0000006A 2310 AND R17, R16 + \ 0000006C 8310 ST Z, R17 + \ 0000006E C026 RJMP ??Error_3 + 313 } + 314 break; + 315 + 316 + 317 case ERR_PWM_CONTROL: + 318 // Clear flag. + 319 ErrorFlags &= ~i; + \ ??Error_6: + \ 00000070 2F08 MOV R16, R24 + \ 00000072 9500 COM R16 + \ 00000074 .... LDI R30, LOW(ErrorFlags) + \ 00000076 .... LDI R31, (ErrorFlags) >> 8 + \ 00000078 8110 LD R17, Z + \ 0000007A 2310 AND R17, R16 + \ 0000007C 8310 ST Z, R17 + \ 0000007E C01E RJMP ??Error_3 + 320 break; + 321 + 322 + 323 case ERR_BATTERY_TEMPERATURE: + 324 // Clear flag. + 325 ErrorFlags &= ~i; + \ ??Error_7: + \ 00000080 2F08 MOV R16, R24 + \ 00000082 9500 COM R16 + \ 00000084 .... LDI R30, LOW(ErrorFlags) + \ 00000086 .... LDI R31, (ErrorFlags) >> 8 + \ 00000088 8110 LD R17, Z + \ 0000008A 2310 AND R17, R16 + \ 0000008C 8310 ST Z, R17 + \ 0000008E C016 RJMP ??Error_3 + 326 break; + 327 + 328 + 329 case ERR_BATTERY_EXHAUSTED: + 330 // Try the other battery. + 331 BattData.Exhausted = FALSE; + \ ??Error_8: + \ 00000090 .... LDI R30, LOW(BattData) + \ 00000092 .... LDI R31, (BattData) >> 8 + \ 00000094 8100 LD R16, Z + \ 00000096 7F07 ANDI R16, 0xF7 + \ 00000098 8300 ST Z, R16 + 332 BattActive = (BattActive + 1) % 2; + \ 0000009A 91E0.... LDS R30, BattActive + \ 0000009E E0F0 LDI R31, 0 + \ 000000A0 9631 ADIW R31:R30, 1 + \ 000000A2 018F MOVW R17:R16, R31:R30 + \ 000000A4 E042 LDI R20, 2 + \ 000000A6 E050 LDI R21, 0 + \ 000000A8 .... RCALL ?SS_DIVMOD_L02 + \ 000000AA 9340.... STS BattActive, R20 + 333 ErrorFlags &= ~i; + \ 000000AE 2F08 MOV R16, R24 + \ 000000B0 9500 COM R16 + \ 000000B2 .... LDI R30, LOW(ErrorFlags) + \ 000000B4 .... LDI R31, (ErrorFlags) >> 8 + \ 000000B6 8110 LD R17, Z + \ 000000B8 2310 AND R17, R16 + \ 000000BA 8310 ST Z, R17 + 334 break; + 335 + 336 + 337 default: + 338 break; + 339 } + 340 } + 341 } + \ ??Error_3: + \ 000000BC 0F88 LSL R24 + \ 000000BE CFA6 RJMP ??Error_1 + 342 } while (ErrorFlags); + \ ??Error_2: + \ 000000C0 9100.... LDS R16, ErrorFlags + \ 000000C4 2300 TST R16 + \ 000000C6 F009 BREQ $+2+2 + \ 000000C8 CF9F RJMP ??Error_0 + 343 + 344 return(ST_INIT); + \ 000000CA E00A LDI R16, 10 + \ 000000CC E0E2 LDI R30, 2 + \ 000000CE .... RJMP ?EPILOGUE_B2_L09 + 345 } + 346 + 347 + 348 /*! \brief Sets the specified error-flag and saves the current state + 349 * + 350 * Updates \ref ErrorFlags and \ref ErrorState. + 351 * + 352 * \note Error flags are specified in statefunc.h. + 353 * + 354 * \param Flag Specifies what error to flag. + 355 */ + + \ In segment CODE, align 2, keep-with-next + 356 void SetErrorFlag(unsigned char Flag) + \ SetErrorFlag: + 357 { + 358 ErrorFlags |= Flag; + \ 00000000 .... LDI R30, LOW(ErrorFlags) + \ 00000002 .... LDI R31, (ErrorFlags) >> 8 + \ 00000004 8110 LD R17, Z + \ 00000006 2B10 OR R17, R16 + \ 00000008 8310 ST Z, R17 + 359 ErrorState = CurrentState; + \ 0000000A 9110.... LDS R17, CurrentState + \ 0000000E 9310.... STS ErrorState, R17 + 360 } + \ 00000012 9508 RET + 361 + 362 + 363 /*! \brief Checks on-board jumpers. + 364 * + 365 * Checks on-board jumpers by disconnecting all loads, engaging the PWM and + 366 * increasing the duty cycle until conditioned output voltage equals conditioned + 367 * input voltage. At low PWM duty and no load buck output should be zero and, + 368 * when increasing PWM duty, should quickly jump to steady state output roughly + 369 * equal to input voltage. Will disable and leave disabled all batteries. + 370 * + 371 * \retval FALSE If jumper or load mismatch. + 372 * \retval TRUE If everything OK. + 373 */ + + \ In segment CODE, align 2, keep-with-next + 374 unsigned char JumperCheck(void) + \ JumperCheck: + 375 { + 376 DisableBatteries(); // Disconnect, or loads may be destroyed! + \ 00000000 .... RCALL DisableBatteries + 377 + 378 PWM_Start(); // Start PWM (controls the buck charger). + \ 00000002 .... RCALL PWM_Start + 379 + 380 // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s. + 381 Time_Set(TIMER_GEN,0,1,0); + \ 00000004 E040 LDI R20, 0 + \ 00000006 E011 LDI R17, 1 + \ 00000008 E020 LDI R18, 0 + \ 0000000A E030 LDI R19, 0 + \ 0000000C E002 LDI R16, 2 + \ 0000000E .... RCALL Time_Set + 382 + 383 do { + 384 // If the PWM output voltage saturates the ADC, stop PWM output and + 385 // report a failure. + 386 if (ADCS.rawVBAT == 1023) { + \ ??JumperCheck_0: + \ 00000010 .... LDI R30, LOW(ADCS) + \ 00000012 .... LDI R31, (ADCS) >> 8 + \ 00000014 8106 LDD R16, Z+6 + \ 00000016 8117 LDD R17, Z+7 + \ 00000018 3F0F CPI R16, 255 + \ 0000001A E023 LDI R18, 3 + \ 0000001C 0712 CPC R17, R18 + \ 0000001E F419 BRNE ??JumperCheck_1 + 387 PWM_Stop(); + \ 00000020 .... RCALL PWM_Stop + 388 return(FALSE); + \ 00000022 E000 LDI R16, 0 + \ 00000024 9508 RET + 389 } + 390 + 391 // If the absolute difference between measured (VIN - VBAT) and the + 392 // typical value are below our set maximum, everything is OK. + 393 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) < + 394 VIN_VBAT_DIFF_MAX ) { + \ ??JumperCheck_1: + \ 00000026 .... LDI R30, LOW(ADCS) + \ 00000028 .... LDI R31, (ADCS) >> 8 + \ 0000002A 8500 LDD R16, Z+8 + \ 0000002C 8511 LDD R17, Z+9 + \ 0000002E 5508 SUBI R16, 88 + \ 00000030 4012 SBCI R17, 2 + \ 00000032 .... LDI R30, LOW(ADCS) + \ 00000034 .... LDI R31, (ADCS) >> 8 + \ 00000036 8522 LDD R18, Z+10 + \ 00000038 8533 LDD R19, Z+11 + \ 0000003A 1B02 SUB R16, R18 + \ 0000003C 0B13 SBC R17, R19 + \ 0000003E .... RCALL abs + \ 00000040 3F04 CPI R16, 244 + \ 00000042 E021 LDI R18, 1 + \ 00000044 0712 CPC R17, R18 + \ 00000046 F41C BRGE ??JumperCheck_2 + 395 + 396 PWM_Stop(); + \ 00000048 .... RCALL PWM_Stop + 397 return(TRUE); + \ 0000004A E001 LDI R16, 1 + \ 0000004C 9508 RET + 398 } + 399 + 400 // Charge current is too high -> check load and jumper J405 and J406. + 401 if (abs(ADCS.IBAT) > 100) { + \ ??JumperCheck_2: + \ 0000004E .... LDI R30, LOW(ADCS) + \ 00000050 .... LDI R31, (ADCS) >> 8 + \ 00000052 8504 LDD R16, Z+12 + \ 00000054 8515 LDD R17, Z+13 + \ 00000056 .... RCALL abs + \ 00000058 3605 CPI R16, 101 + \ 0000005A E020 LDI R18, 0 + \ 0000005C 0712 CPC R17, R18 + \ 0000005E F01C BRLT ??JumperCheck_3 + 402 PWM_Stop(); + \ 00000060 .... RCALL PWM_Stop + 403 return(FALSE); + \ 00000062 E000 LDI R16, 0 + \ 00000064 9508 RET + 404 } + 405 + 406 // If the PWM output can't be increased high enough -> check jumpers + 407 // J400-J404, J407 and J408. + 408 if (!PWM_IncrementDutyCycle()) { + \ ??JumperCheck_3: + \ 00000066 .... RCALL PWM_IncrementDutyCycle + \ 00000068 2300 TST R16 + \ 0000006A F419 BRNE ??JumperCheck_4 + 409 PWM_Stop(); + \ 0000006C .... RCALL PWM_Stop + 410 return(FALSE); + \ 0000006E E000 LDI R16, 0 + \ 00000070 9508 RET + 411 } + 412 + 413 // Wait for ADC conversions to complete + 414 ADC_Wait(); + \ ??JumperCheck_4: + \ 00000072 .... RCALL ADC_Wait + 415 } while (Time_Left(TIMER_GEN)); + \ 00000074 E002 LDI R16, 2 + \ 00000076 .... RCALL Time_Left + \ 00000078 2300 TST R16 + \ 0000007A F651 BRNE ??JumperCheck_0 + 416 + 417 + 418 // If we end up here, the measurements took too long. + 419 PWM_Stop(); + \ 0000007C .... RCALL PWM_Stop + 420 return(FALSE); + \ 0000007E E000 LDI R16, 0 + \ 00000080 9508 RET + 421 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + BatteryControl 3 4 + -> JumperCheck 3 2 + -> SetErrorFlag 3 2 + -> EnableBattery 3 2 + -> ADC_Wait 3 2 + -> BatteryStatusRefresh 3 2 + -> BatteryDataRefresh 3 2 + -> DisableBatteries 3 2 + Discharge 0 2 + Doze 0 2 + -> ADC_Wait 0 2 + -> ADC_Wait 0 2 + Error 2 4 + -> PWM_Stop 2 2 + -> DisableBatteries 2 2 + -> Doze 2 2 + -> JumperCheck 2 2 + Initialize 4 4 + -> OWI_Init 4 2 + -> DisableBatteries 4 2 + -> SPI_Init 4 2 + -> ADC_Init 4 2 + -> Time_Init 4 2 + -> EnableBattery 4 2 + -> ADC_Wait 4 2 + -> BatteryStatusRefresh 4 2 + -> DisableBatteries 4 2 + JumperCheck 0 2 + -> DisableBatteries 0 2 + -> PWM_Start 0 2 + -> Time_Set 0 2 + -> PWM_Stop 0 2 + -> abs 0 2 + -> PWM_Stop 0 2 + -> abs 0 2 + -> PWM_Stop 0 2 + -> PWM_IncrementDutyCycle 0 2 + -> PWM_Stop 0 2 + -> ADC_Wait 0 2 + -> Time_Left 0 2 + -> PWM_Stop 0 2 + SetErrorFlag 0 2 + Sleep 2 2 + -> Doze 2 2 + -> EnableBattery 2 2 + -> ADC_Wait 2 2 + -> BatteryStatusRefresh 2 2 + -> DisableBatteries 2 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_MCUCR 1 + _A_MCUSR 1 + _A_CLKPR 1 + _A_WDTCR 1 + _A_DDRB 1 + _A_ADCSRA 1 + ErrorFlags 1 + ErrorState 1 + Initialize 122 + BatteryControl 110 + Discharge 6 + Sleep 50 + Doze 88 + Error 208 + SetErrorFlag 20 + JumperCheck 130 + Others 6 + + + 6 bytes in segment ABSOLUTE + 734 bytes in segment CODE + 6 bytes in segment INITTAB + 2 bytes in segment NEAR_Z + + 734 bytes of CODE memory (+ 6 bytes shared) + 2 bytes of DATA memory (+ 6 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/statefunc.s90 b/BaseTinyFirmware/IAR/Debug/List/statefunc.s90 new file mode 100644 index 0000000..4c8dfd3 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/statefunc.s90 @@ -0,0 +1,1001 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:39 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c / +// Command line = C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IA / +// R\Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\De / +// bug\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug / +// \List\ --initializers_in_flash -z2 --no_cse / +// --no_inline --no_code_motion --no_cross_call / +// --no_clustering --no_tbaa --debug / +// -DENABLE_BIT_DEFINITIONS -e --require_prototypes -I / +// "C:\Program Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 / +// List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\statefun / +// c.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME statefunc + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?EPILOGUE_B2_L09 + EXTERN ?EPILOGUE_B3_L09 + EXTERN ?EPILOGUE_B4_L09 + EXTERN ?PROLOGUE2_L09 + EXTERN ?PROLOGUE3_L09 + EXTERN ?PROLOGUE4_L09 + EXTERN ?SS_DIVMOD_L02 + EXTERN ?S_MUL_L02 + EXTERN ?need_segment_init + EXTERN __eeget8_16 + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBLIC BatteryControl + PUBLIC Discharge + PUBLIC Doze + PUBLIC Error + PUBLIC ErrorFlags + PUBLIC ErrorState + PUBLIC Initialize + PUBLIC JumperCheck + PUBLIC SetErrorFlag + PUBLIC `Sleep` + PUBWEAK _A_ADCSRA + PUBWEAK _A_CLKPR + PUBWEAK _A_DDRB + PUBWEAK _A_MCUCR + PUBWEAK _A_MCUSR + PUBWEAK _A_WDTCR + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN OWI_Init + EXTERN DisableBatteries + EXTERN SPI_Init + EXTERN ADC_Init + EXTERN Time_Init + EXTERN EnableBattery + EXTERN ADC_Wait + EXTERN BatteryStatusRefresh + EXTERN BatteryDataRefresh + EXTERN PWM_Stop + EXTERN PWM_Start + EXTERN Time_Set + EXTERN abs + EXTERN PWM_IncrementDutyCycle + EXTERN Time_Left + EXTERN ADCS + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + EXTERN BattEEPROM + EXTERN CurrentState + +// C:\home\kevin\pub\src\bc100_cal\IAR\statefunc.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * State functions +// 6 * +// 7 * Contains the functions related to the states defined in menu.h.\n +// 8 * Also contains related functions, i.e. for checking jumpers, setting +// 9 * error flags and "dozing". +// 10 * +// 11 * \note The state function Charge() is in a separate file since it +// 12 * should easily be changed with regard to battery type. +// 13 * +// 14 * \par Application note: +// 15 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 16 * AVR463: Charging NiMH Batteries with BC100 +// 17 * +// 18 * \par Documentation +// 19 * For comprehensive code documentation, supported compilers, compiler +// 20 * settings and supported devices see readme.html +// 21 * +// 22 * \author +// 23 * Atmel Corporation: http://www.atmel.com \n +// 24 * Support email: avr@atmel.com +// 25 * +// 26 * +// 27 * $Name$ +// 28 * $Revision: 2299 $ +// 29 * $RCSfile$ +// 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $ +// 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 32 ******************************************************************************/ +// 33 +// 34 #include + + ASEGN ABSOLUTE:DATA:NOROOT,055H +// volatile __io _A_MCUCR +_A_MCUCR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,054H +// volatile __io _A_MCUSR +_A_MCUSR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,048H +// volatile __io _A_CLKPR +_A_CLKPR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,041H +// volatile __io _A_WDTCR +_A_WDTCR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,037H +// volatile __io _A_DDRB +_A_DDRB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,026H +// volatile __io _A_ADCSRA +_A_ADCSRA: + DS 1 +// 35 #include +// 36 #include +// 37 +// 38 #include "structs.h" +// 39 #include "enums.h" +// 40 +// 41 #include "ADC.h" +// 42 #include "statefunc.h" +// 43 #include "battery.h" +// 44 #include "charge.h" +// 45 #include "main.h" +// 46 #include "menu.h" +// 47 #include "OWI.h" +// 48 #include "PWM.h" +// 49 #include "time.h" +// 50 #include "USI.h" +// 51 +// 52 +// 53 //****************************************************************************** +// 54 // Variables +// 55 //****************************************************************************** + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 56 unsigned char ErrorFlags; //!< \brief Holds error flags. +ErrorFlags: + DS 1 +// 57 //!< \note See statefunc.h for definitions of flags. +// 58 +// 59 //! \brief Holds the state in which latest error flag was set. +// 60 //! \note See menu.h for definitions of states. + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 61 unsigned char ErrorState; +ErrorState: + DS 1 +// 62 +// 63 +// 64 //****************************************************************************** +// 65 // Functions +// 66 //****************************************************************************** +// 67 /*! \brief Initialization +// 68 * +// 69 * - Sets the system clock prescaler to 1 (run at 8 MHz) +// 70 * - Initializes the one-wire interface +// 71 * - Clears on-chip EEPROM +// 72 * - Sets battery enable pins as outputs, then disables batteries +// 73 * - Initializes SPI according to \ref SPIMODE +// 74 * - Initializes ADC +// 75 * - Initializes timers +// 76 * - Reads battery data from both battery inputs (via ADC) +// 77 * - Disables batteries again +// 78 * - Sets battery A as the current one (\ref BattActive = 0) +// 79 * - Clears ErrorFlags +// 80 * +// 81 * \param inp Not used. +// 82 * +// 83 * \retval ST_BATCON Next state in the sequence. +// 84 */ + + RSEG CODE:CODE:NOROOT(1) +// 85 unsigned char Initialize(unsigned char inp) +Initialize: +// 86 { + RCALL ?PROLOGUE4_L09 + MOV R27, R16 +// 87 unsigned char i, page; +// 88 +// 89 // Disable interrupts while setting prescaler. +// 90 __disable_interrupt(); + CLI +// 91 +// 92 CLKPR = (1< 8 MHz clock frequency. + LDI R16, 0 + OUT 0x28, R16 +// 94 +// 95 // Init 1-Wire(R) interface. +// 96 OWI_Init(OWIBUS); + LDI R16, 1 + RCALL OWI_Init +// 97 +// 98 // Clear on-chip EEPROM. +// 99 for (page = 0; page < 4; page++) { + LDI R25, 0 +??Initialize_0: + CPI R25, 4 + BRCC ??Initialize_1 +// 100 for (i = 0; i < 32; i++) { + LDI R24, 0 +??Initialize_2: + CPI R24, 32 + BRCC ??Initialize_3 +// 101 BattEEPROM[page][i] = 0; + LDI R26, 0 + MOV R20, R25 + LDI R21, 0 + LDI R16, 32 + LDI R17, 0 + RCALL ?S_MUL_L02 + LDI R20, LOW(BattEEPROM) + LDI R21, (BattEEPROM) >> 8 + ADD R20, R16 + ADC R21, R17 + MOV R16, R24 + LDI R17, 0 + ADD R20, R16 + ADC R21, R17 + MOV R16, R26 + RCALL __eeput8_16 +// 102 } + INC R24 + RJMP ??Initialize_2 +// 103 } +??Initialize_3: + INC R25 + RJMP ??Initialize_0 +// 104 +// 105 DDRB = (1<> 8 + RCALL __eeget8_16 + ANDI R16, 0x01 + TST R16 + BRNE ??BatteryControl_2 + LDI R20, LOW((BattControl + 1)) + LDI R21, HIGH((BattControl + 1)) + RCALL __eeget8_16 + ANDI R16, 0x01 + TST R16 + BRNE ??BatteryControl_2 +// 156 SetErrorFlag(ERR_NO_BATTERIES_ENABLED); + LDI R16, 2 + RCALL SetErrorFlag +// 157 +// 158 return(ST_ERROR); + LDI R16, 90 + RJMP ??BatteryControl_1 +// 159 } +// 160 +// 161 // Get ADC-readings, try to read EPROM, and start prequalification +// 162 // of any uncharged battery. +// 163 for (i = 0; i < 2; i++) { +??BatteryControl_2: + LDI R24, 0 +??BatteryControl_3: + CPI R24, 2 + BRCC ??BatteryControl_4 +// 164 if (BattControl[i].Enabled) { + LDI R25, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R24 + ADC R21, R25 + RCALL __eeget8_16 + ANDI R16, 0x01 + TST R16 + BREQ ??BatteryControl_5 +// 165 EnableBattery(i); + MOV R16, R24 + RCALL EnableBattery +// 166 ADC_Wait(); + RCALL ADC_Wait +// 167 +// 168 if (BatteryStatusRefresh()) { + RCALL BatteryStatusRefresh + TST R16 + BREQ ??BatteryControl_5 +// 169 if (!BattData.Charged) { + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + SBRC R16, 1 + RJMP ??BatteryControl_5 +// 170 BatteryDataRefresh(); + RCALL BatteryDataRefresh +// 171 +// 172 return(ST_PREQUAL); + LDI R16, 30 + RJMP ??BatteryControl_1 +// 173 } +// 174 } +// 175 } +// 176 } +??BatteryControl_5: + INC R24 + RJMP ??BatteryControl_3 +// 177 +// 178 // If we end up here, one or two batteries are found and fully charged. +// 179 // Disconnect, so we don't drain them, and go to sleep. +// 180 DisableBatteries(); +??BatteryControl_4: + RCALL DisableBatteries +// 181 +// 182 return(ST_SLEEP); + LDI R16, 40 +??BatteryControl_1: + LDI R30, 3 + RJMP ?EPILOGUE_B3_L09 +// 183 } +// 184 +// 185 +// 186 /*! \brief Start running on batteries +// 187 * +// 188 * \todo Run on batteries, if battery voltage high enough. +// 189 * \todo Jump here when mains voltage drops below threshold +// 190 * +// 191 */ + + RSEG CODE:CODE:NOROOT(1) +// 192 unsigned char Discharge(unsigned char inp) +Discharge: +// 193 { + MOV R17, R16 +// 194 return(ST_BATCON); // Supply voltage restored, start charging + LDI R16, 20 + RET +// 195 } +// 196 +// 197 +// 198 /*! \brief Sleeps until either battery needs charging +// 199 * +// 200 * Calls Doze(), then refreshes the status for both batteries on wakeup. If +// 201 * connected batteries are both charged, the function will loop. If not, it's +// 202 * back to ST_BATCON. +// 203 * +// 204 * \param inp Not used. +// 205 * +// 206 * \retval ST_BATCON Next state if a connected battery isn't fully charged. +// 207 */ + + RSEG CODE:CODE:NOROOT(1) +// 208 unsigned char Sleep(unsigned char inp) +`Sleep`: +// 209 { + RCALL ?PROLOGUE2_L09 + MOV R25, R16 +// 210 unsigned char i; +// 211 +// 212 do { +// 213 Doze(); // Take a nap (~8 seconds). +??Sleep_0: + RCALL Doze +// 214 +// 215 // If any batteries need charging, go to ST_BATCON. +// 216 // Otherwise, keep sleeping. +// 217 for (i = 0; i < 2; i++) { + LDI R24, 0 +??Sleep_1: + CPI R24, 2 + BRCC ??Sleep_2 +// 218 EnableBattery(i); + MOV R16, R24 + RCALL EnableBattery +// 219 ADC_Wait(); + RCALL ADC_Wait +// 220 if ((BatteryStatusRefresh()) && (!BattData.Charged)) { + RCALL BatteryStatusRefresh + TST R16 + BREQ ??Sleep_3 + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + SBRC R16, 1 + RJMP ??Sleep_3 +// 221 return(ST_BATCON); + LDI R16, 20 + RJMP ??Sleep_4 +??Sleep_3: + INC R24 + RJMP ??Sleep_1 +// 222 } +// 223 } +// 224 +// 225 DisableBatteries(); // Disable both batteries before Doze()! +??Sleep_2: + RCALL DisableBatteries +// 226 } while (TRUE); + RJMP ??Sleep_0 +??Sleep_4: + LDI R30, 2 + RJMP ?EPILOGUE_B2_L09 +// 227 } +// 228 +// 229 +// 230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V) +// 231 * +// 232 * Waits for ADC-cycles to complete, disables the ADC, then sleeps for +// 233 * approx. 8 seconds (Vcc = 5 V) using the watchdog timer. +// 234 * On wakeup, ADC is re-enabled. +// 235 */ + + RSEG CODE:CODE:NOROOT(1) +// 236 void Doze(void) +Doze: +// 237 { +// 238 // Wait for this ADC cycle to complete, then halt after the next one. +// 239 ADC_Wait(); + RCALL ADC_Wait +// 240 ADCS.Halt = TRUE; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ORI R16, 0x80 + ST Z, R16 +// 241 ADCS.Flag = FALSE; + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ANDI R16, 0xDF + ST Z, R16 +// 242 +// 243 do { +// 244 } while (ADCS.Flag == FALSE); +??Doze_0: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + SBRS R16, 5 + RJMP ??Doze_0 +// 245 +// 246 WDTCR = (1<> 8 + LD R16, Z + ANDI R16, 0x7F + ST Z, R16 +// 257 ADCSRA |= (1<> 8 + LD R17, Z + AND R17, R16 + ST Z, R17 +// 305 JumperCheck(); + RCALL JumperCheck + RJMP ??Error_3 +// 306 break; +// 307 +// 308 +// 309 case ERR_NO_BATTERIES_ENABLED: +// 310 // Clear if any battery gets enabled. +// 311 if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) { +??Error_5: + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + RCALL __eeget8_16 + ANDI R16, 0x01 + TST R16 + BRNE ??Error_9 + LDI R20, LOW((BattControl + 1)) + LDI R21, HIGH((BattControl + 1)) + RCALL __eeget8_16 + ANDI R16, 0x01 + TST R16 + BREQ ??Error_3 +// 312 ErrorFlags &= ~i; +??Error_9: + MOV R16, R24 + COM R16 + LDI R30, LOW(ErrorFlags) + LDI R31, (ErrorFlags) >> 8 + LD R17, Z + AND R17, R16 + ST Z, R17 + RJMP ??Error_3 +// 313 } +// 314 break; +// 315 +// 316 +// 317 case ERR_PWM_CONTROL: +// 318 // Clear flag. +// 319 ErrorFlags &= ~i; +??Error_6: + MOV R16, R24 + COM R16 + LDI R30, LOW(ErrorFlags) + LDI R31, (ErrorFlags) >> 8 + LD R17, Z + AND R17, R16 + ST Z, R17 + RJMP ??Error_3 +// 320 break; +// 321 +// 322 +// 323 case ERR_BATTERY_TEMPERATURE: +// 324 // Clear flag. +// 325 ErrorFlags &= ~i; +??Error_7: + MOV R16, R24 + COM R16 + LDI R30, LOW(ErrorFlags) + LDI R31, (ErrorFlags) >> 8 + LD R17, Z + AND R17, R16 + ST Z, R17 + RJMP ??Error_3 +// 326 break; +// 327 +// 328 +// 329 case ERR_BATTERY_EXHAUSTED: +// 330 // Try the other battery. +// 331 BattData.Exhausted = FALSE; +??Error_8: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ANDI R16, 0xF7 + ST Z, R16 +// 332 BattActive = (BattActive + 1) % 2; + LDS R30, BattActive + LDI R31, 0 + ADIW R31:R30, 1 + MOVW R17:R16, R31:R30 + LDI R20, 2 + LDI R21, 0 + RCALL ?SS_DIVMOD_L02 + STS BattActive, R20 +// 333 ErrorFlags &= ~i; + MOV R16, R24 + COM R16 + LDI R30, LOW(ErrorFlags) + LDI R31, (ErrorFlags) >> 8 + LD R17, Z + AND R17, R16 + ST Z, R17 +// 334 break; +// 335 +// 336 +// 337 default: +// 338 break; +// 339 } +// 340 } +// 341 } +??Error_3: + LSL R24 + RJMP ??Error_1 +// 342 } while (ErrorFlags); +??Error_2: + LDS R16, ErrorFlags + TST R16 + BREQ $+2+2 + RJMP ??Error_0 +// 343 +// 344 return(ST_INIT); + LDI R16, 10 + LDI R30, 2 + RJMP ?EPILOGUE_B2_L09 +// 345 } +// 346 +// 347 +// 348 /*! \brief Sets the specified error-flag and saves the current state +// 349 * +// 350 * Updates \ref ErrorFlags and \ref ErrorState. +// 351 * +// 352 * \note Error flags are specified in statefunc.h. +// 353 * +// 354 * \param Flag Specifies what error to flag. +// 355 */ + + RSEG CODE:CODE:NOROOT(1) +// 356 void SetErrorFlag(unsigned char Flag) +SetErrorFlag: +// 357 { +// 358 ErrorFlags |= Flag; + LDI R30, LOW(ErrorFlags) + LDI R31, (ErrorFlags) >> 8 + LD R17, Z + OR R17, R16 + ST Z, R17 +// 359 ErrorState = CurrentState; + LDS R17, CurrentState + STS ErrorState, R17 +// 360 } + RET +// 361 +// 362 +// 363 /*! \brief Checks on-board jumpers. +// 364 * +// 365 * Checks on-board jumpers by disconnecting all loads, engaging the PWM and +// 366 * increasing the duty cycle until conditioned output voltage equals conditioned +// 367 * input voltage. At low PWM duty and no load buck output should be zero and, +// 368 * when increasing PWM duty, should quickly jump to steady state output roughly +// 369 * equal to input voltage. Will disable and leave disabled all batteries. +// 370 * +// 371 * \retval FALSE If jumper or load mismatch. +// 372 * \retval TRUE If everything OK. +// 373 */ + + RSEG CODE:CODE:NOROOT(1) +// 374 unsigned char JumperCheck(void) +JumperCheck: +// 375 { +// 376 DisableBatteries(); // Disconnect, or loads may be destroyed! + RCALL DisableBatteries +// 377 +// 378 PWM_Start(); // Start PWM (controls the buck charger). + RCALL PWM_Start +// 379 +// 380 // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s. +// 381 Time_Set(TIMER_GEN,0,1,0); + LDI R20, 0 + LDI R17, 1 + LDI R18, 0 + LDI R19, 0 + LDI R16, 2 + RCALL Time_Set +// 382 +// 383 do { +// 384 // If the PWM output voltage saturates the ADC, stop PWM output and +// 385 // report a failure. +// 386 if (ADCS.rawVBAT == 1023) { +??JumperCheck_0: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+6 + LDD R17, Z+7 + CPI R16, 255 + LDI R18, 3 + CPC R17, R18 + BRNE ??JumperCheck_1 +// 387 PWM_Stop(); + RCALL PWM_Stop +// 388 return(FALSE); + LDI R16, 0 + RET +// 389 } +// 390 +// 391 // If the absolute difference between measured (VIN - VBAT) and the +// 392 // typical value are below our set maximum, everything is OK. +// 393 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) < +// 394 VIN_VBAT_DIFF_MAX ) { +??JumperCheck_1: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+8 + LDD R17, Z+9 + SUBI R16, 88 + SBCI R17, 2 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+10 + LDD R19, Z+11 + SUB R16, R18 + SBC R17, R19 + RCALL abs + CPI R16, 244 + LDI R18, 1 + CPC R17, R18 + BRGE ??JumperCheck_2 +// 395 +// 396 PWM_Stop(); + RCALL PWM_Stop +// 397 return(TRUE); + LDI R16, 1 + RET +// 398 } +// 399 +// 400 // Charge current is too high -> check load and jumper J405 and J406. +// 401 if (abs(ADCS.IBAT) > 100) { +??JumperCheck_2: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+12 + LDD R17, Z+13 + RCALL abs + CPI R16, 101 + LDI R18, 0 + CPC R17, R18 + BRLT ??JumperCheck_3 +// 402 PWM_Stop(); + RCALL PWM_Stop +// 403 return(FALSE); + LDI R16, 0 + RET +// 404 } +// 405 +// 406 // If the PWM output can't be increased high enough -> check jumpers +// 407 // J400-J404, J407 and J408. +// 408 if (!PWM_IncrementDutyCycle()) { +??JumperCheck_3: + RCALL PWM_IncrementDutyCycle + TST R16 + BRNE ??JumperCheck_4 +// 409 PWM_Stop(); + RCALL PWM_Stop +// 410 return(FALSE); + LDI R16, 0 + RET +// 411 } +// 412 +// 413 // Wait for ADC conversions to complete +// 414 ADC_Wait(); +??JumperCheck_4: + RCALL ADC_Wait +// 415 } while (Time_Left(TIMER_GEN)); + LDI R16, 2 + RCALL Time_Left + TST R16 + BRNE ??JumperCheck_0 +// 416 +// 417 +// 418 // If we end up here, the measurements took too long. +// 419 PWM_Stop(); + RCALL PWM_Stop +// 420 return(FALSE); + LDI R16, 0 + RET +// 421 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 6 bytes in segment ABSOLUTE +// 734 bytes in segment CODE +// 6 bytes in segment INITTAB +// 2 bytes in segment NEAR_Z +// +// 734 bytes of CODE memory (+ 6 bytes shared) +// 2 bytes of DATA memory (+ 6 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/List/time.lst b/BaseTinyFirmware/IAR/Debug/List/time.lst new file mode 100644 index 0000000..15d2e6f --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/List/time.lst @@ -0,0 +1,512 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 12/Mar/2008 23:01:40 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100_cal\IAR\time.c # +# Command line = C:\home\kevin\pub\src\bc100_cal\IAR\time.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc100_cal\IAR # +# \Debug\Obj\ -lC C:\home\kevin\pub\src\bc100_cal\IAR\Debu # +# g\List\ -lB C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Li # +# st\ --initializers_in_flash -z2 --no_cse --no_inline # +# --no_code_motion --no_cross_call --no_clustering # +# --no_tbaa --debug -DENABLE_BIT_DEFINITIONS -e # +# --require_prototypes -I "C:\Program Files\IAR # +# Systems\Embedded Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench 4.0\avr\INC\CLIB\" # +# --eeprom_size 512 # +# List file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\List\time.lst # +# Object file = C:\home\kevin\pub\src\bc100_cal\IAR\Debug\Obj\time.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100_cal\IAR\time.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for timing + 6 * + 7 * Contains functions to initialize, set, poll and stop timers. + 8 * + 9 * \par Application note: + 10 * AVR458: Charging Li-Ion Batteries with BC100 \n + 11 * AVR463: Charging NiMH Batteries with BC100 + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2299 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $ + 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 #include + + \ In segment ABSOLUTE, at 0x59 + \ volatile __io _A_TIMSK + \ _A_TIMSK: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x53 + \ volatile __io _A_TCCR0B + \ _A_TCCR0B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x35 + \ volatile __io _A_TCCR0A + \ _A_TCCR0A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x33 + \ volatile __io _A_OCR0A + \ _A_OCR0A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x32 + \ volatile __io _A_OCR0B + \ _A_OCR0B: + \ 00000000 DS 1 + 30 #include + 31 + 32 #include "enums.h" + 33 + 34 #include "main.h" + 35 #include "time.h" + 36 + 37 + 38 //****************************************************************************** + 39 // Variables + 40 //****************************************************************************** + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 41 unsigned long timeval[TIMERS]; //!< Contains the values for each timer. + \ timeval: + \ 00000000 DS 16 + 42 + 43 // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms + 44 //#pragma vector = TIM0_OVF_vect + 45 + 46 + 47 //****************************************************************************** + 48 // Functions + 49 //****************************************************************************** + 50 /*! \brief Interrupt service routine for timer 0 overflow + 51 * + 52 * Timer 0 runs at 125 kHz and compare match will occur every millisecond + 53 * (125 / 125 kHz = 1.0 ms), which will result in a call to this function. + 54 * When called, this function will decrement the time left for each timer, + 55 * unless they are already at zero. + 56 */ + 57 #pragma vector = TIM0_COMPA_vect + + \ In segment CODE, align 2, keep-with-next + 58 __interrupt void TICK_ISR(void) + \ TICK_ISR: + 59 { + \ 00000000 93FA ST -Y, R31 + \ 00000002 93EA ST -Y, R30 + \ 00000004 920A ST -Y, R0 + \ 00000006 937A ST -Y, R23 + \ 00000008 936A ST -Y, R22 + \ 0000000A 935A ST -Y, R21 + \ 0000000C 934A ST -Y, R20 + \ 0000000E 933A ST -Y, R19 + \ 00000010 932A ST -Y, R18 + \ 00000012 931A ST -Y, R17 + \ 00000014 930A ST -Y, R16 + \ 00000016 B60F IN R0, 0x3F + 60 unsigned char i; + 61 + 62 // 1 ms has passed, decrement all non-zero timers. + 63 for (i = 0; i < TIMERS; i++) { + \ 00000018 E000 LDI R16, 0 + \ ??TICK_ISR_0: + \ 0000001A 3004 CPI R16, 4 + \ 0000001C F540 BRCC ??TICK_ISR_1 + 64 if(timeval[i] > 0) { + \ 0000001E 2F20 MOV R18, R16 + \ 00000020 E030 LDI R19, 0 + \ 00000022 0F22 LSL R18 + \ 00000024 1F33 ROL R19 + \ 00000026 0F22 LSL R18 + \ 00000028 1F33 ROL R19 + \ 0000002A 01F9 MOVW R31:R30, R19:R18 + \ 0000002C .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 0000002E .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000030 8140 LD R20, Z + \ 00000032 8151 LDD R21, Z+1 + \ 00000034 8162 LDD R22, Z+2 + \ 00000036 8173 LDD R23, Z+3 + \ 00000038 2B45 OR R20, R21 + \ 0000003A 2B46 OR R20, R22 + \ 0000003C 2B47 OR R20, R23 + \ 0000003E F0A9 BREQ ??TICK_ISR_2 + 65 timeval[i]--; + \ 00000040 2F20 MOV R18, R16 + \ 00000042 E030 LDI R19, 0 + \ 00000044 0F22 LSL R18 + \ 00000046 1F33 ROL R19 + \ 00000048 0F22 LSL R18 + \ 0000004A 1F33 ROL R19 + \ 0000004C 01F9 MOVW R31:R30, R19:R18 + \ 0000004E .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 00000050 .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000052 8140 LD R20, Z + \ 00000054 8151 LDD R21, Z+1 + \ 00000056 8162 LDD R22, Z+2 + \ 00000058 8173 LDD R23, Z+3 + \ 0000005A 5041 SUBI R20, 1 + \ 0000005C 4050 SBCI R21, 0 + \ 0000005E 4060 SBCI R22, 0 + \ 00000060 4070 SBCI R23, 0 + \ 00000062 8340 ST Z, R20 + \ 00000064 8351 STD Z+1, R21 + \ 00000066 8362 STD Z+2, R22 + \ 00000068 8373 STD Z+3, R23 + 66 } + 67 } + \ ??TICK_ISR_2: + \ 0000006A 9503 INC R16 + \ 0000006C CFD6 RJMP ??TICK_ISR_0 + 68 } + \ ??TICK_ISR_1: + \ 0000006E BE0F OUT 0x3F, R0 + \ 00000070 9109 LD R16, Y+ + \ 00000072 9119 LD R17, Y+ + \ 00000074 9129 LD R18, Y+ + \ 00000076 9139 LD R19, Y+ + \ 00000078 9149 LD R20, Y+ + \ 0000007A 9159 LD R21, Y+ + \ 0000007C 9169 LD R22, Y+ + \ 0000007E 9179 LD R23, Y+ + \ 00000080 9009 LD R0, Y+ + \ 00000082 91E9 LD R30, Y+ + \ 00000084 91F9 LD R31, Y+ + \ 00000086 9518 RETI + 69 + 70 + 71 /*! \brief Checks if a specified timer has expired + 72 * + 73 * \param timer Specifies timer + 74 * + 75 * \retval TRUE Timer still going. + 76 * \retval FALSE Timer has expired. + 77 */ + + \ In segment CODE, align 2, keep-with-next + 78 unsigned char Time_Left(unsigned char timer) + \ Time_Left: + 79 { + \ 00000000 2F20 MOV R18, R16 + 80 if(timeval[timer] > 0) { + \ 00000002 2F02 MOV R16, R18 + \ 00000004 E010 LDI R17, 0 + \ 00000006 0F00 LSL R16 + \ 00000008 1F11 ROL R17 + \ 0000000A 0F00 LSL R16 + \ 0000000C 1F11 ROL R17 + \ 0000000E 01F8 MOVW R31:R30, R17:R16 + \ 00000010 .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 00000012 .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000014 8140 LD R20, Z + \ 00000016 8151 LDD R21, Z+1 + \ 00000018 8162 LDD R22, Z+2 + \ 0000001A 8173 LDD R23, Z+3 + \ 0000001C 2B45 OR R20, R21 + \ 0000001E 2B46 OR R20, R22 + \ 00000020 2B47 OR R20, R23 + \ 00000022 F011 BREQ ??Time_Left_0 + 81 return(TRUE); + \ 00000024 E001 LDI R16, 1 + \ 00000026 9508 RET + 82 } else { + 83 return(FALSE); + \ ??Time_Left_0: + \ 00000028 E000 LDI R16, 0 + \ 0000002A 9508 RET + 84 } + 85 } + 86 + 87 + 88 /*! \brief Sets the specified timer + 89 * + 90 * \param timer Specifies timer + 91 * \param min Minutes for timer to count down + 92 * \param sec Seconds for timer to count down + 93 * \param ms Milliseconds for timer to count down + 94 */ + + \ In segment CODE, align 2, keep-with-next + 95 void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, + \ Time_Set: + 96 unsigned char ms) + 97 { + \ 00000000 .... RCALL ?PROLOGUE7_L09 + \ 00000002 REQUIRE ?Register_R4_is_cg_reg + \ 00000002 REQUIRE ?Register_R5_is_cg_reg + \ 00000002 REQUIRE ?Register_R6_is_cg_reg + \ 00000002 2FA0 MOV R26, R16 + \ 00000004 01C9 MOVW R25:R24, R19:R18 + \ 00000006 2E61 MOV R6, R17 + \ 00000008 2E44 MOV R4, R20 + 98 // timeval[i] = 4 * (1000*(sec + 60*min) + ms); // about 4000 ticks per second + 99 // timeval[i] = 240000 * (unsigned long)min; + 100 // timeval[i] += 4000 * (unsigned long)sec; + 101 // timeval[i] += 4 * (unsigned long)ms; + 102 + 103 timeval[timer] = 60000 * (unsigned long)min; + \ 0000000A 01AC MOVW R21:R20, R25:R24 + \ 0000000C E060 LDI R22, 0 + \ 0000000E E070 LDI R23, 0 + \ 00000010 E600 LDI R16, 96 + \ 00000012 EE1A LDI R17, 234 + \ 00000014 E020 LDI R18, 0 + \ 00000016 E030 LDI R19, 0 + \ 00000018 .... RCALL ?L_MUL_L03 + \ 0000001A 2F4A MOV R20, R26 + \ 0000001C E050 LDI R21, 0 + \ 0000001E 0F44 LSL R20 + \ 00000020 1F55 ROL R21 + \ 00000022 0F44 LSL R20 + \ 00000024 1F55 ROL R21 + \ 00000026 01FA MOVW R31:R30, R21:R20 + \ 00000028 .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 0000002A .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 0000002C 8300 ST Z, R16 + \ 0000002E 8311 STD Z+1, R17 + \ 00000030 8322 STD Z+2, R18 + \ 00000032 8333 STD Z+3, R19 + 104 timeval[timer] += 1000 * (unsigned long)sec; + \ 00000034 2D46 MOV R20, R6 + \ 00000036 E050 LDI R21, 0 + \ 00000038 E060 LDI R22, 0 + \ 0000003A E070 LDI R23, 0 + \ 0000003C EE08 LDI R16, 232 + \ 0000003E E013 LDI R17, 3 + \ 00000040 E020 LDI R18, 0 + \ 00000042 E030 LDI R19, 0 + \ 00000044 .... RCALL ?L_MUL_L03 + \ 00000046 2F4A MOV R20, R26 + \ 00000048 E050 LDI R21, 0 + \ 0000004A 0F44 LSL R20 + \ 0000004C 1F55 ROL R21 + \ 0000004E 0F44 LSL R20 + \ 00000050 1F55 ROL R21 + \ 00000052 01FA MOVW R31:R30, R21:R20 + \ 00000054 .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 00000056 .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000058 8140 LD R20, Z + \ 0000005A 8151 LDD R21, Z+1 + \ 0000005C 8162 LDD R22, Z+2 + \ 0000005E 8173 LDD R23, Z+3 + \ 00000060 0F40 ADD R20, R16 + \ 00000062 1F51 ADC R21, R17 + \ 00000064 1F62 ADC R22, R18 + \ 00000066 1F73 ADC R23, R19 + \ 00000068 8340 ST Z, R20 + \ 0000006A 8351 STD Z+1, R21 + \ 0000006C 8362 STD Z+2, R22 + \ 0000006E 8373 STD Z+3, R23 + 105 timeval[timer] += 1 * (unsigned long)ms; + \ 00000070 2455 CLR R5 + \ 00000072 0182 MOVW R17:R16, R5:R4 + \ 00000074 E020 LDI R18, 0 + \ 00000076 E030 LDI R19, 0 + \ 00000078 2F4A MOV R20, R26 + \ 0000007A E050 LDI R21, 0 + \ 0000007C 0F44 LSL R20 + \ 0000007E 1F55 ROL R21 + \ 00000080 0F44 LSL R20 + \ 00000082 1F55 ROL R21 + \ 00000084 01FA MOVW R31:R30, R21:R20 + \ 00000086 .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 00000088 .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 0000008A 8140 LD R20, Z + \ 0000008C 8151 LDD R21, Z+1 + \ 0000008E 8162 LDD R22, Z+2 + \ 00000090 8173 LDD R23, Z+3 + \ 00000092 0F40 ADD R20, R16 + \ 00000094 1F51 ADC R21, R17 + \ 00000096 1F62 ADC R22, R18 + \ 00000098 1F73 ADC R23, R19 + \ 0000009A 8340 ST Z, R20 + \ 0000009C 8351 STD Z+1, R21 + \ 0000009E 8362 STD Z+2, R22 + \ 000000A0 8373 STD Z+3, R23 + 106 } + \ 000000A2 E0E7 LDI R30, 7 + \ 000000A4 .... RJMP ?EPILOGUE_B7_L09 + 107 + 108 + 109 /*! \brief Stops timers + 110 * + 111 * Sets timer0's clock source to none. + 112 */ + + \ In segment CODE, align 2, keep-with-next + 113 void Time_Stop(void) + \ Time_Stop: + 114 { + 115 TCCR0B = 0; + \ 00000000 E000 LDI R16, 0 + \ 00000002 BF03 OUT 0x33, R16 + 116 } + \ 00000004 9508 RET + \ 00000006 REQUIRE _A_TCCR0B + 117 + 118 + 119 /*! \brief Starts timers + 120 * + 121 * Sets timer0's clock source to system clock divided by 64. + 122 */ + + \ In segment CODE, align 2, keep-with-next + 123 void Time_Start(void) + \ Time_Start: + 124 { + 125 TCCR0B = (0<> 8 + \ 00000020 8300 ST Z, R16 + \ 00000022 8311 STD Z+1, R17 + \ 00000024 8322 STD Z+2, R18 + \ 00000026 8333 STD Z+3, R19 + 140 } + \ 00000028 9543 INC R20 + \ 0000002A CFEB RJMP ??Time_Init_0 + 141 + 142 // OCR0A = 0; // Doesn't matter, will run in normal mode. + 143 + 144 OCR0A = 125; // Will give a compare match every ms. + \ ??Time_Init_1: + \ 0000002C E70D LDI R16, 125 + \ 0000002E BB03 OUT 0x13, R16 + 145 + 146 OCR0B = 0; // Doesn't matter, will run in normal mode. + \ 00000030 E000 LDI R16, 0 + \ 00000032 BB02 OUT 0x12, R16 + 147 + 148 // TCCR0A = 0; // Normal 8-bit mode, no input capture. + 149 + 150 TCCR0A = (1<` + PUBWEAK `??TICK_ISR??INTVEC 28` + PUBLIC TICK_ISR + PUBLIC Time_Init + PUBLIC Time_Left + PUBLIC Time_Set + PUBLIC Time_Start + PUBLIC Time_Stop + PUBWEAK _A_OCR0A + PUBWEAK _A_OCR0B + PUBWEAK _A_TCCR0A + PUBWEAK _A_TCCR0B + PUBWEAK _A_TIMSK + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + PUBLIC timeval + +TICK_ISR SYMBOL "TICK_ISR" +`??TICK_ISR??INTVEC 28` SYMBOL "??INTVEC 28", TICK_ISR + +// C:\home\kevin\pub\src\bc100_cal\IAR\time.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for timing +// 6 * +// 7 * Contains functions to initialize, set, poll and stop timers. +// 8 * +// 9 * \par Application note: +// 10 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 11 * AVR463: Charging NiMH Batteries with BC100 +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2299 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $ +// 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 #include + + ASEGN ABSOLUTE:DATA:NOROOT,059H +// volatile __io _A_TIMSK +_A_TIMSK: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,053H +// volatile __io _A_TCCR0B +_A_TCCR0B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,035H +// volatile __io _A_TCCR0A +_A_TCCR0A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,033H +// volatile __io _A_OCR0A +_A_OCR0A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,032H +// volatile __io _A_OCR0B +_A_OCR0B: + DS 1 +// 30 #include +// 31 +// 32 #include "enums.h" +// 33 +// 34 #include "main.h" +// 35 #include "time.h" +// 36 +// 37 +// 38 //****************************************************************************** +// 39 // Variables +// 40 //****************************************************************************** + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 41 unsigned long timeval[TIMERS]; //!< Contains the values for each timer. +timeval: + DS 16 +// 42 +// 43 // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms +// 44 //#pragma vector = TIM0_OVF_vect +// 45 +// 46 +// 47 //****************************************************************************** +// 48 // Functions +// 49 //****************************************************************************** +// 50 /*! \brief Interrupt service routine for timer 0 overflow +// 51 * +// 52 * Timer 0 runs at 125 kHz and compare match will occur every millisecond +// 53 * (125 / 125 kHz = 1.0 ms), which will result in a call to this function. +// 54 * When called, this function will decrement the time left for each timer, +// 55 * unless they are already at zero. +// 56 */ +// 57 #pragma vector = TIM0_COMPA_vect + + RSEG CODE:CODE:NOROOT(1) +// 58 __interrupt void TICK_ISR(void) +TICK_ISR: +// 59 { + ST -Y, R31 + ST -Y, R30 + ST -Y, R0 + ST -Y, R23 + ST -Y, R22 + ST -Y, R21 + ST -Y, R20 + ST -Y, R19 + ST -Y, R18 + ST -Y, R17 + ST -Y, R16 + IN R0, 0x3F +// 60 unsigned char i; +// 61 +// 62 // 1 ms has passed, decrement all non-zero timers. +// 63 for (i = 0; i < TIMERS; i++) { + LDI R16, 0 +??TICK_ISR_0: + CPI R16, 4 + BRCC ??TICK_ISR_1 +// 64 if(timeval[i] > 0) { + MOV R18, R16 + LDI R19, 0 + LSL R18 + ROL R19 + LSL R18 + ROL R19 + MOVW R31:R30, R19:R18 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R20, Z + LDD R21, Z+1 + LDD R22, Z+2 + LDD R23, Z+3 + OR R20, R21 + OR R20, R22 + OR R20, R23 + BREQ ??TICK_ISR_2 +// 65 timeval[i]--; + MOV R18, R16 + LDI R19, 0 + LSL R18 + ROL R19 + LSL R18 + ROL R19 + MOVW R31:R30, R19:R18 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R20, Z + LDD R21, Z+1 + LDD R22, Z+2 + LDD R23, Z+3 + SUBI R20, 1 + SBCI R21, 0 + SBCI R22, 0 + SBCI R23, 0 + ST Z, R20 + STD Z+1, R21 + STD Z+2, R22 + STD Z+3, R23 +// 66 } +// 67 } +??TICK_ISR_2: + INC R16 + RJMP ??TICK_ISR_0 +// 68 } +??TICK_ISR_1: + OUT 0x3F, R0 + LD R16, Y+ + LD R17, Y+ + LD R18, Y+ + LD R19, Y+ + LD R20, Y+ + LD R21, Y+ + LD R22, Y+ + LD R23, Y+ + LD R0, Y+ + LD R30, Y+ + LD R31, Y+ + RETI +// 69 +// 70 +// 71 /*! \brief Checks if a specified timer has expired +// 72 * +// 73 * \param timer Specifies timer +// 74 * +// 75 * \retval TRUE Timer still going. +// 76 * \retval FALSE Timer has expired. +// 77 */ + + RSEG CODE:CODE:NOROOT(1) +// 78 unsigned char Time_Left(unsigned char timer) +Time_Left: +// 79 { + MOV R18, R16 +// 80 if(timeval[timer] > 0) { + MOV R16, R18 + LDI R17, 0 + LSL R16 + ROL R17 + LSL R16 + ROL R17 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R20, Z + LDD R21, Z+1 + LDD R22, Z+2 + LDD R23, Z+3 + OR R20, R21 + OR R20, R22 + OR R20, R23 + BREQ ??Time_Left_0 +// 81 return(TRUE); + LDI R16, 1 + RET +// 82 } else { +// 83 return(FALSE); +??Time_Left_0: + LDI R16, 0 + RET +// 84 } +// 85 } +// 86 +// 87 +// 88 /*! \brief Sets the specified timer +// 89 * +// 90 * \param timer Specifies timer +// 91 * \param min Minutes for timer to count down +// 92 * \param sec Seconds for timer to count down +// 93 * \param ms Milliseconds for timer to count down +// 94 */ + + RSEG CODE:CODE:NOROOT(1) +// 95 void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, +Time_Set: +// 96 unsigned char ms) +// 97 { + RCALL ?PROLOGUE7_L09 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + MOV R26, R16 + MOVW R25:R24, R19:R18 + MOV R6, R17 + MOV R4, R20 +// 98 // timeval[i] = 4 * (1000*(sec + 60*min) + ms); // about 4000 ticks per second +// 99 // timeval[i] = 240000 * (unsigned long)min; +// 100 // timeval[i] += 4000 * (unsigned long)sec; +// 101 // timeval[i] += 4 * (unsigned long)ms; +// 102 +// 103 timeval[timer] = 60000 * (unsigned long)min; + MOVW R21:R20, R25:R24 + LDI R22, 0 + LDI R23, 0 + LDI R16, 96 + LDI R17, 234 + LDI R18, 0 + LDI R19, 0 + RCALL ?L_MUL_L03 + MOV R20, R26 + LDI R21, 0 + LSL R20 + ROL R21 + LSL R20 + ROL R21 + MOVW R31:R30, R21:R20 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + ST Z, R16 + STD Z+1, R17 + STD Z+2, R18 + STD Z+3, R19 +// 104 timeval[timer] += 1000 * (unsigned long)sec; + MOV R20, R6 + LDI R21, 0 + LDI R22, 0 + LDI R23, 0 + LDI R16, 232 + LDI R17, 3 + LDI R18, 0 + LDI R19, 0 + RCALL ?L_MUL_L03 + MOV R20, R26 + LDI R21, 0 + LSL R20 + ROL R21 + LSL R20 + ROL R21 + MOVW R31:R30, R21:R20 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R20, Z + LDD R21, Z+1 + LDD R22, Z+2 + LDD R23, Z+3 + ADD R20, R16 + ADC R21, R17 + ADC R22, R18 + ADC R23, R19 + ST Z, R20 + STD Z+1, R21 + STD Z+2, R22 + STD Z+3, R23 +// 105 timeval[timer] += 1 * (unsigned long)ms; + CLR R5 + MOVW R17:R16, R5:R4 + LDI R18, 0 + LDI R19, 0 + MOV R20, R26 + LDI R21, 0 + LSL R20 + ROL R21 + LSL R20 + ROL R21 + MOVW R31:R30, R21:R20 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R20, Z + LDD R21, Z+1 + LDD R22, Z+2 + LDD R23, Z+3 + ADD R20, R16 + ADC R21, R17 + ADC R22, R18 + ADC R23, R19 + ST Z, R20 + STD Z+1, R21 + STD Z+2, R22 + STD Z+3, R23 +// 106 } + LDI R30, 7 + RJMP ?EPILOGUE_B7_L09 +// 107 +// 108 +// 109 /*! \brief Stops timers +// 110 * +// 111 * Sets timer0's clock source to none. +// 112 */ + + RSEG CODE:CODE:NOROOT(1) +// 113 void Time_Stop(void) +Time_Stop: +// 114 { +// 115 TCCR0B = 0; + LDI R16, 0 + OUT 0x33, R16 +// 116 } + RET + REQUIRE _A_TCCR0B +// 117 +// 118 +// 119 /*! \brief Starts timers +// 120 * +// 121 * Sets timer0's clock source to system clock divided by 64. +// 122 */ + + RSEG CODE:CODE:NOROOT(1) +// 123 void Time_Start(void) +Time_Start: +// 124 { +// 125 TCCR0B = (0<> 8 + ST Z, R16 + STD Z+1, R17 + STD Z+2, R18 + STD Z+3, R19 +// 140 } + INC R20 + RJMP ??Time_Init_0 +// 141 +// 142 // OCR0A = 0; // Doesn't matter, will run in normal mode. +// 143 +// 144 OCR0A = 125; // Will give a compare match every ms. +??Time_Init_1: + LDI R16, 125 + OUT 0x13, R16 +// 145 +// 146 OCR0B = 0; // Doesn't matter, will run in normal mode. + LDI R16, 0 + OUT 0x12, R16 +// 147 +// 148 // TCCR0A = 0; // Normal 8-bit mode, no input capture. +// 149 +// 150 TCCR0A = (1<`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 5 bytes in segment ABSOLUTE +// 428 bytes in segment CODE +// 6 bytes in segment INITTAB +// 2 bytes in segment INTVEC +// 16 bytes in segment NEAR_Z +// +// 428 bytes of CODE memory (+ 8 bytes shared) +// 16 bytes of DATA memory (+ 5 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Debug/Obj/ADC.r90 b/BaseTinyFirmware/IAR/Debug/Obj/ADC.r90 new file mode 100644 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 index 0000000..3c882c0 --- /dev/null +++ b/BaseTinyFirmware/IAR/Debug/Obj/BC100_tiny.pbd @@ -0,0 +1,13 @@ +This is an internal working file generated by the Source Browser. +04:48 47s +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\ADC.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\NIMHcharge.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\OWI.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\PWM.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\USI.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\battery.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\chargefunc.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\main.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\menu.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\statefunc.pbi +C:\home\kevin\pub\src\bc100\IAR\Debug\Obj\time.pbi diff --git a/BaseTinyFirmware/IAR/Debug/Obj/NIMHcharge.r90 b/BaseTinyFirmware/IAR/Debug/Obj/NIMHcharge.r90 new file mode 100644 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 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 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 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 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 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 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 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 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 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 index 0000000..49dfe5b --- /dev/null +++ b/BaseTinyFirmware/IAR/LIIONcharge.c @@ -0,0 +1,156 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Charge state function for Li-Ion batteries + * + * Contains the charge state function, in which the Li-Ion charging + * algorithm is, plus the associated functions. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONcharge.c $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" +#include "structs.h" + +#include "battery.h" +#include "charge.h" +#include "chargefunc.h" +#include "main.h" +#include "menu.h" +#include "LIIONspecs.h" +#include "PWM.h" +#include "time.h" + +#ifndef LIION +#error LIION not defined in main.h! +#endif // LIION + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Controls the charging. + * + * This function contains the charging algorithm itself, divided into stages.\n + * For each stage the PWM may be started/stopped, and the timer, + * halt-requirements and charge parameters may be set.\n + * The charging functions return whatever state is next, and as long as no + * errors occur this is the next charging stage. + * + * \note If more stages are needed simply define more states in menu.h, include + * them in \ref menu_state[] in menu.c, then add the cases to this function. + * + * \note This algorithm is for Li-Ion batteries. + */ +unsigned char Charge(unsigned char inp) +{ + unsigned char NextState; + + switch (CurrentState) { + case ST_PREQUAL: // First step is prequalification. + + // Charge with the defined prequalifiction-current, and if no errors + // occur return ST_CCURRENT as the next state. + ChargeParameters.Current = BAT_CURRENT_PREQUAL; + ChargeParameters.NextState = ST_CCURRENT; + + // We want charging to halt if voltage reaches a limit or time runs out. + // In case of timeout the battery will be flagged as exhausted, and an + // error will be flagged. + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_FLAG_EXHAUSTION); + + // Set the maximum temperature and charge voltage limit. + HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + + // Start PWM output and charging timer first. + PWM_Start(); + Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + + // Call the constant current charging-function. + // If all goes well, we will get ST_CCURRENT in return. + NextState = ConstantCurrent(); + break; + + + case ST_CCURRENT: // Second step is constant current charging. + + // Set charging timer to the battery's maximum charge time. + Time_Set(TIMER_CHG,BattData.MaxTime,0,0); + + // Charge at the battery's maximum current, go to ST_CVOLTAGE next. + ChargeParameters.Current = BattData.MaxCurrent; + ChargeParameters.NextState = ST_CVOLTAGE; + + + // Charge until the defined BatChargeVoltage is reached. + HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + + // Start charging using constant current. + NextState = ConstantCurrent(); + break; + + + case ST_CVOLTAGE: // Third step is constant voltage charging. + + // Charge with the defined charge-voltage, go to ST_ENDCHARGE next. + ChargeParameters.Voltage = BAT_VOLTAGE_MAX; + ChargeParameters.NextState = ST_ENDCHARGE; + + // We want charging to halt if temperature rises too high, if current + // sinks below limit, or time runs out. Also, flag error if temperature + // limit is reached. Timeout doesn't mean anything is wrong at this point. + HaltParameters.HaltFlags = (HALT_CURRENT_MIN | HALT_TIME); + + HaltParameters.CurrentMin = BattData.MinCurrent; + + // Start charging using constant voltage. We will continue on the + // timer started in ST_CCURRENT. + NextState = ConstantVoltage(); + break; + + + case ST_ENDCHARGE: // Charging is done! + + PWM_Stop(); + BattData.Charged = TRUE; + + // If the other battery is enabled go to ST_BATCON, otherwise + // go to ST_SLEEP. + if (BattControl[(BattActive+1)%2].Enabled) { + NextState = ST_BATCON; + } else { + NextState = ST_SLEEP; + } + break; + + + default: // Shouldn't end up here. Reinitialize for safety. + NextState = ST_INIT; + break; + } + + // Return the next state. + return(NextState); +} diff --git a/BaseTinyFirmware/IAR/LIIONspecs.h b/BaseTinyFirmware/IAR/LIIONspecs.h new file mode 100644 index 0000000..e662b1e --- /dev/null +++ b/BaseTinyFirmware/IAR/LIIONspecs.h @@ -0,0 +1,102 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Li-Ion specifications + * + * Contains example definitions of Li-Ion battery specifications. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/LIIONspecs.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef LIIONSPECS_H +#define LIIONSPECS_H + + +//****************************************************************************** +// Cell limits +//****************************************************************************** +// This is for common NiMH batteries. +#define CELL_VOLTAGE_SAFETY 0 /*!< \brief Buffer for unmatched batteries. + * + * If we are charging a multicell battery and the cells aren't matched, we + * may risk overcharging at least one. Therefore, we may subtract this constant + * per additional cell in battery to allow for a "buffer". + * + * \note Set to 0 if batteries are properly matched. + * + * \note If this is changed to something higher than (CELL_VOLTAGE_MAX - + * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit + * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause + * the charger to keep trying to charge, but instantly finishing because + * the battery voltage is already at max. + */ +//! Maximum charge voltage for cell, in mV. +#define CELL_VOLTAGE_MAX 4200 + +//! Minimum voltage to consider cell charged at, in mV. +#define CELL_VOLTAGE_LOW 4050 + +//! Minimum voltage to start charging at, in mV. +#define CELL_VOLTAGE_MIN 2750 + +//! Target voltage during prequalification, in mV. +#define CELL_VOLTAGE_PREQUAL 3000 + + +//****************************************************************************** +// Battery limits +//****************************************************************************** +// Battery-definitions. +//! Number of cells in battery. +#define BAT_CELL_NUMBER 1 + +//! Maximum cell temperature (Celsius). +#define BAT_TEMPERATURE_MAX 45 + +//! Minimum Cell temperature (Celsius). +#define BAT_TEMPERATURE_MIN 0 + +//! Maximum time for prequalification, in minutes. +#define BAT_TIME_PREQUAL 9 + +//! \brief Constant charge current, in mA, during prequalification mode. +//! \note This is typically lower than the main charge current. +#define BAT_CURRENT_PREQUAL 150 + +//! Charge current hysteresis, in mA. +#define BAT_CURRENT_HYST 5 + +//! Charge voltage hysteresis, in mV. +#define BAT_VOLTAGE_HYST 10 + +//! Maximum battery voltage, in mV. +#define BAT_VOLTAGE_MAX (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \ + ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY) + +//! Minimum voltage, in mV, to consider battery charged. +#define BAT_VOLTAGE_LOW (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER) + +//! Minimum voltage, in mV, to consider battery safe to charge. +#define BAT_VOLTAGE_MIN (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER) + +//! Charge voltage to achieve, in mV, during prequalification mode. +#define BAT_VOLTAGE_PREQUAL (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER) + +#endif // LIIONSPECS_H diff --git a/BaseTinyFirmware/IAR/NIMHcharge.c b/BaseTinyFirmware/IAR/NIMHcharge.c new file mode 100644 index 0000000..5d85a71 --- /dev/null +++ b/BaseTinyFirmware/IAR/NIMHcharge.c @@ -0,0 +1,179 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Charge state function for NiMH batteries + * + * Contains the charge state function, in which the NiMH charging + * algorithm is, plus the associated functions. + * + * \par Application note: + * AVR463: Charging NiMH Batteries with BC100 \n + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2255 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $ + * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" +#include "structs.h" + +#include "battery.h" +#include "charge.h" +#include "chargefunc.h" +#include "main.h" +#include "menu.h" +#include "NIMHspecs.h" +#include "PWM.h" +#include "time.h" + +#ifndef NIMH +#error NIMH not defined in main.h! +#endif // NIMH + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Controls the charging. + * + * This function contains the charging algorithm itself, divided into stages.\n + * For each stage the PWM may be started/stopped, and the timer, + * halt-requirements and charge parameters may be set.\n + * The charging functions return whatever state is next, and as long as no + * errors occur this is the next charging stage. + * + * \note If more stages are needed simply define more states in menu.h, include + * them in \ref menu_state[] in menu.c, then add the cases to this function. + * + * \note This algorithm is for NiMH batteries. + */ +unsigned char Charge(unsigned char inp) +{ + unsigned char NextState; + + switch (CurrentState) { + // First stage is a prequalification. Attempt to charge battery to 1 V, + // using a 0.1 C current, within 2 minutes. + // If this fails, the battery is likely damaged. + // If it succeeds, start a fast charge. + case ST_PREQUAL: + + // Set up charge current and next state. + ChargeParameters.Current = BattData.Capacity / 10; + ChargeParameters.NextState = ST_FASTCHARGE; + + // Halt charge on voltage limit or timeout. + // Timeout means battery exhaustion. + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_FLAG_EXHAUSTION); + + // Set up voltage limit and temperature limits. + HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + HaltParameters.TemperatureMax = 35; + + // Reset temperature measurement for HaltNow(). + HaltParameters.LastNTC = 0; + + // Start PWM and charge timer before calling the charge function. + PWM_Start(); + Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + + // Call charge function, get next state. + NextState = ConstantCurrent(); + break; + + + // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours, + // until either rate of temperature increase or voltage reaches limit, or + // the voltage drops sufficiently. + // Timeout doesn't mean battery exhaustion now. + case ST_FASTCHARGE: + + // Set up charge current and next state. + ChargeParameters.Current = BattData.Capacity; + ChargeParameters.NextState = ST_LOWRATECHARGE; + + // Halt charge on voltage limit, timeout, voltage drop or rate of + // temperature increase. + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE); + + // Set up limits for voltage, voltage drop, temperature and rate of + // temperature increase (1 degree C per minute). + HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP; + HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + HaltParameters.TemperatureRise = 1; + + // Reset maximum voltage measurement for HaltNow(). + HaltParameters.VBATMax = 0; + + // Start timer, PWM should still be running. + Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0); + + // Call charge function, get next state. + NextState = ConstantCurrent(); + break; + + + // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes, + // until either rate of temperature increase or voltage reaches limit. + case ST_LOWRATECHARGE: + + // Set up charge current and next state. + ChargeParameters.Current = BattData.Capacity / 10; + ChargeParameters.NextState = ST_ENDCHARGE; + + // Halt charge on voltage limit, timeout or temperature rise. + // Use the same requirements as during the last stage (ST_FASTCHARGE). + HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + HALT_TEMPERATURE_RISE); + + // Start timer, 30 minutes. + Time_Set(TIMER_CHG, 30, 0, 0); + + // Call charge function, get next state. + NextState = ConstantCurrent(); + break; + + + // Charging is done! + case ST_ENDCHARGE: + + // Stop the PWM output and flag battery as charged. + PWM_Stop(); + BattData.Charged = TRUE; + + // If the other battery is enabled go to ST_BATCON, otherwise + // go to ST_SLEEP. + if (BattControl[(BattActive+1)%2].Enabled) { + NextState = ST_BATCON; + } else { + NextState = ST_SLEEP; + } + break; + + + default: // Shouldn't end up here. Reinitialize for safety. + NextState = ST_INIT; + break; + } + + // Return the next state to main(). + return(NextState); +} diff --git a/BaseTinyFirmware/IAR/NIMHspecs.h b/BaseTinyFirmware/IAR/NIMHspecs.h new file mode 100644 index 0000000..cd27677 --- /dev/null +++ b/BaseTinyFirmware/IAR/NIMHspecs.h @@ -0,0 +1,108 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * NiMH specifications + * + * Contains example definitions of NiMH battery specifications. + * + * \par Application note: + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2255 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHspecs.h $ + * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n + ******************************************************************************/ + +#ifndef NIMHSPECS_H +#define NIMHSPECS_H + + +//****************************************************************************** +// Cell limits +//****************************************************************************** +// This is for common NiMH batteries. +#define CELL_VOLTAGE_SAFETY 0 /*!< \brief Buffer for unmatched batteries. + * + * If we are charging a multicell battery and the cells aren't matched, we + * may risk overcharging at least one. Therefore, we may subtract this constant + * per additional cell in battery to allow for a "buffer". + * + * \note Set to 0 if batteries are properly matched. + * + * \note If this is changed to something higher than (CELL_VOLTAGE_MAX - + * CELL_VOLTAGE_LOW), and the number of cells is great enough, the limit + * BAT_VOLTAGE_LOW will become higher than BAT_VOLTAGE_MAX. This will cause + * the charger to keep trying to charge, but instantly finishing because + * the battery voltage is already at max. + */ +//! Maximum charge voltage for cell, in mV. +#define CELL_VOLTAGE_MAX 1600 + +//! Minimum voltage to consider cell charged at, in mV. +#define CELL_VOLTAGE_LOW 1350 + +//! Minimum voltage to start charging at, in mV. +#define CELL_VOLTAGE_MIN 800 + +//! Target voltage during prequalification, in mV. +#define CELL_VOLTAGE_PREQUAL 1000 + +//! Cell voltage drop when full charge is achieved. +#define CELL_VOLTAGE_DROP 15 + + +//****************************************************************************** +// Battery limits +//****************************************************************************** +// Battery-definitions. +//! Number of cells in battery. +#define BAT_CELL_NUMBER 3 + +//! Maximum cell temperature (Celsius). +#define BAT_TEMPERATURE_MAX 50 + +//! Minimum Cell temperature (Celsius). +#define BAT_TEMPERATURE_MIN 5 + +//! Maximum time for prequalification, in minutes. +#define BAT_TIME_PREQUAL 2 + +//! \brief Constant charge current, in mA, during prequalification mode. +//! \note This is typically lower than the main charge current. +#define BAT_CURRENT_PREQUAL 150 + +//! Charge current hysteresis, in mA. +#define BAT_CURRENT_HYST 3 + +//! Charge voltage hysteresis, in mV. +#define BAT_VOLTAGE_HYST 10 + +//! Maximum battery voltage, in mV. +#define BAT_VOLTAGE_MAX (CELL_VOLTAGE_MAX * BAT_CELL_NUMBER) - \ + ((BAT_CELL_NUMBER - 1) * CELL_VOLTAGE_SAFETY) + +//! Minimum voltage, in mV, to consider battery charged. +#define BAT_VOLTAGE_LOW (CELL_VOLTAGE_LOW * BAT_CELL_NUMBER) + +//! Minimum voltage, in mV, to consider battery safe to charge. +#define BAT_VOLTAGE_MIN (CELL_VOLTAGE_MIN * BAT_CELL_NUMBER) + +//! Voltage drop, in mV, when full charge is achieved. +#define BAT_VOLTAGE_DROP (CELL_VOLTAGE_DROP * BAT_CELL_NUMBER) + +//! Charge voltage to achieve, in mV, during prequalification mode. +#define BAT_VOLTAGE_PREQUAL (CELL_VOLTAGE_PREQUAL * BAT_CELL_NUMBER) + +#endif // NIMHSPECS_H diff --git a/BaseTinyFirmware/IAR/OWI.c b/BaseTinyFirmware/IAR/OWI.c new file mode 100644 index 0000000..98cdd9c --- /dev/null +++ b/BaseTinyFirmware/IAR/OWI.c @@ -0,0 +1,516 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ******************************************************************** + * + * \brief + * Functions for 1-Wire(R) bus communication + * + * High level functions for transmission of full bytes on the 1-Wire(R) + * bus and implementations of ROM commands.\n + * Polled software only implementation of the basic bit-level signalling + * in the 1-Wire(R) protocol.\n + * Includes functions for computing and checking CRC8 & 16 values of data + * sets, and of 64 bit ROM identifiers. + * Supported devices: All AVRs. + * + * \par Application Note: + * AVR458: Charging Li-Ion Batteries with BC100\n + * AVR463: Charging NiMH Batteries with BC100\n + * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +****************************************************************************/ + +#include +#include + +#include "OWI.h" + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Initialization of the one wire bus(es). (Software only driver) + * + * This function initializes the 1-Wire bus(es) by releasing it and + * waiting until any presence signals are finished. + * + * \param pins A bitmask of the buses to initialize. + */ +void OWI_Init(unsigned char pins){ + OWI_RELEASE_BUS(pins); + // The first rising edge can be interpreted by a slave as the end of a + // Reset-pulse. Delay for the required reset recovery time (H) to be + // sure that the real reset is interpreted correctly. + __delay_cycles(OWI_DELAY_H_STD_MODE); +} + + +/*! \brief Write a '1' bit to the bus(es). (Software only driver) + * + * Generates the waveform for transmission of a '1' bit on the 1-Wire + * bus. + * + * \param pins A bitmask of the buses to write to. + */ +void OWI_WriteBit1(unsigned char pins){ + unsigned char intState; + + // Disable interrupts. + intState = __save_interrupt(); + __disable_interrupt(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + __delay_cycles(OWI_DELAY_A_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + __delay_cycles(OWI_DELAY_B_STD_MODE); + + // Restore interrupts. + __restore_interrupt(intState); +} + +/*! \brief Write a '0' to the bus(es). (Software only driver) + * + * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) + * bus. + * + * \param pins A bitmask of the buses to write to. + */ +void OWI_WriteBit0(unsigned char pins) +{ + unsigned char intState; + + // Disable interrupts. + intState = __save_interrupt(); + __disable_interrupt(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + __delay_cycles(OWI_DELAY_C_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + __delay_cycles(OWI_DELAY_D_STD_MODE); + + // Restore interrupts. + __restore_interrupt(intState); +} + +/*! \brief Read a bit from the bus(es). (Software only driver) + * + * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). + * + * \param pins A bitmask of the bus(es) to read from. + * + * \return A bitmask of the buses where a '1' was read. + */ +unsigned char OWI_ReadBit(unsigned char pins) +{ + unsigned char intState; + unsigned char bitsRead; + + // Disable interrupts. + intState = __save_interrupt(); + __disable_interrupt(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + __delay_cycles(OWI_DELAY_A_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + __delay_cycles(OWI_DELAY_E_STD_MODE); + + // Sample bus and delay. + bitsRead = OWI_PIN & pins; + __delay_cycles(OWI_DELAY_F_STD_MODE); + + // Restore interrupts. + __restore_interrupt(intState); + + return bitsRead; +} + + +/*! \brief Send a Reset signal and listen for Presence signal. (software + * only driver) + * + * Generates the waveform for transmission of a Reset pulse on the + * 1-Wire(R) bus and listens for presence signals. + * + * \param pins A bitmask of the buses to send the Reset signal on. + * + * \return A bitmask of the buses where a presence signal was detected. + */ +unsigned char OWI_DetectPresence(unsigned char pins) +{ + unsigned char intState; + unsigned char presenceDetected; + + // Disable interrupts. + intState = __save_interrupt(); + __disable_interrupt(); + + // Drive bus low and delay. + OWI_PULL_BUS_LOW(pins); + __delay_cycles(OWI_DELAY_H_STD_MODE); + + // Release bus and delay. + OWI_RELEASE_BUS(pins); + __delay_cycles(OWI_DELAY_I_STD_MODE); + + // Sample bus to detect presence signal and delay. + presenceDetected = ((~OWI_PIN) & pins); + __delay_cycles(OWI_DELAY_J_STD_MODE); + + // Restore interrupts. + __restore_interrupt(intState); + + return presenceDetected; +} + + +/*! \brief Sends one byte of data on the 1-Wire(R) bus(es). + * + * This function automates the task of sending a complete byte + * of data on the 1-Wire bus(es). + * + * \param data The data to send on the bus(es). + * + * \param pins A bitmask of the buses to send the data to. + */ +void OWI_SendByte(unsigned char data, unsigned char pins) +{ + unsigned char temp; + unsigned char i; + + // Do once for each bit + for (i = 0; i < 8; i++) { + // Determine if LSB is '0' or '1' and transmit corresponding + // waveform on the bus. + temp = data & 0x01; + + if (temp) { + OWI_WriteBit1(pins); + } else { + OWI_WriteBit0(pins); + } + + data >>= 1; // Right shift the data to get next bit. + } +} + + +/*! \brief Receives one byte of data from the 1-Wire(R) bus. + * + * This function automates the task of receiving a complete byte + * of data from the 1-Wire bus. + * + * \param pin A bitmask of the bus to read from. + * + * \return The byte read from the bus. + */ +unsigned char OWI_ReceiveByte(unsigned char pin) +{ + unsigned char data; + unsigned char i; + + // Clear the temporary input variable. + data = 0x00; + + // Do once for each bit + for (i = 0; i < 8; i++) { + // Shift temporary input variable right. + data >>= 1; + + // Set the MSB if a '1' value is read from the bus. + // Leave as it is ('0') else. + if (OWI_ReadBit(pin)) { + data |= 0x80; + } + } + + return data; +} + + +/*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). + * + * \param pins A bitmask of the buses to send the SKIP ROM command to. + */ +void OWI_SkipRom(unsigned char pins) +{ + // Send the SKIP ROM command on the bus. + OWI_SendByte(OWI_ROM_SKIP, pins); +} + + +/*! \brief Sends the READ ROM command and reads back the ROM id. + * + * \param romValue A pointer where the id will be placed. + * + * \param pin A bitmask of the bus to read from. + */ +void OWI_ReadRom(unsigned char * romValue, unsigned char pin) +{ + unsigned char bytesLeft = 8; + + // Send the READ ROM command on the bus. + OWI_SendByte(OWI_ROM_READ, pin); + + // Do 8 times. + while (bytesLeft > 0) { + // Place the received data in memory. + *romValue++ = OWI_ReceiveByte(pin); + bytesLeft--; + } +} + + +/*! \brief Sends the MATCH ROM command and the ROM id to match against. + * + * \param romValue A pointer to the ID to match against. + * + * \param pins A bitmask of the buses to perform the MATCH ROM command on. + */ +void OWI_MatchRom(unsigned char * romValue, unsigned char pins) +{ + unsigned char bytesLeft = 8; + + // Send the MATCH ROM command. + OWI_SendByte(OWI_ROM_MATCH, pins); + + // Do once for each byte. + while (bytesLeft > 0) { + // Transmit 1 byte of the ID to match. + OWI_SendByte(*romValue++, pins); + bytesLeft--; + } +} + + +/*! \brief Sends the SEARCH ROM command and returns 1 id found on the + * 1-Wire(R) bus. + * + * \param bitPattern A pointer to an 8 byte char array where the + * discovered identifier will be placed. When + * searching for several slaves, a copy of the + * last found identifier should be supplied in + * the array, or the search will fail. + * + * \param lastDeviation The bit position where the algorithm made a + * choice the last time it was run. This argument + * should be 0 when a search is initiated. Supplying + * the return argument of this function when calling + * repeatedly will go through the complete slave + * search. + * + * \param pin A bit-mask of the bus to perform a ROM search on. + * + * \return The last bit position where there was a discrepancy between slave + * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED + * if an error was detected (e.g. a device was connected to the bus during the + * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be + * discovered. + * + * \note See main.c for an example of how to utilize this function. + */ +unsigned char OWI_SearchRom(unsigned char * bitPattern, + unsigned char lastDeviation, unsigned char pin) +{ + unsigned char currentBit = 1; + unsigned char newDeviation = 0; + unsigned char bitMask = 0x01; + unsigned char bitA; + unsigned char bitB; + + // Send SEARCH ROM command on the bus. + OWI_SendByte(OWI_ROM_SEARCH, pin); + + // Walk through all 64 bits. + while (currentBit <= 64) { + // Read bit from bus twice. + bitA = OWI_ReadBit(pin); + bitB = OWI_ReadBit(pin); + + if (bitA && bitB) { + // Both bits 1 (Error). + newDeviation = OWI_ROM_SEARCH_FAILED; + return newDeviation; + } else if (bitA ^ bitB) { + // Bits A and B are different. All devices have the same bit here. + // Set the bit in bitPattern to this value. + if (bitA) { + (*bitPattern) |= bitMask; + } else { + (*bitPattern) &= ~bitMask; + } + } else { + // If this is where a choice was made the last time, + // a '1' bit is selected this time. + if (currentBit == lastDeviation) { + (*bitPattern) |= bitMask; + } + + // For the rest of the id, '0' bits are selected when + // discrepancies occur. + else if (currentBit > lastDeviation) { + (*bitPattern) &= ~bitMask; + newDeviation = currentBit; + } + + // If current bit in bit pattern = 0, then this is + // out new deviation. + else if ( !(*bitPattern & bitMask)) { + newDeviation = currentBit; + } + + // IF the bit is already 1, do nothing. + else { + } + } + + // Send the selected bit to the bus. + if ((*bitPattern) & bitMask) { + OWI_WriteBit1(pin); + } else { + OWI_WriteBit0(pin); + } + + // Increment current bit. + currentBit++; + + // Adjust bitMask and bitPattern pointer. + bitMask <<= 1; + if (!bitMask) { + bitMask = 0x01; + bitPattern++; + } + } + + return newDeviation; +} + + +/* Functions for handling CRC */ +/*! \brief Compute the CRC8 value of a data set. + * + * This function will compute the CRC8 or DOW-CRC of inData using seed + * as inital value for the CRC. + * + * \param inData One byte of data to compute CRC from. + * + * \param seed The starting value of the CRC. + * + * \return The CRC8 of inData with seed as initial value. + * + * \note Setting seed to 0 computes the crc8 of the inData. + * + * \note Constantly passing the return value of this function + * As the seed argument computes the CRC8 value of a + * longer string of data. + */ +unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) +{ + unsigned char bitsLeft; + unsigned char temp; + + for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + temp = ((seed ^ inData) & 0x01); + + if (temp == 0) { + seed >>= 1; + } else { + seed ^= 0x18; + seed >>= 1; + seed |= 0x80; + } + + inData >>= 1; + } + return seed; +} + + +/*! \brief Compute the CRC16 value of a data set. + * + * This function will compute the CRC16 of inData using seed + * as inital value for the CRC. + * + * \param inData One byte of data to compute CRC from. + * + * \param seed The starting value of the CRC. + * + * \return The CRC16 of inData with seed as initial value. + * + * \note Setting seed to 0 computes the crc16 of the inData. + * + * \note Constantly passing the return value of this function + * As the seed argument computes the CRC16 value of a + * longer string of data. + */ +unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) +{ + unsigned char bitsLeft; + unsigned char temp; + + for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + temp = ((seed ^ inData) & 0x01); + + if (temp == 0) { + seed >>= 1; + } else { + seed ^= 0x4002; + seed >>= 1; + seed |= 0x8000; + } + + inData >>= 1; + } + + return seed; +} + + +/*! \brief Calculate and check the CRC of a 64 bit ROM identifier. + * + * This function computes the CRC8 value of the first 56 bits of a + * 64 bit identifier. It then checks the calculated value against the + * CRC value stored in ROM. + * + * \param *romValue A pointer to an array holding a 64 bit identifier. + * + * \retval OWI_CRC_OK The CRC's matched. + * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. + */ +unsigned char OWI_CheckRomCRC(unsigned char *romValue) +{ + unsigned char i; + unsigned char crc8 = 0; + + for (i = 0; i < 7; i++) { + crc8 = OWI_ComputeCRC8(*romValue, crc8); + romValue++; + } + + if (crc8 == (*romValue)) { + return OWI_CRC_OK; + } + + return OWI_CRC_ERROR; +} diff --git a/BaseTinyFirmware/IAR/OWI.h b/BaseTinyFirmware/IAR/OWI.h new file mode 100644 index 0000000..f07f7a2 --- /dev/null +++ b/BaseTinyFirmware/IAR/OWI.h @@ -0,0 +1,178 @@ +// This file has been prepared for Doxygen automatic documentation generation. +/*! \file ******************************************************************** + * + * \brief + * Header file for OWI.c + * + * Contains definitions used in the polled 1-Wire(R) driver. + * + * \par Application Note: + * AVR458: Charging Li-Ion Batteries with BC100\n + * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n +****************************************************************************/ + +#ifndef OWI_H +#define OWI_H + +#include + + +//****************************************************************************** +// Defines for CRC-functions +//****************************************************************************** +#define OWI_CRC_OK 0x00 //!< CRC check succeded +#define OWI_CRC_ERROR 0x01 //!< CRC check failed + + +//****************************************************************************** +// Defines for OWI-functions +//****************************************************************************** +/*! \brief CPU clock frequency. + * + * This define is used to calculate delays when the software only driver + * is used. The CPU frequency must be at least 2.170 MHz to be able to + * generate the shortest delays. + */ +#define CPU_FREQUENCY 8.000 + + +/*! \brief Use internal pull-up resistor on 1-Wire buses. + * + * If this symbol is defined, the internal pull-up resister on the GPIO pins + * of the AVR will be used to generate the necessary pull-up on the bus. If + * an external pull-up resistor is used, uncomment this define. + */ +//#define OWI_USE_INTERNAL_PULLUP + + +// Port configuration registers for 1-Wire buses. +// Make sure that all three registers belong to the same port. +#define OWI_PORT PORTA //!< 1-Wire PORT Data register. +#define OWI_PIN PINA //!< 1-Wire Input pin register. +#define OWI_DDR DDRA //!< 1-Wire Data direction register. + + +//****************************************************************************** +// Pin bitmasks +//****************************************************************************** +#define OWI_PIN_0 0x01 +#define OWI_PIN_1 0x02 +#define OWI_PIN_2 0x04 +#define OWI_PIN_3 0x08 +#define OWI_PIN_4 0x10 +#define OWI_PIN_5 0x20 +#define OWI_PIN_6 0x40 +#define OWI_PIN_7 0x80 + + +//****************************************************************************** +// Timing parameters +//****************************************************************************** +//! Timing delay when pulling bus low and releasing bus. +#define OWI_DELAY_OFFSET_CYCLES 13 + +// Bit timing delays in clock cycles (= us*clock freq in MHz). +#define OWI_DELAY_A_STD_MODE (unsigned long)((6 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_B_STD_MODE (unsigned long)((64 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_C_STD_MODE (unsigned long)((60 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_D_STD_MODE (unsigned long)((10 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_E_STD_MODE (unsigned long)((9 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_F_STD_MODE (unsigned long)((55 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +//#define OWI_DELAY_G_STD_MODE (unsigned long)((0 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_H_STD_MODE (unsigned long)((480 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_I_STD_MODE (unsigned long)((70 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) +#define OWI_DELAY_J_STD_MODE (unsigned long)((410 * CPU_FREQUENCY) - OWI_DELAY_OFFSET_CYCLES) + + +//****************************************************************************** +// ROM commands +//****************************************************************************** +#define OWI_ROM_READ 0x33 //!< READ ROM command code. +#define OWI_ROM_SKIP 0xcc //!< SKIP ROM command code. +#define OWI_ROM_MATCH 0x55 //!< MATCH ROM command code. +#define OWI_ROM_SEARCH 0xf0 //!< SEARCH ROM command code. + + +//****************************************************************************** +// Return codes +//****************************************************************************** +#define OWI_ROM_SEARCH_FINISHED 0x00 //!< Search finished return code. +#define OWI_ROM_SEARCH_FAILED 0xff //!< Search failed return code. + + +//****************************************************************************** +// Macros +//****************************************************************************** +/*! \brief Pull 1-Wire bus low. + * + * This macro sets the direction of the 1-Wire pin(s) to output and + * pull the line(s) low. + * + * \param bitMask A bitmask of the buses to pull low. + */ +#define OWI_PULL_BUS_LOW(bitMask) \ + OWI_DDR |= (bitMask); \ + OWI_PORT &= ~(bitMask) + + +/*! \def OWI_RELEASE_BUS(bitMask) + * + * \brief Release the bus. + * + * This macro releases the bus and enables the internal pull-up if + * it is used. + * + * \param bitMask A bitmask of the buses to release. + */ +#ifdef OWI_USE_INTERNAL_PULLUP + // Set 1-Wire pin(s) to input and enable internal pull-up resistor. +#define OWI_RELEASE_BUS(bitMask) \ + OWI_DDR &= ~(bitMask); \ + OWI_PORT |= (bitMask) + +#else + // Set 1-Wire pin(s) to input mode. No internal pull-up enabled. +#define OWI_RELEASE_BUS(bitMask) \ + OWI_DDR &= ~(bitMask); \ + OWI_PORT &= ~(bitMask) + +#endif + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +void OWI_SendByte(unsigned char data, unsigned char pins); +unsigned char OWI_ReceiveByte(unsigned char pin); +void OWI_SkipRom(unsigned char pins); +void OWI_ReadRom(unsigned char * romValue, unsigned char pin); +void OWI_MatchRom(unsigned char * romValue, unsigned char pins); +unsigned char OWI_SearchRom(unsigned char * bitPattern, + unsigned char lastDeviation, unsigned char pin); +void OWI_Init(unsigned char pins); +void OWI_WriteBit1(unsigned char pins); +void OWI_WriteBit0(unsigned char pins); +unsigned char OWI_ReadBit(unsigned char pins); +unsigned char OWI_DetectPresence(unsigned char pins); + +unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed); +unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed); +unsigned char OWI_CheckRomCRC(unsigned char *romValue); + +#endif // OWI_H + diff --git a/BaseTinyFirmware/IAR/PWM.c b/BaseTinyFirmware/IAR/PWM.c new file mode 100644 index 0000000..b00c75a --- /dev/null +++ b/BaseTinyFirmware/IAR/PWM.c @@ -0,0 +1,150 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for use of PWM + * + * Contains functions for initializing and controlling PWM output. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100\n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" + +#include "main.h" +#include "PWM.h" +#include "time.h" + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Stops PWM output + * + */ +void PWM_Stop(void) +{ + OCR1B = 0; // Reset compare level. + PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode. + TCCR1A = 0; // Set normal port operation, disable PWM modes. + TCCR1B = 0; // Stop timer/counter1. + TCCR1C = 0; // Set normal port operation. + TCCR1D = 0; // No fault protection, normal waveform. + OCR1C = 0; // Reset compare. + OCR1D = 0; // Reset compare. + DT1 = 0; // No dead time values. +} + + +/*! \brief Initializes and starts PWM output + * + * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n + * Its comparator is connected to PB3 and will output high until timer1 reaches + * the value of OCR1B. It is then dropped to 0.\n + * The comparator outputs high again when the counter overflows, which will + * happen at a rate of 250 kHz. + */ +void PWM_Start(void) +{ + // Clear OC1B on compare match, enable PWM on comparator OCR1B. + TCCR1A = (1< 0) { + OCR1B -= 1; + return(TRUE); + } else { + return(FALSE); + } +} diff --git a/BaseTinyFirmware/IAR/PWM.h b/BaseTinyFirmware/IAR/PWM.h new file mode 100644 index 0000000..bda3a88 --- /dev/null +++ b/BaseTinyFirmware/IAR/PWM.h @@ -0,0 +1,50 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Header file for PWM.c + * + * Contains definitions to control PWM behaviour. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef PWM_H +#define PWM_H + +//****************************************************************************** +// Constants for PWM +//****************************************************************************** +//! Needed for JumperCheck() to succeed. ADC is saturated otherwise! +#define PWM_OFFSET 12 + +//! PWM duty cycle limit (must be less than 256). +#define PWM_MAX 255 + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +void PWM_Start(void); +void PWM_Stop(void); +unsigned char PWM_IncrementDutyCycle(void); +unsigned char PWM_DecrementDutyCycle(void); + +#endif // PWM_H + diff --git a/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny.hex b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny.hex new file mode 100644 index 0000000..1bf58a1 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny.hex @@ -0,0 +1,298 @@ +:020000020000FC +:100000004BC8189518951895189518951895189522 +:100010001FC3189518951CC018951895A1C7189559 +:100020001895189518950AFF061428071E9D012893 +:100030006707329D013C9D01469D015065075A6945 +:10004000070000005300440100007400D000FA11C2 +:100050004A92BA93AA939A938A93FA93EA933A921A +:100060002A921A920A927A936A935A934A933A93EB +:100070002A931A930A934FB680E090E03798A4E44D +:10008000B1E00C910F710A9549F00A9571F00A954B +:1000900099F0025011F1025181F17EC004B115B105 +:1000A000FD010483158302E078C004B115B1FD01A0 +:1000B0000283138303E071C024B135B104E092D010 +:1000C000FD0100871187003311410C9110F40F7B63 +:1000D00001C000640C9305E060C004B115B1FD01DE +:1000E0000683178324B135B140E050E0ECD77AD0D5 +:1000F000FD010287138707E150C004B115B112302A +:10010000C0F000E014E024B135B1021B130BFD0177 +:10011000218122952F7030E0200F311F40E050E008 +:10012000D2D793D0119501951040FD010487158712 +:1001300014C004B115B1012B69F024B135B1FD0132 +:10014000018102950F70201B304040E050E0BBD78A +:100150007CD0EBCFFD018487858724853585008D94 +:100160000370000FE00FF81F26873787FD01008D11 +:100170000395008F3E9604E021913191820F931FE9 +:100180000A95D1F78C0144E050E0E1D7FD01068BE0 +:10019000178B0C9100620C9301E01C91107E0F7183 +:1001A000012B0C930F71005C07B91F980C91007A1A +:1001B000003A19F006B1006C06B94FBE09911991C9 +:1001C00029913991499159916991799109901990A1 +:1001D00029903990E991F99189919991A991B991D1 +:1001E000499018952A2EBC01A02FC9010330A901FE +:1001F000A1F40DE110E077D7369527953695279530 +:10020000200D311D9695879596958795969587959E +:1002100096958795820F931F14C007E210E063D76D +:1002200096958795969587959695879596958795B2 +:10023000800D911DA33028F48C0143E04A1B69D73F +:10024000C8018C01CB01A22D08952A2EBC01A02F3C +:10025000C9010330A901A9F405E110E044D736959E +:100260002795369527953695279536952795021B20 +:10027000130B880F892F881F90E0991F800F911F03 +:100280001AC00CE110E02FD798018C011695079544 +:100290001695079516950795201B310B8C0145E0A7 +:1002A00038D7C801820F931FA33028F48C0143E094 +:1002B0004A1B2FD7C8018C01CB01A22D0895FFCF77 +:1002C000F894E4E4F1E000810F7700830AB3097049 +:1002D0000ABB0BB309700BBB03E407B900E003B919 +:1002E00007EC06B9349BFECF349A2181207F04B1FC +:1002F00015B10F70022B018316E517B917EC16B96B +:10030000349BFECF349A0F7024B135B12295207FF3 +:10031000202B21830081007C0160008301E407B968 +:1003200000E0068B078B3E9624E0019301932A950B +:10033000E1F70FEC06B97894FFCF009184010E51DC +:1003400049F0045149F10A5009F44AC00A5009F42D +:100350005EC077C0E1E6F1E0048115814AE050E03B +:10036000DED6EFE7F1E00283138302E30483EEE6D7 +:10037000F1E0008308EB1BE00383148305E010E049 +:100380000187128703E2078310871787108B24D118 +:1003900040E010E022E037C021E631E0F9010481BD +:1003A0001581EFE7F1E0028313830CE30483EEE6AB +:1003B000F1E00BE1008300EC12E1038314830DE212 +:1003C00010E00183128302E30783108701E00387B3 +:1003D00014871587168740E0F9012085318515C0FF +:1003E000E1E6F1E0048115814AE050E098D6EFE7BC +:1003F000F1E00283138306E404830AE100936E01B3 +:1004000040E010E02EE130E001E0E9D596C3D9D01C +:10041000E1E6F1E000810260008300916D0110E0EF +:100420000F5F1F4F42E050E092D621E030E0240FF2 +:10043000351FA90148D6017011F004E1089508E2C2 +:1004400008950AE0089500951AB310231ABB1BB350 +:1004500010231BBB0CEB13E001501040E9F700C068 +:1004600008951FB7F8942AB3202B2ABB00952BB30D +:1004700020232BBB2BE02A95F1F700C02AB32023C1 +:100480002ABB2BB320232BBB06EA0A95F1F7000009 +:100490001FBF08951FB7F8942AB3202B2ABB0095DD +:1004A0002BB320232BBB2BE92A95F1F700C02AB3ED +:1004B00020232ABB2BB320232BBB06E10A95F1F79F +:1004C00000001FBF08952FB7F8941AB3102B1ABB62 +:1004D000102F10953BB331233BBB3BE03A95F1F72E +:1004E00000C03AB331233ABB3BB331233BBB13E1EA +:1004F0001A95F1F700C019B310230EE80A95F1F729 +:1005000000002FBF012F08952FB7F8941AB3102BB6 +:100510001ABB102F10953BB331233BBB4CEB53E080 +:1005200041505040E9F700C03AB331233ABB3BB3E6 +:1005300031233BBB16EB1A95F1F7000019B3109568 +:10054000012340E353E041505040E9F700C02FBF82 +:100550000895AA939A938A93A02F912F88E0A0FBE5 +:10056000092F16F47EDF01C095DFA6958A95B9F7AD +:1005700089919991A9910895AA939A938A93A02F0A +:1005800090E088E096950A2F9EDF002309F090689E +:100590008A95C1F7092F89919991A991089538E019 +:1005A000212F2170402F4170422711F4169504C06D +:1005B00028E112271695106806953A9589F7012FBC +:1005C000089500E00CBD09BD00BF0FBD07BD06BD0D +:1005D0000BBD0ABD04BD089501E200BF00E00FBDE0 +:1005E00000B7007F07BD00E006BD00B90DBD0CE0FF +:1005F0000CBD0FEF0BBD00E00ABD04BDBB9A02E0CD +:1006000009BD41E010E020E030E0E9D402E0D3D4BD +:100610000023E1F709B500FFFDCF09B5046009BD6E +:100620000FB501600FBD08950CB50F3F29F00CB553 +:1006300003950CBD01E0089500E008950CB500237A +:1006400029F00CB50A950CBD01E0089500E008956D +:100650008A93FA93EA933A922A921A920A927A9396 +:100660006A935A934A933A932A931A930A938FB7A9 +:1006700000E0A1D4002331F4EDE5F1E002810F7335 +:100680000064028340E011E020E030E000E0A7D405 +:1006900000E40EB9EDE5F1E003810460038312810B +:1006A000012F000F001F001F0370015029F00A9551 +:1006B00001F10A9531F172C00FB10083002309F4F2 +:1006C0006DC006FF03C003810E7F02C0038101607D +:1006D0000383008107FF03C00381026002C003811E +:1006E0000D7F038300810F73006802830CEC83D0BD +:1006F00055C00FB100830183012F006C02830BEB07 +:10070000F6CF212F107C022F0A950F73012B028345 +:100710002F7309F440C02181138110FF2EC02A9548 +:1007200049F02A9571F02A9591F02A95B1F02A9511 +:10073000E1F021C00F7310E0F801EC5BFE4F008187 +:10074000D6CF0F7310E0F801E359FE4FF8CF0F73C7 +:1007500010E0F801EF59FE4FF2CF0F7310E041E0C7 +:1007600050E0400F511FAFD4C2CF0F7310E0F8011B +:10077000E957FE4FE4CF00E0BACF1FB110832450F9 +:1007800069F4212F0F7310E041E050E0400F511F3A +:10079000022FA5D403C00F73006402838FBF099199 +:1007A00019912991399149915991699179910990BA +:1007B000199029903990E991F99189911895F894B7 +:1007C000B99A17B31A7F17BB18B3156018BB000F7F +:1007D000000F08650DB9EDE5F1E000E0008303814D +:1007E0000C7F038300E4028300E001830381037F25 +:1007F0000383789408951EB11F70EDE5F1E029F0B0 +:1008000003810860038300E008951381137F13833D +:100810000FB901E00895BA93AA938A9381E0E1E6C3 +:10082000F1E0A481B58110D0002309F480E0E1E675 +:10083000F1E004811581A017B10709F080E0082FCD +:100840008991A991B9910895BA93AA939A938A9399 +:10085000A1E6B1E00C910C7F04600C9300E0FD0177 +:10086000018302830483058306830783008701874E +:10087000028703871ED1DBD0102F117010FB0C9163 +:1008800004F90C93E4E4F1E002851385003629E0D5 +:10089000120718F00C910B7F0C930285023D1F404C +:1008A00018F00C9102600C930CB5002319F40C9114 +:1008B00002FF08C00CB5002351F08689978981306A +:1008C00090402CF00C9101600C9301E004C00C915D +:1008D0000B7F0C9300E01C9114FF00E0899199912B +:1008E000A991B99108958A927A926A925A924A92FB +:1008F000BA93AA939A938A9390E0A3E0B0E0772406 +:1009000001E002DE013009F055C011E003E321DE11 +:1009100001E032DE502E10E042DE802F06E0402E55 +:1009200001E02ADE182F3BDE802F4A94C9F701E050 +:1009300023DE182F34DE0023E9F550926201009186 +:1009400062010930B9F5492E429400EF4022440C6F +:1009500011E003ECFEDD11E0042DFBDD11E000E011 +:10096000F8DD10E003EC1BDE102F042D18DE102F35 +:1009700000E015DE802F01E0FFDD182F10DE0023E0 +:10098000C9F480E02D0100E2602E01E0F5DD802E4B +:10099000182F05DE802F082DA201A1D301E0400E03 +:1009A000571C6A9491F7E8DD182FF9DD002311F444 +:1009B000739408C0AD0110E200E091D34F5F5F4F28 +:1009C0001A95D1F793959096943008F498CF072D07 +:1009D00089919991A991B99149905990699079908B +:1009E000899008958A93802F44E610E020E030E05B +:1009F00002E0F5D280936D0101E010E0482F4C5FDA +:100A000082D318B3102B18BB01E010E045E0481B5F +:100A10007AD3009518B3102318BB02E0CCD2002380 +:100A2000E1F78991089508B30F7C08BB08953B2F27 +:100A30002A2E40E0E0EDF0E024E001E611E0A6E43B +:100A4000B1E06D917C910080118060157105F0F02E +:100A50000280138006161706C8F046815781D80118 +:100A600014964D935C9340855185D80116964D930D +:100A70005C9342855385D80118964D935C934485C9 +:100A80005585D8011A964D935C9341E03E962A9580 +:100A9000B1F6442351F420E0F80124832583268312 +:100AA00027832087218722872387042FA22DB32F16 +:100AB0000895BA933A2E282E00E080E0A1E6B1E036 +:100AC000482F50E09A01440F551F420F531F28E052 +:100AD00031E0240F351FE4E4F1E044815581F90150 +:100AE0006081718146175707D0F0082F000F000F63 +:100AF000FD010283F9014281FD0143830091480118 +:100B0000152FF90120813181021B130B000F111FDA +:100B100050E005D3FD011281101B128301E0839583 +:100B2000843110F4002361F2002319F400E50093EE +:100B30006301822DA32DB99108955A924A92BA93D6 +:100B4000AA939A938A9355244424B9DB00916D01AA +:100B500010E041E050E0400F511FB5D2047031F079 +:100B6000442443947BD200E00CBD25C0442011F006 +:100B7000442477D2E4E4F1E00689178911234AF08E +:100B8000A1E8B1E0ED91FC91CF0103970817190797 +:100B900058F44ADD002379F404E09FD10AE500937C +:100BA00083015524539407C03396E017F10718F4D6 +:100BB00045DD002389F30DD0002311F4552029F2DF +:100BC0000091830189919991A991B9914990599086 +:100BD00008959A928A927A926A925A924A92BA9313 +:100BE000AA939A938A9377246ADB6624639484E4B5 +:100BF00091E001E6402E01E0502EAEE6B1E00C910E +:100C0000062109F47CC0062D0A9551F00A9509F1D8 +:100C1000025051F1045079F1085009F453C06FC0EB +:100C2000FD0105851685FC01228533850217130712 +:100C300020F4FD012587368762C0021B130BFD01DE +:100C4000218132810217130708F459C07724739465 +:100C500056C0FC0102851385FD01238134810217F2 +:100C6000130708F44CC0F2CFFD0105811681FC0189 +:100C700026893789F4CFFC0104811581FD01878421 +:100C800090888016910668F4FC0104811581FD01AD +:100C90000787108B40E01EE120E030E003E09FD1A9 +:100CA0002EC0801A910AF201438150E0FD010385B4 +:100CB000148519D28014910410F103E07CD1002333 +:100CC00029F6E2CF01E077D10023C9F477247394A9 +:100CD0000C9105FF14C075DC00916D0110E041E03E +:100CE00050E0400F511FEFD10E7FF9D1F20100818A +:100CF0000860008300E1F1D00AE5FD01058B660C78 +:100D000009F07DCFE1E6F1E00281FD012185328528 +:100D1000102F110F110B2017310744F4102F110F52 +:100D2000110B278130850217130740F04ADC08E0D9 +:100D3000D4D00AE5FD01058B772473946CDD002384 +:100D400031F43FDC0AE0FD01058B772473940091B8 +:100D5000440106FD06C035DC08E2FD01058B772461 +:100D60007394072D89919991A991B99149905990BE +:100D7000699079908990999008959A938A932AE03E +:100D80002093840180E090E000E006C01A3019F45E +:100D90003196859194910395402F50E0BA01440F0C +:100DA000551F460F571FE6E2F0E0E40FF51F1491C0 +:100DB000112361F700E08030900719F0FC010995DC +:100DC000202F009184012017A9F32093840100E0D3 +:100DD000402F50E0BA01440F551F460F571FE6E25F +:100DE000F0E0E40FF51F1491112321F330918401F9 +:100DF000131719F43196859194910395E9CF8A934D +:100E0000F89400E808BD00E008BD01E01CDB43E009 +:100E100050E010E800E063D14F5F5F4F1A95D1F7C3 +:100E200000E307BB00DE00E0CADC4ADA1DD180E047 +:100E3000082FD8DD44DA08DD83958230C8F3F3DD6E +:100E400000E000936D010093850104E1899108950C +:100E5000BA93AA939A938A9349D0002311F40AE58E +:100E60002FC081E090E0AC012ED1017079F4AC018B +:100E70004F5F5F4F28D1017049F4E5E8F1E0008150 +:100E800002600083009184010183E9CFA0E0B0E01B +:100E9000AC014A0F5B1F17D1017069F00A2FA2DD68 +:100EA0000EDAD2DC002339F00091610101FD03C0AC +:100EB0001ADD0EE105C0A395A23048F3B4DD08E2C7 +:100EC00089919991A991B991089504E10895F7D96B +:100ED000FFCF77DBA8DDF3D9FFCFE5E8F1E01081A4 +:100EE000102B10830091840101830895BA93AA9373 +:100EF0009ADD72DB40E011E020E030E002E06FD0EC +:100F0000A4E4B1E010C01C960D911C911D97BCD0BB +:100F1000053610407CF488DB002361F0D0D902E074 +:100F20004AD0002339F016960D911C9117970F3F68 +:100F3000134019F446DB00E010C018960D911D9186 +:100F4000085512402D913C911B97021B130B9CD00E +:100F5000043F1140C4F635DB01E0A991B991089531 +:100F6000FA93EA937A936A935A934A931A930A9359 +:100F70001FB7E7E8F1E004E04081518162817381AD +:100F8000452B462B472B49F0408141505040604053 +:100F90007040408351836283738334960A950023A3 +:100FA00059F71FBF09911991499159916991799107 +:100FB000E991F991189510E0000F111F000F111F12 +:100FC000F801E957FE4F0081118122813381012B05 +:100FD000022B032B11F001E0089500E008958A929E +:100FE0006A925A924A92BA93AA939A938A93402EFB +:100FF000812E642EA90160E070E000E61AEE20E088 +:1010000030E0B8D0C801D901482D50E060E070E070 +:1010100008EE13E020E030E0ADD0080F191F2A1FC2 +:101020003B1F462D50E060E070E0400F511F621FF3 +:10103000731F5524440C551C440C551CF201E957F0 +:10104000FE4F408351836283738389919991A99163 +:10105000B9914990599069908990089500E003BF33 +:10106000089503E003BF08950DE703BB00E002BB52 +:1010700001E005BB03E003BF09B7006109BF789435 +:10108000089500008895FECF11231AF4119501955B +:1010900010409801890108950FEC0DBF00E00EBFCC +:1010A000C0EAD0E080D0002309F08DD066DEE9DF11 +:1010B000E8CFE199FECF08954F5F5F4FFADF4EBB57 +:1010C0005FBBE09A0895FADF0DB308954F5F5F4F5D +:1010D0004EBB5FBBF894E29AE19A0FBE08950FB63B +:1010E000E8DF0DBBF5CF002411240030010741F0EB +:1010F0001695079510F4040E151E440F551FF5CFD5 +:10110000002D112D08954A951AF0000F111FFBCFE5 +:1011100008954A951AF016950795FBCF0895002477 +:101120001124EFE0001F111F001C111C04161506EE +:1011300010F0041A150AEA95AAF7001F111FA00162 +:101140000095109508955195419550400895FF27B9 +:10115000552312F4F160F7DF112312F4F09506D055 +:10116000DEDFF0FD03D0F1FDEECF0895119501957E +:1011700010400895002411241001E02FE12BE22BF0 +:10118000E32B71F0369527951795079520F4040EFB +:10119000151E261E371E440F551F661F771FEDCFE5 +:1011A00080019101089501E0089520E006D0E9F75B +:1011B0000895259102D0E9F708952D93015010402C +:1011C000202F212B089584E490E0FC0105911491D7 +:1011D000FC013296A591B491FC013496259134918D +:1011E000422F432B19F0F901E4DF01C0DEDF069640 +:1011F00010E08035910748F308952E0293023C0FCA +:10120000260204012C010A00E8024B03901AEE02A8 +:1012100068012C010E006503BE031027E803DB0103 +:101220002C01130049048104C05DD007DB01A40137 +:101230002600EA0317B9031986031A51031B1C037E +:101240001BE6021BB1021A7D021A4B02191B02187F +:10125000EE0116C301159C011377011255011136D9 +:0E126000010F1A010E00010DE9000BD4000A67 +:0400000300000000F9 +:00000001FF diff --git a/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_data.hex b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_data.hex new file mode 100644 index 0000000..8f152e0 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_data.hex @@ -0,0 +1,2 @@ +:0400000300000000F9 +:00000001FF diff --git a/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_eeprom.hex b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_eeprom.hex new file mode 100644 index 0000000..09e3e1c --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/Exe/BC100_tiny_eeprom.hex @@ -0,0 +1,12 @@ +:020000020000FC +:1000000001030300000000000000000000000000E9 +:1000100000000000000000000000000000000000E0 +:1000200000000000000000000000000000000000D0 +:1000300000000000000000000000000000000000C0 +:1000400000000000000000000000000000000000B0 +:1000500000000000000000000000000000000000A0 +:100060000000000000000000000000000000000090 +:100070000000000000000000000000000000000080 +:030080000000007D +:0400000300000000F9 +:00000001FF diff --git a/BaseTinyFirmware/IAR/Release/List/ADC.lst b/BaseTinyFirmware/IAR/Release/List/ADC.lst new file mode 100644 index 0000000..c465541 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/ADC.lst @@ -0,0 +1,983 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:35 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\ADC.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\ADC.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\AD # +# C.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC # +# .r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\ADC.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for use of ADC + 6 * + 7 * Contains high level functions for initializing the ADC, interrupt + 8 * handling, and treatment of samples.\n + 9 * The ADC is set to free running mode and uses an external reference + 10 * voltage.\n + 11 * To make all sampling take at least 25 clock cycles the ADC is stopped + 12 * and restarted by the ISR. + 13 * + 14 * \par Application note: + 15 * AVR458: Charging Li-Ion Batteries with BC100 \n + 16 * AVR463: Charging NiMH Batteries with BC100 + 17 * + 18 * \par Documentation: + 19 * For comprehensive code documentation, supported compilers, compiler + 20 * settings and supported devices see readme.html + 21 * + 22 * \author + 23 * Atmel Corporation: http://www.atmel.com \n + 24 * Support email: avr@atmel.com \n + 25 * Original author: \n + 26 * + 27 * $Name$ + 28 * $Revision: 2299 $ + 29 * $RCSfile$ + 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $ + 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 32 ******************************************************************************/ + 33 + 34 #include + + \ In segment ABSOLUTE, at 0x3b + \ volatile __io _A_PORTA + \ _A_PORTA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x3a + \ volatile __io _A_DDRA + \ _A_DDRA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x27 + \ volatile __io _A_ADMUX + \ _A_ADMUX: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x26 + \ volatile __io _A_ADCSRA + \ _A_ADCSRA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x24 + \ volatile __io _A_ADC + \ _A_ADC: + \ 00000000 DS 2 + + \ In segment ABSOLUTE, at 0x23 + \ volatile __io _A_ADCSRB + \ _A_ADCSRB: + \ 00000000 DS 1 + 35 #include + 36 + 37 #include "structs.h" + 38 + 39 #include "main.h" + 40 #include "ADC.h" + 41 + 42 + 43 //****************************************************************************** + 44 // Variables + 45 //****************************************************************************** + 46 // ADC status struct. + 47 //! \brief Holds sampled data and ADC-status + 48 ADC_Status_t ADCS; + 49 + 50 + 51 /*! \brief Indicates maximum battery voltage. + 52 * + 53 * This variable is stored in EEPROM and indicates how much the battery voltage + 54 * is downscaled by HW before it is sampled. The amount of downscaling depends + 55 * on the maximum battery voltage, and is necessary to avoid saturation of the + 56 * ADC (reference voltage is 2.5 V). + 57 * + 58 * \note Used by the ADC ISR when calling ScaleU() and ScaleI(). + 59 * + 60 * \note Defaults to 1, which means 10 V max battery voltage. + 61 * + 62 * \note Table of settings: + 63 *
+     64           * VBAT_RANGE | Max battery voltage | Jumper setting
+     65           *         0  |             5V      |        1/2
+     66           *         1  |            10V      |        1/4
+     67           *         2  |            20V      |        1/8
+     68           *         3  |            30V      |       1/12
+     69           *         4  |            40V      |       1/16
+     70           * 
+ 71 */ + 72 // Maximum battery voltage (affects scaling of samples). + + \ In segment EEPROM_I, align 1, keep-with-next + 73 __eeprom unsigned char VBAT_RANGE = 1; + \ VBAT_RANGE: + \ 00000000 01 DB 1 + 74 + 75 + 76 //****************************************************************************** + 77 // Functions + 78 //****************************************************************************** + 79 /*! \brief Interrupt Service routine for ADC. + 80 * + 81 * This ISR stores the sampled values in the ADC status-struct, then + 82 * updates the ADC MUX to the next channel in the scanning-sequence.\n + 83 * Once the sequence is completed, ADCS.Flag is set and unless + 84 * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC + 85 * is disabled.\n + 86 * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. + 87 * + 88 * \note Table of scanning sequence: + 89 *
+     90           * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed
+     91           * ----+--------+----------+----------+------+---------+-------
+     92           *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no
+     93           *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no
+     94           *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no
+     95           *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no
+     96           *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no
+     97           *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no
+     98           *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no
+     99           *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes
+    100           * 
+ 101 * + 102 * \todo IIN (#7 in sequence) is never used. + 103 * + 104 * \todo Signed is never set. Signed measurements of IBAT will halve the + 105 * measuring sensitivity, and is therefore not favourable. At the moment, + 106 * great currents (f.ex. if something happens with the battery) will be + 107 * interpreted as negative, which might cause unfavourable behaviour during + 108 * charging (depending on what PWM behaviour is defined), f.ex. + 109 * ConstantCurrent() will keep increasing the PWM output. This results in an + 110 * PWM controller error being flagged and the program going into + 111 * error-state and eventually reinitializing. + 112 */ + 113 #pragma vector=ADC_vect + + \ In segment CODE, align 2, keep-with-next + 114 __interrupt void ADC_ISR(void) + \ ADC_ISR: + 115 { + \ 00000000 924A ST -Y, R4 + \ 00000002 93BA ST -Y, R27 + \ 00000004 93AA ST -Y, R26 + \ 00000006 939A ST -Y, R25 + \ 00000008 938A ST -Y, R24 + \ 0000000A 93FA ST -Y, R31 + \ 0000000C 93EA ST -Y, R30 + \ 0000000E 923A ST -Y, R3 + \ 00000010 922A ST -Y, R2 + \ 00000012 921A ST -Y, R1 + \ 00000014 920A ST -Y, R0 + \ 00000016 937A ST -Y, R23 + \ 00000018 936A ST -Y, R22 + \ 0000001A 935A ST -Y, R21 + \ 0000001C 934A ST -Y, R20 + \ 0000001E 933A ST -Y, R19 + \ 00000020 932A ST -Y, R18 + \ 00000022 931A ST -Y, R17 + \ 00000024 930A ST -Y, R16 + \ 00000026 B64F IN R4, 0x3F + \ 00000028 REQUIRE ?Register_R4_is_cg_reg + 116 static unsigned char avgIndex = 0; + 117 unsigned char i, Next, Signed; + 118 signed int temp = 0; + \ 00000028 E080 LDI R24, 0 + \ 0000002A E090 LDI R25, 0 + 119 + 120 Signed = FALSE; // Presume next conversion is unipolar. + 121 ADCSRA &= ~(1<> 8 + \ 00000032 910C LD R16, X + \ 00000034 710F ANDI R16, 0x1F + \ 00000036 950A DEC R16 + \ 00000038 F049 BREQ ??ADC_ISR_0 + \ 0000003A 950A DEC R16 + \ 0000003C F071 BREQ ??ADC_ISR_1 + \ 0000003E 950A DEC R16 + \ 00000040 F099 BREQ ??ADC_ISR_2 + \ 00000042 5002 SUBI R16, 2 + \ 00000044 F111 BREQ ??ADC_ISR_3 + \ 00000046 5102 SUBI R16, 18 + \ 00000048 F181 BREQ ??ADC_ISR_4 + \ 0000004A C07E RJMP ??ADC_ISR_5 + 127 // MUX = 0b000001 => ADC1 (PA1) = NTC + 128 case 0x01: + 129 ADCS.rawNTC = ADC; + \ ??ADC_ISR_0: + \ 0000004C B104 IN R16, 0x04 + \ 0000004E B115 IN R17, 0x05 + \ 00000050 01FD MOVW R31:R30, R27:R26 + \ 00000052 8304 STD Z+4, R16 + \ 00000054 8315 STD Z+5, R17 + 130 Next=0x02; + \ 00000056 E002 LDI R16, 2 + \ 00000058 C078 RJMP ??ADC_ISR_6 + 131 break; + 132 + 133 + 134 // MUX = 0b000010 => ADC2 (PA2) = RID + 135 case 0x02: + 136 ADCS.rawRID = ADC; + \ ??ADC_ISR_1: + \ 0000005A B104 IN R16, 0x04 + \ 0000005C B115 IN R17, 0x05 + \ 0000005E 01FD MOVW R31:R30, R27:R26 + \ 00000060 8302 STD Z+2, R16 + \ 00000062 8313 STD Z+3, R17 + 137 Next=0x03; + \ 00000064 E003 LDI R16, 3 + \ 00000066 C071 RJMP ??ADC_ISR_6 + 138 break; + 139 + 140 + 141 // MUX = 0b000011 => ADC3 (PA4) = VIN- + 142 case 0x03: + 143 // Supply voltage is always divided by 16. + 144 ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short. + \ ??ADC_ISR_2: + \ 00000068 B124 IN R18, 0x04 + \ 0000006A B135 IN R19, 0x05 + \ 0000006C E004 LDI R16, 4 + \ 0000006E .... RCALL ScaleU + \ 00000070 01FD MOVW R31:R30, R27:R26 + \ 00000072 8700 STD Z+8, R16 + \ 00000074 8711 STD Z+9, R17 + 145 + 146 // Is mains failing? + 147 if (ADCS.VIN < VIN_MIN) { + \ 00000076 3300 CPI R16, 48 + \ 00000078 4111 SBCI R17, 17 + \ 0000007A 910C LD R16, X + \ 0000007C F410 BRCC ??ADC_ISR_7 + 148 ADCS.Mains = FALSE; + \ 0000007E 7B0F ANDI R16, 0xBF + \ 00000080 C001 RJMP ??ADC_ISR_8 + 149 } else { + 150 ADCS.Mains = TRUE; + \ ??ADC_ISR_7: + \ 00000082 6400 ORI R16, 0x40 + \ ??ADC_ISR_8: + \ 00000084 930C ST X, R16 + 151 } + 152 + 153 Next=0x05; + \ 00000086 E005 LDI R16, 5 + \ 00000088 C060 RJMP ??ADC_ISR_6 + 154 break; + 155 + 156 + 157 // MUX = 0b000101 => ADC5 (PA6) = VBAT- + 158 case 0x05: + 159 ADCS.rawVBAT = ADC; + \ ??ADC_ISR_3: + \ 0000008A B104 IN R16, 0x04 + \ 0000008C B115 IN R17, 0x05 + \ 0000008E 01FD MOVW R31:R30, R27:R26 + \ 00000090 8306 STD Z+6, R16 + \ 00000092 8317 STD Z+7, R17 + 160 + 161 // Scale voltage according to jumper setting. + 162 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short. + \ 00000094 B124 IN R18, 0x04 + \ 00000096 B135 IN R19, 0x05 + \ 00000098 .... LDI R20, LOW(VBAT_RANGE) + \ 0000009A .... LDI R21, (VBAT_RANGE) >> 8 + \ 0000009C .... RCALL __eeget8_16 + \ 0000009E .... RCALL ScaleU + \ 000000A0 01FD MOVW R31:R30, R27:R26 + \ 000000A2 8702 STD Z+10, R16 + \ 000000A4 8713 STD Z+11, R17 + 163 Next=0x17; + \ 000000A6 E107 LDI R16, 23 + \ 000000A8 C050 RJMP ??ADC_ISR_6 + 164 // Signed = TRUE; // Next conversion is bipolar. Halves sensitivity! + 165 break; + 166 + 167 + 168 case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT + 169 // If bipolar, from -512 to 0, to 511: + 170 // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF + 171 + 172 // Scale sample according to jumper setting, handle negative numbers. + 173 if (ADC > 511) { + \ ??ADC_ISR_4: + \ 000000AA B104 IN R16, 0x04 + \ 000000AC B115 IN R17, 0x05 + \ 000000AE 3012 CPI R17, 2 + \ 000000B0 F0C0 BRCS ??ADC_ISR_9 + 174 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE, + 175 (1024 - (ADC-ADCS.ADC5_G20_OS))); + \ 000000B2 E000 LDI R16, 0 + \ 000000B4 E014 LDI R17, 4 + \ 000000B6 B124 IN R18, 0x04 + \ 000000B8 B135 IN R19, 0x05 + \ 000000BA 1B02 SUB R16, R18 + \ 000000BC 0B13 SBC R17, R19 + \ 000000BE 01FD MOVW R31:R30, R27:R26 + \ 000000C0 8121 LDD R18, Z+1 + \ 000000C2 9522 SWAP R18 + \ 000000C4 702F ANDI R18, 0x0F + \ 000000C6 E030 LDI R19, 0 + \ 000000C8 0F20 ADD R18, R16 + \ 000000CA 1F31 ADC R19, R17 + \ 000000CC .... LDI R20, LOW(VBAT_RANGE) + \ 000000CE .... LDI R21, (VBAT_RANGE) >> 8 + \ 000000D0 .... RCALL __eeget8_16 + \ 000000D2 .... RCALL ScaleI + \ 000000D4 9511 NEG R17 + \ 000000D6 9501 NEG R16 + \ 000000D8 4010 SBCI R17, 0 + \ ??ADC_ISR_10: + \ 000000DA 01FD MOVW R31:R30, R27:R26 + \ 000000DC 8704 STD Z+12, R16 + \ 000000DE 8715 STD Z+13, R17 + \ 000000E0 C014 RJMP ??ADC_ISR_11 + 176 } else if (ADC > 0) { + \ ??ADC_ISR_9: + \ 000000E2 B104 IN R16, 0x04 + \ 000000E4 B115 IN R17, 0x05 + \ 000000E6 2B01 OR R16, R17 + \ 000000E8 F069 BREQ ??ADC_ISR_12 + 177 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS)); + \ 000000EA B124 IN R18, 0x04 + \ 000000EC B135 IN R19, 0x05 + \ 000000EE 01FD MOVW R31:R30, R27:R26 + \ 000000F0 8101 LDD R16, Z+1 + \ 000000F2 9502 SWAP R16 + \ 000000F4 700F ANDI R16, 0x0F + \ 000000F6 1B20 SUB R18, R16 + \ 000000F8 4030 SBCI R19, 0 + \ 000000FA .... LDI R20, LOW(VBAT_RANGE) + \ 000000FC .... LDI R21, (VBAT_RANGE) >> 8 + \ 000000FE .... RCALL __eeget8_16 + \ 00000100 .... RCALL ScaleI + \ 00000102 CFEB RJMP ??ADC_ISR_10 + 178 } else { + 179 ADCS.IBAT = 0; + \ ??ADC_ISR_12: + \ 00000104 01FD MOVW R31:R30, R27:R26 + \ 00000106 8784 STD Z+12, R24 + \ 00000108 8785 STD Z+13, R24 + 180 } + 181 + 182 // Insert sample of battery current into the averaging-array + 183 // (overwriting the oldest sample), then recalculate and store the + 184 // average. This is the last conversion in the sequence, so + 185 // flag a complete ADC-cycle and restart sequence. + 186 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT; + \ ??ADC_ISR_11: + \ 0000010A 8524 LDD R18, Z+12 + \ 0000010C 8535 LDD R19, Z+13 + \ 0000010E 8D00 LDD R16, Z+24 + \ 00000110 7003 ANDI R16, 0x03 + \ 00000112 0F00 LSL R16 + \ 00000114 0FE0 ADD R30, R16 + \ 00000116 1FF8 ADC R31, R24 + \ 00000118 8726 STD Z+14, R18 + \ 0000011A 8737 STD Z+15, R19 + \ 0000011C 01FD MOVW R31:R30, R27:R26 + \ 0000011E 8D00 LDD R16, Z+24 + \ 00000120 9503 INC R16 + \ 00000122 8F00 STD Z+24, R16 + 187 for (i = 0; i < 4 ; i++) { + \ 00000124 963E ADIW R31:R30, 14 + \ 00000126 E004 LDI R16, 4 + 188 temp += ADCS.discIBAT[i]; + \ ??ADC_ISR_13: + \ 00000128 9121 LD R18, Z+ + \ 0000012A 9131 LD R19, Z+ + \ 0000012C 0F82 ADD R24, R18 + \ 0000012E 1F93 ADC R25, R19 + 189 } + \ 00000130 950A DEC R16 + \ 00000132 F7D1 BRNE ??ADC_ISR_13 + 190 + 191 ADCS.avgIBAT = (temp / 4); + \ 00000134 018C MOVW R17:R16, R25:R24 + \ 00000136 E044 LDI R20, 4 + \ 00000138 E050 LDI R21, 0 + \ 0000013A .... RCALL ?SS_DIVMOD_L02 + \ 0000013C 01FD MOVW R31:R30, R27:R26 + \ 0000013E 8B06 STD Z+22, R16 + \ 00000140 8B17 STD Z+23, R17 + 192 + 193 ADCS.Flag = TRUE; + \ 00000142 910C LD R16, X + \ 00000144 6200 ORI R16, 0x20 + \ 00000146 930C ST X, R16 + 194 Next=0x01; + 195 Signed = FALSE; // This is the only bipolar conversion. + 196 break; + 197 + 198 + 199 default: // Should not happen. (Invalid MUX-channel) + 200 Next=0x01; // Start at the beginning of sequence. + \ ??ADC_ISR_5: + \ 00000148 E001 LDI R16, 1 + 201 break; + 202 } + 203 + 204 // Update MUX to next channel in sequence, set a bipolar conversion if + 205 // this has been flagged. + 206 ADCS.MUX = Next; + \ ??ADC_ISR_6: + \ 0000014A 911C LD R17, X + \ 0000014C 7E10 ANDI R17, 0xE0 + \ 0000014E 710F ANDI R16, 0x1F + \ 00000150 2B01 OR R16, R17 + \ 00000152 930C ST X, R16 + 207 ADMUX = (1<` + \ ADCS: + \ 00000000 DS 24 + \ 00000018 DS 1 + 221 + 222 + 223 /*! \brief Scales sample to represent "actual voltage" in mV. + 224 * + 225 * This function returns the actual sampled voltage, scaled according + 226 * to the jumper settings. + 227 * + 228 * \param setting Indicates what downscaling was used. + 229 * \param data The sampled value. + 230 * + 231 * \note Table for setting-parameter:\n + 232 *
+    233           * Presume VREF = 2.5V and Gain = 1x.
+    234           * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB
+    235           * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)
+    236           * --------+--------+------+------------+-----------+-------
+    237           *     N/A |        |    - |       -    |   2.441mV |  2.50V
+    238           *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V
+    239           *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V
+    240           *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V
+    241           *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V
+    242           *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V
+    243           *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V
+    244           * 
+ 245 */ + + \ In segment CODE, align 2, keep-with-next + 246 unsigned int ScaleU(unsigned char setting, unsigned int data) + \ ScaleU: + 247 { + \ 00000000 2E2A MOV R2, R26 + \ 00000002 01BC MOVW R23:R22, R25:R24 + \ 00000004 2FA0 MOV R26, R16 + \ 00000006 01C9 MOVW R25:R24, R19:R18 + 248 // Temporary variable needed. + 249 unsigned int scaled = 0; + 250 + 251 // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16 + 252 if (setting == 3) { + \ 00000008 3003 CPI R16, 3 + \ 0000000A 01A9 MOVW R21:R20, R19:R18 + \ 0000000C F4A1 BRNE ??ScaleU_0 + 253 scaled = 29 * data; + 254 scaled += (data >> 2); + 255 scaled += (data >> 4); + \ 0000000E E10D LDI R16, 29 + \ 00000010 E010 LDI R17, 0 + \ 00000012 .... RCALL ?S_MUL_L02 + \ 00000014 9536 LSR R19 + \ 00000016 9527 ROR R18 + \ 00000018 9536 LSR R19 + \ 0000001A 9527 ROR R18 + \ 0000001C 0D20 ADD R18, R0 + \ 0000001E 1D31 ADC R19, R1 + \ 00000020 9596 LSR R25 + \ 00000022 9587 ROR R24 + \ 00000024 9596 LSR R25 + \ 00000026 9587 ROR R24 + \ 00000028 9596 LSR R25 + \ 0000002A 9587 ROR R24 + \ 0000002C 9596 LSR R25 + \ 0000002E 9587 ROR R24 + \ 00000030 0F82 ADD R24, R18 + \ 00000032 1F93 ADC R25, R19 + \ 00000034 C014 RJMP ??ScaleU_1 + 256 } else { + 257 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16 + 258 scaled = 39 * data; + 259 scaled += (data >> 4); + \ ??ScaleU_0: + \ 00000036 E207 LDI R16, 39 + \ 00000038 E010 LDI R17, 0 + \ 0000003A .... RCALL ?S_MUL_L02 + \ 0000003C 9596 LSR R25 + \ 0000003E 9587 ROR R24 + \ 00000040 9596 LSR R25 + \ 00000042 9587 ROR R24 + \ 00000044 9596 LSR R25 + \ 00000046 9587 ROR R24 + \ 00000048 9596 LSR R25 + \ 0000004A 9587 ROR R24 + \ 0000004C 0D80 ADD R24, R0 + \ 0000004E 1D91 ADC R25, R1 + 260 + 261 if (setting <3) { + \ 00000050 30A3 CPI R26, 3 + \ 00000052 F428 BRCC ??ScaleU_1 + 262 // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8 + 263 // 1: mV/LSB = 9.766 = 39.06 / 4 + 264 // 2: mV/LSB = 19.53 = 39.06 / 2 + 265 scaled = (scaled >> (3-setting)); + \ 00000054 018C MOVW R17:R16, R25:R24 + \ 00000056 E043 LDI R20, 3 + \ 00000058 1B4A SUB R20, R26 + \ 0000005A .... RCALL ?US_SHR_L02 + \ 0000005C 01C8 MOVW R25:R24, R17:R16 + 266 } + 267 } + 268 + 269 return(scaled); + \ ??ScaleU_1: + \ 0000005E 018C MOVW R17:R16, R25:R24 + \ 00000060 01CB MOVW R25:R24, R23:R22 + \ 00000062 2DA2 MOV R26, R2 + \ 00000064 9508 RET + 270 } + 271 + 272 + 273 /*! \brief Scales sample to represent "actual current" in mA. + 274 * + 275 * This function returns the actual sampled current, scaled according + 276 * to the jumper settings. + 277 * + 278 * \param setting Indicates what downscaling was used. + 279 * \param data The sampled value. + 280 * + 281 * \note Table for setting-parameter:\n + 282 *
+    283           * Presume VREF = 2.5V and Gain = 1x or 20x.
+    284           * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
+    285           * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
+    286           * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain
+    287           * --------+------+------------+----------+----------+--------+-----
+    288           *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x
+    289           *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x
+    290           *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x
+    291           *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x
+    292           *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x
+    293           *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x
+    294           *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x
+    295           * 
+ 296 */ + + \ In segment CODE, align 2, keep-with-next + 297 unsigned int ScaleI(unsigned char setting, unsigned int data) + \ ScaleI: + 298 { + \ 00000000 2E2A MOV R2, R26 + \ 00000002 01BC MOVW R23:R22, R25:R24 + \ 00000004 2FA0 MOV R26, R16 + \ 00000006 01C9 MOVW R25:R24, R19:R18 + 299 // Temporary variable needed. + 300 unsigned int scaled = 0; + 301 + 302 // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128 + 303 if (setting == 3) { + \ 00000008 3003 CPI R16, 3 + \ 0000000A 01A9 MOVW R21:R20, R19:R18 + \ 0000000C F4A9 BRNE ??ScaleI_0 + 304 scaled = 21 * data; + 305 scaled -= (data >> 4); + 306 scaled += (data >> 7); + \ 0000000E E105 LDI R16, 21 + \ 00000010 E010 LDI R17, 0 + \ 00000012 .... RCALL ?S_MUL_L02 + \ 00000014 9536 LSR R19 + \ 00000016 9527 ROR R18 + \ 00000018 9536 LSR R19 + \ 0000001A 9527 ROR R18 + \ 0000001C 9536 LSR R19 + \ 0000001E 9527 ROR R18 + \ 00000020 9536 LSR R19 + \ 00000022 9527 ROR R18 + \ 00000024 1B02 SUB R16, R18 + \ 00000026 0B13 SBC R17, R19 + \ 00000028 0F88 LSL R24 + \ 0000002A 2F89 MOV R24, R25 + \ 0000002C 1F88 ROL R24 + \ 0000002E E090 LDI R25, 0 + \ 00000030 1F99 ROL R25 + \ 00000032 0F80 ADD R24, R16 + \ 00000034 1F91 ADC R25, R17 + \ 00000036 C01A RJMP ??ScaleI_1 + 307 } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32 + 308 scaled = 28 * data; + 309 scaled -= (data >> 3); + 310 scaled += (data >> 5); + \ ??ScaleI_0: + \ 00000038 E10C LDI R16, 28 + \ 0000003A E010 LDI R17, 0 + \ 0000003C .... RCALL ?S_MUL_L02 + \ 0000003E 0198 MOVW R19:R18, R17:R16 + \ 00000040 018C MOVW R17:R16, R25:R24 + \ 00000042 9516 LSR R17 + \ 00000044 9507 ROR R16 + \ 00000046 9516 LSR R17 + \ 00000048 9507 ROR R16 + \ 0000004A 9516 LSR R17 + \ 0000004C 9507 ROR R16 + \ 0000004E 1B20 SUB R18, R16 + \ 00000050 0B31 SBC R19, R17 + \ 00000052 018C MOVW R17:R16, R25:R24 + \ 00000054 E045 LDI R20, 5 + \ 00000056 .... RCALL ?US_SHR_L02 + \ 00000058 01C8 MOVW R25:R24, R17:R16 + \ 0000005A 0F82 ADD R24, R18 + \ 0000005C 1F93 ADC R25, R19 + 311 + 312 if (setting <3) { + \ 0000005E 30A3 CPI R26, 3 + \ 00000060 F428 BRCC ??ScaleI_1 + 313 // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8 + 314 // 1: mA/LSB = 6.978mA = 27.909 / 4 + 315 // 2: mA/LSB = 13.955mA = 27.909 / 2 + 316 scaled = (scaled >> (3-setting)); + \ 00000062 018C MOVW R17:R16, R25:R24 + \ 00000064 E043 LDI R20, 3 + \ 00000066 1B4A SUB R20, R26 + \ 00000068 .... RCALL ?US_SHR_L02 + \ 0000006A 01C8 MOVW R25:R24, R17:R16 + 317 } + 318 } + 319 + 320 return(scaled); + \ ??ScaleI_1: + \ 0000006C 018C MOVW R17:R16, R25:R24 + \ 0000006E 01CB MOVW R25:R24, R23:R22 + \ 00000070 2DA2 MOV R26, R2 + \ 00000072 9508 RET + 321 } + 322 + 323 + 324 /*! \brief Waits for two full cycles of ADC-conversions to occur. + 325 * + 326 * This function clears the cycle complete-flag, then waits for it to be set + 327 * again. This is then repeated once before the function exits. + 328 * + 329 */ + + \ In segment CODE, align 2, keep-with-next + 330 void ADC_Wait(void) + \ ADC_Wait: + \ ??ADC_Wait_0: + 331 { + 332 // Clear ADC flag and wait for cycle to complete. + 333 ADCS.Flag = FALSE; + 334 do { + 335 } while (ADCS.Flag == FALSE); + \ 00000000 CFFF RJMP ??ADC_Wait_0 + 336 + 337 // Repeat, so we are sure the data beong to the same cycle. + 338 ADCS.Flag = FALSE; + 339 do { + 340 } while (ADCS.Flag == FALSE); + 341 } + 342 + 343 + 344 /*! \brief Initializes ADC and input pins. + 345 * + 346 * This function initializes the ADC to free running mode, sampling from + 347 * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n + 348 * It also measures and stores calibration data for offset. + 349 * + 350 * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway. + 351 * + 352 * \note Table of MUX settings for offset measurement: + 353 *
+    354           *    Ch | Pin |    Gain |    MUX
+    355           * ------+-----+---------+-------
+    356           *  ADC1 | PA1 |     20x | 001101
+    357           *  ADC3 | PA4 |     20x | 010001
+    358           *  ADC5 | PA6 |     20x | 010110
+    359           *  ADC9 | PB6 |     20x | 011011
+    360           *  ADC0 | PA0 | 20x/32x | 111000
+    361           *  ADC0 | PA0 |   1x/8x | 111001
+    362           *  ADC1 | PA1 | 20x/32x | 111010
+    363           *  ADC2 | PA2 | 20x/32x | 111011
+    364           *  ADC4 | PA5 | 20x/32x | 111100
+    365           *  ADC5 | PA6 | 20x/32x | 111101
+    366           *  ADC6 | PA7 | 20x/32x | 111110
+    367           * 
+ 368 */ + + \ In segment CODE, align 2, keep-with-next + 369 void ADC_Init(void) + \ ADC_Init: + 370 { + 371 unsigned char i; + 372 + 373 __disable_interrupt(); + \ 00000000 94F8 CLI + 374 + 375 ADCS.Halt = FALSE; // Enable consecutive runs of ADC. + \ 00000002 .... LDI R30, LOW(ADCS) + \ 00000004 .... LDI R31, (ADCS) >> 8 + \ 00000006 8100 LD R16, Z + \ 00000008 770F ANDI R16, 0x7F + \ 0000000A 8300 ST Z, R16 + 376 + 377 // Configure ADC pins (inputs and disabled pull-ups). + 378 DDRA &= ~((1< ScaleU 19 2 + -> ScaleU 19 2 + -> ScaleI 19 2 + -> ScaleI 19 2 + ADC_Init 0 2 + ADC_Wait 0 2 + ScaleI 3 4 + ScaleU 3 4 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_PORTA 1 + _A_DDRA 1 + _A_ADMUX 1 + _A_ADCSRA 1 + _A_ADC 2 + _A_ADCSRB 1 + VBAT_RANGE 1 + ADC_ISR 404 + ADCS 25 + ScaleU 102 + ScaleI 116 + ??ADC_Wait_0 2 + ADC_Init 122 + ??ADC_ISR??INTVEC 22 2 + Others 6 + + + 7 bytes in segment ABSOLUTE + 746 bytes in segment CODE + 1 byte in segment EEPROM_I + 6 bytes in segment INITTAB + 2 bytes in segment INTVEC + 25 bytes in segment NEAR_Z + + 746 bytes of CODE memory (+ 8 bytes shared) + 25 bytes of DATA memory (+ 7 bytes shared) + 1 byte of XDATA memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/ADC.s90 b/BaseTinyFirmware/IAR/Release/List/ADC.s90 new file mode 100644 index 0000000..d5b2c6b --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/ADC.s90 @@ -0,0 +1,1002 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:35 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\ADC.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\ADC.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\A / +// DC.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME `ADC` + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?Register_R4_is_cg_reg + EXTERN ?SS_DIVMOD_L02 + EXTERN ?S_MUL_L02 + EXTERN ?US_SHR_L02 + EXTERN ?need_segment_init + EXTERN __eeget8_16 + + PUBWEAK `?` + PUBWEAK `??ADC_ISR??INTVEC 22` + PUBLIC ADCS + PUBLIC ADC_ISR + PUBLIC ADC_Init + PUBLIC ADC_Wait + PUBLIC ScaleI + PUBLIC ScaleU + PUBLIC VBAT_RANGE + PUBWEAK _A_ADC + PUBWEAK _A_ADCSRA + PUBWEAK _A_ADCSRB + PUBWEAK _A_ADMUX + PUBWEAK _A_DDRA + PUBWEAK _A_PORTA + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + +ADC_ISR SYMBOL "ADC_ISR" +`??ADC_ISR??INTVEC 22` SYMBOL "??INTVEC 22", ADC_ISR + +// C:\home\kevin\pub\src\bc100\IAR\ADC.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for use of ADC +// 6 * +// 7 * Contains high level functions for initializing the ADC, interrupt +// 8 * handling, and treatment of samples.\n +// 9 * The ADC is set to free running mode and uses an external reference +// 10 * voltage.\n +// 11 * To make all sampling take at least 25 clock cycles the ADC is stopped +// 12 * and restarted by the ISR. +// 13 * +// 14 * \par Application note: +// 15 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 16 * AVR463: Charging NiMH Batteries with BC100 +// 17 * +// 18 * \par Documentation: +// 19 * For comprehensive code documentation, supported compilers, compiler +// 20 * settings and supported devices see readme.html +// 21 * +// 22 * \author +// 23 * Atmel Corporation: http://www.atmel.com \n +// 24 * Support email: avr@atmel.com \n +// 25 * Original author: \n +// 26 * +// 27 * $Name$ +// 28 * $Revision: 2299 $ +// 29 * $RCSfile$ +// 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/ADC.c $ +// 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 32 ******************************************************************************/ +// 33 +// 34 #include + + ASEGN ABSOLUTE:DATA:NOROOT,03bH +// volatile __io _A_PORTA +_A_PORTA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,03aH +// volatile __io _A_DDRA +_A_DDRA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,027H +// volatile __io _A_ADMUX +_A_ADMUX: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,026H +// volatile __io _A_ADCSRA +_A_ADCSRA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,024H +// volatile __io _A_ADC +_A_ADC: + DS 2 + + ASEGN ABSOLUTE:DATA:NOROOT,023H +// volatile __io _A_ADCSRB +_A_ADCSRB: + DS 1 +// 35 #include +// 36 +// 37 #include "structs.h" +// 38 +// 39 #include "main.h" +// 40 #include "ADC.h" +// 41 +// 42 +// 43 //****************************************************************************** +// 44 // Variables +// 45 //****************************************************************************** +// 46 // ADC status struct. +// 47 //! \brief Holds sampled data and ADC-status +// 48 ADC_Status_t ADCS; +// 49 +// 50 +// 51 /*! \brief Indicates maximum battery voltage. +// 52 * +// 53 * This variable is stored in EEPROM and indicates how much the battery voltage +// 54 * is downscaled by HW before it is sampled. The amount of downscaling depends +// 55 * on the maximum battery voltage, and is necessary to avoid saturation of the +// 56 * ADC (reference voltage is 2.5 V). +// 57 * +// 58 * \note Used by the ADC ISR when calling ScaleU() and ScaleI(). +// 59 * +// 60 * \note Defaults to 1, which means 10 V max battery voltage. +// 61 * +// 62 * \note Table of settings: +// 63 *
+//   64  * VBAT_RANGE | Max battery voltage | Jumper setting
+//   65  *         0  |             5V      |        1/2
+//   66  *         1  |            10V      |        1/4
+//   67  *         2  |            20V      |        1/8
+//   68  *         3  |            30V      |       1/12
+//   69  *         4  |            40V      |       1/16
+//   70  * 
+// 71 */ +// 72 // Maximum battery voltage (affects scaling of samples). + + RSEG EEPROM_I:XDATA:NOROOT(0) +// 73 __eeprom unsigned char VBAT_RANGE = 1; +VBAT_RANGE: + DB 1 +// 74 +// 75 +// 76 //****************************************************************************** +// 77 // Functions +// 78 //****************************************************************************** +// 79 /*! \brief Interrupt Service routine for ADC. +// 80 * +// 81 * This ISR stores the sampled values in the ADC status-struct, then +// 82 * updates the ADC MUX to the next channel in the scanning-sequence.\n +// 83 * Once the sequence is completed, ADCS.Flag is set and unless +// 84 * ADCS.Halt has been set, the sequence starts over. Otherwise, the ADC +// 85 * is disabled.\n +// 86 * If the mains voltage is below minimum, ADCS.Mains gets set to FALSE. +// 87 * +// 88 * \note Table of scanning sequence: +// 89 *
+//   90  * Seq |    MUX |  pos I/P |  neg I/P | gain | measure | signed
+//   91  * ----+--------+----------+----------+------+---------+-------
+//   92  *  01 | 000001 | ADC1/PA1 |      n/a |   1x |     NTC |     no
+//   93  *  02 | 000010 | ADC2/PA2 |      n/a |   1x |     RID |     no
+//   94  *  03 | 000011 | ADC3/PA4 |      n/a |   1x |    VIN- |     no
+//   95  *  04 | 000100 | ADC4/PA5 |      n/a |   1x |    VIN+ |     no
+//   96  *  05 | 000101 | ADC5/PA6 |      n/a |   1x |   VBAT- |     no
+//   97  *  06 | 000110 | ADC6/PA7 |      n/a |   1x |   VBAT+ |     no
+//   98  *  07 | 010010 | ADC4/PA5 | ADC3/PA4 |  20x |     IIN |     no
+//   99  *  08 | 010111 | ADC6/PA7 | ADC5/PA6 |  20x |    IBAT |    yes
+//  100  * 
+// 101 * +// 102 * \todo IIN (#7 in sequence) is never used. +// 103 * +// 104 * \todo Signed is never set. Signed measurements of IBAT will halve the +// 105 * measuring sensitivity, and is therefore not favourable. At the moment, +// 106 * great currents (f.ex. if something happens with the battery) will be +// 107 * interpreted as negative, which might cause unfavourable behaviour during +// 108 * charging (depending on what PWM behaviour is defined), f.ex. +// 109 * ConstantCurrent() will keep increasing the PWM output. This results in an +// 110 * PWM controller error being flagged and the program going into +// 111 * error-state and eventually reinitializing. +// 112 */ +// 113 #pragma vector=ADC_vect + + RSEG CODE:CODE:NOROOT(1) +// 114 __interrupt void ADC_ISR(void) +ADC_ISR: +// 115 { + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + ST -Y, R31 + ST -Y, R30 + ST -Y, R3 + ST -Y, R2 + ST -Y, R1 + ST -Y, R0 + ST -Y, R23 + ST -Y, R22 + ST -Y, R21 + ST -Y, R20 + ST -Y, R19 + ST -Y, R18 + ST -Y, R17 + ST -Y, R16 + IN R4, 0x3F + REQUIRE ?Register_R4_is_cg_reg +// 116 static unsigned char avgIndex = 0; +// 117 unsigned char i, Next, Signed; +// 118 signed int temp = 0; + LDI R24, 0 + LDI R25, 0 +// 119 +// 120 Signed = FALSE; // Presume next conversion is unipolar. +// 121 ADCSRA &= ~(1<> 8 + LD R16, X + ANDI R16, 0x1F + DEC R16 + BREQ ??ADC_ISR_0 + DEC R16 + BREQ ??ADC_ISR_1 + DEC R16 + BREQ ??ADC_ISR_2 + SUBI R16, 2 + BREQ ??ADC_ISR_3 + SUBI R16, 18 + BREQ ??ADC_ISR_4 + RJMP ??ADC_ISR_5 +// 127 // MUX = 0b000001 => ADC1 (PA1) = NTC +// 128 case 0x01: +// 129 ADCS.rawNTC = ADC; +??ADC_ISR_0: + IN R16, 0x04 + IN R17, 0x05 + MOVW R31:R30, R27:R26 + STD Z+4, R16 + STD Z+5, R17 +// 130 Next=0x02; + LDI R16, 2 + RJMP ??ADC_ISR_6 +// 131 break; +// 132 +// 133 +// 134 // MUX = 0b000010 => ADC2 (PA2) = RID +// 135 case 0x02: +// 136 ADCS.rawRID = ADC; +??ADC_ISR_1: + IN R16, 0x04 + IN R17, 0x05 + MOVW R31:R30, R27:R26 + STD Z+2, R16 + STD Z+3, R17 +// 137 Next=0x03; + LDI R16, 3 + RJMP ??ADC_ISR_6 +// 138 break; +// 139 +// 140 +// 141 // MUX = 0b000011 => ADC3 (PA4) = VIN- +// 142 case 0x03: +// 143 // Supply voltage is always divided by 16. +// 144 ADCS.VIN = ScaleU(4, (unsigned int)ADC); // Cast because ADC is short. +??ADC_ISR_2: + IN R18, 0x04 + IN R19, 0x05 + LDI R16, 4 + RCALL ScaleU + MOVW R31:R30, R27:R26 + STD Z+8, R16 + STD Z+9, R17 +// 145 +// 146 // Is mains failing? +// 147 if (ADCS.VIN < VIN_MIN) { + CPI R16, 48 + SBCI R17, 17 + LD R16, X + BRCC ??ADC_ISR_7 +// 148 ADCS.Mains = FALSE; + ANDI R16, 0xBF + RJMP ??ADC_ISR_8 +// 149 } else { +// 150 ADCS.Mains = TRUE; +??ADC_ISR_7: + ORI R16, 0x40 +??ADC_ISR_8: + ST X, R16 +// 151 } +// 152 +// 153 Next=0x05; + LDI R16, 5 + RJMP ??ADC_ISR_6 +// 154 break; +// 155 +// 156 +// 157 // MUX = 0b000101 => ADC5 (PA6) = VBAT- +// 158 case 0x05: +// 159 ADCS.rawVBAT = ADC; +??ADC_ISR_3: + IN R16, 0x04 + IN R17, 0x05 + MOVW R31:R30, R27:R26 + STD Z+6, R16 + STD Z+7, R17 +// 160 +// 161 // Scale voltage according to jumper setting. +// 162 ADCS.VBAT = ScaleU(VBAT_RANGE, (unsigned int)ADC); // ADC is a short. + IN R18, 0x04 + IN R19, 0x05 + LDI R20, LOW(VBAT_RANGE) + LDI R21, (VBAT_RANGE) >> 8 + RCALL __eeget8_16 + RCALL ScaleU + MOVW R31:R30, R27:R26 + STD Z+10, R16 + STD Z+11, R17 +// 163 Next=0x17; + LDI R16, 23 + RJMP ??ADC_ISR_6 +// 164 // Signed = TRUE; // Next conversion is bipolar. Halves sensitivity! +// 165 break; +// 166 +// 167 +// 168 case 0x17: // MUX = 0b010111 => 20 x [ADC6(PA7) - ADC5(PA6)] = IBAT +// 169 // If bipolar, from -512 to 0, to 511: +// 170 // 0x200 ... 0x3ff, 0x000, 0x001 ... 0x1FF +// 171 +// 172 // Scale sample according to jumper setting, handle negative numbers. +// 173 if (ADC > 511) { +??ADC_ISR_4: + IN R16, 0x04 + IN R17, 0x05 + CPI R17, 2 + BRCS ??ADC_ISR_9 +// 174 ADCS.IBAT = -(signed int)ScaleI(VBAT_RANGE, +// 175 (1024 - (ADC-ADCS.ADC5_G20_OS))); + LDI R16, 0 + LDI R17, 4 + IN R18, 0x04 + IN R19, 0x05 + SUB R16, R18 + SBC R17, R19 + MOVW R31:R30, R27:R26 + LDD R18, Z+1 + SWAP R18 + ANDI R18, 0x0F + LDI R19, 0 + ADD R18, R16 + ADC R19, R17 + LDI R20, LOW(VBAT_RANGE) + LDI R21, (VBAT_RANGE) >> 8 + RCALL __eeget8_16 + RCALL ScaleI + NEG R17 + NEG R16 + SBCI R17, 0 +??ADC_ISR_10: + MOVW R31:R30, R27:R26 + STD Z+12, R16 + STD Z+13, R17 + RJMP ??ADC_ISR_11 +// 176 } else if (ADC > 0) { +??ADC_ISR_9: + IN R16, 0x04 + IN R17, 0x05 + OR R16, R17 + BREQ ??ADC_ISR_12 +// 177 ADCS.IBAT = ScaleI(VBAT_RANGE, (ADC-ADCS.ADC5_G20_OS)); + IN R18, 0x04 + IN R19, 0x05 + MOVW R31:R30, R27:R26 + LDD R16, Z+1 + SWAP R16 + ANDI R16, 0x0F + SUB R18, R16 + SBCI R19, 0 + LDI R20, LOW(VBAT_RANGE) + LDI R21, (VBAT_RANGE) >> 8 + RCALL __eeget8_16 + RCALL ScaleI + RJMP ??ADC_ISR_10 +// 178 } else { +// 179 ADCS.IBAT = 0; +??ADC_ISR_12: + MOVW R31:R30, R27:R26 + STD Z+12, R24 + STD Z+13, R24 +// 180 } +// 181 +// 182 // Insert sample of battery current into the averaging-array +// 183 // (overwriting the oldest sample), then recalculate and store the +// 184 // average. This is the last conversion in the sequence, so +// 185 // flag a complete ADC-cycle and restart sequence. +// 186 ADCS.discIBAT[(avgIndex++ & 0x03)] = ADCS.IBAT; +??ADC_ISR_11: + LDD R18, Z+12 + LDD R19, Z+13 + LDD R16, Z+24 + ANDI R16, 0x03 + LSL R16 + ADD R30, R16 + ADC R31, R24 + STD Z+14, R18 + STD Z+15, R19 + MOVW R31:R30, R27:R26 + LDD R16, Z+24 + INC R16 + STD Z+24, R16 +// 187 for (i = 0; i < 4 ; i++) { + ADIW R31:R30, 14 + LDI R16, 4 +// 188 temp += ADCS.discIBAT[i]; +??ADC_ISR_13: + LD R18, Z+ + LD R19, Z+ + ADD R24, R18 + ADC R25, R19 +// 189 } + DEC R16 + BRNE ??ADC_ISR_13 +// 190 +// 191 ADCS.avgIBAT = (temp / 4); + MOVW R17:R16, R25:R24 + LDI R20, 4 + LDI R21, 0 + RCALL ?SS_DIVMOD_L02 + MOVW R31:R30, R27:R26 + STD Z+22, R16 + STD Z+23, R17 +// 192 +// 193 ADCS.Flag = TRUE; + LD R16, X + ORI R16, 0x20 + ST X, R16 +// 194 Next=0x01; +// 195 Signed = FALSE; // This is the only bipolar conversion. +// 196 break; +// 197 +// 198 +// 199 default: // Should not happen. (Invalid MUX-channel) +// 200 Next=0x01; // Start at the beginning of sequence. +??ADC_ISR_5: + LDI R16, 1 +// 201 break; +// 202 } +// 203 +// 204 // Update MUX to next channel in sequence, set a bipolar conversion if +// 205 // this has been flagged. +// 206 ADCS.MUX = Next; +??ADC_ISR_6: + LD R17, X + ANDI R17, 0xE0 + ANDI R16, 0x1F + OR R16, R17 + ST X, R16 +// 207 ADMUX = (1<` +ADCS: + DS 24 + DS 1 +// 221 +// 222 +// 223 /*! \brief Scales sample to represent "actual voltage" in mV. +// 224 * +// 225 * This function returns the actual sampled voltage, scaled according +// 226 * to the jumper settings. +// 227 * +// 228 * \param setting Indicates what downscaling was used. +// 229 * \param data The sampled value. +// 230 * +// 231 * \note Table for setting-parameter:\n +// 232 *
+//  233  * Presume VREF = 2.5V and Gain = 1x.
+//  234  * => Resolution @ 1/1 = 2.5V / 1024 = 2.4414 mV/LSB
+//  235  * setting | source |   R1 | R2/(R1+R2) | UADC(LSB) | U(MAX)
+//  236  * --------+--------+------+------------+-----------+-------
+//  237  *     N/A |        |    - |       -    |   2.441mV |  2.50V
+//  238  *       0 |   VBAT |  10k |     1/2    |   4.883mV |  5.00V
+//  239  *       1 |   VBAT |  30k |     1/4    |   9.766mV |  9.99V
+//  240  *       2 |   VBAT |  70k |     1/8    |   19.53mV | 19.98V
+//  241  *       3 |   VBAT | 110k |    1/12    |   29.30mV | 29.97V
+//  242  *       4 |   VBAT | 150k |    1/16    |   39.06mV | 39.96V
+//  243  *       4 |    VIN | 150k |    1/16    |   39.06mV | 39.96V
+//  244  * 
+// 245 */ + + RSEG CODE:CODE:NOROOT(1) +// 246 unsigned int ScaleU(unsigned char setting, unsigned int data) +ScaleU: +// 247 { + MOV R2, R26 + MOVW R23:R22, R25:R24 + MOV R26, R16 + MOVW R25:R24, R19:R18 +// 248 // Temporary variable needed. +// 249 unsigned int scaled = 0; +// 250 +// 251 // Jumper setting 3: mV/LSB = 29.30 ~= 29 + 1/4 + 1/16 +// 252 if (setting == 3) { + CPI R16, 3 + MOVW R21:R20, R19:R18 + BRNE ??ScaleU_0 +// 253 scaled = 29 * data; +// 254 scaled += (data >> 2); +// 255 scaled += (data >> 4); + LDI R16, 29 + LDI R17, 0 + RCALL ?S_MUL_L02 + LSR R19 + ROR R18 + LSR R19 + ROR R18 + ADD R18, R0 + ADC R19, R1 + LSR R25 + ROR R24 + LSR R25 + ROR R24 + LSR R25 + ROR R24 + LSR R25 + ROR R24 + ADD R24, R18 + ADC R25, R19 + RJMP ??ScaleU_1 +// 256 } else { +// 257 // Jumper setting 4: mV/LSB = 39.06 ~= 39 + 1/16 +// 258 scaled = 39 * data; +// 259 scaled += (data >> 4); +??ScaleU_0: + LDI R16, 39 + LDI R17, 0 + RCALL ?S_MUL_L02 + LSR R25 + ROR R24 + LSR R25 + ROR R24 + LSR R25 + ROR R24 + LSR R25 + ROR R24 + ADD R24, R0 + ADC R25, R1 +// 260 +// 261 if (setting <3) { + CPI R26, 3 + BRCC ??ScaleU_1 +// 262 // Jumper setting 0: mV/LSB = 4.883 = 39.06 / 8 +// 263 // 1: mV/LSB = 9.766 = 39.06 / 4 +// 264 // 2: mV/LSB = 19.53 = 39.06 / 2 +// 265 scaled = (scaled >> (3-setting)); + MOVW R17:R16, R25:R24 + LDI R20, 3 + SUB R20, R26 + RCALL ?US_SHR_L02 + MOVW R25:R24, R17:R16 +// 266 } +// 267 } +// 268 +// 269 return(scaled); +??ScaleU_1: + MOVW R17:R16, R25:R24 + MOVW R25:R24, R23:R22 + MOV R26, R2 + RET +// 270 } +// 271 +// 272 +// 273 /*! \brief Scales sample to represent "actual current" in mA. +// 274 * +// 275 * This function returns the actual sampled current, scaled according +// 276 * to the jumper settings. +// 277 * +// 278 * \param setting Indicates what downscaling was used. +// 279 * \param data The sampled value. +// 280 * +// 281 * \note Table for setting-parameter:\n +// 282 *
+//  283  * Presume VREF = 2.5V and Gain = 1x or 20x.
+//  284  * => Resolution(U) @ (1/1 and 20x) = 2.5V / (GAIN x 1024) = 0.1221 mV/LSB
+//  285  * => Resolution(I) = Resolution(U) / Rshunt = Resolution(U) / 0.07
+//  286  * Setting |   R1 | R2/(R1+R2) |   U(LSB) |   I(LSB) | I(MAX) | Gain
+//  287  * --------+------+------------+----------+----------+--------+-----
+//  288  *     N/A |    - |       -    | 0.1221mV |  1.744mA |  1.78A |  20x
+//  289  *       0 |  10k |     1/2    | 0.2442mV |  3.489mA |  3.57A |  20x
+//  290  *       1 |  30k |     1/4    | 0.4884mV |  6.978mA |  7.14A |  20x
+//  291  *       2 |  70k |     1/8    | 0.9768mV | 13.955mA |  14.3A |  20x
+//  292  *       3 | 110k |    1/12    | 1.4652mV | 20.931mA |  21.4A |  20x
+//  293  *       4 | 150k |    1/16    | 1.9536mV | 27.909mA |  28.5A |  20x
+//  294  *       5 |  10k |     1/2    | 2.4414mV | 34.877mA |  35.7A |   1x
+//  295  * 
+// 296 */ + + RSEG CODE:CODE:NOROOT(1) +// 297 unsigned int ScaleI(unsigned char setting, unsigned int data) +ScaleI: +// 298 { + MOV R2, R26 + MOVW R23:R22, R25:R24 + MOV R26, R16 + MOVW R25:R24, R19:R18 +// 299 // Temporary variable needed. +// 300 unsigned int scaled = 0; +// 301 +// 302 // Jumper setting 3: mA/LSB = 20.931mA ~= 21 - 1/16 + 1/128 +// 303 if (setting == 3) { + CPI R16, 3 + MOVW R21:R20, R19:R18 + BRNE ??ScaleI_0 +// 304 scaled = 21 * data; +// 305 scaled -= (data >> 4); +// 306 scaled += (data >> 7); + LDI R16, 21 + LDI R17, 0 + RCALL ?S_MUL_L02 + LSR R19 + ROR R18 + LSR R19 + ROR R18 + LSR R19 + ROR R18 + LSR R19 + ROR R18 + SUB R16, R18 + SBC R17, R19 + LSL R24 + MOV R24, R25 + ROL R24 + LDI R25, 0 + ROL R25 + ADD R24, R16 + ADC R25, R17 + RJMP ??ScaleI_1 +// 307 } else { // Jumper setting 4: mA/LSB = 27.909mA ~= 28 - 1/8 + 1/32 +// 308 scaled = 28 * data; +// 309 scaled -= (data >> 3); +// 310 scaled += (data >> 5); +??ScaleI_0: + LDI R16, 28 + LDI R17, 0 + RCALL ?S_MUL_L02 + MOVW R19:R18, R17:R16 + MOVW R17:R16, R25:R24 + LSR R17 + ROR R16 + LSR R17 + ROR R16 + LSR R17 + ROR R16 + SUB R18, R16 + SBC R19, R17 + MOVW R17:R16, R25:R24 + LDI R20, 5 + RCALL ?US_SHR_L02 + MOVW R25:R24, R17:R16 + ADD R24, R18 + ADC R25, R19 +// 311 +// 312 if (setting <3) { + CPI R26, 3 + BRCC ??ScaleI_1 +// 313 // Jumper setting 0: mA/LSB = 3.489mA = 27.909 / 8 +// 314 // 1: mA/LSB = 6.978mA = 27.909 / 4 +// 315 // 2: mA/LSB = 13.955mA = 27.909 / 2 +// 316 scaled = (scaled >> (3-setting)); + MOVW R17:R16, R25:R24 + LDI R20, 3 + SUB R20, R26 + RCALL ?US_SHR_L02 + MOVW R25:R24, R17:R16 +// 317 } +// 318 } +// 319 +// 320 return(scaled); +??ScaleI_1: + MOVW R17:R16, R25:R24 + MOVW R25:R24, R23:R22 + MOV R26, R2 + RET +// 321 } +// 322 +// 323 +// 324 /*! \brief Waits for two full cycles of ADC-conversions to occur. +// 325 * +// 326 * This function clears the cycle complete-flag, then waits for it to be set +// 327 * again. This is then repeated once before the function exits. +// 328 * +// 329 */ + + RSEG CODE:CODE:NOROOT(1) +// 330 void ADC_Wait(void) +ADC_Wait: +??ADC_Wait_0: +// 331 { +// 332 // Clear ADC flag and wait for cycle to complete. +// 333 ADCS.Flag = FALSE; +// 334 do { +// 335 } while (ADCS.Flag == FALSE); + RJMP ??ADC_Wait_0 +// 336 +// 337 // Repeat, so we are sure the data beong to the same cycle. +// 338 ADCS.Flag = FALSE; +// 339 do { +// 340 } while (ADCS.Flag == FALSE); +// 341 } +// 342 +// 343 +// 344 /*! \brief Initializes ADC and input pins. +// 345 * +// 346 * This function initializes the ADC to free running mode, sampling from +// 347 * PA1/2/4/5/6/7, and using an external reference voltage (PA3).\n +// 348 * It also measures and stores calibration data for offset. +// 349 * +// 350 * \todo Odd offset measurement for ADC3_G20_OS? It is never used anyway. +// 351 * +// 352 * \note Table of MUX settings for offset measurement: +// 353 *
+//  354  *    Ch | Pin |    Gain |    MUX
+//  355  * ------+-----+---------+-------
+//  356  *  ADC1 | PA1 |     20x | 001101
+//  357  *  ADC3 | PA4 |     20x | 010001
+//  358  *  ADC5 | PA6 |     20x | 010110
+//  359  *  ADC9 | PB6 |     20x | 011011
+//  360  *  ADC0 | PA0 | 20x/32x | 111000
+//  361  *  ADC0 | PA0 |   1x/8x | 111001
+//  362  *  ADC1 | PA1 | 20x/32x | 111010
+//  363  *  ADC2 | PA2 | 20x/32x | 111011
+//  364  *  ADC4 | PA5 | 20x/32x | 111100
+//  365  *  ADC5 | PA6 | 20x/32x | 111101
+//  366  *  ADC6 | PA7 | 20x/32x | 111110
+//  367  * 
+// 368 */ + + RSEG CODE:CODE:NOROOT(1) +// 369 void ADC_Init(void) +ADC_Init: +// 370 { +// 371 unsigned char i; +// 372 +// 373 __disable_interrupt(); + CLI +// 374 +// 375 ADCS.Halt = FALSE; // Enable consecutive runs of ADC. + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LD R16, Z + ANDI R16, 0x7F + ST Z, R16 +// 376 +// 377 // Configure ADC pins (inputs and disabled pull-ups). +// 378 DDRA &= ~((1<`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 7 bytes in segment ABSOLUTE +// 746 bytes in segment CODE +// 1 byte in segment EEPROM_I +// 6 bytes in segment INITTAB +// 2 bytes in segment INTVEC +// 25 bytes in segment NEAR_Z +// +// 746 bytes of CODE memory (+ 8 bytes shared) +// 25 bytes of DATA memory (+ 7 bytes shared) +// 1 byte of XDATA memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/BC100_tiny.map b/BaseTinyFirmware/IAR/Release/List/BC100_tiny.map new file mode 100644 index 0000000..21cee84 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/BC100_tiny.map @@ -0,0 +1,2087 @@ +################################################################################ +# # +# IAR Universal Linker V4.60I/386 # +# # +# Link time = 13/Mar/2008 04:52:03 # +# Target CPU = A90 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\BC10 # +# 0_tiny.map # +# Output file 1 = C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 # +# _tiny.hex # +# Format: intel-extended, variant: -y(CODE) # +# MISRA C Rules: # +# Enabled = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,38-39, # +# 42-43,46,50,52-54,56-59,61-62,64-65,68-80,83-84,8 # +# 7-91,94-95,98-100,103-110,112-126 # +# Checked = 11,25-26 # +# Output file 2 = C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 # +# _tiny_data.hex # +# Format: intel-extended, variant: -y(DATA) # +# MISRA C Rules: # +# Enabled = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,38-39, # +# 42-43,46,50,52-54,56-59,61-62,64-65,68-80,83-84,8 # +# 7-91,94-95,98-100,103-110,112-126 # +# Checked = 11,25-26 # +# Output file 3 = C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 # +# _tiny_eeprom.hex # +# Format: intel-extended, variant: -y(XDATA) # +# MISRA C Rules: # +# Enabled = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35,38-39, # +# 42-43,46,50,52-54,56-59,61-62,64-65,68-80,83-84,8 # +# 7-91,94-95,98-100,103-110,112-126 # +# Checked = 11,25-26 # +# Command line = -y(CODE) # +# -Ointel-extended,(DATA)=C:\home\kevin\pub\src\bc1 # +# 00\IAR\Release\Exe\BC100_tiny_data.hex # +# -Ointel-extended,(XDATA)=C:\home\kevin\pub\src\bc # +# 100\IAR\Release\Exe\BC100_tiny_eeprom.hex # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC.r # +# 90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIMHc # +# harge.r90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI.r # +# 90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM.r # +# 90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI.r # +# 90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\batte # +# ry.r90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\charg # +# efunc.r90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\main. # +# r90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\menu. # +# r90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\state # +# func.r90 # +# C:\home\kevin\pub\src\bc100\IAR\Release\Obj\time. # +# r90 # +# -o # +# C:\home\kevin\pub\src\bc100\IAR\Release\Exe\BC100 # +# _tiny.hex # +# -Fintel-extended -B -l # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\BC10 # +# 0_tiny.map # +# -xmsno # +# "-IC:\Program Files\IAR Systems\Embedded Workbenc # +# h 4.0\avr\LIB\" # +# -f # +# "C:\Program Files\IAR Systems\Embedded Workbench # +# 4.0\avr\src\template\cfgtiny861.xcl" # +# (-D_..X_INTVEC_SIZE=26 -D_..X_FLASH_END=1FFF # +# -D_..X_SRAM_BASE=60 # +# -D_..X_SRAM_TBASE=_..X_SRAM_BASE # +# -D_..X_SRAM_TSIZE=(100-_..X_SRAM_BASE) # +# -D_..X_SRAM_END=25F # +# -D_..X_EXT_SRAM_BASE=_..X_SRAM_END # +# -D_..X_EXT_SRAM_SIZE=0 # +# -D_..X_EXT_ROM_BASE=_..X_SRAM_END # +# -D_..X_EXT_ROM_SIZE=0 # +# -D_..X_EXT_NV_BASE=_..X_SRAM_END # +# -D_..X_EXT_NV_SIZE=0 -D_..X_EEPROM_END=1FF # +# -D_..X_EEPROM_START=0) -D_..X_HEAP_SIZE=10 # +# -D_..X_TINY_HEAP_SIZE=0 -D_..X_NEAR_HEAP_SIZE=0 # +# -D_..X_FAR_HEAP_SIZE=0 -D_..X_HUGE_HEAP_SIZE=0 # +# -D_..X_CSTACK_SIZE=40 -D_..X_RSTACK_SIZE=30 -f # +# "C:\Program Files\IAR Systems\Embedded Workbench # +# 4.0\avr\src\template\cfg1soim.xcl" # +# (-ca90 -w29 -Z(CODE)INTVEC=0-_..X_INTVEC_SIZE # +# -Z(CODE)TINY_F=_..X_FLASH_BASE-FF # +# -Z(CODE)NEAR_F=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)SWITCH=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)INITTAB=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)DIFUNCT=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)CODE=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)TINY_ID=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)NEAR_ID=_..X_FLASH_BASE-_..X_FLASH_END # +# -Z(CODE)CHECKSUM#_..X_FLASH_END # +# -Z(DATA)TINY_I,TINY_Z,TINY_N=_..X_SRAM_TBASE:+_.. # +# X_SRAM_TSIZE # +# -Z(DATA)CSTACK+_..X_CSTACK_SIZE=_..X_CSTACK_BASE- # +# _..X_CSTACK_END # +# -Z(DATA)HEAP+_..X_HEAP_SIZE=_..X_SRAM_BASE-_..X_S # +# RAM_END # +# -Z(DATA)IOSTREAM_N#_..X_SRAM_BASE-_..X_SRAM_END # +# -Z(DATA)NEAR_HEAP+_..X_NEAR_HEAP_SIZE=_..X_SRAM_B # +# ASE-_..X_SRAM_END # +# -Z(DATA)RSTACK+_..X_RSTACK_SIZE=_..X_RSTACK_BASE- # +# _..X_RSTACK_END # +# -Z(DATA)NEAR_I,NEAR_Z,NEAR_N=_..X_SRAM_BASE-_..X_ # +# SRAM_END # +# -Z(XDATA)EEPROM_I,EEPROM_N=_..X_EEPROM_START-_..X # +# _EEPROM_END) # +# -D_..X_FLASH_BASE=_..X_INTVEC_SIZE -H1895 # +# -h(CODE)0-(_..X_INTVEC_SIZE-1) # +# -D_..X_CSTACK_BASE=_..X_SRAM_BASE # +# -D_..X_CSTACK_END=_..X_SRAM_END # +# -D_..X_RSTACK_BASE=_..X_SRAM_BASE # +# -D_..X_RSTACK_END=_..X_SRAM_END -s # +# __program_start # +# "C:\Program Files\IAR Systems\Embedded Workbench # +# 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90" # +# -e_small_write=_formatted_write # +# -e_medium_read=_formatted_read # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32,34- # +# 35,38-39,42-43,46,50,52-54,56-59,61-62,64-65,68-8 # +# 0,83-84,87-91,94-95,98-100,103-110,112-126 # +# # +# Copyright 1987-2007 IAR Systems. All rights reserved. # +################################################################################ + + + + + + **************************************** + * * + * CROSS REFERENCE * + * * + **************************************** + + Program entry at : CODE 00000000 Relocatable, from module : ?RESET + + + + + **************************************** + * * + * RUNTIME MODEL * + * * + **************************************** + + EEPROM_SIZE = 2 + R4 = REG + R5 = REG + R6 = REG + R7 = REG + R8 = REG + R9 = REG + __64bit_doubles = disabled + __cpu = 1 + __cpu_name = ATtiny861 + __enhanced_core = enabled + __has_elpm = false + __memory_model = 2 + __rt_version = 3 + + + + **************************************** + * * + * MODULE MAP * + * * + **************************************** + + + DEFINED ABSOLUTE ENTRIES + PROGRAM MODULE, NAME : ?ABS_ENTRY_MOD + +Absolute parts + ENTRY ADDRESS REF BY + ===== ======= ====== + _..X_RSTACK_END 0000025F + _..X_RSTACK_BASE 00000060 + _..X_CSTACK_END 0000025F + _..X_CSTACK_BASE 00000060 + _..X_FLASH_BASE 00000026 + _..X_RSTACK_SIZE 00000030 + _..X_CSTACK_SIZE 00000040 + _..X_HUGE_HEAP_SIZE 00000000 + _..X_FAR_HEAP_SIZE 00000000 + _..X_NEAR_HEAP_SIZE 00000000 + _..X_TINY_HEAP_SIZE 00000000 + _..X_HEAP_SIZE 00000010 + _..X_EEPROM_START 00000000 + _..X_EEPROM_END 000001FF + _..X_EXT_NV_SIZE 00000000 + _..X_EXT_NV_BASE 0000025F + _..X_EXT_ROM_SIZE 00000000 + _..X_EXT_ROM_BASE 0000025F + _..X_EXT_SRAM_SIZE 00000000 + _..X_EXT_SRAM_BASE 0000025F + _..X_SRAM_END 0000025F + _..X_SRAM_TSIZE 000000A0 + _..X_SRAM_TBASE 00000060 + _..X_SRAM_BASE 00000060 + _..X_FLASH_END 00001FFF + _..X_INTVEC_SIZE 00000026 + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC.r90 + PROGRAM MODULE, NAME : ADC + + SEGMENTS IN THE MODULE + ====================== +ABSOLUTE + Relative segment, address: DATA 0000003B - 0000003B (0x1 bytes), align: 0 + Segment part 1. Intra module refs: ADC_Init + OWI_DetectPresence (OWI) + OWI_Init (OWI) + OWI_ReadBit (OWI) + OWI_WriteBit0 (OWI) + OWI_WriteBit1 (OWI) + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_PORTA 0000003B + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000003A - 0000003A (0x1 bytes), align: 0 + Segment part 2. Intra module refs: ADC_Init + OWI_DetectPresence (OWI) + OWI_Init (OWI) + OWI_ReadBit (OWI) + OWI_WriteBit0 (OWI) + OWI_WriteBit1 (OWI) + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_DDRA 0000003A + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000027 - 00000027 (0x1 bytes), align: 0 + Segment part 3. Intra module refs: ADC_ISR + ADC_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_ADMUX 00000027 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000026 - 00000026 (0x1 bytes), align: 0 + Segment part 4. Intra module refs: ADC_ISR + ADC_Init + Error (statefunc) + Sleep (statefunc) + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_ADCSRA 00000026 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000024 - 00000025 (0x2 bytes), align: 0 + Segment part 5. Intra module refs: ADC_ISR + ADC_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_ADC 00000024 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000023 - 00000023 (0x1 bytes), align: 0 + Segment part 6. Intra module refs: ADC_ISR + ADC_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_ADCSRB 00000023 + ------------------------------------------------------------------------- +EEPROM_I + Relative segment, address: XDATA 00000000 - 00000000 (0x1 bytes), align: 0 + Segment part 16. Intra module refs: ADC_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + VBAT_RANGE 00000000 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000050 - 000001E3 (0x194 bytes), align: 1 + Segment part 17. Intra module refs: ADC_ISR::??INTVEC 22 + ENTRY ADDRESS REF BY + ===== ======= ====== + ADC_ISR 00000050 + interrupt function + calls direct + stack 1 = 00000000 ( 00000013 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +NEAR_Z + Relative segment, address: DATA 00000144 - 0000015C (0x19 bytes), align: 0 + Segment part 14. Intra module refs: ADC_ISR + ADC_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + ADCS 00000144 BatteryStatusRefresh (battery) + ConstantCurrent (chargefunc) + HaltNow (chargefunc) + JumperCheck (statefunc) + NTCLookUp (battery) + RIDLookUp (battery) + USI_OVF_ISR (USI) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000001E4 - 00000249 (0x66 bytes), align: 1 + Segment part 18. Intra module refs: ADC_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + ScaleU 000001E4 + stack 1 = 00000000 ( 00000003 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 0000024A - 000002BD (0x74 bytes), align: 1 + Segment part 19. Intra module refs: ADC_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + ScaleI 0000024A + stack 1 = 00000000 ( 00000003 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000002BE - 000002BF (0x2 bytes), align: 1 + Segment part 20. + ENTRY ADDRESS REF BY + ===== ======= ====== + ADC_Wait 000002BE BatteryControl (statefunc) + ConstantCurrent (chargefunc) + Error (statefunc) + HaltNow (chargefunc) + Initialize (statefunc) + JumperCheck (statefunc) + Sleep (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000002C0 - 00000339 (0x7a bytes), align: 1 + Segment part 21. + ENTRY ADDRESS REF BY + ===== ======= ====== + ADC_Init 000002C0 Initialize (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000001C, align: 0 + Segment part 7. + ENTRY ADDRESS REF BY + ===== ======= ====== + __?EECR 0000001C Segment part 0 (?EEPROM_16) + Segment part 1 (?EEPROM_16) + Segment part 8 (?EEPROM_16) + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000001D, align: 0 + Segment part 8. + ENTRY ADDRESS REF BY + ===== ======= ====== + __?EEDR 0000001D __eeget8_16 (?EEPROM_16) + __eeput8_16 (?EEPROM_16) + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000001E, align: 0 + Segment part 9. + ENTRY ADDRESS REF BY + ===== ======= ====== + __?EEARL 0000001E Segment part 1 (?EEPROM_16) + Segment part 8 (?EEPROM_16) + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000001F, align: 0 + Segment part 10. + ENTRY ADDRESS REF BY + ===== ======= ====== + __?EEARH 0000001F Segment part 1 (?EEPROM_16) + Segment part 8 (?EEPROM_16) + ------------------------------------------------------------------------- +INTVEC + Common segment, address: CODE 00000000 - 00000017 (0x18 bytes), align: 1 + Segment part 11. ROOT. + ENTRY ADDRESS REF BY + ===== ======= ====== + ADC_ISR::??INTVEC 22 00000016 + ------------------------------------------------------------------------- +INITTAB + Relative segment, address: CODE 00000044 - 00000049 (0x6 bytes), align: 0 + Segment part 15. Intra module refs: ADCS + BattActive (battery) + BattData (battery) + CurrentState (main) + SPI (USI) + Segment part 13 (statefunc) + Segment part 8 (chargefunc) + timeval (time) + ENTRY ADDRESS REF BY + ===== ======= ====== + ? + 00000044 + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIMHcharge.r90 + PROGRAM MODULE, NAME : NIMHcharge + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 0000033A - 00000445 (0x10c bytes), align: 1 + Segment part 7. + ENTRY ADDRESS REF BY + ===== ======= ====== + Charge 0000033A menu_state (menu) + calls direct + stack 1 = 00000000 ( 00000002 ) + stack 2 = 00000000 ( 00000004 ) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI.r90 + PROGRAM MODULE, NAME : OWI + + SEGMENTS IN THE MODULE + ====================== +ABSOLUTE + Relative segment, address: DATA 00000039 - 00000039 (0x1 bytes), align: 0 + Segment part 3. Intra module refs: OWI_DetectPresence + OWI_ReadBit + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_PINA 00000039 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000446 - 00000461 (0x1c bytes), align: 1 + Segment part 10. + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_Init 00000446 Initialize (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000462 - 00000493 (0x32 bytes), align: 1 + Segment part 11. Intra module refs: OWI_SendByte + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_WriteBit1 00000462 + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000494 - 000004C5 (0x32 bytes), align: 1 + Segment part 12. Intra module refs: OWI_SendByte + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_WriteBit0 00000494 + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000004C6 - 00000507 (0x42 bytes), align: 1 + Segment part 13. Intra module refs: OWI_ReceiveByte + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_ReadBit 000004C6 + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000508 - 00000551 (0x4a bytes), align: 1 + Segment part 14. + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_DetectPresence 00000508 BatteryDataRefresh (battery) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000552 - 00000577 (0x26 bytes), align: 1 + Segment part 15. + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_SendByte 00000552 BatteryDataRefresh (battery) + calls direct + stack 1 = 00000000 ( 00000003 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000578 - 0000059D (0x26 bytes), align: 1 + Segment part 16. + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_ReceiveByte 00000578 BatteryDataRefresh (battery) + calls direct + stack 1 = 00000000 ( 00000003 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 0000059E - 000005C1 (0x24 bytes), align: 1 + Segment part 22. + ENTRY ADDRESS REF BY + ===== ======= ====== + OWI_ComputeCRC8 0000059E BatteryDataRefresh (battery) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM.r90 + PROGRAM MODULE, NAME : PWM + + SEGMENTS IN THE MODULE + ====================== +ABSOLUTE + Relative segment, address: DATA 00000050 - 00000050 (0x1 bytes), align: 0 + Segment part 1. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR1A 00000050 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000004F - 0000004F (0x1 bytes), align: 0 + Segment part 2. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR1B 0000004F + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000004D - 0000004D (0x1 bytes), align: 0 + Segment part 3. Intra module refs: PWM_Start + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_OCR1A 0000004D + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000004C - 0000004C (0x1 bytes), align: 0 + Segment part 4. Intra module refs: BatteryStatusRefresh (battery) + ConstantCurrent (chargefunc) + PWM_DecrementDutyCycle + PWM_IncrementDutyCycle + PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_OCR1B 0000004C + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000004B - 0000004B (0x1 bytes), align: 0 + Segment part 5. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_OCR1C 0000004B + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000004A - 0000004A (0x1 bytes), align: 0 + Segment part 6. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_OCR1D 0000004A + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000049 - 00000049 (0x1 bytes), align: 0 + Segment part 7. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_PLLCSR 00000049 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000047 - 00000047 (0x1 bytes), align: 0 + Segment part 8. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR1C 00000047 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000046 - 00000046 (0x1 bytes), align: 0 + Segment part 9. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR1D 00000046 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000044 - 00000044 (0x1 bytes), align: 0 + Segment part 10. Intra module refs: PWM_Start + PWM_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_DT1 00000044 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000037 - 00000037 (0x1 bytes), align: 0 + Segment part 11. Intra module refs: Initialize (statefunc) + PWM_Start + SPI_Init (USI) + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_DDRB 00000037 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000020 - 00000020 (0x1 bytes), align: 0 + Segment part 12. Intra module refs: PWM_Start + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR1E 00000020 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000005C2 - 000005D7 (0x16 bytes), align: 1 + Segment part 19. + ENTRY ADDRESS REF BY + ===== ======= ====== + PWM_Stop 000005C2 Charge (NIMHcharge) + Error (statefunc) + HaltNow (chargefunc) + JumperCheck (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000005D8 - 00000627 (0x50 bytes), align: 1 + Segment part 20. + ENTRY ADDRESS REF BY + ===== ======= ====== + PWM_Start 000005D8 Charge (NIMHcharge) + JumperCheck (statefunc) + calls direct + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000628 - 0000063B (0x14 bytes), align: 1 + Segment part 21. + ENTRY ADDRESS REF BY + ===== ======= ====== + PWM_IncrementDutyCycle + 00000628 ConstantCurrent (chargefunc) + JumperCheck (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 0000063C - 0000064F (0x14 bytes), align: 1 + Segment part 22. + ENTRY ADDRESS REF BY + ===== ======= ====== + PWM_DecrementDutyCycle + 0000063C ConstantCurrent (chargefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI.r90 + PROGRAM MODULE, NAME : USI + + SEGMENTS IN THE MODULE + ====================== +ABSOLUTE + Relative segment, address: DATA 00000038 - 00000038 (0x1 bytes), align: 0 + Segment part 1. Intra module refs: DisableBatteries (battery) + EnableBattery (battery) + SPI_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_PORTB 00000038 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000002F - 0000002F (0x1 bytes), align: 0 + Segment part 3. Intra module refs: SPI_Put + USI_OVF_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_USIDR 0000002F + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000002E - 0000002E (0x1 bytes), align: 0 + Segment part 4. Intra module refs: SPI_Put + USI_OVF_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_USISR 0000002E + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 0000002D - 0000002D (0x1 bytes), align: 0 + Segment part 5. Intra module refs: SPI_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_USICR 0000002D + ------------------------------------------------------------------------- +NEAR_Z + Relative segment, address: DATA 0000015D - 00000160 (0x4 bytes), align: 0 + Segment part 13. Intra module refs: SPI_Init + SPI_Put + USI_OVF_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + SPI 0000015D + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000650 - 000007BD (0x16e bytes), align: 1 + Segment part 15. Intra module refs: USI_OVF_ISR::??INTVEC 16 + ENTRY ADDRESS REF BY + ===== ======= ====== + USI_OVF_ISR 00000650 + interrupt function + calls direct + stack 1 = 00000000 ( 0000000F ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000007BE - 000007F5 (0x38 bytes), align: 1 + Segment part 16. + ENTRY ADDRESS REF BY + ===== ======= ====== + SPI_Init 000007BE Initialize (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000007F6 - 00000815 (0x20 bytes), align: 1 + Segment part 17. Intra module refs: USI_OVF_ISR + ENTRY ADDRESS REF BY + ===== ======= ====== + SPI_Put 000007F6 + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +INTVEC + Common segment, address: CODE 00000000 - 00000011 (0x12 bytes), align: 1 + Segment part 10. ROOT. + ENTRY ADDRESS REF BY + ===== ======= ====== + USI_OVF_ISR::??INTVEC 16 + 00000010 + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\battery.r90 + PROGRAM MODULE, NAME : battery + + SEGMENTS IN THE MODULE + ====================== +EEPROM_I + Relative segment, address: XDATA 00000001 - 00000002 (0x2 bytes), align: 0 + Segment part 9. + ENTRY ADDRESS REF BY + ===== ======= ====== + BattControl 00000001 BatteryControl (statefunc) + Charge (NIMHcharge) + ConstantCurrent (chargefunc) + HaltNow (chargefunc) + USI_OVF_ISR (USI) + ------------------------------------------------------------------------- +NEAR_Z + Relative segment, address: DATA 00000161 - 0000016C (0xc bytes), align: 0 + Segment part 10. Intra module refs: BatteryCheck + BatteryDataRefresh + BatteryStatusRefresh + NTCLookUp + RIDLookUp + ENTRY ADDRESS REF BY + ===== ======= ====== + BattData 00000161 BatteryControl (statefunc) + Charge (NIMHcharge) + HaltNow (chargefunc) + USI_OVF_ISR (USI) + ------------------------------------------------------------------------- +EEPROM_I + Relative segment, address: XDATA 00000003 - 00000082 (0x80 bytes), align: 0 + Segment part 12. Intra module refs: BatteryDataRefresh + ENTRY ADDRESS REF BY + ===== ======= ====== + BattEEPROM 00000003 Initialize (statefunc) + ------------------------------------------------------------------------- +NEAR_Z + Relative segment, address: DATA 0000016D - 0000016D (0x1 bytes), align: 0 + Segment part 13. Intra module refs: EnableBattery + ENTRY ADDRESS REF BY + ===== ======= ====== + BattActive 0000016D Charge (NIMHcharge) + ConstantCurrent (chargefunc) + HaltNow (chargefunc) + Initialize (statefunc) + USI_OVF_ISR (USI) + ------------------------------------------------------------------------- +NEAR_I + Relative segment, address: DATA 000000D0 - 00000107 (0x38 bytes), align: 0 + Segment part 14. Intra module refs: RIDLookUp + ENTRY ADDRESS REF BY + ===== ======= ====== + RID 000000D0 + ------------------------------------------------------------------------- +NEAR_I + Relative segment, address: DATA 00000108 - 00000143 (0x3c bytes), align: 0 + Segment part 17. Intra module refs: NTCLookUp + ENTRY ADDRESS REF BY + ===== ======= ====== + NTC 00000108 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000816 - 00000847 (0x32 bytes), align: 1 + Segment part 19. + ENTRY ADDRESS REF BY + ===== ======= ====== + BatteryCheck 00000816 HaltNow (chargefunc) + calls direct + stack 1 = 00000000 ( 00000003 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000848 - 000008E5 (0x9e bytes), align: 1 + Segment part 20. Intra module refs: BatteryCheck + ENTRY ADDRESS REF BY + ===== ======= ====== + BatteryStatusRefresh 00000848 BatteryControl (statefunc) + Initialize (statefunc) + calls direct + stack 1 = 00000000 ( 00000004 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000008E6 - 000009E3 (0xfe bytes), align: 1 + Segment part 21. + ENTRY ADDRESS REF BY + ===== ======= ====== + BatteryDataRefresh 000008E6 BatteryControl (statefunc) + calls direct + stack 1 = 00000000 ( 00000009 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000009E4 - 00000A25 (0x42 bytes), align: 1 + Segment part 22. + ENTRY ADDRESS REF BY + ===== ======= ====== + EnableBattery 000009E4 BatteryControl (statefunc) + Initialize (statefunc) + calls direct + stack 1 = 00000000 ( 00000001 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000A26 - 00000A2D (0x8 bytes), align: 1 + Segment part 23. + ENTRY ADDRESS REF BY + ===== ======= ====== + DisableBatteries 00000A26 BatteryControl (statefunc) + Error (statefunc) + Initialize (statefunc) + JumperCheck (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000A2E - 00000AB1 (0x84 bytes), align: 1 + Segment part 24. Intra module refs: BatteryStatusRefresh + ENTRY ADDRESS REF BY + ===== ======= ====== + RIDLookUp 00000A2E + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000AB2 - 00000B39 (0x88 bytes), align: 1 + Segment part 25. Intra module refs: BatteryStatusRefresh + ENTRY ADDRESS REF BY + ===== ======= ====== + NTCLookUp 00000AB2 + stack 1 = 00000000 ( 00000003 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +NEAR_ID + Relative segment, address: CODE 000011FA - 00001231 (0x38 bytes), align: 0 + Segment part 15. Intra module refs: RID + ------------------------------------------------------------------------- +INITTAB + Relative segment, address: CODE 0000004A - 0000004F (0x6 bytes), align: 0 + Segment part 16. Intra module refs: NTC + RID + ENTRY ADDRESS REF BY + ===== ======= ====== + ? + 0000004A + ------------------------------------------------------------------------- +NEAR_ID + Relative segment, address: CODE 00001232 - 0000126D (0x3c bytes), align: 0 + Segment part 18. Intra module refs: NTC + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\chargefunc.r90 + PROGRAM MODULE, NAME : chargefunc + + SEGMENTS IN THE MODULE + ====================== +NEAR_Z + Relative segment, address: DATA 0000016E - 00000183 (0x16 bytes), align: 0 + Segment part 8. Intra module refs: ConstantCurrent + HaltNow + ENTRY ADDRESS REF BY + ===== ======= ====== + ChargeParameters 0000017F Charge (NIMHcharge) + HaltParameters 0000016E Charge (NIMHcharge) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000B3A - 00000BD1 (0x98 bytes), align: 1 + Segment part 10. + ENTRY ADDRESS REF BY + ===== ======= ====== + ConstantCurrent 00000B3A Charge (NIMHcharge) + calls direct + stack 1 = 00000000 ( 00000006 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000BD2 - 00000D79 (0x1a8 bytes), align: 1 + Segment part 12. Intra module refs: ConstantCurrent + ENTRY ADDRESS REF BY + ===== ======= ====== + HaltNow 00000BD2 + calls direct + stack 1 = 00000000 ( 0000000A ) + stack 2 = 00000000 ( 00000004 ) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\main.r90 + PROGRAM MODULE, NAME : main + + SEGMENTS IN THE MODULE + ====================== +NEAR_Z + Relative segment, address: DATA 00000184 - 00000184 (0x1 bytes), align: 0 + Segment part 7. Intra module refs: main + ENTRY ADDRESS REF BY + ===== ======= ====== + CurrentState 00000184 BatteryControl (statefunc) + Charge (NIMHcharge) + SetErrorFlag (statefunc) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000D7A - 00000DFD (0x84 bytes), align: 1 + Segment part 9. + ENTRY ADDRESS REF BY + ===== ======= ====== + main 00000D7A ?cstartup_call_main (?C_STARTUP) + calls indirect + stack 1 = 00000000 ( 00000002 ) + stack 2 = 00000000 ( 00000002 ) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\menu.r90 + PROGRAM MODULE, NAME : menu + + SEGMENTS IN THE MODULE + ====================== +NEAR_F + Relative segment, address: CODE 00000026 - 00000043 (0x1e bytes), align: 0 + Segment part 7. + ENTRY ADDRESS REF BY + ===== ======= ====== + menu_state 00000026 main (main) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\statefunc.r90 + PROGRAM MODULE, NAME : statefunc + + SEGMENTS IN THE MODULE + ====================== +ABSOLUTE + Relative segment, address: DATA 00000055 - 00000055 (0x1 bytes), align: 0 + Segment part 1. Intra module refs: Error + Sleep + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_MCUCR 00000055 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000054 - 00000054 (0x1 bytes), align: 0 + Segment part 2. Intra module refs: Error + Sleep + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_MCUSR 00000054 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000048 - 00000048 (0x1 bytes), align: 0 + Segment part 3. Intra module refs: Initialize + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_CLKPR 00000048 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000041 - 00000041 (0x1 bytes), align: 0 + Segment part 4. Intra module refs: Error + Sleep + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_WDTCR 00000041 + ------------------------------------------------------------------------- +NEAR_Z + Relative segment, address: DATA 00000185 - 00000186 (0x2 bytes), align: 0 + Segment part 13. Intra module refs: BatteryControl + Initialize + SetErrorFlag + ENTRY ADDRESS REF BY + ===== ======= ====== + ErrorFlags 00000185 + ErrorState 00000186 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000DFE - 00000E4F (0x52 bytes), align: 1 + Segment part 15. + ENTRY ADDRESS REF BY + ===== ======= ====== + Initialize 00000DFE menu_state (menu) + calls direct + stack 1 = 00000000 ( 00000001 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000E50 - 00000EC9 (0x7a bytes), align: 1 + Segment part 16. + ENTRY ADDRESS REF BY + ===== ======= ====== + BatteryControl 00000E50 menu_state (menu) + calls direct + stack 1 = 00000000 ( 00000004 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000ECA - 00000ECD (0x4 bytes), align: 1 + Segment part 17. + ENTRY ADDRESS REF BY + ===== ======= ====== + Discharge 00000ECA menu_state (menu) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000ECE - 00000ED1 (0x4 bytes), align: 1 + Segment part 18. + ENTRY ADDRESS REF BY + ===== ======= ====== + Sleep 00000ECE menu_state (menu) + calls direct + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000ED2 - 00000ED9 (0x8 bytes), align: 1 + Segment part 20. + ENTRY ADDRESS REF BY + ===== ======= ====== + Error 00000ED2 menu_state (menu) + calls direct + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000EDA - 00000EEB (0x12 bytes), align: 1 + Segment part 21. + ENTRY ADDRESS REF BY + ===== ======= ====== + SetErrorFlag 00000EDA ConstantCurrent (chargefunc) + HaltNow (chargefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000EEC - 00000F5F (0x74 bytes), align: 1 + Segment part 22. Intra module refs: BatteryControl + ENTRY ADDRESS REF BY + ===== ======= ====== + JumperCheck 00000EEC + calls direct + stack 1 = 00000000 ( 00000002 ) + stack 2 = 00000000 ( 00000002 ) + + ************************************************************************* + + FILE NAME : C:\home\kevin\pub\src\bc100\IAR\Release\Obj\time.r90 + PROGRAM MODULE, NAME : time + + SEGMENTS IN THE MODULE + ====================== +ABSOLUTE + Relative segment, address: DATA 00000059 - 00000059 (0x1 bytes), align: 0 + Segment part 1. Intra module refs: Time_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TIMSK 00000059 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000053 - 00000053 (0x1 bytes), align: 0 + Segment part 2. Intra module refs: Time_Init + Time_Start + Time_Stop + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR0B 00000053 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000035 - 00000035 (0x1 bytes), align: 0 + Segment part 3. Intra module refs: Time_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_TCCR0A 00000035 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000033 - 00000033 (0x1 bytes), align: 0 + Segment part 4. Intra module refs: Time_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_OCR0A 00000033 + ------------------------------------------------------------------------- +ABSOLUTE + Relative segment, address: DATA 00000032 - 00000032 (0x1 bytes), align: 0 + Segment part 5. Intra module refs: Time_Init + ENTRY ADDRESS REF BY + ===== ======= ====== + _A_OCR0B 00000032 + ------------------------------------------------------------------------- +NEAR_Z + Relative segment, address: DATA 00000187 - 00000196 (0x10 bytes), align: 0 + Segment part 13. Intra module refs: TICK_ISR + Time_Left + Time_Set + ENTRY ADDRESS REF BY + ===== ======= ====== + timeval 00000187 USI_OVF_ISR (USI) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000F60 - 00000FB5 (0x56 bytes), align: 1 + Segment part 15. Intra module refs: TICK_ISR::??INTVEC 28 + ENTRY ADDRESS REF BY + ===== ======= ====== + TICK_ISR 00000F60 + interrupt function + stack 1 = 00000000 ( 00000009 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000FB6 - 00000FDD (0x28 bytes), align: 1 + Segment part 16. + ENTRY ADDRESS REF BY + ===== ======= ====== + Time_Left 00000FB6 EnableBattery (battery) + HaltNow (chargefunc) + JumperCheck (statefunc) + PWM_Start (PWM) + USI_OVF_ISR (USI) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00000FDE - 0000105B (0x7e bytes), align: 1 + Segment part 17. + ENTRY ADDRESS REF BY + ===== ======= ====== + Time_Set 00000FDE Charge (NIMHcharge) + EnableBattery (battery) + HaltNow (chargefunc) + JumperCheck (statefunc) + PWM_Start (PWM) + USI_OVF_ISR (USI) + stack 1 = 00000000 ( 00000008 ) + stack 2 = 00000000 ( 00000004 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 0000105C - 00001061 (0x6 bytes), align: 1 + Segment part 18. + ENTRY ADDRESS REF BY + ===== ======= ====== + Time_Stop 0000105C ConstantCurrent (chargefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00001062 - 00001067 (0x6 bytes), align: 1 + Segment part 19. + ENTRY ADDRESS REF BY + ===== ======= ====== + Time_Start 00001062 ConstantCurrent (chargefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00001068 - 00001081 (0x1a bytes), align: 1 + Segment part 20. + ENTRY ADDRESS REF BY + ===== ======= ====== + Time_Init 00001068 Initialize (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +INTVEC + Common segment, address: CODE 00000000 - 0000001D (0x1e bytes), align: 1 + Segment part 10. ROOT. + ENTRY ADDRESS REF BY + ===== ======= ====== + TICK_ISR::??INTVEC 28 0000001C + + ************************************************************************* + + FILE NAME : C:\Program Files\IAR Systems\Embedded Workbench 4.0\avr\LIB\CLIB\cl1s-ec_nomul.r90 + LIBRARY MODULE, NAME : ?__exit + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001082 - 00001087 (0x6 bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + __exit 00001084 + ?C_EXIT 00001084 + ?C_FUNCALL 00001082 + _exit 00001082 ?cstartup_call_main (?C_STARTUP) + exit 00001082 ?cstartup_call_main (?C_STARTUP) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?abs + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001088 - 00001097 (0x10 bytes), align: 1 + Segment part 3. + ENTRY ADDRESS REF BY + ===== ======= ====== + abs 00001088 JumperCheck (statefunc) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?RESET + + SEGMENTS IN THE MODULE + ====================== +INTVEC + Common segment, address: CODE 00000000 - 00000001 (0x2 bytes), align: 1 + Segment part 0. ROOT. + ENTRY ADDRESS REF BY + ===== ======= ====== + __program_start 00000000 Absolute parts (?ABS_ENTRY_MOD) + ?RESET 00000000 Segment part 2 (?C_STARTUP) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?C_STARTUP + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001098, align: 1 + Segment part 2. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?C_STARTUP 00001098 Segment part 0 (?RESET) + __RESTART 00001098 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 00001098 - 000010A3 (0xc bytes), align: 1 + Segment part 5. Intra module refs: Segment part 2 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010A4 - 000010A5 (0x2 bytes), align: 1 + Segment part 7. Intra module refs: Segment part 5 + ENTRY ADDRESS REF BY + ===== ======= ====== + ?call_low_level_init 000010A4 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010A6 - 000010AB (0x6 bytes), align: 1 + Segment part 8. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?need_segment_init 000010A6 ? (battery) + ? (ADC) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010AC - 000010B1 (0x6 bytes), align: 1 + Segment part 9. Intra module refs: ?call_low_level_init + ENTRY ADDRESS REF BY + ===== ======= ====== + ?cstartup_call_main 000010AC + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?EEPROM_16 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000010B2 - 000010B7 (0x6 bytes), align: 1 + Segment part 0. Intra module refs: Segment part 1 + __eeput8_16 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010B8 - 000010C5 (0xe bytes), align: 1 + Segment part 1. Intra module refs: __eeget8_16 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010C6 - 000010CB (0x6 bytes), align: 1 + Segment part 3. + ENTRY ADDRESS REF BY + ===== ======= ====== + __eeget8_16 000010C6 ADC_ISR (ADC) + BatteryControl (statefunc) + Charge (NIMHcharge) + ConstantCurrent (chargefunc) + HaltNow (chargefunc) + USI_OVF_ISR (USI) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010CC - 000010DD (0x12 bytes), align: 1 + Segment part 8. Intra module refs: __eeput8_16 + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000010DE - 000010E5 (0x8 bytes), align: 1 + Segment part 10. + ENTRY ADDRESS REF BY + ===== ======= ====== + __eeput8_16 000010DE BatteryDataRefresh (battery) + HaltNow (chargefunc) + Initialize (statefunc) + USI_OVF_ISR (USI) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?S_MUL_L02 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000010E6 - 00001105 (0x20 bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?S_MUL_L02 000010E6 HaltNow (chargefunc) + ScaleI (ADC) + ScaleU (ADC) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?S_SHL_L02 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001106 - 00001111 (0xc bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?S_SHL_L02 00001106 EnableBattery (battery) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?US_SHR_L02 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001112 - 0000111D (0xc bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?US_SHR_L02 00001112 ScaleI (ADC) + ScaleU (ADC) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?US_DIVMOD_L02 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 0000111E - 00001145 (0x28 bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?US_DIVMOD_L02 0000111E ?SS_DIVMOD_L02 (?SS_DIVMOD_L02) + Charge (NIMHcharge) + NTCLookUp (battery) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?SS_DIVMOD_L02 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001146 - 00001173 (0x2e bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?SS_DIVMOD_L02 0000114E ADC_ISR (ADC) + Charge (NIMHcharge) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?L_MUL_L03 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 00001174 - 000011A5 (0x32 bytes), align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?L_MUL_L03 00001174 Time_Set (time) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?REGISTER_CGREGR4_L10 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6, align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?Register_R4_is_cg_reg + 000011A6 ADC_ISR (ADC) + BatteryDataRefresh (battery) + ConstantCurrent (chargefunc) + HaltNow (chargefunc) + Time_Set (time) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?REGISTER_CGREGR5_L10 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6, align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?Register_R5_is_cg_reg + 000011A6 BatteryDataRefresh (battery) + ConstantCurrent (chargefunc) + HaltNow (chargefunc) + Time_Set (time) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?REGISTER_CGREGR6_L10 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6, align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?Register_R6_is_cg_reg + 000011A6 BatteryDataRefresh (battery) + HaltNow (chargefunc) + Time_Set (time) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?REGISTER_CGREGR7_L10 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6, align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?Register_R7_is_cg_reg + 000011A6 BatteryDataRefresh (battery) + HaltNow (chargefunc) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?REGISTER_CGREGR8_L10 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6, align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?Register_R8_is_cg_reg + 000011A6 BatteryDataRefresh (battery) + HaltNow (chargefunc) + Time_Set (time) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?REGISTER_CGREGR9_L10 + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6, align: 1 + Segment part 0. + ENTRY ADDRESS REF BY + ===== ======= ====== + ?Register_R9_is_cg_reg + 000011A6 HaltNow (chargefunc) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?low_level_init + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011A6 - 000011A9 (0x4 bytes), align: 1 + Segment part 3. + ENTRY ADDRESS REF BY + ===== ======= ====== + __low_level_init 000011A6 ?call_low_level_init (?C_STARTUP) + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + + ------------------------------------------------------------------------- + LIBRARY MODULE, NAME : ?segment_init + + SEGMENTS IN THE MODULE + ====================== +CODE + Relative segment, address: CODE 000011AA - 000011B1 (0x8 bytes), align: 1 + Segment part 3. Intra module refs: __segment_init + LOCAL ADDRESS + ===== ======= + __memclr 000011AA + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000011B2 - 000011B9 (0x8 bytes), align: 1 + Segment part 4. Intra module refs: __segment_init + LOCAL ADDRESS + ===== ======= + __flashcpy 000011B2 + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000011BA - 000011C5 (0xc bytes), align: 1 + Segment part 5. Intra module refs: __flashcpy + __memclr + ------------------------------------------------------------------------- +CODE + Relative segment, address: CODE 000011C6 - 000011F9 (0x34 bytes), align: 1 + Segment part 6. + ENTRY ADDRESS REF BY + ===== ======= ====== + __segment_init 000011C6 ?need_segment_init (?C_STARTUP) + calls direct + stack 1 = 00000000 ( 00000000 ) + stack 2 = 00000000 ( 00000002 ) + + ************************************************************************* + + DEFINED ABSOLUTE ENTRIES + PROGRAM MODULE, NAME : ?FILLER_BYTES + + SEGMENTS IN THE MODULE + ====================== +INTVEC + Common segment, address: CODE 00000000 - 0000001D (0x1e bytes), align: 0 + Segment part 1. + ------------------------------------------------------------------------- +?FILL1 + Relative segment, address: CODE 0000001E - 00000025 (0x8 bytes), align: 0 + Segment part 0. + + + + + **************************************** + * * + * MODULE SUMMARY * + * * + **************************************** + +Module CODE DATA XDATA +------ ---- ---- ----- + (Rel) (Rel) (Abs) (Rel) +?C_STARTUP 26 +?EEPROM_16 52 +?FILLER_BYTES 8 + + common 30 +?L_MUL_L03 50 +?RESET + + common 2 +?SS_DIVMOD_L02 46 +?S_MUL_L02 32 +?S_SHL_L02 12 +?US_DIVMOD_L02 40 +?US_SHR_L02 12 +?__exit 6 +?abs 16 +?low_level_init 4 +?segment_init 80 +ADC 746 25 4 1 + + shared 6 3 + + common 24 +NIMHcharge 268 +OWI 380 1 +PWM 142 10 + + shared 2 +USI 454 4 3 + + shared 18 1 + + common +battery 926 129 130 +chargefunc 576 22 +main 132 1 +menu 30 +statefunc 354 2 4 +time 290 16 5 + + common 30 +N/A (command line) 112 +N/A (alignment) +---------- ----- --- -- --- +Total: 4 688 311 33 131 + + common 30 + + + **************************************** + * * + * CALL GRAPH * + * * + **************************************** + + ->Sub-tree of type: Interrupt function tree that does not make + : indirect calls + CSTACK RSTACK + | Stack used (prev) : 00000000 00000000 + 02 ScaleI + | Stack used (prev) : 00000000 00000000 + | + function block : 00000003 00000004 + 02 ScaleI + | Stack used (prev) : 00000000 00000000 + | + function block : 00000003 00000004 + | Already listed + 02 ScaleU + | Stack used (prev) : 00000000 00000000 + | + function block : 00000003 00000004 + 02 ScaleU + | Stack used (prev) : 00000000 00000000 + | + function block : 00000003 00000004 + | Already listed + 01 ADC_ISR + | Stack used (prev) : 00000003 00000004 + | + function block : 00000013 00000002 + <-Sub-tree of type: Interrupt function tree that does not make + : indirect calls + | Stack used : 00000016 00000006 + + + ->Sub-tree of type: Interrupt function tree that does not make + : indirect calls + CSTACK RSTACK + | Stack used (prev) : 00000016 00000006 + 02 Time_Set + | Stack used (prev) : 00000016 00000006 + | + function block : 00000008 00000004 + 02 Time_Left + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 SPI_Put + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 01 USI_OVF_ISR + | Stack used (prev) : 0000001E 0000000A + | + function block : 0000000F 00000002 + <-Sub-tree of type: Interrupt function tree that does not make + : indirect calls + | Stack used : 0000002D 0000000C + + + ->Sub-tree of type: Interrupt function tree that does not make + : indirect calls + CSTACK RSTACK + | Stack used (prev) : 0000002D 0000000C + 01 TICK_ISR + | Stack used (prev) : 0000002D 0000000C + | + function block : 00000009 00000002 + <-Sub-tree of type: Interrupt function tree that does not make + : indirect calls + | Stack used : 00000036 0000000E + + + ->Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + CSTACK RSTACK + | Stack used (prev) : 00000036 0000000E + 02 Time_Set + | Stack used (prev) : 00000016 00000006 + | + function block : 00000008 00000004 + | Already listed + 03 Time_Start + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 Time_Stop + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 SetErrorFlag + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 04 Time_Set + | Stack used (prev) : 00000016 00000006 + | + function block : 00000008 00000004 + | Already listed + 04 Time_Left + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 04 SetErrorFlag + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 06 NTCLookUp + | Stack used (prev) : 00000036 0000000E + | + function block : 00000003 00000004 + 06 RIDLookUp + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 05 BatteryStatusRefresh + | Stack used (prev) : 00000039 00000012 + | + function block : 00000004 00000002 + 04 BatteryCheck + | Stack used (prev) : 0000003D 00000014 + | + function block : 00000003 00000002 + 04 PWM_Stop + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 04 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 HaltNow + | Stack used (prev) : 00000040 00000016 + | + function block : 0000000A 00000002 + 03 PWM_DecrementDutyCycle + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 PWM_IncrementDutyCycle + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 02 ConstantCurrent + | Stack used (prev) : 0000004A 00000018 + | + function block : 00000006 00000002 + 03 Time_Set + | Stack used (prev) : 00000016 00000006 + | + function block : 00000008 00000004 + | Already listed + 03 Time_Left + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 PWM_Start + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 02 PWM_Stop + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 01 Charge + | Stack used (prev) : 00000050 0000001A + | + function block : 00000002 00000002 + <-Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + | Stack used : 00000052 0000001C + + + ->Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + CSTACK RSTACK + | Stack used (prev) : 00000036 0000000E + 02 Time_Init + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 02 DisableBatteries + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 Time_Set + | Stack used (prev) : 00000016 00000006 + | + function block : 00000008 00000004 + | Already listed + 03 Time_Left + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 02 EnableBattery + | Stack used (prev) : 00000036 0000000E + | + function block : 00000001 00000004 + 02 BatteryStatusRefresh + | Stack used (prev) : 00000039 00000012 + | + function block : 00000004 00000002 + | Already listed + 02 SPI_Init + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 02 OWI_Init + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 02 ADC_Init + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 02 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 01 Initialize + | Stack used (prev) : 0000003D 00000014 + | + function block : 00000001 00000002 + <-Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + | Stack used : 0000003E 00000016 + + + ->Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + CSTACK RSTACK + | Stack used (prev) : 00000036 0000000E + 03 abs + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 Time_Set + | Stack used (prev) : 00000016 00000006 + | + function block : 00000008 00000004 + | Already listed + 03 Time_Left + | Stack used (prev) : 00000016 00000006 + | + function block : 00000000 00000002 + | Already listed + 03 DisableBatteries + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 03 PWM_IncrementDutyCycle + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 03 PWM_Start + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 03 PWM_Stop + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 03 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 02 JumperCheck + | Stack used (prev) : 00000036 00000010 + | + function block : 00000002 00000002 + 02 DisableBatteries + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 02 EnableBattery + | Stack used (prev) : 00000036 0000000E + | + function block : 00000001 00000004 + | Already listed + 03 OWI_ComputeCRC8 + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 04 OWI_ReadBit + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 OWI_ReceiveByte + | Stack used (prev) : 00000036 00000010 + | + function block : 00000003 00000002 + 04 OWI_WriteBit0 + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 04 OWI_WriteBit1 + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 03 OWI_SendByte + | Stack used (prev) : 00000036 00000010 + | + function block : 00000003 00000002 + 03 OWI_DetectPresence + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + 02 BatteryDataRefresh + | Stack used (prev) : 00000039 00000012 + | + function block : 00000009 00000002 + 02 BatteryStatusRefresh + | Stack used (prev) : 00000039 00000012 + | + function block : 00000004 00000002 + | Already listed + 02 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 01 BatteryControl + | Stack used (prev) : 00000042 00000014 + | + function block : 00000004 00000002 + <-Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + | Stack used : 00000046 00000016 + + + ->Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + CSTACK RSTACK + | Stack used (prev) : 00000036 0000000E + 01 Discharge + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + <-Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + | Stack used : 00000036 00000010 + + + ->Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + CSTACK RSTACK + | Stack used (prev) : 00000036 0000000E + 02 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 01 Sleep + | Stack used (prev) : 00000036 00000010 + | + function block : 00000000 00000002 + <-Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + | Stack used : 00000036 00000012 + + + ->Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + CSTACK RSTACK + | Stack used (prev) : 00000036 0000000E + 02 DisableBatteries + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 02 PWM_Stop + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 02 ADC_Wait + | Stack used (prev) : 00000036 0000000E + | + function block : 00000000 00000002 + | Already listed + 01 Error + | Stack used (prev) : 00000036 00000010 + | + function block : 00000000 00000002 + <-Sub-tree of type: Indirectly called function tree that does not make + : indirect calls (Is not an interrupt and is not flagged + : as not overlayable) + | Stack used : 00000036 00000012 + + + ->Sub-tree of type: Function tree that makes indirect calls + CSTACK RSTACK + | Stack used (prev) : 00000052 0000001C + 01 main + | Stack used (prev) : 00000052 0000001C + | + function block : 00000002 00000002 + <-Sub-tree of type: Function tree that makes indirect calls + | Stack used : 00000054 0000001E + + + ->Sub-tree of type: Function tree + CSTACK RSTACK + | Stack used (prev) : 00000054 0000001E + 01 __low_level_init + | Stack used (prev) : 00000054 0000001E + | + function block : 00000000 00000002 + <-Sub-tree of type: Function tree + | Stack used : 00000054 00000020 + + + ->Sub-tree of type: Function tree + CSTACK RSTACK + | Stack used (prev) : 00000054 00000020 + 02 __flashcpy + | Stack used (prev) : 00000054 00000020 + | + function block : 00000000 00000002 + 02 __memclr + | Stack used (prev) : 00000054 00000020 + | + function block : 00000000 00000002 + 01 __segment_init + | Stack used (prev) : 00000054 00000022 + | + function block : 00000000 00000002 + <-Sub-tree of type: Function tree + | Stack used : 00000054 00000024 + + + + + **************************************** + * * + * SEGMENTS IN ADDRESS ORDER * + * * + **************************************** + + +SEGMENT SPACE START ADDRESS END ADDRESS SIZE TYPE ALIGN +======= ===== ============= =========== ==== ==== ===== +INTVEC CODE 00000000 - 0000001D 1E com 1 +?FILL1 CODE 0000001E - 00000025 8 rel 0 +NEAR_F CODE 00000026 - 00000043 1E rel 0 +INITTAB CODE 00000044 - 0000004F C rel 0 +CODE CODE 00000050 - 000011F9 11AA rel 1 +NEAR_ID CODE 000011FA - 0000126D 74 rel 0 +ABSOLUTE DATA 0000001C rel 0 + DATA 0000001D + DATA 0000001E + DATA 0000001F + DATA 00000020 - 00000020 1 + DATA 00000023 - 00000027 5 + DATA 0000002D - 0000002F 3 + DATA 00000032 - 00000033 2 + DATA 00000035 - 00000035 1 + DATA 00000037 - 0000003B 5 + DATA 00000041 - 00000041 1 + DATA 00000044 - 00000044 1 + DATA 00000046 - 0000004D 8 + DATA 0000004F - 00000050 2 + DATA 00000053 - 00000055 3 + DATA 00000059 - 00000059 1 +CSTACK DATA 00000060 - 0000009F 40 dse 0 +RSTACK DATA 000000A0 - 000000CF 30 dse 0 +NEAR_I DATA 000000D0 - 00000143 74 rel 0 +NEAR_Z DATA 00000144 - 00000196 53 rel 0 +EEPROM_I XDATA 00000000 - 00000082 83 rel 0 + + **************************************** + * * + * END OF CROSS REFERENCE * + * * + **************************************** + + 4 710 bytes of CODE memory (+ 8 range fill ) + 311 bytes of DATA memory (+ 33 absolute ) + 131 bytes of XDATA memory + +Errors: none +Warnings: none + diff --git a/BaseTinyFirmware/IAR/Release/List/NIMHcharge.lst b/BaseTinyFirmware/IAR/Release/List/NIMHcharge.lst new file mode 100644 index 0000000..fefe96f --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/NIMHcharge.lst @@ -0,0 +1,389 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\NI # +# MHcharge.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIM # +# Hcharge.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Charge state function for NiMH batteries + 6 * + 7 * Contains the charge state function, in which the NiMH charging + 8 * algorithm is, plus the associated functions. + 9 * + 10 * \par Application note: + 11 * AVR463: Charging NiMH Batteries with BC100 \n + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2255 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $ + 26 * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 #include + 30 + 31 #include "enums.h" + 32 #include "structs.h" + 33 + 34 #include "battery.h" + 35 #include "charge.h" + 36 #include "chargefunc.h" + 37 #include "main.h" + 38 #include "menu.h" + 39 #include "NIMHspecs.h" + 40 #include "PWM.h" + 41 #include "time.h" + 42 + 43 #ifndef NIMH + 44 #error NIMH not defined in main.h! + 45 #endif // NIMH + 46 + 47 + 48 //****************************************************************************** + 49 // Functions + 50 //****************************************************************************** + 51 /*! \brief Controls the charging. + 52 * + 53 * This function contains the charging algorithm itself, divided into stages.\n + 54 * For each stage the PWM may be started/stopped, and the timer, + 55 * halt-requirements and charge parameters may be set.\n + 56 * The charging functions return whatever state is next, and as long as no + 57 * errors occur this is the next charging stage. + 58 * + 59 * \note If more stages are needed simply define more states in menu.h, include + 60 * them in \ref menu_state[] in menu.c, then add the cases to this function. + 61 * + 62 * \note This algorithm is for NiMH batteries. + 63 */ + + \ In segment CODE, align 2, keep-with-next + 64 unsigned char Charge(unsigned char inp) + \ Charge: + 65 { + 66 unsigned char NextState; + 67 + 68 switch (CurrentState) { + \ 00000000 9100.... LDS R16, CurrentState + \ 00000004 510E SUBI R16, 30 + \ 00000006 F049 BREQ ??Charge_0 + \ 00000008 5104 SUBI R16, 20 + \ 0000000A F149 BREQ ??Charge_1 + \ 0000000C 500A SUBI R16, 10 + \ 0000000E F409 BRNE $+2+2 + \ 00000010 C04A RJMP ??Charge_2 + \ 00000012 500A SUBI R16, 10 + \ 00000014 F409 BRNE $+2+2 + \ 00000016 C05E RJMP ??Charge_3 + \ 00000018 C077 RJMP ??Charge_4 + 69 // First stage is a prequalification. Attempt to charge battery to 1 V, + 70 // using a 0.1 C current, within 2 minutes. + 71 // If this fails, the battery is likely damaged. + 72 // If it succeeds, start a fast charge. + 73 case ST_PREQUAL: + 74 + 75 // Set up charge current and next state. + 76 ChargeParameters.Current = BattData.Capacity / 10; + \ ??Charge_0: + \ 0000001A .... LDI R30, LOW(BattData) + \ 0000001C .... LDI R31, (BattData) >> 8 + \ 0000001E 8104 LDD R16, Z+4 + \ 00000020 8115 LDD R17, Z+5 + \ 00000022 E04A LDI R20, 10 + \ 00000024 E050 LDI R21, 0 + \ 00000026 .... RCALL ?US_DIVMOD_L02 + \ 00000028 .... LDI R30, LOW(ChargeParameters) + \ 0000002A .... LDI R31, (ChargeParameters) >> 8 + \ 0000002C 8302 STD Z+2, R16 + \ 0000002E 8313 STD Z+3, R17 + 77 ChargeParameters.NextState = ST_FASTCHARGE; + \ 00000030 E302 LDI R16, 50 + \ 00000032 8304 STD Z+4, R16 + 78 + 79 // Halt charge on voltage limit or timeout. + 80 // Timeout means battery exhaustion. + 81 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + 82 HALT_FLAG_EXHAUSTION); + \ 00000034 .... LDI R30, LOW(HaltParameters) + \ 00000036 .... LDI R31, (HaltParameters) >> 8 + \ 00000038 8300 ST Z, R16 + 83 + 84 // Set up voltage limit and temperature limits. + 85 HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + \ 0000003A EB08 LDI R16, 184 + \ 0000003C E01B LDI R17, 11 + \ 0000003E 8303 STD Z+3, R16 + \ 00000040 8314 STD Z+4, R17 + 86 HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + \ 00000042 E005 LDI R16, 5 + \ 00000044 E010 LDI R17, 0 + \ 00000046 8701 STD Z+9, R16 + \ 00000048 8712 STD Z+10, R17 + 87 HaltParameters.TemperatureMax = 35; + \ 0000004A E203 LDI R16, 35 + \ 0000004C 8307 STD Z+7, R16 + \ 0000004E 8710 STD Z+8, R17 + 88 + 89 // Reset temperature measurement for HaltNow(). + 90 HaltParameters.LastNTC = 0; + \ 00000050 8717 STD Z+15, R17 + \ 00000052 8B10 STD Z+16, R17 + 91 + 92 // Start PWM and charge timer before calling the charge function. + 93 PWM_Start(); + \ 00000054 .... RCALL PWM_Start + 94 Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + \ 00000056 E040 LDI R20, 0 + \ 00000058 E010 LDI R17, 0 + \ 0000005A E022 LDI R18, 2 + \ 0000005C C037 RJMP ??Charge_5 + 95 + 96 // Call charge function, get next state. + 97 NextState = ConstantCurrent(); + 98 break; + 99 + 100 + 101 // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours, + 102 // until either rate of temperature increase or voltage reaches limit, or + 103 // the voltage drops sufficiently. + 104 // Timeout doesn't mean battery exhaustion now. + 105 case ST_FASTCHARGE: + 106 + 107 // Set up charge current and next state. + 108 ChargeParameters.Current = BattData.Capacity; + \ ??Charge_1: + \ 0000005E .... LDI R18, LOW(BattData) + \ 00000060 .... LDI R19, (BattData) >> 8 + \ 00000062 01F9 MOVW R31:R30, R19:R18 + \ 00000064 8104 LDD R16, Z+4 + \ 00000066 8115 LDD R17, Z+5 + \ 00000068 .... LDI R30, LOW(ChargeParameters) + \ 0000006A .... LDI R31, (ChargeParameters) >> 8 + \ 0000006C 8302 STD Z+2, R16 + \ 0000006E 8313 STD Z+3, R17 + 109 ChargeParameters.NextState = ST_LOWRATECHARGE; + \ 00000070 E30C LDI R16, 60 + \ 00000072 8304 STD Z+4, R16 + 110 + 111 // Halt charge on voltage limit, timeout, voltage drop or rate of + 112 // temperature increase. + 113 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + 114 HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE); + \ 00000074 .... LDI R30, LOW(HaltParameters) + \ 00000076 .... LDI R31, (HaltParameters) >> 8 + \ 00000078 E10B LDI R16, 27 + \ 0000007A 8300 ST Z, R16 + 115 + 116 // Set up limits for voltage, voltage drop, temperature and rate of + 117 // temperature increase (1 degree C per minute). + 118 HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + \ 0000007C EC00 LDI R16, 192 + \ 0000007E E112 LDI R17, 18 + \ 00000080 8303 STD Z+3, R16 + \ 00000082 8314 STD Z+4, R17 + 119 HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP; + \ 00000084 E20D LDI R16, 45 + \ 00000086 E010 LDI R17, 0 + \ 00000088 8301 STD Z+1, R16 + \ 0000008A 8312 STD Z+2, R17 + 120 HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + \ 0000008C E302 LDI R16, 50 + \ 0000008E 8307 STD Z+7, R16 + \ 00000090 8710 STD Z+8, R17 + 121 HaltParameters.TemperatureRise = 1; + \ 00000092 E001 LDI R16, 1 + \ 00000094 8703 STD Z+11, R16 + \ 00000096 8714 STD Z+12, R17 + 122 + 123 // Reset maximum voltage measurement for HaltNow(). + 124 HaltParameters.VBATMax = 0; + \ 00000098 8715 STD Z+13, R17 + \ 0000009A 8716 STD Z+14, R17 + 125 + 126 // Start timer, PWM should still be running. + 127 Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0); + \ 0000009C E040 LDI R20, 0 + \ 0000009E 01F9 MOVW R31:R30, R19:R18 + \ 000000A0 8520 LDD R18, Z+8 + \ 000000A2 8531 LDD R19, Z+9 + \ 000000A4 C015 RJMP ??Charge_6 + 128 + 129 // Call charge function, get next state. + 130 NextState = ConstantCurrent(); + 131 break; + 132 + 133 + 134 // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes, + 135 // until either rate of temperature increase or voltage reaches limit. + 136 case ST_LOWRATECHARGE: + 137 + 138 // Set up charge current and next state. + 139 ChargeParameters.Current = BattData.Capacity / 10; + \ ??Charge_2: + \ 000000A6 .... LDI R30, LOW(BattData) + \ 000000A8 .... LDI R31, (BattData) >> 8 + \ 000000AA 8104 LDD R16, Z+4 + \ 000000AC 8115 LDD R17, Z+5 + \ 000000AE E04A LDI R20, 10 + \ 000000B0 E050 LDI R21, 0 + \ 000000B2 .... RCALL ?US_DIVMOD_L02 + \ 000000B4 .... LDI R30, LOW(ChargeParameters) + \ 000000B6 .... LDI R31, (ChargeParameters) >> 8 + \ 000000B8 8302 STD Z+2, R16 + \ 000000BA 8313 STD Z+3, R17 + 140 ChargeParameters.NextState = ST_ENDCHARGE; + \ 000000BC E406 LDI R16, 70 + \ 000000BE 8304 STD Z+4, R16 + 141 + 142 // Halt charge on voltage limit, timeout or temperature rise. + 143 // Use the same requirements as during the last stage (ST_FASTCHARGE). + 144 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | + 145 HALT_TEMPERATURE_RISE); + \ 000000C0 E10A LDI R16, 26 + \ 000000C2 9300.... STS HaltParameters, R16 + 146 + 147 // Start timer, 30 minutes. + 148 Time_Set(TIMER_CHG, 30, 0, 0); + \ 000000C6 E040 LDI R20, 0 + \ 000000C8 E010 LDI R17, 0 + \ 000000CA E12E LDI R18, 30 + \ ??Charge_5: + \ 000000CC E030 LDI R19, 0 + \ 000000CE E001 LDI R16, 1 + \ ??Charge_6: + \ 000000D0 .... RCALL Time_Set + 149 + 150 // Call charge function, get next state. + 151 NextState = ConstantCurrent(); + \ 000000D2 .... RJMP ConstantCurrent + 152 break; + 153 + 154 + 155 // Charging is done! + 156 case ST_ENDCHARGE: + 157 + 158 // Stop the PWM output and flag battery as charged. + 159 PWM_Stop(); + \ ??Charge_3: + \ 000000D4 .... RCALL PWM_Stop + 160 BattData.Charged = TRUE; + \ 000000D6 .... LDI R30, LOW(BattData) + \ 000000D8 .... LDI R31, (BattData) >> 8 + \ 000000DA 8100 LD R16, Z + \ 000000DC 6002 ORI R16, 0x02 + \ 000000DE 8300 ST Z, R16 + 161 + 162 // If the other battery is enabled go to ST_BATCON, otherwise + 163 // go to ST_SLEEP. + 164 if (BattControl[(BattActive+1)%2].Enabled) { + \ 000000E0 9100.... LDS R16, BattActive + \ 000000E4 E010 LDI R17, 0 + \ 000000E6 5F0F SUBI R16, 255 + \ 000000E8 4F1F SBCI R17, 255 + \ 000000EA E042 LDI R20, 2 + \ 000000EC E050 LDI R21, 0 + \ 000000EE .... RCALL ?SS_DIVMOD_L02 + \ 000000F0 .... LDI R18, LOW(BattControl) + \ 000000F2 .... LDI R19, (BattControl) >> 8 + \ 000000F4 0F24 ADD R18, R20 + \ 000000F6 1F35 ADC R19, R21 + \ 000000F8 01A9 MOVW R21:R20, R19:R18 + \ 000000FA .... RCALL __eeget8_16 + \ 000000FC 7001 ANDI R16, 0x01 + \ 000000FE F011 BREQ ??Charge_7 + 165 NextState = ST_BATCON; + \ 00000100 E104 LDI R16, 20 + \ 00000102 9508 RET + 166 } else { + 167 NextState = ST_SLEEP; + \ ??Charge_7: + \ 00000104 E208 LDI R16, 40 + \ 00000106 9508 RET + 168 } + 169 break; + 170 + 171 + 172 default: // Shouldn't end up here. Reinitialize for safety. + 173 NextState = ST_INIT; + \ ??Charge_4: + \ 00000108 E00A LDI R16, 10 + 174 break; + 175 } + 176 + 177 // Return the next state to main(). + 178 return(NextState); + \ 0000010A 9508 RET + 179 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + Charge 2 4 + -> PWM_Start 2 2 + -> Time_Set 2 2 + -> ConstantCurrent 2 2 + -> Time_Set 2 2 + -> ConstantCurrent 2 2 + -> Time_Set 2 2 + -> ConstantCurrent 2 2 + -> PWM_Stop 2 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + Charge 268 + + + 268 bytes in segment CODE + + 268 bytes of CODE memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/NIMHcharge.s90 b/BaseTinyFirmware/IAR/Release/List/NIMHcharge.s90 new file mode 100644 index 0000000..a9ad11d --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/NIMHcharge.s90 @@ -0,0 +1,405 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\N / +// IMHcharge.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME NIMHcharge + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?SS_DIVMOD_L02 + EXTERN ?US_DIVMOD_L02 + EXTERN __eeget8_16 + + PUBLIC Charge + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN PWM_Start + EXTERN Time_Set + EXTERN ConstantCurrent + EXTERN PWM_Stop + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + EXTERN ChargeParameters + EXTERN CurrentState + EXTERN HaltParameters + +// C:\home\kevin\pub\src\bc100\IAR\NIMHcharge.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Charge state function for NiMH batteries +// 6 * +// 7 * Contains the charge state function, in which the NiMH charging +// 8 * algorithm is, plus the associated functions. +// 9 * +// 10 * \par Application note: +// 11 * AVR463: Charging NiMH Batteries with BC100 \n +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2255 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr463_Charging_NiMH_Batteries_with_BC100/trunk/code/IAR/NIMHcharge.c $ +// 26 * $Date: 2007-08-09 14:47:58 +0200 (to, 09 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 #include +// 30 +// 31 #include "enums.h" +// 32 #include "structs.h" +// 33 +// 34 #include "battery.h" +// 35 #include "charge.h" +// 36 #include "chargefunc.h" +// 37 #include "main.h" +// 38 #include "menu.h" +// 39 #include "NIMHspecs.h" +// 40 #include "PWM.h" +// 41 #include "time.h" +// 42 +// 43 #ifndef NIMH +// 44 #error NIMH not defined in main.h! +// 45 #endif // NIMH +// 46 +// 47 +// 48 //****************************************************************************** +// 49 // Functions +// 50 //****************************************************************************** +// 51 /*! \brief Controls the charging. +// 52 * +// 53 * This function contains the charging algorithm itself, divided into stages.\n +// 54 * For each stage the PWM may be started/stopped, and the timer, +// 55 * halt-requirements and charge parameters may be set.\n +// 56 * The charging functions return whatever state is next, and as long as no +// 57 * errors occur this is the next charging stage. +// 58 * +// 59 * \note If more stages are needed simply define more states in menu.h, include +// 60 * them in \ref menu_state[] in menu.c, then add the cases to this function. +// 61 * +// 62 * \note This algorithm is for NiMH batteries. +// 63 */ + + RSEG CODE:CODE:NOROOT(1) +// 64 unsigned char Charge(unsigned char inp) +Charge: +// 65 { +// 66 unsigned char NextState; +// 67 +// 68 switch (CurrentState) { + LDS R16, CurrentState + SUBI R16, 30 + BREQ ??Charge_0 + SUBI R16, 20 + BREQ ??Charge_1 + SUBI R16, 10 + BRNE $+2+2 + RJMP ??Charge_2 + SUBI R16, 10 + BRNE $+2+2 + RJMP ??Charge_3 + RJMP ??Charge_4 +// 69 // First stage is a prequalification. Attempt to charge battery to 1 V, +// 70 // using a 0.1 C current, within 2 minutes. +// 71 // If this fails, the battery is likely damaged. +// 72 // If it succeeds, start a fast charge. +// 73 case ST_PREQUAL: +// 74 +// 75 // Set up charge current and next state. +// 76 ChargeParameters.Current = BattData.Capacity / 10; +??Charge_0: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R20, 10 + LDI R21, 0 + RCALL ?US_DIVMOD_L02 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 77 ChargeParameters.NextState = ST_FASTCHARGE; + LDI R16, 50 + STD Z+4, R16 +// 78 +// 79 // Halt charge on voltage limit or timeout. +// 80 // Timeout means battery exhaustion. +// 81 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | +// 82 HALT_FLAG_EXHAUSTION); + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + ST Z, R16 +// 83 +// 84 // Set up voltage limit and temperature limits. +// 85 HaltParameters.VoltageMax = BAT_VOLTAGE_PREQUAL; + LDI R16, 184 + LDI R17, 11 + STD Z+3, R16 + STD Z+4, R17 +// 86 HaltParameters.TemperatureMin = BAT_TEMPERATURE_MIN; + LDI R16, 5 + LDI R17, 0 + STD Z+9, R16 + STD Z+10, R17 +// 87 HaltParameters.TemperatureMax = 35; + LDI R16, 35 + STD Z+7, R16 + STD Z+8, R17 +// 88 +// 89 // Reset temperature measurement for HaltNow(). +// 90 HaltParameters.LastNTC = 0; + STD Z+15, R17 + STD Z+16, R17 +// 91 +// 92 // Start PWM and charge timer before calling the charge function. +// 93 PWM_Start(); + RCALL PWM_Start +// 94 Time_Set(TIMER_CHG, BAT_TIME_PREQUAL, 0, 0); + LDI R20, 0 + LDI R17, 0 + LDI R18, 2 + RJMP ??Charge_5 +// 95 +// 96 // Call charge function, get next state. +// 97 NextState = ConstantCurrent(); +// 98 break; +// 99 +// 100 +// 101 // Second stage is a fast charge. Charge at 1.0 C for at most 1.5 hours, +// 102 // until either rate of temperature increase or voltage reaches limit, or +// 103 // the voltage drops sufficiently. +// 104 // Timeout doesn't mean battery exhaustion now. +// 105 case ST_FASTCHARGE: +// 106 +// 107 // Set up charge current and next state. +// 108 ChargeParameters.Current = BattData.Capacity; +??Charge_1: + LDI R18, LOW(BattData) + LDI R19, (BattData) >> 8 + MOVW R31:R30, R19:R18 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 109 ChargeParameters.NextState = ST_LOWRATECHARGE; + LDI R16, 60 + STD Z+4, R16 +// 110 +// 111 // Halt charge on voltage limit, timeout, voltage drop or rate of +// 112 // temperature increase. +// 113 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | +// 114 HALT_VOLTAGE_DROP | HALT_TEMPERATURE_RISE); + LDI R30, LOW(HaltParameters) + LDI R31, (HaltParameters) >> 8 + LDI R16, 27 + ST Z, R16 +// 115 +// 116 // Set up limits for voltage, voltage drop, temperature and rate of +// 117 // temperature increase (1 degree C per minute). +// 118 HaltParameters.VoltageMax = BAT_VOLTAGE_MAX; + LDI R16, 192 + LDI R17, 18 + STD Z+3, R16 + STD Z+4, R17 +// 119 HaltParameters.VoltageDrop = BAT_VOLTAGE_DROP; + LDI R16, 45 + LDI R17, 0 + STD Z+1, R16 + STD Z+2, R17 +// 120 HaltParameters.TemperatureMax = BAT_TEMPERATURE_MAX; + LDI R16, 50 + STD Z+7, R16 + STD Z+8, R17 +// 121 HaltParameters.TemperatureRise = 1; + LDI R16, 1 + STD Z+11, R16 + STD Z+12, R17 +// 122 +// 123 // Reset maximum voltage measurement for HaltNow(). +// 124 HaltParameters.VBATMax = 0; + STD Z+13, R17 + STD Z+14, R17 +// 125 +// 126 // Start timer, PWM should still be running. +// 127 Time_Set(TIMER_CHG, BattData.MaxTime, 0, 0); + LDI R20, 0 + MOVW R31:R30, R19:R18 + LDD R18, Z+8 + LDD R19, Z+9 + RJMP ??Charge_6 +// 128 +// 129 // Call charge function, get next state. +// 130 NextState = ConstantCurrent(); +// 131 break; +// 132 +// 133 +// 134 // Last stage is a trickle charge. Charge at 0.1 C for at most 30 minutes, +// 135 // until either rate of temperature increase or voltage reaches limit. +// 136 case ST_LOWRATECHARGE: +// 137 +// 138 // Set up charge current and next state. +// 139 ChargeParameters.Current = BattData.Capacity / 10; +??Charge_2: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + LDI R20, 10 + LDI R21, 0 + RCALL ?US_DIVMOD_L02 + LDI R30, LOW(ChargeParameters) + LDI R31, (ChargeParameters) >> 8 + STD Z+2, R16 + STD Z+3, R17 +// 140 ChargeParameters.NextState = ST_ENDCHARGE; + LDI R16, 70 + STD Z+4, R16 +// 141 +// 142 // Halt charge on voltage limit, timeout or temperature rise. +// 143 // Use the same requirements as during the last stage (ST_FASTCHARGE). +// 144 HaltParameters.HaltFlags = (HALT_VOLTAGE_MAX | HALT_TIME | +// 145 HALT_TEMPERATURE_RISE); + LDI R16, 26 + STS HaltParameters, R16 +// 146 +// 147 // Start timer, 30 minutes. +// 148 Time_Set(TIMER_CHG, 30, 0, 0); + LDI R20, 0 + LDI R17, 0 + LDI R18, 30 +??Charge_5: + LDI R19, 0 + LDI R16, 1 +??Charge_6: + RCALL Time_Set +// 149 +// 150 // Call charge function, get next state. +// 151 NextState = ConstantCurrent(); + RJMP ConstantCurrent +// 152 break; +// 153 +// 154 +// 155 // Charging is done! +// 156 case ST_ENDCHARGE: +// 157 +// 158 // Stop the PWM output and flag battery as charged. +// 159 PWM_Stop(); +??Charge_3: + RCALL PWM_Stop +// 160 BattData.Charged = TRUE; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LD R16, Z + ORI R16, 0x02 + ST Z, R16 +// 161 +// 162 // If the other battery is enabled go to ST_BATCON, otherwise +// 163 // go to ST_SLEEP. +// 164 if (BattControl[(BattActive+1)%2].Enabled) { + LDS R16, BattActive + LDI R17, 0 + SUBI R16, 255 + SBCI R17, 255 + LDI R20, 2 + LDI R21, 0 + RCALL ?SS_DIVMOD_L02 + LDI R18, LOW(BattControl) + LDI R19, (BattControl) >> 8 + ADD R18, R20 + ADC R19, R21 + MOVW R21:R20, R19:R18 + RCALL __eeget8_16 + ANDI R16, 0x01 + BREQ ??Charge_7 +// 165 NextState = ST_BATCON; + LDI R16, 20 + RET +// 166 } else { +// 167 NextState = ST_SLEEP; +??Charge_7: + LDI R16, 40 + RET +// 168 } +// 169 break; +// 170 +// 171 +// 172 default: // Shouldn't end up here. Reinitialize for safety. +// 173 NextState = ST_INIT; +??Charge_4: + LDI R16, 10 +// 174 break; +// 175 } +// 176 +// 177 // Return the next state to main(). +// 178 return(NextState); + RET +// 179 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// +// 268 bytes in segment CODE +// +// 268 bytes of CODE memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/OWI.lst b/BaseTinyFirmware/IAR/Release/List/OWI.lst new file mode 100644 index 0000000..7eab274 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/OWI.lst @@ -0,0 +1,1082 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:36 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\OWI.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\OWI.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\OW # +# I.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI # +# .r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\OWI.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ******************************************************************** + 3 * + 4 * \brief + 5 * Functions for 1-Wire(R) bus communication + 6 * + 7 * High level functions for transmission of full bytes on the 1-Wire(R) + 8 * bus and implementations of ROM commands.\n + 9 * Polled software only implementation of the basic bit-level signalling + 10 * in the 1-Wire(R) protocol.\n + 11 * Includes functions for computing and checking CRC8 & 16 values of data + 12 * sets, and of 64 bit ROM identifiers. + 13 * Supported devices: All AVRs. + 14 * + 15 * \par Application Note: + 16 * AVR458: Charging Li-Ion Batteries with BC100\n + 17 * AVR463: Charging NiMH Batteries with BC100\n + 18 * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. + 19 * + 20 * \par Documentation: + 21 * For comprehensive code documentation, supported compilers, compiler + 22 * settings and supported devices see readme.html + 23 * + 24 * \author + 25 * Atmel Corporation: http://www.atmel.com \n + 26 * Support email: avr@atmel.com \n + 27 * Original author: \n + 28 * + 29 * $Name$ + 30 * $Revision: 2299 $ + 31 * $RCSfile$ + 32 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ + 33 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 34 ****************************************************************************/ + 35 + 36 #include + + \ In segment ABSOLUTE, at 0x3b + \ volatile __io _A_PORTA + \ _A_PORTA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x3a + \ volatile __io _A_DDRA + \ _A_DDRA: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x39 + \ volatile __io _A_PINA + \ _A_PINA: + \ 00000000 DS 1 + 37 #include + 38 + 39 #include "OWI.h" + 40 + 41 + 42 //****************************************************************************** + 43 // Functions + 44 //****************************************************************************** + 45 /*! \brief Initialization of the one wire bus(es). (Software only driver) + 46 * + 47 * This function initializes the 1-Wire bus(es) by releasing it and + 48 * waiting until any presence signals are finished. + 49 * + 50 * \param pins A bitmask of the buses to initialize. + 51 */ + + \ In segment CODE, align 2, keep-with-next + 52 void OWI_Init(unsigned char pins){ + \ OWI_Init: + 53 OWI_RELEASE_BUS(pins); + \ 00000000 9500 COM R16 + \ 00000002 B31A IN R17, 0x1A + \ 00000004 2310 AND R17, R16 + \ 00000006 BB1A OUT 0x1A, R17 + \ 00000008 B31B IN R17, 0x1B + \ 0000000A 2310 AND R17, R16 + \ 0000000C BB1B OUT 0x1B, R17 + 54 // The first rising edge can be interpreted by a slave as the end of a + 55 // Reset-pulse. Delay for the required reset recovery time (H) to be + 56 // sure that the real reset is interpreted correctly. + 57 __delay_cycles(OWI_DELAY_H_STD_MODE); + \ 0000000E EB0C LDI R16, 188 + \ 00000010 E013 LDI R17, 3 + \ 00000012 5001 SUBI R16, 1 + \ 00000014 4010 SBCI R17, 0 + \ 00000016 F7E9 BRNE $-4 + \ 00000018 C000 RJMP $+2 + 58 } + \ 0000001A 9508 RET + \ 0000001C REQUIRE _A_PORTA + \ 0000001C REQUIRE _A_DDRA + 59 + 60 + 61 /*! \brief Write a '1' bit to the bus(es). (Software only driver) + 62 * + 63 * Generates the waveform for transmission of a '1' bit on the 1-Wire + 64 * bus. + 65 * + 66 * \param pins A bitmask of the buses to write to. + 67 */ + + \ In segment CODE, align 2, keep-with-next + 68 void OWI_WriteBit1(unsigned char pins){ + \ OWI_WriteBit1: + 69 unsigned char intState; + 70 + 71 // Disable interrupts. + 72 intState = __save_interrupt(); + \ 00000000 B71F IN R17, 0x3F + 73 __disable_interrupt(); + \ 00000002 94F8 CLI + 74 + 75 // Drive bus low and delay. + 76 OWI_PULL_BUS_LOW(pins); + \ 00000004 B32A IN R18, 0x1A + \ 00000006 2B20 OR R18, R16 + \ 00000008 BB2A OUT 0x1A, R18 + \ 0000000A 9500 COM R16 + \ 0000000C B32B IN R18, 0x1B + \ 0000000E 2320 AND R18, R16 + \ 00000010 BB2B OUT 0x1B, R18 + 77 __delay_cycles(OWI_DELAY_A_STD_MODE); + \ 00000012 E02B LDI R18, 11 + \ 00000014 952A DEC R18 + \ 00000016 F7F1 BRNE $-2 + \ 00000018 C000 RJMP $+2 + 78 + 79 // Release bus and delay. + 80 OWI_RELEASE_BUS(pins); + \ 0000001A B32A IN R18, 0x1A + \ 0000001C 2320 AND R18, R16 + \ 0000001E BB2A OUT 0x1A, R18 + \ 00000020 B32B IN R18, 0x1B + \ 00000022 2320 AND R18, R16 + \ 00000024 BB2B OUT 0x1B, R18 + 81 __delay_cycles(OWI_DELAY_B_STD_MODE); + \ 00000026 EA06 LDI R16, 166 + \ 00000028 950A DEC R16 + \ 0000002A F7F1 BRNE $-2 + \ 0000002C 0000 NOP + 82 + 83 // Restore interrupts. + 84 __restore_interrupt(intState); + \ 0000002E BF1F OUT 0x3F, R17 + 85 } + \ 00000030 9508 RET + \ 00000032 REQUIRE _A_PORTA + \ 00000032 REQUIRE _A_DDRA + 86 + 87 /*! \brief Write a '0' to the bus(es). (Software only driver) + 88 * + 89 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) + 90 * bus. + 91 * + 92 * \param pins A bitmask of the buses to write to. + 93 */ + + \ In segment CODE, align 2, keep-with-next + 94 void OWI_WriteBit0(unsigned char pins) + \ OWI_WriteBit0: + 95 { + 96 unsigned char intState; + 97 + 98 // Disable interrupts. + 99 intState = __save_interrupt(); + \ 00000000 B71F IN R17, 0x3F + 100 __disable_interrupt(); + \ 00000002 94F8 CLI + 101 + 102 // Drive bus low and delay. + 103 OWI_PULL_BUS_LOW(pins); + \ 00000004 B32A IN R18, 0x1A + \ 00000006 2B20 OR R18, R16 + \ 00000008 BB2A OUT 0x1A, R18 + \ 0000000A 9500 COM R16 + \ 0000000C B32B IN R18, 0x1B + \ 0000000E 2320 AND R18, R16 + \ 00000010 BB2B OUT 0x1B, R18 + 104 __delay_cycles(OWI_DELAY_C_STD_MODE); + \ 00000012 E92B LDI R18, 155 + \ 00000014 952A DEC R18 + \ 00000016 F7F1 BRNE $-2 + \ 00000018 C000 RJMP $+2 + 105 + 106 // Release bus and delay. + 107 OWI_RELEASE_BUS(pins); + \ 0000001A B32A IN R18, 0x1A + \ 0000001C 2320 AND R18, R16 + \ 0000001E BB2A OUT 0x1A, R18 + \ 00000020 B32B IN R18, 0x1B + \ 00000022 2320 AND R18, R16 + \ 00000024 BB2B OUT 0x1B, R18 + 108 __delay_cycles(OWI_DELAY_D_STD_MODE); + \ 00000026 E106 LDI R16, 22 + \ 00000028 950A DEC R16 + \ 0000002A F7F1 BRNE $-2 + \ 0000002C 0000 NOP + 109 + 110 // Restore interrupts. + 111 __restore_interrupt(intState); + \ 0000002E BF1F OUT 0x3F, R17 + 112 } + \ 00000030 9508 RET + \ 00000032 REQUIRE _A_PORTA + \ 00000032 REQUIRE _A_DDRA + 113 + 114 /*! \brief Read a bit from the bus(es). (Software only driver) + 115 * + 116 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). + 117 * + 118 * \param pins A bitmask of the bus(es) to read from. + 119 * + 120 * \return A bitmask of the buses where a '1' was read. + 121 */ + + \ In segment CODE, align 2, keep-with-next + 122 unsigned char OWI_ReadBit(unsigned char pins) + \ OWI_ReadBit: + 123 { + 124 unsigned char intState; + 125 unsigned char bitsRead; + 126 + 127 // Disable interrupts. + 128 intState = __save_interrupt(); + \ 00000000 B72F IN R18, 0x3F + 129 __disable_interrupt(); + \ 00000002 94F8 CLI + 130 + 131 // Drive bus low and delay. + 132 OWI_PULL_BUS_LOW(pins); + \ 00000004 B31A IN R17, 0x1A + \ 00000006 2B10 OR R17, R16 + \ 00000008 BB1A OUT 0x1A, R17 + \ 0000000A 2F10 MOV R17, R16 + \ 0000000C 9510 COM R17 + \ 0000000E B33B IN R19, 0x1B + \ 00000010 2331 AND R19, R17 + \ 00000012 BB3B OUT 0x1B, R19 + 133 __delay_cycles(OWI_DELAY_A_STD_MODE); + \ 00000014 E03B LDI R19, 11 + \ 00000016 953A DEC R19 + \ 00000018 F7F1 BRNE $-2 + \ 0000001A C000 RJMP $+2 + 134 + 135 // Release bus and delay. + 136 OWI_RELEASE_BUS(pins); + \ 0000001C B33A IN R19, 0x1A + \ 0000001E 2331 AND R19, R17 + \ 00000020 BB3A OUT 0x1A, R19 + \ 00000022 B33B IN R19, 0x1B + \ 00000024 2331 AND R19, R17 + \ 00000026 BB3B OUT 0x1B, R19 + 137 __delay_cycles(OWI_DELAY_E_STD_MODE); + \ 00000028 E113 LDI R17, 19 + \ 0000002A 951A DEC R17 + \ 0000002C F7F1 BRNE $-2 + \ 0000002E C000 RJMP $+2 + 138 + 139 // Sample bus and delay. + 140 bitsRead = OWI_PIN & pins; + \ 00000030 B319 IN R17, 0x19 + \ 00000032 2310 AND R17, R16 + 141 __delay_cycles(OWI_DELAY_F_STD_MODE); + \ 00000034 E80E LDI R16, 142 + \ 00000036 950A DEC R16 + \ 00000038 F7F1 BRNE $-2 + \ 0000003A 0000 NOP + 142 + 143 // Restore interrupts. + 144 __restore_interrupt(intState); + \ 0000003C BF2F OUT 0x3F, R18 + 145 + 146 return bitsRead; + \ 0000003E 2F01 MOV R16, R17 + \ 00000040 9508 RET + \ 00000042 REQUIRE _A_PORTA + \ 00000042 REQUIRE _A_DDRA + \ 00000042 REQUIRE _A_PINA + 147 } + 148 + 149 + 150 /*! \brief Send a Reset signal and listen for Presence signal. (software + 151 * only driver) + 152 * + 153 * Generates the waveform for transmission of a Reset pulse on the + 154 * 1-Wire(R) bus and listens for presence signals. + 155 * + 156 * \param pins A bitmask of the buses to send the Reset signal on. + 157 * + 158 * \return A bitmask of the buses where a presence signal was detected. + 159 */ + + \ In segment CODE, align 2, keep-with-next + 160 unsigned char OWI_DetectPresence(unsigned char pins) + \ OWI_DetectPresence: + 161 { + 162 unsigned char intState; + 163 unsigned char presenceDetected; + 164 + 165 // Disable interrupts. + 166 intState = __save_interrupt(); + \ 00000000 B72F IN R18, 0x3F + 167 __disable_interrupt(); + \ 00000002 94F8 CLI + 168 + 169 // Drive bus low and delay. + 170 OWI_PULL_BUS_LOW(pins); + \ 00000004 B31A IN R17, 0x1A + \ 00000006 2B10 OR R17, R16 + \ 00000008 BB1A OUT 0x1A, R17 + \ 0000000A 2F10 MOV R17, R16 + \ 0000000C 9510 COM R17 + \ 0000000E B33B IN R19, 0x1B + \ 00000010 2331 AND R19, R17 + \ 00000012 BB3B OUT 0x1B, R19 + 171 __delay_cycles(OWI_DELAY_H_STD_MODE); + \ 00000014 EB4C LDI R20, 188 + \ 00000016 E053 LDI R21, 3 + \ 00000018 5041 SUBI R20, 1 + \ 0000001A 4050 SBCI R21, 0 + \ 0000001C F7E9 BRNE $-4 + \ 0000001E C000 RJMP $+2 + 172 + 173 // Release bus and delay. + 174 OWI_RELEASE_BUS(pins); + \ 00000020 B33A IN R19, 0x1A + \ 00000022 2331 AND R19, R17 + \ 00000024 BB3A OUT 0x1A, R19 + \ 00000026 B33B IN R19, 0x1B + \ 00000028 2331 AND R19, R17 + \ 0000002A BB3B OUT 0x1B, R19 + 175 __delay_cycles(OWI_DELAY_I_STD_MODE); + \ 0000002C EB16 LDI R17, 182 + \ 0000002E 951A DEC R17 + \ 00000030 F7F1 BRNE $-2 + \ 00000032 0000 NOP + 176 + 177 // Sample bus to detect presence signal and delay. + 178 presenceDetected = ((~OWI_PIN) & pins); + \ 00000034 B319 IN R17, 0x19 + \ 00000036 9510 COM R17 + \ 00000038 2301 AND R16, R17 + 179 __delay_cycles(OWI_DELAY_J_STD_MODE); + \ 0000003A E340 LDI R20, 48 + \ 0000003C E053 LDI R21, 3 + \ 0000003E 5041 SUBI R20, 1 + \ 00000040 4050 SBCI R21, 0 + \ 00000042 F7E9 BRNE $-4 + \ 00000044 C000 RJMP $+2 + 180 + 181 // Restore interrupts. + 182 __restore_interrupt(intState); + \ 00000046 BF2F OUT 0x3F, R18 + 183 + 184 return presenceDetected; + \ 00000048 9508 RET + \ 0000004A REQUIRE _A_PORTA + \ 0000004A REQUIRE _A_DDRA + \ 0000004A REQUIRE _A_PINA + 185 } + 186 + 187 + 188 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es). + 189 * + 190 * This function automates the task of sending a complete byte + 191 * of data on the 1-Wire bus(es). + 192 * + 193 * \param data The data to send on the bus(es). + 194 * + 195 * \param pins A bitmask of the buses to send the data to. + 196 */ + + \ In segment CODE, align 2, keep-with-next + 197 void OWI_SendByte(unsigned char data, unsigned char pins) + \ OWI_SendByte: + 198 { + \ 00000000 93AA ST -Y, R26 + \ 00000002 939A ST -Y, R25 + \ 00000004 938A ST -Y, R24 + \ 00000006 2FA0 MOV R26, R16 + \ 00000008 2F91 MOV R25, R17 + 199 unsigned char temp; + 200 unsigned char i; + 201 + 202 // Do once for each bit + 203 for (i = 0; i < 8; i++) { + \ 0000000A E088 LDI R24, 8 + 204 // Determine if LSB is '0' or '1' and transmit corresponding + 205 // waveform on the bus. + 206 temp = data & 0x01; + 207 + 208 if (temp) { + \ ??OWI_SendByte_0: + \ 0000000C FBA0 BST R26, 0 + \ 0000000E 2F09 MOV R16, R25 + \ 00000010 F416 BRTC ??OWI_SendByte_1 + 209 OWI_WriteBit1(pins); + \ 00000012 .... RCALL OWI_WriteBit1 + \ 00000014 C001 RJMP ??OWI_SendByte_2 + 210 } else { + 211 OWI_WriteBit0(pins); + \ ??OWI_SendByte_1: + \ 00000016 .... RCALL OWI_WriteBit0 + 212 } + 213 + 214 data >>= 1; // Right shift the data to get next bit. + \ ??OWI_SendByte_2: + \ 00000018 95A6 LSR R26 + 215 } + \ 0000001A 958A DEC R24 + \ 0000001C F7B9 BRNE ??OWI_SendByte_0 + 216 } + \ 0000001E 9189 LD R24, Y+ + \ 00000020 9199 LD R25, Y+ + \ 00000022 91A9 LD R26, Y+ + \ 00000024 9508 RET + 217 + 218 + 219 /*! \brief Receives one byte of data from the 1-Wire(R) bus. + 220 * + 221 * This function automates the task of receiving a complete byte + 222 * of data from the 1-Wire bus. + 223 * + 224 * \param pin A bitmask of the bus to read from. + 225 * + 226 * \return The byte read from the bus. + 227 */ + + \ In segment CODE, align 2, keep-with-next + 228 unsigned char OWI_ReceiveByte(unsigned char pin) + \ OWI_ReceiveByte: + 229 { + \ 00000000 93AA ST -Y, R26 + \ 00000002 939A ST -Y, R25 + \ 00000004 938A ST -Y, R24 + \ 00000006 2FA0 MOV R26, R16 + 230 unsigned char data; + 231 unsigned char i; + 232 + 233 // Clear the temporary input variable. + 234 data = 0x00; + \ 00000008 E090 LDI R25, 0 + 235 + 236 // Do once for each bit + 237 for (i = 0; i < 8; i++) { + \ 0000000A E088 LDI R24, 8 + 238 // Shift temporary input variable right. + 239 data >>= 1; + \ ??OWI_ReceiveByte_0: + \ 0000000C 9596 LSR R25 + 240 + 241 // Set the MSB if a '1' value is read from the bus. + 242 // Leave as it is ('0') else. + 243 if (OWI_ReadBit(pin)) { + \ 0000000E 2F0A MOV R16, R26 + \ 00000010 .... RCALL OWI_ReadBit + \ 00000012 2300 TST R16 + \ 00000014 F009 BREQ ??OWI_ReceiveByte_1 + 244 data |= 0x80; + \ 00000016 6890 ORI R25, 0x80 + 245 } + 246 } + \ ??OWI_ReceiveByte_1: + \ 00000018 958A DEC R24 + \ 0000001A F7C1 BRNE ??OWI_ReceiveByte_0 + 247 + 248 return data; + \ 0000001C 2F09 MOV R16, R25 + \ 0000001E 9189 LD R24, Y+ + \ 00000020 9199 LD R25, Y+ + \ 00000022 91A9 LD R26, Y+ + \ 00000024 9508 RET + 249 } + 250 + 251 + 252 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). + 253 * + 254 * \param pins A bitmask of the buses to send the SKIP ROM command to. + 255 */ + + \ In segment CODE, align 2, keep-with-next + 256 void OWI_SkipRom(unsigned char pins) + \ OWI_SkipRom: + 257 { + 258 // Send the SKIP ROM command on the bus. + 259 OWI_SendByte(OWI_ROM_SKIP, pins); + \ 00000000 2F10 MOV R17, R16 + \ 00000002 EC0C LDI R16, 204 + \ 00000004 .... RJMP OWI_SendByte + 260 } + 261 + 262 + 263 /*! \brief Sends the READ ROM command and reads back the ROM id. + 264 * + 265 * \param romValue A pointer where the id will be placed. + 266 * + 267 * \param pin A bitmask of the bus to read from. + 268 */ + + \ In segment CODE, align 2, keep-with-next + 269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin) + \ OWI_ReadRom: + 270 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + \ 00000004 939A ST -Y, R25 + \ 00000006 938A ST -Y, R24 + \ 00000008 01D8 MOVW R27:R26, R17:R16 + \ 0000000A 2F92 MOV R25, R18 + 271 unsigned char bytesLeft = 8; + 272 + 273 // Send the READ ROM command on the bus. + 274 OWI_SendByte(OWI_ROM_READ, pin); + \ 0000000C 2F12 MOV R17, R18 + \ 0000000E E303 LDI R16, 51 + \ 00000010 .... RCALL OWI_SendByte + \ 00000012 E088 LDI R24, 8 + 275 + 276 // Do 8 times. + 277 while (bytesLeft > 0) { + 278 // Place the received data in memory. + 279 *romValue++ = OWI_ReceiveByte(pin); + \ ??OWI_ReadRom_0: + \ 00000014 2F09 MOV R16, R25 + \ 00000016 .... RCALL OWI_ReceiveByte + \ 00000018 930D ST X+, R16 + 280 bytesLeft--; + \ 0000001A 958A DEC R24 + 281 } + \ 0000001C F7D9 BRNE ??OWI_ReadRom_0 + 282 } + \ 0000001E REQUIRE ?Subroutine0 + \ 0000001E ; // Fall through to label ?Subroutine0 + + \ In segment CODE, align 2, keep-with-next + \ ?Subroutine0: + \ 00000000 9189 LD R24, Y+ + \ 00000002 9199 LD R25, Y+ + \ 00000004 91A9 LD R26, Y+ + \ 00000006 91B9 LD R27, Y+ + \ 00000008 9508 RET + 283 + 284 + 285 /*! \brief Sends the MATCH ROM command and the ROM id to match against. + 286 * + 287 * \param romValue A pointer to the ID to match against. + 288 * + 289 * \param pins A bitmask of the buses to perform the MATCH ROM command on. + 290 */ + + \ In segment CODE, align 2, keep-with-next + 291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins) + \ OWI_MatchRom: + 292 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + \ 00000004 939A ST -Y, R25 + \ 00000006 938A ST -Y, R24 + \ 00000008 01D8 MOVW R27:R26, R17:R16 + \ 0000000A 2F92 MOV R25, R18 + 293 unsigned char bytesLeft = 8; + 294 + 295 // Send the MATCH ROM command. + 296 OWI_SendByte(OWI_ROM_MATCH, pins); + \ 0000000C 2F12 MOV R17, R18 + \ 0000000E E505 LDI R16, 85 + \ 00000010 .... RCALL OWI_SendByte + \ 00000012 E088 LDI R24, 8 + 297 + 298 // Do once for each byte. + 299 while (bytesLeft > 0) { + 300 // Transmit 1 byte of the ID to match. + 301 OWI_SendByte(*romValue++, pins); + \ ??OWI_MatchRom_0: + \ 00000014 2F19 MOV R17, R25 + \ 00000016 910D LD R16, X+ + \ 00000018 .... RCALL OWI_SendByte + 302 bytesLeft--; + \ 0000001A 958A DEC R24 + 303 } + \ 0000001C F7D9 BRNE ??OWI_MatchRom_0 + 304 } + \ 0000001E .... RJMP ?Subroutine0 + 305 + 306 + 307 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the + 308 * 1-Wire(R) bus. + 309 * + 310 * \param bitPattern A pointer to an 8 byte char array where the + 311 * discovered identifier will be placed. When + 312 * searching for several slaves, a copy of the + 313 * last found identifier should be supplied in + 314 * the array, or the search will fail. + 315 * + 316 * \param lastDeviation The bit position where the algorithm made a + 317 * choice the last time it was run. This argument + 318 * should be 0 when a search is initiated. Supplying + 319 * the return argument of this function when calling + 320 * repeatedly will go through the complete slave + 321 * search. + 322 * + 323 * \param pin A bit-mask of the bus to perform a ROM search on. + 324 * + 325 * \return The last bit position where there was a discrepancy between slave + 326 * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED + 327 * if an error was detected (e.g. a device was connected to the bus during the + 328 * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be + 329 * discovered. + 330 * + 331 * \note See main.c for an example of how to utilize this function. + 332 */ + + \ In segment CODE, align 2, keep-with-next + 333 unsigned char OWI_SearchRom(unsigned char * bitPattern, + \ OWI_SearchRom: + 334 unsigned char lastDeviation, unsigned char pin) + 335 { + \ 00000000 927A ST -Y, R7 + \ 00000002 926A ST -Y, R6 + \ 00000004 925A ST -Y, R5 + \ 00000006 924A ST -Y, R4 + \ 00000008 93BA ST -Y, R27 + \ 0000000A 93AA ST -Y, R26 + \ 0000000C 939A ST -Y, R25 + \ 0000000E 938A ST -Y, R24 + \ 00000010 REQUIRE ?Register_R4_is_cg_reg + \ 00000010 REQUIRE ?Register_R5_is_cg_reg + \ 00000010 REQUIRE ?Register_R6_is_cg_reg + \ 00000010 REQUIRE ?Register_R7_is_cg_reg + \ 00000010 01D8 MOVW R27:R26, R17:R16 + \ 00000012 2E62 MOV R6, R18 + \ 00000014 2E43 MOV R4, R19 + 336 unsigned char currentBit = 1; + \ 00000016 E081 LDI R24, 1 + 337 unsigned char newDeviation = 0; + \ 00000018 2455 CLR R5 + 338 unsigned char bitMask = 0x01; + \ 0000001A E091 LDI R25, 1 + 339 unsigned char bitA; + 340 unsigned char bitB; + 341 + 342 // Send SEARCH ROM command on the bus. + 343 OWI_SendByte(OWI_ROM_SEARCH, pin); + \ 0000001C 2F13 MOV R17, R19 + \ 0000001E EF00 LDI R16, 240 + \ 00000020 .... RCALL OWI_SendByte + 344 + 345 // Walk through all 64 bits. + 346 while (currentBit <= 64) { + 347 // Read bit from bus twice. + 348 bitA = OWI_ReadBit(pin); + \ ??OWI_SearchRom_0: + \ 00000022 2D04 MOV R16, R4 + \ 00000024 .... RCALL OWI_ReadBit + \ 00000026 2E70 MOV R7, R16 + 349 bitB = OWI_ReadBit(pin); + \ 00000028 2D04 MOV R16, R4 + \ 0000002A .... RCALL OWI_ReadBit + 350 + 351 if (bitA && bitB) { + \ 0000002C 2077 TST R7 + \ 0000002E F021 BREQ ??OWI_SearchRom_1 + \ 00000030 2300 TST R16 + \ 00000032 F011 BREQ ??OWI_SearchRom_1 + 352 // Both bits 1 (Error). + 353 newDeviation = OWI_ROM_SEARCH_FAILED; + 354 return newDeviation; + \ 00000034 EF0F LDI R16, 255 + \ 00000036 C02C RJMP ??OWI_SearchRom_2 + 355 } else if (bitA ^ bitB) { + \ ??OWI_SearchRom_1: + \ 00000038 2507 EOR R16, R7 + \ 0000003A F069 BREQ ??OWI_SearchRom_3 + 356 // Bits A and B are different. All devices have the same bit here. + 357 // Set the bit in bitPattern to this value. + 358 if (bitA) { + \ 0000003C 2077 TST R7 + \ 0000003E F029 BREQ ??OWI_SearchRom_4 + 359 (*bitPattern) |= bitMask; + \ ??OWI_SearchRom_5: + \ 00000040 01FD MOVW R31:R30, R27:R26 + \ 00000042 8100 LD R16, Z + \ 00000044 2B09 OR R16, R25 + \ 00000046 8300 ST Z, R16 + \ 00000048 C014 RJMP ??OWI_SearchRom_6 + 360 } else { + 361 (*bitPattern) &= ~bitMask; + \ ??OWI_SearchRom_4: + \ 0000004A 2F09 MOV R16, R25 + \ 0000004C 9500 COM R16 + \ 0000004E 911C LD R17, X + \ 00000050 2310 AND R17, R16 + \ 00000052 931C ST X, R17 + \ 00000054 C00E RJMP ??OWI_SearchRom_6 + 362 } + 363 } else { + 364 // If this is where a choice was made the last time, + 365 // a '1' bit is selected this time. + 366 if (currentBit == lastDeviation) { + \ ??OWI_SearchRom_3: + \ 00000056 1586 CP R24, R6 + \ 00000058 F399 BREQ ??OWI_SearchRom_5 + 367 (*bitPattern) |= bitMask; + 368 } + 369 + 370 // For the rest of the id, '0' bits are selected when + 371 // discrepancies occur. + 372 else if (currentBit > lastDeviation) { + \ 0000005A 1668 CP R6, R24 + \ 0000005C F430 BRCC ??OWI_SearchRom_7 + 373 (*bitPattern) &= ~bitMask; + \ 0000005E 2F09 MOV R16, R25 + \ 00000060 9500 COM R16 + \ 00000062 911C LD R17, X + \ 00000064 2310 AND R17, R16 + \ 00000066 931C ST X, R17 + 374 newDeviation = currentBit; + \ 00000068 C003 RJMP ??OWI_SearchRom_8 + 375 } + 376 + 377 // If current bit in bit pattern = 0, then this is + 378 // out new deviation. + 379 else if ( !(*bitPattern & bitMask)) { + \ ??OWI_SearchRom_7: + \ 0000006A 910C LD R16, X + \ 0000006C 2309 AND R16, R25 + \ 0000006E F409 BRNE ??OWI_SearchRom_6 + 380 newDeviation = currentBit; + \ ??OWI_SearchRom_8: + \ 00000070 2E58 MOV R5, R24 + 381 } + 382 + 383 // IF the bit is already 1, do nothing. + 384 else { + 385 } + 386 } + 387 + 388 // Send the selected bit to the bus. + 389 if ((*bitPattern) & bitMask) { + \ ??OWI_SearchRom_6: + \ 00000072 910C LD R16, X + \ 00000074 2309 AND R16, R25 + \ 00000076 2D04 MOV R16, R4 + \ 00000078 F011 BREQ ??OWI_SearchRom_9 + 390 OWI_WriteBit1(pin); + \ 0000007A .... RCALL OWI_WriteBit1 + \ 0000007C C001 RJMP ??OWI_SearchRom_10 + 391 } else { + 392 OWI_WriteBit0(pin); + \ ??OWI_SearchRom_9: + \ 0000007E .... RCALL OWI_WriteBit0 + 393 } + 394 + 395 // Increment current bit. + 396 currentBit++; + \ ??OWI_SearchRom_10: + \ 00000080 9583 INC R24 + 397 + 398 // Adjust bitMask and bitPattern pointer. + 399 bitMask <<= 1; + \ 00000082 0F99 LSL R25 + 400 if (!bitMask) { + \ 00000084 F411 BRNE ??OWI_SearchRom_11 + 401 bitMask = 0x01; + \ 00000086 E091 LDI R25, 1 + 402 bitPattern++; + \ 00000088 9611 ADIW R27:R26, 1 + 403 } + 404 } + \ ??OWI_SearchRom_11: + \ 0000008A 3481 CPI R24, 65 + \ 0000008C F250 BRCS ??OWI_SearchRom_0 + 405 + 406 return newDeviation; + \ 0000008E 2D05 MOV R16, R5 + \ ??OWI_SearchRom_2: + \ 00000090 9189 LD R24, Y+ + \ 00000092 9199 LD R25, Y+ + \ 00000094 91A9 LD R26, Y+ + \ 00000096 91B9 LD R27, Y+ + \ 00000098 9049 LD R4, Y+ + \ 0000009A 9059 LD R5, Y+ + \ 0000009C 9069 LD R6, Y+ + \ 0000009E 9079 LD R7, Y+ + \ 000000A0 9508 RET + 407 } + 408 + 409 + 410 /* Functions for handling CRC */ + 411 /*! \brief Compute the CRC8 value of a data set. + 412 * + 413 * This function will compute the CRC8 or DOW-CRC of inData using seed + 414 * as inital value for the CRC. + 415 * + 416 * \param inData One byte of data to compute CRC from. + 417 * + 418 * \param seed The starting value of the CRC. + 419 * + 420 * \return The CRC8 of inData with seed as initial value. + 421 * + 422 * \note Setting seed to 0 computes the crc8 of the inData. + 423 * + 424 * \note Constantly passing the return value of this function + 425 * As the seed argument computes the CRC8 value of a + 426 * longer string of data. + 427 */ + + \ In segment CODE, align 2, keep-with-next + 428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) + \ OWI_ComputeCRC8: + 429 { + 430 unsigned char bitsLeft; + 431 unsigned char temp; + 432 + 433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + \ 00000000 E038 LDI R19, 8 + 434 temp = ((seed ^ inData) & 0x01); + 435 + 436 if (temp == 0) { + \ ??OWI_ComputeCRC8_0: + \ 00000002 2F21 MOV R18, R17 + \ 00000004 7021 ANDI R18, 0x01 + \ 00000006 2F40 MOV R20, R16 + \ 00000008 7041 ANDI R20, 0x01 + \ 0000000A 2742 EOR R20, R18 + \ 0000000C F411 BRNE ??OWI_ComputeCRC8_1 + 437 seed >>= 1; + \ 0000000E 9516 LSR R17 + \ 00000010 C004 RJMP ??OWI_ComputeCRC8_2 + 438 } else { + 439 seed ^= 0x18; + 440 seed >>= 1; + 441 seed |= 0x80; + \ ??OWI_ComputeCRC8_1: + \ 00000012 E128 LDI R18, 24 + \ 00000014 2712 EOR R17, R18 + \ 00000016 9516 LSR R17 + \ 00000018 6810 ORI R17, 0x80 + 442 } + 443 + 444 inData >>= 1; + \ ??OWI_ComputeCRC8_2: + \ 0000001A 9506 LSR R16 + 445 } + \ 0000001C 953A DEC R19 + \ 0000001E F789 BRNE ??OWI_ComputeCRC8_0 + 446 return seed; + \ 00000020 2F01 MOV R16, R17 + \ 00000022 9508 RET + 447 } + 448 + 449 + 450 /*! \brief Compute the CRC16 value of a data set. + 451 * + 452 * This function will compute the CRC16 of inData using seed + 453 * as inital value for the CRC. + 454 * + 455 * \param inData One byte of data to compute CRC from. + 456 * + 457 * \param seed The starting value of the CRC. + 458 * + 459 * \return The CRC16 of inData with seed as initial value. + 460 * + 461 * \note Setting seed to 0 computes the crc16 of the inData. + 462 * + 463 * \note Constantly passing the return value of this function + 464 * As the seed argument computes the CRC16 value of a + 465 * longer string of data. + 466 */ + + \ In segment CODE, align 2, keep-with-next + 467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) + \ OWI_ComputeCRC16: + 468 { + 469 unsigned char bitsLeft; + 470 unsigned char temp; + 471 + 472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + \ 00000000 E018 LDI R17, 8 + 473 temp = ((seed ^ inData) & 0x01); + 474 + 475 if (temp == 0) { + \ ??OWI_ComputeCRC16_0: + \ 00000002 2F42 MOV R20, R18 + \ 00000004 7041 ANDI R20, 0x01 + \ 00000006 2F50 MOV R21, R16 + \ 00000008 7051 ANDI R21, 0x01 + \ 0000000A 2754 EOR R21, R20 + \ 0000000C F419 BRNE ??OWI_ComputeCRC16_1 + 476 seed >>= 1; + \ 0000000E 9536 LSR R19 + \ 00000010 9527 ROR R18 + \ 00000012 C008 RJMP ??OWI_ComputeCRC16_2 + 477 } else { + 478 seed ^= 0x4002; + 479 seed >>= 1; + 480 seed |= 0x8000; + \ ??OWI_ComputeCRC16_1: + \ 00000014 E042 LDI R20, 2 + \ 00000016 E450 LDI R21, 64 + \ 00000018 2742 EOR R20, R18 + \ 0000001A 2753 EOR R21, R19 + \ 0000001C 019A MOVW R19:R18, R21:R20 + \ 0000001E 9536 LSR R19 + \ 00000020 9527 ROR R18 + \ 00000022 6830 ORI R19, 0x80 + 481 } + 482 + 483 inData >>= 1; + \ ??OWI_ComputeCRC16_2: + \ 00000024 9506 LSR R16 + 484 } + \ 00000026 951A DEC R17 + \ 00000028 F761 BRNE ??OWI_ComputeCRC16_0 + 485 + 486 return seed; + \ 0000002A 0189 MOVW R17:R16, R19:R18 + \ 0000002C 9508 RET + 487 } + 488 + 489 + 490 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier. + 491 * + 492 * This function computes the CRC8 value of the first 56 bits of a + 493 * 64 bit identifier. It then checks the calculated value against the + 494 * CRC value stored in ROM. + 495 * + 496 * \param *romValue A pointer to an array holding a 64 bit identifier. + 497 * + 498 * \retval OWI_CRC_OK The CRC's matched. + 499 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. + 500 */ + + \ In segment CODE, align 2, keep-with-next + 501 unsigned char OWI_CheckRomCRC(unsigned char *romValue) + \ OWI_CheckRomCRC: + 502 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + \ 00000004 938A ST -Y, R24 + \ 00000006 01D8 MOVW R27:R26, R17:R16 + 503 unsigned char i; + 504 unsigned char crc8 = 0; + \ 00000008 E010 LDI R17, 0 + 505 + 506 for (i = 0; i < 7; i++) { + \ 0000000A E087 LDI R24, 7 + 507 crc8 = OWI_ComputeCRC8(*romValue, crc8); + \ ??OWI_CheckRomCRC_0: + \ 0000000C 910D LD R16, X+ + \ 0000000E .... RCALL OWI_ComputeCRC8 + \ 00000010 2F10 MOV R17, R16 + 508 romValue++; + 509 } + \ 00000012 958A DEC R24 + \ 00000014 F7D9 BRNE ??OWI_CheckRomCRC_0 + 510 + 511 if (crc8 == (*romValue)) { + \ 00000016 910C LD R16, X + \ 00000018 1710 CP R17, R16 + \ 0000001A F411 BRNE ??OWI_CheckRomCRC_1 + 512 return OWI_CRC_OK; + \ 0000001C E000 LDI R16, 0 + \ 0000001E C001 RJMP ??OWI_CheckRomCRC_2 + 513 } + 514 + 515 return OWI_CRC_ERROR; + \ ??OWI_CheckRomCRC_1: + \ 00000020 E001 LDI R16, 1 + \ ??OWI_CheckRomCRC_2: + \ 00000022 9189 LD R24, Y+ + \ 00000024 91A9 LD R26, Y+ + \ 00000026 91B9 LD R27, Y+ + \ 00000028 9508 RET + 516 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + OWI_CheckRomCRC 3 2 + -> OWI_ComputeCRC8 3 2 + OWI_ComputeCRC16 0 2 + OWI_ComputeCRC8 0 2 + OWI_DetectPresence 0 2 + OWI_Init 0 2 + OWI_MatchRom 4 2 + -> OWI_SendByte 4 2 + -> OWI_SendByte 4 2 + OWI_ReadBit 0 2 + OWI_ReadRom 4 2 + -> OWI_SendByte 4 2 + -> OWI_ReceiveByte 4 2 + OWI_ReceiveByte 3 2 + -> OWI_ReadBit 3 2 + OWI_SearchRom 8 2 + -> OWI_SendByte 8 2 + -> OWI_ReadBit 8 2 + -> OWI_ReadBit 8 2 + -> OWI_WriteBit1 8 2 + -> OWI_WriteBit0 8 2 + OWI_SendByte 3 2 + -> OWI_WriteBit1 3 2 + -> OWI_WriteBit0 3 2 + OWI_SkipRom 0 2 + -> OWI_SendByte 0 2 + OWI_WriteBit0 0 2 + OWI_WriteBit1 0 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_PORTA 1 + _A_DDRA 1 + _A_PINA 1 + OWI_Init 28 + OWI_WriteBit1 50 + OWI_WriteBit0 50 + OWI_ReadBit 66 + OWI_DetectPresence 74 + OWI_SendByte 38 + OWI_ReceiveByte 38 + OWI_SkipRom 6 + OWI_ReadRom 30 + ?Subroutine0 10 + OWI_MatchRom 32 + OWI_SearchRom 162 + OWI_ComputeCRC8 36 + OWI_ComputeCRC16 46 + OWI_CheckRomCRC 42 + + + 3 bytes in segment ABSOLUTE + 708 bytes in segment CODE + + 708 bytes of CODE memory + 0 bytes of DATA memory (+ 3 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/OWI.s90 b/BaseTinyFirmware/IAR/Release/List/OWI.s90 new file mode 100644 index 0000000..5bfb792 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/OWI.s90 @@ -0,0 +1,1068 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:36 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\OWI.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\OWI.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\O / +// WI.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME OWI + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?Register_R6_is_cg_reg + EXTERN ?Register_R7_is_cg_reg + + PUBLIC OWI_CheckRomCRC + PUBLIC OWI_ComputeCRC16 + PUBLIC OWI_ComputeCRC8 + PUBLIC OWI_DetectPresence + PUBLIC OWI_Init + PUBLIC OWI_MatchRom + PUBLIC OWI_ReadBit + PUBLIC OWI_ReadRom + PUBLIC OWI_ReceiveByte + PUBLIC OWI_SearchRom + PUBLIC OWI_SendByte + PUBLIC OWI_SkipRom + PUBLIC OWI_WriteBit0 + PUBLIC OWI_WriteBit1 + PUBWEAK _A_DDRA + PUBWEAK _A_PINA + PUBWEAK _A_PORTA + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + +// C:\home\kevin\pub\src\bc100\IAR\OWI.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ******************************************************************** +// 3 * +// 4 * \brief +// 5 * Functions for 1-Wire(R) bus communication +// 6 * +// 7 * High level functions for transmission of full bytes on the 1-Wire(R) +// 8 * bus and implementations of ROM commands.\n +// 9 * Polled software only implementation of the basic bit-level signalling +// 10 * in the 1-Wire(R) protocol.\n +// 11 * Includes functions for computing and checking CRC8 & 16 values of data +// 12 * sets, and of 64 bit ROM identifiers. +// 13 * Supported devices: All AVRs. +// 14 * +// 15 * \par Application Note: +// 16 * AVR458: Charging Li-Ion Batteries with BC100\n +// 17 * AVR463: Charging NiMH Batteries with BC100\n +// 18 * One-wire protocol based on AVR318 - Dallas 1-Wire(R) master. +// 19 * +// 20 * \par Documentation: +// 21 * For comprehensive code documentation, supported compilers, compiler +// 22 * settings and supported devices see readme.html +// 23 * +// 24 * \author +// 25 * Atmel Corporation: http://www.atmel.com \n +// 26 * Support email: avr@atmel.com \n +// 27 * Original author: \n +// 28 * +// 29 * $Name$ +// 30 * $Revision: 2299 $ +// 31 * $RCSfile$ +// 32 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/OWI.c $ +// 33 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 34 ****************************************************************************/ +// 35 +// 36 #include + + ASEGN ABSOLUTE:DATA:NOROOT,03bH +// volatile __io _A_PORTA +_A_PORTA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,03aH +// volatile __io _A_DDRA +_A_DDRA: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,039H +// volatile __io _A_PINA +_A_PINA: + DS 1 +// 37 #include +// 38 +// 39 #include "OWI.h" +// 40 +// 41 +// 42 //****************************************************************************** +// 43 // Functions +// 44 //****************************************************************************** +// 45 /*! \brief Initialization of the one wire bus(es). (Software only driver) +// 46 * +// 47 * This function initializes the 1-Wire bus(es) by releasing it and +// 48 * waiting until any presence signals are finished. +// 49 * +// 50 * \param pins A bitmask of the buses to initialize. +// 51 */ + + RSEG CODE:CODE:NOROOT(1) +// 52 void OWI_Init(unsigned char pins){ +OWI_Init: +// 53 OWI_RELEASE_BUS(pins); + COM R16 + IN R17, 0x1A + AND R17, R16 + OUT 0x1A, R17 + IN R17, 0x1B + AND R17, R16 + OUT 0x1B, R17 +// 54 // The first rising edge can be interpreted by a slave as the end of a +// 55 // Reset-pulse. Delay for the required reset recovery time (H) to be +// 56 // sure that the real reset is interpreted correctly. +// 57 __delay_cycles(OWI_DELAY_H_STD_MODE); + LDI R16, 188 + LDI R17, 3 + SUBI R16, 1 + SBCI R17, 0 + BRNE $-4 + RJMP $+2 +// 58 } + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA +// 59 +// 60 +// 61 /*! \brief Write a '1' bit to the bus(es). (Software only driver) +// 62 * +// 63 * Generates the waveform for transmission of a '1' bit on the 1-Wire +// 64 * bus. +// 65 * +// 66 * \param pins A bitmask of the buses to write to. +// 67 */ + + RSEG CODE:CODE:NOROOT(1) +// 68 void OWI_WriteBit1(unsigned char pins){ +OWI_WriteBit1: +// 69 unsigned char intState; +// 70 +// 71 // Disable interrupts. +// 72 intState = __save_interrupt(); + IN R17, 0x3F +// 73 __disable_interrupt(); + CLI +// 74 +// 75 // Drive bus low and delay. +// 76 OWI_PULL_BUS_LOW(pins); + IN R18, 0x1A + OR R18, R16 + OUT 0x1A, R18 + COM R16 + IN R18, 0x1B + AND R18, R16 + OUT 0x1B, R18 +// 77 __delay_cycles(OWI_DELAY_A_STD_MODE); + LDI R18, 11 + DEC R18 + BRNE $-2 + RJMP $+2 +// 78 +// 79 // Release bus and delay. +// 80 OWI_RELEASE_BUS(pins); + IN R18, 0x1A + AND R18, R16 + OUT 0x1A, R18 + IN R18, 0x1B + AND R18, R16 + OUT 0x1B, R18 +// 81 __delay_cycles(OWI_DELAY_B_STD_MODE); + LDI R16, 166 + DEC R16 + BRNE $-2 + NOP +// 82 +// 83 // Restore interrupts. +// 84 __restore_interrupt(intState); + OUT 0x3F, R17 +// 85 } + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA +// 86 +// 87 /*! \brief Write a '0' to the bus(es). (Software only driver) +// 88 * +// 89 * Generates the waveform for transmission of a '0' bit on the 1-Wire(R) +// 90 * bus. +// 91 * +// 92 * \param pins A bitmask of the buses to write to. +// 93 */ + + RSEG CODE:CODE:NOROOT(1) +// 94 void OWI_WriteBit0(unsigned char pins) +OWI_WriteBit0: +// 95 { +// 96 unsigned char intState; +// 97 +// 98 // Disable interrupts. +// 99 intState = __save_interrupt(); + IN R17, 0x3F +// 100 __disable_interrupt(); + CLI +// 101 +// 102 // Drive bus low and delay. +// 103 OWI_PULL_BUS_LOW(pins); + IN R18, 0x1A + OR R18, R16 + OUT 0x1A, R18 + COM R16 + IN R18, 0x1B + AND R18, R16 + OUT 0x1B, R18 +// 104 __delay_cycles(OWI_DELAY_C_STD_MODE); + LDI R18, 155 + DEC R18 + BRNE $-2 + RJMP $+2 +// 105 +// 106 // Release bus and delay. +// 107 OWI_RELEASE_BUS(pins); + IN R18, 0x1A + AND R18, R16 + OUT 0x1A, R18 + IN R18, 0x1B + AND R18, R16 + OUT 0x1B, R18 +// 108 __delay_cycles(OWI_DELAY_D_STD_MODE); + LDI R16, 22 + DEC R16 + BRNE $-2 + NOP +// 109 +// 110 // Restore interrupts. +// 111 __restore_interrupt(intState); + OUT 0x3F, R17 +// 112 } + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA +// 113 +// 114 /*! \brief Read a bit from the bus(es). (Software only driver) +// 115 * +// 116 * Generates the waveform for reception of a bit on the 1-Wire(R) bus(es). +// 117 * +// 118 * \param pins A bitmask of the bus(es) to read from. +// 119 * +// 120 * \return A bitmask of the buses where a '1' was read. +// 121 */ + + RSEG CODE:CODE:NOROOT(1) +// 122 unsigned char OWI_ReadBit(unsigned char pins) +OWI_ReadBit: +// 123 { +// 124 unsigned char intState; +// 125 unsigned char bitsRead; +// 126 +// 127 // Disable interrupts. +// 128 intState = __save_interrupt(); + IN R18, 0x3F +// 129 __disable_interrupt(); + CLI +// 130 +// 131 // Drive bus low and delay. +// 132 OWI_PULL_BUS_LOW(pins); + IN R17, 0x1A + OR R17, R16 + OUT 0x1A, R17 + MOV R17, R16 + COM R17 + IN R19, 0x1B + AND R19, R17 + OUT 0x1B, R19 +// 133 __delay_cycles(OWI_DELAY_A_STD_MODE); + LDI R19, 11 + DEC R19 + BRNE $-2 + RJMP $+2 +// 134 +// 135 // Release bus and delay. +// 136 OWI_RELEASE_BUS(pins); + IN R19, 0x1A + AND R19, R17 + OUT 0x1A, R19 + IN R19, 0x1B + AND R19, R17 + OUT 0x1B, R19 +// 137 __delay_cycles(OWI_DELAY_E_STD_MODE); + LDI R17, 19 + DEC R17 + BRNE $-2 + RJMP $+2 +// 138 +// 139 // Sample bus and delay. +// 140 bitsRead = OWI_PIN & pins; + IN R17, 0x19 + AND R17, R16 +// 141 __delay_cycles(OWI_DELAY_F_STD_MODE); + LDI R16, 142 + DEC R16 + BRNE $-2 + NOP +// 142 +// 143 // Restore interrupts. +// 144 __restore_interrupt(intState); + OUT 0x3F, R18 +// 145 +// 146 return bitsRead; + MOV R16, R17 + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA + REQUIRE _A_PINA +// 147 } +// 148 +// 149 +// 150 /*! \brief Send a Reset signal and listen for Presence signal. (software +// 151 * only driver) +// 152 * +// 153 * Generates the waveform for transmission of a Reset pulse on the +// 154 * 1-Wire(R) bus and listens for presence signals. +// 155 * +// 156 * \param pins A bitmask of the buses to send the Reset signal on. +// 157 * +// 158 * \return A bitmask of the buses where a presence signal was detected. +// 159 */ + + RSEG CODE:CODE:NOROOT(1) +// 160 unsigned char OWI_DetectPresence(unsigned char pins) +OWI_DetectPresence: +// 161 { +// 162 unsigned char intState; +// 163 unsigned char presenceDetected; +// 164 +// 165 // Disable interrupts. +// 166 intState = __save_interrupt(); + IN R18, 0x3F +// 167 __disable_interrupt(); + CLI +// 168 +// 169 // Drive bus low and delay. +// 170 OWI_PULL_BUS_LOW(pins); + IN R17, 0x1A + OR R17, R16 + OUT 0x1A, R17 + MOV R17, R16 + COM R17 + IN R19, 0x1B + AND R19, R17 + OUT 0x1B, R19 +// 171 __delay_cycles(OWI_DELAY_H_STD_MODE); + LDI R20, 188 + LDI R21, 3 + SUBI R20, 1 + SBCI R21, 0 + BRNE $-4 + RJMP $+2 +// 172 +// 173 // Release bus and delay. +// 174 OWI_RELEASE_BUS(pins); + IN R19, 0x1A + AND R19, R17 + OUT 0x1A, R19 + IN R19, 0x1B + AND R19, R17 + OUT 0x1B, R19 +// 175 __delay_cycles(OWI_DELAY_I_STD_MODE); + LDI R17, 182 + DEC R17 + BRNE $-2 + NOP +// 176 +// 177 // Sample bus to detect presence signal and delay. +// 178 presenceDetected = ((~OWI_PIN) & pins); + IN R17, 0x19 + COM R17 + AND R16, R17 +// 179 __delay_cycles(OWI_DELAY_J_STD_MODE); + LDI R20, 48 + LDI R21, 3 + SUBI R20, 1 + SBCI R21, 0 + BRNE $-4 + RJMP $+2 +// 180 +// 181 // Restore interrupts. +// 182 __restore_interrupt(intState); + OUT 0x3F, R18 +// 183 +// 184 return presenceDetected; + RET + REQUIRE _A_PORTA + REQUIRE _A_DDRA + REQUIRE _A_PINA +// 185 } +// 186 +// 187 +// 188 /*! \brief Sends one byte of data on the 1-Wire(R) bus(es). +// 189 * +// 190 * This function automates the task of sending a complete byte +// 191 * of data on the 1-Wire bus(es). +// 192 * +// 193 * \param data The data to send on the bus(es). +// 194 * +// 195 * \param pins A bitmask of the buses to send the data to. +// 196 */ + + RSEG CODE:CODE:NOROOT(1) +// 197 void OWI_SendByte(unsigned char data, unsigned char pins) +OWI_SendByte: +// 198 { + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + MOV R26, R16 + MOV R25, R17 +// 199 unsigned char temp; +// 200 unsigned char i; +// 201 +// 202 // Do once for each bit +// 203 for (i = 0; i < 8; i++) { + LDI R24, 8 +// 204 // Determine if LSB is '0' or '1' and transmit corresponding +// 205 // waveform on the bus. +// 206 temp = data & 0x01; +// 207 +// 208 if (temp) { +??OWI_SendByte_0: + BST R26, 0 + MOV R16, R25 + BRTC ??OWI_SendByte_1 +// 209 OWI_WriteBit1(pins); + RCALL OWI_WriteBit1 + RJMP ??OWI_SendByte_2 +// 210 } else { +// 211 OWI_WriteBit0(pins); +??OWI_SendByte_1: + RCALL OWI_WriteBit0 +// 212 } +// 213 +// 214 data >>= 1; // Right shift the data to get next bit. +??OWI_SendByte_2: + LSR R26 +// 215 } + DEC R24 + BRNE ??OWI_SendByte_0 +// 216 } + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + RET +// 217 +// 218 +// 219 /*! \brief Receives one byte of data from the 1-Wire(R) bus. +// 220 * +// 221 * This function automates the task of receiving a complete byte +// 222 * of data from the 1-Wire bus. +// 223 * +// 224 * \param pin A bitmask of the bus to read from. +// 225 * +// 226 * \return The byte read from the bus. +// 227 */ + + RSEG CODE:CODE:NOROOT(1) +// 228 unsigned char OWI_ReceiveByte(unsigned char pin) +OWI_ReceiveByte: +// 229 { + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + MOV R26, R16 +// 230 unsigned char data; +// 231 unsigned char i; +// 232 +// 233 // Clear the temporary input variable. +// 234 data = 0x00; + LDI R25, 0 +// 235 +// 236 // Do once for each bit +// 237 for (i = 0; i < 8; i++) { + LDI R24, 8 +// 238 // Shift temporary input variable right. +// 239 data >>= 1; +??OWI_ReceiveByte_0: + LSR R25 +// 240 +// 241 // Set the MSB if a '1' value is read from the bus. +// 242 // Leave as it is ('0') else. +// 243 if (OWI_ReadBit(pin)) { + MOV R16, R26 + RCALL OWI_ReadBit + TST R16 + BREQ ??OWI_ReceiveByte_1 +// 244 data |= 0x80; + ORI R25, 0x80 +// 245 } +// 246 } +??OWI_ReceiveByte_1: + DEC R24 + BRNE ??OWI_ReceiveByte_0 +// 247 +// 248 return data; + MOV R16, R25 + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + RET +// 249 } +// 250 +// 251 +// 252 /*! \brief Sends the SKIP ROM command to the 1-Wire bus(es). +// 253 * +// 254 * \param pins A bitmask of the buses to send the SKIP ROM command to. +// 255 */ + + RSEG CODE:CODE:NOROOT(1) +// 256 void OWI_SkipRom(unsigned char pins) +OWI_SkipRom: +// 257 { +// 258 // Send the SKIP ROM command on the bus. +// 259 OWI_SendByte(OWI_ROM_SKIP, pins); + MOV R17, R16 + LDI R16, 204 + RJMP OWI_SendByte +// 260 } +// 261 +// 262 +// 263 /*! \brief Sends the READ ROM command and reads back the ROM id. +// 264 * +// 265 * \param romValue A pointer where the id will be placed. +// 266 * +// 267 * \param pin A bitmask of the bus to read from. +// 268 */ + + RSEG CODE:CODE:NOROOT(1) +// 269 void OWI_ReadRom(unsigned char * romValue, unsigned char pin) +OWI_ReadRom: +// 270 { + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + MOVW R27:R26, R17:R16 + MOV R25, R18 +// 271 unsigned char bytesLeft = 8; +// 272 +// 273 // Send the READ ROM command on the bus. +// 274 OWI_SendByte(OWI_ROM_READ, pin); + MOV R17, R18 + LDI R16, 51 + RCALL OWI_SendByte + LDI R24, 8 +// 275 +// 276 // Do 8 times. +// 277 while (bytesLeft > 0) { +// 278 // Place the received data in memory. +// 279 *romValue++ = OWI_ReceiveByte(pin); +??OWI_ReadRom_0: + MOV R16, R25 + RCALL OWI_ReceiveByte + ST X+, R16 +// 280 bytesLeft--; + DEC R24 +// 281 } + BRNE ??OWI_ReadRom_0 +// 282 } + REQUIRE ?Subroutine0 + ; // Fall through to label ?Subroutine0 + + RSEG CODE:CODE:NOROOT(1) +?Subroutine0: + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + RET +// 283 +// 284 +// 285 /*! \brief Sends the MATCH ROM command and the ROM id to match against. +// 286 * +// 287 * \param romValue A pointer to the ID to match against. +// 288 * +// 289 * \param pins A bitmask of the buses to perform the MATCH ROM command on. +// 290 */ + + RSEG CODE:CODE:NOROOT(1) +// 291 void OWI_MatchRom(unsigned char * romValue, unsigned char pins) +OWI_MatchRom: +// 292 { + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + MOVW R27:R26, R17:R16 + MOV R25, R18 +// 293 unsigned char bytesLeft = 8; +// 294 +// 295 // Send the MATCH ROM command. +// 296 OWI_SendByte(OWI_ROM_MATCH, pins); + MOV R17, R18 + LDI R16, 85 + RCALL OWI_SendByte + LDI R24, 8 +// 297 +// 298 // Do once for each byte. +// 299 while (bytesLeft > 0) { +// 300 // Transmit 1 byte of the ID to match. +// 301 OWI_SendByte(*romValue++, pins); +??OWI_MatchRom_0: + MOV R17, R25 + LD R16, X+ + RCALL OWI_SendByte +// 302 bytesLeft--; + DEC R24 +// 303 } + BRNE ??OWI_MatchRom_0 +// 304 } + RJMP ?Subroutine0 +// 305 +// 306 +// 307 /*! \brief Sends the SEARCH ROM command and returns 1 id found on the +// 308 * 1-Wire(R) bus. +// 309 * +// 310 * \param bitPattern A pointer to an 8 byte char array where the +// 311 * discovered identifier will be placed. When +// 312 * searching for several slaves, a copy of the +// 313 * last found identifier should be supplied in +// 314 * the array, or the search will fail. +// 315 * +// 316 * \param lastDeviation The bit position where the algorithm made a +// 317 * choice the last time it was run. This argument +// 318 * should be 0 when a search is initiated. Supplying +// 319 * the return argument of this function when calling +// 320 * repeatedly will go through the complete slave +// 321 * search. +// 322 * +// 323 * \param pin A bit-mask of the bus to perform a ROM search on. +// 324 * +// 325 * \return The last bit position where there was a discrepancy between slave +// 326 * addresses the last time this function was run. Returns OWI_ROM_SEARCH_FAILED +// 327 * if an error was detected (e.g. a device was connected to the bus during the +// 328 * search), or OWI_ROM_SEARCH_FINISHED when there are no more devices to be +// 329 * discovered. +// 330 * +// 331 * \note See main.c for an example of how to utilize this function. +// 332 */ + + RSEG CODE:CODE:NOROOT(1) +// 333 unsigned char OWI_SearchRom(unsigned char * bitPattern, +OWI_SearchRom: +// 334 unsigned char lastDeviation, unsigned char pin) +// 335 { + ST -Y, R7 + ST -Y, R6 + ST -Y, R5 + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + REQUIRE ?Register_R7_is_cg_reg + MOVW R27:R26, R17:R16 + MOV R6, R18 + MOV R4, R19 +// 336 unsigned char currentBit = 1; + LDI R24, 1 +// 337 unsigned char newDeviation = 0; + CLR R5 +// 338 unsigned char bitMask = 0x01; + LDI R25, 1 +// 339 unsigned char bitA; +// 340 unsigned char bitB; +// 341 +// 342 // Send SEARCH ROM command on the bus. +// 343 OWI_SendByte(OWI_ROM_SEARCH, pin); + MOV R17, R19 + LDI R16, 240 + RCALL OWI_SendByte +// 344 +// 345 // Walk through all 64 bits. +// 346 while (currentBit <= 64) { +// 347 // Read bit from bus twice. +// 348 bitA = OWI_ReadBit(pin); +??OWI_SearchRom_0: + MOV R16, R4 + RCALL OWI_ReadBit + MOV R7, R16 +// 349 bitB = OWI_ReadBit(pin); + MOV R16, R4 + RCALL OWI_ReadBit +// 350 +// 351 if (bitA && bitB) { + TST R7 + BREQ ??OWI_SearchRom_1 + TST R16 + BREQ ??OWI_SearchRom_1 +// 352 // Both bits 1 (Error). +// 353 newDeviation = OWI_ROM_SEARCH_FAILED; +// 354 return newDeviation; + LDI R16, 255 + RJMP ??OWI_SearchRom_2 +// 355 } else if (bitA ^ bitB) { +??OWI_SearchRom_1: + EOR R16, R7 + BREQ ??OWI_SearchRom_3 +// 356 // Bits A and B are different. All devices have the same bit here. +// 357 // Set the bit in bitPattern to this value. +// 358 if (bitA) { + TST R7 + BREQ ??OWI_SearchRom_4 +// 359 (*bitPattern) |= bitMask; +??OWI_SearchRom_5: + MOVW R31:R30, R27:R26 + LD R16, Z + OR R16, R25 + ST Z, R16 + RJMP ??OWI_SearchRom_6 +// 360 } else { +// 361 (*bitPattern) &= ~bitMask; +??OWI_SearchRom_4: + MOV R16, R25 + COM R16 + LD R17, X + AND R17, R16 + ST X, R17 + RJMP ??OWI_SearchRom_6 +// 362 } +// 363 } else { +// 364 // If this is where a choice was made the last time, +// 365 // a '1' bit is selected this time. +// 366 if (currentBit == lastDeviation) { +??OWI_SearchRom_3: + CP R24, R6 + BREQ ??OWI_SearchRom_5 +// 367 (*bitPattern) |= bitMask; +// 368 } +// 369 +// 370 // For the rest of the id, '0' bits are selected when +// 371 // discrepancies occur. +// 372 else if (currentBit > lastDeviation) { + CP R6, R24 + BRCC ??OWI_SearchRom_7 +// 373 (*bitPattern) &= ~bitMask; + MOV R16, R25 + COM R16 + LD R17, X + AND R17, R16 + ST X, R17 +// 374 newDeviation = currentBit; + RJMP ??OWI_SearchRom_8 +// 375 } +// 376 +// 377 // If current bit in bit pattern = 0, then this is +// 378 // out new deviation. +// 379 else if ( !(*bitPattern & bitMask)) { +??OWI_SearchRom_7: + LD R16, X + AND R16, R25 + BRNE ??OWI_SearchRom_6 +// 380 newDeviation = currentBit; +??OWI_SearchRom_8: + MOV R5, R24 +// 381 } +// 382 +// 383 // IF the bit is already 1, do nothing. +// 384 else { +// 385 } +// 386 } +// 387 +// 388 // Send the selected bit to the bus. +// 389 if ((*bitPattern) & bitMask) { +??OWI_SearchRom_6: + LD R16, X + AND R16, R25 + MOV R16, R4 + BREQ ??OWI_SearchRom_9 +// 390 OWI_WriteBit1(pin); + RCALL OWI_WriteBit1 + RJMP ??OWI_SearchRom_10 +// 391 } else { +// 392 OWI_WriteBit0(pin); +??OWI_SearchRom_9: + RCALL OWI_WriteBit0 +// 393 } +// 394 +// 395 // Increment current bit. +// 396 currentBit++; +??OWI_SearchRom_10: + INC R24 +// 397 +// 398 // Adjust bitMask and bitPattern pointer. +// 399 bitMask <<= 1; + LSL R25 +// 400 if (!bitMask) { + BRNE ??OWI_SearchRom_11 +// 401 bitMask = 0x01; + LDI R25, 1 +// 402 bitPattern++; + ADIW R27:R26, 1 +// 403 } +// 404 } +??OWI_SearchRom_11: + CPI R24, 65 + BRCS ??OWI_SearchRom_0 +// 405 +// 406 return newDeviation; + MOV R16, R5 +??OWI_SearchRom_2: + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + LD R4, Y+ + LD R5, Y+ + LD R6, Y+ + LD R7, Y+ + RET +// 407 } +// 408 +// 409 +// 410 /* Functions for handling CRC */ +// 411 /*! \brief Compute the CRC8 value of a data set. +// 412 * +// 413 * This function will compute the CRC8 or DOW-CRC of inData using seed +// 414 * as inital value for the CRC. +// 415 * +// 416 * \param inData One byte of data to compute CRC from. +// 417 * +// 418 * \param seed The starting value of the CRC. +// 419 * +// 420 * \return The CRC8 of inData with seed as initial value. +// 421 * +// 422 * \note Setting seed to 0 computes the crc8 of the inData. +// 423 * +// 424 * \note Constantly passing the return value of this function +// 425 * As the seed argument computes the CRC8 value of a +// 426 * longer string of data. +// 427 */ + + RSEG CODE:CODE:NOROOT(1) +// 428 unsigned char OWI_ComputeCRC8(unsigned char inData, unsigned char seed) +OWI_ComputeCRC8: +// 429 { +// 430 unsigned char bitsLeft; +// 431 unsigned char temp; +// 432 +// 433 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + LDI R19, 8 +// 434 temp = ((seed ^ inData) & 0x01); +// 435 +// 436 if (temp == 0) { +??OWI_ComputeCRC8_0: + MOV R18, R17 + ANDI R18, 0x01 + MOV R20, R16 + ANDI R20, 0x01 + EOR R20, R18 + BRNE ??OWI_ComputeCRC8_1 +// 437 seed >>= 1; + LSR R17 + RJMP ??OWI_ComputeCRC8_2 +// 438 } else { +// 439 seed ^= 0x18; +// 440 seed >>= 1; +// 441 seed |= 0x80; +??OWI_ComputeCRC8_1: + LDI R18, 24 + EOR R17, R18 + LSR R17 + ORI R17, 0x80 +// 442 } +// 443 +// 444 inData >>= 1; +??OWI_ComputeCRC8_2: + LSR R16 +// 445 } + DEC R19 + BRNE ??OWI_ComputeCRC8_0 +// 446 return seed; + MOV R16, R17 + RET +// 447 } +// 448 +// 449 +// 450 /*! \brief Compute the CRC16 value of a data set. +// 451 * +// 452 * This function will compute the CRC16 of inData using seed +// 453 * as inital value for the CRC. +// 454 * +// 455 * \param inData One byte of data to compute CRC from. +// 456 * +// 457 * \param seed The starting value of the CRC. +// 458 * +// 459 * \return The CRC16 of inData with seed as initial value. +// 460 * +// 461 * \note Setting seed to 0 computes the crc16 of the inData. +// 462 * +// 463 * \note Constantly passing the return value of this function +// 464 * As the seed argument computes the CRC16 value of a +// 465 * longer string of data. +// 466 */ + + RSEG CODE:CODE:NOROOT(1) +// 467 unsigned int OWI_ComputeCRC16(unsigned char inData, unsigned int seed) +OWI_ComputeCRC16: +// 468 { +// 469 unsigned char bitsLeft; +// 470 unsigned char temp; +// 471 +// 472 for (bitsLeft = 8; bitsLeft > 0; bitsLeft--) { + LDI R17, 8 +// 473 temp = ((seed ^ inData) & 0x01); +// 474 +// 475 if (temp == 0) { +??OWI_ComputeCRC16_0: + MOV R20, R18 + ANDI R20, 0x01 + MOV R21, R16 + ANDI R21, 0x01 + EOR R21, R20 + BRNE ??OWI_ComputeCRC16_1 +// 476 seed >>= 1; + LSR R19 + ROR R18 + RJMP ??OWI_ComputeCRC16_2 +// 477 } else { +// 478 seed ^= 0x4002; +// 479 seed >>= 1; +// 480 seed |= 0x8000; +??OWI_ComputeCRC16_1: + LDI R20, 2 + LDI R21, 64 + EOR R20, R18 + EOR R21, R19 + MOVW R19:R18, R21:R20 + LSR R19 + ROR R18 + ORI R19, 0x80 +// 481 } +// 482 +// 483 inData >>= 1; +??OWI_ComputeCRC16_2: + LSR R16 +// 484 } + DEC R17 + BRNE ??OWI_ComputeCRC16_0 +// 485 +// 486 return seed; + MOVW R17:R16, R19:R18 + RET +// 487 } +// 488 +// 489 +// 490 /*! \brief Calculate and check the CRC of a 64 bit ROM identifier. +// 491 * +// 492 * This function computes the CRC8 value of the first 56 bits of a +// 493 * 64 bit identifier. It then checks the calculated value against the +// 494 * CRC value stored in ROM. +// 495 * +// 496 * \param *romValue A pointer to an array holding a 64 bit identifier. +// 497 * +// 498 * \retval OWI_CRC_OK The CRC's matched. +// 499 * \retval OWI_CRC_ERROR Calculated and stored CRC did not match. +// 500 */ + + RSEG CODE:CODE:NOROOT(1) +// 501 unsigned char OWI_CheckRomCRC(unsigned char *romValue) +OWI_CheckRomCRC: +// 502 { + ST -Y, R27 + ST -Y, R26 + ST -Y, R24 + MOVW R27:R26, R17:R16 +// 503 unsigned char i; +// 504 unsigned char crc8 = 0; + LDI R17, 0 +// 505 +// 506 for (i = 0; i < 7; i++) { + LDI R24, 7 +// 507 crc8 = OWI_ComputeCRC8(*romValue, crc8); +??OWI_CheckRomCRC_0: + LD R16, X+ + RCALL OWI_ComputeCRC8 + MOV R17, R16 +// 508 romValue++; +// 509 } + DEC R24 + BRNE ??OWI_CheckRomCRC_0 +// 510 +// 511 if (crc8 == (*romValue)) { + LD R16, X + CP R17, R16 + BRNE ??OWI_CheckRomCRC_1 +// 512 return OWI_CRC_OK; + LDI R16, 0 + RJMP ??OWI_CheckRomCRC_2 +// 513 } +// 514 +// 515 return OWI_CRC_ERROR; +??OWI_CheckRomCRC_1: + LDI R16, 1 +??OWI_CheckRomCRC_2: + LD R24, Y+ + LD R26, Y+ + LD R27, Y+ + RET +// 516 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// +// 3 bytes in segment ABSOLUTE +// 708 bytes in segment CODE +// +// 708 bytes of CODE memory +// 0 bytes of DATA memory (+ 3 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/PWM.lst b/BaseTinyFirmware/IAR/Release/List/PWM.lst new file mode 100644 index 0000000..c523013 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/PWM.lst @@ -0,0 +1,402 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\PWM.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\PWM.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\PW # +# M.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM # +# .r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\PWM.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for use of PWM + 6 * + 7 * Contains functions for initializing and controlling PWM output. + 8 * + 9 * \par Application note: + 10 * AVR458: Charging Li-Ion Batteries with BC100\n + 11 * AVR463: Charging NiMH Batteries with BC100 + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2299 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $ + 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 #include + + \ In segment ABSOLUTE, at 0x50 + \ volatile __io _A_TCCR1A + \ _A_TCCR1A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4f + \ volatile __io _A_TCCR1B + \ _A_TCCR1B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4d + \ volatile __io _A_OCR1A + \ _A_OCR1A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4c + \ volatile __io _A_OCR1B + \ _A_OCR1B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4b + \ volatile __io _A_OCR1C + \ _A_OCR1C: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x4a + \ volatile __io _A_OCR1D + \ _A_OCR1D: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x49 + \ volatile __io _A_PLLCSR + \ _A_PLLCSR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x47 + \ volatile __io _A_TCCR1C + \ _A_TCCR1C: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x46 + \ volatile __io _A_TCCR1D + \ _A_TCCR1D: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x44 + \ volatile __io _A_DT1 + \ _A_DT1: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x37 + \ volatile __io _A_DDRB + \ _A_DDRB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x20 + \ volatile __io _A_TCCR1E + \ _A_TCCR1E: + \ 00000000 DS 1 + 30 + 31 #include "enums.h" + 32 + 33 #include "main.h" + 34 #include "PWM.h" + 35 #include "time.h" + 36 + 37 + 38 //****************************************************************************** + 39 // Functions + 40 //****************************************************************************** + 41 /*! \brief Stops PWM output + 42 * + 43 */ + + \ In segment CODE, align 2, keep-with-next + 44 void PWM_Stop(void) + \ PWM_Stop: + 45 { + 46 OCR1B = 0; // Reset compare level. + \ 00000000 E000 LDI R16, 0 + \ 00000002 BD0C OUT 0x2C, R16 + 47 PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode. + \ 00000004 BD09 OUT 0x29, R16 + 48 TCCR1A = 0; // Set normal port operation, disable PWM modes. + \ 00000006 BF00 OUT 0x30, R16 + 49 TCCR1B = 0; // Stop timer/counter1. + \ 00000008 BD0F OUT 0x2F, R16 + 50 TCCR1C = 0; // Set normal port operation. + \ 0000000A BD07 OUT 0x27, R16 + 51 TCCR1D = 0; // No fault protection, normal waveform. + \ 0000000C BD06 OUT 0x26, R16 + 52 OCR1C = 0; // Reset compare. + \ 0000000E BD0B OUT 0x2B, R16 + 53 OCR1D = 0; // Reset compare. + \ 00000010 BD0A OUT 0x2A, R16 + 54 DT1 = 0; // No dead time values. + \ 00000012 BD04 OUT 0x24, R16 + 55 } + \ 00000014 9508 RET + \ 00000016 REQUIRE _A_TCCR1A + \ 00000016 REQUIRE _A_TCCR1B + \ 00000016 REQUIRE _A_OCR1B + \ 00000016 REQUIRE _A_OCR1C + \ 00000016 REQUIRE _A_OCR1D + \ 00000016 REQUIRE _A_PLLCSR + \ 00000016 REQUIRE _A_TCCR1C + \ 00000016 REQUIRE _A_TCCR1D + \ 00000016 REQUIRE _A_DT1 + 56 + 57 + 58 /*! \brief Initializes and starts PWM output + 59 * + 60 * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n + 61 * Its comparator is connected to PB3 and will output high until timer1 reaches + 62 * the value of OCR1B. It is then dropped to 0.\n + 63 * The comparator outputs high again when the counter overflows, which will + 64 * happen at a rate of 250 kHz. + 65 */ + + \ In segment CODE, align 2, keep-with-next + 66 void PWM_Start(void) + \ PWM_Start: + 67 { + 68 // Clear OC1B on compare match, enable PWM on comparator OCR1B. + 69 TCCR1A = (1< 0) { + \ 00000000 B50C IN R16, 0x2C + \ 00000002 2300 TST R16 + \ 00000004 F029 BREQ ??PWM_DecrementDutyCycle_0 + 145 OCR1B -= 1; + \ 00000006 B50C IN R16, 0x2C + \ 00000008 950A DEC R16 + \ 0000000A BD0C OUT 0x2C, R16 + 146 return(TRUE); + \ 0000000C E001 LDI R16, 1 + \ 0000000E 9508 RET + 147 } else { + 148 return(FALSE); + \ ??PWM_DecrementDutyCycle_0: + \ 00000010 E000 LDI R16, 0 + \ 00000012 9508 RET + \ 00000014 REQUIRE _A_OCR1B + 149 } + 150 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + PWM_DecrementDutyCycle 0 2 + PWM_IncrementDutyCycle 0 2 + PWM_Start 0 2 + -> Time_Set 0 2 + -> Time_Left 0 2 + PWM_Stop 0 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_TCCR1A 1 + _A_TCCR1B 1 + _A_OCR1A 1 + _A_OCR1B 1 + _A_OCR1C 1 + _A_OCR1D 1 + _A_PLLCSR 1 + _A_TCCR1C 1 + _A_TCCR1D 1 + _A_DT1 1 + _A_DDRB 1 + _A_TCCR1E 1 + PWM_Stop 22 + PWM_Start 80 + PWM_IncrementDutyCycle 20 + PWM_DecrementDutyCycle 20 + + + 12 bytes in segment ABSOLUTE + 142 bytes in segment CODE + + 142 bytes of CODE memory + 0 bytes of DATA memory (+ 12 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/PWM.s90 b/BaseTinyFirmware/IAR/Release/List/PWM.s90 new file mode 100644 index 0000000..84e65d6 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/PWM.s90 @@ -0,0 +1,409 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\PWM.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\PWM.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\P / +// WM.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME PWM + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + PUBLIC PWM_DecrementDutyCycle + PUBLIC PWM_IncrementDutyCycle + PUBLIC PWM_Start + PUBLIC PWM_Stop + PUBWEAK _A_DDRB + PUBWEAK _A_DT1 + PUBWEAK _A_OCR1A + PUBWEAK _A_OCR1B + PUBWEAK _A_OCR1C + PUBWEAK _A_OCR1D + PUBWEAK _A_PLLCSR + PUBWEAK _A_TCCR1A + PUBWEAK _A_TCCR1B + PUBWEAK _A_TCCR1C + PUBWEAK _A_TCCR1D + PUBWEAK _A_TCCR1E + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN Time_Set + EXTERN Time_Left + +// C:\home\kevin\pub\src\bc100\IAR\PWM.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for use of PWM +// 6 * +// 7 * Contains functions for initializing and controlling PWM output. +// 8 * +// 9 * \par Application note: +// 10 * AVR458: Charging Li-Ion Batteries with BC100\n +// 11 * AVR463: Charging NiMH Batteries with BC100 +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2299 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/PWM.c $ +// 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 #include + + ASEGN ABSOLUTE:DATA:NOROOT,050H +// volatile __io _A_TCCR1A +_A_TCCR1A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04fH +// volatile __io _A_TCCR1B +_A_TCCR1B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04dH +// volatile __io _A_OCR1A +_A_OCR1A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04cH +// volatile __io _A_OCR1B +_A_OCR1B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04bH +// volatile __io _A_OCR1C +_A_OCR1C: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,04aH +// volatile __io _A_OCR1D +_A_OCR1D: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,049H +// volatile __io _A_PLLCSR +_A_PLLCSR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,047H +// volatile __io _A_TCCR1C +_A_TCCR1C: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,046H +// volatile __io _A_TCCR1D +_A_TCCR1D: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,044H +// volatile __io _A_DT1 +_A_DT1: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,037H +// volatile __io _A_DDRB +_A_DDRB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,020H +// volatile __io _A_TCCR1E +_A_TCCR1E: + DS 1 +// 30 +// 31 #include "enums.h" +// 32 +// 33 #include "main.h" +// 34 #include "PWM.h" +// 35 #include "time.h" +// 36 +// 37 +// 38 //****************************************************************************** +// 39 // Functions +// 40 //****************************************************************************** +// 41 /*! \brief Stops PWM output +// 42 * +// 43 */ + + RSEG CODE:CODE:NOROOT(1) +// 44 void PWM_Stop(void) +PWM_Stop: +// 45 { +// 46 OCR1B = 0; // Reset compare level. + LDI R16, 0 + OUT 0x2C, R16 +// 47 PLLCSR = 0; // Disable PLL, switch to synchronous CLK mode. + OUT 0x29, R16 +// 48 TCCR1A = 0; // Set normal port operation, disable PWM modes. + OUT 0x30, R16 +// 49 TCCR1B = 0; // Stop timer/counter1. + OUT 0x2F, R16 +// 50 TCCR1C = 0; // Set normal port operation. + OUT 0x27, R16 +// 51 TCCR1D = 0; // No fault protection, normal waveform. + OUT 0x26, R16 +// 52 OCR1C = 0; // Reset compare. + OUT 0x2B, R16 +// 53 OCR1D = 0; // Reset compare. + OUT 0x2A, R16 +// 54 DT1 = 0; // No dead time values. + OUT 0x24, R16 +// 55 } + RET + REQUIRE _A_TCCR1A + REQUIRE _A_TCCR1B + REQUIRE _A_OCR1B + REQUIRE _A_OCR1C + REQUIRE _A_OCR1D + REQUIRE _A_PLLCSR + REQUIRE _A_TCCR1C + REQUIRE _A_TCCR1D + REQUIRE _A_DT1 +// 56 +// 57 +// 58 /*! \brief Initializes and starts PWM output +// 59 * +// 60 * Initializes timer1 for use as a PWM with a clock rate of 64 MHz.\n +// 61 * Its comparator is connected to PB3 and will output high until timer1 reaches +// 62 * the value of OCR1B. It is then dropped to 0.\n +// 63 * The comparator outputs high again when the counter overflows, which will +// 64 * happen at a rate of 250 kHz. +// 65 */ + + RSEG CODE:CODE:NOROOT(1) +// 66 void PWM_Start(void) +PWM_Start: +// 67 { +// 68 // Clear OC1B on compare match, enable PWM on comparator OCR1B. +// 69 TCCR1A = (1< 0) { + IN R16, 0x2C + TST R16 + BREQ ??PWM_DecrementDutyCycle_0 +// 145 OCR1B -= 1; + IN R16, 0x2C + DEC R16 + OUT 0x2C, R16 +// 146 return(TRUE); + LDI R16, 1 + RET +// 147 } else { +// 148 return(FALSE); +??PWM_DecrementDutyCycle_0: + LDI R16, 0 + RET + REQUIRE _A_OCR1B +// 149 } +// 150 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// +// 12 bytes in segment ABSOLUTE +// 142 bytes in segment CODE +// +// 142 bytes of CODE memory +// 0 bytes of DATA memory (+ 12 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/USI.lst b/BaseTinyFirmware/IAR/Release/List/USI.lst new file mode 100644 index 0000000..749b2f7 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/USI.lst @@ -0,0 +1,713 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\USI.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\USI.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\US # +# I.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI # +# .r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\USI.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for use of the Universal Serial Interface + 6 * + 7 * Contains high level functions for initializing the USI as an SPI slave, + 8 * interrupt handling, sending and receiving single bytes. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 * + 14 * \par Documentation: + 15 * For comprehensive code documentation, supported compilers, compiler + 16 * settings and supported devices see readme.html + 17 * + 18 * \author + 19 * Atmel Corporation: http://www.atmel.com \n + 20 * Support email: avr@atmel.com \n + 21 * Original author: \n + 22 * + 23 * $Name$ + 24 * $Revision: 2299 $ + 25 * $RCSfile$ + 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $ + 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 28 ******************************************************************************/ + 29 + 30 #include + + \ In segment ABSOLUTE, at 0x38 + \ volatile __io _A_PORTB + \ _A_PORTB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x37 + \ volatile __io _A_DDRB + \ _A_DDRB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x2f + \ volatile __io _A_USIDR + \ _A_USIDR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x2e + \ volatile __io _A_USISR + \ _A_USISR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x2d + \ volatile __io _A_USICR + \ _A_USICR: + \ 00000000 DS 1 + 31 #include + 32 + 33 #include "enums.h" + 34 #include "structs.h" + 35 + 36 #include "main.h" + 37 #include "ADC.h" + 38 #include "battery.h" + 39 #include "time.h" + 40 #include "USI.h" + 41 + 42 + 43 //****************************************************************************** + 44 // Variables + 45 //****************************************************************************** + 46 //! SPI status struct + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 47 SPI_Status_t SPI; + \ SPI: + \ 00000000 DS 4 + 48 + 49 + 50 //****************************************************************************** + 51 //Functions + 52 //***************************************************************************** + 53 /*! \brief USI Counter Overflow Interrupt Service Routine + 54 * + 55 * When the USI counter overflows, a byte has been transferred.\n + 56 * The USIDR contents are stored and flags are updated. + 57 * + 58 * The protocol is quite simple and has three sequential states: command, + 59 * address and data. + 60 * (Keep in mind that the Master is in charge of data clocking, which means + 61 * there is a one byte "delay" from when the Slave puts something to SPI till + 62 * the Master can read it.) + 63 * + 64 * 1. If a non-zero byte is received in the command state, the ISR will + 65 * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of + 66 * bytes). To signal that the command was received, 0xCC is put to the SPI bus. + 67 * If a zero byte (0x00) is received in the command state, it is simply ignored + 68 * because it is an invalid command. + 69 * + 70 * 2. When a byte is received in the address state, it is stored to the SPI + 71 * struct. To signal that the address was received, 0xBB is put to SPI bus. + 72 * + 73 * 3. In the data state, variables are read/written "from back to front" until + 74 * the byte counter reaches zero. Since the Master is in charge of the data + 75 * clocking, the Slave will go to command state before the last byte is + 76 * transferred during reading. This means that the Master should send an + 77 * invalid command when getting each byte, ie 0x00. + 78 * + 79 * If the time between two transfers is 1 second or more, the Slave + 80 * automatically reverts to command state. + 81 * + 82 * \note Battery charging is not automatically halted during SPI communication. + 83 * This means that the current charge state (current and voltage) will + 84 * remain constant during heavy and prolonged serial traffic. + 85 * + 86 * \todo Variable writing not implemented yet. + 87 * \todo EEPROM/SRAM flag doesn't really do anything with this implementation. + 88 */ + 89 #pragma vector=USI_OVF_vect + + \ In segment CODE, align 2, keep-with-next + 90 __interrupt void USI_OVF_ISR(void) + \ USI_OVF_ISR: + 91 { + \ 00000000 938A ST -Y, R24 + \ 00000002 93FA ST -Y, R31 + \ 00000004 93EA ST -Y, R30 + \ 00000006 923A ST -Y, R3 + \ 00000008 922A ST -Y, R2 + \ 0000000A 921A ST -Y, R1 + \ 0000000C 920A ST -Y, R0 + \ 0000000E 937A ST -Y, R23 + \ 00000010 936A ST -Y, R22 + \ 00000012 935A ST -Y, R21 + \ 00000014 934A ST -Y, R20 + \ 00000016 933A ST -Y, R19 + \ 00000018 932A ST -Y, R18 + \ 0000001A 931A ST -Y, R17 + \ 0000001C 930A ST -Y, R16 + \ 0000001E B78F IN R24, 0x3F + 92 // If the communication timed out, set ST_CMD as current state. + 93 if (!Time_Left(TIMER_USI)) { + \ 00000020 E000 LDI R16, 0 + \ 00000022 .... RCALL Time_Left + \ 00000024 2300 TST R16 + \ 00000026 F431 BRNE ??USI_OVF_ISR_0 + 94 SPI.State = ST_CMD; + \ 00000028 .... LDI R30, LOW(SPI) + \ 0000002A .... LDI R31, (SPI) >> 8 + \ 0000002C 8102 LDD R16, Z+2 + \ 0000002E 730F ANDI R16, 0x3F + \ 00000030 6400 ORI R16, 0x40 + \ 00000032 8302 STD Z+2, R16 + 95 } + 96 + 97 // Start communication timer. If further communication doesn't happen + 98 // within 1 second, the SPI communication state is reset to CMD. + 99 Time_Set(TIMER_USI, 0, 1, 0); + \ ??USI_OVF_ISR_0: + \ 00000034 E040 LDI R20, 0 + \ 00000036 E011 LDI R17, 1 + \ 00000038 E020 LDI R18, 0 + \ 0000003A E030 LDI R19, 0 + \ 0000003C E000 LDI R16, 0 + \ 0000003E .... RCALL Time_Set + 100 + 101 // Clear USI counter and flag completed transfer. + 102 USISR = (1<> 8 + \ 00000048 8103 LDD R16, Z+3 + \ 0000004A 6004 ORI R16, 0x04 + \ 0000004C 8303 STD Z+3, R16 + 104 + 105 // Process incoming data. + 106 switch(SPI.State) { + \ 0000004E 8112 LDD R17, Z+2 + \ 00000050 2F01 MOV R16, R17 + \ 00000052 0F00 LSL R16 + \ 00000054 1F00 ROL R16 + \ 00000056 1F00 ROL R16 + \ 00000058 7003 ANDI R16, 0x03 + \ 0000005A 5001 SUBI R16, 1 + \ 0000005C F029 BREQ ??USI_OVF_ISR_1 + \ 0000005E 950A DEC R16 + \ 00000060 F101 BREQ ??USI_OVF_ISR_2 + \ 00000062 950A DEC R16 + \ 00000064 F131 BREQ ??USI_OVF_ISR_3 + \ 00000066 C072 RJMP ??USI_OVF_ISR_4 + 107 // A valid SPI transfer starts with a Command Byte sent by the Master. + 108 case ST_CMD: + 109 SPI.Data = USIDR; // Store the transferred byte. + \ ??USI_OVF_ISR_1: + \ 00000068 B10F IN R16, 0x0F + \ 0000006A 8300 ST Z, R16 + 110 + 111 // If the master sent 0, it is trying to get data. Ignore in this state. + 112 if (SPI.Data != 0) { + \ 0000006C 2300 TST R16 + \ 0000006E F409 BRNE $+2+2 + \ 00000070 C06D RJMP ??USI_OVF_ISR_4 + 113 // Does the master want to read or write? + 114 if (SPI.Data & 0x40) { + \ 00000072 FF06 SBRS R16, 6 + \ 00000074 C003 RJMP ??USI_OVF_ISR_5 + 115 SPI.Read = FALSE; + \ 00000076 8103 LDD R16, Z+3 + \ 00000078 7F0E ANDI R16, 0xFE + \ 0000007A C002 RJMP ??USI_OVF_ISR_6 + 116 } else { + 117 SPI.Read = TRUE; + \ ??USI_OVF_ISR_5: + \ 0000007C 8103 LDD R16, Z+3 + \ 0000007E 6001 ORI R16, 0x01 + \ ??USI_OVF_ISR_6: + \ 00000080 8303 STD Z+3, R16 + 118 } + 119 + 120 // From/to EEPROM or SRAM? + 121 if (SPI.Data &0x80) { + \ 00000082 8100 LD R16, Z + \ 00000084 FF07 SBRS R16, 7 + \ 00000086 C003 RJMP ??USI_OVF_ISR_7 + 122 SPI.EEPROM = TRUE; + \ 00000088 8103 LDD R16, Z+3 + \ 0000008A 6002 ORI R16, 0x02 + \ 0000008C C002 RJMP ??USI_OVF_ISR_8 + 123 } else { + 124 SPI.EEPROM = FALSE; + \ ??USI_OVF_ISR_7: + \ 0000008E 8103 LDD R16, Z+3 + \ 00000090 7F0D ANDI R16, 0xFD + \ ??USI_OVF_ISR_8: + \ 00000092 8303 STD Z+3, R16 + 125 } + 126 + 127 SPI.Count = (SPI.Data & 0x3F); // Get number of bytes to receive/send. + 128 SPI.State = ST_ADDR; // The Master will send the address byte next. + \ 00000094 8100 LD R16, Z + \ 00000096 730F ANDI R16, 0x3F + \ 00000098 6800 ORI R16, 0x80 + \ 0000009A 8302 STD Z+2, R16 + 129 + 130 SPI_Put(0xCC); // Signal that command was received. + \ 0000009C EC0C LDI R16, 204 + \ ??USI_OVF_ISR_9: + \ 0000009E .... RCALL SPI_Put + \ 000000A0 C055 RJMP ??USI_OVF_ISR_4 + 131 } + 132 break; + 133 + 134 + 135 case ST_ADDR: + 136 SPI.Data = USIDR; // Store the address. + \ ??USI_OVF_ISR_2: + \ 000000A2 B10F IN R16, 0x0F + \ 000000A4 8300 ST Z, R16 + 137 SPI.Address = SPI.Data; + \ 000000A6 8301 STD Z+1, R16 + 138 SPI.State = ST_DATA; // The master will send/wait for data next. + \ 000000A8 2F01 MOV R16, R17 + \ 000000AA 6C00 ORI R16, 0xC0 + \ 000000AC 8302 STD Z+2, R16 + 139 + 140 SPI_Put(0xBB); // Signal that address was received. + \ 000000AE EB0B LDI R16, 187 + \ 000000B0 CFF6 RJMP ??USI_OVF_ISR_9 + 141 break; + 142 + 143 + 144 // Note well: this will process at least one byte, regardless of Count. + 145 case ST_DATA: + 146 if (SPI.Count-- > 0) { + \ ??USI_OVF_ISR_3: + \ 000000B2 2F21 MOV R18, R17 + \ 000000B4 7C10 ANDI R17, 0xC0 + \ 000000B6 2F02 MOV R16, R18 + \ 000000B8 950A DEC R16 + \ 000000BA 730F ANDI R16, 0x3F + \ 000000BC 2B01 OR R16, R17 + \ 000000BE 8302 STD Z+2, R16 + \ 000000C0 732F ANDI R18, 0x3F + \ 000000C2 F409 BRNE $+2+2 + \ 000000C4 C040 RJMP ??USI_OVF_ISR_10 + 147 // Write specified variable to SPI, "back to front". + 148 if (SPI.Read) { + \ 000000C6 8121 LDD R18, Z+1 + \ 000000C8 8113 LDD R17, Z+3 + \ 000000CA FF10 SBRS R17, 0 + \ 000000CC C02E RJMP ??USI_OVF_ISR_11 + 149 switch (SPI.Address) { + \ 000000CE 952A DEC R18 + \ 000000D0 F049 BREQ ??USI_OVF_ISR_12 + \ 000000D2 952A DEC R18 + \ 000000D4 F071 BREQ ??USI_OVF_ISR_13 + \ 000000D6 952A DEC R18 + \ 000000D8 F091 BREQ ??USI_OVF_ISR_14 + \ 000000DA 952A DEC R18 + \ 000000DC F0B1 BREQ ??USI_OVF_ISR_15 + \ 000000DE 952A DEC R18 + \ 000000E0 F0E1 BREQ ??USI_OVF_ISR_16 + \ 000000E2 C021 RJMP ??USI_OVF_ISR_17 + 150 case ADR_ADCS: + 151 SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count))); + \ ??USI_OVF_ISR_12: + \ 000000E4 730F ANDI R16, 0x3F + \ 000000E6 E010 LDI R17, 0 + \ 000000E8 01F8 MOVW R31:R30, R17:R16 + \ 000000EA .... SUBI R30, LOW((-(ADCS) & 0xFFFF)) + \ 000000EC .... SBCI R31, (-(ADCS) & 0xFFFF) >> 8 + \ ??USI_OVF_ISR_18: + \ 000000EE 8100 LD R16, Z + \ 000000F0 CFD6 RJMP ??USI_OVF_ISR_9 + 152 break; + 153 + 154 + 155 case ADR_BATTACTIVE: + 156 SPI_Put(*((unsigned char*)&BattActive + (SPI.Count))); + \ ??USI_OVF_ISR_13: + \ 000000F2 730F ANDI R16, 0x3F + \ 000000F4 E010 LDI R17, 0 + \ 000000F6 01F8 MOVW R31:R30, R17:R16 + \ 000000F8 .... SUBI R30, LOW((-(BattActive) & 0xFFFF)) + \ 000000FA .... SBCI R31, (-(BattActive) & 0xFFFF) >> 8 + \ 000000FC CFF8 RJMP ??USI_OVF_ISR_18 + 157 break; + 158 + 159 + 160 case ADR_BATTDATA: + 161 SPI_Put(*((unsigned char*)&BattData + (SPI.Count))); + \ ??USI_OVF_ISR_14: + \ 000000FE 730F ANDI R16, 0x3F + \ 00000100 E010 LDI R17, 0 + \ 00000102 01F8 MOVW R31:R30, R17:R16 + \ 00000104 .... SUBI R30, LOW((-(BattData) & 0xFFFF)) + \ 00000106 .... SBCI R31, (-(BattData) & 0xFFFF) >> 8 + \ 00000108 CFF2 RJMP ??USI_OVF_ISR_18 + 162 break; + 163 + 164 + 165 case ADR_BATTCTRL: + 166 SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count))); + \ ??USI_OVF_ISR_15: + \ 0000010A 730F ANDI R16, 0x3F + \ 0000010C E010 LDI R17, 0 + \ 0000010E .... LDI R20, LOW(BattControl) + \ 00000110 .... LDI R21, (BattControl) >> 8 + \ 00000112 0F40 ADD R20, R16 + \ 00000114 1F51 ADC R21, R17 + \ 00000116 .... RCALL __eeget8_16 + \ 00000118 CFC2 RJMP ??USI_OVF_ISR_9 + 167 break; + 168 + 169 case ADR_TIMERS: + 170 SPI_Put(*((unsigned char*)&timeval + (SPI.Count))); + \ ??USI_OVF_ISR_16: + \ 0000011A 730F ANDI R16, 0x3F + \ 0000011C E010 LDI R17, 0 + \ 0000011E 01F8 MOVW R31:R30, R17:R16 + \ 00000120 .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 00000122 .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000124 CFE4 RJMP ??USI_OVF_ISR_18 + 171 break; + 172 + 173 + 174 default: + 175 SPI_Put(0); + \ ??USI_OVF_ISR_17: + \ 00000126 E000 LDI R16, 0 + \ 00000128 CFBA RJMP ??USI_OVF_ISR_9 + 176 break; + 177 } + 178 } else { + 179 // Read byte from SPI + 180 SPI.Data = USIDR; + \ ??USI_OVF_ISR_11: + \ 0000012A B11F IN R17, 0x0F + \ 0000012C 8310 ST Z, R17 + 181 + 182 // ******************************************** + 183 // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED + 184 // ******************************************** + 185 + 186 // Save byte to specified variable. + 187 switch (SPI.Address) { + \ 0000012E 5024 SUBI R18, 4 + \ 00000130 F469 BRNE ??USI_OVF_ISR_4 + 188 case ADR_BATTCTRL: + 189 *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data; + \ 00000132 2F21 MOV R18, R17 + \ 00000134 730F ANDI R16, 0x3F + \ 00000136 E010 LDI R17, 0 + \ 00000138 .... LDI R20, LOW(BattControl) + \ 0000013A .... LDI R21, (BattControl) >> 8 + \ 0000013C 0F40 ADD R20, R16 + \ 0000013E 1F51 ADC R21, R17 + \ 00000140 2F02 MOV R16, R18 + \ 00000142 .... RCALL __eeput8_16 + \ 00000144 C003 RJMP ??USI_OVF_ISR_4 + 190 break; + 191 + 192 + 193 default: + 194 break; + 195 } + 196 } + 197 + 198 + 199 } else { + 200 SPI.State = ST_CMD; + \ ??USI_OVF_ISR_10: + \ 00000146 730F ANDI R16, 0x3F + \ 00000148 6400 ORI R16, 0x40 + \ 0000014A 8302 STD Z+2, R16 + 201 } + 202 break; + 203 + 204 default: // Shouldn't end up here. (Unknown SPI-state) + 205 break; + 206 } + 207 } + \ ??USI_OVF_ISR_4: + \ 0000014C BF8F OUT 0x3F, R24 + \ 0000014E 9109 LD R16, Y+ + \ 00000150 9119 LD R17, Y+ + \ 00000152 9129 LD R18, Y+ + \ 00000154 9139 LD R19, Y+ + \ 00000156 9149 LD R20, Y+ + \ 00000158 9159 LD R21, Y+ + \ 0000015A 9169 LD R22, Y+ + \ 0000015C 9179 LD R23, Y+ + \ 0000015E 9009 LD R0, Y+ + \ 00000160 9019 LD R1, Y+ + \ 00000162 9029 LD R2, Y+ + \ 00000164 9039 LD R3, Y+ + \ 00000166 91E9 LD R30, Y+ + \ 00000168 91F9 LD R31, Y+ + \ 0000016A 9189 LD R24, Y+ + \ 0000016C 9518 RETI + \ 0000016E REQUIRE _A_USIDR + \ 0000016E REQUIRE _A_USISR + 208 + 209 + 210 /*! \brief Initializes USI as an SPI slave + 211 * + 212 * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for + 213 * I/O and clock, and USI counter overflow interrupts enabled.\n + 214 * Also initializes the SPI status struct. + 215 * + 216 * \param spi_mode Specifies if USI should trigger on positive (0) or negative + 217 * (1) edge of clock signal + 218 * + 219 * \note Clears the stored data + 220 * + 221 * \todo Timer should reset SPI protocol on timeout + 222 */ + + \ In segment CODE, align 2, keep-with-next + 223 void SPI_Init(unsigned char spi_mode) + \ SPI_Init: + 224 { + 225 __disable_interrupt(); + \ 00000000 94F8 CLI + 226 + 227 // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. + 228 USI_DIR_REG |= (1<> 8 + \ 0000001C E000 LDI R16, 0 + \ 0000001E 8300 ST Z, R16 + 237 SPI.State = ST_CMD; // Initial SPI state: wait for command. + 238 SPI.Read = FALSE; // Doesn't matter right now. + 239 SPI.EEPROM = FALSE; // Doesn't matter right now. + \ 00000020 8103 LDD R16, Z+3 + \ 00000022 7F0C ANDI R16, 0xFC + \ 00000024 8303 STD Z+3, R16 + 240 SPI.Count = 0; // Doesn't matter right now. + \ 00000026 E400 LDI R16, 64 + \ 00000028 8302 STD Z+2, R16 + 241 SPI.Address = 0; // Doesn't matter right now. + \ 0000002A E000 LDI R16, 0 + \ 0000002C 8301 STD Z+1, R16 + 242 SPI.XferComplete = FALSE; // We haven't even started a transfer yet. + 243 SPI.WriteCollision = FALSE; // ..And therefore a collision hasn't happened. + \ 0000002E 8103 LDD R16, Z+3 + \ 00000030 7F03 ANDI R16, 0xF3 + \ 00000032 8303 STD Z+3, R16 + 244 + 245 __enable_interrupt(); + \ 00000034 9478 SEI + 246 } + \ 00000036 9508 RET + \ 00000038 REQUIRE _A_PORTB + \ 00000038 REQUIRE _A_DDRB + \ 00000038 REQUIRE _A_USICR + 247 + 248 + 249 // Put one byte on bus. Use this function like you would write to the SPDR + 250 // register in the native SPI module. Calling this function will prepare a + 251 // byte for the next transfer initiated by the master device. If a transfer + 252 // is in progress, this function will set the write collision flag and return + 253 // without altering the data registers. + 254 // + 255 // Returns 0 if a write collision occurred, 1 otherwise. + 256 /*! \brief Write a byte to SPI bus + 257 * + 258 * This function first checks if a transmission is in progress, and if so, flags + 259 * a write collision, and returns FALSE.\n + 260 * If a transmission is not in progress, the flags for write collision and + 261 * transfer complete are cleared, and the input byte is written to SPDR.\n + 262 * + 263 * \param val The byte to send. + 264 * + 265 * \retval FALSE A write collision happened. + 266 * \retval TRUE Byte written to SPDR. + 267 */ + + \ In segment CODE, align 2, keep-with-next + 268 unsigned char SPI_Put(unsigned char val) + \ SPI_Put: + 269 { + 270 // Check if transmission in progress, i.e. if USI counter doesn't equal zero. + 271 // If this fails, flag a write collision and return. + 272 if((USISR & 0x0F) != 0) { + \ 00000000 B11E IN R17, 0x0E + \ 00000002 701F ANDI R17, 0x0F + \ 00000004 .... LDI R30, LOW(SPI) + \ 00000006 .... LDI R31, (SPI) >> 8 + \ 00000008 F029 BREQ ??SPI_Put_0 + 273 SPI.WriteCollision = TRUE; + \ 0000000A 8103 LDD R16, Z+3 + \ 0000000C 6008 ORI R16, 0x08 + \ 0000000E 8303 STD Z+3, R16 + 274 return(FALSE); + \ 00000010 E000 LDI R16, 0 + \ 00000012 9508 RET + 275 } + 276 + 277 // Reinitialize flags. + 278 SPI.XferComplete = FALSE; + 279 SPI.WriteCollision = FALSE; + \ ??SPI_Put_0: + \ 00000014 8113 LDD R17, Z+3 + \ 00000016 7F13 ANDI R17, 0xF3 + \ 00000018 8313 STD Z+3, R17 + 280 + 281 USIDR = val; // Put data in USI data register. + \ 0000001A B90F OUT 0x0F, R16 + 282 + 283 return (TRUE); + \ 0000001C E001 LDI R16, 1 + \ 0000001E 9508 RET + \ 00000020 REQUIRE _A_USIDR + \ 00000020 REQUIRE _A_USISR + 284 } + 285 + 286 + 287 // Get one byte from bus. This function only returns the previous stored + 288 // USIDR value. The transfer complete flag is not checked. Use this function + 289 // like you would read from the SPDR register in the native SPI module. + 290 /*! \brief Get the last byte received from SPI bus + 291 * + 292 * This function simply returns the last byte stored to the SPI status struct, + 293 * without checking if a completed transfer is flagged. + 294 * + 295 * \retval SPI.Data The last byte read from SPI. + 296 */ + + \ In segment CODE, align 2, keep-with-next + 297 unsigned char SPI_Get(void) + \ SPI_Get: + 298 { + 299 return SPI.Data; + \ 00000000 9100.... LDS R16, SPI + \ 00000004 9508 RET + 300 } + 301 + 302 + 303 /*! \brief Wait for SPI transfer to complete + 304 * + 305 * This function waits for a transfer complete to be flagged. + 306 */ + + \ In segment CODE, align 2, keep-with-next + 307 void SPI_Wait(void) + \ SPI_Wait: + 308 { + \ 00000000 9100.... LDS R16, (SPI + 3) + \ 00000004 FF02 SBRS R16, 2 + 309 do { // Wait for transfer complete. + 310 } while (SPI.XferComplete == FALSE); + \ ??SPI_Wait_0: + \ 00000006 CFFF RJMP ??SPI_Wait_0 + 311 } + \ ??SPI_Wait_1: + \ 00000008 9508 RET + + \ In segment INTVEC, offset 0x10, root + \ `??USI_OVF_ISR??INTVEC 16`: + \ 00000010 .... RJMP USI_OVF_ISR + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + SPI_Get 0 2 + SPI_Init 0 2 + SPI_Put 0 2 + SPI_Wait 0 2 + USI_OVF_ISR 15 4 + -> Time_Left 15 2 + -> Time_Set 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + -> SPI_Put 15 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_PORTB 1 + _A_DDRB 1 + _A_USIDR 1 + _A_USISR 1 + _A_USICR 1 + SPI 4 + USI_OVF_ISR 366 + SPI_Init 56 + SPI_Put 32 + SPI_Get 6 + SPI_Wait 10 + ??USI_OVF_ISR??INTVEC 16 2 + Others 6 + + + 5 bytes in segment ABSOLUTE + 470 bytes in segment CODE + 6 bytes in segment INITTAB + 2 bytes in segment INTVEC + 4 bytes in segment NEAR_Z + + 470 bytes of CODE memory (+ 8 bytes shared) + 4 bytes of DATA memory (+ 5 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/USI.s90 b/BaseTinyFirmware/IAR/Release/List/USI.s90 new file mode 100644 index 0000000..ae4ae09 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/USI.s90 @@ -0,0 +1,731 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\USI.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\USI.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\U / +// SI.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME USI + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?need_segment_init + EXTERN __eeget8_16 + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBWEAK `??USI_OVF_ISR??INTVEC 16` + PUBLIC SPI + PUBLIC SPI_Get + PUBLIC SPI_Init + PUBLIC SPI_Put + PUBLIC SPI_Wait + PUBLIC USI_OVF_ISR + PUBWEAK _A_DDRB + PUBWEAK _A_PORTB + PUBWEAK _A_USICR + PUBWEAK _A_USIDR + PUBWEAK _A_USISR + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + +USI_OVF_ISR SYMBOL "USI_OVF_ISR" +`??USI_OVF_ISR??INTVEC 16` SYMBOL "??INTVEC 16", USI_OVF_ISR + + EXTERN Time_Left + EXTERN Time_Set + EXTERN ADCS + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + EXTERN timeval + +// C:\home\kevin\pub\src\bc100\IAR\USI.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for use of the Universal Serial Interface +// 6 * +// 7 * Contains high level functions for initializing the USI as an SPI slave, +// 8 * interrupt handling, sending and receiving single bytes. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 * +// 14 * \par Documentation: +// 15 * For comprehensive code documentation, supported compilers, compiler +// 16 * settings and supported devices see readme.html +// 17 * +// 18 * \author +// 19 * Atmel Corporation: http://www.atmel.com \n +// 20 * Support email: avr@atmel.com \n +// 21 * Original author: \n +// 22 * +// 23 * $Name$ +// 24 * $Revision: 2299 $ +// 25 * $RCSfile$ +// 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $ +// 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 28 ******************************************************************************/ +// 29 +// 30 #include + + ASEGN ABSOLUTE:DATA:NOROOT,038H +// volatile __io _A_PORTB +_A_PORTB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,037H +// volatile __io _A_DDRB +_A_DDRB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,02fH +// volatile __io _A_USIDR +_A_USIDR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,02eH +// volatile __io _A_USISR +_A_USISR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,02dH +// volatile __io _A_USICR +_A_USICR: + DS 1 +// 31 #include +// 32 +// 33 #include "enums.h" +// 34 #include "structs.h" +// 35 +// 36 #include "main.h" +// 37 #include "ADC.h" +// 38 #include "battery.h" +// 39 #include "time.h" +// 40 #include "USI.h" +// 41 +// 42 +// 43 //****************************************************************************** +// 44 // Variables +// 45 //****************************************************************************** +// 46 //! SPI status struct + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 47 SPI_Status_t SPI; +SPI: + DS 4 +// 48 +// 49 +// 50 //****************************************************************************** +// 51 //Functions +// 52 //***************************************************************************** +// 53 /*! \brief USI Counter Overflow Interrupt Service Routine +// 54 * +// 55 * When the USI counter overflows, a byte has been transferred.\n +// 56 * The USIDR contents are stored and flags are updated. +// 57 * +// 58 * The protocol is quite simple and has three sequential states: command, +// 59 * address and data. +// 60 * (Keep in mind that the Master is in charge of data clocking, which means +// 61 * there is a one byte "delay" from when the Slave puts something to SPI till +// 62 * the Master can read it.) +// 63 * +// 64 * 1. If a non-zero byte is received in the command state, the ISR will +// 65 * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of +// 66 * bytes). To signal that the command was received, 0xCC is put to the SPI bus. +// 67 * If a zero byte (0x00) is received in the command state, it is simply ignored +// 68 * because it is an invalid command. +// 69 * +// 70 * 2. When a byte is received in the address state, it is stored to the SPI +// 71 * struct. To signal that the address was received, 0xBB is put to SPI bus. +// 72 * +// 73 * 3. In the data state, variables are read/written "from back to front" until +// 74 * the byte counter reaches zero. Since the Master is in charge of the data +// 75 * clocking, the Slave will go to command state before the last byte is +// 76 * transferred during reading. This means that the Master should send an +// 77 * invalid command when getting each byte, ie 0x00. +// 78 * +// 79 * If the time between two transfers is 1 second or more, the Slave +// 80 * automatically reverts to command state. +// 81 * +// 82 * \note Battery charging is not automatically halted during SPI communication. +// 83 * This means that the current charge state (current and voltage) will +// 84 * remain constant during heavy and prolonged serial traffic. +// 85 * +// 86 * \todo Variable writing not implemented yet. +// 87 * \todo EEPROM/SRAM flag doesn't really do anything with this implementation. +// 88 */ +// 89 #pragma vector=USI_OVF_vect + + RSEG CODE:CODE:NOROOT(1) +// 90 __interrupt void USI_OVF_ISR(void) +USI_OVF_ISR: +// 91 { + ST -Y, R24 + ST -Y, R31 + ST -Y, R30 + ST -Y, R3 + ST -Y, R2 + ST -Y, R1 + ST -Y, R0 + ST -Y, R23 + ST -Y, R22 + ST -Y, R21 + ST -Y, R20 + ST -Y, R19 + ST -Y, R18 + ST -Y, R17 + ST -Y, R16 + IN R24, 0x3F +// 92 // If the communication timed out, set ST_CMD as current state. +// 93 if (!Time_Left(TIMER_USI)) { + LDI R16, 0 + RCALL Time_Left + TST R16 + BRNE ??USI_OVF_ISR_0 +// 94 SPI.State = ST_CMD; + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + LDD R16, Z+2 + ANDI R16, 0x3F + ORI R16, 0x40 + STD Z+2, R16 +// 95 } +// 96 +// 97 // Start communication timer. If further communication doesn't happen +// 98 // within 1 second, the SPI communication state is reset to CMD. +// 99 Time_Set(TIMER_USI, 0, 1, 0); +??USI_OVF_ISR_0: + LDI R20, 0 + LDI R17, 1 + LDI R18, 0 + LDI R19, 0 + LDI R16, 0 + RCALL Time_Set +// 100 +// 101 // Clear USI counter and flag completed transfer. +// 102 USISR = (1<> 8 + LDD R16, Z+3 + ORI R16, 0x04 + STD Z+3, R16 +// 104 +// 105 // Process incoming data. +// 106 switch(SPI.State) { + LDD R17, Z+2 + MOV R16, R17 + LSL R16 + ROL R16 + ROL R16 + ANDI R16, 0x03 + SUBI R16, 1 + BREQ ??USI_OVF_ISR_1 + DEC R16 + BREQ ??USI_OVF_ISR_2 + DEC R16 + BREQ ??USI_OVF_ISR_3 + RJMP ??USI_OVF_ISR_4 +// 107 // A valid SPI transfer starts with a Command Byte sent by the Master. +// 108 case ST_CMD: +// 109 SPI.Data = USIDR; // Store the transferred byte. +??USI_OVF_ISR_1: + IN R16, 0x0F + ST Z, R16 +// 110 +// 111 // If the master sent 0, it is trying to get data. Ignore in this state. +// 112 if (SPI.Data != 0) { + TST R16 + BRNE $+2+2 + RJMP ??USI_OVF_ISR_4 +// 113 // Does the master want to read or write? +// 114 if (SPI.Data & 0x40) { + SBRS R16, 6 + RJMP ??USI_OVF_ISR_5 +// 115 SPI.Read = FALSE; + LDD R16, Z+3 + ANDI R16, 0xFE + RJMP ??USI_OVF_ISR_6 +// 116 } else { +// 117 SPI.Read = TRUE; +??USI_OVF_ISR_5: + LDD R16, Z+3 + ORI R16, 0x01 +??USI_OVF_ISR_6: + STD Z+3, R16 +// 118 } +// 119 +// 120 // From/to EEPROM or SRAM? +// 121 if (SPI.Data &0x80) { + LD R16, Z + SBRS R16, 7 + RJMP ??USI_OVF_ISR_7 +// 122 SPI.EEPROM = TRUE; + LDD R16, Z+3 + ORI R16, 0x02 + RJMP ??USI_OVF_ISR_8 +// 123 } else { +// 124 SPI.EEPROM = FALSE; +??USI_OVF_ISR_7: + LDD R16, Z+3 + ANDI R16, 0xFD +??USI_OVF_ISR_8: + STD Z+3, R16 +// 125 } +// 126 +// 127 SPI.Count = (SPI.Data & 0x3F); // Get number of bytes to receive/send. +// 128 SPI.State = ST_ADDR; // The Master will send the address byte next. + LD R16, Z + ANDI R16, 0x3F + ORI R16, 0x80 + STD Z+2, R16 +// 129 +// 130 SPI_Put(0xCC); // Signal that command was received. + LDI R16, 204 +??USI_OVF_ISR_9: + RCALL SPI_Put + RJMP ??USI_OVF_ISR_4 +// 131 } +// 132 break; +// 133 +// 134 +// 135 case ST_ADDR: +// 136 SPI.Data = USIDR; // Store the address. +??USI_OVF_ISR_2: + IN R16, 0x0F + ST Z, R16 +// 137 SPI.Address = SPI.Data; + STD Z+1, R16 +// 138 SPI.State = ST_DATA; // The master will send/wait for data next. + MOV R16, R17 + ORI R16, 0xC0 + STD Z+2, R16 +// 139 +// 140 SPI_Put(0xBB); // Signal that address was received. + LDI R16, 187 + RJMP ??USI_OVF_ISR_9 +// 141 break; +// 142 +// 143 +// 144 // Note well: this will process at least one byte, regardless of Count. +// 145 case ST_DATA: +// 146 if (SPI.Count-- > 0) { +??USI_OVF_ISR_3: + MOV R18, R17 + ANDI R17, 0xC0 + MOV R16, R18 + DEC R16 + ANDI R16, 0x3F + OR R16, R17 + STD Z+2, R16 + ANDI R18, 0x3F + BRNE $+2+2 + RJMP ??USI_OVF_ISR_10 +// 147 // Write specified variable to SPI, "back to front". +// 148 if (SPI.Read) { + LDD R18, Z+1 + LDD R17, Z+3 + SBRS R17, 0 + RJMP ??USI_OVF_ISR_11 +// 149 switch (SPI.Address) { + DEC R18 + BREQ ??USI_OVF_ISR_12 + DEC R18 + BREQ ??USI_OVF_ISR_13 + DEC R18 + BREQ ??USI_OVF_ISR_14 + DEC R18 + BREQ ??USI_OVF_ISR_15 + DEC R18 + BREQ ??USI_OVF_ISR_16 + RJMP ??USI_OVF_ISR_17 +// 150 case ADR_ADCS: +// 151 SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count))); +??USI_OVF_ISR_12: + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(ADCS) & 0xFFFF)) + SBCI R31, (-(ADCS) & 0xFFFF) >> 8 +??USI_OVF_ISR_18: + LD R16, Z + RJMP ??USI_OVF_ISR_9 +// 152 break; +// 153 +// 154 +// 155 case ADR_BATTACTIVE: +// 156 SPI_Put(*((unsigned char*)&BattActive + (SPI.Count))); +??USI_OVF_ISR_13: + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(BattActive) & 0xFFFF)) + SBCI R31, (-(BattActive) & 0xFFFF) >> 8 + RJMP ??USI_OVF_ISR_18 +// 157 break; +// 158 +// 159 +// 160 case ADR_BATTDATA: +// 161 SPI_Put(*((unsigned char*)&BattData + (SPI.Count))); +??USI_OVF_ISR_14: + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(BattData) & 0xFFFF)) + SBCI R31, (-(BattData) & 0xFFFF) >> 8 + RJMP ??USI_OVF_ISR_18 +// 162 break; +// 163 +// 164 +// 165 case ADR_BATTCTRL: +// 166 SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count))); +??USI_OVF_ISR_15: + ANDI R16, 0x3F + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + RJMP ??USI_OVF_ISR_9 +// 167 break; +// 168 +// 169 case ADR_TIMERS: +// 170 SPI_Put(*((unsigned char*)&timeval + (SPI.Count))); +??USI_OVF_ISR_16: + ANDI R16, 0x3F + LDI R17, 0 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + RJMP ??USI_OVF_ISR_18 +// 171 break; +// 172 +// 173 +// 174 default: +// 175 SPI_Put(0); +??USI_OVF_ISR_17: + LDI R16, 0 + RJMP ??USI_OVF_ISR_9 +// 176 break; +// 177 } +// 178 } else { +// 179 // Read byte from SPI +// 180 SPI.Data = USIDR; +??USI_OVF_ISR_11: + IN R17, 0x0F + ST Z, R17 +// 181 +// 182 // ******************************************** +// 183 // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED +// 184 // ******************************************** +// 185 +// 186 // Save byte to specified variable. +// 187 switch (SPI.Address) { + SUBI R18, 4 + BRNE ??USI_OVF_ISR_4 +// 188 case ADR_BATTCTRL: +// 189 *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data; + MOV R18, R17 + ANDI R16, 0x3F + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + MOV R16, R18 + RCALL __eeput8_16 + RJMP ??USI_OVF_ISR_4 +// 190 break; +// 191 +// 192 +// 193 default: +// 194 break; +// 195 } +// 196 } +// 197 +// 198 +// 199 } else { +// 200 SPI.State = ST_CMD; +??USI_OVF_ISR_10: + ANDI R16, 0x3F + ORI R16, 0x40 + STD Z+2, R16 +// 201 } +// 202 break; +// 203 +// 204 default: // Shouldn't end up here. (Unknown SPI-state) +// 205 break; +// 206 } +// 207 } +??USI_OVF_ISR_4: + OUT 0x3F, R24 + LD R16, Y+ + LD R17, Y+ + LD R18, Y+ + LD R19, Y+ + LD R20, Y+ + LD R21, Y+ + LD R22, Y+ + LD R23, Y+ + LD R0, Y+ + LD R1, Y+ + LD R2, Y+ + LD R3, Y+ + LD R30, Y+ + LD R31, Y+ + LD R24, Y+ + RETI + REQUIRE _A_USIDR + REQUIRE _A_USISR +// 208 +// 209 +// 210 /*! \brief Initializes USI as an SPI slave +// 211 * +// 212 * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for +// 213 * I/O and clock, and USI counter overflow interrupts enabled.\n +// 214 * Also initializes the SPI status struct. +// 215 * +// 216 * \param spi_mode Specifies if USI should trigger on positive (0) or negative +// 217 * (1) edge of clock signal +// 218 * +// 219 * \note Clears the stored data +// 220 * +// 221 * \todo Timer should reset SPI protocol on timeout +// 222 */ + + RSEG CODE:CODE:NOROOT(1) +// 223 void SPI_Init(unsigned char spi_mode) +SPI_Init: +// 224 { +// 225 __disable_interrupt(); + CLI +// 226 +// 227 // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. +// 228 USI_DIR_REG |= (1<> 8 + LDI R16, 0 + ST Z, R16 +// 237 SPI.State = ST_CMD; // Initial SPI state: wait for command. +// 238 SPI.Read = FALSE; // Doesn't matter right now. +// 239 SPI.EEPROM = FALSE; // Doesn't matter right now. + LDD R16, Z+3 + ANDI R16, 0xFC + STD Z+3, R16 +// 240 SPI.Count = 0; // Doesn't matter right now. + LDI R16, 64 + STD Z+2, R16 +// 241 SPI.Address = 0; // Doesn't matter right now. + LDI R16, 0 + STD Z+1, R16 +// 242 SPI.XferComplete = FALSE; // We haven't even started a transfer yet. +// 243 SPI.WriteCollision = FALSE; // ..And therefore a collision hasn't happened. + LDD R16, Z+3 + ANDI R16, 0xF3 + STD Z+3, R16 +// 244 +// 245 __enable_interrupt(); + SEI +// 246 } + RET + REQUIRE _A_PORTB + REQUIRE _A_DDRB + REQUIRE _A_USICR +// 247 +// 248 +// 249 // Put one byte on bus. Use this function like you would write to the SPDR +// 250 // register in the native SPI module. Calling this function will prepare a +// 251 // byte for the next transfer initiated by the master device. If a transfer +// 252 // is in progress, this function will set the write collision flag and return +// 253 // without altering the data registers. +// 254 // +// 255 // Returns 0 if a write collision occurred, 1 otherwise. +// 256 /*! \brief Write a byte to SPI bus +// 257 * +// 258 * This function first checks if a transmission is in progress, and if so, flags +// 259 * a write collision, and returns FALSE.\n +// 260 * If a transmission is not in progress, the flags for write collision and +// 261 * transfer complete are cleared, and the input byte is written to SPDR.\n +// 262 * +// 263 * \param val The byte to send. +// 264 * +// 265 * \retval FALSE A write collision happened. +// 266 * \retval TRUE Byte written to SPDR. +// 267 */ + + RSEG CODE:CODE:NOROOT(1) +// 268 unsigned char SPI_Put(unsigned char val) +SPI_Put: +// 269 { +// 270 // Check if transmission in progress, i.e. if USI counter doesn't equal zero. +// 271 // If this fails, flag a write collision and return. +// 272 if((USISR & 0x0F) != 0) { + IN R17, 0x0E + ANDI R17, 0x0F + LDI R30, LOW(SPI) + LDI R31, (SPI) >> 8 + BREQ ??SPI_Put_0 +// 273 SPI.WriteCollision = TRUE; + LDD R16, Z+3 + ORI R16, 0x08 + STD Z+3, R16 +// 274 return(FALSE); + LDI R16, 0 + RET +// 275 } +// 276 +// 277 // Reinitialize flags. +// 278 SPI.XferComplete = FALSE; +// 279 SPI.WriteCollision = FALSE; +??SPI_Put_0: + LDD R17, Z+3 + ANDI R17, 0xF3 + STD Z+3, R17 +// 280 +// 281 USIDR = val; // Put data in USI data register. + OUT 0x0F, R16 +// 282 +// 283 return (TRUE); + LDI R16, 1 + RET + REQUIRE _A_USIDR + REQUIRE _A_USISR +// 284 } +// 285 +// 286 +// 287 // Get one byte from bus. This function only returns the previous stored +// 288 // USIDR value. The transfer complete flag is not checked. Use this function +// 289 // like you would read from the SPDR register in the native SPI module. +// 290 /*! \brief Get the last byte received from SPI bus +// 291 * +// 292 * This function simply returns the last byte stored to the SPI status struct, +// 293 * without checking if a completed transfer is flagged. +// 294 * +// 295 * \retval SPI.Data The last byte read from SPI. +// 296 */ + + RSEG CODE:CODE:NOROOT(1) +// 297 unsigned char SPI_Get(void) +SPI_Get: +// 298 { +// 299 return SPI.Data; + LDS R16, SPI + RET +// 300 } +// 301 +// 302 +// 303 /*! \brief Wait for SPI transfer to complete +// 304 * +// 305 * This function waits for a transfer complete to be flagged. +// 306 */ + + RSEG CODE:CODE:NOROOT(1) +// 307 void SPI_Wait(void) +SPI_Wait: +// 308 { + LDS R16, (SPI + 3) + SBRS R16, 2 +// 309 do { // Wait for transfer complete. +// 310 } while (SPI.XferComplete == FALSE); +??SPI_Wait_0: + RJMP ??SPI_Wait_0 +// 311 } +??SPI_Wait_1: + RET + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + COMMON INTVEC:CODE:ROOT(1) + ORG 16 +`??USI_OVF_ISR??INTVEC 16`: + RJMP USI_OVF_ISR + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 5 bytes in segment ABSOLUTE +// 470 bytes in segment CODE +// 6 bytes in segment INITTAB +// 2 bytes in segment INTVEC +// 4 bytes in segment NEAR_Z +// +// 470 bytes of CODE memory (+ 8 bytes shared) +// 4 bytes of DATA memory (+ 5 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/battery.lst b/BaseTinyFirmware/IAR/Release/List/battery.lst new file mode 100644 index 0000000..2bc0dbe --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/battery.lst @@ -0,0 +1,1104 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\battery.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\battery.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\ba # +# ttery.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\bat # +# tery.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\battery.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions related to battery control and data acquisition. + 6 * + 7 * Contains functions for enabling/disabling batteries, and looking up + 8 * their status and specifications using the ADC. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 + 14 * + 15 * \par Documentation + 16 * For comprehensive code documentation, supported compilers, compiler + 17 * settings and supported devices see readme.html + 18 * + 19 * \author + 20 * Atmel Corporation: http://www.atmel.com \n + 21 * Support email: avr@atmel.com + 22 * + 23 * + 24 * $Name$ + 25 * $Revision: 2299 $ + 26 * $RCSfile$ + 27 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $ + 28 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 29 ******************************************************************************/ + 30 + 31 #include + + \ In segment ABSOLUTE, at 0x4c + \ volatile __io _A_OCR1B + \ _A_OCR1B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x38 + \ volatile __io _A_PORTB + \ _A_PORTB: + \ 00000000 DS 1 + 32 #include + 33 + 34 #include "structs.h" + 35 #include "enums.h" + 36 + 37 #include "ADC.h" + 38 #include "battery.h" + 39 #include "main.h" + 40 #include "OWI.h" + 41 #include "time.h" + 42 + 43 #ifdef NIMH + 44 #include "NIMHspecs.h" + 45 #endif // NIMH + 46 + 47 #ifdef LIION + 48 #include "LIIONspecs.h" + 49 #endif // LIION + 50 + 51 + 52 + 53 //****************************************************************************** + 54 // Variables + 55 //****************************************************************************** + 56 /* Control-struct for batteries */ + 57 /*! \brief Holds control data for both batteries + 58 * \note Stored in EEPROM. + 59 */ + + \ In segment EEPROM_I, align 1, keep-with-next + 60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE}, + \ BattControl: + \ 00000000 0303 DB 3, 3 + 61 {TRUE, TRUE, FALSE}}; + 62 + 63 /* Data-struct for battery */ + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 64 Batteries_t BattData; //!< Holds data for the current battery + \ BattData: + \ 00000000 DS 12 + 65 + 66 + 67 /* Storage for battery EPROM */ + 68 /*! \brief Storage space for data from the batteries' own EPROMs. + 69 * \note Stored in EEPROM. + 70 */ + + \ In segment EEPROM_I, align 1, keep-with-next + 71 __eeprom unsigned char BattEEPROM[4][32]; + \ BattEEPROM: + \ 00000000 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000010 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000020 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000030 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000040 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000050 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000060 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + \ 00000070 000000000000 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + \ 000000000000 + \ 00000000 + 72 + 73 + 74 //! Global that indicates current battery (0 = battery A, 1 = B) + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 75 unsigned char BattActive; + \ BattActive: + \ 00000000 DS 1 + 76 + 77 + 78 /*! \brief RID lookup-table + 79 * + 80 * Contains Resistor ID data specified by manufacturer. + 81 * + 82 * \note Values have been calculated assuming a +/- 15% tolerance. + 83 */ + + \ In segment NEAR_I, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 84 const RID_Lookup_t RID[RID_TABLE_SIZE] = { + \ RID: + \ 00000000 DS 56 + \ 00000038 REQUIRE `?` + 85 {558, 659, 3900, 550, 260, 300, 10}, + 86 {744, 843, 6800, 750, 360, 300, 14}, + 87 {869, 958, 10000, 1000, 475, 300, 19}, + 88 {1097, 1153, 24000, 2000, 475, 420, 38} + 89 }; + 90 + 91 + 92 /*! \brief NTC lookup-table + 93 * + 94 * The first entry is 0 degrees. For every entry after, temperature increases + 95 * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n + 96 * It must be sorted in descending ADC order. + 97 * + 98 * \note This was calculated for a Mitsubishi RH16-3H103FB NTC. + 99 * + 100 * \note NTCLookUp() must be modified if this table is changed so that: + 101 * - first entry is no longer 0 degrees. + 102 * - temperature difference between entries is no longer 4 degrees. + 103 * - ADCsteps no longer specifies ADC steps per half degree. + 104 */ + 105 // FOR VARTA POLYFLEX NTC + + \ In segment NEAR_I, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + \ NTC: + \ 00000000 DS 60 + \ 0000003C REQUIRE `?` + 107 {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27}, + 108 {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24}, + 109 {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17}, + 110 {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10} + 111 }; + 112 + 113 + 114 // FOR MITSUBISHI NTC + 115 /* + 116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + 117 {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27}, + 118 {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24}, + 119 {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17}, + 120 {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10} + 121 }; + 122 */ + 123 + 124 + 125 //****************************************************************************** + 126 // Functions + 127 //****************************************************************************** + 128 /*! \brief Checks if battery has changed + 129 * + 130 * Stores current capacity, then attempts to refresh battery status.\n + 131 * If the refresh is successful, old capacity is compared with the new one. + 132 * + 133 * \retval FALSE Battery is disconnected, or capacity has changed. + 134 * \retval TRUE All OK. + 135 */ + + \ In segment CODE, align 2, keep-with-next + 136 unsigned char BatteryCheck(void) + \ BatteryCheck: + 137 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + \ 00000004 938A ST -Y, R24 + 138 unsigned char success = TRUE; + \ 00000006 E081 LDI R24, 1 + 139 unsigned int oldCapacity; + 140 + 141 // Save to see if battery data has changed. + 142 oldCapacity = BattData.Capacity; + \ 00000008 .... LDI R30, LOW(BattData) + \ 0000000A .... LDI R31, (BattData) >> 8 + \ 0000000C 81A4 LDD R26, Z+4 + \ 0000000E 81B5 LDD R27, Z+5 + 143 + 144 if (!BatteryStatusRefresh()) { + \ 00000010 .... RCALL BatteryStatusRefresh + \ 00000012 2300 TST R16 + \ 00000014 F409 BRNE ??BatteryCheck_0 + 145 success = FALSE; // Battery not present or RID was invalid. + \ 00000016 E080 LDI R24, 0 + 146 } + 147 + 148 if (oldCapacity != BattData.Capacity) { + \ ??BatteryCheck_0: + \ 00000018 .... LDI R30, LOW(BattData) + \ 0000001A .... LDI R31, (BattData) >> 8 + \ 0000001C 8104 LDD R16, Z+4 + \ 0000001E 8115 LDD R17, Z+5 + \ 00000020 17A0 CP R26, R16 + \ 00000022 07B1 CPC R27, R17 + \ 00000024 F009 BREQ ??BatteryCheck_1 + 149 success = FALSE; // Battery configuration has changed. + \ 00000026 E080 LDI R24, 0 + 150 } + 151 + 152 return(success); + \ ??BatteryCheck_1: + \ 00000028 2F08 MOV R16, R24 + \ 0000002A 9189 LD R24, Y+ + \ 0000002C 91A9 LD R26, Y+ + \ 0000002E 91B9 LD R27, Y+ + \ 00000030 9508 RET + 153 } + 154 + 155 + 156 /*! \brief Refreshes battery status information + 157 * + 158 * Refreshes battery status information, if it is present, based on + 159 * RID and NTC (read by ADC).\n + 160 * The battery must have been enabled and a complete set of ADC data must have + 161 * been collected before calling.\n + 162 * + 163 * \retval FALSE No battery present. + 164 * \retval TRUE Battery present, status refreshed. + 165 * + 166 * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry + 167 * is found in the lookup table. Instead, default battery data will be used. + 168 */ + + \ In segment CODE, align 2, keep-with-next + 169 unsigned char BatteryStatusRefresh(void) + \ BatteryStatusRefresh: + 170 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + \ 00000004 939A ST -Y, R25 + \ 00000006 938A ST -Y, R24 + 171 // Assume the worst.. + 172 unsigned char success = FALSE; + 173 + 174 BattData.Present = FALSE; + 175 BattData.Charged = FALSE; + 176 BattData.Low = TRUE; + \ 00000008 .... LDI R26, LOW(BattData) + \ 0000000A .... LDI R27, (BattData) >> 8 + \ 0000000C 910C LD R16, X + \ 0000000E 7F0C ANDI R16, 0xFC + \ 00000010 6004 ORI R16, 0x04 + \ 00000012 930C ST X, R16 + 177 BattData.Circuit = OW_NONE; + \ 00000014 E000 LDI R16, 0 + \ 00000016 01FD MOVW R31:R30, R27:R26 + \ 00000018 8301 STD Z+1, R16 + 178 BattData.Temperature = 0; + \ 0000001A 8302 STD Z+2, R16 + 179 BattData.Capacity = 0; + \ 0000001C 8304 STD Z+4, R16 + \ 0000001E 8305 STD Z+5, R16 + 180 BattData.MaxCurrent = 0; + \ 00000020 8306 STD Z+6, R16 + \ 00000022 8307 STD Z+7, R16 + 181 BattData.MaxTime = 0; + \ 00000024 8700 STD Z+8, R16 + \ 00000026 8701 STD Z+9, R16 + 182 BattData.MinCurrent = 0; + \ 00000028 8702 STD Z+10, R16 + \ 0000002A 8703 STD Z+11, R16 + 183 + 184 NTCLookUp(); + \ 0000002C .... RCALL NTCLookUp + 185 BattData.HasRID = RIDLookUp(); + \ 0000002E .... RCALL RIDLookUp + \ 00000030 2F10 MOV R17, R16 + \ 00000032 7011 ANDI R17, 0x01 + \ 00000034 FB10 BST R17, 0 + \ 00000036 910C LD R16, X + \ 00000038 F904 BLD R16, 4 + \ 0000003A 930C ST X, R16 + 186 + 187 // Is the battery voltage above minimum safe cell voltage? + 188 if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + \ 0000003C .... LDI R30, LOW(ADCS) + \ 0000003E .... LDI R31, (ADCS) >> 8 + \ 00000040 8502 LDD R16, Z+10 + \ 00000042 8513 LDD R17, Z+11 + \ 00000044 3600 CPI R16, 96 + \ 00000046 E029 LDI R18, 9 + \ 00000048 0712 CPC R17, R18 + \ 0000004A F018 BRCS ??BatteryStatusRefresh_0 + 189 BattData.Low = FALSE; + \ 0000004C 910C LD R16, X + \ 0000004E 7F0B ANDI R16, 0xFB + \ 00000050 930C ST X, R16 + 190 } + 191 + 192 // Is the battery charged? + 193 if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { + \ ??BatteryStatusRefresh_0: + \ 00000052 8502 LDD R16, Z+10 + \ 00000054 3D02 CPI R16, 210 + \ 00000056 401F SBCI R17, 15 + \ 00000058 F018 BRCS ??BatteryStatusRefresh_1 + 194 BattData.Charged = TRUE; + \ 0000005A 910C LD R16, X + \ 0000005C 6002 ORI R16, 0x02 + \ 0000005E 930C ST X, R16 + 195 } + 196 + 197 // If we are not charging, yet VBAT is above safe limit, battery is present. + 198 // If we are charging and there's a current flowing, the battery is present. + 199 + 200 /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence + 201 * check is redundant since charging will be aborted due to low current at + 202 * max duty cycle. That is preferrable since the charge current reading is + 203 * not 100% proof. + 204 */ + 205 if (((OCR1B == 0) && (!BattData.Low)) || + 206 ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { + \ ??BatteryStatusRefresh_1: + \ 00000060 B50C IN R16, 0x2C + \ 00000062 2300 TST R16 + \ 00000064 F419 BRNE ??BatteryStatusRefresh_2 + \ 00000066 910C LD R16, X + \ 00000068 FF02 SBRS R16, 2 + \ 0000006A C008 RJMP ??BatteryStatusRefresh_3 + \ ??BatteryStatusRefresh_2: + \ 0000006C B50C IN R16, 0x2C + \ 0000006E 2300 TST R16 + \ 00000070 F051 BREQ ??BatteryStatusRefresh_4 + \ 00000072 8986 LDD R24, Z+22 + \ 00000074 8997 LDD R25, Z+23 + \ 00000076 3081 CPI R24, 1 + \ 00000078 4090 SBCI R25, 0 + \ 0000007A F02C BRLT ??BatteryStatusRefresh_4 + 207 BattData.Present = TRUE; + \ ??BatteryStatusRefresh_3: + \ 0000007C 910C LD R16, X + \ 0000007E 6001 ORI R16, 0x01 + \ 00000080 930C ST X, R16 + 208 success = TRUE; + \ 00000082 E001 LDI R16, 1 + \ 00000084 C004 RJMP ??BatteryStatusRefresh_5 + 209 } else { + 210 BattData.Low = FALSE; // (This is just a technicality..) + \ ??BatteryStatusRefresh_4: + \ 00000086 910C LD R16, X + \ 00000088 7F0B ANDI R16, 0xFB + \ 0000008A 930C ST X, R16 + 211 success = FALSE; + \ 0000008C E000 LDI R16, 0 + 212 } + 213 + 214 #ifndef ALLOW_NO_RID + 215 // Return FALSE if no valid RID entry was found, to stop charging. + 216 if(!BattData.HasRID) { + \ ??BatteryStatusRefresh_5: + \ 0000008E 911C LD R17, X + \ 00000090 FF14 SBRS R17, 4 + 217 success = FALSE; + \ 00000092 E000 LDI R16, 0 + 218 } + 219 #endif + 220 + 221 return(success); + \ ??BatteryStatusRefresh_6: + \ 00000094 9189 LD R24, Y+ + \ 00000096 9199 LD R25, Y+ + \ 00000098 91A9 LD R26, Y+ + \ 0000009A 91B9 LD R27, Y+ + \ 0000009C 9508 RET + \ 0000009E REQUIRE _A_OCR1B + 222 } + 223 + 224 + 225 /*! \brief Refreshes battery data in the EEPROM + 226 * + 227 * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store + 228 * these data in on-chip EEPROM.\n + 229 * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared. + 230 * + 231 * \todo Updating BattData with these data. Specs needed. + 232 * + 233 * \retval FALSE Refresh failed. + 234 * \retval TRUE Refresh successful. + 235 */ + + \ In segment CODE, align 2, keep-with-next + 236 unsigned char BatteryDataRefresh(void) + \ BatteryDataRefresh: + 237 { + \ 00000000 928A ST -Y, R8 + \ 00000002 927A ST -Y, R7 + \ 00000004 926A ST -Y, R6 + \ 00000006 925A ST -Y, R5 + \ 00000008 924A ST -Y, R4 + \ 0000000A 93BA ST -Y, R27 + \ 0000000C 93AA ST -Y, R26 + \ 0000000E 939A ST -Y, R25 + \ 00000010 938A ST -Y, R24 + \ 00000012 REQUIRE ?Register_R4_is_cg_reg + \ 00000012 REQUIRE ?Register_R5_is_cg_reg + \ 00000012 REQUIRE ?Register_R6_is_cg_reg + \ 00000012 REQUIRE ?Register_R7_is_cg_reg + \ 00000012 REQUIRE ?Register_R8_is_cg_reg + 238 unsigned char offset; + 239 unsigned char i, crc, family, temp, page; + 240 unsigned char success; + 241 + 242 // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found. + 243 for (page = 0; page < 4; page++) { + \ 00000012 E090 LDI R25, 0 + \ 00000014 .... LDI R26, LOW(BattEEPROM) + \ 00000016 .... LDI R27, (BattEEPROM) >> 8 + 244 success = FALSE; + \ ??BatteryDataRefresh_0: + \ 00000018 2477 CLR R7 + 245 + 246 if (OWI_DetectPresence(OWIBUS) == OWIBUS) { + \ 0000001A E001 LDI R16, 1 + \ 0000001C .... RCALL OWI_DetectPresence + \ 0000001E 3001 CPI R16, 1 + \ 00000020 F009 BREQ $+2+2 + \ 00000022 C055 RJMP ??BatteryDataRefresh_1 + 247 + 248 // Presence detected, check type and CRC. + 249 OWI_SendByte(OWI_ROM_READ, OWIBUS); + \ 00000024 E011 LDI R17, 1 + \ 00000026 E303 LDI R16, 51 + \ 00000028 .... RCALL OWI_SendByte + 250 family = OWI_ReceiveByte(OWIBUS); + \ 0000002A E001 LDI R16, 1 + \ 0000002C .... RCALL OWI_ReceiveByte + \ 0000002E 2E50 MOV R5, R16 + 251 crc = OWI_ComputeCRC8(family,0); + \ 00000030 E010 LDI R17, 0 + \ 00000032 .... RCALL OWI_ComputeCRC8 + \ 00000034 2F80 MOV R24, R16 + 252 + 253 for (i = 0; i < 6; i++) { + \ 00000036 E006 LDI R16, 6 + \ 00000038 2E40 MOV R4, R16 + 254 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc); + \ ??BatteryDataRefresh_2: + \ 0000003A E001 LDI R16, 1 + \ 0000003C .... RCALL OWI_ReceiveByte + \ 0000003E 2F18 MOV R17, R24 + \ 00000040 .... RCALL OWI_ComputeCRC8 + \ 00000042 2F80 MOV R24, R16 + 255 } + \ 00000044 944A DEC R4 + \ 00000046 F7C9 BRNE ??BatteryDataRefresh_2 + 256 + 257 // CRC ok, device found. + 258 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + \ 00000048 E001 LDI R16, 1 + \ 0000004A .... RCALL OWI_ReceiveByte + \ 0000004C 2F18 MOV R17, R24 + \ 0000004E .... RCALL OWI_ComputeCRC8 + \ 00000050 2300 TST R16 + \ 00000052 F5E9 BRNE ??BatteryDataRefresh_1 + 259 BattData.Circuit = family; + \ 00000054 9250.... STS (BattData + 1), R5 + 260 + 261 // For now, we only read data from DS2505 EPROMs. + 262 if (BattData.Circuit == OW_DS2505) { + \ 00000058 9100.... LDS R16, (BattData + 1) + \ 0000005C 3009 CPI R16, 9 + \ 0000005E F5B9 BRNE ??BatteryDataRefresh_1 + 263 offset = page*32; + \ 00000060 2E49 MOV R4, R25 + \ 00000062 9442 SWAP R4 + \ 00000064 EF00 LDI R16, 240 + \ 00000066 2240 AND R4, R16 + \ 00000068 0C44 LSL R4 + 264 OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data. + \ 0000006A E011 LDI R17, 1 + \ 0000006C EC03 LDI R16, 195 + \ 0000006E .... RCALL OWI_SendByte + 265 OWI_SendByte(offset, OWIBUS); // Data: low address. + \ 00000070 E011 LDI R17, 1 + \ 00000072 2D04 MOV R16, R4 + \ 00000074 .... RCALL OWI_SendByte + 266 OWI_SendByte(0, OWIBUS); // Data: high address. + \ 00000076 E011 LDI R17, 1 + \ 00000078 E000 LDI R16, 0 + \ 0000007A .... RCALL OWI_SendByte + 267 + 268 // Calculate checksums. + 269 crc = OWI_ComputeCRC8(DS2505_DATA_READ,0); + \ 0000007C E010 LDI R17, 0 + \ 0000007E EC03 LDI R16, 195 + \ 00000080 .... RCALL OWI_ComputeCRC8 + 270 crc = OWI_ComputeCRC8(offset,crc); + \ 00000082 2F10 MOV R17, R16 + \ 00000084 2D04 MOV R16, R4 + \ 00000086 .... RCALL OWI_ComputeCRC8 + 271 crc = OWI_ComputeCRC8(0,crc); + \ 00000088 2F10 MOV R17, R16 + \ 0000008A E000 LDI R16, 0 + \ 0000008C .... RCALL OWI_ComputeCRC8 + \ 0000008E 2F80 MOV R24, R16 + 272 + 273 // Command received succesfully, now start reading data + 274 // and writing it to EEPROM. + 275 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + \ 00000090 E001 LDI R16, 1 + \ 00000092 .... RCALL OWI_ReceiveByte + \ 00000094 2F18 MOV R17, R24 + \ 00000096 .... RCALL OWI_ComputeCRC8 + \ 00000098 2300 TST R16 + \ 0000009A F4C9 BRNE ??BatteryDataRefresh_1 + 276 crc = 0; + \ 0000009C E080 LDI R24, 0 + 277 + 278 // Fill page with data. + 279 for (i=0; i<32; i++) { + \ 0000009E 012D MOVW R5:R4, R27:R26 + \ 000000A0 E200 LDI R16, 32 + \ 000000A2 2E60 MOV R6, R16 + 280 temp = OWI_ReceiveByte(OWIBUS); + \ ??BatteryDataRefresh_3: + \ 000000A4 E001 LDI R16, 1 + \ 000000A6 .... RCALL OWI_ReceiveByte + \ 000000A8 2E80 MOV R8, R16 + 281 crc = OWI_ComputeCRC8(temp, crc); + \ 000000AA 2F18 MOV R17, R24 + \ 000000AC .... RCALL OWI_ComputeCRC8 + \ 000000AE 2F80 MOV R24, R16 + 282 BattEEPROM[page][i] = temp; + \ 000000B0 2D08 MOV R16, R8 + \ 000000B2 01A2 MOVW R21:R20, R5:R4 + \ 000000B4 .... RCALL __eeput8_16 + 283 } + \ 000000B6 E001 LDI R16, 1 + \ 000000B8 0E40 ADD R4, R16 + \ 000000BA 1C57 ADC R5, R7 + \ 000000BC 946A DEC R6 + \ 000000BE F791 BRNE ??BatteryDataRefresh_3 + 284 + 285 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + \ 000000C0 .... RCALL OWI_ReceiveByte + \ 000000C2 2F18 MOV R17, R24 + \ 000000C4 .... RCALL OWI_ComputeCRC8 + \ 000000C6 2300 TST R16 + \ 000000C8 F411 BRNE ??BatteryDataRefresh_1 + 286 success = TRUE; // Data read OK + \ 000000CA 9473 INC R7 + \ 000000CC C008 RJMP ??BatteryDataRefresh_4 + 287 } + 288 } else { // Not able to start reading data. + 289 } + 290 } else { // Wrong device type. + 291 } + 292 } else { // No device found. + 293 } + 294 } else { // No presence detected on one-wire bus. + 295 } + 296 + 297 // Erase local EEPROM page if there were any errors during transfer. + 298 if (!success) { + 299 for (i=0; i<32; i++) { + \ ??BatteryDataRefresh_1: + \ 000000CE 01AD MOVW R21:R20, R27:R26 + \ 000000D0 E210 LDI R17, 32 + 300 BattEEPROM[page][i] = 0; + \ ??BatteryDataRefresh_5: + \ 000000D2 E000 LDI R16, 0 + \ 000000D4 .... RCALL __eeput8_16 + 301 } + \ 000000D6 5F4F SUBI R20, 255 + \ 000000D8 4F5F SBCI R21, 255 + \ 000000DA 951A DEC R17 + \ 000000DC F7D1 BRNE ??BatteryDataRefresh_5 + 302 } + 303 } + \ ??BatteryDataRefresh_4: + \ 000000DE 9593 INC R25 + \ 000000E0 9690 ADIW R27:R26, 32 + \ 000000E2 3094 CPI R25, 4 + \ 000000E4 F408 BRCC $+2+2 + \ 000000E6 CF98 RJMP ??BatteryDataRefresh_0 + 304 + 305 return(success); + \ 000000E8 2D07 MOV R16, R7 + \ 000000EA 9189 LD R24, Y+ + \ 000000EC 9199 LD R25, Y+ + \ 000000EE 91A9 LD R26, Y+ + \ 000000F0 91B9 LD R27, Y+ + \ 000000F2 9049 LD R4, Y+ + \ 000000F4 9059 LD R5, Y+ + \ 000000F6 9069 LD R6, Y+ + \ 000000F8 9079 LD R7, Y+ + \ 000000FA 9089 LD R8, Y+ + \ 000000FC 9508 RET + 306 } + 307 + 308 + 309 /*! \brief Enables specified battery + 310 * + 311 * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears + 312 * PB5/PB4 in PORTB, depending on which battery is specified.\n + 313 * The function takes 100 ms to allow the port switch to settle. + 314 * + 315 * \param bat Specifies which battery to enable (0 = battery A, 1 = B) + 316 */ + + \ In segment CODE, align 2, keep-with-next + 317 void EnableBattery(unsigned char bat) + \ EnableBattery: + 318 { + \ 00000000 938A ST -Y, R24 + \ 00000002 2F80 MOV R24, R16 + 319 // Use general timer, set timeout to 100ms. + 320 Time_Set(TIMER_GEN,0,0,100); + \ 00000004 E644 LDI R20, 100 + \ 00000006 E010 LDI R17, 0 + \ 00000008 E020 LDI R18, 0 + \ 0000000A E030 LDI R19, 0 + \ 0000000C E002 LDI R16, 2 + \ 0000000E .... RCALL Time_Set + 321 + 322 // Set specified battery as the active one. + 323 BattActive = bat; + \ 00000010 9380.... STS BattActive, R24 + 324 + 325 // Enable current battery in hardware, light LED & connect battery. + 326 PORTB |= (1 << (PB4+bat)); + \ 00000014 E001 LDI R16, 1 + \ 00000016 E010 LDI R17, 0 + \ 00000018 2F48 MOV R20, R24 + \ 0000001A 5F4C SUBI R20, 252 + \ 0000001C .... RCALL ?S_SHL_L02 + \ 0000001E B318 IN R17, 0x18 + \ 00000020 2B10 OR R17, R16 + \ 00000022 BB18 OUT 0x18, R17 + 327 + 328 // Disconnect other battery. + 329 PORTB &= ~(1<<(PB5-bat)); + \ 00000024 E001 LDI R16, 1 + \ 00000026 E010 LDI R17, 0 + \ 00000028 E045 LDI R20, 5 + \ 0000002A 1B48 SUB R20, R24 + \ 0000002C .... RCALL ?S_SHL_L02 + \ 0000002E 9500 COM R16 + \ 00000030 B318 IN R17, 0x18 + \ 00000032 2310 AND R17, R16 + \ 00000034 BB18 OUT 0x18, R17 + 330 + 331 do { // Let port switch settle. + 332 } while (Time_Left(TIMER_GEN)); + \ ??EnableBattery_0: + \ 00000036 E002 LDI R16, 2 + \ 00000038 .... RCALL Time_Left + \ 0000003A 2300 TST R16 + \ 0000003C F7E1 BRNE ??EnableBattery_0 + 333 } + \ 0000003E 9189 LD R24, Y+ + \ 00000040 9508 RET + \ 00000042 REQUIRE _A_PORTB + 334 + 335 + 336 /*! \brief Disables both batteries + 337 * + 338 * Clears PB4 and PB5 in PORTB, disabling both batteries. + 339 */ + + \ In segment CODE, align 2, keep-with-next + 340 void DisableBatteries(void) + \ DisableBatteries: + 341 { + 342 // Turn off LEDs and disconnect batteries. + 343 PORTB &= ~((1<> 8 + \ 0000000A E024 LDI R18, 4 + \ 0000000C .... LDI R16, LOW(BattData) + \ 0000000E .... LDI R17, (BattData) >> 8 + 363 if (ADCS.rawRID >= RID[i].Low) { + \ ??RIDLookUp_0: + \ 00000010 .... LDI R26, LOW((ADCS + 2)) + \ 00000012 .... LDI R27, HIGH((ADCS + 2)) + \ 00000014 916D LD R22, X+ + \ 00000016 917C LD R23, X + \ 00000018 8000 LD R0, Z + \ 0000001A 8011 LDD R1, Z+1 + \ 0000001C 1560 CP R22, R0 + \ 0000001E 0571 CPC R23, R1 + \ 00000020 F0F0 BRCS ??RIDLookUp_1 + 364 if (ADCS.rawRID <= RID[i].High) { + \ 00000022 8002 LDD R0, Z+2 + \ 00000024 8013 LDD R1, Z+3 + \ 00000026 1606 CP R0, R22 + \ 00000028 0617 CPC R1, R23 + \ 0000002A F0C8 BRCS ??RIDLookUp_1 + 365 BattData.Capacity = RID[i].Capacity; + \ 0000002C 8146 LDD R20, Z+6 + \ 0000002E 8157 LDD R21, Z+7 + \ 00000030 01D8 MOVW R27:R26, R17:R16 + \ 00000032 9614 ADIW R27:R26, 4 + \ 00000034 934D ST X+, R20 + \ 00000036 935C ST X, R21 + 366 BattData.MaxCurrent = RID[i].Icharge; + \ 00000038 8540 LDD R20, Z+8 + \ 0000003A 8551 LDD R21, Z+9 + \ 0000003C 01D8 MOVW R27:R26, R17:R16 + \ 0000003E 9616 ADIW R27:R26, 6 + \ 00000040 934D ST X+, R20 + \ 00000042 935C ST X, R21 + 367 BattData.MaxTime = RID[i].tCutOff; + \ 00000044 8542 LDD R20, Z+10 + \ 00000046 8553 LDD R21, Z+11 + \ 00000048 01D8 MOVW R27:R26, R17:R16 + \ 0000004A 9618 ADIW R27:R26, 8 + \ 0000004C 934D ST X+, R20 + \ 0000004E 935C ST X, R21 + 368 BattData.MinCurrent = RID[i].ICutOff; + \ 00000050 8544 LDD R20, Z+12 + \ 00000052 8555 LDD R21, Z+13 + \ 00000054 01D8 MOVW R27:R26, R17:R16 + \ 00000056 961A ADIW R27:R26, 10 + \ 00000058 934D ST X+, R20 + \ 0000005A 935C ST X, R21 + 369 + 370 found = TRUE; + \ 0000005C E041 LDI R20, 1 + 371 } + 372 } + 373 } + \ ??RIDLookUp_1: + \ 0000005E 963E ADIW R31:R30, 14 + \ 00000060 952A DEC R18 + \ 00000062 F6B1 BRNE ??RIDLookUp_0 + 374 + 375 // If no valid entry is found, use defaults and return FALSE. + 376 if (!found) { + \ 00000064 2344 TST R20 + \ 00000066 F451 BRNE ??RIDLookUp_2 + 377 BattData.Capacity = DEF_BAT_CAPACITY; + \ 00000068 E020 LDI R18, 0 + \ 0000006A 01F8 MOVW R31:R30, R17:R16 + \ 0000006C 8324 STD Z+4, R18 + \ 0000006E 8325 STD Z+5, R18 + 378 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX; + \ 00000070 8326 STD Z+6, R18 + \ 00000072 8327 STD Z+7, R18 + 379 BattData.MaxTime = DEF_BAT_TIME_MAX; + \ 00000074 8720 STD Z+8, R18 + \ 00000076 8721 STD Z+9, R18 + 380 BattData.MinCurrent = DEF_BAT_CURRENT_MIN; + \ 00000078 8722 STD Z+10, R18 + \ 0000007A 8723 STD Z+11, R18 + 381 } + 382 + 383 return(found); + \ ??RIDLookUp_2: + \ 0000007C 2F04 MOV R16, R20 + \ 0000007E 2DA2 MOV R26, R2 + \ 00000080 2FB3 MOV R27, R19 + \ 00000082 9508 RET + 384 } + 385 + 386 + 387 /*! \brief Calculates temperature from a lookup table + 388 * + 389 * Looks up the highest NTC value below or equal to the measured one.\n + 390 * With the current lookup table, temperature is calculated with the formula:\n + 391 * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry) + 392 * + 393 * \note If the NTC-measurement is saturated, with the current lookup table, + 394 * the temperature will be reported as -1 C. + 395 * + 396 * \note If no valid entry is found, battery temperature is set to 80. + 397 */ + + \ In segment CODE, align 2, keep-with-next + 398 void NTCLookUp (void) + \ NTCLookUp: + 399 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 2E3A MOV R3, R26 + \ 00000004 2E28 MOV R2, R24 + 400 unsigned char i; + 401 unsigned char found = FALSE; + \ 00000006 E000 LDI R16, 0 + 402 + 403 // Lookup in the NTC-table. Use the first entry which is equal or below + 404 // sampled NTC. Calculate temperature by using the index number, and the + 405 // difference between the measured NTC value and the one in the entry. + 406 for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { + \ 00000008 E080 LDI R24, 0 + \ 0000000A .... LDI R26, LOW(BattData) + \ 0000000C .... LDI R27, (BattData) >> 8 + 407 if (ADCS.rawNTC >= NTC[i].ADC) { + \ ??NTCLookUp_0: + \ 0000000E 2F48 MOV R20, R24 + \ 00000010 E050 LDI R21, 0 + \ 00000012 019A MOVW R19:R18, R21:R20 + \ 00000014 0F44 LSL R20 + \ 00000016 1F55 ROL R21 + \ 00000018 0F42 ADD R20, R18 + \ 0000001A 1F53 ADC R21, R19 + \ 0000001C .... LDI R18, LOW(NTC) + \ 0000001E .... LDI R19, (NTC) >> 8 + \ 00000020 0F24 ADD R18, R20 + \ 00000022 1F35 ADC R19, R21 + \ 00000024 .... LDI R30, LOW(ADCS) + \ 00000026 .... LDI R31, (ADCS) >> 8 + \ 00000028 8144 LDD R20, Z+4 + \ 0000002A 8155 LDD R21, Z+5 + \ 0000002C 01F9 MOVW R31:R30, R19:R18 + \ 0000002E 8160 LD R22, Z + \ 00000030 8171 LDD R23, Z+1 + \ 00000032 1746 CP R20, R22 + \ 00000034 0757 CPC R21, R23 + \ 00000036 F0D0 BRCS ??NTCLookUp_1 + 408 BattData.Temperature = (i<<2) ; + \ 00000038 2F08 MOV R16, R24 + \ 0000003A 0F00 LSL R16 + \ 0000003C 0F00 LSL R16 + \ 0000003E 01FD MOVW R31:R30, R27:R26 + \ 00000040 8302 STD Z+2, R16 + 409 BattData.ADCSteps = NTC[i].ADCsteps; + \ 00000042 01F9 MOVW R31:R30, R19:R18 + \ 00000044 8142 LDD R20, Z+2 + \ 00000046 01FD MOVW R31:R30, R27:R26 + \ 00000048 8343 STD Z+3, R20 + 410 BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps; + \ 0000004A 9100.... LDS R16, (ADCS + 4) + \ 0000004E 2F15 MOV R17, R21 + \ 00000050 01F9 MOVW R31:R30, R19:R18 + \ 00000052 8120 LD R18, Z + \ 00000054 8131 LDD R19, Z+1 + \ 00000056 1B02 SUB R16, R18 + \ 00000058 0B13 SBC R17, R19 + \ 0000005A 0F00 LSL R16 + \ 0000005C 1F11 ROL R17 + \ 0000005E E050 LDI R21, 0 + \ 00000060 .... RCALL ?US_DIVMOD_L02 + \ 00000062 01FD MOVW R31:R30, R27:R26 + \ 00000064 8112 LDD R17, Z+2 + \ 00000066 1B10 SUB R17, R16 + \ 00000068 8312 STD Z+2, R17 + 411 + 412 found = TRUE; // Could be done with a break, but that violates MISRA. + \ 0000006A E001 LDI R16, 1 + 413 } + 414 } + \ ??NTCLookUp_1: + \ 0000006C 9583 INC R24 + \ 0000006E 3184 CPI R24, 20 + \ 00000070 F410 BRCC ??NTCLookUp_2 + \ 00000072 2300 TST R16 + \ 00000074 F261 BREQ ??NTCLookUp_0 + 415 + 416 // For safety, is temperature is greater than the NTC + 417 if (!found) { + \ ??NTCLookUp_2: + \ 00000076 2300 TST R16 + \ 00000078 F419 BRNE ??NTCLookUp_3 + 418 BattData.Temperature = 80; + \ 0000007A E500 LDI R16, 80 + \ 0000007C 9300.... STS (BattData + 2), R16 + 419 } + 420 } + \ ??NTCLookUp_3: + \ 00000080 2D82 MOV R24, R2 + \ 00000082 2DA3 MOV R26, R3 + \ 00000084 91B9 LD R27, Y+ + \ 00000086 9508 RET + + \ In segment NEAR_ID, align 1, keep-with-next + \ `?`: + \ 00000000 022E02930F3C DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14 + \ 02260104012C + \ 000A02E8034B + \ 1A9002EE0168 + \ 012C000E + \ 0000001C 036503BE2710 DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475 + \ 03E801DB012C + \ 001304490481 + \ 5DC007D001DB + \ 00000034 01A40026 DW 420, 38 + + \ In segment NEAR_ID, align 1, keep-with-next + \ `?`: + \ 00000000 03EA DW 1002 + \ 00000002 17 DB 23 + \ 00000003 03B9 DW 953 + \ 00000005 19 DB 25 + \ 00000006 0386 DW 902 + \ 00000008 1A DB 26 + \ 00000009 0351 DW 849 + \ 0000000B 1B DB 27 + \ 0000000C 031C DW 796 + \ 0000000E 1B DB 27 + \ 0000000F 02E6 DW 742 + \ 00000011 1B DB 27 + \ 00000012 02B1 DW 689 + \ 00000014 1A DB 26 + \ 00000015 027D DW 637 + \ 00000017 1A DB 26 + \ 00000018 024B DW 587 + \ 0000001A 19 DB 25 + \ 0000001B 021B DW 539 + \ 0000001D 18 DB 24 + \ 0000001E 01EE DW 494 + \ 00000020 16 DB 22 + \ 00000021 01C3 DW 451 + \ 00000023 15 DB 21 + \ 00000024 019C DW 412 + \ 00000026 13 DB 19 + \ 00000027 0177 DW 375 + \ 00000029 12 DB 18 + \ 0000002A 0155 DW 341 + \ 0000002C 11 DB 17 + \ 0000002D 0136 DW 310 + \ 0000002F 0F DB 15 + \ 00000030 011A DW 282 + \ 00000032 0E DB 14 + \ 00000033 0100 DW 256 + \ 00000035 0D DB 13 + \ 00000036 00E9 DW 233 + \ 00000038 0B DB 11 + \ 00000039 00D4 DW 212 + \ 0000003B 0A DB 10 + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + BatteryCheck 3 2 + -> BatteryStatusRefresh 3 2 + BatteryDataRefresh 9 4 + -> OWI_DetectPresence 9 2 + -> OWI_SendByte 9 2 + -> OWI_ReceiveByte 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ReceiveByte 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ReceiveByte 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_SendByte 9 2 + -> OWI_SendByte 9 2 + -> OWI_SendByte 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ReceiveByte 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ReceiveByte 9 2 + -> OWI_ComputeCRC8 9 2 + -> OWI_ReceiveByte 9 2 + -> OWI_ComputeCRC8 9 2 + BatteryStatusRefresh 4 2 + -> NTCLookUp 4 2 + -> RIDLookUp 4 2 + DisableBatteries 0 2 + EnableBattery 1 4 + -> Time_Set 1 2 + -> Time_Left 1 2 + NTCLookUp 3 4 + RIDLookUp 0 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_OCR1B 1 + _A_PORTB 1 + BattControl 2 + BattData 12 + BattEEPROM 128 + BattActive 1 + RID 56 + NTC 60 + BatteryCheck 50 + BatteryStatusRefresh 158 + BatteryDataRefresh 254 + EnableBattery 66 + DisableBatteries 8 + RIDLookUp 132 + NTCLookUp 136 + ? 56 + ? 60 + Others 12 + + + 2 bytes in segment ABSOLUTE + 804 bytes in segment CODE + 130 bytes in segment EEPROM_I + 12 bytes in segment INITTAB + 116 bytes in segment NEAR_I + 116 bytes in segment NEAR_ID + 13 bytes in segment NEAR_Z + + 920 bytes of CODE memory (+ 12 bytes shared) + 129 bytes of DATA memory (+ 2 bytes shared) + 130 bytes of XDATA memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/battery.s90 b/BaseTinyFirmware/IAR/Release/List/battery.s90 new file mode 100644 index 0000000..a736f3d --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/battery.s90 @@ -0,0 +1,1090 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:02 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\battery.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\battery.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\b / +// attery.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME battery + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?Register_R6_is_cg_reg + EXTERN ?Register_R7_is_cg_reg + EXTERN ?Register_R8_is_cg_reg + EXTERN ?S_SHL_L02 + EXTERN ?US_DIVMOD_L02 + EXTERN ?need_segment_init + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBWEAK `?` + PUBLIC BattActive + PUBLIC BattControl + PUBLIC BattData + PUBLIC BattEEPROM + PUBLIC BatteryCheck + PUBLIC BatteryDataRefresh + PUBLIC BatteryStatusRefresh + PUBLIC DisableBatteries + PUBLIC EnableBattery + PUBLIC NTC + PUBLIC NTCLookUp + PUBLIC RID + PUBLIC RIDLookUp + PUBWEAK _A_OCR1B + PUBWEAK _A_PORTB + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN OWI_DetectPresence + EXTERN OWI_SendByte + EXTERN OWI_ReceiveByte + EXTERN OWI_ComputeCRC8 + EXTERN Time_Set + EXTERN Time_Left + EXTERN ADCS + +// C:\home\kevin\pub\src\bc100\IAR\battery.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions related to battery control and data acquisition. +// 6 * +// 7 * Contains functions for enabling/disabling batteries, and looking up +// 8 * their status and specifications using the ADC. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 +// 14 * +// 15 * \par Documentation +// 16 * For comprehensive code documentation, supported compilers, compiler +// 17 * settings and supported devices see readme.html +// 18 * +// 19 * \author +// 20 * Atmel Corporation: http://www.atmel.com \n +// 21 * Support email: avr@atmel.com +// 22 * +// 23 * +// 24 * $Name$ +// 25 * $Revision: 2299 $ +// 26 * $RCSfile$ +// 27 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.c $ +// 28 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 29 ******************************************************************************/ +// 30 +// 31 #include + + ASEGN ABSOLUTE:DATA:NOROOT,04cH +// volatile __io _A_OCR1B +_A_OCR1B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,038H +// volatile __io _A_PORTB +_A_PORTB: + DS 1 +// 32 #include +// 33 +// 34 #include "structs.h" +// 35 #include "enums.h" +// 36 +// 37 #include "ADC.h" +// 38 #include "battery.h" +// 39 #include "main.h" +// 40 #include "OWI.h" +// 41 #include "time.h" +// 42 +// 43 #ifdef NIMH +// 44 #include "NIMHspecs.h" +// 45 #endif // NIMH +// 46 +// 47 #ifdef LIION +// 48 #include "LIIONspecs.h" +// 49 #endif // LIION +// 50 +// 51 +// 52 +// 53 //****************************************************************************** +// 54 // Variables +// 55 //****************************************************************************** +// 56 /* Control-struct for batteries */ +// 57 /*! \brief Holds control data for both batteries +// 58 * \note Stored in EEPROM. +// 59 */ + + RSEG EEPROM_I:XDATA:NOROOT(0) +// 60 __eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE}, +BattControl: + DB 3, 3 +// 61 {TRUE, TRUE, FALSE}}; +// 62 +// 63 /* Data-struct for battery */ + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 64 Batteries_t BattData; //!< Holds data for the current battery +BattData: + DS 12 +// 65 +// 66 +// 67 /* Storage for battery EPROM */ +// 68 /*! \brief Storage space for data from the batteries' own EPROMs. +// 69 * \note Stored in EEPROM. +// 70 */ + + RSEG EEPROM_I:XDATA:NOROOT(0) +// 71 __eeprom unsigned char BattEEPROM[4][32]; +BattEEPROM: + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +// 72 +// 73 +// 74 //! Global that indicates current battery (0 = battery A, 1 = B) + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 75 unsigned char BattActive; +BattActive: + DS 1 +// 76 +// 77 +// 78 /*! \brief RID lookup-table +// 79 * +// 80 * Contains Resistor ID data specified by manufacturer. +// 81 * +// 82 * \note Values have been calculated assuming a +/- 15% tolerance. +// 83 */ + + RSEG NEAR_I:DATA:NOROOT(0) + REQUIRE `?` +// 84 const RID_Lookup_t RID[RID_TABLE_SIZE] = { +RID: + DS 56 + REQUIRE `?` +// 85 {558, 659, 3900, 550, 260, 300, 10}, +// 86 {744, 843, 6800, 750, 360, 300, 14}, +// 87 {869, 958, 10000, 1000, 475, 300, 19}, +// 88 {1097, 1153, 24000, 2000, 475, 420, 38} +// 89 }; +// 90 +// 91 +// 92 /*! \brief NTC lookup-table +// 93 * +// 94 * The first entry is 0 degrees. For every entry after, temperature increases +// 95 * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n +// 96 * It must be sorted in descending ADC order. +// 97 * +// 98 * \note This was calculated for a Mitsubishi RH16-3H103FB NTC. +// 99 * +// 100 * \note NTCLookUp() must be modified if this table is changed so that: +// 101 * - first entry is no longer 0 degrees. +// 102 * - temperature difference between entries is no longer 4 degrees. +// 103 * - ADCsteps no longer specifies ADC steps per half degree. +// 104 */ +// 105 // FOR VARTA POLYFLEX NTC + + RSEG NEAR_I:DATA:NOROOT(0) + REQUIRE `?` +// 106 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { +NTC: + DS 60 + REQUIRE `?` +// 107 {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27}, +// 108 {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24}, +// 109 {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17}, +// 110 {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10} +// 111 }; +// 112 +// 113 +// 114 // FOR MITSUBISHI NTC +// 115 /* +// 116 const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { +// 117 {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27}, +// 118 {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24}, +// 119 {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17}, +// 120 {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10} +// 121 }; +// 122 */ +// 123 +// 124 +// 125 //****************************************************************************** +// 126 // Functions +// 127 //****************************************************************************** +// 128 /*! \brief Checks if battery has changed +// 129 * +// 130 * Stores current capacity, then attempts to refresh battery status.\n +// 131 * If the refresh is successful, old capacity is compared with the new one. +// 132 * +// 133 * \retval FALSE Battery is disconnected, or capacity has changed. +// 134 * \retval TRUE All OK. +// 135 */ + + RSEG CODE:CODE:NOROOT(1) +// 136 unsigned char BatteryCheck(void) +BatteryCheck: +// 137 { + ST -Y, R27 + ST -Y, R26 + ST -Y, R24 +// 138 unsigned char success = TRUE; + LDI R24, 1 +// 139 unsigned int oldCapacity; +// 140 +// 141 // Save to see if battery data has changed. +// 142 oldCapacity = BattData.Capacity; + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R26, Z+4 + LDD R27, Z+5 +// 143 +// 144 if (!BatteryStatusRefresh()) { + RCALL BatteryStatusRefresh + TST R16 + BRNE ??BatteryCheck_0 +// 145 success = FALSE; // Battery not present or RID was invalid. + LDI R24, 0 +// 146 } +// 147 +// 148 if (oldCapacity != BattData.Capacity) { +??BatteryCheck_0: + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+4 + LDD R17, Z+5 + CP R26, R16 + CPC R27, R17 + BREQ ??BatteryCheck_1 +// 149 success = FALSE; // Battery configuration has changed. + LDI R24, 0 +// 150 } +// 151 +// 152 return(success); +??BatteryCheck_1: + MOV R16, R24 + LD R24, Y+ + LD R26, Y+ + LD R27, Y+ + RET +// 153 } +// 154 +// 155 +// 156 /*! \brief Refreshes battery status information +// 157 * +// 158 * Refreshes battery status information, if it is present, based on +// 159 * RID and NTC (read by ADC).\n +// 160 * The battery must have been enabled and a complete set of ADC data must have +// 161 * been collected before calling.\n +// 162 * +// 163 * \retval FALSE No battery present. +// 164 * \retval TRUE Battery present, status refreshed. +// 165 * +// 166 * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry +// 167 * is found in the lookup table. Instead, default battery data will be used. +// 168 */ + + RSEG CODE:CODE:NOROOT(1) +// 169 unsigned char BatteryStatusRefresh(void) +BatteryStatusRefresh: +// 170 { + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 +// 171 // Assume the worst.. +// 172 unsigned char success = FALSE; +// 173 +// 174 BattData.Present = FALSE; +// 175 BattData.Charged = FALSE; +// 176 BattData.Low = TRUE; + LDI R26, LOW(BattData) + LDI R27, (BattData) >> 8 + LD R16, X + ANDI R16, 0xFC + ORI R16, 0x04 + ST X, R16 +// 177 BattData.Circuit = OW_NONE; + LDI R16, 0 + MOVW R31:R30, R27:R26 + STD Z+1, R16 +// 178 BattData.Temperature = 0; + STD Z+2, R16 +// 179 BattData.Capacity = 0; + STD Z+4, R16 + STD Z+5, R16 +// 180 BattData.MaxCurrent = 0; + STD Z+6, R16 + STD Z+7, R16 +// 181 BattData.MaxTime = 0; + STD Z+8, R16 + STD Z+9, R16 +// 182 BattData.MinCurrent = 0; + STD Z+10, R16 + STD Z+11, R16 +// 183 +// 184 NTCLookUp(); + RCALL NTCLookUp +// 185 BattData.HasRID = RIDLookUp(); + RCALL RIDLookUp + MOV R17, R16 + ANDI R17, 0x01 + BST R17, 0 + LD R16, X + BLD R16, 4 + ST X, R16 +// 186 +// 187 // Is the battery voltage above minimum safe cell voltage? +// 188 if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+10 + LDD R17, Z+11 + CPI R16, 96 + LDI R18, 9 + CPC R17, R18 + BRCS ??BatteryStatusRefresh_0 +// 189 BattData.Low = FALSE; + LD R16, X + ANDI R16, 0xFB + ST X, R16 +// 190 } +// 191 +// 192 // Is the battery charged? +// 193 if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { +??BatteryStatusRefresh_0: + LDD R16, Z+10 + CPI R16, 210 + SBCI R17, 15 + BRCS ??BatteryStatusRefresh_1 +// 194 BattData.Charged = TRUE; + LD R16, X + ORI R16, 0x02 + ST X, R16 +// 195 } +// 196 +// 197 // If we are not charging, yet VBAT is above safe limit, battery is present. +// 198 // If we are charging and there's a current flowing, the battery is present. +// 199 +// 200 /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence +// 201 * check is redundant since charging will be aborted due to low current at +// 202 * max duty cycle. That is preferrable since the charge current reading is +// 203 * not 100% proof. +// 204 */ +// 205 if (((OCR1B == 0) && (!BattData.Low)) || +// 206 ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { +??BatteryStatusRefresh_1: + IN R16, 0x2C + TST R16 + BRNE ??BatteryStatusRefresh_2 + LD R16, X + SBRS R16, 2 + RJMP ??BatteryStatusRefresh_3 +??BatteryStatusRefresh_2: + IN R16, 0x2C + TST R16 + BREQ ??BatteryStatusRefresh_4 + LDD R24, Z+22 + LDD R25, Z+23 + CPI R24, 1 + SBCI R25, 0 + BRLT ??BatteryStatusRefresh_4 +// 207 BattData.Present = TRUE; +??BatteryStatusRefresh_3: + LD R16, X + ORI R16, 0x01 + ST X, R16 +// 208 success = TRUE; + LDI R16, 1 + RJMP ??BatteryStatusRefresh_5 +// 209 } else { +// 210 BattData.Low = FALSE; // (This is just a technicality..) +??BatteryStatusRefresh_4: + LD R16, X + ANDI R16, 0xFB + ST X, R16 +// 211 success = FALSE; + LDI R16, 0 +// 212 } +// 213 +// 214 #ifndef ALLOW_NO_RID +// 215 // Return FALSE if no valid RID entry was found, to stop charging. +// 216 if(!BattData.HasRID) { +??BatteryStatusRefresh_5: + LD R17, X + SBRS R17, 4 +// 217 success = FALSE; + LDI R16, 0 +// 218 } +// 219 #endif +// 220 +// 221 return(success); +??BatteryStatusRefresh_6: + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + RET + REQUIRE _A_OCR1B +// 222 } +// 223 +// 224 +// 225 /*! \brief Refreshes battery data in the EEPROM +// 226 * +// 227 * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store +// 228 * these data in on-chip EEPROM.\n +// 229 * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared. +// 230 * +// 231 * \todo Updating BattData with these data. Specs needed. +// 232 * +// 233 * \retval FALSE Refresh failed. +// 234 * \retval TRUE Refresh successful. +// 235 */ + + RSEG CODE:CODE:NOROOT(1) +// 236 unsigned char BatteryDataRefresh(void) +BatteryDataRefresh: +// 237 { + ST -Y, R8 + ST -Y, R7 + ST -Y, R6 + ST -Y, R5 + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + REQUIRE ?Register_R7_is_cg_reg + REQUIRE ?Register_R8_is_cg_reg +// 238 unsigned char offset; +// 239 unsigned char i, crc, family, temp, page; +// 240 unsigned char success; +// 241 +// 242 // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found. +// 243 for (page = 0; page < 4; page++) { + LDI R25, 0 + LDI R26, LOW(BattEEPROM) + LDI R27, (BattEEPROM) >> 8 +// 244 success = FALSE; +??BatteryDataRefresh_0: + CLR R7 +// 245 +// 246 if (OWI_DetectPresence(OWIBUS) == OWIBUS) { + LDI R16, 1 + RCALL OWI_DetectPresence + CPI R16, 1 + BREQ $+2+2 + RJMP ??BatteryDataRefresh_1 +// 247 +// 248 // Presence detected, check type and CRC. +// 249 OWI_SendByte(OWI_ROM_READ, OWIBUS); + LDI R17, 1 + LDI R16, 51 + RCALL OWI_SendByte +// 250 family = OWI_ReceiveByte(OWIBUS); + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R5, R16 +// 251 crc = OWI_ComputeCRC8(family,0); + LDI R17, 0 + RCALL OWI_ComputeCRC8 + MOV R24, R16 +// 252 +// 253 for (i = 0; i < 6; i++) { + LDI R16, 6 + MOV R4, R16 +// 254 crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc); +??BatteryDataRefresh_2: + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R24 + RCALL OWI_ComputeCRC8 + MOV R24, R16 +// 255 } + DEC R4 + BRNE ??BatteryDataRefresh_2 +// 256 +// 257 // CRC ok, device found. +// 258 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R24 + RCALL OWI_ComputeCRC8 + TST R16 + BRNE ??BatteryDataRefresh_1 +// 259 BattData.Circuit = family; + STS (BattData + 1), R5 +// 260 +// 261 // For now, we only read data from DS2505 EPROMs. +// 262 if (BattData.Circuit == OW_DS2505) { + LDS R16, (BattData + 1) + CPI R16, 9 + BRNE ??BatteryDataRefresh_1 +// 263 offset = page*32; + MOV R4, R25 + SWAP R4 + LDI R16, 240 + AND R4, R16 + LSL R4 +// 264 OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data. + LDI R17, 1 + LDI R16, 195 + RCALL OWI_SendByte +// 265 OWI_SendByte(offset, OWIBUS); // Data: low address. + LDI R17, 1 + MOV R16, R4 + RCALL OWI_SendByte +// 266 OWI_SendByte(0, OWIBUS); // Data: high address. + LDI R17, 1 + LDI R16, 0 + RCALL OWI_SendByte +// 267 +// 268 // Calculate checksums. +// 269 crc = OWI_ComputeCRC8(DS2505_DATA_READ,0); + LDI R17, 0 + LDI R16, 195 + RCALL OWI_ComputeCRC8 +// 270 crc = OWI_ComputeCRC8(offset,crc); + MOV R17, R16 + MOV R16, R4 + RCALL OWI_ComputeCRC8 +// 271 crc = OWI_ComputeCRC8(0,crc); + MOV R17, R16 + LDI R16, 0 + RCALL OWI_ComputeCRC8 + MOV R24, R16 +// 272 +// 273 // Command received succesfully, now start reading data +// 274 // and writing it to EEPROM. +// 275 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R17, R24 + RCALL OWI_ComputeCRC8 + TST R16 + BRNE ??BatteryDataRefresh_1 +// 276 crc = 0; + LDI R24, 0 +// 277 +// 278 // Fill page with data. +// 279 for (i=0; i<32; i++) { + MOVW R5:R4, R27:R26 + LDI R16, 32 + MOV R6, R16 +// 280 temp = OWI_ReceiveByte(OWIBUS); +??BatteryDataRefresh_3: + LDI R16, 1 + RCALL OWI_ReceiveByte + MOV R8, R16 +// 281 crc = OWI_ComputeCRC8(temp, crc); + MOV R17, R24 + RCALL OWI_ComputeCRC8 + MOV R24, R16 +// 282 BattEEPROM[page][i] = temp; + MOV R16, R8 + MOVW R21:R20, R5:R4 + RCALL __eeput8_16 +// 283 } + LDI R16, 1 + ADD R4, R16 + ADC R5, R7 + DEC R6 + BRNE ??BatteryDataRefresh_3 +// 284 +// 285 if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + RCALL OWI_ReceiveByte + MOV R17, R24 + RCALL OWI_ComputeCRC8 + TST R16 + BRNE ??BatteryDataRefresh_1 +// 286 success = TRUE; // Data read OK + INC R7 + RJMP ??BatteryDataRefresh_4 +// 287 } +// 288 } else { // Not able to start reading data. +// 289 } +// 290 } else { // Wrong device type. +// 291 } +// 292 } else { // No device found. +// 293 } +// 294 } else { // No presence detected on one-wire bus. +// 295 } +// 296 +// 297 // Erase local EEPROM page if there were any errors during transfer. +// 298 if (!success) { +// 299 for (i=0; i<32; i++) { +??BatteryDataRefresh_1: + MOVW R21:R20, R27:R26 + LDI R17, 32 +// 300 BattEEPROM[page][i] = 0; +??BatteryDataRefresh_5: + LDI R16, 0 + RCALL __eeput8_16 +// 301 } + SUBI R20, 255 + SBCI R21, 255 + DEC R17 + BRNE ??BatteryDataRefresh_5 +// 302 } +// 303 } +??BatteryDataRefresh_4: + INC R25 + ADIW R27:R26, 32 + CPI R25, 4 + BRCC $+2+2 + RJMP ??BatteryDataRefresh_0 +// 304 +// 305 return(success); + MOV R16, R7 + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + LD R4, Y+ + LD R5, Y+ + LD R6, Y+ + LD R7, Y+ + LD R8, Y+ + RET +// 306 } +// 307 +// 308 +// 309 /*! \brief Enables specified battery +// 310 * +// 311 * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears +// 312 * PB5/PB4 in PORTB, depending on which battery is specified.\n +// 313 * The function takes 100 ms to allow the port switch to settle. +// 314 * +// 315 * \param bat Specifies which battery to enable (0 = battery A, 1 = B) +// 316 */ + + RSEG CODE:CODE:NOROOT(1) +// 317 void EnableBattery(unsigned char bat) +EnableBattery: +// 318 { + ST -Y, R24 + MOV R24, R16 +// 319 // Use general timer, set timeout to 100ms. +// 320 Time_Set(TIMER_GEN,0,0,100); + LDI R20, 100 + LDI R17, 0 + LDI R18, 0 + LDI R19, 0 + LDI R16, 2 + RCALL Time_Set +// 321 +// 322 // Set specified battery as the active one. +// 323 BattActive = bat; + STS BattActive, R24 +// 324 +// 325 // Enable current battery in hardware, light LED & connect battery. +// 326 PORTB |= (1 << (PB4+bat)); + LDI R16, 1 + LDI R17, 0 + MOV R20, R24 + SUBI R20, 252 + RCALL ?S_SHL_L02 + IN R17, 0x18 + OR R17, R16 + OUT 0x18, R17 +// 327 +// 328 // Disconnect other battery. +// 329 PORTB &= ~(1<<(PB5-bat)); + LDI R16, 1 + LDI R17, 0 + LDI R20, 5 + SUB R20, R24 + RCALL ?S_SHL_L02 + COM R16 + IN R17, 0x18 + AND R17, R16 + OUT 0x18, R17 +// 330 +// 331 do { // Let port switch settle. +// 332 } while (Time_Left(TIMER_GEN)); +??EnableBattery_0: + LDI R16, 2 + RCALL Time_Left + TST R16 + BRNE ??EnableBattery_0 +// 333 } + LD R24, Y+ + RET + REQUIRE _A_PORTB +// 334 +// 335 +// 336 /*! \brief Disables both batteries +// 337 * +// 338 * Clears PB4 and PB5 in PORTB, disabling both batteries. +// 339 */ + + RSEG CODE:CODE:NOROOT(1) +// 340 void DisableBatteries(void) +DisableBatteries: +// 341 { +// 342 // Turn off LEDs and disconnect batteries. +// 343 PORTB &= ~((1<> 8 + LDI R18, 4 + LDI R16, LOW(BattData) + LDI R17, (BattData) >> 8 +// 363 if (ADCS.rawRID >= RID[i].Low) { +??RIDLookUp_0: + LDI R26, LOW((ADCS + 2)) + LDI R27, HIGH((ADCS + 2)) + LD R22, X+ + LD R23, X + LD R0, Z + LDD R1, Z+1 + CP R22, R0 + CPC R23, R1 + BRCS ??RIDLookUp_1 +// 364 if (ADCS.rawRID <= RID[i].High) { + LDD R0, Z+2 + LDD R1, Z+3 + CP R0, R22 + CPC R1, R23 + BRCS ??RIDLookUp_1 +// 365 BattData.Capacity = RID[i].Capacity; + LDD R20, Z+6 + LDD R21, Z+7 + MOVW R27:R26, R17:R16 + ADIW R27:R26, 4 + ST X+, R20 + ST X, R21 +// 366 BattData.MaxCurrent = RID[i].Icharge; + LDD R20, Z+8 + LDD R21, Z+9 + MOVW R27:R26, R17:R16 + ADIW R27:R26, 6 + ST X+, R20 + ST X, R21 +// 367 BattData.MaxTime = RID[i].tCutOff; + LDD R20, Z+10 + LDD R21, Z+11 + MOVW R27:R26, R17:R16 + ADIW R27:R26, 8 + ST X+, R20 + ST X, R21 +// 368 BattData.MinCurrent = RID[i].ICutOff; + LDD R20, Z+12 + LDD R21, Z+13 + MOVW R27:R26, R17:R16 + ADIW R27:R26, 10 + ST X+, R20 + ST X, R21 +// 369 +// 370 found = TRUE; + LDI R20, 1 +// 371 } +// 372 } +// 373 } +??RIDLookUp_1: + ADIW R31:R30, 14 + DEC R18 + BRNE ??RIDLookUp_0 +// 374 +// 375 // If no valid entry is found, use defaults and return FALSE. +// 376 if (!found) { + TST R20 + BRNE ??RIDLookUp_2 +// 377 BattData.Capacity = DEF_BAT_CAPACITY; + LDI R18, 0 + MOVW R31:R30, R17:R16 + STD Z+4, R18 + STD Z+5, R18 +// 378 BattData.MaxCurrent = DEF_BAT_CURRENT_MAX; + STD Z+6, R18 + STD Z+7, R18 +// 379 BattData.MaxTime = DEF_BAT_TIME_MAX; + STD Z+8, R18 + STD Z+9, R18 +// 380 BattData.MinCurrent = DEF_BAT_CURRENT_MIN; + STD Z+10, R18 + STD Z+11, R18 +// 381 } +// 382 +// 383 return(found); +??RIDLookUp_2: + MOV R16, R20 + MOV R26, R2 + MOV R27, R19 + RET +// 384 } +// 385 +// 386 +// 387 /*! \brief Calculates temperature from a lookup table +// 388 * +// 389 * Looks up the highest NTC value below or equal to the measured one.\n +// 390 * With the current lookup table, temperature is calculated with the formula:\n +// 391 * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry) +// 392 * +// 393 * \note If the NTC-measurement is saturated, with the current lookup table, +// 394 * the temperature will be reported as -1 C. +// 395 * +// 396 * \note If no valid entry is found, battery temperature is set to 80. +// 397 */ + + RSEG CODE:CODE:NOROOT(1) +// 398 void NTCLookUp (void) +NTCLookUp: +// 399 { + ST -Y, R27 + MOV R3, R26 + MOV R2, R24 +// 400 unsigned char i; +// 401 unsigned char found = FALSE; + LDI R16, 0 +// 402 +// 403 // Lookup in the NTC-table. Use the first entry which is equal or below +// 404 // sampled NTC. Calculate temperature by using the index number, and the +// 405 // difference between the measured NTC value and the one in the entry. +// 406 for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { + LDI R24, 0 + LDI R26, LOW(BattData) + LDI R27, (BattData) >> 8 +// 407 if (ADCS.rawNTC >= NTC[i].ADC) { +??NTCLookUp_0: + MOV R20, R24 + LDI R21, 0 + MOVW R19:R18, R21:R20 + LSL R20 + ROL R21 + ADD R20, R18 + ADC R21, R19 + LDI R18, LOW(NTC) + LDI R19, (NTC) >> 8 + ADD R18, R20 + ADC R19, R21 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R20, Z+4 + LDD R21, Z+5 + MOVW R31:R30, R19:R18 + LD R22, Z + LDD R23, Z+1 + CP R20, R22 + CPC R21, R23 + BRCS ??NTCLookUp_1 +// 408 BattData.Temperature = (i<<2) ; + MOV R16, R24 + LSL R16 + LSL R16 + MOVW R31:R30, R27:R26 + STD Z+2, R16 +// 409 BattData.ADCSteps = NTC[i].ADCsteps; + MOVW R31:R30, R19:R18 + LDD R20, Z+2 + MOVW R31:R30, R27:R26 + STD Z+3, R20 +// 410 BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps; + LDS R16, (ADCS + 4) + MOV R17, R21 + MOVW R31:R30, R19:R18 + LD R18, Z + LDD R19, Z+1 + SUB R16, R18 + SBC R17, R19 + LSL R16 + ROL R17 + LDI R21, 0 + RCALL ?US_DIVMOD_L02 + MOVW R31:R30, R27:R26 + LDD R17, Z+2 + SUB R17, R16 + STD Z+2, R17 +// 411 +// 412 found = TRUE; // Could be done with a break, but that violates MISRA. + LDI R16, 1 +// 413 } +// 414 } +??NTCLookUp_1: + INC R24 + CPI R24, 20 + BRCC ??NTCLookUp_2 + TST R16 + BREQ ??NTCLookUp_0 +// 415 +// 416 // For safety, is temperature is greater than the NTC +// 417 if (!found) { +??NTCLookUp_2: + TST R16 + BRNE ??NTCLookUp_3 +// 418 BattData.Temperature = 80; + LDI R16, 80 + STS (BattData + 2), R16 +// 419 } +// 420 } +??NTCLookUp_3: + MOV R24, R2 + MOV R26, R3 + LD R27, Y+ + RET + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + RSEG NEAR_ID:CODE:NOROOT(0) +`?`: + DW 558, 659, 3900, 550, 260, 300, 10, 744, 843, 6800, 750, 360, 300, 14 + DW 869, 958, 10000, 1000, 475, 300, 19, 1097, 1153, 24000, 2000, 475 + DW 420, 38 + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_I) - SFB(NEAR_I) + DW SFB(NEAR_I) + DW SFB(NEAR_ID) + REQUIRE ?need_segment_init + + RSEG NEAR_ID:CODE:NOROOT(0) +`?`: + DW 1002 + DB 23 + DW 953 + DB 25 + DW 902 + DB 26 + DW 849 + DB 27 + DW 796 + DB 27 + DW 742 + DB 27 + DW 689 + DB 26 + DW 637 + DB 26 + DW 587 + DB 25 + DW 539 + DB 24 + DW 494 + DB 22 + DW 451 + DB 21 + DW 412 + DB 19 + DW 375 + DB 18 + DW 341 + DB 17 + DW 310 + DB 15 + DW 282 + DB 14 + DW 256 + DB 13 + DW 233 + DB 11 + DW 212 + DB 10 + + END +// +// 2 bytes in segment ABSOLUTE +// 804 bytes in segment CODE +// 130 bytes in segment EEPROM_I +// 12 bytes in segment INITTAB +// 116 bytes in segment NEAR_I +// 116 bytes in segment NEAR_ID +// 13 bytes in segment NEAR_Z +// +// 920 bytes of CODE memory (+ 12 bytes shared) +// 129 bytes of DATA memory (+ 2 bytes shared) +// 130 bytes of XDATA memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/chargefunc.lst b/BaseTinyFirmware/IAR/Release/List/chargefunc.lst new file mode 100644 index 0000000..1bc2244 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/chargefunc.lst @@ -0,0 +1,870 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\chargefunc.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\chargefunc.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\ch # +# argefunc.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\cha # +# rgefunc.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\chargefunc.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Charge functions + 6 * + 7 * Contains the functions for charging with constant current and voltage, + 8 * and for deciding when to halt. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 * + 14 * \par Documentation + 15 * For comprehensive code documentation, supported compilers, compiler + 16 * settings and supported devices see readme.html + 17 * + 18 * \author + 19 * Atmel Corporation: http://www.atmel.com \n + 20 * Support email: avr@atmel.com + 21 * + 22 * + 23 * $Name$ + 24 * $Revision: 2299 $ + 25 * $RCSfile$ + 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $ + 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 28 ******************************************************************************/ + 29 + 30 #include + + \ In segment ABSOLUTE, at 0x4c + \ volatile __io _A_OCR1B + \ _A_OCR1B: + \ 00000000 DS 1 + 31 + 32 #include "enums.h" + 33 #include "structs.h" + 34 + 35 #include "ADC.h" + 36 #include "battery.h" + 37 #include "chargefunc.h" + 38 #include "main.h" + 39 #include "menu.h" + 40 #include "PWM.h" + 41 #include "statefunc.h" + 42 #include "time.h" + 43 + 44 #ifdef NIMH + 45 #include "NIMHspecs.h" + 46 #endif // NIMH + 47 + 48 #ifdef LIION + 49 #include "LIIONspecs.h" + 50 #endif // LIION + 51 + 52 + 53 //****************************************************************************** + 54 // Variables + 55 //****************************************************************************** + 56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage(). + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 57 ChargeParameters_t ChargeParameters; + 58 + 59 //! Struct that holds parameters for HaltNow(). + 60 HaltParameters_t HaltParameters; + \ HaltParameters: + \ 00000000 DS 17 + \ ChargeParameters: + \ 00000011 DS 5 + 61 + 62 + 63 //****************************************************************************** + 64 // Functions + 65 //****************************************************************************** + 66 /*! \brief Charges battery with a constant current. + 67 * + 68 * This function applies a constant current (set in ChargeParameters.Current) + 69 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + 70 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + 71 * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n + 72 * If the Master inhibits charging, timers are stopped and PWM output dropped. + 73 * Once the battery is no longer flagged for charge inhibit, timers are + 74 * started again and charging resumed. + 75 * + 76 * \retval ChargeParameters.NextState Next state once this stage is done. + 77 * If no errors occured, this will be whatever was set in Charge(). Otherwise, + 78 * HaltNow() will have set a new next state. + 79 */ + + \ In segment CODE, align 2, keep-with-next + 80 unsigned char ConstantCurrent(void) + \ ConstantCurrent: + 81 { + \ 00000000 925A ST -Y, R5 + \ 00000002 924A ST -Y, R4 + \ 00000004 93BA ST -Y, R27 + \ 00000006 93AA ST -Y, R26 + \ 00000008 939A ST -Y, R25 + \ 0000000A 938A ST -Y, R24 + \ 0000000C REQUIRE ?Register_R4_is_cg_reg + \ 0000000C REQUIRE ?Register_R5_is_cg_reg + 82 unsigned char error = FALSE, + \ 0000000C 2455 CLR R5 + 83 wasStopped = FALSE; + \ 0000000E 2444 CLR R4 + 84 + 85 do { + 86 // Wait for ADC conversions to complete. + 87 ADC_Wait(); + \ ??ConstantCurrent_0: + \ 00000010 .... RCALL ADC_Wait + 88 + 89 // If Master has flagged for a charge inhibit, pause charging. + 90 // (This is to prevent damage during prolonged serial communication.) + 91 if (BattControl[BattActive].ChargeInhibit) { + \ 00000012 9100.... LDS R16, BattActive + \ 00000016 E010 LDI R17, 0 + \ 00000018 .... LDI R20, LOW(BattControl) + \ 0000001A .... LDI R21, (BattControl) >> 8 + \ 0000001C 0F40 ADD R20, R16 + \ 0000001E 1F51 ADC R21, R17 + \ 00000020 .... RCALL __eeget8_16 + \ 00000022 7004 ANDI R16, 0x04 + \ 00000024 F031 BREQ ??ConstantCurrent_1 + 92 wasStopped = TRUE; + \ 00000026 2444 CLR R4 + \ 00000028 9443 INC R4 + 93 Time_Stop(); + \ 0000002A .... RCALL Time_Stop + 94 OCR1B = 0; + \ 0000002C E000 LDI R16, 0 + \ 0000002E BD0C OUT 0x2C, R16 + \ 00000030 C025 RJMP ??ConstantCurrent_2 + 95 } else { + 96 // Continue charging! + 97 if (wasStopped) { + \ ??ConstantCurrent_1: + \ 00000032 2044 TST R4 + \ 00000034 F011 BREQ ??ConstantCurrent_3 + 98 wasStopped = FALSE; + \ 00000036 2444 CLR R4 + 99 + 100 // Timer variables are not reset by this. + 101 Time_Start(); + \ 00000038 .... RCALL Time_Start + 102 } + 103 + 104 // Adjust the charge current to within ChargeParameters.Current + 105 // +/- BAT_CURRENT_HYST. + 106 if ((ADCS.avgIBAT < 0) || + 107 (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { + \ ??ConstantCurrent_3: + \ 0000003A .... LDI R30, LOW(ADCS) + \ 0000003C .... LDI R31, (ADCS) >> 8 + \ 0000003E 8906 LDD R16, Z+22 + \ 00000040 8917 LDD R17, Z+23 + \ 00000042 2311 TST R17 + \ 00000044 F04A BRMI ??ConstantCurrent_4 + \ 00000046 .... LDI R26, LOW((HaltParameters + 19)) + \ 00000048 .... LDI R27, HIGH((HaltParameters + 19)) + \ 0000004A 91ED LD R30, X+ + \ 0000004C 91FC LD R31, X + \ 0000004E 01CF MOVW R25:R24, R31:R30 + \ 00000050 9703 SBIW R25:R24, 3 + \ 00000052 1708 CP R16, R24 + \ 00000054 0719 CPC R17, R25 + \ 00000056 F458 BRCC ??ConstantCurrent_5 + 108 + 109 if(!PWM_IncrementDutyCycle()) { + \ ??ConstantCurrent_4: + \ 00000058 .... RCALL PWM_IncrementDutyCycle + \ 0000005A 2300 TST R16 + \ 0000005C F479 BRNE ??ConstantCurrent_2 + 110 #ifdef ABORT_IF_PWM_MAX + 111 // If the duty cycle cannot be incremented, flag error and + 112 // go to error state. + 113 SetErrorFlag(ERR_PWM_CONTROL); + \ ??ConstantCurrent_6: + \ 0000005E E004 LDI R16, 4 + \ 00000060 .... RCALL SetErrorFlag + 114 ChargeParameters.NextState = ST_ERROR; + \ 00000062 E50A LDI R16, 90 + \ 00000064 9300.... STS (HaltParameters + 21), R16 + 115 error = TRUE; + \ 00000068 2455 CLR R5 + \ 0000006A 9453 INC R5 + \ 0000006C C007 RJMP ??ConstantCurrent_2 + 116 #endif + 117 } + 118 } else if ((ADCS.avgIBAT >= 0) && + \ ??ConstantCurrent_5: + \ 0000006E 9633 ADIW R31:R30, 3 + \ 00000070 17E0 CP R30, R16 + \ 00000072 07F1 CPC R31, R17 + \ 00000074 F418 BRCC ??ConstantCurrent_2 + 119 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { + 120 + 121 if(!PWM_DecrementDutyCycle()) { + \ 00000076 .... RCALL PWM_DecrementDutyCycle + \ 00000078 2300 TST R16 + \ 0000007A F389 BREQ ??ConstantCurrent_6 + 122 #ifdef ABORT_IF_PWM_MIN + 123 // If the duty cycle cannot be decremented, flag error and + 124 // go to error state. + 125 SetErrorFlag(ERR_PWM_CONTROL); + 126 ChargeParameters.NextState = ST_ERROR; + 127 error = TRUE; + 128 #endif + 129 } + 130 } + 131 } + 132 } while ((!HaltNow()) && (!error)); + \ ??ConstantCurrent_2: + \ 0000007C .... RCALL HaltNow + \ 0000007E 2300 TST R16 + \ 00000080 F411 BRNE ??ConstantCurrent_7 + \ 00000082 2055 TST R5 + \ 00000084 F229 BREQ ??ConstantCurrent_0 + 133 + 134 // Return the next state to Charge(). If an error has occured, this will + 135 // point to some other state than the next state of charging. + 136 return(ChargeParameters.NextState); + \ ??ConstantCurrent_7: + \ 00000086 9100.... LDS R16, (HaltParameters + 21) + \ 0000008A 9189 LD R24, Y+ + \ 0000008C 9199 LD R25, Y+ + \ 0000008E 91A9 LD R26, Y+ + \ 00000090 91B9 LD R27, Y+ + \ 00000092 9049 LD R4, Y+ + \ 00000094 9059 LD R5, Y+ + \ 00000096 9508 RET + \ 00000098 REQUIRE _A_OCR1B + 137 } + 138 + 139 + 140 /*! \brief Charges battery with a constant voltage + 141 * + 142 * This function applies a constant voltage (set in ChargeParameters.Voltage) + 143 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + 144 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + 145 * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n + 146 * If the Master inhibits charging, timers are stopped and PWM output dropped. + 147 * Once the battery is no longer flagged for charge inhibit, timers are + 148 * started again and charging resumed. + 149 * + 150 * \retval ChargeParameters.NextState Next state once this stage is done. + 151 * If no errors occured, this will be whatever was set in Charge(). Otherwise, + 152 * HaltNow() will have set a new next state. + 153 */ + + \ In segment CODE, align 2, keep-with-next + 154 unsigned char ConstantVoltage(void) + \ ConstantVoltage: + 155 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + \ 00000004 939A ST -Y, R25 + \ 00000006 938A ST -Y, R24 + 156 unsigned char error = FALSE, + \ 00000008 E090 LDI R25, 0 + 157 wasStopped = FALSE; + \ 0000000A E080 LDI R24, 0 + 158 + 159 do{ + 160 + 161 // Wait for ADC conversions to complete. + 162 ADC_Wait(); + \ ??ConstantVoltage_0: + \ 0000000C .... RCALL ADC_Wait + 163 + 164 // If Master has flagged for a charge inhibit, pause charging. + 165 // (This is to prevent damage during prolonged serial communication.) + 166 if (BattControl[BattActive].ChargeInhibit) { + \ 0000000E 9100.... LDS R16, BattActive + \ 00000012 E010 LDI R17, 0 + \ 00000014 .... LDI R20, LOW(BattControl) + \ 00000016 .... LDI R21, (BattControl) >> 8 + \ 00000018 0F40 ADD R20, R16 + \ 0000001A 1F51 ADC R21, R17 + \ 0000001C .... RCALL __eeget8_16 + \ 0000001E 7004 ANDI R16, 0x04 + \ 00000020 F029 BREQ ??ConstantVoltage_1 + 167 wasStopped = TRUE; + \ 00000022 E081 LDI R24, 1 + 168 Time_Stop(); + \ 00000024 .... RCALL Time_Stop + 169 OCR1B = 0; + \ 00000026 E000 LDI R16, 0 + \ 00000028 BD0C OUT 0x2C, R16 + \ 0000002A C024 RJMP ??ConstantVoltage_2 + 170 } + 171 + 172 else { + 173 // Continue charging! + 174 if (wasStopped) { + \ ??ConstantVoltage_1: + \ 0000002C 2388 TST R24 + \ 0000002E F011 BREQ ??ConstantVoltage_3 + 175 wasStopped = FALSE; + \ 00000030 E080 LDI R24, 0 + 176 + 177 // Timer variables aren't reset by this. + 178 Time_Start(); + \ 00000032 .... RCALL Time_Start + 179 } + 180 + 181 // Adjust the charge voltage to within ChargeParameters.Voltage + 182 // +/- BAT_VOLTAGE_HYST. + 183 if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { + \ ??ConstantVoltage_3: + \ 00000034 .... LDI R26, LOW(HaltParameters) + \ 00000036 .... LDI R27, (HaltParameters) >> 8 + \ 00000038 01FD MOVW R31:R30, R27:R26 + \ 0000003A 8901 LDD R16, Z+17 + \ 0000003C 8912 LDD R17, Z+18 + \ 0000003E .... LDI R30, LOW(ADCS) + \ 00000040 .... LDI R31, (ADCS) >> 8 + \ 00000042 8522 LDD R18, Z+10 + \ 00000044 8533 LDD R19, Z+11 + \ 00000046 01F8 MOVW R31:R30, R17:R16 + \ 00000048 973A SBIW R31:R30, 10 + \ 0000004A 172E CP R18, R30 + \ 0000004C 073F CPC R19, R31 + \ 0000004E F450 BRCC ??ConstantVoltage_4 + 184 + 185 if(!PWM_IncrementDutyCycle()) { + \ 00000050 .... RCALL PWM_IncrementDutyCycle + \ 00000052 2300 TST R16 + \ 00000054 F479 BRNE ??ConstantVoltage_2 + 186 #ifdef ABORT_IF_PWM_MAX + 187 // Flag PWM control error and go to error-state if the duty + 188 // cycle cannot be incremented. + 189 SetErrorFlag(ERR_PWM_CONTROL); + \ ??ConstantVoltage_5: + \ 00000056 E004 LDI R16, 4 + \ 00000058 .... RCALL SetErrorFlag + 190 ChargeParameters.NextState = ST_ERROR; + \ 0000005A E50A LDI R16, 90 + \ 0000005C 01FD MOVW R31:R30, R27:R26 + \ 0000005E 8B05 STD Z+21, R16 + 191 error = TRUE; + \ 00000060 E091 LDI R25, 1 + \ 00000062 C008 RJMP ??ConstantVoltage_2 + 192 #endif + 193 } + 194 } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { + \ ??ConstantVoltage_4: + \ 00000064 5F06 SUBI R16, 246 + \ 00000066 4F1F SBCI R17, 255 + \ 00000068 1702 CP R16, R18 + \ 0000006A 0713 CPC R17, R19 + \ 0000006C F418 BRCC ??ConstantVoltage_2 + 195 + 196 if(!PWM_DecrementDutyCycle()) { + \ 0000006E .... RCALL PWM_DecrementDutyCycle + \ 00000070 2300 TST R16 + \ 00000072 F389 BREQ ??ConstantVoltage_5 + 197 #ifdef ABORT_IF_PWM_MIN + 198 // Flag PWM control error and go to error-state if duty + 199 // cycle cannot be decremented. + 200 SetErrorFlag(ERR_PWM_CONTROL); + 201 ChargeParameters.NextState = ST_ERROR; + 202 error = TRUE; + 203 #endif + 204 } + 205 } + 206 } + 207 + 208 } while ((!HaltNow()) && (!error)); + \ ??ConstantVoltage_2: + \ 00000074 .... RCALL HaltNow + \ 00000076 2300 TST R16 + \ 00000078 F411 BRNE ??ConstantVoltage_6 + \ 0000007A 2399 TST R25 + \ 0000007C F239 BREQ ??ConstantVoltage_0 + 209 + 210 // Return the next state to Charge(). If an error has occured, this will + 211 // point to some other state than the next state of charging. + 212 return(ChargeParameters.NextState); + \ ??ConstantVoltage_6: + \ 0000007E 9100.... LDS R16, (HaltParameters + 21) + \ 00000082 9189 LD R24, Y+ + \ 00000084 9199 LD R25, Y+ + \ 00000086 91A9 LD R26, Y+ + \ 00000088 91B9 LD R27, Y+ + \ 0000008A 9508 RET + \ 0000008C REQUIRE _A_OCR1B + 213 } + 214 + 215 + 216 /*! \brief Determines when to halt charging. + 217 * + 218 * This function evaluates parameters depending on what has been flagged in + 219 * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should + 220 * halt or not.\n + 221 * In addition, error flagging on timeout (battery exhaustion) can be set.\n + 222 * + 223 * The function also checks if the battery temperature is within limits, + 224 * if mains is OK, and if BatteryCheck() returns TRUE. + 225 * If an error is detected, the associated errorflag is set and + 226 * ChargeParameters.NextState is changed to an appropriate state. + 227 * + 228 * \retval TRUE Halt now. + 229 * \retval FALSE Don't halt now. + 230 * + 231 * \note See chargefunc.h for definitions of halt flags. + 232 * \note It is generally a bad idea not to halt on a timeout. + 233 * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be + 234 * reset in Charge() before calling a charging-function. + 235 * + 236 * \todo "Priorities" of standard error checks OK? + 237 */ + + \ In segment CODE, align 2, keep-with-next + 238 unsigned char HaltNow(void) + \ HaltNow: + 239 { + \ 00000000 929A ST -Y, R9 + \ 00000002 928A ST -Y, R8 + \ 00000004 927A ST -Y, R7 + \ 00000006 926A ST -Y, R6 + \ 00000008 925A ST -Y, R5 + \ 0000000A 924A ST -Y, R4 + \ 0000000C 93BA ST -Y, R27 + \ 0000000E 93AA ST -Y, R26 + \ 00000010 939A ST -Y, R25 + \ 00000012 938A ST -Y, R24 + \ 00000014 REQUIRE ?Register_R4_is_cg_reg + \ 00000014 REQUIRE ?Register_R5_is_cg_reg + \ 00000014 REQUIRE ?Register_R6_is_cg_reg + \ 00000014 REQUIRE ?Register_R7_is_cg_reg + \ 00000014 REQUIRE ?Register_R8_is_cg_reg + \ 00000014 REQUIRE ?Register_R9_is_cg_reg + 240 unsigned char i, halt = FALSE; + \ 00000014 2477 CLR R7 + 241 + 242 // Wait for a full ADC-cycle to finish. + 243 ADC_Wait(); + \ 00000016 .... RCALL ADC_Wait + 244 + 245 // Evaluate ADC readings according to HaltFlags. Flag errors if selected. + 246 // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR. + 247 // (Gets overridden if either mains is failing, or the battery changes.) + 248 for (i = 0x01; i != 0; i <<= 1) { + \ 00000018 2466 CLR R6 + \ 0000001A 9463 INC R6 + \ 0000001C .... LDI R24, LOW(ADCS) + \ 0000001E .... LDI R25, (ADCS) >> 8 + \ 00000020 .... LDI R16, LOW(BattData) + \ 00000022 2E40 MOV R4, R16 + \ 00000024 .... LDI R16, (BattData) >> 8 + \ 00000026 2E50 MOV R5, R16 + \ 00000028 .... LDI R26, LOW(HaltParameters) + \ 0000002A .... LDI R27, (HaltParameters) >> 8 + 249 if (HaltParameters.HaltFlags & i) { + \ ??HaltNow_0: + \ 0000002C 910C LD R16, X + \ 0000002E 2106 AND R16, R6 + \ 00000030 F409 BRNE $+2+2 + \ 00000032 C07C RJMP ??HaltNow_1 + 250 switch (i) { + \ 00000034 2D06 MOV R16, R6 + \ 00000036 950A DEC R16 + \ 00000038 F051 BREQ ??HaltNow_2 + \ 0000003A 950A DEC R16 + \ 0000003C F109 BREQ ??HaltNow_3 + \ 0000003E 5002 SUBI R16, 2 + \ 00000040 F151 BREQ ??HaltNow_4 + \ 00000042 5004 SUBI R16, 4 + \ 00000044 F179 BREQ ??HaltNow_5 + \ 00000046 5008 SUBI R16, 8 + \ 00000048 F409 BRNE $+2+2 + \ 0000004A C053 RJMP ??HaltNow_6 + \ 0000004C C06F RJMP ??HaltNow_1 + 251 // Is VBAT less than the recorded maximum? + 252 case HALT_VOLTAGE_DROP: + 253 + 254 // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. + 255 if (ADCS.VBAT > HaltParameters.VBATMax) { + \ ??HaltNow_2: + \ 0000004E 01FD MOVW R31:R30, R27:R26 + \ 00000050 8505 LDD R16, Z+13 + \ 00000052 8516 LDD R17, Z+14 + \ 00000054 01FC MOVW R31:R30, R25:R24 + \ 00000056 8522 LDD R18, Z+10 + \ 00000058 8533 LDD R19, Z+11 + \ 0000005A 1702 CP R16, R18 + \ 0000005C 0713 CPC R17, R19 + \ 0000005E F420 BRCC ??HaltNow_7 + 256 HaltParameters.VBATMax = ADCS.VBAT; + \ 00000060 01FD MOVW R31:R30, R27:R26 + \ 00000062 8725 STD Z+13, R18 + \ 00000064 8736 STD Z+14, R19 + \ 00000066 C062 RJMP ??HaltNow_1 + 257 } else if((HaltParameters.VBATMax - ADCS.VBAT) >= + 258 HaltParameters.VoltageDrop) { + \ ??HaltNow_7: + \ 00000068 1B02 SUB R16, R18 + \ 0000006A 0B13 SBC R17, R19 + \ 0000006C 01FD MOVW R31:R30, R27:R26 + \ 0000006E 8121 LDD R18, Z+1 + \ 00000070 8132 LDD R19, Z+2 + \ 00000072 1702 CP R16, R18 + \ 00000074 0713 CPC R17, R19 + \ 00000076 F408 BRCC $+2+2 + \ 00000078 C059 RJMP ??HaltNow_1 + 259 halt = TRUE; + \ ??HaltNow_8: + \ 0000007A 2477 CLR R7 + \ 0000007C 9473 INC R7 + \ 0000007E C056 RJMP ??HaltNow_1 + 260 } + 261 break; + 262 + 263 + 264 // Has VBAT reached the maximum limit? + 265 case HALT_VOLTAGE_MAX: + 266 + 267 if (ADCS.VBAT >= HaltParameters.VoltageMax) { + \ ??HaltNow_3: + \ 00000080 01FC MOVW R31:R30, R25:R24 + \ 00000082 8502 LDD R16, Z+10 + \ 00000084 8513 LDD R17, Z+11 + \ 00000086 01FD MOVW R31:R30, R27:R26 + \ 00000088 8123 LDD R18, Z+3 + \ 0000008A 8134 LDD R19, Z+4 + \ ??HaltNow_9: + \ 0000008C 1702 CP R16, R18 + \ 0000008E 0713 CPC R17, R19 + \ 00000090 F408 BRCC $+2+2 + \ 00000092 C04C RJMP ??HaltNow_1 + \ 00000094 CFF2 RJMP ??HaltNow_8 + 268 halt = TRUE; + 269 } + 270 break; + 271 + 272 + 273 // Has IBAT reached the minimum limit? + 274 case HALT_CURRENT_MIN: + 275 + 276 if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { + \ ??HaltNow_4: + \ 00000096 01FD MOVW R31:R30, R27:R26 + \ 00000098 8105 LDD R16, Z+5 + \ 0000009A 8116 LDD R17, Z+6 + \ 0000009C 01FC MOVW R31:R30, R25:R24 + \ 0000009E 8926 LDD R18, Z+22 + \ 000000A0 8937 LDD R19, Z+23 + \ 000000A2 CFF4 RJMP ??HaltNow_9 + 277 halt = TRUE; + 278 } + 279 break; + 280 + 281 + 282 // Is the temperature rising too fast? + 283 case HALT_TEMPERATURE_RISE: + 284 + 285 // If rawNTC has increased, the temperature has dropped. + 286 // We can store this value for now, and start the timer. + 287 // Otherwise, check if NTC has changed too fast. + 288 if (ADCS.rawNTC > HaltParameters.LastNTC) { + \ ??HaltNow_5: + \ 000000A4 01FC MOVW R31:R30, R25:R24 + \ 000000A6 8104 LDD R16, Z+4 + \ 000000A8 8115 LDD R17, Z+5 + \ 000000AA 01FD MOVW R31:R30, R27:R26 + \ 000000AC 8487 LDD R8, Z+15 + \ 000000AE 8890 LDD R9, Z+16 + \ 000000B0 1680 CP R8, R16 + \ 000000B2 0691 CPC R9, R17 + \ 000000B4 F468 BRCC ??HaltNow_10 + 289 HaltParameters.LastNTC = ADCS.rawNTC; + \ ??HaltNow_11: + \ 000000B6 01FC MOVW R31:R30, R25:R24 + \ 000000B8 8104 LDD R16, Z+4 + \ 000000BA 8115 LDD R17, Z+5 + \ 000000BC 01FD MOVW R31:R30, R27:R26 + \ 000000BE 8707 STD Z+15, R16 + \ 000000C0 8B10 STD Z+16, R17 + 290 Time_Set(TIMER_TEMP,0,30,0); + \ 000000C2 E040 LDI R20, 0 + \ 000000C4 E11E LDI R17, 30 + \ 000000C6 E020 LDI R18, 0 + \ 000000C8 E030 LDI R19, 0 + \ 000000CA E003 LDI R16, 3 + \ 000000CC .... RCALL Time_Set + \ 000000CE C02E RJMP ??HaltNow_1 + 291 + 292 // Is the increase in temperature greater than the set threshold? + 293 } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= + 294 (BattData.ADCSteps * HaltParameters.TemperatureRise)) { + \ ??HaltNow_10: + \ 000000D0 1A80 SUB R8, R16 + \ 000000D2 0A91 SBC R9, R17 + \ 000000D4 01F2 MOVW R31:R30, R5:R4 + \ 000000D6 8143 LDD R20, Z+3 + \ 000000D8 E050 LDI R21, 0 + \ 000000DA 01FD MOVW R31:R30, R27:R26 + \ 000000DC 8503 LDD R16, Z+11 + \ 000000DE 8514 LDD R17, Z+12 + \ 000000E0 .... RCALL ?S_MUL_L02 + \ 000000E2 1480 CP R8, R0 + \ 000000E4 0491 CPC R9, R1 + \ 000000E6 F110 BRCS ??HaltNow_1 + 295 + 296 // If this happened within a timeframe of 30 seconds, the + 297 // temperature is rising faster than we want. + 298 // If not, update LastNTC and reset timer. + 299 if (Time_Left(TIMER_TEMP)) { + \ 000000E8 E003 LDI R16, 3 + \ 000000EA .... RCALL Time_Left + \ 000000EC 2300 TST R16 + \ 000000EE F629 BRNE ??HaltNow_8 + \ 000000F0 CFE2 RJMP ??HaltNow_11 + 300 halt = TRUE; + 301 } else { + 302 HaltParameters.LastNTC = ADCS.rawNTC; + 303 Time_Set(TIMER_TEMP,0,30,0); + 304 } + 305 } + 306 break; + 307 + 308 + 309 // Is there any time left? + 310 case HALT_TIME: + 311 + 312 if (!Time_Left(TIMER_CHG)) { + \ ??HaltNow_6: + \ 000000F2 E001 LDI R16, 1 + \ 000000F4 .... RCALL Time_Left + \ 000000F6 2300 TST R16 + \ 000000F8 F4C9 BRNE ??HaltNow_1 + 313 halt = TRUE; + \ 000000FA 2477 CLR R7 + \ 000000FC 9473 INC R7 + 314 + 315 // If exhaustion flagging is selected, stop the PWM, disable the + 316 // battery and flag it as exhausted. Make ST_ERROR next state. + 317 if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { + \ 000000FE 910C LD R16, X + \ 00000100 FF05 SBRS R16, 5 + \ 00000102 C014 RJMP ??HaltNow_1 + 318 PWM_Stop(); + \ 00000104 .... RCALL PWM_Stop + 319 BattControl[BattActive].Enabled = FALSE; + \ 00000106 9100.... LDS R16, BattActive + \ 0000010A E010 LDI R17, 0 + \ 0000010C .... LDI R20, LOW(BattControl) + \ 0000010E .... LDI R21, (BattControl) >> 8 + \ 00000110 0F40 ADD R20, R16 + \ 00000112 1F51 ADC R21, R17 + \ 00000114 .... RCALL __eeget8_16 + \ 00000116 7F0E ANDI R16, 0xFE + \ 00000118 .... RCALL __eeput8_16 + 320 BattData.Exhausted = TRUE; + \ 0000011A 01F2 MOVW R31:R30, R5:R4 + \ 0000011C 8100 LD R16, Z + \ 0000011E 6008 ORI R16, 0x08 + \ 00000120 8300 ST Z, R16 + 321 SetErrorFlag(ERR_BATTERY_EXHAUSTED); + \ 00000122 E100 LDI R16, 16 + \ 00000124 .... RCALL SetErrorFlag + 322 ChargeParameters.NextState = ST_ERROR; + \ 00000126 E50A LDI R16, 90 + \ 00000128 01FD MOVW R31:R30, R27:R26 + \ 0000012A 8B05 STD Z+21, R16 + 323 } + 324 } + 325 break; + 326 + 327 + 328 default: // Shouldn't end up here, but is needed for MISRA compliance. + 329 break; + 330 } + 331 } + 332 } + \ ??HaltNow_1: + \ 0000012C 0C66 LSL R6 + \ 0000012E F009 BREQ $+2+2 + \ 00000130 CF7D RJMP ??HaltNow_0 + 333 + 334 // Standard checks: + 335 + 336 // Battery too cold or hot? + 337 if ((BattData.Temperature <= HaltParameters.TemperatureMin) || + 338 (BattData.Temperature >= HaltParameters.TemperatureMax)) { + \ 00000132 .... LDI R30, LOW(BattData) + \ 00000134 .... LDI R31, (BattData) >> 8 + \ 00000136 8102 LDD R16, Z+2 + \ 00000138 01FD MOVW R31:R30, R27:R26 + \ 0000013A 8521 LDD R18, Z+9 + \ 0000013C 8532 LDD R19, Z+10 + \ 0000013E 2F10 MOV R17, R16 + \ 00000140 0F11 LSL R17 + \ 00000142 0B11 SBC R17, R17 + \ 00000144 1720 CP R18, R16 + \ 00000146 0731 CPC R19, R17 + \ 00000148 F444 BRGE ??HaltNow_12 + \ 0000014A 2F10 MOV R17, R16 + \ 0000014C 0F11 LSL R17 + \ 0000014E 0B11 SBC R17, R17 + \ 00000150 8127 LDD R18, Z+7 + \ 00000152 8530 LDD R19, Z+8 + \ 00000154 1702 CP R16, R18 + \ 00000156 0713 CPC R17, R19 + \ 00000158 F040 BRCS ??HaltNow_13 + 339 + 340 PWM_Stop(); + \ ??HaltNow_12: + \ 0000015A .... RCALL PWM_Stop + 341 SetErrorFlag(ERR_BATTERY_TEMPERATURE); + \ 0000015C E008 LDI R16, 8 + \ 0000015E .... RCALL SetErrorFlag + 342 ChargeParameters.NextState = ST_ERROR; + \ 00000160 E50A LDI R16, 90 + \ 00000162 01FD MOVW R31:R30, R27:R26 + \ 00000164 8B05 STD Z+21, R16 + 343 halt = TRUE; + \ 00000166 2477 CLR R7 + \ 00000168 9473 INC R7 + 344 } + 345 + 346 // Battery not OK? + 347 if (!BatteryCheck()) { + \ ??HaltNow_13: + \ 0000016A .... RCALL BatteryCheck + \ 0000016C 2300 TST R16 + \ 0000016E F431 BRNE ??HaltNow_14 + 348 PWM_Stop(); + \ 00000170 .... RCALL PWM_Stop + 349 ChargeParameters.NextState = ST_INIT; + \ 00000172 E00A LDI R16, 10 + \ 00000174 01FD MOVW R31:R30, R27:R26 + \ 00000176 8B05 STD Z+21, R16 + 350 halt = TRUE; + \ 00000178 2477 CLR R7 + \ 0000017A 9473 INC R7 + 351 } + 352 + 353 // Is mains voltage OK? + 354 if (!ADCS.Mains) { + \ ??HaltNow_14: + \ 0000017C 9100.... LDS R16, ADCS + \ 00000180 FD06 SBRC R16, 6 + \ 00000182 C006 RJMP ??HaltNow_15 + 355 PWM_Stop(); + \ 00000184 .... RCALL PWM_Stop + 356 ChargeParameters.NextState = ST_SLEEP; + \ 00000186 E208 LDI R16, 40 + \ 00000188 01FD MOVW R31:R30, R27:R26 + \ 0000018A 8B05 STD Z+21, R16 + 357 halt = TRUE; + \ 0000018C 2477 CLR R7 + \ 0000018E 9473 INC R7 + 358 } + 359 + 360 return(halt); + \ ??HaltNow_15: + \ 00000190 2D07 MOV R16, R7 + \ 00000192 9189 LD R24, Y+ + \ 00000194 9199 LD R25, Y+ + \ 00000196 91A9 LD R26, Y+ + \ 00000198 91B9 LD R27, Y+ + \ 0000019A 9049 LD R4, Y+ + \ 0000019C 9059 LD R5, Y+ + \ 0000019E 9069 LD R6, Y+ + \ 000001A0 9079 LD R7, Y+ + \ 000001A2 9089 LD R8, Y+ + \ 000001A4 9099 LD R9, Y+ + \ 000001A6 9508 RET + 361 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + ConstantCurrent 6 4 + -> ADC_Wait 6 2 + -> Time_Stop 6 2 + -> Time_Start 6 2 + -> PWM_IncrementDutyCycle 6 2 + -> SetErrorFlag 6 2 + -> PWM_DecrementDutyCycle 6 2 + -> HaltNow 6 2 + ConstantVoltage 4 4 + -> ADC_Wait 4 2 + -> Time_Stop 4 2 + -> Time_Start 4 2 + -> PWM_IncrementDutyCycle 4 2 + -> SetErrorFlag 4 2 + -> PWM_DecrementDutyCycle 4 2 + -> HaltNow 4 2 + HaltNow 10 4 + -> ADC_Wait 10 2 + -> Time_Set 10 2 + -> Time_Left 10 2 + -> Time_Left 10 2 + -> PWM_Stop 10 2 + -> SetErrorFlag 10 2 + -> PWM_Stop 10 2 + -> SetErrorFlag 10 2 + -> BatteryCheck 10 2 + -> PWM_Stop 10 2 + -> PWM_Stop 10 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_OCR1B 1 + HaltParameters 22 + ConstantCurrent 152 + ConstantVoltage 140 + HaltNow 424 + Others 6 + + + 1 byte in segment ABSOLUTE + 716 bytes in segment CODE + 6 bytes in segment INITTAB + 22 bytes in segment NEAR_Z + + 716 bytes of CODE memory (+ 6 bytes shared) + 22 bytes of DATA memory (+ 1 byte shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/chargefunc.s90 b/BaseTinyFirmware/IAR/Release/List/chargefunc.s90 new file mode 100644 index 0000000..3628818 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/chargefunc.s90 @@ -0,0 +1,886 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\chargefunc.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\chargefunc.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\c / +// hargefunc.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME chargefunc + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?Register_R4_is_cg_reg + EXTERN ?Register_R5_is_cg_reg + EXTERN ?Register_R6_is_cg_reg + EXTERN ?Register_R7_is_cg_reg + EXTERN ?Register_R8_is_cg_reg + EXTERN ?Register_R9_is_cg_reg + EXTERN ?S_MUL_L02 + EXTERN ?need_segment_init + EXTERN __eeget8_16 + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBLIC ChargeParameters + PUBLIC ConstantCurrent + PUBLIC ConstantVoltage + PUBLIC HaltNow + PUBLIC HaltParameters + PUBWEAK _A_OCR1B + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN ADC_Wait + EXTERN Time_Stop + EXTERN Time_Start + EXTERN PWM_IncrementDutyCycle + EXTERN SetErrorFlag + EXTERN PWM_DecrementDutyCycle + EXTERN Time_Set + EXTERN Time_Left + EXTERN PWM_Stop + EXTERN BatteryCheck + EXTERN ADCS + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + +// C:\home\kevin\pub\src\bc100\IAR\chargefunc.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Charge functions +// 6 * +// 7 * Contains the functions for charging with constant current and voltage, +// 8 * and for deciding when to halt. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 * +// 14 * \par Documentation +// 15 * For comprehensive code documentation, supported compilers, compiler +// 16 * settings and supported devices see readme.html +// 17 * +// 18 * \author +// 19 * Atmel Corporation: http://www.atmel.com \n +// 20 * Support email: avr@atmel.com +// 21 * +// 22 * +// 23 * $Name$ +// 24 * $Revision: 2299 $ +// 25 * $RCSfile$ +// 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $ +// 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 28 ******************************************************************************/ +// 29 +// 30 #include + + ASEGN ABSOLUTE:DATA:NOROOT,04cH +// volatile __io _A_OCR1B +_A_OCR1B: + DS 1 +// 31 +// 32 #include "enums.h" +// 33 #include "structs.h" +// 34 +// 35 #include "ADC.h" +// 36 #include "battery.h" +// 37 #include "chargefunc.h" +// 38 #include "main.h" +// 39 #include "menu.h" +// 40 #include "PWM.h" +// 41 #include "statefunc.h" +// 42 #include "time.h" +// 43 +// 44 #ifdef NIMH +// 45 #include "NIMHspecs.h" +// 46 #endif // NIMH +// 47 +// 48 #ifdef LIION +// 49 #include "LIIONspecs.h" +// 50 #endif // LIION +// 51 +// 52 +// 53 //****************************************************************************** +// 54 // Variables +// 55 //****************************************************************************** +// 56 //! Struct that holds parameters for ConstantCurrent() and ConstantVoltage(). + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 57 ChargeParameters_t ChargeParameters; +// 58 +// 59 //! Struct that holds parameters for HaltNow(). +// 60 HaltParameters_t HaltParameters; +HaltParameters: + DS 17 +ChargeParameters: + DS 5 +// 61 +// 62 +// 63 //****************************************************************************** +// 64 // Functions +// 65 //****************************************************************************** +// 66 /*! \brief Charges battery with a constant current. +// 67 * +// 68 * This function applies a constant current (set in ChargeParameters.Current) +// 69 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and +// 70 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n +// 71 * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n +// 72 * If the Master inhibits charging, timers are stopped and PWM output dropped. +// 73 * Once the battery is no longer flagged for charge inhibit, timers are +// 74 * started again and charging resumed. +// 75 * +// 76 * \retval ChargeParameters.NextState Next state once this stage is done. +// 77 * If no errors occured, this will be whatever was set in Charge(). Otherwise, +// 78 * HaltNow() will have set a new next state. +// 79 */ + + RSEG CODE:CODE:NOROOT(1) +// 80 unsigned char ConstantCurrent(void) +ConstantCurrent: +// 81 { + ST -Y, R5 + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg +// 82 unsigned char error = FALSE, + CLR R5 +// 83 wasStopped = FALSE; + CLR R4 +// 84 +// 85 do { +// 86 // Wait for ADC conversions to complete. +// 87 ADC_Wait(); +??ConstantCurrent_0: + RCALL ADC_Wait +// 88 +// 89 // If Master has flagged for a charge inhibit, pause charging. +// 90 // (This is to prevent damage during prolonged serial communication.) +// 91 if (BattControl[BattActive].ChargeInhibit) { + LDS R16, BattActive + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + ANDI R16, 0x04 + BREQ ??ConstantCurrent_1 +// 92 wasStopped = TRUE; + CLR R4 + INC R4 +// 93 Time_Stop(); + RCALL Time_Stop +// 94 OCR1B = 0; + LDI R16, 0 + OUT 0x2C, R16 + RJMP ??ConstantCurrent_2 +// 95 } else { +// 96 // Continue charging! +// 97 if (wasStopped) { +??ConstantCurrent_1: + TST R4 + BREQ ??ConstantCurrent_3 +// 98 wasStopped = FALSE; + CLR R4 +// 99 +// 100 // Timer variables are not reset by this. +// 101 Time_Start(); + RCALL Time_Start +// 102 } +// 103 +// 104 // Adjust the charge current to within ChargeParameters.Current +// 105 // +/- BAT_CURRENT_HYST. +// 106 if ((ADCS.avgIBAT < 0) || +// 107 (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { +??ConstantCurrent_3: + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R16, Z+22 + LDD R17, Z+23 + TST R17 + BRMI ??ConstantCurrent_4 + LDI R26, LOW((HaltParameters + 19)) + LDI R27, HIGH((HaltParameters + 19)) + LD R30, X+ + LD R31, X + MOVW R25:R24, R31:R30 + SBIW R25:R24, 3 + CP R16, R24 + CPC R17, R25 + BRCC ??ConstantCurrent_5 +// 108 +// 109 if(!PWM_IncrementDutyCycle()) { +??ConstantCurrent_4: + RCALL PWM_IncrementDutyCycle + TST R16 + BRNE ??ConstantCurrent_2 +// 110 #ifdef ABORT_IF_PWM_MAX +// 111 // If the duty cycle cannot be incremented, flag error and +// 112 // go to error state. +// 113 SetErrorFlag(ERR_PWM_CONTROL); +??ConstantCurrent_6: + LDI R16, 4 + RCALL SetErrorFlag +// 114 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + STS (HaltParameters + 21), R16 +// 115 error = TRUE; + CLR R5 + INC R5 + RJMP ??ConstantCurrent_2 +// 116 #endif +// 117 } +// 118 } else if ((ADCS.avgIBAT >= 0) && +??ConstantCurrent_5: + ADIW R31:R30, 3 + CP R30, R16 + CPC R31, R17 + BRCC ??ConstantCurrent_2 +// 119 (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { +// 120 +// 121 if(!PWM_DecrementDutyCycle()) { + RCALL PWM_DecrementDutyCycle + TST R16 + BREQ ??ConstantCurrent_6 +// 122 #ifdef ABORT_IF_PWM_MIN +// 123 // If the duty cycle cannot be decremented, flag error and +// 124 // go to error state. +// 125 SetErrorFlag(ERR_PWM_CONTROL); +// 126 ChargeParameters.NextState = ST_ERROR; +// 127 error = TRUE; +// 128 #endif +// 129 } +// 130 } +// 131 } +// 132 } while ((!HaltNow()) && (!error)); +??ConstantCurrent_2: + RCALL HaltNow + TST R16 + BRNE ??ConstantCurrent_7 + TST R5 + BREQ ??ConstantCurrent_0 +// 133 +// 134 // Return the next state to Charge(). If an error has occured, this will +// 135 // point to some other state than the next state of charging. +// 136 return(ChargeParameters.NextState); +??ConstantCurrent_7: + LDS R16, (HaltParameters + 21) + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + LD R4, Y+ + LD R5, Y+ + RET + REQUIRE _A_OCR1B +// 137 } +// 138 +// 139 +// 140 /*! \brief Charges battery with a constant voltage +// 141 * +// 142 * This function applies a constant voltage (set in ChargeParameters.Voltage) +// 143 * to the battery until HaltNow() returns TRUE, or a PWM error occurs and +// 144 * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n +// 145 * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n +// 146 * If the Master inhibits charging, timers are stopped and PWM output dropped. +// 147 * Once the battery is no longer flagged for charge inhibit, timers are +// 148 * started again and charging resumed. +// 149 * +// 150 * \retval ChargeParameters.NextState Next state once this stage is done. +// 151 * If no errors occured, this will be whatever was set in Charge(). Otherwise, +// 152 * HaltNow() will have set a new next state. +// 153 */ + + RSEG CODE:CODE:NOROOT(1) +// 154 unsigned char ConstantVoltage(void) +ConstantVoltage: +// 155 { + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 +// 156 unsigned char error = FALSE, + LDI R25, 0 +// 157 wasStopped = FALSE; + LDI R24, 0 +// 158 +// 159 do{ +// 160 +// 161 // Wait for ADC conversions to complete. +// 162 ADC_Wait(); +??ConstantVoltage_0: + RCALL ADC_Wait +// 163 +// 164 // If Master has flagged for a charge inhibit, pause charging. +// 165 // (This is to prevent damage during prolonged serial communication.) +// 166 if (BattControl[BattActive].ChargeInhibit) { + LDS R16, BattActive + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + ANDI R16, 0x04 + BREQ ??ConstantVoltage_1 +// 167 wasStopped = TRUE; + LDI R24, 1 +// 168 Time_Stop(); + RCALL Time_Stop +// 169 OCR1B = 0; + LDI R16, 0 + OUT 0x2C, R16 + RJMP ??ConstantVoltage_2 +// 170 } +// 171 +// 172 else { +// 173 // Continue charging! +// 174 if (wasStopped) { +??ConstantVoltage_1: + TST R24 + BREQ ??ConstantVoltage_3 +// 175 wasStopped = FALSE; + LDI R24, 0 +// 176 +// 177 // Timer variables aren't reset by this. +// 178 Time_Start(); + RCALL Time_Start +// 179 } +// 180 +// 181 // Adjust the charge voltage to within ChargeParameters.Voltage +// 182 // +/- BAT_VOLTAGE_HYST. +// 183 if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { +??ConstantVoltage_3: + LDI R26, LOW(HaltParameters) + LDI R27, (HaltParameters) >> 8 + MOVW R31:R30, R27:R26 + LDD R16, Z+17 + LDD R17, Z+18 + LDI R30, LOW(ADCS) + LDI R31, (ADCS) >> 8 + LDD R18, Z+10 + LDD R19, Z+11 + MOVW R31:R30, R17:R16 + SBIW R31:R30, 10 + CP R18, R30 + CPC R19, R31 + BRCC ??ConstantVoltage_4 +// 184 +// 185 if(!PWM_IncrementDutyCycle()) { + RCALL PWM_IncrementDutyCycle + TST R16 + BRNE ??ConstantVoltage_2 +// 186 #ifdef ABORT_IF_PWM_MAX +// 187 // Flag PWM control error and go to error-state if the duty +// 188 // cycle cannot be incremented. +// 189 SetErrorFlag(ERR_PWM_CONTROL); +??ConstantVoltage_5: + LDI R16, 4 + RCALL SetErrorFlag +// 190 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + MOVW R31:R30, R27:R26 + STD Z+21, R16 +// 191 error = TRUE; + LDI R25, 1 + RJMP ??ConstantVoltage_2 +// 192 #endif +// 193 } +// 194 } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { +??ConstantVoltage_4: + SUBI R16, 246 + SBCI R17, 255 + CP R16, R18 + CPC R17, R19 + BRCC ??ConstantVoltage_2 +// 195 +// 196 if(!PWM_DecrementDutyCycle()) { + RCALL PWM_DecrementDutyCycle + TST R16 + BREQ ??ConstantVoltage_5 +// 197 #ifdef ABORT_IF_PWM_MIN +// 198 // Flag PWM control error and go to error-state if duty +// 199 // cycle cannot be decremented. +// 200 SetErrorFlag(ERR_PWM_CONTROL); +// 201 ChargeParameters.NextState = ST_ERROR; +// 202 error = TRUE; +// 203 #endif +// 204 } +// 205 } +// 206 } +// 207 +// 208 } while ((!HaltNow()) && (!error)); +??ConstantVoltage_2: + RCALL HaltNow + TST R16 + BRNE ??ConstantVoltage_6 + TST R25 + BREQ ??ConstantVoltage_0 +// 209 +// 210 // Return the next state to Charge(). If an error has occured, this will +// 211 // point to some other state than the next state of charging. +// 212 return(ChargeParameters.NextState); +??ConstantVoltage_6: + LDS R16, (HaltParameters + 21) + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + RET + REQUIRE _A_OCR1B +// 213 } +// 214 +// 215 +// 216 /*! \brief Determines when to halt charging. +// 217 * +// 218 * This function evaluates parameters depending on what has been flagged in +// 219 * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should +// 220 * halt or not.\n +// 221 * In addition, error flagging on timeout (battery exhaustion) can be set.\n +// 222 * +// 223 * The function also checks if the battery temperature is within limits, +// 224 * if mains is OK, and if BatteryCheck() returns TRUE. +// 225 * If an error is detected, the associated errorflag is set and +// 226 * ChargeParameters.NextState is changed to an appropriate state. +// 227 * +// 228 * \retval TRUE Halt now. +// 229 * \retval FALSE Don't halt now. +// 230 * +// 231 * \note See chargefunc.h for definitions of halt flags. +// 232 * \note It is generally a bad idea not to halt on a timeout. +// 233 * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be +// 234 * reset in Charge() before calling a charging-function. +// 235 * +// 236 * \todo "Priorities" of standard error checks OK? +// 237 */ + + RSEG CODE:CODE:NOROOT(1) +// 238 unsigned char HaltNow(void) +HaltNow: +// 239 { + ST -Y, R9 + ST -Y, R8 + ST -Y, R7 + ST -Y, R6 + ST -Y, R5 + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + REQUIRE ?Register_R7_is_cg_reg + REQUIRE ?Register_R8_is_cg_reg + REQUIRE ?Register_R9_is_cg_reg +// 240 unsigned char i, halt = FALSE; + CLR R7 +// 241 +// 242 // Wait for a full ADC-cycle to finish. +// 243 ADC_Wait(); + RCALL ADC_Wait +// 244 +// 245 // Evaluate ADC readings according to HaltFlags. Flag errors if selected. +// 246 // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR. +// 247 // (Gets overridden if either mains is failing, or the battery changes.) +// 248 for (i = 0x01; i != 0; i <<= 1) { + CLR R6 + INC R6 + LDI R24, LOW(ADCS) + LDI R25, (ADCS) >> 8 + LDI R16, LOW(BattData) + MOV R4, R16 + LDI R16, (BattData) >> 8 + MOV R5, R16 + LDI R26, LOW(HaltParameters) + LDI R27, (HaltParameters) >> 8 +// 249 if (HaltParameters.HaltFlags & i) { +??HaltNow_0: + LD R16, X + AND R16, R6 + BRNE $+2+2 + RJMP ??HaltNow_1 +// 250 switch (i) { + MOV R16, R6 + DEC R16 + BREQ ??HaltNow_2 + DEC R16 + BREQ ??HaltNow_3 + SUBI R16, 2 + BREQ ??HaltNow_4 + SUBI R16, 4 + BREQ ??HaltNow_5 + SUBI R16, 8 + BRNE $+2+2 + RJMP ??HaltNow_6 + RJMP ??HaltNow_1 +// 251 // Is VBAT less than the recorded maximum? +// 252 case HALT_VOLTAGE_DROP: +// 253 +// 254 // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. +// 255 if (ADCS.VBAT > HaltParameters.VBATMax) { +??HaltNow_2: + MOVW R31:R30, R27:R26 + LDD R16, Z+13 + LDD R17, Z+14 + MOVW R31:R30, R25:R24 + LDD R18, Z+10 + LDD R19, Z+11 + CP R16, R18 + CPC R17, R19 + BRCC ??HaltNow_7 +// 256 HaltParameters.VBATMax = ADCS.VBAT; + MOVW R31:R30, R27:R26 + STD Z+13, R18 + STD Z+14, R19 + RJMP ??HaltNow_1 +// 257 } else if((HaltParameters.VBATMax - ADCS.VBAT) >= +// 258 HaltParameters.VoltageDrop) { +??HaltNow_7: + SUB R16, R18 + SBC R17, R19 + MOVW R31:R30, R27:R26 + LDD R18, Z+1 + LDD R19, Z+2 + CP R16, R18 + CPC R17, R19 + BRCC $+2+2 + RJMP ??HaltNow_1 +// 259 halt = TRUE; +??HaltNow_8: + CLR R7 + INC R7 + RJMP ??HaltNow_1 +// 260 } +// 261 break; +// 262 +// 263 +// 264 // Has VBAT reached the maximum limit? +// 265 case HALT_VOLTAGE_MAX: +// 266 +// 267 if (ADCS.VBAT >= HaltParameters.VoltageMax) { +??HaltNow_3: + MOVW R31:R30, R25:R24 + LDD R16, Z+10 + LDD R17, Z+11 + MOVW R31:R30, R27:R26 + LDD R18, Z+3 + LDD R19, Z+4 +??HaltNow_9: + CP R16, R18 + CPC R17, R19 + BRCC $+2+2 + RJMP ??HaltNow_1 + RJMP ??HaltNow_8 +// 268 halt = TRUE; +// 269 } +// 270 break; +// 271 +// 272 +// 273 // Has IBAT reached the minimum limit? +// 274 case HALT_CURRENT_MIN: +// 275 +// 276 if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { +??HaltNow_4: + MOVW R31:R30, R27:R26 + LDD R16, Z+5 + LDD R17, Z+6 + MOVW R31:R30, R25:R24 + LDD R18, Z+22 + LDD R19, Z+23 + RJMP ??HaltNow_9 +// 277 halt = TRUE; +// 278 } +// 279 break; +// 280 +// 281 +// 282 // Is the temperature rising too fast? +// 283 case HALT_TEMPERATURE_RISE: +// 284 +// 285 // If rawNTC has increased, the temperature has dropped. +// 286 // We can store this value for now, and start the timer. +// 287 // Otherwise, check if NTC has changed too fast. +// 288 if (ADCS.rawNTC > HaltParameters.LastNTC) { +??HaltNow_5: + MOVW R31:R30, R25:R24 + LDD R16, Z+4 + LDD R17, Z+5 + MOVW R31:R30, R27:R26 + LDD R8, Z+15 + LDD R9, Z+16 + CP R8, R16 + CPC R9, R17 + BRCC ??HaltNow_10 +// 289 HaltParameters.LastNTC = ADCS.rawNTC; +??HaltNow_11: + MOVW R31:R30, R25:R24 + LDD R16, Z+4 + LDD R17, Z+5 + MOVW R31:R30, R27:R26 + STD Z+15, R16 + STD Z+16, R17 +// 290 Time_Set(TIMER_TEMP,0,30,0); + LDI R20, 0 + LDI R17, 30 + LDI R18, 0 + LDI R19, 0 + LDI R16, 3 + RCALL Time_Set + RJMP ??HaltNow_1 +// 291 +// 292 // Is the increase in temperature greater than the set threshold? +// 293 } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= +// 294 (BattData.ADCSteps * HaltParameters.TemperatureRise)) { +??HaltNow_10: + SUB R8, R16 + SBC R9, R17 + MOVW R31:R30, R5:R4 + LDD R20, Z+3 + LDI R21, 0 + MOVW R31:R30, R27:R26 + LDD R16, Z+11 + LDD R17, Z+12 + RCALL ?S_MUL_L02 + CP R8, R0 + CPC R9, R1 + BRCS ??HaltNow_1 +// 295 +// 296 // If this happened within a timeframe of 30 seconds, the +// 297 // temperature is rising faster than we want. +// 298 // If not, update LastNTC and reset timer. +// 299 if (Time_Left(TIMER_TEMP)) { + LDI R16, 3 + RCALL Time_Left + TST R16 + BRNE ??HaltNow_8 + RJMP ??HaltNow_11 +// 300 halt = TRUE; +// 301 } else { +// 302 HaltParameters.LastNTC = ADCS.rawNTC; +// 303 Time_Set(TIMER_TEMP,0,30,0); +// 304 } +// 305 } +// 306 break; +// 307 +// 308 +// 309 // Is there any time left? +// 310 case HALT_TIME: +// 311 +// 312 if (!Time_Left(TIMER_CHG)) { +??HaltNow_6: + LDI R16, 1 + RCALL Time_Left + TST R16 + BRNE ??HaltNow_1 +// 313 halt = TRUE; + CLR R7 + INC R7 +// 314 +// 315 // If exhaustion flagging is selected, stop the PWM, disable the +// 316 // battery and flag it as exhausted. Make ST_ERROR next state. +// 317 if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { + LD R16, X + SBRS R16, 5 + RJMP ??HaltNow_1 +// 318 PWM_Stop(); + RCALL PWM_Stop +// 319 BattControl[BattActive].Enabled = FALSE; + LDS R16, BattActive + LDI R17, 0 + LDI R20, LOW(BattControl) + LDI R21, (BattControl) >> 8 + ADD R20, R16 + ADC R21, R17 + RCALL __eeget8_16 + ANDI R16, 0xFE + RCALL __eeput8_16 +// 320 BattData.Exhausted = TRUE; + MOVW R31:R30, R5:R4 + LD R16, Z + ORI R16, 0x08 + ST Z, R16 +// 321 SetErrorFlag(ERR_BATTERY_EXHAUSTED); + LDI R16, 16 + RCALL SetErrorFlag +// 322 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + MOVW R31:R30, R27:R26 + STD Z+21, R16 +// 323 } +// 324 } +// 325 break; +// 326 +// 327 +// 328 default: // Shouldn't end up here, but is needed for MISRA compliance. +// 329 break; +// 330 } +// 331 } +// 332 } +??HaltNow_1: + LSL R6 + BREQ $+2+2 + RJMP ??HaltNow_0 +// 333 +// 334 // Standard checks: +// 335 +// 336 // Battery too cold or hot? +// 337 if ((BattData.Temperature <= HaltParameters.TemperatureMin) || +// 338 (BattData.Temperature >= HaltParameters.TemperatureMax)) { + LDI R30, LOW(BattData) + LDI R31, (BattData) >> 8 + LDD R16, Z+2 + MOVW R31:R30, R27:R26 + LDD R18, Z+9 + LDD R19, Z+10 + MOV R17, R16 + LSL R17 + SBC R17, R17 + CP R18, R16 + CPC R19, R17 + BRGE ??HaltNow_12 + MOV R17, R16 + LSL R17 + SBC R17, R17 + LDD R18, Z+7 + LDD R19, Z+8 + CP R16, R18 + CPC R17, R19 + BRCS ??HaltNow_13 +// 339 +// 340 PWM_Stop(); +??HaltNow_12: + RCALL PWM_Stop +// 341 SetErrorFlag(ERR_BATTERY_TEMPERATURE); + LDI R16, 8 + RCALL SetErrorFlag +// 342 ChargeParameters.NextState = ST_ERROR; + LDI R16, 90 + MOVW R31:R30, R27:R26 + STD Z+21, R16 +// 343 halt = TRUE; + CLR R7 + INC R7 +// 344 } +// 345 +// 346 // Battery not OK? +// 347 if (!BatteryCheck()) { +??HaltNow_13: + RCALL BatteryCheck + TST R16 + BRNE ??HaltNow_14 +// 348 PWM_Stop(); + RCALL PWM_Stop +// 349 ChargeParameters.NextState = ST_INIT; + LDI R16, 10 + MOVW R31:R30, R27:R26 + STD Z+21, R16 +// 350 halt = TRUE; + CLR R7 + INC R7 +// 351 } +// 352 +// 353 // Is mains voltage OK? +// 354 if (!ADCS.Mains) { +??HaltNow_14: + LDS R16, ADCS + SBRC R16, 6 + RJMP ??HaltNow_15 +// 355 PWM_Stop(); + RCALL PWM_Stop +// 356 ChargeParameters.NextState = ST_SLEEP; + LDI R16, 40 + MOVW R31:R30, R27:R26 + STD Z+21, R16 +// 357 halt = TRUE; + CLR R7 + INC R7 +// 358 } +// 359 +// 360 return(halt); +??HaltNow_15: + MOV R16, R7 + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + LD R4, Y+ + LD R5, Y+ + LD R6, Y+ + LD R7, Y+ + LD R8, Y+ + LD R9, Y+ + RET +// 361 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 1 byte in segment ABSOLUTE +// 716 bytes in segment CODE +// 6 bytes in segment INITTAB +// 22 bytes in segment NEAR_Z +// +// 716 bytes of CODE memory (+ 6 bytes shared) +// 22 bytes of DATA memory (+ 1 byte shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/main.lst b/BaseTinyFirmware/IAR/Release/List/main.lst new file mode 100644 index 0000000..b9151aa --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/main.lst @@ -0,0 +1,355 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:00 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\main.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\main.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\ma # +# in.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\mai # +# n.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\main.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Main program file + 6 * + 7 * Contains the main program, which is a basic state machine. + 8 * + 9 * \par Application note: + 10 * AVR458: Charging Li-Ion Batteries with BC100 \n + 11 * AVR463: Charging NiMH Batteries with BC100 + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2302 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $ + 26 * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 /*! \page License + 30 * Copyright (c) 2007, Atmel Corporation All rights reserved. + 31 * + 32 * Redistribution and use in source and binary forms, with or without + 33 * modification, are permitted provided that the following conditions are met: + 34 * + 35 * 1. Redistributions of source code must retain the above copyright notice, + 36 * this list of conditions and the following disclaimer. + 37 * + 38 * 2. Redistributions in binary form must reproduce the above copyright notice, + 39 * this list of conditions and the following disclaimer in the documentation + 40 * and/or other materials provided with the distribution. + 41 * + 42 * 3. The name of ATMEL may not be used to endorse or promote products derived + 43 * from this software without specific prior written permission. + 44 * + 45 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED + 46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + 47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + 48 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + 49 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + 50 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + 51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + 52 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + 55 */ + 56 + 57 #include + 58 #include + 59 #include + 60 + 61 #include "structs.h" + 62 + 63 #include "main.h" + 64 #include "ADC.h" + 65 #include "statefunc.h" + 66 #include "battery.h" + 67 #include "menu.h" + 68 #include "OWI.h" + 69 #include "PWM.h" + 70 #include "time.h" + 71 #include "USI.h" + 72 + 73 + 74 + 75 //****************************************************************************** + 76 // Globals + 77 //****************************************************************************** + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 78 unsigned char CurrentState; //!< \brief Global that indicates current state + \ CurrentState: + \ 00000000 DS 1 + 79 //!< + 80 //!< Updated by main(). + 81 //!< \note See menu.h for definition of states. + 82 + 83 + 84 //****************************************************************************** + 85 // Functions + 86 //****************************************************************************** + 87 /*! \brief Main program + 88 * + 89 * The main function goes into an infinite loop, keeping track of the current + 90 * state and the next one. If the next state is different from the current, it + 91 * looks up the address to the next state function, in \ref menu_state[], and + 92 * updates \ref CurrentState. The state function is then called and will + 93 * eventually return a new state, and so the loop reiterates. + 94 * + 95 * \todo The variable inp is passed to all state functions, but is not used + 96 * for anything yet. Remove? + 97 */ + + \ In segment CODE, align 2, keep-with-next + 98 int main( void ) + \ main: + 99 { + \ 00000000 939A ST -Y, R25 + \ 00000002 938A ST -Y, R24 + 100 unsigned char nextstate, inp, i; + 101 unsigned char (*pStateFunc)(unsigned char); // Function pointer. + 102 + 103 // Initialize local state variables. + 104 inp = ZERO; + 105 CurrentState = nextstate = ST_INIT; + \ 00000004 E02A LDI R18, 10 + \ 00000006 9320.... STS CurrentState, R18 + 106 pStateFunc = NULL; + \ 0000000A E080 LDI R24, 0 + \ 0000000C E090 LDI R25, 0 + 107 + 108 // Look for function associated with current state, get its address. + 109 for (i = 0; menu_state[i].state != 0; i++) { + \ 0000000E E000 LDI R16, 0 + \ 00000010 C006 RJMP ??main_0 + 110 if (menu_state[i].state == CurrentState) { + \ ??main_1: + \ 00000012 301A CPI R17, 10 + \ 00000014 F419 BRNE ??main_2 + 111 pStateFunc = menu_state[i].pFunc; + \ 00000016 9631 ADIW R31:R30, 1 + \ 00000018 9185 LPM R24, Z+ + \ 0000001A 9194 LPM R25, Z + 112 } + 113 } + \ ??main_2: + \ 0000001C 9503 INC R16 + \ ??main_0: + \ 0000001E 2F40 MOV R20, R16 + \ 00000020 E050 LDI R21, 0 + \ 00000022 01BA MOVW R23:R22, R21:R20 + \ 00000024 0F44 LSL R20 + \ 00000026 1F55 ROL R21 + \ 00000028 0F46 ADD R20, R22 + \ 0000002A 1F57 ADC R21, R23 + \ 0000002C .... LDI R30, LOW(menu_state) + \ 0000002E .... LDI R31, (menu_state) >> 8 + \ 00000030 0FE4 ADD R30, R20 + \ 00000032 1FF5 ADC R31, R21 + \ 00000034 9114 LPM R17, Z + \ 00000036 2311 TST R17 + \ 00000038 F761 BRNE ??main_1 + 114 + 115 while (TRUE) { + 116 // Run function associated with current state, get next state in return. + 117 if (pStateFunc != NULL){ + \ ??main_3: + \ 0000003A E000 LDI R16, 0 + \ 0000003C 3080 CPI R24, 0 + \ 0000003E 0790 CPC R25, R16 + \ 00000040 F019 BREQ ??main_4 + 118 nextstate = pStateFunc(inp); + \ 00000042 01FC MOVW R31:R30, R25:R24 + \ 00000044 9509 ICALL + \ 00000046 2F20 MOV R18, R16 + 119 } + 120 + 121 // Look up function for next state, if it differs from the current. + 122 if (nextstate != CurrentState) { + \ ??main_4: + \ 00000048 9100.... LDS R16, CurrentState + \ 0000004C 1720 CP R18, R16 + \ 0000004E F3A9 BREQ ??main_3 + 123 CurrentState = nextstate; + \ 00000050 9320.... STS CurrentState, R18 + 124 for ( i = 0; menu_state[i].state != 0; i++) { + \ 00000054 E000 LDI R16, 0 + \ ??main_5: + \ 00000056 2F40 MOV R20, R16 + \ 00000058 E050 LDI R21, 0 + \ 0000005A 01BA MOVW R23:R22, R21:R20 + \ 0000005C 0F44 LSL R20 + \ 0000005E 1F55 ROL R21 + \ 00000060 0F46 ADD R20, R22 + \ 00000062 1F57 ADC R21, R23 + \ 00000064 .... LDI R30, LOW(menu_state) + \ 00000066 .... LDI R31, (menu_state) >> 8 + \ 00000068 0FE4 ADD R30, R20 + \ 0000006A 1FF5 ADC R31, R21 + \ 0000006C 9114 LPM R17, Z + \ 0000006E 2311 TST R17 + \ 00000070 F321 BREQ ??main_3 + 125 if (menu_state[i].state == CurrentState) { + \ 00000072 9130.... LDS R19, CurrentState + \ 00000076 1713 CP R17, R19 + \ 00000078 F419 BRNE ??main_6 + 126 pStateFunc = menu_state[i].pFunc; + \ 0000007A 9631 ADIW R31:R30, 1 + \ 0000007C 9185 LPM R24, Z+ + \ 0000007E 9194 LPM R25, Z + 127 } + 128 } + \ ??main_6: + \ 00000080 9503 INC R16 + \ 00000082 CFE9 RJMP ??main_5 + 129 } + 130 } + 131 } + 132 + 133 + 134 /* Doxygen documentation mainpage ********************************************/ + 135 /*! \mainpage + 136 * \section intro Introduction + 137 * This documents the software for application note AVR458. This is a charger + 138 * for Li-Ion batteries, based on ATAVRBC100. + 139 * + 140 * \section compinfo Compilation Info + 141 * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC + 142 * the source have to be modified.\n + 143 * \n + 144 * To make project on IAR EWAVR:\n + 145 * Add the .c files to project (ADC.c, battery.c, main.c, menu.c, + 146 * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c, + 147 * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate + 148 * battery data if needed.\n + 149 * \n + 150 * Use device --cpu=tiny861, enable bit definitions in I/O include files, + 151 * optimization low for debug target and high for release, output format: ubrof8 + 152 * for Debug and intel_extended for Release. \n + 153 * + 154 * \section deviceinfo Device Info + 155 * This application is based on the ATtiny 861, but it is possible to migrate + 156 * the design to other AVR microcontrollers, such as pin-compatible devices + 157 * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be + 158 * used, but with reduced functionality. + 159 * + 160 * Required fuse bit settings: + 161 *
+    162           *    FUSE BIT  | SETTING
+    163           *    ----------+--------------------
+    164           *    CKDIV8    | 1 (unprogrammed)
+    165           *    CKSEL3..0 | 0010 (internal osc)
+    166           *    
+ 167 * + 168 * + 169 * \section todo To Do-list + 170 * \todo + 171 * - Finalize master-slave communication protocol + 172 * - Implement discharge mode + 173 * + 174 * \section contactinfo Contact Info + 175 * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n + 176 * For application notes visit + 177 * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n + 178 * Support mail: avr@atmel.com + 179 */ + 180 + 181 + 182 /*! \page misra MISRA C rule violations + 183 * + 184 * \par Rule 1 + 185 * "All code shall conform to ISO 9899 standard C, with no extensions + 186 * permitted." + 187 * + 188 * Extensions are necessary because ISO C has no way of specifying that a + 189 * function should be an interrupt service routine, or that we would like data + 190 * members to be stored in f.ex. EEPROM. + 191 * + 192 * + 193 * \par Rule 37 + 194 * "Bitwise operations shall not be performed on signed integer types." + 195 * + 196 * The compiler assumes all the 1's we shift around to make bitmasks are signed + 197 * integers. Specifying them all to be (unsigned int), either directly or via a + 198 * definition, would fix the rule violations, but also reduce code readability. + 199 * + 200 * + 201 * \par Rule 45 + 202 * "Type casting from any type to or from pointers shall not be used." + 203 * + 204 * Assigning macro NULL, defined in stdlib.h, to a pointer causes this.. + 205 * + 206 * + 207 * \par Rule 96 + 208 * "In the definition of a function-like macro the whole definition, and each + 209 * instance of a parameter, shall be enclosed in parentheses." + 210 * + 211 * It is difficult to use parentheses with void function-like macros. + 212 */ + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + main 2 2 + -> Indirect call 2 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + CurrentState 1 + main 132 + Others 6 + + + 132 bytes in segment CODE + 6 bytes in segment INITTAB + 1 byte in segment NEAR_Z + + 132 bytes of CODE memory (+ 6 bytes shared) + 1 byte of DATA memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/main.s90 b/BaseTinyFirmware/IAR/Release/List/main.s90 new file mode 100644 index 0000000..f6a8396 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/main.s90 @@ -0,0 +1,374 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:00 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\main.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\main.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\m / +// ain.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME main + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?need_segment_init + + PUBWEAK `?` + PUBLIC CurrentState + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + PUBLIC main + + EXTERN menu_state + +// C:\home\kevin\pub\src\bc100\IAR\main.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Main program file +// 6 * +// 7 * Contains the main program, which is a basic state machine. +// 8 * +// 9 * \par Application note: +// 10 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 11 * AVR463: Charging NiMH Batteries with BC100 +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2302 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $ +// 26 * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 /*! \page License +// 30 * Copyright (c) 2007, Atmel Corporation All rights reserved. +// 31 * +// 32 * Redistribution and use in source and binary forms, with or without +// 33 * modification, are permitted provided that the following conditions are met: +// 34 * +// 35 * 1. Redistributions of source code must retain the above copyright notice, +// 36 * this list of conditions and the following disclaimer. +// 37 * +// 38 * 2. Redistributions in binary form must reproduce the above copyright notice, +// 39 * this list of conditions and the following disclaimer in the documentation +// 40 * and/or other materials provided with the distribution. +// 41 * +// 42 * 3. The name of ATMEL may not be used to endorse or promote products derived +// 43 * from this software without specific prior written permission. +// 44 * +// 45 * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED +// 46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// 47 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND +// 48 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, +// 49 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// 50 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// 51 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// 52 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// 53 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// 54 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 55 */ +// 56 +// 57 #include +// 58 #include +// 59 #include +// 60 +// 61 #include "structs.h" +// 62 +// 63 #include "main.h" +// 64 #include "ADC.h" +// 65 #include "statefunc.h" +// 66 #include "battery.h" +// 67 #include "menu.h" +// 68 #include "OWI.h" +// 69 #include "PWM.h" +// 70 #include "time.h" +// 71 #include "USI.h" +// 72 +// 73 +// 74 +// 75 //****************************************************************************** +// 76 // Globals +// 77 //****************************************************************************** + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 78 unsigned char CurrentState; //!< \brief Global that indicates current state +CurrentState: + DS 1 +// 79 //!< +// 80 //!< Updated by main(). +// 81 //!< \note See menu.h for definition of states. +// 82 +// 83 +// 84 //****************************************************************************** +// 85 // Functions +// 86 //****************************************************************************** +// 87 /*! \brief Main program +// 88 * +// 89 * The main function goes into an infinite loop, keeping track of the current +// 90 * state and the next one. If the next state is different from the current, it +// 91 * looks up the address to the next state function, in \ref menu_state[], and +// 92 * updates \ref CurrentState. The state function is then called and will +// 93 * eventually return a new state, and so the loop reiterates. +// 94 * +// 95 * \todo The variable inp is passed to all state functions, but is not used +// 96 * for anything yet. Remove? +// 97 */ + + RSEG CODE:CODE:NOROOT(1) +// 98 int main( void ) +main: +// 99 { + ST -Y, R25 + ST -Y, R24 +// 100 unsigned char nextstate, inp, i; +// 101 unsigned char (*pStateFunc)(unsigned char); // Function pointer. +// 102 +// 103 // Initialize local state variables. +// 104 inp = ZERO; +// 105 CurrentState = nextstate = ST_INIT; + LDI R18, 10 + STS CurrentState, R18 +// 106 pStateFunc = NULL; + LDI R24, 0 + LDI R25, 0 +// 107 +// 108 // Look for function associated with current state, get its address. +// 109 for (i = 0; menu_state[i].state != 0; i++) { + LDI R16, 0 + RJMP ??main_0 +// 110 if (menu_state[i].state == CurrentState) { +??main_1: + CPI R17, 10 + BRNE ??main_2 +// 111 pStateFunc = menu_state[i].pFunc; + ADIW R31:R30, 1 + LPM R24, Z+ + LPM R25, Z +// 112 } +// 113 } +??main_2: + INC R16 +??main_0: + MOV R20, R16 + LDI R21, 0 + MOVW R23:R22, R21:R20 + LSL R20 + ROL R21 + ADD R20, R22 + ADC R21, R23 + LDI R30, LOW(menu_state) + LDI R31, (menu_state) >> 8 + ADD R30, R20 + ADC R31, R21 + LPM R17, Z + TST R17 + BRNE ??main_1 +// 114 +// 115 while (TRUE) { +// 116 // Run function associated with current state, get next state in return. +// 117 if (pStateFunc != NULL){ +??main_3: + LDI R16, 0 + CPI R24, 0 + CPC R25, R16 + BREQ ??main_4 +// 118 nextstate = pStateFunc(inp); + MOVW R31:R30, R25:R24 + ICALL + MOV R18, R16 +// 119 } +// 120 +// 121 // Look up function for next state, if it differs from the current. +// 122 if (nextstate != CurrentState) { +??main_4: + LDS R16, CurrentState + CP R18, R16 + BREQ ??main_3 +// 123 CurrentState = nextstate; + STS CurrentState, R18 +// 124 for ( i = 0; menu_state[i].state != 0; i++) { + LDI R16, 0 +??main_5: + MOV R20, R16 + LDI R21, 0 + MOVW R23:R22, R21:R20 + LSL R20 + ROL R21 + ADD R20, R22 + ADC R21, R23 + LDI R30, LOW(menu_state) + LDI R31, (menu_state) >> 8 + ADD R30, R20 + ADC R31, R21 + LPM R17, Z + TST R17 + BREQ ??main_3 +// 125 if (menu_state[i].state == CurrentState) { + LDS R19, CurrentState + CP R17, R19 + BRNE ??main_6 +// 126 pStateFunc = menu_state[i].pFunc; + ADIW R31:R30, 1 + LPM R24, Z+ + LPM R25, Z +// 127 } +// 128 } +??main_6: + INC R16 + RJMP ??main_5 +// 129 } +// 130 } +// 131 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// 132 +// 133 +// 134 /* Doxygen documentation mainpage ********************************************/ +// 135 /*! \mainpage +// 136 * \section intro Introduction +// 137 * This documents the software for application note AVR458. This is a charger +// 138 * for Li-Ion batteries, based on ATAVRBC100. +// 139 * +// 140 * \section compinfo Compilation Info +// 141 * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC +// 142 * the source have to be modified.\n +// 143 * \n +// 144 * To make project on IAR EWAVR:\n +// 145 * Add the .c files to project (ADC.c, battery.c, main.c, menu.c, +// 146 * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c, +// 147 * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate +// 148 * battery data if needed.\n +// 149 * \n +// 150 * Use device --cpu=tiny861, enable bit definitions in I/O include files, +// 151 * optimization low for debug target and high for release, output format: ubrof8 +// 152 * for Debug and intel_extended for Release. \n +// 153 * +// 154 * \section deviceinfo Device Info +// 155 * This application is based on the ATtiny 861, but it is possible to migrate +// 156 * the design to other AVR microcontrollers, such as pin-compatible devices +// 157 * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be +// 158 * used, but with reduced functionality. +// 159 * +// 160 * Required fuse bit settings: +// 161 *
+//  162  *    FUSE BIT  | SETTING
+//  163  *    ----------+--------------------
+//  164  *    CKDIV8    | 1 (unprogrammed)
+//  165  *    CKSEL3..0 | 0010 (internal osc)
+//  166  *    
+// 167 * +// 168 * +// 169 * \section todo To Do-list +// 170 * \todo +// 171 * - Finalize master-slave communication protocol +// 172 * - Implement discharge mode +// 173 * +// 174 * \section contactinfo Contact Info +// 175 * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n +// 176 * For application notes visit +// 177 * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n +// 178 * Support mail: avr@atmel.com +// 179 */ +// 180 +// 181 +// 182 /*! \page misra MISRA C rule violations +// 183 * +// 184 * \par Rule 1 +// 185 * "All code shall conform to ISO 9899 standard C, with no extensions +// 186 * permitted." +// 187 * +// 188 * Extensions are necessary because ISO C has no way of specifying that a +// 189 * function should be an interrupt service routine, or that we would like data +// 190 * members to be stored in f.ex. EEPROM. +// 191 * +// 192 * +// 193 * \par Rule 37 +// 194 * "Bitwise operations shall not be performed on signed integer types." +// 195 * +// 196 * The compiler assumes all the 1's we shift around to make bitmasks are signed +// 197 * integers. Specifying them all to be (unsigned int), either directly or via a +// 198 * definition, would fix the rule violations, but also reduce code readability. +// 199 * +// 200 * +// 201 * \par Rule 45 +// 202 * "Type casting from any type to or from pointers shall not be used." +// 203 * +// 204 * Assigning macro NULL, defined in stdlib.h, to a pointer causes this.. +// 205 * +// 206 * +// 207 * \par Rule 96 +// 208 * "In the definition of a function-like macro the whole definition, and each +// 209 * instance of a parameter, shall be enclosed in parentheses." +// 210 * +// 211 * It is difficult to use parentheses with void function-like macros. +// 212 */ +// +// 132 bytes in segment CODE +// 6 bytes in segment INITTAB +// 1 byte in segment NEAR_Z +// +// 132 bytes of CODE memory (+ 6 bytes shared) +// 1 byte of DATA memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/menu.lst b/BaseTinyFirmware/IAR/Release/List/menu.lst new file mode 100644 index 0000000..66bc677 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/menu.lst @@ -0,0 +1,156 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:38 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\menu.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\menu.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\me # +# nu.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\men # +# u.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\menu.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * State menu definition + 6 * + 7 * Contains the definition of the state menu.\n + 8 * The state menu contains all states and adresses to associated functions. + 9 * + 10 * \par Application note: + 11 * AVR458: Charging Li-Ion Batteries with BC100 \n + 12 * AVR463: Charging NiMH Batteries with BC100 + 13 * + 14 * \par Documentation: + 15 * For comprehensive code documentation, supported compilers, compiler + 16 * settings and supported devices see readme.html + 17 * + 18 * \author + 19 * Atmel Corporation: http://www.atmel.com \n + 20 * Support email: avr@atmel.com + 21 * + 22 * + 23 * $Name$ + 24 * $Revision: 2299 $ + 25 * $RCSfile$ + 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $ + 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 28 ******************************************************************************/ + 29 + 30 #include + 31 + 32 #include "statefunc.h" + 33 #include "charge.h" + 34 #include "main.h" + 35 #include "menu.h" + 36 + 37 + 38 //****************************************************************************** + 39 // State menu (relies on the proper battery type to be defined in main.h!) + 40 //****************************************************************************** + 41 #ifdef NIMH + 42 /*! \brief The state menu + 43 * + 44 * Contains all the defined states and addresses to their associated functions. + 45 */ + + \ In segment NEAR_F, align 1, keep-with-next + 46 __flash const MENU_STATE_t menu_state[] = { + \ menu_state: + \ 00000000 0A DB 10 + \ 00000001 .... DW Initialize/2 + \ 00000003 14 DB 20 + \ 00000004 .... DW BatteryControl/2 + \ 00000006 1E DB 30 + \ 00000007 .... DW Charge/2 + \ 00000009 28 DB 40 + \ 0000000A .... DW `Sleep`/2 + \ 0000000C 32 DB 50 + \ 0000000D .... DW Charge/2 + \ 0000000F 3C DB 60 + \ 00000010 .... DW Charge/2 + \ 00000012 46 DB 70 + \ 00000013 .... DW Charge/2 + \ 00000015 50 DB 80 + \ 00000016 .... DW Discharge/2 + \ 00000018 5A DB 90 + \ 00000019 .... DW Error/2 + \ 0000001B 00 DB 0 + \ 0000001C 0000 DW 0H + 47 // State State function + 48 { ST_INIT, Initialize}, + 49 { ST_BATCON, BatteryControl}, + 50 { ST_PREQUAL, Charge}, + 51 { ST_SLEEP, Sleep}, + 52 { ST_FASTCHARGE, Charge}, + 53 { ST_LOWRATECHARGE, Charge}, + 54 { ST_ENDCHARGE, Charge}, + 55 { ST_DISCHARGE, Discharge}, + 56 { ST_ERROR, Error}, + 57 { 0, NULL}, + 58 }; + 59 #endif // NIMH + 60 + 61 #ifdef LIION + 62 /*! \brief The state menu + 63 * + 64 * Contains all the defined states and addresses to their associated functions. + 65 */ + 66 __flash const MENU_STATE_t menu_state[] = { + 67 // State State function + 68 { ST_INIT, Initialize}, + 69 { ST_BATCON, BatteryControl}, + 70 { ST_PREQUAL, Charge}, + 71 { ST_SLEEP, Sleep}, + 72 { ST_CCURRENT, Charge}, + 73 { ST_CVOLTAGE, Charge}, + 74 { ST_ENDCHARGE, Charge}, + 75 { ST_DISCHARGE, Discharge}, + 76 { ST_ERROR, Error}, + 77 { 0, NULL}, + 78 }; + 79 #endif // LIION + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + menu_state 30 + + + 30 bytes in segment NEAR_F + + 30 bytes of CODE memory + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/menu.s90 b/BaseTinyFirmware/IAR/Release/List/menu.s90 new file mode 100644 index 0000000..0bbbf82 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/menu.s90 @@ -0,0 +1,178 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:49:38 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\menu.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\menu.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\m / +// enu.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME menu + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + PUBLIC menu_state + + EXTERN BatteryControl + EXTERN Charge + EXTERN Discharge + EXTERN Error + EXTERN Initialize + EXTERN `Sleep` + +// C:\home\kevin\pub\src\bc100\IAR\menu.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * State menu definition +// 6 * +// 7 * Contains the definition of the state menu.\n +// 8 * The state menu contains all states and adresses to associated functions. +// 9 * +// 10 * \par Application note: +// 11 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 12 * AVR463: Charging NiMH Batteries with BC100 +// 13 * +// 14 * \par Documentation: +// 15 * For comprehensive code documentation, supported compilers, compiler +// 16 * settings and supported devices see readme.html +// 17 * +// 18 * \author +// 19 * Atmel Corporation: http://www.atmel.com \n +// 20 * Support email: avr@atmel.com +// 21 * +// 22 * +// 23 * $Name$ +// 24 * $Revision: 2299 $ +// 25 * $RCSfile$ +// 26 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $ +// 27 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 28 ******************************************************************************/ +// 29 +// 30 #include +// 31 +// 32 #include "statefunc.h" +// 33 #include "charge.h" +// 34 #include "main.h" +// 35 #include "menu.h" +// 36 +// 37 +// 38 //****************************************************************************** +// 39 // State menu (relies on the proper battery type to be defined in main.h!) +// 40 //****************************************************************************** +// 41 #ifdef NIMH +// 42 /*! \brief The state menu +// 43 * +// 44 * Contains all the defined states and addresses to their associated functions. +// 45 */ + + RSEG NEAR_F:CODE:NOROOT(0) +// 46 __flash const MENU_STATE_t menu_state[] = { +menu_state: + DB 10 + DW Initialize/2 + DB 20 + DW BatteryControl/2 + DB 30 + DW Charge/2 + DB 40 + DW `Sleep`/2 + DB 50 + DW Charge/2 + DB 60 + DW Charge/2 + DB 70 + DW Charge/2 + DB 80 + DW Discharge/2 + DB 90 + DW Error/2 + DB 0 + DW 0H + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + END +// 47 // State State function +// 48 { ST_INIT, Initialize}, +// 49 { ST_BATCON, BatteryControl}, +// 50 { ST_PREQUAL, Charge}, +// 51 { ST_SLEEP, Sleep}, +// 52 { ST_FASTCHARGE, Charge}, +// 53 { ST_LOWRATECHARGE, Charge}, +// 54 { ST_ENDCHARGE, Charge}, +// 55 { ST_DISCHARGE, Discharge}, +// 56 { ST_ERROR, Error}, +// 57 { 0, NULL}, +// 58 }; +// 59 #endif // NIMH +// 60 +// 61 #ifdef LIION +// 62 /*! \brief The state menu +// 63 * +// 64 * Contains all the defined states and addresses to their associated functions. +// 65 */ +// 66 __flash const MENU_STATE_t menu_state[] = { +// 67 // State State function +// 68 { ST_INIT, Initialize}, +// 69 { ST_BATCON, BatteryControl}, +// 70 { ST_PREQUAL, Charge}, +// 71 { ST_SLEEP, Sleep}, +// 72 { ST_CCURRENT, Charge}, +// 73 { ST_CVOLTAGE, Charge}, +// 74 { ST_ENDCHARGE, Charge}, +// 75 { ST_DISCHARGE, Discharge}, +// 76 { ST_ERROR, Error}, +// 77 { 0, NULL}, +// 78 }; +// 79 #endif // LIION +// +// 30 bytes in segment NEAR_F +// +// 30 bytes of CODE memory +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/statefunc.lst b/BaseTinyFirmware/IAR/Release/List/statefunc.lst new file mode 100644 index 0000000..a5c05c5 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/statefunc.lst @@ -0,0 +1,802 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\statefunc.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\statefunc.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\st # +# atefunc.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\sta # +# tefunc.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\statefunc.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * State functions + 6 * + 7 * Contains the functions related to the states defined in menu.h.\n + 8 * Also contains related functions, i.e. for checking jumpers, setting + 9 * error flags and "dozing". + 10 * + 11 * \note The state function Charge() is in a separate file since it + 12 * should easily be changed with regard to battery type. + 13 * + 14 * \par Application note: + 15 * AVR458: Charging Li-Ion Batteries with BC100 \n + 16 * AVR463: Charging NiMH Batteries with BC100 + 17 * + 18 * \par Documentation + 19 * For comprehensive code documentation, supported compilers, compiler + 20 * settings and supported devices see readme.html + 21 * + 22 * \author + 23 * Atmel Corporation: http://www.atmel.com \n + 24 * Support email: avr@atmel.com + 25 * + 26 * + 27 * $Name$ + 28 * $Revision: 2299 $ + 29 * $RCSfile$ + 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $ + 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 32 ******************************************************************************/ + 33 + 34 #include + + \ In segment ABSOLUTE, at 0x55 + \ volatile __io _A_MCUCR + \ _A_MCUCR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x54 + \ volatile __io _A_MCUSR + \ _A_MCUSR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x48 + \ volatile __io _A_CLKPR + \ _A_CLKPR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x41 + \ volatile __io _A_WDTCR + \ _A_WDTCR: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x37 + \ volatile __io _A_DDRB + \ _A_DDRB: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x26 + \ volatile __io _A_ADCSRA + \ _A_ADCSRA: + \ 00000000 DS 1 + 35 #include + 36 #include + 37 + 38 #include "structs.h" + 39 #include "enums.h" + 40 + 41 #include "ADC.h" + 42 #include "statefunc.h" + 43 #include "battery.h" + 44 #include "charge.h" + 45 #include "main.h" + 46 #include "menu.h" + 47 #include "OWI.h" + 48 #include "PWM.h" + 49 #include "time.h" + 50 #include "USI.h" + 51 + 52 + 53 //****************************************************************************** + 54 // Variables + 55 //****************************************************************************** + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 56 unsigned char ErrorFlags; //!< \brief Holds error flags. + \ ErrorFlags: + \ 00000000 DS 1 + 57 //!< \note See statefunc.h for definitions of flags. + 58 + 59 //! \brief Holds the state in which latest error flag was set. + 60 //! \note See menu.h for definitions of states. + 61 unsigned char ErrorState; + \ ErrorState: + \ 00000001 DS 1 + 62 + 63 + 64 //****************************************************************************** + 65 // Functions + 66 //****************************************************************************** + 67 /*! \brief Initialization + 68 * + 69 * - Sets the system clock prescaler to 1 (run at 8 MHz) + 70 * - Initializes the one-wire interface + 71 * - Clears on-chip EEPROM + 72 * - Sets battery enable pins as outputs, then disables batteries + 73 * - Initializes SPI according to \ref SPIMODE + 74 * - Initializes ADC + 75 * - Initializes timers + 76 * - Reads battery data from both battery inputs (via ADC) + 77 * - Disables batteries again + 78 * - Sets battery A as the current one (\ref BattActive = 0) + 79 * - Clears ErrorFlags + 80 * + 81 * \param inp Not used. + 82 * + 83 * \retval ST_BATCON Next state in the sequence. + 84 */ + + \ In segment CODE, align 2, keep-with-next + 85 unsigned char Initialize(unsigned char inp) + \ Initialize: + 86 { + \ 00000000 938A ST -Y, R24 + 87 unsigned char i, page; + 88 + 89 // Disable interrupts while setting prescaler. + 90 __disable_interrupt(); + \ 00000002 94F8 CLI + 91 + 92 CLKPR = (1< 8 MHz clock frequency. + \ 00000008 E000 LDI R16, 0 + \ 0000000A BD08 OUT 0x28, R16 + 94 + 95 // Init 1-Wire(R) interface. + 96 OWI_Init(OWIBUS); + \ 0000000C E001 LDI R16, 1 + \ 0000000E .... RCALL OWI_Init + 97 + 98 // Clear on-chip EEPROM. + 99 for (page = 0; page < 4; page++) { + \ 00000010 .... LDI R20, LOW(BattEEPROM) + \ 00000012 .... LDI R21, (BattEEPROM) >> 8 + \ 00000014 E810 LDI R17, 128 + 100 for (i = 0; i < 32; i++) { + 101 BattEEPROM[page][i] = 0; + \ ??Initialize_0: + \ 00000016 E000 LDI R16, 0 + \ 00000018 .... RCALL __eeput8_16 + 102 } + \ 0000001A 5F4F SUBI R20, 255 + \ 0000001C 4F5F SBCI R21, 255 + 103 } + \ 0000001E 951A DEC R17 + \ 00000020 F7D1 BRNE ??Initialize_0 + 104 + 105 DDRB = (1<> 8 + \ 00000016 01AC MOVW R21:R20, R25:R24 + \ 00000018 .... RCALL __eeget8_16 + \ 0000001A 7001 ANDI R16, 0x01 + \ 0000001C F479 BRNE ??BatteryControl_3 + \ 0000001E 01AC MOVW R21:R20, R25:R24 + \ 00000020 5F4F SUBI R20, 255 + \ 00000022 4F5F SBCI R21, 255 + \ 00000024 .... RCALL __eeget8_16 + \ 00000026 7001 ANDI R16, 0x01 + \ 00000028 F449 BRNE ??BatteryControl_3 + 156 SetErrorFlag(ERR_NO_BATTERIES_ENABLED); + \ 0000002A .... LDI R30, LOW(ErrorFlags) + \ 0000002C .... LDI R31, (ErrorFlags) >> 8 + \ 0000002E 8100 LD R16, Z + \ 00000030 6002 ORI R16, 0x02 + \ 00000032 8300 ST Z, R16 + \ 00000034 9100.... LDS R16, CurrentState + \ 00000038 8301 STD Z+1, R16 + 157 + 158 return(ST_ERROR); + \ 0000003A CFE9 RJMP ??BatteryControl_1 + 159 } + 160 + 161 // Get ADC-readings, try to read EPROM, and start prequalification + 162 // of any uncharged battery. + 163 for (i = 0; i < 2; i++) { + \ ??BatteryControl_3: + \ 0000003C E0A0 LDI R26, 0 + 164 if (BattControl[i].Enabled) { + \ ??BatteryControl_4: + \ 0000003E E0B0 LDI R27, 0 + \ 00000040 01AC MOVW R21:R20, R25:R24 + \ 00000042 0F4A ADD R20, R26 + \ 00000044 1F5B ADC R21, R27 + \ 00000046 .... RCALL __eeget8_16 + \ 00000048 7001 ANDI R16, 0x01 + \ 0000004A F069 BREQ ??BatteryControl_5 + 165 EnableBattery(i); + \ 0000004C 2F0A MOV R16, R26 + \ 0000004E .... RCALL EnableBattery + 166 ADC_Wait(); + \ 00000050 .... RCALL ADC_Wait + 167 + 168 if (BatteryStatusRefresh()) { + \ 00000052 .... RCALL BatteryStatusRefresh + \ 00000054 2300 TST R16 + \ 00000056 F039 BREQ ??BatteryControl_5 + 169 if (!BattData.Charged) { + \ 00000058 9100.... LDS R16, BattData + \ 0000005C FD01 SBRC R16, 1 + \ 0000005E C003 RJMP ??BatteryControl_5 + 170 BatteryDataRefresh(); + \ 00000060 .... RCALL BatteryDataRefresh + 171 + 172 return(ST_PREQUAL); + \ 00000062 E10E LDI R16, 30 + \ 00000064 C005 RJMP ??BatteryControl_2 + 173 } + 174 } + 175 } + 176 } + \ ??BatteryControl_5: + \ 00000066 95A3 INC R26 + \ 00000068 30A2 CPI R26, 2 + \ 0000006A F348 BRCS ??BatteryControl_4 + 177 + 178 // If we end up here, one or two batteries are found and fully charged. + 179 // Disconnect, so we don't drain them, and go to sleep. + 180 DisableBatteries(); + \ 0000006C .... RCALL DisableBatteries + 181 + 182 return(ST_SLEEP); + \ 0000006E E208 LDI R16, 40 + \ ??BatteryControl_2: + \ 00000070 9189 LD R24, Y+ + \ 00000072 9199 LD R25, Y+ + \ 00000074 91A9 LD R26, Y+ + \ 00000076 91B9 LD R27, Y+ + \ 00000078 9508 RET + 183 } + 184 + 185 + 186 /*! \brief Start running on batteries + 187 * + 188 * \todo Run on batteries, if battery voltage high enough. + 189 * \todo Jump here when mains voltage drops below threshold + 190 * + 191 */ + + \ In segment CODE, align 2, keep-with-next + 192 unsigned char Discharge(unsigned char inp) + \ Discharge: + 193 { + 194 return(ST_BATCON); // Supply voltage restored, start charging + \ 00000000 E104 LDI R16, 20 + \ 00000002 9508 RET + 195 } + 196 + 197 + 198 /*! \brief Sleeps until either battery needs charging + 199 * + 200 * Calls Doze(), then refreshes the status for both batteries on wakeup. If + 201 * connected batteries are both charged, the function will loop. If not, it's + 202 * back to ST_BATCON. + 203 * + 204 * \param inp Not used. + 205 * + 206 * \retval ST_BATCON Next state if a connected battery isn't fully charged. + 207 */ + + \ In segment CODE, align 2, keep-with-next + 208 unsigned char Sleep(unsigned char inp) + \ `Sleep`: + 209 { + 210 unsigned char i; + 211 + 212 do { + 213 Doze(); // Take a nap (~8 seconds). + \ 00000000 .... RCALL ADC_Wait + \ ??Sleep_0: + \ 00000002 CFFF RJMP ??Sleep_0 + \ 00000004 REQUIRE _A_MCUCR + \ 00000004 REQUIRE _A_MCUSR + \ 00000004 REQUIRE _A_WDTCR + \ 00000004 REQUIRE _A_ADCSRA + 214 + 215 // If any batteries need charging, go to ST_BATCON. + 216 // Otherwise, keep sleeping. + 217 for (i = 0; i < 2; i++) { + 218 EnableBattery(i); + 219 ADC_Wait(); + 220 if ((BatteryStatusRefresh()) && (!BattData.Charged)) { + 221 return(ST_BATCON); + 222 } + 223 } + 224 + 225 DisableBatteries(); // Disable both batteries before Doze()! + 226 } while (TRUE); + 227 } + 228 + 229 + 230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V) + 231 * + 232 * Waits for ADC-cycles to complete, disables the ADC, then sleeps for + 233 * approx. 8 seconds (Vcc = 5 V) using the watchdog timer. + 234 * On wakeup, ADC is re-enabled. + 235 */ + + \ In segment CODE, align 2, keep-with-next + 236 void Doze(void) + \ Doze: + 237 { + 238 // Wait for this ADC cycle to complete, then halt after the next one. + 239 ADC_Wait(); + \ 00000000 .... RCALL ADC_Wait + 240 ADCS.Halt = TRUE; + 241 ADCS.Flag = FALSE; + 242 + 243 do { + 244 } while (ADCS.Flag == FALSE); + \ ??Doze_0: + \ 00000002 CFFF RJMP ??Doze_0 + \ 00000004 REQUIRE _A_MCUCR + \ 00000004 REQUIRE _A_MCUSR + \ 00000004 REQUIRE _A_WDTCR + \ 00000004 REQUIRE _A_ADCSRA + 245 + 246 WDTCR = (1<> 8 + \ 00000004 8110 LD R17, Z + \ 00000006 2B10 OR R17, R16 + \ 00000008 8310 ST Z, R17 + 359 ErrorState = CurrentState; + \ 0000000A 9100.... LDS R16, CurrentState + \ 0000000E 8301 STD Z+1, R16 + 360 } + \ 00000010 9508 RET + 361 + 362 + 363 /*! \brief Checks on-board jumpers. + 364 * + 365 * Checks on-board jumpers by disconnecting all loads, engaging the PWM and + 366 * increasing the duty cycle until conditioned output voltage equals conditioned + 367 * input voltage. At low PWM duty and no load buck output should be zero and, + 368 * when increasing PWM duty, should quickly jump to steady state output roughly + 369 * equal to input voltage. Will disable and leave disabled all batteries. + 370 * + 371 * \retval FALSE If jumper or load mismatch. + 372 * \retval TRUE If everything OK. + 373 */ + + \ In segment CODE, align 2, keep-with-next + 374 unsigned char JumperCheck(void) + \ JumperCheck: + 375 { + \ 00000000 93BA ST -Y, R27 + \ 00000002 93AA ST -Y, R26 + 376 DisableBatteries(); // Disconnect, or loads may be destroyed! + \ 00000004 .... RCALL DisableBatteries + 377 + 378 PWM_Start(); // Start PWM (controls the buck charger). + \ 00000006 .... RCALL PWM_Start + 379 + 380 // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s. + 381 Time_Set(TIMER_GEN,0,1,0); + \ 00000008 E040 LDI R20, 0 + \ 0000000A E011 LDI R17, 1 + \ 0000000C E020 LDI R18, 0 + \ 0000000E E030 LDI R19, 0 + \ 00000010 E002 LDI R16, 2 + \ 00000012 .... RCALL Time_Set + \ 00000014 .... LDI R26, LOW(ADCS) + \ 00000016 .... LDI R27, (ADCS) >> 8 + \ 00000018 C010 RJMP ??JumperCheck_0 + 382 + 383 do { + 384 // If the PWM output voltage saturates the ADC, stop PWM output and + 385 // report a failure. + 386 if (ADCS.rawVBAT == 1023) { + 387 PWM_Stop(); + 388 return(FALSE); + 389 } + 390 + 391 // If the absolute difference between measured (VIN - VBAT) and the + 392 // typical value are below our set maximum, everything is OK. + 393 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) < + 394 VIN_VBAT_DIFF_MAX ) { + 395 + 396 PWM_Stop(); + 397 return(TRUE); + 398 } + 399 + 400 // Charge current is too high -> check load and jumper J405 and J406. + 401 if (abs(ADCS.IBAT) > 100) { + \ ??JumperCheck_1: + \ 0000001A 961C ADIW R27:R26, 12 + \ 0000001C 910D LD R16, X+ + \ 0000001E 911C LD R17, X + \ 00000020 971D SBIW R27:R26, 13 + \ 00000022 .... RCALL abs + \ 00000024 3605 CPI R16, 101 + \ 00000026 4010 SBCI R17, 0 + \ 00000028 F47C BRGE ??JumperCheck_2 + 402 PWM_Stop(); + 403 return(FALSE); + 404 } + 405 + 406 // If the PWM output can't be increased high enough -> check jumpers + 407 // J400-J404, J407 and J408. + 408 if (!PWM_IncrementDutyCycle()) { + \ 0000002A .... RCALL PWM_IncrementDutyCycle + \ 0000002C 2300 TST R16 + \ 0000002E F061 BREQ ??JumperCheck_2 + 409 PWM_Stop(); + 410 return(FALSE); + 411 } + 412 + 413 // Wait for ADC conversions to complete + 414 ADC_Wait(); + \ 00000030 .... RCALL ADC_Wait + 415 } while (Time_Left(TIMER_GEN)); + \ 00000032 E002 LDI R16, 2 + \ 00000034 .... RCALL Time_Left + \ 00000036 2300 TST R16 + \ 00000038 F039 BREQ ??JumperCheck_2 + \ ??JumperCheck_0: + \ 0000003A 9616 ADIW R27:R26, 6 + \ 0000003C 910D LD R16, X+ + \ 0000003E 911C LD R17, X + \ 00000040 9717 SBIW R27:R26, 7 + \ 00000042 3F0F CPI R16, 255 + \ 00000044 4013 SBCI R17, 3 + \ 00000046 F419 BRNE ??JumperCheck_3 + \ ??JumperCheck_2: + \ 00000048 .... RCALL PWM_Stop + \ 0000004A E000 LDI R16, 0 + \ 0000004C C010 RJMP ??JumperCheck_4 + \ ??JumperCheck_3: + \ 0000004E 9618 ADIW R27:R26, 8 + \ 00000050 910D LD R16, X+ + \ 00000052 911D LD R17, X+ + \ 00000054 5508 SUBI R16, 88 + \ 00000056 4012 SBCI R17, 2 + \ 00000058 912D LD R18, X+ + \ 0000005A 913C LD R19, X + \ 0000005C 971B SBIW R27:R26, 11 + \ 0000005E 1B02 SUB R16, R18 + \ 00000060 0B13 SBC R17, R19 + \ 00000062 .... RCALL abs + \ 00000064 3F04 CPI R16, 244 + \ 00000066 4011 SBCI R17, 1 + \ 00000068 F6C4 BRGE ??JumperCheck_1 + \ 0000006A .... RCALL PWM_Stop + \ 0000006C E001 LDI R16, 1 + \ ??JumperCheck_4: + \ 0000006E 91A9 LD R26, Y+ + \ 00000070 91B9 LD R27, Y+ + \ 00000072 9508 RET + 416 + 417 + 418 // If we end up here, the measurements took too long. + 419 PWM_Stop(); + 420 return(FALSE); + 421 } + + Maximum stack usage in bytes: + + Function CSTACK RSTACK + -------- ------ ------ + BatteryControl 4 4 + -> JumperCheck 4 2 + -> EnableBattery 4 2 + -> ADC_Wait 4 2 + -> BatteryStatusRefresh 4 2 + -> BatteryDataRefresh 4 2 + -> DisableBatteries 4 2 + Discharge 0 2 + Doze 0 2 + -> ADC_Wait 0 2 + Error 0 2 + -> PWM_Stop 0 2 + -> DisableBatteries 0 2 + -> ADC_Wait 0 2 + Initialize 1 4 + -> OWI_Init 1 2 + -> DisableBatteries 1 2 + -> SPI_Init 1 2 + -> ADC_Init 1 2 + -> Time_Init 1 2 + -> EnableBattery 1 2 + -> ADC_Wait 1 2 + -> BatteryStatusRefresh 1 2 + -> DisableBatteries 1 2 + JumperCheck 2 2 + -> DisableBatteries 2 2 + -> PWM_Start 2 2 + -> Time_Set 2 2 + -> abs 2 2 + -> PWM_IncrementDutyCycle 2 2 + -> ADC_Wait 2 2 + -> Time_Left 2 2 + -> PWM_Stop 2 2 + -> abs 2 2 + -> PWM_Stop 2 2 + SetErrorFlag 0 2 + Sleep 0 2 + -> ADC_Wait 0 2 + + + Segment part sizes: + + Function/Label Bytes + -------------- ----- + _A_MCUCR 1 + _A_MCUSR 1 + _A_CLKPR 1 + _A_WDTCR 1 + _A_DDRB 1 + _A_ADCSRA 1 + ErrorFlags 2 + Initialize 82 + BatteryControl 122 + Discharge 4 + Sleep 4 + Doze 4 + Error 8 + SetErrorFlag 18 + JumperCheck 116 + Others 6 + + + 6 bytes in segment ABSOLUTE + 358 bytes in segment CODE + 6 bytes in segment INITTAB + 2 bytes in segment NEAR_Z + + 358 bytes of CODE memory (+ 6 bytes shared) + 2 bytes of DATA memory (+ 6 bytes shared) + +Errors: none +Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/statefunc.s90 b/BaseTinyFirmware/IAR/Release/List/statefunc.s90 new file mode 100644 index 0000000..5f7f353 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/statefunc.s90 @@ -0,0 +1,808 @@ +/////////////////////////////////////////////////////////////////////////////// +// / +// IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:01 / +// Copyright 1996-2007 IAR Systems. All rights reserved. / +// / +// Source file = C:\home\kevin\pub\src\bc100\IAR\statefunc.c / +// Command line = C:\home\kevin\pub\src\bc100\IAR\statefunc.c / +// --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc1 / +// 00\IAR\Release\Obj\ -D NDEBUG -lCN / +// C:\home\kevin\pub\src\bc100\IAR\Release\List\ / +// -lB C:\home\kevin\pub\src\bc100\IAR\Release\Li / +// st\ --initializers_in_flash -s9 / +// --no_cross_call --no_tbaa / +// -DENABLE_BIT_DEFINITIONS -e -I "C:\Program / +// Files\IAR Systems\Embedded Workbench / +// 4.0\avr\INC\" -I "C:\Program Files\IAR / +// Systems\Embedded Workbench 4.0\avr\INC\CLIB\" / +// --eeprom_size 512 --misrac=5-9,11-12,14,16-17, / +// 19-21,24-26,29-32,34-35,38-39,42-43,46,50, / +// 52-54,56-59,61-62,64-65,68-80,83-84,87-91, / +// 94-95,98-100,103-110,112-126 / +// Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, / +// 38-39,42-43,46,50,52-54,56-59,61-62,64-65, / +// 68-80,83-84,87-91,94-95,98-100,103-110,112-126 / +// Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, / +// 42,46,50,52-54,56-59,61-62,64,68-69,71-80, / +// 83-84,87-89,91,94-95,98,100,104-105,108-109, / +// 112-115,118-126 / +// Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, / +// 116-117 / +// List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\s / +// tatefunc.s90 / +// / +// / +/////////////////////////////////////////////////////////////////////////////// + + NAME statefunc + + RSEG CSTACK:DATA:NOROOT(0) + RSEG RSTACK:DATA:NOROOT(0) + + EXTERN ?need_segment_init + EXTERN __eeget8_16 + EXTERN __eeput8_16 + + PUBWEAK `?` + PUBLIC BatteryControl + PUBLIC Discharge + PUBLIC Doze + PUBLIC Error + PUBLIC ErrorFlags + PUBLIC ErrorState + PUBLIC Initialize + PUBLIC JumperCheck + PUBLIC SetErrorFlag + PUBLIC `Sleep` + PUBWEAK _A_ADCSRA + PUBWEAK _A_CLKPR + PUBWEAK _A_DDRB + PUBWEAK _A_MCUCR + PUBWEAK _A_MCUSR + PUBWEAK _A_WDTCR + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + + EXTERN OWI_Init + EXTERN DisableBatteries + EXTERN SPI_Init + EXTERN ADC_Init + EXTERN Time_Init + EXTERN EnableBattery + EXTERN ADC_Wait + EXTERN BatteryStatusRefresh + EXTERN BatteryDataRefresh + EXTERN PWM_Stop + EXTERN PWM_Start + EXTERN Time_Set + EXTERN abs + EXTERN PWM_IncrementDutyCycle + EXTERN Time_Left + EXTERN ADCS + EXTERN BattActive + EXTERN BattControl + EXTERN BattData + EXTERN BattEEPROM + EXTERN CurrentState + +// C:\home\kevin\pub\src\bc100\IAR\statefunc.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * State functions +// 6 * +// 7 * Contains the functions related to the states defined in menu.h.\n +// 8 * Also contains related functions, i.e. for checking jumpers, setting +// 9 * error flags and "dozing". +// 10 * +// 11 * \note The state function Charge() is in a separate file since it +// 12 * should easily be changed with regard to battery type. +// 13 * +// 14 * \par Application note: +// 15 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 16 * AVR463: Charging NiMH Batteries with BC100 +// 17 * +// 18 * \par Documentation +// 19 * For comprehensive code documentation, supported compilers, compiler +// 20 * settings and supported devices see readme.html +// 21 * +// 22 * \author +// 23 * Atmel Corporation: http://www.atmel.com \n +// 24 * Support email: avr@atmel.com +// 25 * +// 26 * +// 27 * $Name$ +// 28 * $Revision: 2299 $ +// 29 * $RCSfile$ +// 30 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $ +// 31 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 32 ******************************************************************************/ +// 33 +// 34 #include + + ASEGN ABSOLUTE:DATA:NOROOT,055H +// volatile __io _A_MCUCR +_A_MCUCR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,054H +// volatile __io _A_MCUSR +_A_MCUSR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,048H +// volatile __io _A_CLKPR +_A_CLKPR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,041H +// volatile __io _A_WDTCR +_A_WDTCR: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,037H +// volatile __io _A_DDRB +_A_DDRB: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,026H +// volatile __io _A_ADCSRA +_A_ADCSRA: + DS 1 +// 35 #include +// 36 #include +// 37 +// 38 #include "structs.h" +// 39 #include "enums.h" +// 40 +// 41 #include "ADC.h" +// 42 #include "statefunc.h" +// 43 #include "battery.h" +// 44 #include "charge.h" +// 45 #include "main.h" +// 46 #include "menu.h" +// 47 #include "OWI.h" +// 48 #include "PWM.h" +// 49 #include "time.h" +// 50 #include "USI.h" +// 51 +// 52 +// 53 //****************************************************************************** +// 54 // Variables +// 55 //****************************************************************************** + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 56 unsigned char ErrorFlags; //!< \brief Holds error flags. +ErrorFlags: + DS 1 +// 57 //!< \note See statefunc.h for definitions of flags. +// 58 +// 59 //! \brief Holds the state in which latest error flag was set. +// 60 //! \note See menu.h for definitions of states. +// 61 unsigned char ErrorState; +ErrorState: + DS 1 +// 62 +// 63 +// 64 //****************************************************************************** +// 65 // Functions +// 66 //****************************************************************************** +// 67 /*! \brief Initialization +// 68 * +// 69 * - Sets the system clock prescaler to 1 (run at 8 MHz) +// 70 * - Initializes the one-wire interface +// 71 * - Clears on-chip EEPROM +// 72 * - Sets battery enable pins as outputs, then disables batteries +// 73 * - Initializes SPI according to \ref SPIMODE +// 74 * - Initializes ADC +// 75 * - Initializes timers +// 76 * - Reads battery data from both battery inputs (via ADC) +// 77 * - Disables batteries again +// 78 * - Sets battery A as the current one (\ref BattActive = 0) +// 79 * - Clears ErrorFlags +// 80 * +// 81 * \param inp Not used. +// 82 * +// 83 * \retval ST_BATCON Next state in the sequence. +// 84 */ + + RSEG CODE:CODE:NOROOT(1) +// 85 unsigned char Initialize(unsigned char inp) +Initialize: +// 86 { + ST -Y, R24 +// 87 unsigned char i, page; +// 88 +// 89 // Disable interrupts while setting prescaler. +// 90 __disable_interrupt(); + CLI +// 91 +// 92 CLKPR = (1< 8 MHz clock frequency. + LDI R16, 0 + OUT 0x28, R16 +// 94 +// 95 // Init 1-Wire(R) interface. +// 96 OWI_Init(OWIBUS); + LDI R16, 1 + RCALL OWI_Init +// 97 +// 98 // Clear on-chip EEPROM. +// 99 for (page = 0; page < 4; page++) { + LDI R20, LOW(BattEEPROM) + LDI R21, (BattEEPROM) >> 8 + LDI R17, 128 +// 100 for (i = 0; i < 32; i++) { +// 101 BattEEPROM[page][i] = 0; +??Initialize_0: + LDI R16, 0 + RCALL __eeput8_16 +// 102 } + SUBI R20, 255 + SBCI R21, 255 +// 103 } + DEC R17 + BRNE ??Initialize_0 +// 104 +// 105 DDRB = (1<> 8 + MOVW R21:R20, R25:R24 + RCALL __eeget8_16 + ANDI R16, 0x01 + BRNE ??BatteryControl_3 + MOVW R21:R20, R25:R24 + SUBI R20, 255 + SBCI R21, 255 + RCALL __eeget8_16 + ANDI R16, 0x01 + BRNE ??BatteryControl_3 +// 156 SetErrorFlag(ERR_NO_BATTERIES_ENABLED); + LDI R30, LOW(ErrorFlags) + LDI R31, (ErrorFlags) >> 8 + LD R16, Z + ORI R16, 0x02 + ST Z, R16 + LDS R16, CurrentState + STD Z+1, R16 +// 157 +// 158 return(ST_ERROR); + RJMP ??BatteryControl_1 +// 159 } +// 160 +// 161 // Get ADC-readings, try to read EPROM, and start prequalification +// 162 // of any uncharged battery. +// 163 for (i = 0; i < 2; i++) { +??BatteryControl_3: + LDI R26, 0 +// 164 if (BattControl[i].Enabled) { +??BatteryControl_4: + LDI R27, 0 + MOVW R21:R20, R25:R24 + ADD R20, R26 + ADC R21, R27 + RCALL __eeget8_16 + ANDI R16, 0x01 + BREQ ??BatteryControl_5 +// 165 EnableBattery(i); + MOV R16, R26 + RCALL EnableBattery +// 166 ADC_Wait(); + RCALL ADC_Wait +// 167 +// 168 if (BatteryStatusRefresh()) { + RCALL BatteryStatusRefresh + TST R16 + BREQ ??BatteryControl_5 +// 169 if (!BattData.Charged) { + LDS R16, BattData + SBRC R16, 1 + RJMP ??BatteryControl_5 +// 170 BatteryDataRefresh(); + RCALL BatteryDataRefresh +// 171 +// 172 return(ST_PREQUAL); + LDI R16, 30 + RJMP ??BatteryControl_2 +// 173 } +// 174 } +// 175 } +// 176 } +??BatteryControl_5: + INC R26 + CPI R26, 2 + BRCS ??BatteryControl_4 +// 177 +// 178 // If we end up here, one or two batteries are found and fully charged. +// 179 // Disconnect, so we don't drain them, and go to sleep. +// 180 DisableBatteries(); + RCALL DisableBatteries +// 181 +// 182 return(ST_SLEEP); + LDI R16, 40 +??BatteryControl_2: + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + RET +// 183 } +// 184 +// 185 +// 186 /*! \brief Start running on batteries +// 187 * +// 188 * \todo Run on batteries, if battery voltage high enough. +// 189 * \todo Jump here when mains voltage drops below threshold +// 190 * +// 191 */ + + RSEG CODE:CODE:NOROOT(1) +// 192 unsigned char Discharge(unsigned char inp) +Discharge: +// 193 { +// 194 return(ST_BATCON); // Supply voltage restored, start charging + LDI R16, 20 + RET +// 195 } +// 196 +// 197 +// 198 /*! \brief Sleeps until either battery needs charging +// 199 * +// 200 * Calls Doze(), then refreshes the status for both batteries on wakeup. If +// 201 * connected batteries are both charged, the function will loop. If not, it's +// 202 * back to ST_BATCON. +// 203 * +// 204 * \param inp Not used. +// 205 * +// 206 * \retval ST_BATCON Next state if a connected battery isn't fully charged. +// 207 */ + + RSEG CODE:CODE:NOROOT(1) +// 208 unsigned char Sleep(unsigned char inp) +`Sleep`: +// 209 { +// 210 unsigned char i; +// 211 +// 212 do { +// 213 Doze(); // Take a nap (~8 seconds). + RCALL ADC_Wait +??Sleep_0: + RJMP ??Sleep_0 + REQUIRE _A_MCUCR + REQUIRE _A_MCUSR + REQUIRE _A_WDTCR + REQUIRE _A_ADCSRA +// 214 +// 215 // If any batteries need charging, go to ST_BATCON. +// 216 // Otherwise, keep sleeping. +// 217 for (i = 0; i < 2; i++) { +// 218 EnableBattery(i); +// 219 ADC_Wait(); +// 220 if ((BatteryStatusRefresh()) && (!BattData.Charged)) { +// 221 return(ST_BATCON); +// 222 } +// 223 } +// 224 +// 225 DisableBatteries(); // Disable both batteries before Doze()! +// 226 } while (TRUE); +// 227 } +// 228 +// 229 +// 230 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V) +// 231 * +// 232 * Waits for ADC-cycles to complete, disables the ADC, then sleeps for +// 233 * approx. 8 seconds (Vcc = 5 V) using the watchdog timer. +// 234 * On wakeup, ADC is re-enabled. +// 235 */ + + RSEG CODE:CODE:NOROOT(1) +// 236 void Doze(void) +Doze: +// 237 { +// 238 // Wait for this ADC cycle to complete, then halt after the next one. +// 239 ADC_Wait(); + RCALL ADC_Wait +// 240 ADCS.Halt = TRUE; +// 241 ADCS.Flag = FALSE; +// 242 +// 243 do { +// 244 } while (ADCS.Flag == FALSE); +??Doze_0: + RJMP ??Doze_0 + REQUIRE _A_MCUCR + REQUIRE _A_MCUSR + REQUIRE _A_WDTCR + REQUIRE _A_ADCSRA +// 245 +// 246 WDTCR = (1<> 8 + LD R17, Z + OR R17, R16 + ST Z, R17 +// 359 ErrorState = CurrentState; + LDS R16, CurrentState + STD Z+1, R16 +// 360 } + RET +// 361 +// 362 +// 363 /*! \brief Checks on-board jumpers. +// 364 * +// 365 * Checks on-board jumpers by disconnecting all loads, engaging the PWM and +// 366 * increasing the duty cycle until conditioned output voltage equals conditioned +// 367 * input voltage. At low PWM duty and no load buck output should be zero and, +// 368 * when increasing PWM duty, should quickly jump to steady state output roughly +// 369 * equal to input voltage. Will disable and leave disabled all batteries. +// 370 * +// 371 * \retval FALSE If jumper or load mismatch. +// 372 * \retval TRUE If everything OK. +// 373 */ + + RSEG CODE:CODE:NOROOT(1) +// 374 unsigned char JumperCheck(void) +JumperCheck: +// 375 { + ST -Y, R27 + ST -Y, R26 +// 376 DisableBatteries(); // Disconnect, or loads may be destroyed! + RCALL DisableBatteries +// 377 +// 378 PWM_Start(); // Start PWM (controls the buck charger). + RCALL PWM_Start +// 379 +// 380 // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s. +// 381 Time_Set(TIMER_GEN,0,1,0); + LDI R20, 0 + LDI R17, 1 + LDI R18, 0 + LDI R19, 0 + LDI R16, 2 + RCALL Time_Set + LDI R26, LOW(ADCS) + LDI R27, (ADCS) >> 8 + RJMP ??JumperCheck_0 +// 382 +// 383 do { +// 384 // If the PWM output voltage saturates the ADC, stop PWM output and +// 385 // report a failure. +// 386 if (ADCS.rawVBAT == 1023) { +// 387 PWM_Stop(); +// 388 return(FALSE); +// 389 } +// 390 +// 391 // If the absolute difference between measured (VIN - VBAT) and the +// 392 // typical value are below our set maximum, everything is OK. +// 393 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) < +// 394 VIN_VBAT_DIFF_MAX ) { +// 395 +// 396 PWM_Stop(); +// 397 return(TRUE); +// 398 } +// 399 +// 400 // Charge current is too high -> check load and jumper J405 and J406. +// 401 if (abs(ADCS.IBAT) > 100) { +??JumperCheck_1: + ADIW R27:R26, 12 + LD R16, X+ + LD R17, X + SBIW R27:R26, 13 + RCALL abs + CPI R16, 101 + SBCI R17, 0 + BRGE ??JumperCheck_2 +// 402 PWM_Stop(); +// 403 return(FALSE); +// 404 } +// 405 +// 406 // If the PWM output can't be increased high enough -> check jumpers +// 407 // J400-J404, J407 and J408. +// 408 if (!PWM_IncrementDutyCycle()) { + RCALL PWM_IncrementDutyCycle + TST R16 + BREQ ??JumperCheck_2 +// 409 PWM_Stop(); +// 410 return(FALSE); +// 411 } +// 412 +// 413 // Wait for ADC conversions to complete +// 414 ADC_Wait(); + RCALL ADC_Wait +// 415 } while (Time_Left(TIMER_GEN)); + LDI R16, 2 + RCALL Time_Left + TST R16 + BREQ ??JumperCheck_2 +??JumperCheck_0: + ADIW R27:R26, 6 + LD R16, X+ + LD R17, X + SBIW R27:R26, 7 + CPI R16, 255 + SBCI R17, 3 + BRNE ??JumperCheck_3 +??JumperCheck_2: + RCALL PWM_Stop + LDI R16, 0 + RJMP ??JumperCheck_4 +??JumperCheck_3: + ADIW R27:R26, 8 + LD R16, X+ + LD R17, X+ + SUBI R16, 88 + SBCI R17, 2 + LD R18, X+ + LD R19, X + SBIW R27:R26, 11 + SUB R16, R18 + SBC R17, R19 + RCALL abs + CPI R16, 244 + SBCI R17, 1 + BRGE ??JumperCheck_1 + RCALL PWM_Stop + LDI R16, 1 +??JumperCheck_4: + LD R26, Y+ + LD R27, Y+ + RET +// 416 +// 417 +// 418 // If we end up here, the measurements took too long. +// 419 PWM_Stop(); +// 420 return(FALSE); +// 421 } + + ASEGN ABSOLUTE:DATA:NOROOT,01cH +__?EECR: + + ASEGN ABSOLUTE:DATA:NOROOT,01dH +__?EEDR: + + ASEGN ABSOLUTE:DATA:NOROOT,01eH +__?EEARL: + + ASEGN ABSOLUTE:DATA:NOROOT,01fH +__?EEARH: + + RSEG INITTAB:CODE:NOROOT(0) +`?`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 6 bytes in segment ABSOLUTE +// 358 bytes in segment CODE +// 6 bytes in segment INITTAB +// 2 bytes in segment NEAR_Z +// +// 358 bytes of CODE memory (+ 6 bytes shared) +// 2 bytes of DATA memory (+ 6 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/List/time.lst b/BaseTinyFirmware/IAR/Release/List/time.lst new file mode 100644 index 0000000..19a1403 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/List/time.lst @@ -0,0 +1,456 @@ +############################################################################### +# # +# IAR Atmel AVR C/C++ Compiler V4.30F/W32 13/Mar/2008 04:52:03 # +# Copyright 1996-2007 IAR Systems. All rights reserved. # +# # +# Source file = C:\home\kevin\pub\src\bc100\IAR\time.c # +# Command line = C:\home\kevin\pub\src\bc100\IAR\time.c # +# --cpu=tiny861 -ms -o C:\home\kevin\pub\src\bc10 # +# 0\IAR\Release\Obj\ -D NDEBUG -lCN # +# C:\home\kevin\pub\src\bc100\IAR\Release\List\ # +# -lB C:\home\kevin\pub\src\bc100\IAR\Release\Lis # +# t\ --initializers_in_flash -s9 --no_cross_call # +# --no_tbaa -DENABLE_BIT_DEFINITIONS -e -I # +# "C:\Program Files\IAR Systems\Embedded # +# Workbench 4.0\avr\INC\" -I "C:\Program # +# Files\IAR Systems\Embedded Workbench # +# 4.0\avr\INC\CLIB\" --eeprom_size 512 # +# --misrac=5-9,11-12,14,16-17,19-21,24-26,29-32, # +# 34-35,38-39,42-43,46,50,52-54,56-59,61-62, # +# 64-65,68-80,83-84,87-91,94-95,98-100,103-110, # +# 112-126 # +# Enabled MISRA C rules = 5-9,11-12,14,16-17,19-21,24-26,29-32,34-35, # +# 38-39,42-43,46,50,52-54,56-59,61-62,64-65, # +# 68-80,83-84,87-91,94-95,98-100,103-110,112-126 # +# Checked = 5,7-9,11-12,14,17,19-21,24,29-32,34-35,38-39, # +# 42,46,50,52-54,56-59,61-62,64,68-69,71-80, # +# 83-84,87-89,91,94-95,98,100,104-105,108-109, # +# 112-115,118-126 # +# Not checked = 6,16,25-26,43,65,70,90,99,103,106-107,110, # +# 116-117 # +# List file = C:\home\kevin\pub\src\bc100\IAR\Release\List\ti # +# me.lst # +# Object file = C:\home\kevin\pub\src\bc100\IAR\Release\Obj\tim # +# e.r90 # +# # +# # +############################################################################### + +C:\home\kevin\pub\src\bc100\IAR\time.c + 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ + 2 /*! \file ********************************************************************* + 3 * + 4 * \brief + 5 * Functions for timing + 6 * + 7 * Contains functions to initialize, set, poll and stop timers. + 8 * + 9 * \par Application note: + 10 * AVR458: Charging Li-Ion Batteries with BC100 \n + 11 * AVR463: Charging NiMH Batteries with BC100 + 12 * + 13 * \par Documentation + 14 * For comprehensive code documentation, supported compilers, compiler + 15 * settings and supported devices see readme.html + 16 * + 17 * \author + 18 * Atmel Corporation: http://www.atmel.com \n + 19 * Support email: avr@atmel.com + 20 * + 21 * + 22 * $Name$ + 23 * $Revision: 2299 $ + 24 * $RCSfile$ + 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $ + 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + 27 ******************************************************************************/ + 28 + 29 #include + + \ In segment ABSOLUTE, at 0x59 + \ volatile __io _A_TIMSK + \ _A_TIMSK: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x53 + \ volatile __io _A_TCCR0B + \ _A_TCCR0B: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x35 + \ volatile __io _A_TCCR0A + \ _A_TCCR0A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x33 + \ volatile __io _A_OCR0A + \ _A_OCR0A: + \ 00000000 DS 1 + + \ In segment ABSOLUTE, at 0x32 + \ volatile __io _A_OCR0B + \ _A_OCR0B: + \ 00000000 DS 1 + 30 #include + 31 + 32 #include "enums.h" + 33 + 34 #include "main.h" + 35 #include "time.h" + 36 + 37 + 38 //****************************************************************************** + 39 // Variables + 40 //****************************************************************************** + + \ In segment NEAR_Z, align 1, keep-with-next + \ 00000000 REQUIRE `?` + 41 unsigned long timeval[TIMERS]; //!< Contains the values for each timer. + \ timeval: + \ 00000000 DS 16 + 42 + 43 // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms + 44 //#pragma vector = TIM0_OVF_vect + 45 + 46 + 47 //****************************************************************************** + 48 // Functions + 49 //****************************************************************************** + 50 /*! \brief Interrupt service routine for timer 0 overflow + 51 * + 52 * Timer 0 runs at 125 kHz and compare match will occur every millisecond + 53 * (125 / 125 kHz = 1.0 ms), which will result in a call to this function. + 54 * When called, this function will decrement the time left for each timer, + 55 * unless they are already at zero. + 56 */ + 57 #pragma vector = TIM0_COMPA_vect + + \ In segment CODE, align 2, keep-with-next + 58 __interrupt void TICK_ISR(void) + \ TICK_ISR: + 59 { + \ 00000000 93FA ST -Y, R31 + \ 00000002 93EA ST -Y, R30 + \ 00000004 937A ST -Y, R23 + \ 00000006 936A ST -Y, R22 + \ 00000008 935A ST -Y, R21 + \ 0000000A 934A ST -Y, R20 + \ 0000000C 931A ST -Y, R17 + \ 0000000E 930A ST -Y, R16 + \ 00000010 B71F IN R17, 0x3F + 60 unsigned char i; + 61 + 62 // 1 ms has passed, decrement all non-zero timers. + 63 for (i = 0; i < TIMERS; i++) { + \ 00000012 .... LDI R30, LOW(timeval) + \ 00000014 .... LDI R31, (timeval) >> 8 + \ 00000016 E004 LDI R16, 4 + 64 if(timeval[i] > 0) { + \ ??TICK_ISR_0: + \ 00000018 8140 LD R20, Z + \ 0000001A 8151 LDD R21, Z+1 + \ 0000001C 8162 LDD R22, Z+2 + \ 0000001E 8173 LDD R23, Z+3 + \ 00000020 2B45 OR R20, R21 + \ 00000022 2B46 OR R20, R22 + \ 00000024 2B47 OR R20, R23 + \ 00000026 F049 BREQ ??TICK_ISR_1 + 65 timeval[i]--; + \ 00000028 8140 LD R20, Z + \ 0000002A 5041 SUBI R20, 1 + \ 0000002C 4050 SBCI R21, 0 + \ 0000002E 4060 SBCI R22, 0 + \ 00000030 4070 SBCI R23, 0 + \ 00000032 8340 ST Z, R20 + \ 00000034 8351 STD Z+1, R21 + \ 00000036 8362 STD Z+2, R22 + \ 00000038 8373 STD Z+3, R23 + 66 } + 67 } + \ ??TICK_ISR_1: + \ 0000003A 9634 ADIW R31:R30, 4 + \ 0000003C 950A DEC R16 + \ 0000003E 2300 TST R16 + \ 00000040 F759 BRNE ??TICK_ISR_0 + 68 } + \ 00000042 BF1F OUT 0x3F, R17 + \ 00000044 9109 LD R16, Y+ + \ 00000046 9119 LD R17, Y+ + \ 00000048 9149 LD R20, Y+ + \ 0000004A 9159 LD R21, Y+ + \ 0000004C 9169 LD R22, Y+ + \ 0000004E 9179 LD R23, Y+ + \ 00000050 91E9 LD R30, Y+ + \ 00000052 91F9 LD R31, Y+ + \ 00000054 9518 RETI + 69 + 70 + 71 /*! \brief Checks if a specified timer has expired + 72 * + 73 * \param timer Specifies timer + 74 * + 75 * \retval TRUE Timer still going. + 76 * \retval FALSE Timer has expired. + 77 */ + + \ In segment CODE, align 2, keep-with-next + 78 unsigned char Time_Left(unsigned char timer) + \ Time_Left: + 79 { + 80 if(timeval[timer] > 0) { + \ 00000000 E010 LDI R17, 0 + \ 00000002 0F00 LSL R16 + \ 00000004 1F11 ROL R17 + \ 00000006 0F00 LSL R16 + \ 00000008 1F11 ROL R17 + \ 0000000A 01F8 MOVW R31:R30, R17:R16 + \ 0000000C .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 0000000E .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000010 8100 LD R16, Z + \ 00000012 8111 LDD R17, Z+1 + \ 00000014 8122 LDD R18, Z+2 + \ 00000016 8133 LDD R19, Z+3 + \ 00000018 2B01 OR R16, R17 + \ 0000001A 2B02 OR R16, R18 + \ 0000001C 2B03 OR R16, R19 + \ 0000001E F011 BREQ ??Time_Left_0 + 81 return(TRUE); + \ 00000020 E001 LDI R16, 1 + \ 00000022 9508 RET + 82 } else { + 83 return(FALSE); + \ ??Time_Left_0: + \ 00000024 E000 LDI R16, 0 + \ 00000026 9508 RET + 84 } + 85 } + 86 + 87 + 88 /*! \brief Sets the specified timer + 89 * + 90 * \param timer Specifies timer + 91 * \param min Minutes for timer to count down + 92 * \param sec Seconds for timer to count down + 93 * \param ms Milliseconds for timer to count down + 94 */ + + \ In segment CODE, align 2, keep-with-next + 95 void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, + \ Time_Set: + 96 unsigned char ms) + 97 { + \ 00000000 928A ST -Y, R8 + \ 00000002 926A ST -Y, R6 + \ 00000004 925A ST -Y, R5 + \ 00000006 924A ST -Y, R4 + \ 00000008 93BA ST -Y, R27 + \ 0000000A 93AA ST -Y, R26 + \ 0000000C 939A ST -Y, R25 + \ 0000000E 938A ST -Y, R24 + \ 00000010 REQUIRE ?Register_R4_is_cg_reg + \ 00000010 REQUIRE ?Register_R5_is_cg_reg + \ 00000010 REQUIRE ?Register_R6_is_cg_reg + \ 00000010 REQUIRE ?Register_R8_is_cg_reg + \ 00000010 2E40 MOV R4, R16 + \ 00000012 2E81 MOV R8, R17 + \ 00000014 2E64 MOV R6, R20 + 98 // timeval[i] = 4 * (1000*(sec + 60*min) + ms); // about 4000 ticks per second + 99 // timeval[i] = 240000 * (unsigned long)min; + 100 // timeval[i] += 4000 * (unsigned long)sec; + 101 // timeval[i] += 4 * (unsigned long)ms; + 102 + 103 timeval[timer] = 60000 * (unsigned long)min; + 104 timeval[timer] += 1000 * (unsigned long)sec; + 105 timeval[timer] += 1 * (unsigned long)ms; + \ 00000016 01A9 MOVW R21:R20, R19:R18 + \ 00000018 E060 LDI R22, 0 + \ 0000001A E070 LDI R23, 0 + \ 0000001C E600 LDI R16, 96 + \ 0000001E EE1A LDI R17, 234 + \ 00000020 E020 LDI R18, 0 + \ 00000022 E030 LDI R19, 0 + \ 00000024 .... RCALL ?L_MUL_L03 + \ 00000026 01C8 MOVW R25:R24, R17:R16 + \ 00000028 01D9 MOVW R27:R26, R19:R18 + \ 0000002A 2D48 MOV R20, R8 + \ 0000002C E050 LDI R21, 0 + \ 0000002E E060 LDI R22, 0 + \ 00000030 E070 LDI R23, 0 + \ 00000032 EE08 LDI R16, 232 + \ 00000034 E013 LDI R17, 3 + \ 00000036 E020 LDI R18, 0 + \ 00000038 E030 LDI R19, 0 + \ 0000003A .... RCALL ?L_MUL_L03 + \ 0000003C 0F08 ADD R16, R24 + \ 0000003E 1F19 ADC R17, R25 + \ 00000040 1F2A ADC R18, R26 + \ 00000042 1F3B ADC R19, R27 + \ 00000044 2D46 MOV R20, R6 + \ 00000046 E050 LDI R21, 0 + \ 00000048 E060 LDI R22, 0 + \ 0000004A E070 LDI R23, 0 + \ 0000004C 0F40 ADD R20, R16 + \ 0000004E 1F51 ADC R21, R17 + \ 00000050 1F62 ADC R22, R18 + \ 00000052 1F73 ADC R23, R19 + \ 00000054 2455 CLR R5 + \ 00000056 0C44 LSL R4 + \ 00000058 1C55 ROL R5 + \ 0000005A 0C44 LSL R4 + \ 0000005C 1C55 ROL R5 + \ 0000005E 01F2 MOVW R31:R30, R5:R4 + \ 00000060 .... SUBI R30, LOW((-(timeval) & 0xFFFF)) + \ 00000062 .... SBCI R31, (-(timeval) & 0xFFFF) >> 8 + \ 00000064 8340 ST Z, R20 + \ 00000066 8351 STD Z+1, R21 + \ 00000068 8362 STD Z+2, R22 + \ 0000006A 8373 STD Z+3, R23 + 106 } + \ 0000006C 9189 LD R24, Y+ + \ 0000006E 9199 LD R25, Y+ + \ 00000070 91A9 LD R26, Y+ + \ 00000072 91B9 LD R27, Y+ + \ 00000074 9049 LD R4, Y+ + \ 00000076 9059 LD R5, Y+ + \ 00000078 9069 LD R6, Y+ + \ 0000007A 9089 LD R8, Y+ + \ 0000007C 9508 RET + 107 + 108 + 109 /*! \brief Stops timers + 110 * + 111 * Sets timer0's clock source to none. + 112 */ + + \ In segment CODE, align 2, keep-with-next + 113 void Time_Stop(void) + \ Time_Stop: + 114 { + 115 TCCR0B = 0; + \ 00000000 E000 LDI R16, 0 + \ 00000002 BF03 OUT 0x33, R16 + 116 } + \ 00000004 9508 RET + \ 00000006 REQUIRE _A_TCCR0B + 117 + 118 + 119 /*! \brief Starts timers + 120 * + 121 * Sets timer0's clock source to system clock divided by 64. + 122 */ + + \ In segment CODE, align 2, keep-with-next + 123 void Time_Start(void) + \ Time_Start: + 124 { + 125 TCCR0B = (0<` + PUBWEAK `??TICK_ISR??INTVEC 28` + PUBLIC TICK_ISR + PUBLIC Time_Init + PUBLIC Time_Left + PUBLIC Time_Set + PUBLIC Time_Start + PUBLIC Time_Stop + PUBWEAK _A_OCR0A + PUBWEAK _A_OCR0B + PUBWEAK _A_TCCR0A + PUBWEAK _A_TCCR0B + PUBWEAK _A_TIMSK + PUBWEAK __?EEARH + PUBWEAK __?EEARL + PUBWEAK __?EECR + PUBWEAK __?EEDR + PUBLIC timeval + +TICK_ISR SYMBOL "TICK_ISR" +`??TICK_ISR??INTVEC 28` SYMBOL "??INTVEC 28", TICK_ISR + +// C:\home\kevin\pub\src\bc100\IAR\time.c +// 1 /* This file has been prepared for Doxygen automatic documentation generation.*/ +// 2 /*! \file ********************************************************************* +// 3 * +// 4 * \brief +// 5 * Functions for timing +// 6 * +// 7 * Contains functions to initialize, set, poll and stop timers. +// 8 * +// 9 * \par Application note: +// 10 * AVR458: Charging Li-Ion Batteries with BC100 \n +// 11 * AVR463: Charging NiMH Batteries with BC100 +// 12 * +// 13 * \par Documentation +// 14 * For comprehensive code documentation, supported compilers, compiler +// 15 * settings and supported devices see readme.html +// 16 * +// 17 * \author +// 18 * Atmel Corporation: http://www.atmel.com \n +// 19 * Support email: avr@atmel.com +// 20 * +// 21 * +// 22 * $Name$ +// 23 * $Revision: 2299 $ +// 24 * $RCSfile$ +// 25 * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $ +// 26 * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n +// 27 ******************************************************************************/ +// 28 +// 29 #include + + ASEGN ABSOLUTE:DATA:NOROOT,059H +// volatile __io _A_TIMSK +_A_TIMSK: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,053H +// volatile __io _A_TCCR0B +_A_TCCR0B: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,035H +// volatile __io _A_TCCR0A +_A_TCCR0A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,033H +// volatile __io _A_OCR0A +_A_OCR0A: + DS 1 + + ASEGN ABSOLUTE:DATA:NOROOT,032H +// volatile __io _A_OCR0B +_A_OCR0B: + DS 1 +// 30 #include +// 31 +// 32 #include "enums.h" +// 33 +// 34 #include "main.h" +// 35 #include "time.h" +// 36 +// 37 +// 38 //****************************************************************************** +// 39 // Variables +// 40 //****************************************************************************** + + RSEG NEAR_Z:DATA:NOROOT(0) + REQUIRE `?` +// 41 unsigned long timeval[TIMERS]; //!< Contains the values for each timer. +timeval: + DS 16 +// 42 +// 43 // timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms +// 44 //#pragma vector = TIM0_OVF_vect +// 45 +// 46 +// 47 //****************************************************************************** +// 48 // Functions +// 49 //****************************************************************************** +// 50 /*! \brief Interrupt service routine for timer 0 overflow +// 51 * +// 52 * Timer 0 runs at 125 kHz and compare match will occur every millisecond +// 53 * (125 / 125 kHz = 1.0 ms), which will result in a call to this function. +// 54 * When called, this function will decrement the time left for each timer, +// 55 * unless they are already at zero. +// 56 */ +// 57 #pragma vector = TIM0_COMPA_vect + + RSEG CODE:CODE:NOROOT(1) +// 58 __interrupt void TICK_ISR(void) +TICK_ISR: +// 59 { + ST -Y, R31 + ST -Y, R30 + ST -Y, R23 + ST -Y, R22 + ST -Y, R21 + ST -Y, R20 + ST -Y, R17 + ST -Y, R16 + IN R17, 0x3F +// 60 unsigned char i; +// 61 +// 62 // 1 ms has passed, decrement all non-zero timers. +// 63 for (i = 0; i < TIMERS; i++) { + LDI R30, LOW(timeval) + LDI R31, (timeval) >> 8 + LDI R16, 4 +// 64 if(timeval[i] > 0) { +??TICK_ISR_0: + LD R20, Z + LDD R21, Z+1 + LDD R22, Z+2 + LDD R23, Z+3 + OR R20, R21 + OR R20, R22 + OR R20, R23 + BREQ ??TICK_ISR_1 +// 65 timeval[i]--; + LD R20, Z + SUBI R20, 1 + SBCI R21, 0 + SBCI R22, 0 + SBCI R23, 0 + ST Z, R20 + STD Z+1, R21 + STD Z+2, R22 + STD Z+3, R23 +// 66 } +// 67 } +??TICK_ISR_1: + ADIW R31:R30, 4 + DEC R16 + TST R16 + BRNE ??TICK_ISR_0 +// 68 } + OUT 0x3F, R17 + LD R16, Y+ + LD R17, Y+ + LD R20, Y+ + LD R21, Y+ + LD R22, Y+ + LD R23, Y+ + LD R30, Y+ + LD R31, Y+ + RETI +// 69 +// 70 +// 71 /*! \brief Checks if a specified timer has expired +// 72 * +// 73 * \param timer Specifies timer +// 74 * +// 75 * \retval TRUE Timer still going. +// 76 * \retval FALSE Timer has expired. +// 77 */ + + RSEG CODE:CODE:NOROOT(1) +// 78 unsigned char Time_Left(unsigned char timer) +Time_Left: +// 79 { +// 80 if(timeval[timer] > 0) { + LDI R17, 0 + LSL R16 + ROL R17 + LSL R16 + ROL R17 + MOVW R31:R30, R17:R16 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + LD R16, Z + LDD R17, Z+1 + LDD R18, Z+2 + LDD R19, Z+3 + OR R16, R17 + OR R16, R18 + OR R16, R19 + BREQ ??Time_Left_0 +// 81 return(TRUE); + LDI R16, 1 + RET +// 82 } else { +// 83 return(FALSE); +??Time_Left_0: + LDI R16, 0 + RET +// 84 } +// 85 } +// 86 +// 87 +// 88 /*! \brief Sets the specified timer +// 89 * +// 90 * \param timer Specifies timer +// 91 * \param min Minutes for timer to count down +// 92 * \param sec Seconds for timer to count down +// 93 * \param ms Milliseconds for timer to count down +// 94 */ + + RSEG CODE:CODE:NOROOT(1) +// 95 void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, +Time_Set: +// 96 unsigned char ms) +// 97 { + ST -Y, R8 + ST -Y, R6 + ST -Y, R5 + ST -Y, R4 + ST -Y, R27 + ST -Y, R26 + ST -Y, R25 + ST -Y, R24 + REQUIRE ?Register_R4_is_cg_reg + REQUIRE ?Register_R5_is_cg_reg + REQUIRE ?Register_R6_is_cg_reg + REQUIRE ?Register_R8_is_cg_reg + MOV R4, R16 + MOV R8, R17 + MOV R6, R20 +// 98 // timeval[i] = 4 * (1000*(sec + 60*min) + ms); // about 4000 ticks per second +// 99 // timeval[i] = 240000 * (unsigned long)min; +// 100 // timeval[i] += 4000 * (unsigned long)sec; +// 101 // timeval[i] += 4 * (unsigned long)ms; +// 102 +// 103 timeval[timer] = 60000 * (unsigned long)min; +// 104 timeval[timer] += 1000 * (unsigned long)sec; +// 105 timeval[timer] += 1 * (unsigned long)ms; + MOVW R21:R20, R19:R18 + LDI R22, 0 + LDI R23, 0 + LDI R16, 96 + LDI R17, 234 + LDI R18, 0 + LDI R19, 0 + RCALL ?L_MUL_L03 + MOVW R25:R24, R17:R16 + MOVW R27:R26, R19:R18 + MOV R20, R8 + LDI R21, 0 + LDI R22, 0 + LDI R23, 0 + LDI R16, 232 + LDI R17, 3 + LDI R18, 0 + LDI R19, 0 + RCALL ?L_MUL_L03 + ADD R16, R24 + ADC R17, R25 + ADC R18, R26 + ADC R19, R27 + MOV R20, R6 + LDI R21, 0 + LDI R22, 0 + LDI R23, 0 + ADD R20, R16 + ADC R21, R17 + ADC R22, R18 + ADC R23, R19 + CLR R5 + LSL R4 + ROL R5 + LSL R4 + ROL R5 + MOVW R31:R30, R5:R4 + SUBI R30, LOW((-(timeval) & 0xFFFF)) + SBCI R31, (-(timeval) & 0xFFFF) >> 8 + ST Z, R20 + STD Z+1, R21 + STD Z+2, R22 + STD Z+3, R23 +// 106 } + LD R24, Y+ + LD R25, Y+ + LD R26, Y+ + LD R27, Y+ + LD R4, Y+ + LD R5, Y+ + LD R6, Y+ + LD R8, Y+ + RET +// 107 +// 108 +// 109 /*! \brief Stops timers +// 110 * +// 111 * Sets timer0's clock source to none. +// 112 */ + + RSEG CODE:CODE:NOROOT(1) +// 113 void Time_Stop(void) +Time_Stop: +// 114 { +// 115 TCCR0B = 0; + LDI R16, 0 + OUT 0x33, R16 +// 116 } + RET + REQUIRE _A_TCCR0B +// 117 +// 118 +// 119 /*! \brief Starts timers +// 120 * +// 121 * Sets timer0's clock source to system clock divided by 64. +// 122 */ + + RSEG CODE:CODE:NOROOT(1) +// 123 void Time_Start(void) +Time_Start: +// 124 { +// 125 TCCR0B = (0<`: + DW SFE(NEAR_Z) - SFB(NEAR_Z) + DW SFB(NEAR_Z) + DW 0 + REQUIRE ?need_segment_init + + END +// +// 5 bytes in segment ABSOLUTE +// 290 bytes in segment CODE +// 6 bytes in segment INITTAB +// 2 bytes in segment INTVEC +// 16 bytes in segment NEAR_Z +// +// 290 bytes of CODE memory (+ 8 bytes shared) +// 16 bytes of DATA memory (+ 5 bytes shared) +// +//Errors: none +//Warnings: none diff --git a/BaseTinyFirmware/IAR/Release/Obj/ADC.r90 b/BaseTinyFirmware/IAR/Release/Obj/ADC.r90 new file mode 100644 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 index 0000000..748e2e2 --- /dev/null +++ b/BaseTinyFirmware/IAR/Release/Obj/BC100_tiny.pbd @@ -0,0 +1,13 @@ +This is an internal working file generated by the Source Browser. +04:52 05s +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\ADC.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\NIMHcharge.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\OWI.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\PWM.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\USI.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\battery.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\chargefunc.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\main.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\menu.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\statefunc.pbi +C:\home\kevin\pub\src\bc100\IAR\Release\Obj\time.pbi diff --git a/BaseTinyFirmware/IAR/Release/Obj/NIMHcharge.r90 b/BaseTinyFirmware/IAR/Release/Obj/NIMHcharge.r90 new file mode 100644 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 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 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 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 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 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 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 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 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 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 index 0000000..95f9096 --- /dev/null +++ b/BaseTinyFirmware/IAR/USI.c @@ -0,0 +1,311 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for use of the Universal Serial Interface + * + * Contains high level functions for initializing the USI as an SPI slave, + * interrupt handling, sending and receiving single bytes. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/USI.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include + +#include "enums.h" +#include "structs.h" + +#include "main.h" +#include "ADC.h" +#include "battery.h" +#include "time.h" +#include "USI.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +//! SPI status struct +SPI_Status_t SPI; + + +//****************************************************************************** +//Functions +//***************************************************************************** +/*! \brief USI Counter Overflow Interrupt Service Routine + * + * When the USI counter overflows, a byte has been transferred.\n + * The USIDR contents are stored and flags are updated. + * + * The protocol is quite simple and has three sequential states: command, + * address and data. + * (Keep in mind that the Master is in charge of data clocking, which means + * there is a one byte "delay" from when the Slave puts something to SPI till + * the Master can read it.) + * + * 1. If a non-zero byte is received in the command state, the ISR will + * store the commands to the SPI struct (read/write, EEPROM/SRAM, number of + * bytes). To signal that the command was received, 0xCC is put to the SPI bus. + * If a zero byte (0x00) is received in the command state, it is simply ignored + * because it is an invalid command. + * + * 2. When a byte is received in the address state, it is stored to the SPI + * struct. To signal that the address was received, 0xBB is put to SPI bus. + * + * 3. In the data state, variables are read/written "from back to front" until + * the byte counter reaches zero. Since the Master is in charge of the data + * clocking, the Slave will go to command state before the last byte is + * transferred during reading. This means that the Master should send an + * invalid command when getting each byte, ie 0x00. + * + * If the time between two transfers is 1 second or more, the Slave + * automatically reverts to command state. + * + * \note Battery charging is not automatically halted during SPI communication. + * This means that the current charge state (current and voltage) will + * remain constant during heavy and prolonged serial traffic. + * + * \todo Variable writing not implemented yet. + * \todo EEPROM/SRAM flag doesn't really do anything with this implementation. + */ +#pragma vector=USI_OVF_vect +__interrupt void USI_OVF_ISR(void) +{ + // If the communication timed out, set ST_CMD as current state. + if (!Time_Left(TIMER_USI)) { + SPI.State = ST_CMD; + } + + // Start communication timer. If further communication doesn't happen + // within 1 second, the SPI communication state is reset to CMD. + Time_Set(TIMER_USI, 0, 1, 0); + + // Clear USI counter and flag completed transfer. + USISR = (1< 0) { + // Write specified variable to SPI, "back to front". + if (SPI.Read) { + switch (SPI.Address) { + case ADR_ADCS: + SPI_Put(*(((unsigned char*)&ADCS) + (SPI.Count))); + break; + + + case ADR_BATTACTIVE: + SPI_Put(*((unsigned char*)&BattActive + (SPI.Count))); + break; + + + case ADR_BATTDATA: + SPI_Put(*((unsigned char*)&BattData + (SPI.Count))); + break; + + + case ADR_BATTCTRL: + SPI_Put(*((__eeprom unsigned char*)&BattControl + (SPI.Count))); + break; + + case ADR_TIMERS: + SPI_Put(*((unsigned char*)&timeval + (SPI.Count))); + break; + + + default: + SPI_Put(0); + break; + } + } else { + // Read byte from SPI + SPI.Data = USIDR; + + // ******************************************** + // THIS FUNCTION HAS NOT BEEN FULLY IMPLEMENTED + // ******************************************** + + // Save byte to specified variable. + switch (SPI.Address) { + case ADR_BATTCTRL: + *((__eeprom unsigned char*)&BattControl + SPI.Count) = SPI.Data; + break; + + + default: + break; + } + } + + + } else { + SPI.State = ST_CMD; + } + break; + + default: // Shouldn't end up here. (Unknown SPI-state) + break; + } +} + + +/*! \brief Initializes USI as an SPI slave + * + * Initializes USI as a 3-wire SPI slave using the pins specified in USI.h for + * I/O and clock, and USI counter overflow interrupts enabled.\n + * Also initializes the SPI status struct. + * + * \param spi_mode Specifies if USI should trigger on positive (0) or negative + * (1) edge of clock signal + * + * \note Clears the stored data + * + * \todo Timer should reset SPI protocol on timeout + */ +void SPI_Init(unsigned char spi_mode) +{ + __disable_interrupt(); + + // Configure outputs and inputs, enable pull-ups for DATAIN and CLOCK pins. + USI_DIR_REG |= (1< +#include + +#include "structs.h" +#include "enums.h" + +#include "ADC.h" +#include "battery.h" +#include "main.h" +#include "OWI.h" +#include "time.h" + +#ifdef NIMH +#include "NIMHspecs.h" +#endif // NIMH + +#ifdef LIION +#include "LIIONspecs.h" +#endif // LIION + + + +//****************************************************************************** +// Variables +//****************************************************************************** +/* Control-struct for batteries */ +/*! \brief Holds control data for both batteries + * \note Stored in EEPROM. + */ +__eeprom Battery_t BattControl[2] = {{TRUE, TRUE, FALSE}, + {TRUE, TRUE, FALSE}}; + +/* Data-struct for battery */ +Batteries_t BattData; //!< Holds data for the current battery + + +/* Storage for battery EPROM */ +/*! \brief Storage space for data from the batteries' own EPROMs. + * \note Stored in EEPROM. + */ +__eeprom unsigned char BattEEPROM[4][32]; + + +//! Global that indicates current battery (0 = battery A, 1 = B) +unsigned char BattActive; + + +/*! \brief RID lookup-table + * + * Contains Resistor ID data specified by manufacturer. + * + * \note Values have been calculated assuming a +/- 15% tolerance. + */ +const RID_Lookup_t RID[RID_TABLE_SIZE] = { + {558, 659, 3900, 550, 260, 300, 10}, + {744, 843, 6800, 750, 360, 300, 14}, + {869, 958, 10000, 1000, 475, 300, 19}, + {1097, 1153, 24000, 2000, 475, 420, 38} +}; + + +/*! \brief NTC lookup-table + * + * The first entry is 0 degrees. For every entry after, temperature increases + * with 4 degrees. With 20 entries, the last one equals (20-1)*4 = 76 degrees.\n + * It must be sorted in descending ADC order. + * + * \note This was calculated for a Mitsubishi RH16-3H103FB NTC. + * + * \note NTCLookUp() must be modified if this table is changed so that: + * - first entry is no longer 0 degrees. + * - temperature difference between entries is no longer 4 degrees. + * - ADCsteps no longer specifies ADC steps per half degree. + */ +// FOR VARTA POLYFLEX NTC +const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + {1002, 23}, {953, 25}, {902, 26}, {849, 27}, {796, 27}, + {742, 27}, {689, 26}, {637, 26}, {587, 25}, {539, 24}, + {494, 22}, {451, 21}, {412, 19}, {375, 18}, {341, 17}, + {310, 15}, {282, 14}, {256, 13}, {233, 11}, {212, 10} +}; + + +// FOR MITSUBISHI NTC +/* +const NTC_Lookup_t NTC[NTC_TABLE_SIZE] = { + {1004, 24}, {954, 25}, {903, 26}, {850, 27}, {796, 27}, + {742, 27}, {689, 27}, {637, 26}, {587, 25}, {539, 24}, + {493, 22}, {451, 21}, {411, 20}, {374, 18}, {340, 17}, + {309, 15}, {281, 14}, {255, 13}, {232, 11}, {211, 10} +}; +*/ + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Checks if battery has changed + * + * Stores current capacity, then attempts to refresh battery status.\n + * If the refresh is successful, old capacity is compared with the new one. + * + * \retval FALSE Battery is disconnected, or capacity has changed. + * \retval TRUE All OK. + */ +unsigned char BatteryCheck(void) +{ + unsigned char success = TRUE; + unsigned int oldCapacity; + + // Save to see if battery data has changed. + oldCapacity = BattData.Capacity; + + if (!BatteryStatusRefresh()) { + success = FALSE; // Battery not present or RID was invalid. + } + + if (oldCapacity != BattData.Capacity) { + success = FALSE; // Battery configuration has changed. + } + + return(success); +} + + +/*! \brief Refreshes battery status information + * + * Refreshes battery status information, if it is present, based on + * RID and NTC (read by ADC).\n + * The battery must have been enabled and a complete set of ADC data must have + * been collected before calling.\n + * + * \retval FALSE No battery present. + * \retval TRUE Battery present, status refreshed. + * + * \note If ALLOW_NO_RID is defined, charging will NOT stop if no fitting entry + * is found in the lookup table. Instead, default battery data will be used. + */ +unsigned char BatteryStatusRefresh(void) +{ + // Assume the worst.. + unsigned char success = FALSE; + + BattData.Present = FALSE; + BattData.Charged = FALSE; + BattData.Low = TRUE; + BattData.Circuit = OW_NONE; + BattData.Temperature = 0; + BattData.Capacity = 0; + BattData.MaxCurrent = 0; + BattData.MaxTime = 0; + BattData.MinCurrent = 0; + + NTCLookUp(); + BattData.HasRID = RIDLookUp(); + + // Is the battery voltage above minimum safe cell voltage? + if (ADCS.VBAT >= BAT_VOLTAGE_MIN) { + BattData.Low = FALSE; + } + + // Is the battery charged? + if (ADCS.VBAT >= BAT_VOLTAGE_LOW) { + BattData.Charged = TRUE; + } + + // If we are not charging, yet VBAT is above safe limit, battery is present. + // If we are charging and there's a current flowing, the battery is present. + + /*! \todo If ABORT_IF_PWM_MAX is defined this last check battery presence + * check is redundant since charging will be aborted due to low current at + * max duty cycle. That is preferrable since the charge current reading is + * not 100% proof. + */ + if (((OCR1B == 0) && (!BattData.Low)) || + ((OCR1B != 0) && (ADCS.avgIBAT > 0))) { + BattData.Present = TRUE; + success = TRUE; + } else { + BattData.Low = FALSE; // (This is just a technicality..) + success = FALSE; + } + +#ifndef ALLOW_NO_RID + // Return FALSE if no valid RID entry was found, to stop charging. + if(!BattData.HasRID) { + success = FALSE; + } +#endif + + return(success); +} + + +/*! \brief Refreshes battery data in the EEPROM + * + * Attempts to read 4 pages of 32 bytes each from the battery's EPROM and store + * these data in on-chip EEPROM.\n + * If unsuccessful (CRC doesn't check out), the on-chip EEPROM is cleared. + * + * \todo Updating BattData with these data. Specs needed. + * + * \retval FALSE Refresh failed. + * \retval TRUE Refresh successful. + */ +unsigned char BatteryDataRefresh(void) +{ + unsigned char offset; + unsigned char i, crc, family, temp, page; + unsigned char success; + + // Look for EPROM and read 4 pages of 32 bytes each worth of data, if found. + for (page = 0; page < 4; page++) { + success = FALSE; + + if (OWI_DetectPresence(OWIBUS) == OWIBUS) { + + // Presence detected, check type and CRC. + OWI_SendByte(OWI_ROM_READ, OWIBUS); + family = OWI_ReceiveByte(OWIBUS); + crc = OWI_ComputeCRC8(family,0); + + for (i = 0; i < 6; i++) { + crc = OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc); + } + + // CRC ok, device found. + if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + BattData.Circuit = family; + + // For now, we only read data from DS2505 EPROMs. + if (BattData.Circuit == OW_DS2505) { + offset = page*32; + OWI_SendByte(DS2505_DATA_READ, OWIBUS); // Command: read data. + OWI_SendByte(offset, OWIBUS); // Data: low address. + OWI_SendByte(0, OWIBUS); // Data: high address. + + // Calculate checksums. + crc = OWI_ComputeCRC8(DS2505_DATA_READ,0); + crc = OWI_ComputeCRC8(offset,crc); + crc = OWI_ComputeCRC8(0,crc); + + // Command received succesfully, now start reading data + // and writing it to EEPROM. + if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + crc = 0; + + // Fill page with data. + for (i=0; i<32; i++) { + temp = OWI_ReceiveByte(OWIBUS); + crc = OWI_ComputeCRC8(temp, crc); + BattEEPROM[page][i] = temp; + } + + if (OWI_ComputeCRC8(OWI_ReceiveByte(OWIBUS),crc) == 0) { + success = TRUE; // Data read OK + } + } else { // Not able to start reading data. + } + } else { // Wrong device type. + } + } else { // No device found. + } + } else { // No presence detected on one-wire bus. + } + + // Erase local EEPROM page if there were any errors during transfer. + if (!success) { + for (i=0; i<32; i++) { + BattEEPROM[page][i] = 0; + } + } + } + + return(success); +} + + +/*! \brief Enables specified battery + * + * Updates \ref BattActive to specified battery, then sets PB4/PB5 and clears + * PB5/PB4 in PORTB, depending on which battery is specified.\n + * The function takes 100 ms to allow the port switch to settle. + * + * \param bat Specifies which battery to enable (0 = battery A, 1 = B) + */ +void EnableBattery(unsigned char bat) +{ + // Use general timer, set timeout to 100ms. + Time_Set(TIMER_GEN,0,0,100); + + // Set specified battery as the active one. + BattActive = bat; + + // Enable current battery in hardware, light LED & connect battery. + PORTB |= (1 << (PB4+bat)); + + // Disconnect other battery. + PORTB &= ~(1<<(PB5-bat)); + + do { // Let port switch settle. + } while (Time_Left(TIMER_GEN)); +} + + +/*! \brief Disables both batteries + * + * Clears PB4 and PB5 in PORTB, disabling both batteries. + */ +void DisableBatteries(void) +{ + // Turn off LEDs and disconnect batteries. + PORTB &= ~((1<= RID[i].Low) { + if (ADCS.rawRID <= RID[i].High) { + BattData.Capacity = RID[i].Capacity; + BattData.MaxCurrent = RID[i].Icharge; + BattData.MaxTime = RID[i].tCutOff; + BattData.MinCurrent = RID[i].ICutOff; + + found = TRUE; + } + } + } + + // If no valid entry is found, use defaults and return FALSE. + if (!found) { + BattData.Capacity = DEF_BAT_CAPACITY; + BattData.MaxCurrent = DEF_BAT_CURRENT_MAX; + BattData.MaxTime = DEF_BAT_TIME_MAX; + BattData.MinCurrent = DEF_BAT_CURRENT_MIN; + } + + return(found); +} + + +/*! \brief Calculates temperature from a lookup table + * + * Looks up the highest NTC value below or equal to the measured one.\n + * With the current lookup table, temperature is calculated with the formula:\n + * 4*(index of entry) - 2*(measured NTC - NTC from entry) / (ADCsteps of entry) + * + * \note If the NTC-measurement is saturated, with the current lookup table, + * the temperature will be reported as -1 C. + * + * \note If no valid entry is found, battery temperature is set to 80. + */ +void NTCLookUp (void) +{ + unsigned char i; + unsigned char found = FALSE; + + // Lookup in the NTC-table. Use the first entry which is equal or below + // sampled NTC. Calculate temperature by using the index number, and the + // difference between the measured NTC value and the one in the entry. + for (i=0 ; (i < NTC_TABLE_SIZE) && (!found); i++) { + if (ADCS.rawNTC >= NTC[i].ADC) { + BattData.Temperature = (i<<2) ; + BattData.ADCSteps = NTC[i].ADCsteps; + BattData.Temperature -= ((ADCS.rawNTC - NTC[i].ADC)<<1) / BattData.ADCSteps; + + found = TRUE; // Could be done with a break, but that violates MISRA. + } + } + + // For safety, is temperature is greater than the NTC + if (!found) { + BattData.Temperature = 80; + } +} diff --git a/BaseTinyFirmware/IAR/battery.h b/BaseTinyFirmware/IAR/battery.h new file mode 100644 index 0000000..1fa428a --- /dev/null +++ b/BaseTinyFirmware/IAR/battery.h @@ -0,0 +1,113 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for battery.c + * + * Contains definitions for the setup of 1-Wire(R) and behaviour of the + * battery data and status refreshing functions.\n + * Also contains definitions of default battery data, and declarations + * for the RID and NTC lookup tables. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * Original author: \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/battery.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + + +#ifndef BATTERY_H +#define BATTERY_H + + +//****************************************************************************** +// Defines for EEPROM reading +//****************************************************************************** +#define OWIBUS OWI_PIN_0 //!< One-wire bus (pin). + +#define OW_NONE 0x00 //!< One-wire device family code. +#define OW_DS2505 0x09 //!< One-wire device family code. + +#define DS2505_MEM_READ 0xF0 //!< One-wire device command. +#define DS2505_STATUS_READ 0xAA //!< One-wire device command. +#define DS2505_DATA_READ 0xC3 //!< One-wire device command. + + +//****************************************************************************** +// RID-less charging (for BatteryStatusRefresh()) +//****************************************************************************** +//#define ALLOW_NO_RID //!< Use default battery data if no matching entry found. + +#define DEF_BAT_CAPACITY 0 //!< Default battery capacity, in mAh. +#define DEF_BAT_CURRENT_MAX 0 //!< Default maximum charge current, in mA. +#define DEF_BAT_TIME_MAX 0 //!< Default maximum charge time, in minutes. +//! Default minimum current to stop charge, in mA. +#define DEF_BAT_CURRENT_MIN 0 + + + +//****************************************************************************** +// RID and NTC defines and struct declarations +//****************************************************************************** +#define RID_TABLE_SIZE 4 //!< Number of entries in RID table. +#define NTC_TABLE_SIZE 20 //!< Number of entries in NTC table. + +//! \brief Struct for an entry in the resistor ID lookup-table +struct RID_Lookup_struct { + unsigned int Low; //!< Lowest acceptable ADC value. + unsigned int High; //!< Highest acceptable ADC value. + unsigned int Resistance; //!< RID resistance, in Ohms. + unsigned int Capacity; //!< Associated battery capacity, in mAh. + unsigned int Icharge; //!< Associated initial charge current, in mA. + unsigned int tCutOff; //!< Associated cut-off time, in minutes. + unsigned int ICutOff; //!< Associated cut-off current, in mA. +}; +typedef struct RID_Lookup_struct RID_Lookup_t; //!< For convenience. + +/*! \brief Struct for an entry in the NTC lookup-table + * + * \note Must be sorted in descending ADC order. + */ +struct NTC_Lookup_struct +{ + unsigned int ADC; //!< Measured NTC. + unsigned char ADCsteps; //!< ADC steps per half degree at this temperature. +}; +typedef struct NTC_Lookup_struct NTC_Lookup_t; //!< For convenience. + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern __eeprom Battery_t BattControl[]; +extern Batteries_t BattData; +extern __eeprom unsigned char BattEEPROM[][32]; +extern unsigned char BattActive; + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char BatteryCheck(void); +unsigned char BatteryStatusRefresh(void); +unsigned char BatteryDataRefresh(void); +void EnableBattery(unsigned char); +void DisableBatteries(void); +unsigned char RIDLookUp(void); +void NTCLookUp(void); + + +#endif // BATTERY_H diff --git a/BaseTinyFirmware/IAR/blue.GIF b/BaseTinyFirmware/IAR/blue.GIF new file mode 100644 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 index 0000000..3d387a5 --- /dev/null +++ b/BaseTinyFirmware/IAR/charge.h @@ -0,0 +1,38 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for NIMHcharge.c and LIIONcharge.c + * + * Contains definitions and declarations related to the charge state. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/charge.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef CHARGE_H +#define CHARGE_H + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char Charge(unsigned char inp); + + +#endif // CHARGE_H diff --git a/BaseTinyFirmware/IAR/chargefunc.c b/BaseTinyFirmware/IAR/chargefunc.c new file mode 100644 index 0000000..f620f70 --- /dev/null +++ b/BaseTinyFirmware/IAR/chargefunc.c @@ -0,0 +1,361 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Charge functions + * + * Contains the functions for charging with constant current and voltage, + * and for deciding when to halt. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "enums.h" +#include "structs.h" + +#include "ADC.h" +#include "battery.h" +#include "chargefunc.h" +#include "main.h" +#include "menu.h" +#include "PWM.h" +#include "statefunc.h" +#include "time.h" + +#ifdef NIMH +#include "NIMHspecs.h" +#endif // NIMH + +#ifdef LIION +#include "LIIONspecs.h" +#endif // LIION + + +//****************************************************************************** +// Variables +//****************************************************************************** +//! Struct that holds parameters for ConstantCurrent() and ConstantVoltage(). +ChargeParameters_t ChargeParameters; + +//! Struct that holds parameters for HaltNow(). +HaltParameters_t HaltParameters; + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Charges battery with a constant current. + * + * This function applies a constant current (set in ChargeParameters.Current) + * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + * The charge current can vary with +/- \ref BAT_CURRENT_HYST.\n + * If the Master inhibits charging, timers are stopped and PWM output dropped. + * Once the battery is no longer flagged for charge inhibit, timers are + * started again and charging resumed. + * + * \retval ChargeParameters.NextState Next state once this stage is done. + * If no errors occured, this will be whatever was set in Charge(). Otherwise, + * HaltNow() will have set a new next state. + */ +unsigned char ConstantCurrent(void) +{ + unsigned char error = FALSE, + wasStopped = FALSE; + + do { + // Wait for ADC conversions to complete. + ADC_Wait(); + + // If Master has flagged for a charge inhibit, pause charging. + // (This is to prevent damage during prolonged serial communication.) + if (BattControl[BattActive].ChargeInhibit) { + wasStopped = TRUE; + Time_Stop(); + OCR1B = 0; + } else { + // Continue charging! + if (wasStopped) { + wasStopped = FALSE; + + // Timer variables are not reset by this. + Time_Start(); + } + + // Adjust the charge current to within ChargeParameters.Current + // +/- BAT_CURRENT_HYST. + if ((ADCS.avgIBAT < 0) || + (ADCS.avgIBAT < (ChargeParameters.Current - BAT_CURRENT_HYST))) { + + if(!PWM_IncrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MAX + // If the duty cycle cannot be incremented, flag error and + // go to error state. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } else if ((ADCS.avgIBAT >= 0) && + (ADCS.avgIBAT > (ChargeParameters.Current + BAT_CURRENT_HYST))) { + + if(!PWM_DecrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MIN + // If the duty cycle cannot be decremented, flag error and + // go to error state. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } + } + } while ((!HaltNow()) && (!error)); + + // Return the next state to Charge(). If an error has occured, this will + // point to some other state than the next state of charging. + return(ChargeParameters.NextState); +} + + +/*! \brief Charges battery with a constant voltage + * + * This function applies a constant voltage (set in ChargeParameters.Voltage) + * to the battery until HaltNow() returns TRUE, or a PWM error occurs and + * \ref ABORT_IF_PWM_MIN or \ref ABORT_IF_PWM_MAX is defined.\n + * The charge voltage can vary with +/- \ref BAT_VOLTAGE_HYST.\n + * If the Master inhibits charging, timers are stopped and PWM output dropped. + * Once the battery is no longer flagged for charge inhibit, timers are + * started again and charging resumed. + * + * \retval ChargeParameters.NextState Next state once this stage is done. + * If no errors occured, this will be whatever was set in Charge(). Otherwise, + * HaltNow() will have set a new next state. + */ +unsigned char ConstantVoltage(void) +{ + unsigned char error = FALSE, + wasStopped = FALSE; + + do{ + + // Wait for ADC conversions to complete. + ADC_Wait(); + + // If Master has flagged for a charge inhibit, pause charging. + // (This is to prevent damage during prolonged serial communication.) + if (BattControl[BattActive].ChargeInhibit) { + wasStopped = TRUE; + Time_Stop(); + OCR1B = 0; + } + + else { + // Continue charging! + if (wasStopped) { + wasStopped = FALSE; + + // Timer variables aren't reset by this. + Time_Start(); + } + + // Adjust the charge voltage to within ChargeParameters.Voltage + // +/- BAT_VOLTAGE_HYST. + if (ADCS.VBAT < (ChargeParameters.Voltage - BAT_VOLTAGE_HYST)) { + + if(!PWM_IncrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MAX + // Flag PWM control error and go to error-state if the duty + // cycle cannot be incremented. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } else if (ADCS.VBAT > (ChargeParameters.Voltage + BAT_VOLTAGE_HYST)) { + + if(!PWM_DecrementDutyCycle()) { +#ifdef ABORT_IF_PWM_MIN + // Flag PWM control error and go to error-state if duty + // cycle cannot be decremented. + SetErrorFlag(ERR_PWM_CONTROL); + ChargeParameters.NextState = ST_ERROR; + error = TRUE; +#endif + } + } + } + + } while ((!HaltNow()) && (!error)); + + // Return the next state to Charge(). If an error has occured, this will + // point to some other state than the next state of charging. + return(ChargeParameters.NextState); +} + + +/*! \brief Determines when to halt charging. + * + * This function evaluates parameters depending on what has been flagged in + * HaltParameters.HaltFlags, and returns TRUE or FALSE if the charging should + * halt or not.\n + * In addition, error flagging on timeout (battery exhaustion) can be set.\n + * + * The function also checks if the battery temperature is within limits, + * if mains is OK, and if BatteryCheck() returns TRUE. + * If an error is detected, the associated errorflag is set and + * ChargeParameters.NextState is changed to an appropriate state. + * + * \retval TRUE Halt now. + * \retval FALSE Don't halt now. + * + * \note See chargefunc.h for definitions of halt flags. + * \note It is generally a bad idea not to halt on a timeout. + * \note If HALT_ON_VOLTAGE_DROP is set, HaltParameters.VBATMax should be + * reset in Charge() before calling a charging-function. + * + * \todo "Priorities" of standard error checks OK? + */ +unsigned char HaltNow(void) +{ + unsigned char i, halt = FALSE; + + // Wait for a full ADC-cycle to finish. + ADC_Wait(); + + // Evaluate ADC readings according to HaltFlags. Flag errors if selected. + // If an error is flagged, ChargeParameters.NextState is set to ST_ERROR. + // (Gets overridden if either mains is failing, or the battery changes.) + for (i = 0x01; i != 0; i <<= 1) { + if (HaltParameters.HaltFlags & i) { + switch (i) { + // Is VBAT less than the recorded maximum? + case HALT_VOLTAGE_DROP: + + // Update VBATMax if VBAT is higher. Evaluate for halt otherwise. + if (ADCS.VBAT > HaltParameters.VBATMax) { + HaltParameters.VBATMax = ADCS.VBAT; + } else if((HaltParameters.VBATMax - ADCS.VBAT) >= + HaltParameters.VoltageDrop) { + halt = TRUE; + } + break; + + + // Has VBAT reached the maximum limit? + case HALT_VOLTAGE_MAX: + + if (ADCS.VBAT >= HaltParameters.VoltageMax) { + halt = TRUE; + } + break; + + + // Has IBAT reached the minimum limit? + case HALT_CURRENT_MIN: + + if (ADCS.avgIBAT <= HaltParameters.CurrentMin) { + halt = TRUE; + } + break; + + + // Is the temperature rising too fast? + case HALT_TEMPERATURE_RISE: + + // If rawNTC has increased, the temperature has dropped. + // We can store this value for now, and start the timer. + // Otherwise, check if NTC has changed too fast. + if (ADCS.rawNTC > HaltParameters.LastNTC) { + HaltParameters.LastNTC = ADCS.rawNTC; + Time_Set(TIMER_TEMP,0,30,0); + + // Is the increase in temperature greater than the set threshold? + } else if ((HaltParameters.LastNTC - ADCS.rawNTC) >= + (BattData.ADCSteps * HaltParameters.TemperatureRise)) { + + // If this happened within a timeframe of 30 seconds, the + // temperature is rising faster than we want. + // If not, update LastNTC and reset timer. + if (Time_Left(TIMER_TEMP)) { + halt = TRUE; + } else { + HaltParameters.LastNTC = ADCS.rawNTC; + Time_Set(TIMER_TEMP,0,30,0); + } + } + break; + + + // Is there any time left? + case HALT_TIME: + + if (!Time_Left(TIMER_CHG)) { + halt = TRUE; + + // If exhaustion flagging is selected, stop the PWM, disable the + // battery and flag it as exhausted. Make ST_ERROR next state. + if (HaltParameters.HaltFlags & HALT_FLAG_EXHAUSTION) { + PWM_Stop(); + BattControl[BattActive].Enabled = FALSE; + BattData.Exhausted = TRUE; + SetErrorFlag(ERR_BATTERY_EXHAUSTED); + ChargeParameters.NextState = ST_ERROR; + } + } + break; + + + default: // Shouldn't end up here, but is needed for MISRA compliance. + break; + } + } + } + + // Standard checks: + + // Battery too cold or hot? + if ((BattData.Temperature <= HaltParameters.TemperatureMin) || + (BattData.Temperature >= HaltParameters.TemperatureMax)) { + + PWM_Stop(); + SetErrorFlag(ERR_BATTERY_TEMPERATURE); + ChargeParameters.NextState = ST_ERROR; + halt = TRUE; + } + + // Battery not OK? + if (!BatteryCheck()) { + PWM_Stop(); + ChargeParameters.NextState = ST_INIT; + halt = TRUE; + } + + // Is mains voltage OK? + if (!ADCS.Mains) { + PWM_Stop(); + ChargeParameters.NextState = ST_SLEEP; + halt = TRUE; + } + + return(halt); +} diff --git a/BaseTinyFirmware/IAR/chargefunc.h b/BaseTinyFirmware/IAR/chargefunc.h new file mode 100644 index 0000000..88ac473 --- /dev/null +++ b/BaseTinyFirmware/IAR/chargefunc.h @@ -0,0 +1,134 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for chargefunc.c + * + * Contains definitions to decide PWM error handling and of halt flags, + * and declarations of parameter structs for charging. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/chargefunc.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef CHARGEFUNC_H +#define CHARGEFUNC_H + + +//****************************************************************************** +// PWM error handling +//****************************************************************************** +//! Report error if maximum duty cycle doesn't give a sufficient charge current. +#define ABORT_IF_PWM_MAX + +//! Report error if minimum duty cycle gives a too great charge current. +#define ABORT_IF_PWM_MIN + + +//****************************************************************************** +// Definitions for HaltFlags +//****************************************************************************** +//! Halt if VBAT drops more than the set limit. +#define HALT_VOLTAGE_DROP 0x01 + +//! Halt if VBAT reaches the set maximum. +#define HALT_VOLTAGE_MAX 0x02 + +//! Halt if avgIBAT goes below the set minimum. +#define HALT_CURRENT_MIN 0x04 + +//! Halt if BattData.Temperature rises quicker than the set maximum. +#define HALT_TEMPERATURE_RISE 0x08 + +//! Halt if TIMER_CHG runs out. +#define HALT_TIME 0x10 + +//! Flag battery as exhausted if timeout occurs. +#define HALT_FLAG_EXHAUSTION 0x20 + + +//****************************************************************************** +// Parameter struct for charging +//****************************************************************************** +/*! \brief Holds the parameters for ConstantCurrent() and ConstantVoltage(). + * + */ +struct ChargeParameters_struct { + unsigned int Voltage; //!< Voltage to charge with. + unsigned int Current; //!< Current to charge with. + unsigned char NextState; //!< \brief Next state once charge stage finishes. + //!< \note Set in Charge(), but may be changed by + //!< HaltNow() if an error occurs! +}; +typedef struct ChargeParameters_struct ChargeParameters_t; + + +//****************************************************************************** +// Parameter struct for HaltNow() +//****************************************************************************** +/*! \brief Holds the parameters for HaltNow(); + * + */ +struct HaltParameters_struct { + //! \brief Contains flags for what to evaluate. + //! \note See chargefunc.h for definitions of flags. + unsigned char HaltFlags; + + //! Maximum drop in voltage before halting, in mV. + unsigned int VoltageDrop; + + //! Maximum limit for output voltage, in mV. + unsigned int VoltageMax; + + //! Minimum limit for output current, in mA. + unsigned int CurrentMin; + + //! Maximum limit for battery temperature, in degrees centigrade. + unsigned int TemperatureMax; + + //! Minimum limit for battery temperature, in degrees centigrade. + signed int TemperatureMin; + + //! Maximum limit for temperature to rise, in degrees centigrade per minute. + unsigned int TemperatureRise; + + //! \brief Contains highest VBAT measured, used to calculate voltage drop. + //! \note Must be manually reset. + unsigned int VBATMax; + + //! Used to detect temperature rise. + unsigned int LastNTC; +}; +typedef struct HaltParameters_struct HaltParameters_t; + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern ChargeParameters_t ChargeParameters; +extern HaltParameters_t HaltParameters; + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char ConstantCurrent(void); +unsigned char ConstantVoltage(void); +unsigned char HaltNow(void); + +#endif // CHARGEFUNC_H diff --git a/BaseTinyFirmware/IAR/config_AVR458.doxygen b/BaseTinyFirmware/IAR/config_AVR458.doxygen new file mode 100644 index 0000000..2e5419c --- /dev/null +++ b/BaseTinyFirmware/IAR/config_AVR458.doxygen @@ -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 = "Atmel AVR Application Notes" +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 index 0000000..5ab35da --- /dev/null +++ b/BaseTinyFirmware/IAR/config_AVR463.doxygen @@ -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 = "Atmel AVR Application Notes" +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 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 index 0000000..b8c92c5 --- /dev/null +++ b/BaseTinyFirmware/IAR/enums.h @@ -0,0 +1,56 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Enums in common for Slave and Master + * + * Contains enumerations of timers and variable specifiers for + * time.c and USI.c.\n + * These are also used in the Master, and have therefore been + * put in a separate file for convenience. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/enums.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef ENUMS_H +#define ENUMS_H + +//****************************************************************************** +// Variable specifiers (for Master-Slave communication) +//****************************************************************************** +enum { + ADR_ADCS = 1, //!< Indicates that ADCS is read/write target. + ADR_BATTACTIVE, //!< Indicates that BattActive is read/write target. + ADR_BATTDATA, //!< Indicates that BattData is read/write target. + ADR_BATTCTRL, //!< Indicates that BattControl is read/write target. + ADR_TIMERS //!< Indicates that timeval is read/write target. +}; + + +//****************************************************************************** +// Timers +//****************************************************************************** +enum { + TIMER_USI = 0, //!< Timer meant for USI. + TIMER_CHG, //!< Timer meant for charging. + TIMER_GEN, //!< Timer meant for general use. + TIMER_TEMP, //!< Timer meant for timing of temperature rise. + TIMERS //!< Number of timers used. +}; + +#endif // ENUMS_H diff --git a/BaseTinyFirmware/IAR/main.c b/BaseTinyFirmware/IAR/main.c new file mode 100644 index 0000000..941f779 --- /dev/null +++ b/BaseTinyFirmware/IAR/main.c @@ -0,0 +1,212 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Main program file + * + * Contains the main program, which is a basic state machine. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2302 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.c $ + * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +/*! \page License + * Copyright (c) 2007, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL ``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 EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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. + */ + +#include +#include +#include + +#include "structs.h" + +#include "main.h" +#include "ADC.h" +#include "statefunc.h" +#include "battery.h" +#include "menu.h" +#include "OWI.h" +#include "PWM.h" +#include "time.h" +#include "USI.h" + + + +//****************************************************************************** +// Globals +//****************************************************************************** +unsigned char CurrentState; //!< \brief Global that indicates current state + //!< + //!< Updated by main(). + //!< \note See menu.h for definition of states. + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Main program + * + * The main function goes into an infinite loop, keeping track of the current + * state and the next one. If the next state is different from the current, it + * looks up the address to the next state function, in \ref menu_state[], and + * updates \ref CurrentState. The state function is then called and will + * eventually return a new state, and so the loop reiterates. + * + * \todo The variable inp is passed to all state functions, but is not used + * for anything yet. Remove? + */ +int main( void ) +{ + unsigned char nextstate, inp, i; + unsigned char (*pStateFunc)(unsigned char); // Function pointer. + + // Initialize local state variables. + inp = ZERO; + CurrentState = nextstate = ST_INIT; + pStateFunc = NULL; + + // Look for function associated with current state, get its address. + for (i = 0; menu_state[i].state != 0; i++) { + if (menu_state[i].state == CurrentState) { + pStateFunc = menu_state[i].pFunc; + } + } + + while (TRUE) { + // Run function associated with current state, get next state in return. + if (pStateFunc != NULL){ + nextstate = pStateFunc(inp); + } + + // Look up function for next state, if it differs from the current. + if (nextstate != CurrentState) { + CurrentState = nextstate; + for ( i = 0; menu_state[i].state != 0; i++) { + if (menu_state[i].state == CurrentState) { + pStateFunc = menu_state[i].pFunc; + } + } + } + } +} + + +/* Doxygen documentation mainpage ********************************************/ +/*! \mainpage + * \section intro Introduction + * This documents the software for application note AVR458. This is a charger + * for Li-Ion batteries, based on ATAVRBC100. + * + * \section compinfo Compilation Info + * This software was compiled with IAR Embedded Workbench, 4.30. To use GCC + * the source have to be modified.\n + * \n + * To make project on IAR EWAVR:\n + * Add the .c files to project (ADC.c, battery.c, main.c, menu.c, + * OWI.c, PWM.c, time.c and USI.c). Add either LIIONcharge.c or NIMHcharge.c, + * and update LIIONspecs.h or NIMHspecs.h, and battery.h with the appropriate + * battery data if needed.\n + * \n + * Use device --cpu=tiny861, enable bit definitions in I/O include files, + * optimization low for debug target and high for release, output format: ubrof8 + * for Debug and intel_extended for Release. \n + * + * \section deviceinfo Device Info + * This application is based on the ATtiny 861, but it is possible to migrate + * the design to other AVR microcontrollers, such as pin-compatible devices + * ATtiny 261/461. Low pin count devices such as ATtiny 25/45/85 may also be + * used, but with reduced functionality. + * + * Required fuse bit settings: + *
+ *    FUSE BIT  | SETTING
+ *    ----------+--------------------
+ *    CKDIV8    | 1 (unprogrammed)
+ *    CKSEL3..0 | 0010 (internal osc)
+ *    
+ * + * + * \section todo To Do-list + * \todo + * - Finalize master-slave communication protocol + * - Implement discharge mode + * + * \section contactinfo Contact Info + * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n + * For application notes visit + * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n + * Support mail: avr@atmel.com + */ + + +/*! \page misra MISRA C rule violations + * + * \par Rule 1 + * "All code shall conform to ISO 9899 standard C, with no extensions + * permitted." + * + * Extensions are necessary because ISO C has no way of specifying that a + * function should be an interrupt service routine, or that we would like data + * members to be stored in f.ex. EEPROM. + * + * + * \par Rule 37 + * "Bitwise operations shall not be performed on signed integer types." + * + * The compiler assumes all the 1's we shift around to make bitmasks are signed + * integers. Specifying them all to be (unsigned int), either directly or via a + * definition, would fix the rule violations, but also reduce code readability. + * + * + * \par Rule 45 + * "Type casting from any type to or from pointers shall not be used." + * + * Assigning macro NULL, defined in stdlib.h, to a pointer causes this.. + * + * + * \par Rule 96 + * "In the definition of a function-like macro the whole definition, and each + * instance of a parameter, shall be enclosed in parentheses." + * + * It is difficult to use parentheses with void function-like macros. + */ diff --git a/BaseTinyFirmware/IAR/main.h b/BaseTinyFirmware/IAR/main.h new file mode 100644 index 0000000..31aefa2 --- /dev/null +++ b/BaseTinyFirmware/IAR/main.h @@ -0,0 +1,61 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for main.c + * + * Contains some basic definitions (FALSE, TRUE, ZERO) as well as + * what battery type (NiMh or Li-Ion) the charger is for. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2302 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/main.h $ + * $Date: 2007-08-23 14:57:36 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#ifndef _MAIN_H +#define _MAIN_H + + +//****************************************************************************** +// Firmware revision +//****************************************************************************** +#define SWHIGH 1 +#define SWLOW 0 + + +//****************************************************************************** +// Battery type (add appropriate *charge.c to project!) +//****************************************************************************** +#define NIMH //!< Use specs and state menu for NIMH. +//#define LIION //!< Use specs and state menu for LIION. + + +//****************************************************************************** +// Basic definitions +//****************************************************************************** +#define FALSE 0 //!< We have to define this ourselves. +#define TRUE (!FALSE) //!< We have to define this ourselves. +#define ZERO 0 //!< We have to define this ourselves. + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern unsigned char CurrentState; + + +#endif //_MAIN_H diff --git a/BaseTinyFirmware/IAR/menu.c b/BaseTinyFirmware/IAR/menu.c new file mode 100644 index 0000000..f8995ec --- /dev/null +++ b/BaseTinyFirmware/IAR/menu.c @@ -0,0 +1,79 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * State menu definition + * + * Contains the definition of the state menu.\n + * The state menu contains all states and adresses to associated functions. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include + +#include "statefunc.h" +#include "charge.h" +#include "main.h" +#include "menu.h" + + +//****************************************************************************** +// State menu (relies on the proper battery type to be defined in main.h!) +//****************************************************************************** +#ifdef NIMH +/*! \brief The state menu + * + * Contains all the defined states and addresses to their associated functions. + */ +__flash const MENU_STATE_t menu_state[] = { +// State State function + { ST_INIT, Initialize}, + { ST_BATCON, BatteryControl}, + { ST_PREQUAL, Charge}, + { ST_SLEEP, Sleep}, + { ST_FASTCHARGE, Charge}, + { ST_LOWRATECHARGE, Charge}, + { ST_ENDCHARGE, Charge}, + { ST_DISCHARGE, Discharge}, + { ST_ERROR, Error}, + { 0, NULL}, +}; +#endif // NIMH + +#ifdef LIION +/*! \brief The state menu + * + * Contains all the defined states and addresses to their associated functions. + */ +__flash const MENU_STATE_t menu_state[] = { +// State State function + { ST_INIT, Initialize}, + { ST_BATCON, BatteryControl}, + { ST_PREQUAL, Charge}, + { ST_SLEEP, Sleep}, + { ST_CCURRENT, Charge}, + { ST_CVOLTAGE, Charge}, + { ST_ENDCHARGE, Charge}, + { ST_DISCHARGE, Discharge}, + { ST_ERROR, Error}, + { 0, NULL}, +}; +#endif // LIION diff --git a/BaseTinyFirmware/IAR/menu.h b/BaseTinyFirmware/IAR/menu.h new file mode 100644 index 0000000..9070cd8 --- /dev/null +++ b/BaseTinyFirmware/IAR/menu.h @@ -0,0 +1,70 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for menu.c + * + * Contains definitions of each state and declaration of the state + * menu entry struct. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/menu.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef MENU_H +#define MENU_H + +//****************************************************************************** +// State machine states +//****************************************************************************** +// State machine states -- max size and number of states is 255. +// State values must be larger than zero +#define ST_INIT (10) //!< Identifies initialization state. +#define ST_BATCON (20) //!< Identifies battery control state. +#define ST_PREQUAL (30) //!< Identifies prequalification state. +#define ST_SLEEP (40) //!< Identifies sleep state. +#define ST_FASTCHARGE (50) //!< Identifies fast charge state. +#define ST_LOWRATECHARGE (60) //!< Identifies trickle charge state. +#define ST_ENDCHARGE (70) //!< Identifies end of charge. +#define ST_DISCHARGE (80) //!< Identifies discharge state. +#define ST_ERROR (90) //!< Identifies error state. +#define ST_CCURRENT (100) //!< Identifies constant current charge state. +#define ST_CVOLTAGE (110) //!< Identifies constant voltage charge state. + + +//****************************************************************************** +// Struct declarations +//****************************************************************************** +/*! \brief Holds an entry in the state menu + * + * Contains the ID number of a state, and a pointer to its associated function + */ +struct MENU_STATE_struct +{ + unsigned char state; //!< ID number of state. + unsigned char (*pFunc)(unsigned char inp); //!< Associated function. +}; +typedef struct MENU_STATE_struct MENU_STATE_t; //!< For convenience. + + +//****************************************************************************** +// Global variables +//****************************************************************************** +extern __flash const MENU_STATE_t menu_state[]; + +#endif // MENU_H diff --git a/BaseTinyFirmware/IAR/readme_AVR458.html b/BaseTinyFirmware/IAR/readme_AVR458.html new file mode 100644 index 0000000..7e82c9e --- /dev/null +++ b/BaseTinyFirmware/IAR/readme_AVR458.html @@ -0,0 +1,58 @@ + + + + +ATMEL AVR Doxygen Documentation + + + + + + + + + + + + + + + + + + + + +



+

+ + AVR458: Charging Li-Ion Batteries with BC100 + +

+
+ + 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. +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. + +
+ +

Code documentation

+ +
+
+ Disclaimer: 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. EXCEPT AS SET FORTH IN ATMEL’S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL’S 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. 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’s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.
+
+ © 2006 Atmel Corporation. All rights reserved. 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.
+ + diff --git a/BaseTinyFirmware/IAR/readme_AVR463.html b/BaseTinyFirmware/IAR/readme_AVR463.html new file mode 100644 index 0000000..523775a --- /dev/null +++ b/BaseTinyFirmware/IAR/readme_AVR463.html @@ -0,0 +1,58 @@ + + + + +ATMEL AVR Doxygen Documentation + + + + + + + + + + + + + + + + + + + + +



+

+ + AVR458: Charging Li-Ion Batteries with BC100 + +

+
+ +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. +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. + +
+ +

Code documentation

+ +
+
+ Disclaimer: 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. EXCEPT AS SET FORTH IN ATMEL’S TERMS AND CONDITIONS OF SALE LOCATED ON ATMEL’S 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. 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’s products are not intended, authorized, or warranted for use as components in applications intended to support or sustain life.
+
+ © 2006 Atmel Corporation. All rights reserved. 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.
+ + diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.cspy.bat b/BaseTinyFirmware/IAR/settings/BC100_tiny.cspy.bat new file mode 100644 index 0000000..7e4fce5 --- /dev/null +++ b/BaseTinyFirmware/IAR/settings/BC100_tiny.cspy.bat @@ -0,0 +1,32 @@ +@REM This bat file has been generated by the IAR Embeddded Workbench +@REM C-SPY interactive debugger,as an aid to preparing a command +@REM line for running the cspybat command line utility with the +@REM appropriate settings. +@REM +@REM After making some adjustments to this file, you can launch cspybat +@REM by typing the name of this file followed by the name of the debug +@REM file (usually an ubrof file). Note that this file is generated +@REM every time a new debug session is initialized, so you may want to +@REM move or rename the file before making changes. +@REM +@REM Note: some command line arguments cannot be properly generated +@REM by this process. Specifically, the plugin which is responsible +@REM for the Terminal I/O window (and other C runtime functionality) +@REM comes in a special version for cspybat, and the name of that +@REM plugin dll is not known when generating this file. It resides in +@REM the $TOOLKIT_DIR$\bin folder and is usually called XXXbat.dll or +@REM XXXlibsupportbat.dll, where XXX is the name of the corresponding +@REM tool chain. Replace the '' parameter +@REM below with the appropriate file name. Other plugins loaded by +@REM C-SPY are usually not needed by, or will not work in, cspybat +@REM but they are listed at the end of this file for reference. + + +"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\" --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" + + +@REM Loaded plugins: +@REM avrlibsupport.dll +@REM C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\plugins\CodeCoverage\CodeCoverage.dll +@REM C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\plugins\Profiling\Profiling.dll +@REM C:\Program Files\IAR Systems\Embedded Workbench 4.0\common\plugins\stack\stack.dll diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.dbgdt b/BaseTinyFirmware/IAR/settings/BC100_tiny.dbgdt new file mode 100644 index 0000000..33f4649 --- /dev/null +++ b/BaseTinyFirmware/IAR/settings/BC100_tiny.dbgdt @@ -0,0 +1,5 @@ + + + + + diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.dni b/BaseTinyFirmware/IAR/settings/BC100_tiny.dni new file mode 100644 index 0000000..240a111 --- /dev/null +++ b/BaseTinyFirmware/IAR/settings/BC100_tiny.dni @@ -0,0 +1,15 @@ +[StackPlugin] +Enabled=1 +OverflowWarningsEnabled=1 +WarningThreshold=90 +SpWarningsEnabled=1 +WarnHow=1 +UseTrigger=1 +TriggerName=main +LimitSize=0 +ByteLimit=50 +[Breakpoints] +Count=0 +[TraceHelper] +Enabled=0 +ShowSource=1 diff --git a/BaseTinyFirmware/IAR/settings/BC100_tiny.wsdt b/BaseTinyFirmware/IAR/settings/BC100_tiny.wsdt new file mode 100644 index 0000000..07c1d5c --- /dev/null +++ b/BaseTinyFirmware/IAR/settings/BC100_tiny.wsdt @@ -0,0 +1,56 @@ + + + + + + BC100_tiny/Release + + + + + + + + + 330272727 + + + + + + + 300Find-in-Files1677319448 + 300Build35050601 + + + + + + + TabID-30516-32580 + Workspace + Workspace + + + BC100_tinyBC100_tiny/OutputBC100_tiny/chargefunc.cBC100_tiny/chargefunc.c/Output + + + + 0TabID-27761-22755Find in FilesFind-in-FilesTabID-13095-16835BuildBuild1 + + + + + + TextEditorC:\home\kevin\pub\src\bc100\IAR\chargefunc.c018064076407TextEditorC:\home\kevin\pub\src\bc100\IAR\time.c05023752375TextEditorC:\home\kevin\pub\src\bc100\IAR\time.h0015471547TextEditorC:\home\kevin\pub\src\bc100\IAR\Release\List\BC100_tiny.map02034102104102104TextEditorC:\home\kevin\pub\src\bc100\IAR\Release\List\chargefunc.lst01219296929640100000010000001 + + + + + + + iaridepm.enu1-2-2912404-2-2307268159896231034211458787931-2-22031922-2-219242051002083176724125000176724 + + + + diff --git a/BaseTinyFirmware/IAR/statefunc.c b/BaseTinyFirmware/IAR/statefunc.c new file mode 100644 index 0000000..e34994f --- /dev/null +++ b/BaseTinyFirmware/IAR/statefunc.c @@ -0,0 +1,421 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * State functions + * + * Contains the functions related to the states defined in menu.h.\n + * Also contains related functions, i.e. for checking jumpers, setting + * error flags and "dozing". + * + * \note The state function Charge() is in a separate file since it + * should easily be changed with regard to battery type. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include +#include + +#include "structs.h" +#include "enums.h" + +#include "ADC.h" +#include "statefunc.h" +#include "battery.h" +#include "charge.h" +#include "main.h" +#include "menu.h" +#include "OWI.h" +#include "PWM.h" +#include "time.h" +#include "USI.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +unsigned char ErrorFlags; //!< \brief Holds error flags. + //!< \note See statefunc.h for definitions of flags. + +//! \brief Holds the state in which latest error flag was set. +//! \note See menu.h for definitions of states. +unsigned char ErrorState; + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Initialization + * + * - Sets the system clock prescaler to 1 (run at 8 MHz) + * - Initializes the one-wire interface + * - Clears on-chip EEPROM + * - Sets battery enable pins as outputs, then disables batteries + * - Initializes SPI according to \ref SPIMODE + * - Initializes ADC + * - Initializes timers + * - Reads battery data from both battery inputs (via ADC) + * - Disables batteries again + * - Sets battery A as the current one (\ref BattActive = 0) + * - Clears ErrorFlags + * + * \param inp Not used. + * + * \retval ST_BATCON Next state in the sequence. + */ +unsigned char Initialize(unsigned char inp) +{ + unsigned char i, page; + + // Disable interrupts while setting prescaler. + __disable_interrupt(); + + CLKPR = (1< 8 MHz clock frequency. + + // Init 1-Wire(R) interface. + OWI_Init(OWIBUS); + + // Clear on-chip EEPROM. + for (page = 0; page < 4; page++) { + for (i = 0; i < 32; i++) { + BattEEPROM[page][i] = 0; + } + } + + DDRB = (1< check load and jumper J405 and J406. + if (abs(ADCS.IBAT) > 100) { + PWM_Stop(); + return(FALSE); + } + + // If the PWM output can't be increased high enough -> check jumpers + // J400-J404, J407 and J408. + if (!PWM_IncrementDutyCycle()) { + PWM_Stop(); + return(FALSE); + } + + // Wait for ADC conversions to complete + ADC_Wait(); + } while (Time_Left(TIMER_GEN)); + + + // If we end up here, the measurements took too long. + PWM_Stop(); + return(FALSE); +} diff --git a/BaseTinyFirmware/IAR/statefunc.h b/BaseTinyFirmware/IAR/statefunc.h new file mode 100644 index 0000000..9594f44 --- /dev/null +++ b/BaseTinyFirmware/IAR/statefunc.h @@ -0,0 +1,83 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Headerfile for statefunc.c + * + * Contains definitions for SPI mode and error identifiers. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/statefunc.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + +#ifndef STATEFUNC_H +#define STATEFUNC_H + + +//****************************************************************************** +// Wanted SPI-mode +//****************************************************************************** +//! Sample on leading _rising_ edge, setup on trailing _falling_ edge. +#define SPIMODE 0 + +//! Sample on leading _falling_ edge, setup on trailing _rising_ edge. +//#define SPIMODE 1 + + +//****************************************************************************** +// Typical and maximum voltage difference between supply and battery +//****************************************************************************** +//! Typical difference between VIN and VBAT, in mV. +#define VIN_VBAT_DIFF_TYP 600 + +//! Maximum allowed difference between VIN - VIN_VBAT_DIFF_TYP and VBAT, in mV. +#define VIN_VBAT_DIFF_MAX 500 + + +//****************************************************************************** +// Error-flag bit identifiers +//****************************************************************************** +//! Wrong jumper settings. +#define ERR_JUMPER_MISMATCH 0x01 + +//! Both batteries disabled. +#define ERR_NO_BATTERIES_ENABLED 0x02 + +//! PWM output too much/little. +#define ERR_PWM_CONTROL 0x04 + +//! Battery temperature out of limits. +#define ERR_BATTERY_TEMPERATURE 0x08 + +//! Battery couldn't be charged. +#define ERR_BATTERY_EXHAUSTED 0x10 + + +//****************************************************************************** +// Function prototypes +//****************************************************************************** +unsigned char Initialize(unsigned char); +unsigned char BatteryControl(unsigned char); +unsigned char Discharge(unsigned char); +unsigned char Sleep(unsigned char); +void Doze(void); +unsigned char Error(unsigned char); +void SetErrorFlag(unsigned char); +unsigned char JumperCheck(void); + +#endif // STATEFUNC_H diff --git a/BaseTinyFirmware/IAR/structs.h b/BaseTinyFirmware/IAR/structs.h new file mode 100644 index 0000000..9b80944 --- /dev/null +++ b/BaseTinyFirmware/IAR/structs.h @@ -0,0 +1,102 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Structs in common for Slave and Master + * + * Contains struct declarations for ADC.c and battery.c.\n + * These are also used in the Master, and have therefore been + * put in a separate file for convenience. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 + * + * \par Documentation: + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com \n + * + * $Name$ + * $Revision: 2261 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/structs.h $ + * $Date: 2007-08-10 09:28:35 +0200 (fr, 10 aug 2007) $\n + ******************************************************************************/ + + +#ifndef STRUCTS_H +#define STRUCTS_H + + +//****************************************************************************** +// Battery struct declarations +//****************************************************************************** +/*! \brief Holds status and various data for a battery + * + * These data are updated by BatteryStatusRefresh(), RIDLookUp(), + * NTCLookUp() and BatteryDataRefresh(). + */ +struct Batteries_struct +{ + unsigned char Present : 1; //!< Battery found. (TRUE/FALSE) + unsigned char Charged : 1; //!< Battery fully charged. (TRUE/FALSE) + unsigned char Low : 1; //!< Battery low voltage. (TRUE/FALSE) + unsigned char Exhausted : 1; //!< Battery exhausted. (TRUE/FALSE) + unsigned char HasRID : 1; //!< Battery has resistor ID. (TRUE/FALSE) + unsigned char Circuit; //!< Battery safety circuit (family id). + signed char Temperature; //!< Battery temperature, in centigrade. + unsigned char ADCSteps; //!< ADC steps per half degree. + unsigned int Capacity; //!< Capacity, in mAh. + unsigned int MaxCurrent; //!< Charge current, in mA. + unsigned int MaxTime; //!< Charge cut-off time, in minutes. + unsigned int MinCurrent; //!< Cut-off current, in mA. +}; +typedef struct Batteries_struct Batteries_t; //!< For convenience. + + +//! \brief Holds control data for a battery +struct Battery_struct +{ + //! Battery valid, enabling allowed. (TRUE/FALSE) + unsigned char Enabled : 1; + + //! Disconnect allowed. (TRUE/FALSE) + unsigned char DisconnectAllowed : 1; + + //! Inhibit charging. (TRUE/FALSE) \todo Changed by master? + unsigned char ChargeInhibit : 1; +}; +typedef struct Battery_struct Battery_t; //!< For convenience. + + +//****************************************************************************** +// ADC status struct declaration +//****************************************************************************** +/*! \brief Holds ADC-status and samples + * + * Is updated by ADC_ISR(). + */ +struct ADC_Status_struct +{ + unsigned char MUX : 5; //!< Corresponds to ADMUX low bits MUX4..0. + unsigned char Flag : 1; //!< ADC cycle complete (TRUE/FALSE). + unsigned char Mains : 1; //!< Mains OK? (TRUE/FALSE). + unsigned char Halt : 1; //!< Stop A/D-conversions (TRUE/FALSE). + unsigned char ADC3_G20_OS : 4; //!< Offset on ADC3 at 20x gain. + unsigned char ADC5_G20_OS : 4; //!< Offset on ADC5 at 20x gain. + unsigned int rawRID; //!< Raw, unconditioned resistor ID data. + unsigned int rawNTC; //!< Raw, unconditioned thermistor data. + unsigned int rawVBAT; //!< Raw, unconditioned battery voltage. + unsigned int VIN; //!< Supply voltage, in mV. + unsigned int VBAT; //!< Battery voltage, in mV. + signed int IBAT; //!< Battery current, in mA. + signed int discIBAT[4]; //!< Discrete battery current readings, in mA. + signed int avgIBAT; //!< Average of the last four IBAT readings, in mA. +}; +typedef struct ADC_Status_struct ADC_Status_t; //!< For convenience. + + +#endif // STRUCTS_H diff --git a/BaseTinyFirmware/IAR/time.c b/BaseTinyFirmware/IAR/time.c new file mode 100644 index 0000000..7017517 --- /dev/null +++ b/BaseTinyFirmware/IAR/time.c @@ -0,0 +1,162 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief + * Functions for timing + * + * Contains functions to initialize, set, poll and stop timers. + * + * \par Application note: + * AVR458: Charging Li-Ion Batteries with BC100 \n + * AVR463: Charging NiMH Batteries with BC100 + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * + * $Name$ + * $Revision: 2299 $ + * $RCSfile$ + * $URL: http://svn.norway.atmel.com/AppsAVR8/avr458_Charging_Li-Ion_Batteries_with_BC100/tag/20070904_release_1.0/code/IAR/time.c $ + * $Date: 2007-08-23 12:55:51 +0200 (to, 23 aug 2007) $\n + ******************************************************************************/ + +#include +#include + +#include "enums.h" + +#include "main.h" +#include "time.h" + + +//****************************************************************************** +// Variables +//****************************************************************************** +unsigned long timeval[TIMERS]; //!< Contains the values for each timer. + +// timer runs at 1 MHz and overflow will occur every 255 / 1 Mz ~= 0.25 ms +//#pragma vector = TIM0_OVF_vect + + +//****************************************************************************** +// Functions +//****************************************************************************** +/*! \brief Interrupt service routine for timer 0 overflow + * + * Timer 0 runs at 125 kHz and compare match will occur every millisecond + * (125 / 125 kHz = 1.0 ms), which will result in a call to this function. + * When called, this function will decrement the time left for each timer, + * unless they are already at zero. + */ +#pragma vector = TIM0_COMPA_vect +__interrupt void TICK_ISR(void) +{ + unsigned char i; + + // 1 ms has passed, decrement all non-zero timers. + for (i = 0; i < TIMERS; i++) { + if(timeval[i] > 0) { + timeval[i]--; + } + } +} + + +/*! \brief Checks if a specified timer has expired + * + * \param timer Specifies timer + * + * \retval TRUE Timer still going. + * \retval FALSE Timer has expired. + */ +unsigned char Time_Left(unsigned char timer) +{ + if(timeval[timer] > 0) { + return(TRUE); + } else { + return(FALSE); + } +} + + +/*! \brief Sets the specified timer + * + * \param timer Specifies timer + * \param min Minutes for timer to count down + * \param sec Seconds for timer to count down + * \param ms Milliseconds for timer to count down + */ +void Time_Set(unsigned char timer, unsigned int min, unsigned char sec, + unsigned char ms) +{ +// timeval[i] = 4 * (1000*(sec + 60*min) + ms); // about 4000 ticks per second +// timeval[i] = 240000 * (unsigned long)min; +// timeval[i] += 4000 * (unsigned long)sec; +// timeval[i] += 4 * (unsigned long)ms; + + timeval[timer] = 60000 * (unsigned long)min; + timeval[timer] += 1000 * (unsigned long)sec; + timeval[timer] += 1 * (unsigned long)ms; +} + + +/*! \brief Stops timers + * + * Sets timer0's clock source to none. + */ +void Time_Stop(void) +{ + TCCR0B = 0; +} + + +/*! \brief Starts timers + * + * Sets timer0's clock source to system clock divided by 64. + */ +void Time_Start(void) +{ + TCCR0B = (0< diff --git a/README b/README new file mode 100644 index 0000000..937e017 --- /dev/null +++ b/README @@ -0,0 +1,15 @@ +This project contains code for Atmel's BC100 development board. + +The initial code in this project is located in the BaseTinyFirmware +directory. That code is based on Atmel's original firmware for the +ATTiny controller on the BC100. + +Other firmware versions developed will be located in other +subdirectories and their contents will be listed in this file. + +The web site for future updates for this package is +http://www.avrcode.com/bc100/ + +Kevin Rosenberg +Fri, 14 Mar 2008 09:38:08 -0600 +