KIT Solar Car Project / Mbed 2 deprecated BMS_v1

Dependencies:   mbed INA226

Committer:
takuma1
Date:
Sat Oct 26 05:24:17 2019 +0000
Revision:
2:f6f76dde7e1d
Parent:
1:4dd3e328a30b
BMS;

Who changed what in which revision?

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