// ************************************************************************************************
///
/// \file 1wire_irq.c
///
/// TI (Benchmarq) BQ2023 1 Wire bus Battery Monitor functions
///
/// \par Created 23.10.2002
/// \date $LastChangedDate: 2006-12-20 21:50:05 +0100 (Mi, 20 Dez 2006) $
/// \version $Rev: 415 $
/// \author Udo Jakobza
/// \par Copyright
/// FTZ Leipzig; Wächterstraße 13; 04107 Leipzig
/// info@easytoweb.net
/// \par License
/// This library is free software; you can redistribute it and/or modify it
/// under the terms of the GNU Lesser General Public License as published by
/// the Free Software Foundation; either version 2.1 of the License, or
/// (at your option) any later version. This library is distributed in the hope
/// that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
/// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
/// See the GNU Lesser General Public License for more details.
/// see: http://www.gnu.org/copyleft/lesser.html
/// You should have received a copy of the GNU Lesser General Public License
/// along with this library; if not, write to the Free Software Foundation,
/// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/// Die Bibliothek ist freie Software; Sie dürfen sie unter den Bedingungen der
/// GNU Lesser General Public License, wie von der Free Software Foundation
/// veröffentlicht, weiterverteilen und/oder modifizieren; entweder gemäß
/// Version 2.1 der Lizenz oder (nach Ihrer Option) jeder späteren Version.
/// Diese Bibliothek wird in der Hoffnung weiterverbreitet, daß sie nützlich
/// sein wird, jedoch OHNE IRGENDEINE GARANTIE, auch ohne die implizierte
/// Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN ZWECK.
/// Mehr Details finden Sie in der GNU Lesser General Public License.
/// see: http://www.gnu.org/copyleft/lesser.de.html
/// Sie sollten eine Kopie der GNU Lesser General Public License zusammen mit
/// dieser Bibliothek erhalten haben; falls nicht, schreiben Sie an die FSF,
/// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
///
/// Annotation: If keywords are not substituted by subversion, add property to file.
/// see http://svnbook.red-bean.com/en/1.1/ch07s02.html#svn-ch-7-sect-2.3 for details
///
// ************************************************************************************************
#include
#include "elv_com.h"
// the 1 Wire bus is connected to PORTD
// the data signal is bit 7
#asm
.equ __w1_port=0x12
.equ __w1_bit=7
#endasm
// now you can include the 1 Wire Functions
#include "bq2023.h"
#include <1wire.h>
#pragma regalloc-
BQ2023_OVERFLOW bq2023_overflow={0, 0, 0, 0, 0};
unsigned int ccr_last=0;
unsigned int dcr_last=0;
// allocate SRAM space for the ROM codes & status bit vom 1-Wire
// MAX_1WIRE_DEVICES==8 - specify the maximum number of devices connected to the 1 Wire bus
unsigned char romcodes_1wire[1,9];
unsigned char *bq2023_romcode=0x0;
unsigned char bq2023_buffer[32];
eeprom unsigned long discharge_buffer[MAX_DISCHARGE_VALUE]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // buffer of discharge value of last 24 hours
eeprom unsigned char discharge_buffer_p=0; // pointer to buffer of discharge value
#ifdef BQ2023_DEBUG
unsigned int bq2023_error=0;
#endif
#pragma regalloc+
#ifdef BQ2023_IRQ // controls the use of disable and enable of global IRQ
#define W1_INIT() w1_init_irq()
#define W1_READ() w1_read_irq()
#define W1_WRITE(data) w1_write_irq(data)
#else
#define W1_INIT() w1_init()
#define W1_READ() w1_read()
#define W1_WRITE(data) w1_write(data)
#endif
unsigned char bq2023_overflow_check(void);
// **********************************************************************************
// Description : debug-frontend for BQ2023-functions
// Input : *command: pointer to command
// Output : 0: doesn't serve the command
// 1: serves the command
// Indication : none
// **********************************************************************************
unsigned char bq2023_do_cmd(unsigned char *command)
{
unsigned int Lva;
if(strncmpf(command, "bq2023-info", 8)==0)
{
bq2023_display_register();
return 1;
}
if(strncmpf(command, "bq2023-reset", 8)==0)
{
if(bq2023_init())
{
if(bq2023_reset(bq2023_romcode))
{
putsf("BQ2023-Reset\r");
return 1;
}
}
putsf("BQ2023 Error\r");
return 1;
}
if(strncmpf(command, "bq2023-prog", 8)==0)
{
if(bq2023_init())
{
Lva=0xbbaa;
if(bq2023_write_flash(bq2023_romcode,(unsigned char*)&Lva, 0x07, 2))
putsf("BQ2023-Flash\r");
return 1;
}
putsf("BQ2023 Error\r");
return 1;
}
if(strncmpf(command, "bq2023-data", 8)==0)
{
bq2023_display_data();
return 1;
}
if(strncmpf(command, "bq2023-backup", 8)==0)
{
bq2023_backup();
return 1;
}
return 0;
}
// ********************************************************************************
// Description : this function initializes the 1 Wire devices on the bus.
// Input : none
// Output : 1.) return==0x00 - 1wire device not present
// return==0x01 - 1wire device found
// Indication : 1Wire-Level
// *********************************************************************************
unsigned char w1_init_irq(void)
{
unsigned char Lva;
unsigned char sreg;
sreg=SREG;
#asm("cli");
Lva=w1_init();
SREG=sreg;
return Lva;
}
// ********************************************************************************
// Description : this function reads a byte from the 1 Wire bus.
// Input : none
// Output : 1.) data of 1wire device
// Indication : check with "W1_INIT" wether 1wire device is present
// 1Wire-Level
// *********************************************************************************
unsigned char w1_read_irq(void)
{
unsigned char Lva;
unsigned char sreg;
sreg=SREG;
#asm("cli");
Lva=w1_read();
SREG=sreg;
return Lva;
}
// ********************************************************************************
// Description : this function writes the byte data to the 1 Wire bus.
// Input : 1.) data - data to 1wire device
// Output : 1.) return==0x00 - 1wire write not ok
// return==0x01 - 1wire write ok
// Indication : check with "W1_INIT" wether 1wire device is present
// 1Wire-Level
// *********************************************************************************
unsigned char w1_write_irq(unsigned char data)
{
unsigned char Lva;
unsigned char sreg;
sreg=SREG;
#asm("cli");
Lva=w1_write(data);
SREG=sreg;
return Lva;
}
// ********************************************************************************
// Description : calculates with overflow-variables the discharge+time+temp
// Input : 1.) *buffer - pointer to >16 Byte-Array
// 2.) *temp - int varibale with temp-value in 4*x*Kelvin
// 3.) *discharge - long variable with discharge-value in µAh
// 4.) *time - long variable with time in second
// Output : 1.) return==0x00 - Error
// return!=0x00 - OK BQ2023 found
// Indication : BQ2023-Application-Level
// *********************************************************************************
unsigned char bq2023_discharge(unsigned char *buffer, signed int *temp,
unsigned long *discharge, unsigned long *time)
{
unsigned long Lva;
if(bq2023_init())
{
if(bq2023_read_all_register(bq2023_romcode, buffer, 0x100)) // reads last 16 Registers 0x100(Reserved) .. DCRH
{
if(temp!=NULL)
{
// read Temperatur
*temp=buffer[3];
*temp<<=8;
*temp|=buffer[2];
}
if(time!=NULL)
{
// read DTC - Discharge Time Count
*time=buffer[9]; // add HIGH-Part
*time<<=8;
*time|=buffer[8]; // add LOW-Part
*time=(*time*3600)/4096; // calculate seconds
Lva=57600; // seconds to overflow 16h * 3600
Lva*=bq2023_overflow.dtc_overflow; // overflow-counter for Discharge Time Counter
*time+=Lva;
}
if(discharge!=NULL)
{
// read DCR - Discharge Count Register
*discharge=0x100;
*discharge*=bq2023_overflow.dcr_overflow; // overflow-counter for Discharge Count Register
*discharge|=buffer[15]; // add HIGH-Part
*discharge<<=8;
*discharge|=buffer[14]; // add LOW-Part
if(*discharge>0xfffff)
{
*discharge/=100; // Measure-Resistor with 1.00 Ohm
*discharge*=305; // 3.05µV*h factor of discharge count
}
else
{
*discharge*=305; // 3.05µV*h factor of discharge count
*discharge/=100; // Measure-Resistor with 1.00 Ohm
}
}
return 1;
}
}
return 0;
}
// ********************************************************************************
// Description : calculates with overflow-variables the discharge+time+temp
// Input : 3.) *discharge - long variable with discharge-value in µAh in last 24hour
// 4.) *time - char variable with time in hour
// Output : none
// Indication : BQ2023-Application-Level
// *********************************************************************************
void bq2023_discharge24(unsigned long *discharge24, unsigned char *time)
{
unsigned char Lva, Lvb;
unsigned long first=0, last=0;
*time=0;
*discharge24=0;
Lvb=discharge_buffer_p;
Lvb--;
if(Lvb>=MAX_DISCHARGE_VALUE)
Lvb=MAX_DISCHARGE_VALUE-1; // starts with last value of buffer
if(discharge_buffer[Lvb]!=0)
last=discharge_buffer[Lvb];
for(Lva=0;Lva<(MAX_DISCHARGE_VALUE-1);Lva++)
{
Lvb--;
if(Lvb>=MAX_DISCHARGE_VALUE)
Lvb=MAX_DISCHARGE_VALUE-1; // starts with last value of buffer
if(discharge_buffer[Lvb]!=0)
{
first=discharge_buffer[Lvb];
*time+=1;
}
}
if(first!=0)
*discharge24=labs(last-first);
}
// ********************************************************************************
// Description : init the 1-wire-Interface and check BQ2023
// Input : none
// Output : 1.) return==0x01 - OK BQ2023 found
// return==0x00 - Error
// Indication : BQ2023-Application-Level
// *********************************************************************************
unsigned char bq2023_init(void)
{
unsigned long time;
unsigned char devices_1wire=0;
#ifdef BQ2023_IRQ // controls the use of disable and enable of global IRQ
unsigned char sreg;
#endif
if(bq2023_romcode!=0x00)
return 1;
#ifdef BQ2023_IRQ // controls the use of disable and enable of global IRQ
sreg=SREG;
#asm("cli");
#endif
devices_1wire=w1_search(0xf0, romcodes_1wire); // search all 1Wire-Devices
#ifdef BQ2023_IRQ // controls the use of disable and enable of global IRQ
SREG=sreg;
#endif
if(devices_1wire)
{
if(romcodes_1wire[0,0]==BQ2023_FAMILY_CODE) // found BQ2023
{
bq2023_overflow.ok=0;
if(bq2023_read_data(&romcodes_1wire[0,0], bq2023_buffer, RAM_START, RAM_SIZE)) // starts with address 0xe0
{
memcpy((unsigned char*)&bq2023_overflow, bq2023_buffer, OVERFLOW_SIZE);
bq2023_overflow.ok=1;
bq2023_romcode=&romcodes_1wire[0,0];
if(bq2023_discharge(bq2023_buffer, 0x0, 0x0, &time))
{
counter_10ms_32bit=100*time;
}
return 1;
}
}
}
return 0;
}
//#if funcused ds2430_reset
// ********************************************************************************
// Description : resets all register
// Input : 1.) *romcode - pointer to 9Byte-Array with ROM-number
// Output : 1.) return==0x01 - OK BQ2023 found
// return==0x00 - Error
// Indication : BQ2023-Application-Level
// *********************************************************************************
unsigned char bq2023_reset(unsigned char *romcode)
{
unsigned char buffer[OVERFLOW_SIZE]={0, 0, 0, 0, 0, 0};
// clear overflow-counter (DCR_OVERFLOW_8, CCR_OVERFLOW_8, DTC_OVERFLOW_16, CTC_OVERFLOW_16)
if(!bq2023_write_ram(romcode, buffer, OVERFLOW_START, OVERFLOW_SIZE))
return 0;
bq2023_error=0;
bq2023_overflow.dcr_overflow=0; // overflow-counter for Discharge Count Register
bq2023_overflow.ccr_overflow=0; // overflow-counter for Charge Count Register
bq2023_overflow.dtc_overflow=0; // overflow-counter for Discharge Time Counter
bq2023_overflow.ctc_overflow=0; // overflow-counter for Charge Time Counter
bq2023_overflow.ok=1;
ccr_last=0;
dcr_last=0;
return bq2023_write_register(romcode, CLR_STAT | CLR_CTC | CLR_DTC | CLR_SCR | CLR_CCR | CLR_DCR, CLR);
}
// **********************************************************************************
// Description : checks the BQ2023 overflow cyclic
// Input : none
// Output : none
// Indication : BQ2023-Application-Level
// **********************************************************************************
void bq2023_overflow_execute(void)
{
static unsigned long next_time_overflow=0;
static unsigned long next_time_discharge=0;
unsigned long discharge;
unsigned long time;
if(next_time_discharge==0)
{
next_time_overflow=counter_10ms_32bit+OVERFLOW_CHECK; // check every OVERFLOW_CHECK second
if(bq2023_discharge(bq2023_buffer, NULL, &discharge, &time))
{
discharge_buffer[discharge_buffer_p]=discharge; // first value of discharge buffer
discharge_buffer_p++; // pointer to buffer of discharge value
next_time_discharge=counter_10ms_32bit+DISCHARGE_CHECK;
}
return;
}
if(next_time_overflow=MAX_DISCHARGE_VALUE)
discharge_buffer_p=0;
}
}
}
// ********************************************************************************
// Description : checks the overflow-bits and expands the 16bit DCR- und CCR-Register
// Input : 1.) *romcode - pointer to 9Byte-Array with ROM-number
// Output : 1.) return==0x01 - OK BQ2023 found
// return==0x00 - Error
// Indication : BQ2023-Application-Level
// *********************************************************************************
unsigned char bq2023_overflow_check(void)
{
unsigned char clr=0;
unsigned int data;
unsigned char buffer[11];
if(!bq2023_init())
return 0;
if(bq2023_read_all_register(bq2023_romcode, buffer, 0x105)) // reads last 11 Registers MODE .. DCRH
{
if(bq2023_overflow.ok==0)
{
if(bq2023_read_data(bq2023_romcode, bq2023_buffer, RAM_START, RAM_SIZE)) // starts with address 0xe0
{
memcpy((unsigned char*)&bq2023_overflow, bq2023_buffer, OVERFLOW_SIZE);
bq2023_overflow.ok=1;
}
else
return 0;
}
if(buffer[0] & MODE_STC) // check MODE-register
{
bq2023_overflow.ctc_overflow++; // overflow-counter for Charge Time Counter
clr|=CLR_CTC;
if(!bq2023_write_ram(bq2023_romcode, (unsigned char*)&bq2023_overflow.ctc_overflow, CTC_OVERFLOW_16, 2))
return 0;
}
if(buffer[0] & MODE_STD) // check MODE-register
{
bq2023_overflow.dtc_overflow++; // overflow-counter for Discharge Time Counter
clr|=CLR_DTC;
if(!bq2023_write_ram(bq2023_romcode, (unsigned char*)&bq2023_overflow.dtc_overflow, DTC_OVERFLOW_16, 2))
return 0;
}
data=buffer[8];
data<<=8;
data|=buffer[7];
if(data=0x0110)
return 0;
size=0x0110-start_addr;
if(size==0)
return 0;
if (!bq2023_select(romcode))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0xF0);
crc_data[0]=0xF0;
if (!W1_WRITE(LO(start_addr))) // write LOW-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
if (!W1_WRITE(HI(start_addr))) // write HIGH-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
crc_data[1]=LO(start_addr);
crc_data[2]=HI(start_addr);
data=W1_READ(); // read CRC of command (0xC3) and address
if(data!=w1_dow_crc8(crc_data, 3))
{
#ifdef BQ2023_DEBUG
printf("read_all-CRC BQ:%x MC:%x\n\r", data, w1_dow_crc8(crc_data, 3));
display_frame(crc_data, 3);
bq2023_error++;
#endif
return 0;
}
count=0;
while(size--)
{
*dest++=W1_READ();
start_addr++;
count++;
if(size==0)
{
data=W1_READ(); // read CRC of data from initial starting byte to last byte
if(data!=w1_dow_crc8((unsigned char*)(dest-count), count))
{
#ifdef BQ2023_DEBUG
printf("read_all-CRC BQ:%x MC:%x\n\r", data, w1_dow_crc8((unsigned char*)(dest-count), count));
display_frame((unsigned char*)(dest-count), count);
bq2023_error++;
#endif
return 0;
}
}
}
return 1;
}
//#if funcused bq2023_read_register
// ********************************************************************************
// Description : read a block of size bytes, starting from application
// Input : 1.) *romcode - pointer to 9Byte-Array with ROM-number
// 2.) *dest - pointer to Data-Byte
// 3.) addr - addr of Register only
// Output : 1.) return==0x01 - OK
// return==0x00 - error
// Indication : BQ2023-Level
// *********************************************************************************
unsigned char bq2023_read_register(unsigned char *romcode,
unsigned char dest, BQ2023_R_REG addr)
{
unsigned char crc_data[3];
unsigned char data;
// reads the data from the scratchpad
if (!bq2023_select(romcode))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0xF0);
crc_data[0]=0xF0;
if (!W1_WRITE(addr)) // write LOW-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
if (!W1_WRITE(0x01)) // write HIGH-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
crc_data[1]=addr;
crc_data[2]=0x01;
data=W1_READ(); // read CRC of command (0xC3) and address
if(data!=w1_dow_crc8(crc_data, 3))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
dest=W1_READ();
return 1;
}
//#endif
//#if funcused bq2023_write_register
// ********************************************************************************
// Description : write a byte to register
// Input : 1.) *romcode - pointer to 9Byte-Array with ROM-number
// 2.) *source - pointer to Byte-Data
// 3.) addr - addr of Write-Enable-Register
// Output : 1.) return==0x01 - OK
// return==0x00 - error
// Indication : BQ2023-Level
// *********************************************************************************
unsigned char bq2023_write_register(unsigned char *romcode,
unsigned char source, BQ2023_W_REG addr)
{
unsigned char crc_data[4];
unsigned char data;
// reads the data from the scratchpad
if(!bq2023_select(romcode))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0x0F); // set new command
crc_data[0]=0x0F;
if (!W1_WRITE(addr)) // write LOW-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
crc_data[1]=addr;
if (!W1_WRITE(0x01)) // write HIGH-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
crc_data[2]=0x01;
W1_WRITE(source); // write new data
crc_data[3]=source;
data=W1_READ(); // read CRC of command (0x0F), address and data
if(data!=w1_dow_crc8(crc_data, 4))
{
#ifdef BQ2023_DEBUG
printf("write_reg-CRC BQ:%02x MC:%02x\n\r", data, w1_dow_crc8(crc_data, 4));
bq2023_error++;
#endif
return 0;
}
data=W1_READ(); // read data to verify
if(data!=source)
{
#ifdef BQ2023_DEBUG
printf("write_reg-verify BQ:%02x MC:%02x\n\r", data, source);
bq2023_error++;
#endif
return 0;
}
return 1;
}
//#endif
//#if funcused bq2023_write_flash
// ********************************************************************************
// Description : write a block to flash of size bytes
// Input : 1.) *romcode - pointer to 9Byte-Array with ROM-number
// 2.) *source - pointer to Data-Array
// 3.) addr - addr of flash
// 4.) size - size to write to flash
// Output : 1.) return==0x01 - OK
// return==0x00 - error
// Indication : BQ2023-Level
// *********************************************************************************
unsigned char bq2023_write_flash(unsigned char *romcode,
unsigned char *source, unsigned char addr, unsigned char size)
{
unsigned char crc_data[4];
unsigned char data;
if (!bq2023_select(romcode))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0x0F); // set new command
crc_data[0]=0x0F;
if(!W1_WRITE(addr)) // write LOW-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
if(!W1_WRITE(0x00)) // write HIGH-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
crc_data[1]=addr;
crc_data[2]=0x00;
W1_WRITE(*source); // write first new data
crc_data[3]=*source;
data=W1_READ(); // read CRC of command (0x0F) and address
if(data!=w1_dow_crc8(crc_data, 4))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0x5A); // set programmimg code
delay_us(200);
data=W1_READ(); // read data to verify
if(data!=*source)
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
source++;
size--;
while(size--)
{
addr++;
W1_WRITE(*source); // write new data
crc_data[0]=*source; // init new data to CRC-buffer
data=W1_READ(); // read CRC of data and LO(address)
if(data!=w1_dow_crc8_new(crc_data, 1, addr)) // check CRC with preload of address
{
#ifdef BQ2023_DEBUG
printf("write_flash-CRC BQ:%x MC:%x\n\r", data, w1_dow_crc8_new(crc_data, 1, addr));
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0x5A); // set programmimg code
delay_us(200);
data=W1_READ(); // read data to verify
if(data!=*source)
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
source++;
}
return 1;
}
//#endif
//#if funcused bq2023_write_ram
// ********************************************************************************
// Description : write a block to ram of size bytes
// Input : 1.) *romcode - pointer to 9Byte-Array with ROM-number
// 2.) *source - pointer to Data-Array
// 3.) addr - addr of ram
// 4.) size - size to write to ram
// Output : 1.) return==0x01 - OK
// return==0x00 - error
// Indication : BQ2023-Level
// *********************************************************************************
unsigned char bq2023_write_ram(unsigned char *romcode,
unsigned char *source, unsigned char addr, unsigned char size)
{
unsigned char crc_data[4];
unsigned char data;
if(!bq2023_select(romcode))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
W1_WRITE(0x0F); // set new command
crc_data[0]=0x0F;
if (!W1_WRITE(addr)) // write LOW-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
if (!W1_WRITE(0x00)) // write HIGH-Part of address
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
crc_data[1]=addr;
crc_data[2]=0x00;
W1_WRITE(*source); // write first new data
crc_data[3]=*source;
data=W1_READ(); // read CRC of command (0x0F) and address
if(data!=w1_dow_crc8(crc_data, 4))
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
data=W1_READ(); // read data to verify
if(data!=*source)
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
source++; // pointer to next data
size--; // decrement size-count
while(size--)
{
addr++;
W1_WRITE(*source); // write new data
crc_data[0]=*source; // init new data to CRC-buffer
data=W1_READ(); // read CRC of data and LO(address)
if(data!=w1_dow_crc8_new(crc_data, 1, addr)) // check CRC with preload of address
{
#ifdef BQ2023_DEBUG
printf("write_ram-CRC BQ:%x MC:%x\n\r", data, w1_dow_crc8_new(crc_data, 1, addr));
bq2023_error++;
#endif
return 0;
}
data=W1_READ(); // read data to verify
if(data!=*source)
{
#ifdef BQ2023_DEBUG
bq2023_error++;
#endif
return 0;
}
source++;
}
return 1;
}
#pragma warn-
// ********************************************************************************
// Description : calculates the CRC-value with start-value
// Input : 1.) *p - pointer to Data-Array
// 2.) n - count of data
// 3.) start - start-value
// Output : 1.) return==CRC-value
// Indication : BQ2023-Level
// *********************************************************************************
unsigned char w1_dow_crc8_new(void *p, unsigned char n, unsigned char start)
{
#asm
_w1_dow_crc8_n:
ld r30,y ; set start-value (LSB-Register) from variable "start"
ldd r24,y+1 ; (load Indirect from dataspace) set count-value from variable "n"
tst r24
breq __w1_dow_crc83_n
ldi r22,0x18
ldd r26,y+2 ; load datapointer to XL-Register (LSB)
ldd r27,y+3 ; load datapointer to XH-Register (MSB)
__w1_dow_crc80_n:
ldi r25,8
ld r31,x+ ; read data from X-Pointer
__w1_dow_crc81_n:
mov r23,r31
eor r23,r30
ror r23
brcc __w1_dow_crc82_n
eor r30,r22
__w1_dow_crc82_n:
ror r30
lsr r31
dec r25
brne __w1_dow_crc81_n
dec r24
brne __w1_dow_crc80_n
__w1_dow_crc83_n:
adiw r28,4 ; delete Datastack (Y-Register)
ret
#endasm
}
#pragma warn+
#ifdef BQ2023_DEBUG
unsigned char bq2023_debug_buffer[256];
// **********************************************************************************
// Description : read and displays the sram and flash from BQ2023
// Input : none
// Output : none
// Indication : BQ2023-DEBUG-Level
// **********************************************************************************
void bq2023_display_data(void)
{
rs232_driver_on();
if(bq2023_init())
{
if(bq2023_read_data(bq2023_romcode, bq2023_debug_buffer, 0x00, 0xe0)) // reads FLASH
{
putsf("FLASH:\r");
display_frame(bq2023_debug_buffer, 0xe0);
}
if(bq2023_read_data(bq2023_romcode, bq2023_debug_buffer, 0xe0, 0x20)) // reads SRAM
{
putsf("SRAM:\r");
display_frame(bq2023_debug_buffer, 0x20);
}
return;
}
printf("BQ2023-Error\n\r");
}
// **********************************************************************************
// Description : write a pattern to SRAM from BQ2023
// Input : none
// Output : none
// Indication : BQ2023-DEBUG-Level
// **********************************************************************************
void bq2023_backup(void)
{
unsigned char Lva;
rs232_driver_on();
if(bq2023_init())
{
for(Lva=0;Lva<0x20;Lva++)
bq2023_debug_buffer[Lva]=Lva+33; // writes Pattern
if(bq2023_write_ram(bq2023_romcode, bq2023_debug_buffer, 0xe0, 0x20)) // writes SRAM
if(bq2023_read_data(bq2023_romcode, bq2023_debug_buffer, 0xe0, 0x20)) // reads SRAM
{
putsf("SRAM:\r");
display_frame(bq2023_debug_buffer, 0x20);
}
return;
}
printf("BQ2023-Error\n\r");
}
// **********************************************************************************
// Description : read and displays the register from BQ2023
// Input : none
// Output : none
// Indication : BQ2023-DEBUG-Level
// **********************************************************************************
unsigned char bq2023_display_register(void)
{
unsigned char Lva, Lvb;
signed int temp;
unsigned long discharge;
unsigned long time;
unsigned char delta_time;
rs232_driver_on();
printf("BQ2023-Error: %u\n\r", bq2023_error);
if(bq2023_discharge(bq2023_debug_buffer, &temp, &discharge, &time))
{
printf("FED : 0x%x\n\r", bq2023_debug_buffer[1]);
printf("TEMP: 0x%02x%02x (%i.%02u C)\n\r", bq2023_debug_buffer[3], bq2023_debug_buffer[2], (temp/4-273), (temp%4)*25);
printf("CLR : 0x%02x\n\r", bq2023_debug_buffer[4]);
printf("MODE: 0x%02x\n\r", bq2023_debug_buffer[5]);
printf("DTC : 0x%02x%02x ", bq2023_debug_buffer[9], bq2023_debug_buffer[8]);
printf("SCR : 0x%02x%02x ", bq2023_debug_buffer[11], bq2023_debug_buffer[10]);
printf("DCR : 0x%02x%02x\n\r", bq2023_debug_buffer[15], bq2023_debug_buffer[14]);
printf("CTC : 0x%02x%02x ", bq2023_debug_buffer[7], bq2023_debug_buffer[6]);
printf("CCR : 0x%02x%02x\n\r", bq2023_debug_buffer[13], bq2023_debug_buffer[12]);
printf("Discharge : %u.%umAh (time %uh:%umin:%usec)\n\r", discharge/1000, discharge%1000, time/3600,
(time%3600)/60, (time%3600)%60);
if(discharge<200000) // means <200.0mAh
{
// calculates with mAs/second
discharge*=36; // from µAh to mAs
discharge/=10; // 3600(hours to second)/1000(µA to mA)
}
else
{
// calculates with mAh/hours
time*=10; // from second to hours and µAh to mAh
time/=36; // 1000(µAh to mAh)/3600(second to hour)
}
printf("Current : %u.%03umA\n\r", discharge/time, (discharge*1000)/time);
bq2023_discharge24(&discharge, &delta_time);
time=delta_time;
time*=1000; // µAh/(h*1000)=mA
printf("dDischarge: %u.%03umAh\n\r", discharge/1000, discharge%1000);
if(discharge!=0)
printf("dCurrent : %u.%03umA (%uh)\n\r", discharge/time, (discharge*1000)/time, delta_time);
else
printf("dCurrent : 0.0mA (%uh)\n\r", delta_time);
Lvb=discharge_buffer_p;
for(Lva=0;Lva=MAX_DISCHARGE_VALUE)
Lvb=MAX_DISCHARGE_VALUE-1; // starts with last value of buffer
printf("[%02u]:%4u.%03umAh ", Lvb, discharge_buffer[Lvb]/1000, discharge_buffer[Lvb]%1000);
if((((Lva+1)%3)==0)&&(Lva!=0))
putsf("\r");
}
putsf("\r");
if(bq2023_read_data(bq2023_romcode, bq2023_debug_buffer, RAM_START, RAM_SIZE)) // starts with address 0xe0
memcpy((unsigned char*)&bq2023_overflow, bq2023_debug_buffer, OVERFLOW_SIZE);
printf("ctc_over : %u\n\r", bq2023_overflow.ctc_overflow); // overflow-counter for Charge Time Counter
printf("dtc_over : %u\n\r", bq2023_overflow.dtc_overflow); // overflow-counter for Discharge Time Counter
printf("ccr_over : %u\n\r", bq2023_overflow.ccr_overflow); // overflow-counter for Charge Count Register
printf("dcr_over : %u\n\r", bq2023_overflow.dcr_overflow); // overflow-counter for Discharge Count Register
return 1;
}
printf("BQ2023-Error\n\r");
return 0;
}
#endif // #ifdef BQ2023_DEBUG