BMS_T2

Dependencies:   INA226

Committer:
takuma1
Date:
Tue Oct 13 07:20:11 2020 +0000
Revision:
3:61174d4de67d
Parent:
2:3bbbe439ec11
BMS_T2;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
APS_Lab 0:f06ed53310a3 1 /*
APS_Lab 0:f06ed53310a3 2 General BMS Library
APS_Lab 0:f06ed53310a3 3 LTC681x.cpp
APS_Lab 0:f06ed53310a3 4 */
APS_Lab 0:f06ed53310a3 5
APS_Lab 0:f06ed53310a3 6 #include "mbed.h"
APS_Lab 0:f06ed53310a3 7
APS_Lab 0:f06ed53310a3 8 #include "LTC681x.h"
APS_Lab 0:f06ed53310a3 9 #include "bms.h"
APS_Lab 0:f06ed53310a3 10 //#include "LT_SPI.h"
APS_Lab 0:f06ed53310a3 11
APS_Lab 0:f06ed53310a3 12
APS_Lab 0:f06ed53310a3 13 void wakeup_idle(uint8_t total_ic)
APS_Lab 0:f06ed53310a3 14 {
APS_Lab 0:f06ed53310a3 15 for (int i =0; i<total_ic; i++) {
APS_Lab 1:4dd3e328a30b 16 cs_low();
APS_Lab 1:4dd3e328a30b 17 wait_ms(2); //Guarantees the isoSPI will be in ready mode
APS_Lab 0:f06ed53310a3 18 spi_read_byte(0xff);
APS_Lab 1:4dd3e328a30b 19 cs_high();
APS_Lab 0:f06ed53310a3 20 }
APS_Lab 0:f06ed53310a3 21 }
APS_Lab 0:f06ed53310a3 22
APS_Lab 0:f06ed53310a3 23 //Generic wakeup commannd to wake the LTC6813 from sleep
APS_Lab 0:f06ed53310a3 24 void wakeup_sleep(uint8_t total_ic)
APS_Lab 0:f06ed53310a3 25 {
APS_Lab 0:f06ed53310a3 26 for (int i =0; i<total_ic; i++) {
APS_Lab 1:4dd3e328a30b 27 cs_low();
APS_Lab 0:f06ed53310a3 28 delay_u(300); // Guarantees the LTC6813 will be in standby
APS_Lab 1:4dd3e328a30b 29 cs_high();
APS_Lab 0:f06ed53310a3 30 delay_u(10);
APS_Lab 0:f06ed53310a3 31 }
APS_Lab 0:f06ed53310a3 32 }
APS_Lab 0:f06ed53310a3 33
APS_Lab 0:f06ed53310a3 34 //Generic function to write 68xx commands. Function calculated PEC for tx_cmd data
APS_Lab 0:f06ed53310a3 35 void cmd_68(uint8_t tx_cmd[2])
APS_Lab 0:f06ed53310a3 36 {
APS_Lab 0:f06ed53310a3 37 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 38 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 39 // uint8_t md_bits;
APS_Lab 0:f06ed53310a3 40
APS_Lab 0:f06ed53310a3 41 cmd[0] = tx_cmd[0];
APS_Lab 0:f06ed53310a3 42 cmd[1] = tx_cmd[1];
APS_Lab 0:f06ed53310a3 43 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 44 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 45 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 1:4dd3e328a30b 46 cs_low();
APS_Lab 0:f06ed53310a3 47 spi_write_array(4,cmd);
APS_Lab 1:4dd3e328a30b 48 cs_high();
APS_Lab 0:f06ed53310a3 49 }
APS_Lab 0:f06ed53310a3 50
APS_Lab 0:f06ed53310a3 51 //Generic function to write 68xx commands and write payload data. Function calculated PEC for tx_cmd data
APS_Lab 0:f06ed53310a3 52 void write_68(uint8_t total_ic , uint8_t tx_cmd[2], uint8_t data[])
APS_Lab 0:f06ed53310a3 53 {
APS_Lab 0:f06ed53310a3 54 const uint8_t BYTES_IN_REG = 6;
APS_Lab 0:f06ed53310a3 55 const uint8_t CMD_LEN = 4+(8*total_ic);
APS_Lab 0:f06ed53310a3 56 uint8_t *cmd;
APS_Lab 0:f06ed53310a3 57 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 58 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 59 uint8_t cmd_index;
APS_Lab 0:f06ed53310a3 60
APS_Lab 0:f06ed53310a3 61 cmd = (uint8_t *)malloc(CMD_LEN*sizeof(uint8_t));
APS_Lab 0:f06ed53310a3 62 cmd[0] = tx_cmd[0];
APS_Lab 0:f06ed53310a3 63 cmd[1] = tx_cmd[1];
APS_Lab 0:f06ed53310a3 64 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 65 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 66 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 67 cmd_index = 4;
APS_Lab 0:f06ed53310a3 68 for (uint8_t current_ic = total_ic; current_ic > 0; current_ic--) { // executes for each LTC681x in daisy chain, this loops starts with
APS_Lab 0:f06ed53310a3 69 // the last IC on the stack. The first configuration written is
APS_Lab 0:f06ed53310a3 70 // received by the last IC in the daisy chain
APS_Lab 0:f06ed53310a3 71
APS_Lab 0:f06ed53310a3 72 for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++) {
APS_Lab 0:f06ed53310a3 73 cmd[cmd_index] = data[((current_ic-1)*6)+current_byte];
APS_Lab 0:f06ed53310a3 74 cmd_index = cmd_index + 1;
APS_Lab 0:f06ed53310a3 75 }
APS_Lab 0:f06ed53310a3 76
APS_Lab 0:f06ed53310a3 77 data_pec = (uint16_t)pec15_calc(BYTES_IN_REG, &data[(current_ic-1)*6]); // calculating the PEC for each Iss configuration register data
APS_Lab 0:f06ed53310a3 78 cmd[cmd_index] = (uint8_t)(data_pec >> 8);
APS_Lab 0:f06ed53310a3 79 cmd[cmd_index + 1] = (uint8_t)data_pec;
APS_Lab 0:f06ed53310a3 80 cmd_index = cmd_index + 2;
APS_Lab 0:f06ed53310a3 81 }
APS_Lab 0:f06ed53310a3 82
APS_Lab 0:f06ed53310a3 83
APS_Lab 1:4dd3e328a30b 84 cs_low();
APS_Lab 0:f06ed53310a3 85 spi_write_array(CMD_LEN, cmd);
APS_Lab 1:4dd3e328a30b 86 cs_high();
APS_Lab 0:f06ed53310a3 87 free(cmd);
APS_Lab 0:f06ed53310a3 88 }
APS_Lab 0:f06ed53310a3 89
APS_Lab 0:f06ed53310a3 90 //Generic function to write 68xx commands and read data. Function calculated PEC for tx_cmd data
APS_Lab 0:f06ed53310a3 91 int8_t read_68( uint8_t total_ic, uint8_t tx_cmd[2], uint8_t *rx_data)
APS_Lab 0:f06ed53310a3 92 {
APS_Lab 0:f06ed53310a3 93 const uint8_t BYTES_IN_REG = 8;
APS_Lab 0:f06ed53310a3 94 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 95 uint8_t data[256];
APS_Lab 0:f06ed53310a3 96 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 97 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 98 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 99 uint16_t received_pec;
APS_Lab 0:f06ed53310a3 100
APS_Lab 0:f06ed53310a3 101 // data = (uint8_t *) malloc((8*total_ic)*sizeof(uint8_t)); // This is a problem because it can fail
APS_Lab 0:f06ed53310a3 102
APS_Lab 0:f06ed53310a3 103 cmd[0] = tx_cmd[0];
APS_Lab 0:f06ed53310a3 104 cmd[1] = tx_cmd[1];
APS_Lab 0:f06ed53310a3 105 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 106 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 107 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 108
APS_Lab 0:f06ed53310a3 109
APS_Lab 1:4dd3e328a30b 110 cs_low();
APS_Lab 0:f06ed53310a3 111 spi_write_read(cmd, 4, data, (BYTES_IN_REG*total_ic)); //Read the configuration data of all ICs on the daisy chain into
APS_Lab 1:4dd3e328a30b 112 cs_high(); //rx_data[] array
APS_Lab 0:f06ed53310a3 113
APS_Lab 0:f06ed53310a3 114 for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++) { //executes for each LTC681x in the daisy chain and packs the data
APS_Lab 0:f06ed53310a3 115 //into the r_comm array as well as check the received Config data
APS_Lab 0:f06ed53310a3 116 //for any bit errors
APS_Lab 0:f06ed53310a3 117 for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++) {
APS_Lab 0:f06ed53310a3 118 rx_data[(current_ic*8)+current_byte] = data[current_byte + (current_ic*BYTES_IN_REG)];
APS_Lab 0:f06ed53310a3 119 }
APS_Lab 0:f06ed53310a3 120 received_pec = (rx_data[(current_ic*8)+6]<<8) + rx_data[(current_ic*8)+7];
APS_Lab 0:f06ed53310a3 121 data_pec = pec15_calc(6, &rx_data[current_ic*8]);
APS_Lab 0:f06ed53310a3 122 if (received_pec != data_pec) {
APS_Lab 0:f06ed53310a3 123 pec_error = -1;
APS_Lab 0:f06ed53310a3 124 }
APS_Lab 0:f06ed53310a3 125 }
APS_Lab 0:f06ed53310a3 126
APS_Lab 0:f06ed53310a3 127
APS_Lab 0:f06ed53310a3 128 return(pec_error);
APS_Lab 0:f06ed53310a3 129 }
APS_Lab 0:f06ed53310a3 130
APS_Lab 0:f06ed53310a3 131
APS_Lab 0:f06ed53310a3 132 /*
APS_Lab 0:f06ed53310a3 133 Calculates and returns the CRC15
APS_Lab 0:f06ed53310a3 134 */
APS_Lab 0:f06ed53310a3 135 uint16_t pec15_calc(uint8_t len, //Number of bytes that will be used to calculate a PEC
APS_Lab 0:f06ed53310a3 136 uint8_t *data //Array of data that will be used to calculate a PEC
APS_Lab 0:f06ed53310a3 137 )
APS_Lab 0:f06ed53310a3 138 {
APS_Lab 0:f06ed53310a3 139 uint16_t remainder,addr;
APS_Lab 0:f06ed53310a3 140
APS_Lab 0:f06ed53310a3 141 remainder = 16;//initialize the PEC
APS_Lab 0:f06ed53310a3 142 for (uint8_t i = 0; i<len; i++) { // loops for each byte in data array
APS_Lab 0:f06ed53310a3 143 addr = ((remainder>>7)^data[i])&0xff;//calculate PEC table address
APS_Lab 0:f06ed53310a3 144 //#ifdef MBED
APS_Lab 0:f06ed53310a3 145 remainder = (remainder<<8)^crc15Table[addr];
APS_Lab 0:f06ed53310a3 146 //#else
APS_Lab 0:f06ed53310a3 147 // remainder = (remainder<<8)^pgm_read_word_near(crc15Table+addr);
APS_Lab 0:f06ed53310a3 148 //#endif
APS_Lab 0:f06ed53310a3 149 }
APS_Lab 0:f06ed53310a3 150 return(remainder*2);//The CRC15 has a 0 in the LSB so the remainder must be multiplied by 2
APS_Lab 0:f06ed53310a3 151 }
APS_Lab 0:f06ed53310a3 152
APS_Lab 0:f06ed53310a3 153 //Starts cell voltage conversion
APS_Lab 0:f06ed53310a3 154 void LTC681x_adcv(
APS_Lab 0:f06ed53310a3 155 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 156 uint8_t DCP, //Discharge Permit
APS_Lab 0:f06ed53310a3 157 uint8_t CH //Cell Channels to be measured
APS_Lab 0:f06ed53310a3 158 )
APS_Lab 0:f06ed53310a3 159 {
APS_Lab 0:f06ed53310a3 160 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 161 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 162
APS_Lab 0:f06ed53310a3 163 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 164 cmd[0] = md_bits + 0x02;
APS_Lab 0:f06ed53310a3 165 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 166 cmd[1] = md_bits + 0x60 + (DCP<<4) + CH;
APS_Lab 0:f06ed53310a3 167 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 168 }
APS_Lab 0:f06ed53310a3 169
APS_Lab 0:f06ed53310a3 170
APS_Lab 0:f06ed53310a3 171 //Starts cell voltage and SOC conversion
APS_Lab 0:f06ed53310a3 172 void LTC681x_adcvsc(
APS_Lab 0:f06ed53310a3 173 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 174 uint8_t DCP //Discharge Permit
APS_Lab 0:f06ed53310a3 175 )
APS_Lab 0:f06ed53310a3 176 {
APS_Lab 0:f06ed53310a3 177 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 178 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 179 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 180 cmd[0] = md_bits | 0x04;
APS_Lab 0:f06ed53310a3 181 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 182 cmd[1] = md_bits | 0x60 | (DCP<<4) | 0x07;
APS_Lab 0:f06ed53310a3 183 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 184
APS_Lab 0:f06ed53310a3 185 }
APS_Lab 0:f06ed53310a3 186
APS_Lab 0:f06ed53310a3 187 // Starts cell voltage and GPIO 1&2 conversion
APS_Lab 0:f06ed53310a3 188 void LTC681x_adcvax(
APS_Lab 0:f06ed53310a3 189 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 190 uint8_t DCP //Discharge Permit
APS_Lab 0:f06ed53310a3 191 )
APS_Lab 0:f06ed53310a3 192 {
APS_Lab 0:f06ed53310a3 193 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 194 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 195 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 196 cmd[0] = md_bits | 0x04;
APS_Lab 0:f06ed53310a3 197 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 198 cmd[1] = md_bits | ((DCP&0x01)<<4) + 0x6F;
APS_Lab 0:f06ed53310a3 199 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 200 }
APS_Lab 0:f06ed53310a3 201
APS_Lab 0:f06ed53310a3 202 //Starts cell voltage overlap conversion
APS_Lab 0:f06ed53310a3 203 void LTC681x_adol(
APS_Lab 0:f06ed53310a3 204 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 205 uint8_t DCP //Discharge Permit
APS_Lab 0:f06ed53310a3 206 )
APS_Lab 0:f06ed53310a3 207 {
APS_Lab 0:f06ed53310a3 208 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 209 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 210 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 211 cmd[0] = md_bits + 0x02;
APS_Lab 0:f06ed53310a3 212 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 213 cmd[1] = md_bits + (DCP<<4) +0x01;
APS_Lab 0:f06ed53310a3 214 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 215 }
APS_Lab 0:f06ed53310a3 216
APS_Lab 0:f06ed53310a3 217 //Starts cell voltage self test conversion
APS_Lab 0:f06ed53310a3 218 void LTC681x_cvst(
APS_Lab 0:f06ed53310a3 219 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 220 uint8_t ST //Self Test
APS_Lab 0:f06ed53310a3 221 )
APS_Lab 0:f06ed53310a3 222 {
APS_Lab 0:f06ed53310a3 223 uint8_t cmd[2];
APS_Lab 0:f06ed53310a3 224 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 225
APS_Lab 0:f06ed53310a3 226 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 227 cmd[0] = md_bits + 0x02;
APS_Lab 0:f06ed53310a3 228 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 229 cmd[1] = md_bits + ((ST)<<5) +0x07;
APS_Lab 0:f06ed53310a3 230 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 231
APS_Lab 0:f06ed53310a3 232 }
APS_Lab 0:f06ed53310a3 233
APS_Lab 0:f06ed53310a3 234 //Start an Auxiliary Register Self Test Conversion
APS_Lab 0:f06ed53310a3 235 void LTC681x_axst(
APS_Lab 0:f06ed53310a3 236 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 237 uint8_t ST //Self Test
APS_Lab 0:f06ed53310a3 238 )
APS_Lab 0:f06ed53310a3 239 {
APS_Lab 0:f06ed53310a3 240 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 241 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 242
APS_Lab 0:f06ed53310a3 243 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 244 cmd[0] = md_bits + 0x04;
APS_Lab 0:f06ed53310a3 245 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 246 cmd[1] = md_bits + ((ST&0x03)<<5) +0x07;
APS_Lab 0:f06ed53310a3 247 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 248
APS_Lab 0:f06ed53310a3 249 }
APS_Lab 0:f06ed53310a3 250
APS_Lab 0:f06ed53310a3 251 //Start a Status Register Self Test Conversion
APS_Lab 0:f06ed53310a3 252 void LTC681x_statst(
APS_Lab 0:f06ed53310a3 253 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 254 uint8_t ST //Self Test
APS_Lab 0:f06ed53310a3 255 )
APS_Lab 0:f06ed53310a3 256 {
APS_Lab 0:f06ed53310a3 257 uint8_t cmd[2];
APS_Lab 0:f06ed53310a3 258 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 259
APS_Lab 0:f06ed53310a3 260 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 261 cmd[0] = md_bits + 0x04;
APS_Lab 0:f06ed53310a3 262 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 263 cmd[1] = md_bits + ((ST&0x03)<<5) +0x0F;
APS_Lab 0:f06ed53310a3 264 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 265
APS_Lab 0:f06ed53310a3 266 }
APS_Lab 0:f06ed53310a3 267
APS_Lab 0:f06ed53310a3 268 //Sends the poll adc command
APS_Lab 0:f06ed53310a3 269 uint8_t LTC681x_pladc()
APS_Lab 0:f06ed53310a3 270 {
APS_Lab 0:f06ed53310a3 271 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 272 uint8_t adc_state = 0xFF;
APS_Lab 0:f06ed53310a3 273 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 274
APS_Lab 0:f06ed53310a3 275 cmd[0] = 0x07;
APS_Lab 0:f06ed53310a3 276 cmd[1] = 0x14;
APS_Lab 0:f06ed53310a3 277 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 278 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 279 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 280
APS_Lab 0:f06ed53310a3 281
APS_Lab 1:4dd3e328a30b 282 cs_low();
APS_Lab 0:f06ed53310a3 283 spi_write_array(4,cmd);
APS_Lab 0:f06ed53310a3 284 // adc_state = spi_read_byte(0xFF);
APS_Lab 1:4dd3e328a30b 285 cs_high();
APS_Lab 0:f06ed53310a3 286 return(adc_state);
APS_Lab 0:f06ed53310a3 287 }
APS_Lab 0:f06ed53310a3 288
APS_Lab 0:f06ed53310a3 289 //This function will block operation until the ADC has finished it's conversion
APS_Lab 0:f06ed53310a3 290 uint32_t LTC681x_pollAdc()
APS_Lab 0:f06ed53310a3 291 {
APS_Lab 0:f06ed53310a3 292 uint32_t counter = 0;
APS_Lab 0:f06ed53310a3 293 uint8_t finished = 0;
APS_Lab 0:f06ed53310a3 294 uint8_t current_time = 0;
APS_Lab 0:f06ed53310a3 295 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 296 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 297
APS_Lab 0:f06ed53310a3 298
APS_Lab 0:f06ed53310a3 299 cmd[0] = 0x07;
APS_Lab 0:f06ed53310a3 300 cmd[1] = 0x14;
APS_Lab 0:f06ed53310a3 301 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 302 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 303 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 304
APS_Lab 1:4dd3e328a30b 305 cs_low();
APS_Lab 0:f06ed53310a3 306 spi_write_array(4,cmd);
APS_Lab 0:f06ed53310a3 307
APS_Lab 0:f06ed53310a3 308 while ((counter<200000)&&(finished == 0)) {
APS_Lab 0:f06ed53310a3 309 current_time = spi_read_byte(0xff);
APS_Lab 0:f06ed53310a3 310 if (current_time>0) {
APS_Lab 0:f06ed53310a3 311 finished = 1;
APS_Lab 0:f06ed53310a3 312 } else {
APS_Lab 0:f06ed53310a3 313 counter = counter + 10;
APS_Lab 0:f06ed53310a3 314 }
APS_Lab 0:f06ed53310a3 315 }
APS_Lab 1:4dd3e328a30b 316 cs_high();
APS_Lab 1:4dd3e328a30b 317
APS_Lab 0:f06ed53310a3 318
APS_Lab 0:f06ed53310a3 319 return(counter);
APS_Lab 0:f06ed53310a3 320 }
APS_Lab 0:f06ed53310a3 321
APS_Lab 0:f06ed53310a3 322 //Start a GPIO and Vref2 Conversion
APS_Lab 0:f06ed53310a3 323 void LTC681x_adax(
APS_Lab 0:f06ed53310a3 324 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 325 uint8_t CHG //GPIO Channels to be measured)
APS_Lab 0:f06ed53310a3 326 )
APS_Lab 0:f06ed53310a3 327 {
APS_Lab 0:f06ed53310a3 328 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 329 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 330
APS_Lab 0:f06ed53310a3 331 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 332 cmd[0] = md_bits + 0x04;
APS_Lab 0:f06ed53310a3 333 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 334 cmd[1] = md_bits + 0x60 + CHG ;
APS_Lab 0:f06ed53310a3 335 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 336
APS_Lab 0:f06ed53310a3 337 }
APS_Lab 0:f06ed53310a3 338
APS_Lab 0:f06ed53310a3 339 //Start an GPIO Redundancy test
APS_Lab 0:f06ed53310a3 340 void LTC681x_adaxd(
APS_Lab 0:f06ed53310a3 341 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 342 uint8_t CHG //GPIO Channels to be measured)
APS_Lab 0:f06ed53310a3 343 )
APS_Lab 0:f06ed53310a3 344 {
APS_Lab 0:f06ed53310a3 345 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 346 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 347
APS_Lab 0:f06ed53310a3 348 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 349 cmd[0] = md_bits + 0x04;
APS_Lab 0:f06ed53310a3 350 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 351 cmd[1] = md_bits + CHG ;
APS_Lab 0:f06ed53310a3 352 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 353 }
APS_Lab 0:f06ed53310a3 354
APS_Lab 0:f06ed53310a3 355 //Start a Status ADC Conversion
APS_Lab 0:f06ed53310a3 356 void LTC681x_adstat(
APS_Lab 0:f06ed53310a3 357 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 358 uint8_t CHST //GPIO Channels to be measured
APS_Lab 0:f06ed53310a3 359 )
APS_Lab 0:f06ed53310a3 360 {
APS_Lab 0:f06ed53310a3 361 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 362 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 363
APS_Lab 0:f06ed53310a3 364 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 365 cmd[0] = md_bits + 0x04;
APS_Lab 0:f06ed53310a3 366 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 367 cmd[1] = md_bits + 0x68 + CHST ;
APS_Lab 0:f06ed53310a3 368 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 369 }
APS_Lab 0:f06ed53310a3 370
APS_Lab 0:f06ed53310a3 371 // Start a Status register redundancy test Conversion
APS_Lab 0:f06ed53310a3 372 void LTC681x_adstatd(
APS_Lab 0:f06ed53310a3 373 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 374 uint8_t CHST //GPIO Channels to be measured
APS_Lab 0:f06ed53310a3 375 )
APS_Lab 0:f06ed53310a3 376 {
APS_Lab 0:f06ed53310a3 377 uint8_t cmd[2];
APS_Lab 0:f06ed53310a3 378 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 379
APS_Lab 0:f06ed53310a3 380 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 381 cmd[0] = md_bits + 0x04;
APS_Lab 0:f06ed53310a3 382 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 383 cmd[1] = md_bits + 0x08 + CHST ;
APS_Lab 0:f06ed53310a3 384 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 385
APS_Lab 0:f06ed53310a3 386 }
APS_Lab 0:f06ed53310a3 387
APS_Lab 0:f06ed53310a3 388
APS_Lab 0:f06ed53310a3 389 // Start an open wire Conversion
APS_Lab 0:f06ed53310a3 390 void LTC681x_adow(
APS_Lab 0:f06ed53310a3 391 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 392 uint8_t PUP //Discharge Permit
APS_Lab 0:f06ed53310a3 393 )
APS_Lab 0:f06ed53310a3 394 {
APS_Lab 0:f06ed53310a3 395 uint8_t cmd[2];
APS_Lab 0:f06ed53310a3 396 uint8_t md_bits;
APS_Lab 0:f06ed53310a3 397 md_bits = (MD & 0x02) >> 1;
APS_Lab 0:f06ed53310a3 398 cmd[0] = md_bits + 0x02;
APS_Lab 0:f06ed53310a3 399 md_bits = (MD & 0x01) << 7;
APS_Lab 0:f06ed53310a3 400 cmd[1] = md_bits + 0x28 + (PUP<<6) ;//+ CH;
APS_Lab 0:f06ed53310a3 401 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 402 }
APS_Lab 0:f06ed53310a3 403
APS_Lab 0:f06ed53310a3 404 // Reads the raw cell voltage register data
APS_Lab 0:f06ed53310a3 405 void LTC681x_rdcv_reg(uint8_t reg, //Determines which cell voltage register is read back
APS_Lab 0:f06ed53310a3 406 uint8_t total_ic, //the number of ICs in the
APS_Lab 0:f06ed53310a3 407 uint8_t *data //An array of the unparsed cell codes
APS_Lab 0:f06ed53310a3 408 )
APS_Lab 0:f06ed53310a3 409 {
APS_Lab 0:f06ed53310a3 410 const uint8_t REG_LEN = 8; //number of bytes in each ICs register + 2 bytes for the PEC
APS_Lab 0:f06ed53310a3 411 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 412 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 413
APS_Lab 0:f06ed53310a3 414 if (reg == 1) { //1: RDCVA
APS_Lab 0:f06ed53310a3 415 cmd[1] = 0x04;
APS_Lab 0:f06ed53310a3 416 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 417 } else if (reg == 2) { //2: RDCVB
APS_Lab 0:f06ed53310a3 418 cmd[1] = 0x06;
APS_Lab 0:f06ed53310a3 419 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 420 } else if (reg == 3) { //3: RDCVC
APS_Lab 0:f06ed53310a3 421 cmd[1] = 0x08;
APS_Lab 0:f06ed53310a3 422 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 423 } else if (reg == 4) { //4: RDCVD
APS_Lab 0:f06ed53310a3 424 cmd[1] = 0x0A;
APS_Lab 0:f06ed53310a3 425 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 426 } else if (reg == 5) { //4: RDCVE
APS_Lab 0:f06ed53310a3 427 cmd[1] = 0x09;
APS_Lab 0:f06ed53310a3 428 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 429 } else if (reg == 6) { //4: RDCVF
APS_Lab 0:f06ed53310a3 430 cmd[1] = 0x0B;
APS_Lab 0:f06ed53310a3 431 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 432 }
APS_Lab 0:f06ed53310a3 433
APS_Lab 0:f06ed53310a3 434
APS_Lab 0:f06ed53310a3 435 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 436 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 437 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 438
APS_Lab 1:4dd3e328a30b 439 cs_low();
APS_Lab 0:f06ed53310a3 440 spi_write_read(cmd,4,data,(REG_LEN*total_ic));
APS_Lab 1:4dd3e328a30b 441 cs_high();
APS_Lab 0:f06ed53310a3 442
APS_Lab 0:f06ed53310a3 443 }
APS_Lab 0:f06ed53310a3 444
APS_Lab 0:f06ed53310a3 445 //helper function that parses voltage measurement registers
APS_Lab 0:f06ed53310a3 446 int8_t parse_cells(uint8_t current_ic, uint8_t cell_reg, uint8_t cell_data[], uint16_t *cell_codes, uint8_t *ic_pec)
APS_Lab 0:f06ed53310a3 447 {
APS_Lab 0:f06ed53310a3 448
APS_Lab 0:f06ed53310a3 449 const uint8_t BYT_IN_REG = 6;
APS_Lab 0:f06ed53310a3 450 const uint8_t CELL_IN_REG = 3;
APS_Lab 0:f06ed53310a3 451 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 452 uint16_t parsed_cell;
APS_Lab 0:f06ed53310a3 453 uint16_t received_pec;
APS_Lab 0:f06ed53310a3 454 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 455 uint8_t data_counter = current_ic*NUM_RX_BYT; //data counter
APS_Lab 0:f06ed53310a3 456
APS_Lab 0:f06ed53310a3 457
APS_Lab 0:f06ed53310a3 458 for (uint8_t current_cell = 0; current_cell<CELL_IN_REG; current_cell++) { // This loop parses the read back data into cell voltages, it
APS_Lab 0:f06ed53310a3 459 // loops once for each of the 3 cell voltage codes in the register
APS_Lab 0:f06ed53310a3 460
APS_Lab 0:f06ed53310a3 461 parsed_cell = cell_data[data_counter] + (cell_data[data_counter + 1] << 8);//Each cell code is received as two bytes and is combined to
APS_Lab 0:f06ed53310a3 462 // create the parsed cell voltage code
APS_Lab 0:f06ed53310a3 463 cell_codes[current_cell + ((cell_reg - 1) * CELL_IN_REG)] = parsed_cell;
APS_Lab 0:f06ed53310a3 464 data_counter = data_counter + 2; //Because cell voltage codes are two bytes the data counter
APS_Lab 0:f06ed53310a3 465 //must increment by two for each parsed cell code
APS_Lab 0:f06ed53310a3 466 }
APS_Lab 0:f06ed53310a3 467
APS_Lab 0:f06ed53310a3 468 received_pec = (cell_data[data_counter] << 8) | cell_data[data_counter+1]; //The received PEC for the current_ic is transmitted as the 7th and 8th
APS_Lab 0:f06ed53310a3 469 //after the 6 cell voltage data bytes
APS_Lab 0:f06ed53310a3 470 data_pec = pec15_calc(BYT_IN_REG, &cell_data[(current_ic) * NUM_RX_BYT]);
APS_Lab 0:f06ed53310a3 471
APS_Lab 0:f06ed53310a3 472 if (received_pec != data_pec) {
APS_Lab 0:f06ed53310a3 473 pec_error = 1; //The pec_error variable is simply set negative if any PEC errors
APS_Lab 0:f06ed53310a3 474 ic_pec[cell_reg-1]=1;
APS_Lab 0:f06ed53310a3 475 } else {
APS_Lab 0:f06ed53310a3 476 ic_pec[cell_reg-1]=0;
APS_Lab 0:f06ed53310a3 477 }
APS_Lab 0:f06ed53310a3 478 data_counter=data_counter+2;
APS_Lab 0:f06ed53310a3 479 return(pec_error);
APS_Lab 0:f06ed53310a3 480 }
APS_Lab 0:f06ed53310a3 481
APS_Lab 0:f06ed53310a3 482 /*
APS_Lab 0:f06ed53310a3 483 The function reads a single GPIO voltage register and stores thre read data
APS_Lab 0:f06ed53310a3 484 in the *data point as a byte array. This function is rarely used outside of
APS_Lab 0:f06ed53310a3 485 the LTC6811_rdaux() command.
APS_Lab 0:f06ed53310a3 486 */
APS_Lab 0:f06ed53310a3 487 void LTC681x_rdaux_reg(uint8_t reg, //Determines which GPIO voltage register is read back
APS_Lab 0:f06ed53310a3 488 uint8_t total_ic, //The number of ICs in the system
APS_Lab 0:f06ed53310a3 489 uint8_t *data //Array of the unparsed auxiliary codes
APS_Lab 0:f06ed53310a3 490 )
APS_Lab 0:f06ed53310a3 491 {
APS_Lab 0:f06ed53310a3 492 const uint8_t REG_LEN = 8; // number of bytes in the register + 2 bytes for the PEC
APS_Lab 0:f06ed53310a3 493 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 494 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 495
APS_Lab 0:f06ed53310a3 496
APS_Lab 0:f06ed53310a3 497 if (reg == 1) { //Read back auxiliary group A
APS_Lab 0:f06ed53310a3 498 cmd[1] = 0x0C;
APS_Lab 0:f06ed53310a3 499 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 500 } else if (reg == 2) { //Read back auxiliary group B
APS_Lab 0:f06ed53310a3 501 cmd[1] = 0x0e;
APS_Lab 0:f06ed53310a3 502 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 503 } else if (reg == 3) { //Read back auxiliary group C
APS_Lab 0:f06ed53310a3 504 cmd[1] = 0x0D;
APS_Lab 0:f06ed53310a3 505 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 506 } else if (reg == 4) { //Read back auxiliary group D
APS_Lab 0:f06ed53310a3 507 cmd[1] = 0x0F;
APS_Lab 0:f06ed53310a3 508 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 509 } else { //Read back auxiliary group A
APS_Lab 0:f06ed53310a3 510 cmd[1] = 0x0C;
APS_Lab 0:f06ed53310a3 511 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 512 }
APS_Lab 0:f06ed53310a3 513
APS_Lab 0:f06ed53310a3 514 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 515 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 516 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 517
APS_Lab 1:4dd3e328a30b 518 cs_low();
APS_Lab 0:f06ed53310a3 519 spi_write_read(cmd,4,data,(REG_LEN*total_ic));
APS_Lab 1:4dd3e328a30b 520 cs_high();
APS_Lab 0:f06ed53310a3 521
APS_Lab 0:f06ed53310a3 522 }
APS_Lab 0:f06ed53310a3 523
APS_Lab 0:f06ed53310a3 524 /*
APS_Lab 0:f06ed53310a3 525 The function reads a single stat register and stores the read data
APS_Lab 0:f06ed53310a3 526 in the *data point as a byte array. This function is rarely used outside of
APS_Lab 0:f06ed53310a3 527 the LTC6811_rdstat() command.
APS_Lab 0:f06ed53310a3 528 */
APS_Lab 0:f06ed53310a3 529 void LTC681x_rdstat_reg(uint8_t reg, //Determines which stat register is read back
APS_Lab 0:f06ed53310a3 530 uint8_t total_ic, //The number of ICs in the system
APS_Lab 0:f06ed53310a3 531 uint8_t *data //Array of the unparsed stat codes
APS_Lab 0:f06ed53310a3 532 )
APS_Lab 0:f06ed53310a3 533 {
APS_Lab 0:f06ed53310a3 534 const uint8_t REG_LEN = 8; // number of bytes in the register + 2 bytes for the PEC
APS_Lab 0:f06ed53310a3 535 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 536 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 537
APS_Lab 0:f06ed53310a3 538
APS_Lab 0:f06ed53310a3 539 if (reg == 1) { //Read back statiliary group A
APS_Lab 0:f06ed53310a3 540 cmd[1] = 0x10;
APS_Lab 0:f06ed53310a3 541 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 542 } else if (reg == 2) { //Read back statiliary group B
APS_Lab 0:f06ed53310a3 543 cmd[1] = 0x12;
APS_Lab 0:f06ed53310a3 544 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 545 }
APS_Lab 0:f06ed53310a3 546
APS_Lab 0:f06ed53310a3 547 else { //Read back statiliary group A
APS_Lab 0:f06ed53310a3 548 cmd[1] = 0x10;
APS_Lab 0:f06ed53310a3 549 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 550 }
APS_Lab 0:f06ed53310a3 551
APS_Lab 0:f06ed53310a3 552 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 553 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 554 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 555
APS_Lab 1:4dd3e328a30b 556 cs_low();
APS_Lab 0:f06ed53310a3 557 spi_write_read(cmd,4,data,(REG_LEN*total_ic));
APS_Lab 1:4dd3e328a30b 558 cs_high();
APS_Lab 0:f06ed53310a3 559
APS_Lab 0:f06ed53310a3 560 }
APS_Lab 0:f06ed53310a3 561
APS_Lab 0:f06ed53310a3 562 /*
APS_Lab 0:f06ed53310a3 563 The command clears the cell voltage registers and intiallizes
APS_Lab 0:f06ed53310a3 564 all values to 1. The register will read back hexadecimal 0xFF
APS_Lab 0:f06ed53310a3 565 after the command is sent.
APS_Lab 0:f06ed53310a3 566 */
APS_Lab 0:f06ed53310a3 567 void LTC681x_clrcell()
APS_Lab 0:f06ed53310a3 568 {
APS_Lab 0:f06ed53310a3 569 uint8_t cmd[2]= {0x07 , 0x11};
APS_Lab 0:f06ed53310a3 570 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 571 }
APS_Lab 0:f06ed53310a3 572
APS_Lab 0:f06ed53310a3 573
APS_Lab 0:f06ed53310a3 574 /*
APS_Lab 0:f06ed53310a3 575 The command clears the Auxiliary registers and initializes
APS_Lab 0:f06ed53310a3 576 all values to 1. The register will read back hexadecimal 0xFF
APS_Lab 0:f06ed53310a3 577 after the command is sent.
APS_Lab 0:f06ed53310a3 578 */
APS_Lab 0:f06ed53310a3 579 void LTC681x_clraux()
APS_Lab 0:f06ed53310a3 580 {
APS_Lab 0:f06ed53310a3 581 uint8_t cmd[2]= {0x07 , 0x12};
APS_Lab 0:f06ed53310a3 582 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 583 }
APS_Lab 0:f06ed53310a3 584
APS_Lab 0:f06ed53310a3 585
APS_Lab 0:f06ed53310a3 586 /*
APS_Lab 0:f06ed53310a3 587 The command clears the Stat registers and intiallizes
APS_Lab 0:f06ed53310a3 588 all values to 1. The register will read back hexadecimal 0xFF
APS_Lab 0:f06ed53310a3 589 after the command is sent.
APS_Lab 0:f06ed53310a3 590
APS_Lab 0:f06ed53310a3 591 */
APS_Lab 0:f06ed53310a3 592 void LTC681x_clrstat()
APS_Lab 0:f06ed53310a3 593 {
APS_Lab 0:f06ed53310a3 594 uint8_t cmd[2]= {0x07 , 0x13};
APS_Lab 0:f06ed53310a3 595 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 596 }
APS_Lab 0:f06ed53310a3 597 /*
APS_Lab 0:f06ed53310a3 598 The command clears the Sctrl registers and initializes
APS_Lab 0:f06ed53310a3 599 all values to 0. The register will read back hexadecimal 0x00
APS_Lab 0:f06ed53310a3 600 after the command is sent.
APS_Lab 0:f06ed53310a3 601 */
APS_Lab 0:f06ed53310a3 602 void LTC681x_clrsctrl()
APS_Lab 0:f06ed53310a3 603 {
APS_Lab 0:f06ed53310a3 604 uint8_t cmd[2]= {0x00 , 0x18};
APS_Lab 0:f06ed53310a3 605 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 606 }
APS_Lab 0:f06ed53310a3 607 //Starts the Mux Decoder diagnostic self test
APS_Lab 0:f06ed53310a3 608 void LTC681x_diagn()
APS_Lab 0:f06ed53310a3 609 {
APS_Lab 0:f06ed53310a3 610 uint8_t cmd[2] = {0x07 , 0x15};
APS_Lab 0:f06ed53310a3 611 cmd_68(cmd);
APS_Lab 0:f06ed53310a3 612 }
APS_Lab 0:f06ed53310a3 613
APS_Lab 0:f06ed53310a3 614 //Reads and parses the LTC681x cell voltage registers.
APS_Lab 0:f06ed53310a3 615 uint8_t LTC681x_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
APS_Lab 0:f06ed53310a3 616 uint8_t total_ic, // the number of ICs in the system
APS_Lab 0:f06ed53310a3 617 cell_asic ic[] // Array of the parsed cell codes
APS_Lab 0:f06ed53310a3 618 )
APS_Lab 0:f06ed53310a3 619 {
APS_Lab 0:f06ed53310a3 620 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 621 uint8_t *cell_data;
APS_Lab 0:f06ed53310a3 622 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 623 cell_data = (uint8_t *) malloc((NUM_RX_BYT*total_ic)*sizeof(uint8_t));
APS_Lab 0:f06ed53310a3 624
APS_Lab 0:f06ed53310a3 625 if (reg == 0) {
takuma1 2:3bbbe439ec11 626 for (uint8_t cell_reg = 1; cell_reg<ic[0].ic_reg.num_cv_reg+1; cell_reg++) { //
takuma1 2:3bbbe439ec11 627
APS_Lab 0:f06ed53310a3 628 LTC681x_rdcv_reg(cell_reg, total_ic,cell_data );
APS_Lab 0:f06ed53310a3 629 for (int current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 630 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 631 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 632 } else {
APS_Lab 0:f06ed53310a3 633 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 634 }
APS_Lab 0:f06ed53310a3 635 pec_error = pec_error + parse_cells(current_ic,cell_reg, cell_data,
APS_Lab 0:f06ed53310a3 636 &ic[c_ic].cells.c_codes[0],
APS_Lab 0:f06ed53310a3 637 &ic[c_ic].cells.pec_match[0]);
APS_Lab 0:f06ed53310a3 638 }
APS_Lab 0:f06ed53310a3 639 }
APS_Lab 0:f06ed53310a3 640 }
APS_Lab 0:f06ed53310a3 641
APS_Lab 0:f06ed53310a3 642 else {
APS_Lab 0:f06ed53310a3 643 LTC681x_rdcv_reg(reg, total_ic,cell_data);
APS_Lab 0:f06ed53310a3 644
APS_Lab 0:f06ed53310a3 645 for (int current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 646 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 647 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 648 } else {
APS_Lab 0:f06ed53310a3 649 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 650 }
APS_Lab 0:f06ed53310a3 651 pec_error = pec_error + parse_cells(current_ic,reg, &cell_data[8*c_ic],
APS_Lab 0:f06ed53310a3 652 &ic[c_ic].cells.c_codes[0],
APS_Lab 0:f06ed53310a3 653 &ic[c_ic].cells.pec_match[0]);
APS_Lab 0:f06ed53310a3 654 }
APS_Lab 0:f06ed53310a3 655 }
APS_Lab 0:f06ed53310a3 656 LTC681x_check_pec(total_ic,CELL,ic);
APS_Lab 0:f06ed53310a3 657 free(cell_data);
APS_Lab 0:f06ed53310a3 658 return(pec_error);
APS_Lab 0:f06ed53310a3 659 }
APS_Lab 0:f06ed53310a3 660
APS_Lab 0:f06ed53310a3 661
APS_Lab 0:f06ed53310a3 662
APS_Lab 0:f06ed53310a3 663 /*
APS_Lab 0:f06ed53310a3 664 The function is used
APS_Lab 0:f06ed53310a3 665 to read the parsed GPIO codes of the LTC6811. This function will send the requested
APS_Lab 0:f06ed53310a3 666 read commands parse the data and store the gpio voltages in aux_codes variable
APS_Lab 0:f06ed53310a3 667 */
APS_Lab 0:f06ed53310a3 668 int8_t LTC681x_rdaux(uint8_t reg, //Determines which GPIO voltage register is read back.
APS_Lab 0:f06ed53310a3 669 uint8_t total_ic,//the number of ICs in the system
APS_Lab 0:f06ed53310a3 670 cell_asic ic[]//A two dimensional array of the gpio voltage codes.
APS_Lab 0:f06ed53310a3 671 )
APS_Lab 0:f06ed53310a3 672 {
APS_Lab 0:f06ed53310a3 673 uint8_t *data;
APS_Lab 0:f06ed53310a3 674 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 675 uint8_t c_ic =0;
APS_Lab 0:f06ed53310a3 676 data = (uint8_t *) malloc((NUM_RX_BYT*total_ic)*sizeof(uint8_t));
APS_Lab 0:f06ed53310a3 677
APS_Lab 0:f06ed53310a3 678 if (reg == 0) {
APS_Lab 0:f06ed53310a3 679 for (uint8_t gpio_reg = 1; gpio_reg<ic[0].ic_reg.num_gpio_reg+1; gpio_reg++) { //executes once for each of the LTC6811 aux voltage registers
APS_Lab 0:f06ed53310a3 680 LTC681x_rdaux_reg(gpio_reg, total_ic,data); //Reads the raw auxiliary register data into the data[] array
APS_Lab 0:f06ed53310a3 681 for (int current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 682 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 683 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 684 } else {
APS_Lab 0:f06ed53310a3 685 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 686 }
APS_Lab 0:f06ed53310a3 687 pec_error = parse_cells(current_ic,gpio_reg, data,
APS_Lab 0:f06ed53310a3 688 &ic[c_ic].aux.a_codes[0],
APS_Lab 0:f06ed53310a3 689 &ic[c_ic].aux.pec_match[0]);
APS_Lab 0:f06ed53310a3 690
APS_Lab 0:f06ed53310a3 691 }
APS_Lab 0:f06ed53310a3 692 }
APS_Lab 0:f06ed53310a3 693 } else {
APS_Lab 0:f06ed53310a3 694 LTC681x_rdaux_reg(reg, total_ic, data);
APS_Lab 0:f06ed53310a3 695
APS_Lab 0:f06ed53310a3 696 for (int current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 697 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 698 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 699 } else {
APS_Lab 0:f06ed53310a3 700 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 701 }
APS_Lab 0:f06ed53310a3 702 pec_error = parse_cells(current_ic,reg, data,
APS_Lab 0:f06ed53310a3 703 &ic[c_ic].aux.a_codes[0],
APS_Lab 0:f06ed53310a3 704 &ic[c_ic].aux.pec_match[0]);
APS_Lab 0:f06ed53310a3 705 }
APS_Lab 0:f06ed53310a3 706
APS_Lab 0:f06ed53310a3 707 }
APS_Lab 0:f06ed53310a3 708 LTC681x_check_pec(total_ic,AUX,ic);
APS_Lab 0:f06ed53310a3 709 free(data);
APS_Lab 0:f06ed53310a3 710 return (pec_error);
APS_Lab 0:f06ed53310a3 711 }
APS_Lab 0:f06ed53310a3 712
APS_Lab 0:f06ed53310a3 713 // Reads and parses the LTC681x stat registers.
APS_Lab 0:f06ed53310a3 714 int8_t LTC681x_rdstat(uint8_t reg, //Determines which Stat register is read back.
APS_Lab 0:f06ed53310a3 715 uint8_t total_ic,//the number of ICs in the system
APS_Lab 0:f06ed53310a3 716 cell_asic ic[]
APS_Lab 0:f06ed53310a3 717 )
APS_Lab 0:f06ed53310a3 718
APS_Lab 0:f06ed53310a3 719 {
APS_Lab 0:f06ed53310a3 720
APS_Lab 0:f06ed53310a3 721 const uint8_t BYT_IN_REG = 6;
APS_Lab 0:f06ed53310a3 722 const uint8_t GPIO_IN_REG = 3;
APS_Lab 0:f06ed53310a3 723
APS_Lab 0:f06ed53310a3 724 uint8_t *data;
APS_Lab 0:f06ed53310a3 725 uint8_t data_counter = 0;
APS_Lab 0:f06ed53310a3 726 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 727 uint16_t parsed_stat;
APS_Lab 0:f06ed53310a3 728 uint16_t received_pec;
APS_Lab 0:f06ed53310a3 729 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 730 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 731 data = (uint8_t *) malloc((NUM_RX_BYT*total_ic)*sizeof(uint8_t));
APS_Lab 0:f06ed53310a3 732
APS_Lab 0:f06ed53310a3 733 if (reg == 0) {
APS_Lab 0:f06ed53310a3 734
APS_Lab 0:f06ed53310a3 735 for (uint8_t stat_reg = 1; stat_reg< 3; stat_reg++) { //executes once for each of the LTC6811 stat voltage registers
APS_Lab 0:f06ed53310a3 736 data_counter = 0;
APS_Lab 0:f06ed53310a3 737 LTC681x_rdstat_reg(stat_reg, total_ic,data); //Reads the raw statiliary register data into the data[] array
APS_Lab 0:f06ed53310a3 738
APS_Lab 0:f06ed53310a3 739 for (uint8_t current_ic = 0 ; current_ic < total_ic; current_ic++) { // executes for every LTC6811 in the daisy chain
APS_Lab 0:f06ed53310a3 740 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 741 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 742 } else {
APS_Lab 0:f06ed53310a3 743 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 744 }
APS_Lab 0:f06ed53310a3 745 // current_ic is used as the IC counter
APS_Lab 0:f06ed53310a3 746 if (stat_reg ==1) {
APS_Lab 0:f06ed53310a3 747 for (uint8_t current_gpio = 0; current_gpio< GPIO_IN_REG; current_gpio++) { // This loop parses the read back data into GPIO voltages, it
APS_Lab 0:f06ed53310a3 748 // loops once for each of the 3 gpio voltage codes in the register
APS_Lab 0:f06ed53310a3 749
APS_Lab 0:f06ed53310a3 750 parsed_stat = data[data_counter] + (data[data_counter+1]<<8); //Each gpio codes is received as two bytes and is combined to
APS_Lab 0:f06ed53310a3 751 ic[c_ic].stat.stat_codes[current_gpio] = parsed_stat;
APS_Lab 0:f06ed53310a3 752 data_counter=data_counter+2; //Because gpio voltage codes are two bytes the data counter
APS_Lab 0:f06ed53310a3 753
APS_Lab 0:f06ed53310a3 754 }
APS_Lab 0:f06ed53310a3 755 } else if (stat_reg == 2) {
APS_Lab 0:f06ed53310a3 756 parsed_stat = data[data_counter] + (data[data_counter+1]<<8); //Each gpio codes is received as two bytes and is combined to
APS_Lab 0:f06ed53310a3 757 data_counter = data_counter +2;
APS_Lab 0:f06ed53310a3 758 ic[c_ic].stat.stat_codes[3] = parsed_stat;
APS_Lab 0:f06ed53310a3 759 ic[c_ic].stat.flags[0] = data[data_counter++];
APS_Lab 0:f06ed53310a3 760 ic[c_ic].stat.flags[1] = data[data_counter++];
APS_Lab 0:f06ed53310a3 761 ic[c_ic].stat.flags[2] = data[data_counter++];
APS_Lab 0:f06ed53310a3 762 ic[c_ic].stat.mux_fail[0] = (data[data_counter] & 0x02)>>1;
APS_Lab 0:f06ed53310a3 763 ic[c_ic].stat.thsd[0] = data[data_counter++] & 0x01;
APS_Lab 0:f06ed53310a3 764 }
APS_Lab 0:f06ed53310a3 765
APS_Lab 0:f06ed53310a3 766 received_pec = (data[data_counter]<<8)+ data[data_counter+1]; //The received PEC for the current_ic is transmitted as the 7th and 8th
APS_Lab 0:f06ed53310a3 767 //after the 6 gpio voltage data bytes
APS_Lab 0:f06ed53310a3 768 data_pec = pec15_calc(BYT_IN_REG, &data[current_ic*NUM_RX_BYT]);
APS_Lab 0:f06ed53310a3 769
APS_Lab 0:f06ed53310a3 770 if (received_pec != data_pec) {
APS_Lab 0:f06ed53310a3 771 pec_error = -1; //The pec_error variable is simply set negative if any PEC errors
APS_Lab 0:f06ed53310a3 772 ic[c_ic].stat.pec_match[stat_reg-1]=1;
APS_Lab 0:f06ed53310a3 773 //are detected in the received serial data
APS_Lab 0:f06ed53310a3 774 } else {
APS_Lab 0:f06ed53310a3 775 ic[c_ic].stat.pec_match[stat_reg-1]=0;
APS_Lab 0:f06ed53310a3 776 }
APS_Lab 0:f06ed53310a3 777
APS_Lab 0:f06ed53310a3 778 data_counter=data_counter+2; //Because the transmitted PEC code is 2 bytes long the data_counter
APS_Lab 0:f06ed53310a3 779 //must be incremented by 2 bytes to point to the next ICs gpio voltage data
APS_Lab 0:f06ed53310a3 780 }
APS_Lab 0:f06ed53310a3 781
APS_Lab 0:f06ed53310a3 782
APS_Lab 0:f06ed53310a3 783 }
APS_Lab 0:f06ed53310a3 784
APS_Lab 0:f06ed53310a3 785 } else {
APS_Lab 0:f06ed53310a3 786
APS_Lab 0:f06ed53310a3 787 LTC681x_rdstat_reg(reg, total_ic, data);
APS_Lab 0:f06ed53310a3 788 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) { // executes for every LTC6811 in the daisy chain
APS_Lab 0:f06ed53310a3 789 // current_ic is used as an IC counter
APS_Lab 0:f06ed53310a3 790 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 791 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 792 } else {
APS_Lab 0:f06ed53310a3 793 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 794 }
APS_Lab 0:f06ed53310a3 795 if (reg ==1) {
APS_Lab 0:f06ed53310a3 796 for (uint8_t current_gpio = 0; current_gpio< GPIO_IN_REG; current_gpio++) { // This loop parses the read back data into GPIO voltages, it
APS_Lab 0:f06ed53310a3 797 // loops once for each of the 3 gpio voltage codes in the register
APS_Lab 0:f06ed53310a3 798 parsed_stat = data[data_counter] + (data[data_counter+1]<<8); //Each gpio codes is received as two bytes and is combined to
APS_Lab 0:f06ed53310a3 799 // create the parsed gpio voltage code
APS_Lab 0:f06ed53310a3 800
APS_Lab 0:f06ed53310a3 801 ic[c_ic].stat.stat_codes[current_gpio] = parsed_stat;
APS_Lab 0:f06ed53310a3 802 data_counter=data_counter+2; //Because gpio voltage codes are two bytes the data counter
APS_Lab 0:f06ed53310a3 803 //must increment by two for each parsed gpio voltage code
APS_Lab 0:f06ed53310a3 804
APS_Lab 0:f06ed53310a3 805 }
APS_Lab 0:f06ed53310a3 806 } else if (reg == 2) {
APS_Lab 0:f06ed53310a3 807 parsed_stat = data[data_counter++] + (data[data_counter++]<<8); //Each gpio codes is received as two bytes and is combined to
APS_Lab 0:f06ed53310a3 808 ic[c_ic].stat.stat_codes[3] = parsed_stat;
APS_Lab 0:f06ed53310a3 809 ic[c_ic].stat.flags[0] = data[data_counter++];
APS_Lab 0:f06ed53310a3 810 ic[c_ic].stat.flags[1] = data[data_counter++];
APS_Lab 0:f06ed53310a3 811 ic[c_ic].stat.flags[2] = data[data_counter++];
APS_Lab 0:f06ed53310a3 812 ic[c_ic].stat.mux_fail[0] = (data[data_counter] & 0x02)>>1;
APS_Lab 0:f06ed53310a3 813 ic[c_ic].stat.thsd[0] = data[data_counter++] & 0x01;
APS_Lab 0:f06ed53310a3 814 }
APS_Lab 0:f06ed53310a3 815
APS_Lab 0:f06ed53310a3 816
APS_Lab 0:f06ed53310a3 817 received_pec = (data[data_counter]<<8)+ data[data_counter+1]; //The received PEC for the current_ic is transmitted as the 7th and 8th
APS_Lab 0:f06ed53310a3 818 //after the 6 gpio voltage data bytes
APS_Lab 0:f06ed53310a3 819 data_pec = pec15_calc(BYT_IN_REG, &data[current_ic*NUM_RX_BYT]);
APS_Lab 0:f06ed53310a3 820 if (received_pec != data_pec) {
APS_Lab 0:f06ed53310a3 821 pec_error = -1; //The pec_error variable is simply set negative if any PEC errors
APS_Lab 0:f06ed53310a3 822 ic[c_ic].stat.pec_match[reg-1]=1;
APS_Lab 0:f06ed53310a3 823
APS_Lab 0:f06ed53310a3 824 }
APS_Lab 0:f06ed53310a3 825
APS_Lab 0:f06ed53310a3 826 data_counter=data_counter+2;
APS_Lab 0:f06ed53310a3 827 }
APS_Lab 0:f06ed53310a3 828 }
APS_Lab 0:f06ed53310a3 829 LTC681x_check_pec(total_ic,STAT,ic);
APS_Lab 0:f06ed53310a3 830 free(data);
APS_Lab 0:f06ed53310a3 831 return (pec_error);
APS_Lab 0:f06ed53310a3 832 }
APS_Lab 0:f06ed53310a3 833
APS_Lab 0:f06ed53310a3 834 //Write the LTC681x CFGRA
APS_Lab 0:f06ed53310a3 835 void LTC681x_wrcfg(uint8_t total_ic, //The number of ICs being written to
APS_Lab 0:f06ed53310a3 836 cell_asic ic[]
APS_Lab 0:f06ed53310a3 837 )
APS_Lab 0:f06ed53310a3 838 {
APS_Lab 0:f06ed53310a3 839 uint8_t cmd[2] = {0x00 , 0x01} ;
APS_Lab 0:f06ed53310a3 840 uint8_t write_buffer[256];
APS_Lab 0:f06ed53310a3 841 uint8_t write_count = 0;
APS_Lab 0:f06ed53310a3 842 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 843 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 844 if (ic->isospi_reverse == true) {
APS_Lab 0:f06ed53310a3 845 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 846 } else {
APS_Lab 0:f06ed53310a3 847 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 848 }
APS_Lab 0:f06ed53310a3 849
APS_Lab 0:f06ed53310a3 850 for (uint8_t data = 0; data<6; data++) {
APS_Lab 0:f06ed53310a3 851 write_buffer[write_count] = ic[c_ic].config.tx_data[data];
APS_Lab 0:f06ed53310a3 852 write_count++;
APS_Lab 0:f06ed53310a3 853 }
APS_Lab 0:f06ed53310a3 854 }
APS_Lab 0:f06ed53310a3 855 write_68(total_ic, cmd, write_buffer);
APS_Lab 0:f06ed53310a3 856 }
APS_Lab 0:f06ed53310a3 857
APS_Lab 0:f06ed53310a3 858 //Write the LTC681x CFGRB
APS_Lab 0:f06ed53310a3 859 void LTC681x_wrcfgb(uint8_t total_ic, //The number of ICs being written to
APS_Lab 0:f06ed53310a3 860 cell_asic ic[]
APS_Lab 0:f06ed53310a3 861 )
APS_Lab 0:f06ed53310a3 862 {
APS_Lab 0:f06ed53310a3 863 uint8_t cmd[2] = {0x00 , 0x24} ;
APS_Lab 0:f06ed53310a3 864 uint8_t write_buffer[256];
APS_Lab 0:f06ed53310a3 865 uint8_t write_count = 0;
APS_Lab 0:f06ed53310a3 866 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 867 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 868 if (ic->isospi_reverse == true) {
APS_Lab 0:f06ed53310a3 869 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 870 } else {
APS_Lab 0:f06ed53310a3 871 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 872 }
APS_Lab 0:f06ed53310a3 873
APS_Lab 0:f06ed53310a3 874 for (uint8_t data = 0; data<6; data++) {
APS_Lab 0:f06ed53310a3 875 write_buffer[write_count] = ic[c_ic].configb.tx_data[data];
APS_Lab 0:f06ed53310a3 876 write_count++;
APS_Lab 0:f06ed53310a3 877 }
APS_Lab 0:f06ed53310a3 878 }
APS_Lab 0:f06ed53310a3 879 write_68(total_ic, cmd, write_buffer);
APS_Lab 0:f06ed53310a3 880 }
APS_Lab 0:f06ed53310a3 881
APS_Lab 0:f06ed53310a3 882 //Read CFGA
APS_Lab 0:f06ed53310a3 883 int8_t LTC681x_rdcfg(uint8_t total_ic, //Number of ICs in the system
APS_Lab 0:f06ed53310a3 884 cell_asic ic[]
APS_Lab 0:f06ed53310a3 885 )
APS_Lab 0:f06ed53310a3 886 {
APS_Lab 0:f06ed53310a3 887 uint8_t cmd[2]= {0x00 , 0x02};
APS_Lab 0:f06ed53310a3 888 uint8_t read_buffer[256];
APS_Lab 0:f06ed53310a3 889 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 890 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 891 uint16_t calc_pec;
APS_Lab 0:f06ed53310a3 892 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 893 pec_error = read_68(total_ic, cmd, read_buffer);
APS_Lab 0:f06ed53310a3 894 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 895 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 896 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 897 } else {
APS_Lab 0:f06ed53310a3 898 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 899 }
APS_Lab 0:f06ed53310a3 900
APS_Lab 0:f06ed53310a3 901 for (int byte=0; byte<8; byte++) {
APS_Lab 0:f06ed53310a3 902 ic[c_ic].config.rx_data[byte] = read_buffer[byte+(8*current_ic)];
APS_Lab 0:f06ed53310a3 903 }
APS_Lab 0:f06ed53310a3 904 calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
APS_Lab 0:f06ed53310a3 905 data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
APS_Lab 0:f06ed53310a3 906 if (calc_pec != data_pec ) {
APS_Lab 0:f06ed53310a3 907 ic[c_ic].config.rx_pec_match = 1;
APS_Lab 0:f06ed53310a3 908 } else ic[c_ic].config.rx_pec_match = 0;
APS_Lab 0:f06ed53310a3 909 }
APS_Lab 0:f06ed53310a3 910 LTC681x_check_pec(total_ic,CFGR,ic);
APS_Lab 0:f06ed53310a3 911 return(pec_error);
APS_Lab 0:f06ed53310a3 912 }
APS_Lab 0:f06ed53310a3 913
APS_Lab 0:f06ed53310a3 914 //Reads CFGB
APS_Lab 0:f06ed53310a3 915 int8_t LTC681x_rdcfgb(uint8_t total_ic, //Number of ICs in the system
APS_Lab 0:f06ed53310a3 916 cell_asic ic[]
APS_Lab 0:f06ed53310a3 917 )
APS_Lab 0:f06ed53310a3 918 {
APS_Lab 0:f06ed53310a3 919 uint8_t cmd[2]= {0x00 , 0x26};
APS_Lab 0:f06ed53310a3 920 uint8_t read_buffer[256];
APS_Lab 0:f06ed53310a3 921 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 922 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 923 uint16_t calc_pec;
APS_Lab 0:f06ed53310a3 924 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 925 pec_error = read_68(total_ic, cmd, read_buffer);
APS_Lab 0:f06ed53310a3 926 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 927 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 928 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 929 } else {
APS_Lab 0:f06ed53310a3 930 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 931 }
APS_Lab 0:f06ed53310a3 932
APS_Lab 0:f06ed53310a3 933 for (int byte=0; byte<8; byte++) {
APS_Lab 0:f06ed53310a3 934 ic[c_ic].configb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
APS_Lab 0:f06ed53310a3 935 }
APS_Lab 0:f06ed53310a3 936 calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
APS_Lab 0:f06ed53310a3 937 data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
APS_Lab 0:f06ed53310a3 938 if (calc_pec != data_pec ) {
APS_Lab 0:f06ed53310a3 939 ic[c_ic].configb.rx_pec_match = 1;
APS_Lab 0:f06ed53310a3 940 } else ic[c_ic].configb.rx_pec_match = 0;
APS_Lab 0:f06ed53310a3 941 }
APS_Lab 0:f06ed53310a3 942 LTC681x_check_pec(total_ic,CFGRB,ic);
APS_Lab 0:f06ed53310a3 943 return(pec_error);
APS_Lab 0:f06ed53310a3 944 }
APS_Lab 0:f06ed53310a3 945
APS_Lab 0:f06ed53310a3 946 //Looks up the result pattern for digital filter self test
APS_Lab 0:f06ed53310a3 947 uint16_t LTC681x_st_lookup(
APS_Lab 0:f06ed53310a3 948 uint8_t MD, //ADC Mode
APS_Lab 0:f06ed53310a3 949 uint8_t ST //Self Test
APS_Lab 0:f06ed53310a3 950 )
APS_Lab 0:f06ed53310a3 951 {
APS_Lab 0:f06ed53310a3 952 uint16_t test_pattern = 0;
APS_Lab 0:f06ed53310a3 953 if (MD == 1) {
APS_Lab 0:f06ed53310a3 954 if (ST == 1) {
APS_Lab 0:f06ed53310a3 955 test_pattern = 0x9565;
APS_Lab 0:f06ed53310a3 956 } else {
APS_Lab 0:f06ed53310a3 957 test_pattern = 0x6A9A;
APS_Lab 0:f06ed53310a3 958 }
APS_Lab 0:f06ed53310a3 959 } else {
APS_Lab 0:f06ed53310a3 960 if (ST == 1) {
APS_Lab 0:f06ed53310a3 961 test_pattern = 0x9555;
APS_Lab 0:f06ed53310a3 962 } else {
APS_Lab 0:f06ed53310a3 963 test_pattern = 0x6AAA;
APS_Lab 0:f06ed53310a3 964 }
APS_Lab 0:f06ed53310a3 965 }
APS_Lab 0:f06ed53310a3 966 return(test_pattern);
APS_Lab 0:f06ed53310a3 967 }
APS_Lab 0:f06ed53310a3 968
APS_Lab 0:f06ed53310a3 969 //Clears all of the DCC bits in the configuration registers
APS_Lab 0:f06ed53310a3 970 void clear_discharge(uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 971 {
APS_Lab 0:f06ed53310a3 972 for (int i=0; i<total_ic; i++) {
APS_Lab 0:f06ed53310a3 973 ic[i].config.tx_data[4] = 0;
APS_Lab 0:f06ed53310a3 974 ic[i].config.tx_data[5] = 0;
APS_Lab 0:f06ed53310a3 975 }
APS_Lab 0:f06ed53310a3 976 }
APS_Lab 0:f06ed53310a3 977
APS_Lab 0:f06ed53310a3 978 // Runs the Digital Filter Self Test
APS_Lab 0:f06ed53310a3 979 int16_t LTC681x_run_cell_adc_st(uint8_t adc_reg,uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 980 {
APS_Lab 0:f06ed53310a3 981 int16_t error = 0;
APS_Lab 0:f06ed53310a3 982 uint16_t expected_result = 0;
APS_Lab 0:f06ed53310a3 983 for (int self_test = 1; self_test<3; self_test++) {
APS_Lab 0:f06ed53310a3 984
APS_Lab 0:f06ed53310a3 985 expected_result = LTC681x_st_lookup(2,self_test);
APS_Lab 0:f06ed53310a3 986 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 987 switch (adc_reg) {
APS_Lab 0:f06ed53310a3 988 case CELL:
APS_Lab 0:f06ed53310a3 989 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 990 LTC681x_clrcell();
APS_Lab 0:f06ed53310a3 991 LTC681x_cvst(2,self_test);
APS_Lab 0:f06ed53310a3 992 LTC681x_pollAdc();//this isn't working
APS_Lab 0:f06ed53310a3 993 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 994 error = LTC681x_rdcv(0, total_ic,ic);
APS_Lab 0:f06ed53310a3 995 for (int cic = 0; cic < total_ic; cic++) {
APS_Lab 0:f06ed53310a3 996 for (int channel=0; channel< ic[cic].ic_reg.cell_channels; channel++) {
APS_Lab 0:f06ed53310a3 997 if (ic[cic].cells.c_codes[channel] != expected_result) {
APS_Lab 0:f06ed53310a3 998 error = error+1;
APS_Lab 0:f06ed53310a3 999 }
APS_Lab 0:f06ed53310a3 1000 }
APS_Lab 0:f06ed53310a3 1001 }
APS_Lab 0:f06ed53310a3 1002 break;
APS_Lab 0:f06ed53310a3 1003 case AUX:
APS_Lab 0:f06ed53310a3 1004 error = 0;
APS_Lab 0:f06ed53310a3 1005 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1006 LTC681x_clraux();
APS_Lab 0:f06ed53310a3 1007 LTC681x_axst(2,self_test);
APS_Lab 0:f06ed53310a3 1008 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1009 delay_m(10);
APS_Lab 0:f06ed53310a3 1010 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1011 LTC681x_rdaux(0, total_ic,ic);
APS_Lab 0:f06ed53310a3 1012 for (int cic = 0; cic < total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1013 for (int channel=0; channel< ic[cic].ic_reg.aux_channels; channel++) {
APS_Lab 0:f06ed53310a3 1014 if (ic[cic].aux.a_codes[channel] != expected_result) {
APS_Lab 0:f06ed53310a3 1015 error = error+1;
APS_Lab 0:f06ed53310a3 1016 }
APS_Lab 0:f06ed53310a3 1017 }
APS_Lab 0:f06ed53310a3 1018 }
APS_Lab 0:f06ed53310a3 1019 break;
APS_Lab 0:f06ed53310a3 1020 case STAT:
APS_Lab 0:f06ed53310a3 1021 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1022 LTC681x_clrstat();
APS_Lab 0:f06ed53310a3 1023 LTC681x_statst(2,self_test);
APS_Lab 0:f06ed53310a3 1024 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1025 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1026 error = LTC681x_rdstat(0,total_ic,ic);
APS_Lab 0:f06ed53310a3 1027 for (int cic = 0; cic < total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1028 for (int channel=0; channel< ic[cic].ic_reg.stat_channels; channel++) {
APS_Lab 0:f06ed53310a3 1029 if (ic[cic].stat.stat_codes[channel] != expected_result) {
APS_Lab 0:f06ed53310a3 1030 error = error+1;
APS_Lab 0:f06ed53310a3 1031 }
APS_Lab 0:f06ed53310a3 1032 }
APS_Lab 0:f06ed53310a3 1033 }
APS_Lab 0:f06ed53310a3 1034 break;
APS_Lab 0:f06ed53310a3 1035
APS_Lab 0:f06ed53310a3 1036 default:
APS_Lab 0:f06ed53310a3 1037 error = -1;
APS_Lab 0:f06ed53310a3 1038 break;
APS_Lab 0:f06ed53310a3 1039 }
APS_Lab 0:f06ed53310a3 1040 }
APS_Lab 0:f06ed53310a3 1041 return(error);
APS_Lab 0:f06ed53310a3 1042 }
APS_Lab 0:f06ed53310a3 1043
APS_Lab 0:f06ed53310a3 1044 //runs the redundancy self test
APS_Lab 0:f06ed53310a3 1045 int16_t LTC681x_run_adc_redundancy_st(uint8_t adc_mode, uint8_t adc_reg, uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 1046 {
APS_Lab 0:f06ed53310a3 1047 int16_t error = 0;
APS_Lab 0:f06ed53310a3 1048 for (int self_test = 1; self_test<3; self_test++) {
APS_Lab 0:f06ed53310a3 1049 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1050 switch (adc_reg) {
APS_Lab 0:f06ed53310a3 1051 case AUX:
APS_Lab 0:f06ed53310a3 1052 LTC681x_clraux();
APS_Lab 0:f06ed53310a3 1053 LTC681x_adaxd(adc_mode,AUX_CH_ALL);
APS_Lab 0:f06ed53310a3 1054 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1055 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1056 error = LTC681x_rdaux(0, total_ic,ic);
APS_Lab 0:f06ed53310a3 1057 for (int cic = 0; cic < total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1058 for (int channel=0; channel< ic[cic].ic_reg.aux_channels; channel++) {
APS_Lab 0:f06ed53310a3 1059 if (ic[cic].aux.a_codes[channel] >= 65280) {
APS_Lab 0:f06ed53310a3 1060 error = error+1;
APS_Lab 0:f06ed53310a3 1061 }
APS_Lab 0:f06ed53310a3 1062 }
APS_Lab 0:f06ed53310a3 1063 }
APS_Lab 0:f06ed53310a3 1064 break;
APS_Lab 0:f06ed53310a3 1065 case STAT:
APS_Lab 0:f06ed53310a3 1066 LTC681x_clrstat();
APS_Lab 0:f06ed53310a3 1067 LTC681x_adstatd(adc_mode,STAT_CH_ALL);
APS_Lab 0:f06ed53310a3 1068 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1069 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1070 error = LTC681x_rdstat(0,total_ic,ic);
APS_Lab 0:f06ed53310a3 1071 for (int cic = 0; cic < total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1072 for (int channel=0; channel< ic[cic].ic_reg.stat_channels; channel++) {
APS_Lab 0:f06ed53310a3 1073 if (ic[cic].stat.stat_codes[channel] >= 65280) {
APS_Lab 0:f06ed53310a3 1074 error = error+1;
APS_Lab 0:f06ed53310a3 1075 }
APS_Lab 0:f06ed53310a3 1076 }
APS_Lab 0:f06ed53310a3 1077 }
APS_Lab 0:f06ed53310a3 1078 break;
APS_Lab 0:f06ed53310a3 1079
APS_Lab 0:f06ed53310a3 1080 default:
APS_Lab 0:f06ed53310a3 1081 error = -1;
APS_Lab 0:f06ed53310a3 1082 break;
APS_Lab 0:f06ed53310a3 1083 }
APS_Lab 0:f06ed53310a3 1084 }
APS_Lab 0:f06ed53310a3 1085 return(error);
APS_Lab 0:f06ed53310a3 1086 }
APS_Lab 0:f06ed53310a3 1087
takuma1 2:3bbbe439ec11 1088 //Runs the datasheet algorithm for open wire //オープンワイヤに対してデータシートアルゴリズムを実行します
APS_Lab 0:f06ed53310a3 1089 void LTC681x_run_openwire(uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 1090 {
APS_Lab 0:f06ed53310a3 1091 uint16_t OPENWIRE_THRESHOLD = 4000;
APS_Lab 0:f06ed53310a3 1092 const uint8_t N_CHANNELS = ic[0].ic_reg.cell_channels;
APS_Lab 0:f06ed53310a3 1093
APS_Lab 0:f06ed53310a3 1094 cell_asic pullUp_cell_codes[total_ic];
APS_Lab 0:f06ed53310a3 1095 cell_asic pullDwn_cell_codes[total_ic];
APS_Lab 0:f06ed53310a3 1096 cell_asic openWire_delta[total_ic];
APS_Lab 0:f06ed53310a3 1097 int8_t error;
APS_Lab 0:f06ed53310a3 1098
APS_Lab 0:f06ed53310a3 1099 wakeup_sleep(total_ic);
APS_Lab 0:f06ed53310a3 1100 LTC681x_adow(MD_7KHZ_3KHZ,PULL_UP_CURRENT);
APS_Lab 0:f06ed53310a3 1101 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1102 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1103 LTC681x_adow(MD_7KHZ_3KHZ,PULL_UP_CURRENT);
APS_Lab 0:f06ed53310a3 1104 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1105 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1106 error = LTC681x_rdcv(0, total_ic,pullUp_cell_codes);
APS_Lab 0:f06ed53310a3 1107
APS_Lab 0:f06ed53310a3 1108 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1109 LTC681x_adow(MD_7KHZ_3KHZ,PULL_DOWN_CURRENT);
APS_Lab 0:f06ed53310a3 1110 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1111 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1112 LTC681x_adow(MD_7KHZ_3KHZ,PULL_DOWN_CURRENT);
APS_Lab 0:f06ed53310a3 1113 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1114 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1115 error = LTC681x_rdcv(0, total_ic,pullDwn_cell_codes);
APS_Lab 0:f06ed53310a3 1116
APS_Lab 0:f06ed53310a3 1117 for (int cic=0; cic<total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1118 ic[cic].system_open_wire =0;
APS_Lab 0:f06ed53310a3 1119 for (int cell=0; cell<N_CHANNELS; cell++) {
APS_Lab 0:f06ed53310a3 1120 if (pullDwn_cell_codes[cic].cells.c_codes[cell]>pullUp_cell_codes[cic].cells.c_codes[cell]) {
APS_Lab 0:f06ed53310a3 1121 openWire_delta[cic].cells.c_codes[cell] = pullDwn_cell_codes[cic].cells.c_codes[cell] - pullUp_cell_codes[cic].cells.c_codes[cell] ;
APS_Lab 0:f06ed53310a3 1122 } else {
APS_Lab 0:f06ed53310a3 1123 openWire_delta[cic].cells.c_codes[cell] = 0;
APS_Lab 0:f06ed53310a3 1124 }
APS_Lab 0:f06ed53310a3 1125
APS_Lab 0:f06ed53310a3 1126 }
APS_Lab 0:f06ed53310a3 1127 }
APS_Lab 0:f06ed53310a3 1128 for (int cic=0; cic<total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1129 for (int cell=1; cell<N_CHANNELS; cell++) {
APS_Lab 0:f06ed53310a3 1130
APS_Lab 0:f06ed53310a3 1131 if (openWire_delta[cic].cells.c_codes[cell]>OPENWIRE_THRESHOLD) {
APS_Lab 0:f06ed53310a3 1132 ic[cic].system_open_wire += (1<<cell);
APS_Lab 0:f06ed53310a3 1133
APS_Lab 0:f06ed53310a3 1134 }
APS_Lab 0:f06ed53310a3 1135 }
APS_Lab 0:f06ed53310a3 1136 if (pullUp_cell_codes[cic].cells.c_codes[0] == 0) {
APS_Lab 0:f06ed53310a3 1137 ic[cic].system_open_wire += 1;
APS_Lab 0:f06ed53310a3 1138 }
APS_Lab 0:f06ed53310a3 1139 if (pullUp_cell_codes[cic].cells.c_codes[N_CHANNELS-1] == 0) {
APS_Lab 0:f06ed53310a3 1140 ic[cic].system_open_wire += (1<<(N_CHANNELS));
APS_Lab 0:f06ed53310a3 1141 }
APS_Lab 0:f06ed53310a3 1142 }
APS_Lab 0:f06ed53310a3 1143 }
APS_Lab 0:f06ed53310a3 1144
APS_Lab 0:f06ed53310a3 1145 // Runs the ADC overlap test for the IC
APS_Lab 0:f06ed53310a3 1146 uint16_t LTC681x_run_adc_overlap(uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 1147 {
APS_Lab 0:f06ed53310a3 1148 uint16_t error = 0;
APS_Lab 0:f06ed53310a3 1149 int32_t measure_delta =0;
APS_Lab 0:f06ed53310a3 1150 int16_t failure_pos_limit = 20;
APS_Lab 0:f06ed53310a3 1151 int16_t failure_neg_limit = -20;
APS_Lab 0:f06ed53310a3 1152 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1153 LTC681x_adol(MD_7KHZ_3KHZ,DCP_DISABLED);
APS_Lab 0:f06ed53310a3 1154 LTC681x_pollAdc();
APS_Lab 0:f06ed53310a3 1155 wakeup_idle(total_ic);
APS_Lab 0:f06ed53310a3 1156 error = LTC681x_rdcv(0, total_ic,ic);
APS_Lab 0:f06ed53310a3 1157 for (int cic = 0; cic<total_ic; cic++) {
APS_Lab 0:f06ed53310a3 1158 measure_delta = (int32_t)ic[cic].cells.c_codes[6]-(int32_t)ic[cic].cells.c_codes[7];
APS_Lab 0:f06ed53310a3 1159 if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit)) {
APS_Lab 0:f06ed53310a3 1160 error = error | (1<<(cic-1));
APS_Lab 0:f06ed53310a3 1161 }
APS_Lab 0:f06ed53310a3 1162 }
APS_Lab 0:f06ed53310a3 1163 return(error);
APS_Lab 0:f06ed53310a3 1164 }
APS_Lab 0:f06ed53310a3 1165
APS_Lab 0:f06ed53310a3 1166 //Helper function that increments PEC counters
APS_Lab 0:f06ed53310a3 1167 void LTC681x_check_pec(uint8_t total_ic,uint8_t reg, cell_asic ic[])
APS_Lab 0:f06ed53310a3 1168 {
APS_Lab 0:f06ed53310a3 1169 switch (reg) {
APS_Lab 0:f06ed53310a3 1170 case CFGR:
APS_Lab 0:f06ed53310a3 1171 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1172 ic[current_ic].crc_count.pec_count = ic[current_ic].crc_count.pec_count + ic[current_ic].config.rx_pec_match;
APS_Lab 0:f06ed53310a3 1173 ic[current_ic].crc_count.cfgr_pec = ic[current_ic].crc_count.cfgr_pec + ic[current_ic].config.rx_pec_match;
APS_Lab 0:f06ed53310a3 1174 }
APS_Lab 0:f06ed53310a3 1175 break;
APS_Lab 0:f06ed53310a3 1176
APS_Lab 0:f06ed53310a3 1177 case CFGRB:
APS_Lab 0:f06ed53310a3 1178 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1179 ic[current_ic].crc_count.pec_count = ic[current_ic].crc_count.pec_count + ic[current_ic].configb.rx_pec_match;
APS_Lab 0:f06ed53310a3 1180 ic[current_ic].crc_count.cfgr_pec = ic[current_ic].crc_count.cfgr_pec + ic[current_ic].configb.rx_pec_match;
APS_Lab 0:f06ed53310a3 1181 }
APS_Lab 0:f06ed53310a3 1182 break;
APS_Lab 0:f06ed53310a3 1183 case CELL:
APS_Lab 0:f06ed53310a3 1184 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1185 for (int i=0; i<ic[0].ic_reg.num_cv_reg; i++) {
APS_Lab 0:f06ed53310a3 1186 ic[current_ic].crc_count.pec_count = ic[current_ic].crc_count.pec_count + ic[current_ic].cells.pec_match[i];
APS_Lab 0:f06ed53310a3 1187 ic[current_ic].crc_count.cell_pec[i] = ic[current_ic].crc_count.cell_pec[i] + ic[current_ic].cells.pec_match[i];
APS_Lab 0:f06ed53310a3 1188 }
APS_Lab 0:f06ed53310a3 1189 }
APS_Lab 0:f06ed53310a3 1190 break;
APS_Lab 0:f06ed53310a3 1191 case AUX:
APS_Lab 0:f06ed53310a3 1192 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1193 for (int i=0; i<ic[0].ic_reg.num_gpio_reg; i++) {
APS_Lab 0:f06ed53310a3 1194 ic[current_ic].crc_count.pec_count = ic[current_ic].crc_count.pec_count + (ic[current_ic].aux.pec_match[i]);
APS_Lab 0:f06ed53310a3 1195 ic[current_ic].crc_count.aux_pec[i] = ic[current_ic].crc_count.aux_pec[i] + (ic[current_ic].aux.pec_match[i]);
APS_Lab 0:f06ed53310a3 1196 }
APS_Lab 0:f06ed53310a3 1197 }
APS_Lab 0:f06ed53310a3 1198
APS_Lab 0:f06ed53310a3 1199 break;
APS_Lab 0:f06ed53310a3 1200 case STAT:
APS_Lab 0:f06ed53310a3 1201 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1202
APS_Lab 0:f06ed53310a3 1203 for (int i=0; i<ic[0].ic_reg.num_stat_reg-1; i++) {
APS_Lab 0:f06ed53310a3 1204 ic[current_ic].crc_count.pec_count = ic[current_ic].crc_count.pec_count + ic[current_ic].stat.pec_match[i];
APS_Lab 0:f06ed53310a3 1205 ic[current_ic].crc_count.stat_pec[i] = ic[current_ic].crc_count.stat_pec[i] + ic[current_ic].stat.pec_match[i];
APS_Lab 0:f06ed53310a3 1206 }
APS_Lab 0:f06ed53310a3 1207 }
APS_Lab 0:f06ed53310a3 1208 break;
APS_Lab 0:f06ed53310a3 1209 default:
APS_Lab 0:f06ed53310a3 1210 break;
APS_Lab 0:f06ed53310a3 1211 }
APS_Lab 0:f06ed53310a3 1212 }
APS_Lab 0:f06ed53310a3 1213
APS_Lab 0:f06ed53310a3 1214 //Helper Function to reset PEC counters
APS_Lab 0:f06ed53310a3 1215 void LTC681x_reset_crc_count(uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 1216 {
APS_Lab 0:f06ed53310a3 1217 for (int current_ic = 0 ; current_ic < total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1218 ic[current_ic].crc_count.pec_count = 0;
APS_Lab 0:f06ed53310a3 1219 ic[current_ic].crc_count.cfgr_pec = 0;
APS_Lab 0:f06ed53310a3 1220 for (int i=0; i<6; i++) {
APS_Lab 0:f06ed53310a3 1221 ic[current_ic].crc_count.cell_pec[i]=0;
APS_Lab 0:f06ed53310a3 1222
APS_Lab 0:f06ed53310a3 1223 }
APS_Lab 0:f06ed53310a3 1224 for (int i=0; i<4; i++) {
APS_Lab 0:f06ed53310a3 1225 ic[current_ic].crc_count.aux_pec[i]=0;
APS_Lab 0:f06ed53310a3 1226 }
APS_Lab 0:f06ed53310a3 1227 for (int i=0; i<2; i++) {
APS_Lab 0:f06ed53310a3 1228 ic[current_ic].crc_count.stat_pec[i]=0;
APS_Lab 0:f06ed53310a3 1229 }
APS_Lab 0:f06ed53310a3 1230 }
APS_Lab 0:f06ed53310a3 1231 }
APS_Lab 0:f06ed53310a3 1232
APS_Lab 0:f06ed53310a3 1233 //Helper function to intialize CFG variables.
APS_Lab 0:f06ed53310a3 1234 void LTC681x_init_cfg(uint8_t total_ic, cell_asic ic[])
APS_Lab 0:f06ed53310a3 1235 {
APS_Lab 0:f06ed53310a3 1236 bool REFON = true;
APS_Lab 0:f06ed53310a3 1237 bool ADCOPT = false;
APS_Lab 0:f06ed53310a3 1238 bool gpioBits[5] = {true,true,true,true,true};
APS_Lab 0:f06ed53310a3 1239 bool dccBits[12] = {false,false,false,false,false,false,false,false,false,false,false,false};
APS_Lab 0:f06ed53310a3 1240 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1241 for (int j =0; j<6; j++) {
APS_Lab 0:f06ed53310a3 1242 ic[current_ic].config.tx_data[j] = 0;
APS_Lab 0:f06ed53310a3 1243 ic[current_ic].configb.tx_data[j] = 0;
APS_Lab 0:f06ed53310a3 1244 }
APS_Lab 0:f06ed53310a3 1245 LTC681x_set_cfgr(current_ic ,ic,REFON,ADCOPT,gpioBits,dccBits);
APS_Lab 0:f06ed53310a3 1246
APS_Lab 0:f06ed53310a3 1247 }
APS_Lab 0:f06ed53310a3 1248 }
APS_Lab 0:f06ed53310a3 1249
APS_Lab 0:f06ed53310a3 1250 //Helper function to set CFGR variable
APS_Lab 0:f06ed53310a3 1251 void LTC681x_set_cfgr(uint8_t nIC, cell_asic ic[], bool refon, bool adcopt, bool gpio[5],bool dcc[12])
APS_Lab 0:f06ed53310a3 1252 {
APS_Lab 0:f06ed53310a3 1253 LTC681x_set_cfgr_refon(nIC,ic,refon);
APS_Lab 0:f06ed53310a3 1254 LTC681x_set_cfgr_adcopt(nIC,ic,adcopt);
APS_Lab 0:f06ed53310a3 1255 LTC681x_set_cfgr_gpio(nIC,ic,gpio);
APS_Lab 0:f06ed53310a3 1256 LTC681x_set_cfgr_dis(nIC,ic,dcc);
APS_Lab 0:f06ed53310a3 1257 }
APS_Lab 0:f06ed53310a3 1258
APS_Lab 0:f06ed53310a3 1259 //Helper function to set the REFON bit
APS_Lab 0:f06ed53310a3 1260 void LTC681x_set_cfgr_refon(uint8_t nIC, cell_asic ic[], bool refon)
APS_Lab 0:f06ed53310a3 1261 {
APS_Lab 0:f06ed53310a3 1262 if (refon) ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]|0x04;
APS_Lab 0:f06ed53310a3 1263 else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]&0xFB;
APS_Lab 0:f06ed53310a3 1264 }
APS_Lab 0:f06ed53310a3 1265
APS_Lab 0:f06ed53310a3 1266 //Helper function to set the adcopt bit
APS_Lab 0:f06ed53310a3 1267 void LTC681x_set_cfgr_adcopt(uint8_t nIC, cell_asic ic[], bool adcopt)
APS_Lab 0:f06ed53310a3 1268 {
APS_Lab 0:f06ed53310a3 1269 if (adcopt) ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]|0x01;
APS_Lab 0:f06ed53310a3 1270 else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]&0xFE;
APS_Lab 0:f06ed53310a3 1271 }
APS_Lab 0:f06ed53310a3 1272
APS_Lab 0:f06ed53310a3 1273 //Helper function to set GPIO bits
APS_Lab 0:f06ed53310a3 1274 void LTC681x_set_cfgr_gpio(uint8_t nIC, cell_asic ic[],bool gpio[5])
APS_Lab 0:f06ed53310a3 1275 {
APS_Lab 0:f06ed53310a3 1276 for (int i =0; i<5; i++) {
APS_Lab 0:f06ed53310a3 1277 if (gpio[i])ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]|(0x01<<(i+3));
APS_Lab 0:f06ed53310a3 1278 else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0]&(~(0x01<<(i+3)));
APS_Lab 0:f06ed53310a3 1279 }
APS_Lab 0:f06ed53310a3 1280 }
APS_Lab 0:f06ed53310a3 1281
APS_Lab 0:f06ed53310a3 1282 //Helper function to control discharge
APS_Lab 0:f06ed53310a3 1283 void LTC681x_set_cfgr_dis(uint8_t nIC, cell_asic ic[],bool dcc[12])
APS_Lab 0:f06ed53310a3 1284 {
APS_Lab 0:f06ed53310a3 1285 for (int i =0; i<8; i++) {
APS_Lab 0:f06ed53310a3 1286 if (dcc[i])ic[nIC].config.tx_data[4] = ic[nIC].config.tx_data[4]|(0x01<<i);
APS_Lab 0:f06ed53310a3 1287 else ic[nIC].config.tx_data[4] = ic[nIC].config.tx_data[4]& (~(0x01<<i));
APS_Lab 0:f06ed53310a3 1288 }
APS_Lab 0:f06ed53310a3 1289 for (int i =0; i<4; i++) {
APS_Lab 0:f06ed53310a3 1290 if (dcc[i+8])ic[nIC].config.tx_data[5] = ic[nIC].config.tx_data[5]|(0x01<<i);
APS_Lab 0:f06ed53310a3 1291 else ic[nIC].config.tx_data[5] = ic[nIC].config.tx_data[5]&(~(0x01<<i));
APS_Lab 0:f06ed53310a3 1292 }
APS_Lab 0:f06ed53310a3 1293 }
APS_Lab 0:f06ed53310a3 1294
APS_Lab 0:f06ed53310a3 1295 //Helper Function to set uv value in CFG register
APS_Lab 0:f06ed53310a3 1296 void LTC681x_set_cfgr_uv(uint8_t nIC, cell_asic ic[],uint16_t uv)
APS_Lab 0:f06ed53310a3 1297 {
APS_Lab 0:f06ed53310a3 1298 uint16_t tmp = (uv/16)-1;
APS_Lab 0:f06ed53310a3 1299 ic[nIC].config.tx_data[1] = 0x00FF & tmp;
APS_Lab 0:f06ed53310a3 1300 ic[nIC].config.tx_data[2] = ic[nIC].config.tx_data[2]&0xF0;
APS_Lab 0:f06ed53310a3 1301 ic[nIC].config.tx_data[2] = ic[nIC].config.tx_data[2]|((0x0F00 & tmp)>>8);
APS_Lab 0:f06ed53310a3 1302 }
APS_Lab 0:f06ed53310a3 1303
APS_Lab 0:f06ed53310a3 1304 //helper function to set OV value in CFG register
APS_Lab 0:f06ed53310a3 1305 void LTC681x_set_cfgr_ov(uint8_t nIC, cell_asic ic[],uint16_t ov)
APS_Lab 0:f06ed53310a3 1306 {
APS_Lab 0:f06ed53310a3 1307 uint16_t tmp = (ov/16);
APS_Lab 0:f06ed53310a3 1308 ic[nIC].config.tx_data[3] = 0x00FF & (tmp>>4);
APS_Lab 0:f06ed53310a3 1309 ic[nIC].config.tx_data[2] = ic[nIC].config.tx_data[2]&0x0F;
APS_Lab 0:f06ed53310a3 1310 ic[nIC].config.tx_data[2] = ic[nIC].config.tx_data[2]|((0x000F & tmp)<<4);
APS_Lab 0:f06ed53310a3 1311 }
APS_Lab 0:f06ed53310a3 1312
APS_Lab 0:f06ed53310a3 1313 //Writes the comm register
APS_Lab 0:f06ed53310a3 1314 void LTC681x_wrcomm(uint8_t total_ic, //The number of ICs being written to
APS_Lab 0:f06ed53310a3 1315 cell_asic ic[]
APS_Lab 0:f06ed53310a3 1316 )
APS_Lab 0:f06ed53310a3 1317 {
APS_Lab 0:f06ed53310a3 1318 uint8_t cmd[2]= {0x07 , 0x21};
APS_Lab 0:f06ed53310a3 1319 uint8_t write_buffer[256];
APS_Lab 0:f06ed53310a3 1320 uint8_t write_count = 0;
APS_Lab 0:f06ed53310a3 1321 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 1322 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1323 if (ic->isospi_reverse == true) {
APS_Lab 0:f06ed53310a3 1324 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 1325 } else {
APS_Lab 0:f06ed53310a3 1326 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 1327 }
APS_Lab 0:f06ed53310a3 1328
APS_Lab 0:f06ed53310a3 1329 for (uint8_t data = 0; data<6; data++) {
APS_Lab 0:f06ed53310a3 1330 write_buffer[write_count] = ic[c_ic].com.tx_data[data];
APS_Lab 0:f06ed53310a3 1331 write_count++;
APS_Lab 0:f06ed53310a3 1332 }
APS_Lab 0:f06ed53310a3 1333 }
APS_Lab 0:f06ed53310a3 1334 write_68(total_ic, cmd, write_buffer);
APS_Lab 0:f06ed53310a3 1335 }
APS_Lab 0:f06ed53310a3 1336
APS_Lab 0:f06ed53310a3 1337 /*
APS_Lab 0:f06ed53310a3 1338 Reads COMM registers of a LTC6811 daisy chain
APS_Lab 0:f06ed53310a3 1339 */
APS_Lab 0:f06ed53310a3 1340 int8_t LTC681x_rdcomm(uint8_t total_ic, //Number of ICs in the system
APS_Lab 0:f06ed53310a3 1341 cell_asic ic[]
APS_Lab 0:f06ed53310a3 1342 )
APS_Lab 0:f06ed53310a3 1343 {
APS_Lab 0:f06ed53310a3 1344 uint8_t cmd[2]= {0x07 , 0x22};
APS_Lab 0:f06ed53310a3 1345 uint8_t read_buffer[256];
APS_Lab 0:f06ed53310a3 1346 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 1347 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 1348 uint16_t calc_pec;
APS_Lab 0:f06ed53310a3 1349 uint8_t c_ic=0;
APS_Lab 0:f06ed53310a3 1350 pec_error = read_68(total_ic, cmd, read_buffer);
APS_Lab 0:f06ed53310a3 1351 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1352 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 1353 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 1354 } else {
APS_Lab 0:f06ed53310a3 1355 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 1356 }
APS_Lab 0:f06ed53310a3 1357
APS_Lab 0:f06ed53310a3 1358 for (int byte=0; byte<8; byte++) {
APS_Lab 0:f06ed53310a3 1359 ic[c_ic].com.rx_data[byte] = read_buffer[byte+(8*current_ic)];
APS_Lab 0:f06ed53310a3 1360 }
APS_Lab 0:f06ed53310a3 1361 calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
APS_Lab 0:f06ed53310a3 1362 data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
APS_Lab 0:f06ed53310a3 1363 if (calc_pec != data_pec ) {
APS_Lab 0:f06ed53310a3 1364 ic[c_ic].com.rx_pec_match = 1;
APS_Lab 0:f06ed53310a3 1365 } else ic[c_ic].com.rx_pec_match = 0;
APS_Lab 0:f06ed53310a3 1366 }
APS_Lab 0:f06ed53310a3 1367 return(pec_error);
APS_Lab 0:f06ed53310a3 1368 }
APS_Lab 0:f06ed53310a3 1369
APS_Lab 0:f06ed53310a3 1370 /*
APS_Lab 0:f06ed53310a3 1371 Shifts data in COMM register out over LTC6811 SPI/I2C port
APS_Lab 0:f06ed53310a3 1372 */
APS_Lab 0:f06ed53310a3 1373 void LTC681x_stcomm()
APS_Lab 0:f06ed53310a3 1374 {
APS_Lab 0:f06ed53310a3 1375
APS_Lab 0:f06ed53310a3 1376 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 1377 uint16_t cmd_pec;
APS_Lab 0:f06ed53310a3 1378
APS_Lab 0:f06ed53310a3 1379 cmd[0] = 0x07;
APS_Lab 0:f06ed53310a3 1380 cmd[1] = 0x23;
APS_Lab 0:f06ed53310a3 1381 cmd_pec = pec15_calc(2, cmd);
APS_Lab 0:f06ed53310a3 1382 cmd[2] = (uint8_t)(cmd_pec >> 8);
APS_Lab 0:f06ed53310a3 1383 cmd[3] = (uint8_t)(cmd_pec);
APS_Lab 0:f06ed53310a3 1384
APS_Lab 1:4dd3e328a30b 1385 cs_low();
APS_Lab 0:f06ed53310a3 1386 spi_write_array(4,cmd);
APS_Lab 0:f06ed53310a3 1387 for (int i = 0; i<9; i++) {
APS_Lab 0:f06ed53310a3 1388 spi_read_byte(0xFF);
APS_Lab 0:f06ed53310a3 1389 }
APS_Lab 1:4dd3e328a30b 1390 cs_high();
APS_Lab 0:f06ed53310a3 1391
APS_Lab 0:f06ed53310a3 1392 }
APS_Lab 0:f06ed53310a3 1393
APS_Lab 0:f06ed53310a3 1394 // Writes the pwm register
APS_Lab 0:f06ed53310a3 1395 void LTC681x_wrpwm(uint8_t total_ic,
APS_Lab 0:f06ed53310a3 1396 uint8_t pwmReg,
APS_Lab 0:f06ed53310a3 1397 cell_asic ic[]
APS_Lab 0:f06ed53310a3 1398 )
APS_Lab 0:f06ed53310a3 1399 {
APS_Lab 0:f06ed53310a3 1400 uint8_t cmd[2];
APS_Lab 0:f06ed53310a3 1401 uint8_t write_buffer[256];
APS_Lab 0:f06ed53310a3 1402 uint8_t write_count = 0;
APS_Lab 0:f06ed53310a3 1403 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 1404 if (pwmReg == 0) {
APS_Lab 0:f06ed53310a3 1405 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 1406 cmd[1] = 0x20;
APS_Lab 0:f06ed53310a3 1407 } else {
APS_Lab 0:f06ed53310a3 1408 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 1409 cmd[1] = 0x1C;
APS_Lab 0:f06ed53310a3 1410 }
APS_Lab 0:f06ed53310a3 1411
APS_Lab 0:f06ed53310a3 1412 for (uint8_t current_ic = 0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1413 if (ic->isospi_reverse == true) {
APS_Lab 0:f06ed53310a3 1414 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 1415 } else {
APS_Lab 0:f06ed53310a3 1416 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 1417 }
APS_Lab 0:f06ed53310a3 1418 for (uint8_t data = 0; data<6; data++) {
APS_Lab 0:f06ed53310a3 1419 write_buffer[write_count] = ic[c_ic].pwm.tx_data[data];
APS_Lab 0:f06ed53310a3 1420 write_count++;
APS_Lab 0:f06ed53310a3 1421 }
APS_Lab 0:f06ed53310a3 1422 }
APS_Lab 0:f06ed53310a3 1423 write_68(total_ic, cmd, write_buffer);
APS_Lab 0:f06ed53310a3 1424 }
APS_Lab 0:f06ed53310a3 1425
APS_Lab 0:f06ed53310a3 1426
APS_Lab 0:f06ed53310a3 1427 /*
APS_Lab 0:f06ed53310a3 1428 Reads pwm registers of a LTC6811 daisy chain
APS_Lab 0:f06ed53310a3 1429 */
APS_Lab 0:f06ed53310a3 1430 int8_t LTC681x_rdpwm(uint8_t total_ic, //Number of ICs in the system
APS_Lab 0:f06ed53310a3 1431 uint8_t pwmReg,
APS_Lab 0:f06ed53310a3 1432 cell_asic ic[]
APS_Lab 0:f06ed53310a3 1433 )
APS_Lab 0:f06ed53310a3 1434 {
APS_Lab 0:f06ed53310a3 1435 // const uint8_t BYTES_IN_REG = 8;
APS_Lab 0:f06ed53310a3 1436
APS_Lab 0:f06ed53310a3 1437 uint8_t cmd[4];
APS_Lab 0:f06ed53310a3 1438 uint8_t read_buffer[256];
APS_Lab 0:f06ed53310a3 1439 int8_t pec_error = 0;
APS_Lab 0:f06ed53310a3 1440 uint16_t data_pec;
APS_Lab 0:f06ed53310a3 1441 uint16_t calc_pec;
APS_Lab 0:f06ed53310a3 1442 uint8_t c_ic = 0;
APS_Lab 0:f06ed53310a3 1443
APS_Lab 0:f06ed53310a3 1444 if (pwmReg == 0) {
APS_Lab 0:f06ed53310a3 1445 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 1446 cmd[1] = 0x22;
APS_Lab 0:f06ed53310a3 1447 } else {
APS_Lab 0:f06ed53310a3 1448 cmd[0] = 0x00;
APS_Lab 0:f06ed53310a3 1449 cmd[1] = 0x1E;
APS_Lab 0:f06ed53310a3 1450 }
APS_Lab 0:f06ed53310a3 1451
APS_Lab 0:f06ed53310a3 1452
APS_Lab 0:f06ed53310a3 1453 pec_error = read_68(total_ic, cmd, read_buffer);
APS_Lab 0:f06ed53310a3 1454 for (uint8_t current_ic =0; current_ic<total_ic; current_ic++) {
APS_Lab 0:f06ed53310a3 1455 if (ic->isospi_reverse == false) {
APS_Lab 0:f06ed53310a3 1456 c_ic = current_ic;
APS_Lab 0:f06ed53310a3 1457 } else {
APS_Lab 0:f06ed53310a3 1458 c_ic = total_ic - current_ic - 1;
APS_Lab 0:f06ed53310a3 1459 }
APS_Lab 0:f06ed53310a3 1460 for (int byte=0; byte<8; byte++) {
APS_Lab 0:f06ed53310a3 1461 ic[c_ic].pwm.rx_data[byte] = read_buffer[byte+(8*current_ic)];
APS_Lab 0:f06ed53310a3 1462 }
APS_Lab 0:f06ed53310a3 1463 calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
APS_Lab 0:f06ed53310a3 1464 data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
APS_Lab 0:f06ed53310a3 1465 if (calc_pec != data_pec ) {
APS_Lab 0:f06ed53310a3 1466 ic[c_ic].pwm.rx_pec_match = 1;
APS_Lab 0:f06ed53310a3 1467 } else ic[c_ic].pwm.rx_pec_match = 0;
APS_Lab 0:f06ed53310a3 1468 }
APS_Lab 0:f06ed53310a3 1469 return(pec_error);
APS_Lab 0:f06ed53310a3 1470 }