Files
CuboBmsFirmware/firmware/Core/Inc/driverSWLTC6804.h
2023-03-29 20:05:42 +03:00

259 lines
12 KiB
C

/*
Copyright 2017 - 2018 Danny Bokma danny@diebie.nl
Copyright 2019 - 2020 Kevin Dionne kevin.dionne@ennoid.me
This file is part of the DieBieMS/ENNOID-BMS firmware.
The DieBieMS/ENNOID-BMS firmware is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The DieBieMS/ENNOID-BMS firmware 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "driverHWSPI1.h"
#include "stdlib.h"
#include "math.h"
#include "mainDataTypes.h"
#include "modDelay.h"
//#include "driverSWLTC6804.h"
/*
Pre computed crc15 table used for the LTC6804 PEC calculation
The code used to generate the crc15 table is:
void generate_crc15_table()
{
int remainder;
for(int i = 0; i<256;i++)
{
remainder = i<< 7;
for (int bit = 8; bit > 0; --bit)
{
if ((remainder & 0x4000) > 0)//equivalent to remainder & 2^14 simply check for MSB
{
remainder = ((remainder << 1)) ;
remainder = (remainder ^ 0x4599);
}
else
{
remainder = ((remainder << 1));
}
}
crc15Table[i] = remainder&0xFFFF;
}
}
*/
static const unsigned int crc15Table[256] = {
0x0000, 0xc599, 0xceab, 0x0b32, 0xd8cf, 0x1d56, 0x1664, 0xd3fd, 0xf407, 0x319e, 0x3aac, //!<precomputed CRC15 Table
0xff35, 0x2cc8, 0xe951, 0xe263, 0x27fa, 0xad97, 0x680e, 0x633c, 0xa6a5, 0x7558, 0xb0c1,
0xbbf3, 0x7e6a, 0x5990, 0x9c09, 0x973b, 0x52a2, 0x815f, 0x44c6, 0x4ff4, 0x8a6d, 0x5b2e,
0x9eb7, 0x9585, 0x501c, 0x83e1, 0x4678, 0x4d4a, 0x88d3, 0xaf29, 0x6ab0, 0x6182, 0xa41b,
0x77e6, 0xb27f, 0xb94d, 0x7cd4, 0xf6b9, 0x3320, 0x3812, 0xfd8b, 0x2e76, 0xebef, 0xe0dd,
0x2544, 0x02be, 0xc727, 0xcc15, 0x098c, 0xda71, 0x1fe8, 0x14da, 0xd143, 0xf3c5, 0x365c,
0x3d6e, 0xf8f7, 0x2b0a, 0xee93, 0xe5a1, 0x2038, 0x07c2, 0xc25b, 0xc969, 0x0cf0, 0xdf0d,
0x1a94, 0x11a6, 0xd43f, 0x5e52, 0x9bcb, 0x90f9, 0x5560, 0x869d, 0x4304, 0x4836, 0x8daf,
0xaa55, 0x6fcc, 0x64fe, 0xa167, 0x729a, 0xb703, 0xbc31, 0x79a8, 0xa8eb, 0x6d72, 0x6640,
0xa3d9, 0x7024, 0xb5bd, 0xbe8f, 0x7b16, 0x5cec, 0x9975, 0x9247, 0x57de, 0x8423, 0x41ba,
0x4a88, 0x8f11, 0x057c, 0xc0e5, 0xcbd7, 0x0e4e, 0xddb3, 0x182a, 0x1318, 0xd681, 0xf17b,
0x34e2, 0x3fd0, 0xfa49, 0x29b4, 0xec2d, 0xe71f, 0x2286, 0xa213, 0x678a, 0x6cb8, 0xa921,
0x7adc, 0xbf45, 0xb477, 0x71ee, 0x5614, 0x938d, 0x98bf, 0x5d26, 0x8edb, 0x4b42, 0x4070,
0x85e9, 0x0f84, 0xca1d, 0xc12f, 0x04b6, 0xd74b, 0x12d2, 0x19e0, 0xdc79, 0xfb83, 0x3e1a,
0x3528, 0xf0b1, 0x234c, 0xe6d5, 0xede7, 0x287e, 0xf93d, 0x3ca4, 0x3796, 0xf20f, 0x21f2,
0xe46b, 0xef59, 0x2ac0, 0x0d3a, 0xc8a3, 0xc391, 0x0608, 0xd5f5, 0x106c, 0x1b5e, 0xdec7,
0x54aa, 0x9133, 0x9a01, 0x5f98, 0x8c65, 0x49fc, 0x42ce, 0x8757, 0xa0ad, 0x6534, 0x6e06,
0xab9f, 0x7862, 0xbdfb, 0xb6c9, 0x7350, 0x51d6, 0x944f, 0x9f7d, 0x5ae4, 0x8919, 0x4c80,
0x47b2, 0x822b, 0xa5d1, 0x6048, 0x6b7a, 0xaee3, 0x7d1e, 0xb887, 0xb3b5, 0x762c, 0xfc41,
0x39d8, 0x32ea, 0xf773, 0x248e, 0xe117, 0xea25, 0x2fbc, 0x0846, 0xcddf, 0xc6ed, 0x0374,
0xd089, 0x1510, 0x1e22, 0xdbbb, 0x0af8, 0xcf61, 0xc453, 0x01ca, 0xd237, 0x17ae, 0x1c9c,
0xd905, 0xfeff, 0x3b66, 0x3054, 0xf5cd, 0x2630, 0xe3a9, 0xe89b, 0x2d02, 0xa76f, 0x62f6,
0x69c4, 0xac5d, 0x7fa0, 0xba39, 0xb10b, 0x7492, 0x5368, 0x96f1, 0x9dc3, 0x585a, 0x8ba7,
0x4e3e, 0x450c, 0x8095
};
/*!
|MD| Dec | ADC Conversion Model|
|--|------|---------------------|
|01| 1 | Fast |
|10| 2 | Normal |
|11| 3 | Filtered |
*/
#define MD_FAST 1
#define MD_NORMAL 2
#define MD_FILTERED 3
/*!
|CH | Dec | Channels to convert |
|---|------|---------------------|
|000| 0 | All Cells |
|001| 1 | Cell 1 and Cell 7 |
|010| 2 | Cell 2 and Cell 8 |
|011| 3 | Cell 3 and Cell 9 |
|100| 4 | Cell 4 and Cell 10 |
|101| 5 | Cell 5 and Cell 11 |
|110| 6 | Cell 6 and Cell 12 |
*/
#define CELL_CH_ALL 0
#define CELL_CH_1and7 1
#define CELL_CH_2and8 2
#define CELL_CH_3and9 3
#define CELL_CH_4and10 4
#define CELL_CH_5and11 5
#define CELL_CH_6and12 6
/*!
|CHG | Dec |Channels to convert |
|----|------|----------------------|
|000 | 0 | All GPIOS and 2nd Ref|
|001 | 1 | GPIO 1 |
|010 | 2 | GPIO 2 |
|011 | 3 | GPIO 3 |
|100 | 4 | GPIO 4 |
|101 | 5 | GPIO 5 |
|110 | 6 | Vref2 |
*/
#define AUX_CH_ALL 0
#define AUX_CH_GPIO1 1
#define AUX_CH_GPIO2 2
#define AUX_CH_GPIO3 3
#define AUX_CH_GPIO4 4
#define AUX_CH_GPIO5 5
#define AUX_CH_VREF2 6
//uint8_t CHG = 0; //!< aux channels to be converted
/*!****************************************************
\brief Controls if Discharging transitors are enabled
or disabled during Cell conversions.
|DCP | Discharge Permitted During conversion |
|----|----------------------------------------|
|0 | No - discharge is not permitted |
|1 | Yes - discharge is permitted |
********************************************************/
#define DCP_DISABLED 0
#define DCP_ENABLED 1
typedef enum {
LTC6804WriteConfigRegA = 0x0001, // WRCFG
LTC6804WriteConfigRegB = 0x0024, // WRCFG
LTC6804ReadConfigRegA = 0x0002, // RDCFG
LTC6804ReadConfigRegB = 0x0026, // RDCFG
LTC6804ReadCellVoltageGroupA = 0x0004, // RDVCA
LTC6804ReadCellVoltageGroupB = 0x0006, // RDVCB
LTC6804ReadCellVoltageGroupC = 0x0008, // RDVCC
LTC6804ReadCellVoltageGroupD = 0x000A, // RDVCD
LTC6804ReadAuxGroupA = 0x000C, // RDAUXA
LTC6804ReadAuxGroupB = 0x000E, // RDAUXB
LTC6804ReadStatusRegisterGroupA = 0x0010, // RDSTATA
LTC6804ReadStatusRegisterGroupB = 0x0012, // RDSTATB
LTC6804StartCellVoltageADConversion = 0x0260, // ADCV
LTC6804StartCellOpenWireVoltageADConversion = 0x0228, // ADOW
LTC6804StartCellSelfTestVoltageConversion = 0x0207, // CVST
LTC6804StartGPIOADConversion = 0x0460, // ADAX
LTC6804SelfTestGPIOConversion = 0x0407, // AXST
LTC6804StartStatusGroupConversion = 0x0468, // ADSTAT
LTC6804StartSelfTestStatusGroup = 0x040F, // STATST
LTC6804StartCombinedADConversion = 0x046F, // ADCVAX
LTC6804ClearCellVoltageGroup = 0x0711, // CLRCELL
LTC6804ClearAuxVoltageGroup = 0x0712, // CLRAUX
LTC6804ClearStatusRegisterGroup = 0x0713, // CLRSTAT
LTC6804PollADConversion = 0x0714, // PLADC
LTC6804DiagnoseMUX = 0x0715, // DIAGN
LTC6804CommunicationWriteRegisterGroup = 0x0721, // WRCOMM
LTC6804CommunucationReadRegisterGroup = 0x0722, // RDCOMM
LTC6804CommuncationStart = 0x0723 // STCOMM
} driverSWLTC6804RegistersBase;
typedef struct {
bool GPIO1; // Read/Write opendrain GPIO1
bool GPIO2; // Read/Write opendrain GPIO2
bool GPIO3; // Read/Write opendrain GPIO3
bool GPIO4; // Read/Write opendrain GPIO4
bool GPIO5; // Read/Write opendrain GPIO5
bool GPIO6; // Read/Write opendrain GPIO6
bool GPIO7; // Read/Write opendrain GPIO7
bool GPIO8; // Read/Write opendrain GPIO8
bool GPIO9; // Read/Write opendrain GPIO9
bool ReferenceON; // Reference ON
bool SoftwareTimerFlag; // Read software timer pin
bool ADCOption; // ADC Option register for configuration of over sampling ratio
uint8_t noOfCells; // Number of cells to monitor (that can cause interrupt)
uint32_t DisChargeEnableMask; // Set enable state of discharge, 1=EnableDischarge, 0=DisableDischarge
uint8_t DischargeTimout; // Discharge timout value / limit
double CellUnderVoltageLimit; // Undervoltage level, cell voltages under this limit will cause interrupt
double CellOverVoltageLimit; // Over voltage limit, cell voltages over this limit will cause interrupt
} driverLTC6804ConfigStructTypedef;
typedef struct {
float sumOfCells;
float dieTemperature;
float voltageAnalogSupply;
float voltageDigitalSupply;
uint16_t overVoltage;
uint16_t underVoltage;
bool muxFail;
} driverSWLTC6804StatusStructTypedef;
//Init
void driverSWLTC6804Init(driverLTC6804ConfigStructTypedef configStruct, uint8_t totalNumberOfLTCs, uint8_t maxNoOfCellPerModule, uint8_t maxNoOfTempSensorPerModule, uint8_t cellMonitorType);
//Write/read config registers
void driverSWLTC6804WriteConfigRegister(uint8_t totalNumberOfLTCs, uint32_t *balanceEnableMaskArray, bool useArray);
void driverSWLTC6804WriteConfigRegisterB(uint8_t totalNumberOfLTCs, uint32_t *balanceEnableMaskArray, bool useArray);
int8_t driverSWLTC6804ReadConfigRegister(uint8_t nIC, uint8_t r_config[][8]);
//Balance resistor
void driverSWLTC6804EnableBalanceResistors(uint32_t enableMask, uint8_t cellMonitorType); // Used only for single slave test with "testbms" command
void driverSWLTC6804EnableBalanceResistorsArray(uint32_t *enableMask, uint8_t cellMonitorType);
//Cell voltage
void driverSWLTC6804StartCellAndAuxVoltageConversion(uint8_t MD,uint8_t DCP);
void driverSWLTC6804StartCellVoltageConversion(uint8_t MD,uint8_t DCP, uint8_t CH);
void driverSWLTC6804StartLoadedCellVoltageConversion(uint8_t MD,uint8_t DCP, uint8_t CH,uint8_t PUP);
bool driverSWLTC6804ReadCellVoltagesArray(float cellVoltagesArray[][18]);
uint8_t driverSWLTC6804ReadCellVoltageRegisters(uint8_t reg, uint8_t total_ic, uint16_t cell_codes[][18]);
void driverSWLTC6804ReadCellVoltageGroups(uint8_t reg, uint8_t total_ic, uint8_t *data);
// Aux sensors
void driverSWLTC6804StartAuxVoltageConversion(uint8_t MD, uint8_t CHG);
float driverSWLTC6804ConvertTemperatureExt(uint16_t inputValue,uint32_t ntcNominal,uint32_t ntcSeriesResistance,uint16_t ntcBetaFactor, float ntcNominalTemp);
bool driverSWLTC6804ReadAuxVoltagesArray(float auxVoltagesArray[][12],uint32_t ntcNominal,uint32_t ntcSeriesResistance, uint16_t ntcBetaFactor,float ntcNominalTemp);
int8_t driverSWLTC6804ReadAuxVoltageRegisters(uint8_t reg, uint8_t total_ic, uint16_t aux_codes[][12]);
void driverSWLTC6804ReadAuxGroups(uint8_t reg, uint8_t total_ic,uint8_t *data);
//Status & flags
bool driverSWLTC6804ReadVoltageFlags(uint32_t *underVoltageFlags, uint32_t *overVoltageFlags, uint32_t lastICMask, uint8_t noOfParallelModules, uint32_t dieTemperature[]);
uint8_t driverSWLTC6804ReadStatusValues(uint8_t total_ic, driverSWLTC6804StatusStructTypedef statusArray[]);
void driverSWLTC6804ReadStatusGroups(uint8_t reg, uint8_t total_ic, uint8_t *data );
//Utilities
void driverSWLTC6804ResetCellVoltageRegisters(void);
void driverSWLTC6804ResetAuxRegisters(void);
void driverSWLTC6804ResetStatusRegisters(void);
void driverSWLTC6804DelayMS(uint32_t delayMS);
void driverSWLTC6804Write(uint8_t *writeBytes, uint8_t writeLength);
void driverSWLTC6804WriteRead(uint8_t *writeBytes, uint8_t writeLength, uint8_t *readBytes, uint8_t readLength);
void driverSWLTC6804WakeIC(void);
uint16_t driverSWLTC6804CalcPEC15(uint8_t len, uint8_t *data);