89 #define LTC6804_TWAKE 300 // us, max value
90 #define LTC6804_TSLEEP 1800 // ms, min value
91 #define LTC6804_TREADY 10 // us, max value
92 #define LTC6804_TIDLE 4300 // us, min value
93 #define LTC6804_TDWELL 1 // us, min value of 240ns in datasheet is outside resolution of uP timer.
95 #define LTC6804_NUM_CELLV_ADC_PER_REGISTER_GROUP (LTC6804_REGISTER_GROUP_SIZE / LTC6804_ADC_SIZE) // Number of cell voltage ADC measurements per register group
96 #define LTC6804_NUM_REGISTER_GROUP_READS_FOR_ALL_CELLV (LTC6804_NUM_CELLV_ADC / LTC6804_NUM_CELLV_ADC_PER_REGISTER_GROUP) // Number of register groups that must be read to get all cell voltage ADC measurements
97 #define LTC6804_NUM_REGISTER_GROUP_READS_FOR_TWO_CELLV (2) // Number of register groups that must be read to get a pair of cell voltage ADC measurements
98 #define LTC6804_NUM_AUX_ADC_PER_REGISTER_GROUP (LTC6804_REGISTER_GROUP_SIZE / LTC6804_ADC_SIZE)
100 #define LTC6804_NUM_COMM_BYTES_PER_REGISTER_GROUP 3 // Number of I2C/SPI bytes contained in the COMM register group
103 #define LTC6804_SPI_CLOCK_CYCLES_PER_STCOMM_BYTE 24
104 #define LTC6804_SPI_BYTES_PER_STCOMM_BYTE (LTC6804_SPI_CLOCK_CYCLES_PER_STCOMM_BYTE/BITS_PER_BYTE)
107 #define LTC6804_BAUD_RATE_DIVISOR 2 // tCLK/(SCL Clock Frequency) in table 19 of datasheet
117 const unsigned int16 ltc6804_pec_seed_value = 16;
118 const unsigned int16 ltc6804_pec_table[256] =
119 { 0x0000, 0xc599, 0xceab, 0x0b32, 0xd8cf, 0x1d56, 0x1664, 0xd3fd, 0xf407, 0x319e, 0x3aac,
120 0xff35, 0x2cc8, 0xe951, 0xe263, 0x27fa, 0xad97, 0x680e, 0x633c, 0xa6a5, 0x7558, 0xb0c1,
121 0xbbf3, 0x7e6a, 0x5990, 0x9c09, 0x973b, 0x52a2, 0x815f, 0x44c6, 0x4ff4, 0x8a6d, 0x5b2e,
122 0x9eb7, 0x9585, 0x501c, 0x83e1, 0x4678, 0x4d4a, 0x88d3, 0xaf29, 0x6ab0, 0x6182, 0xa41b,
123 0x77e6, 0xb27f, 0xb94d, 0x7cd4, 0xf6b9, 0x3320, 0x3812, 0xfd8b, 0x2e76, 0xebef, 0xe0dd,
124 0x2544, 0x02be, 0xc727, 0xcc15, 0x098c, 0xda71, 0x1fe8, 0x14da, 0xd143, 0xf3c5, 0x365c,
125 0x3d6e, 0xf8f7, 0x2b0a, 0xee93, 0xe5a1, 0x2038, 0x07c2, 0xc25b, 0xc969, 0x0cf0, 0xdf0d,
126 0x1a94, 0x11a6, 0xd43f, 0x5e52, 0x9bcb, 0x90f9, 0x5560, 0x869d, 0x4304, 0x4836, 0x8daf,
127 0xaa55, 0x6fcc, 0x64fe, 0xa167, 0x729a, 0xb703, 0xbc31, 0x79a8, 0xa8eb, 0x6d72, 0x6640,
128 0xa3d9, 0x7024, 0xb5bd, 0xbe8f, 0x7b16, 0x5cec, 0x9975, 0x9247, 0x57de, 0x8423, 0x41ba,
129 0x4a88, 0x8f11, 0x057c, 0xc0e5, 0xcbd7, 0xe4e, 0xddb3, 0x182a, 0x1318, 0xd681, 0xf17b,
130 0x34e2, 0x3fd0, 0xfa49, 0x29b4, 0xec2d, 0xe71f, 0x2286, 0xa213, 0x678a, 0x6cb8, 0xa921,
131 0x7adc, 0xbf45, 0xb477, 0x71ee, 0x5614, 0x938d, 0x98bf, 0x5d26, 0x8edb, 0x4b42, 0x4070,
132 0x85e9, 0x0f84, 0xca1d, 0xc12f, 0x04b6, 0xd74b, 0x12d2, 0x19e0, 0xdc79, 0xfb83, 0x3e1a, 0x3528,
133 0xf0b1, 0x234c, 0xe6d5, 0xede7, 0x287e, 0xf93d, 0x3ca4, 0x3796, 0xf20f, 0x21f2, 0xe46b, 0xef59,
134 0x2ac0, 0x0d3a, 0xc8a3, 0xc391, 0x0608, 0xd5f5, 0x106c, 0x1b5e, 0xdec7, 0x54aa, 0x9133, 0x9a01,
135 0x5f98, 0x8c65, 0x49fc, 0x42ce, 0x8757, 0xa0ad, 0x6534, 0x6e06, 0xab9f, 0x7862, 0xbdfb, 0xb6c9,
136 0x7350, 0x51d6, 0x944f, 0x9f7d, 0x5ae4, 0x8919, 0x4c80, 0x47b2, 0x822b, 0xa5d1, 0x6048, 0x6b7a,
137 0xaee3, 0x7d1e, 0xb887, 0xb3b5, 0x762c, 0xfc41, 0x39d8, 0x32ea, 0xf773, 0x248e, 0xe117, 0xea25,
138 0x2fbc, 0x0846, 0xcddf, 0xc6ed, 0x0374, 0xd089, 0x1510, 0x1e22, 0xdbbb, 0x0af8, 0xcf61, 0xc453,
139 0x01ca, 0xd237, 0x17ae, 0x1c9c, 0xd905, 0xfeff, 0x3b66, 0x3054, 0xf5cd, 0x2630, 0xe3a9, 0xe89b,
140 0x2d02, 0xa76f, 0x62f6, 0x69c4, 0xac5d, 0x7fa0, 0xba39, 0xb10b, 0x7492, 0x5368, 0x96f1, 0x9dc3,
141 0x585a, 0x8ba7, 0x4e3e, 0x450c, 0x8095
144 unsigned int8 ltc6804_gpio_pulldown;
150 unsigned int32 ltc6804_wakeup_timestamp;
155 void ltc6804_wakeup(
void);
156 void ltc6804_get_adcopt_and_md(int8 conversion_mode, int8* adcopt_ptr, int8* md_ptr);
157 void ltc6804_adc_opt_set(int8 board_num, int8 adcopt);
158 void ltc6804_command_code_send(int16 command_code, BOOLEAN reg_group_command);
159 void ltc6804_register_group_write(int8* register_group);
160 BOOLEAN ltc6804_register_group_read(int8* register_group);
161 void ltc6804_cfgr_modify(int8 board_num, int8* register_mask_ptr, int8* register_value_ptr);
162 void ltc6804_clock_out(int16 bytes_to_send, int16 baud_khz);
163 inline unsigned int16 ltc6804_pec_lookup(
char data,
unsigned int16 remainder);
176 ltc6804_adcopt = 0xFF;
192 ltc6804_gpio_pulldown = gpio_bitmap;
196 memset(®ister_modify.mask[1], 0,
sizeof(register_modify)-1);
197 register_modify.mask[0] = LTC6804_CFGR0_GPIOx_MASK;
198 register_modify.value[0] = LTC6804_CFGR0_GPIOx(ltc6804_gpio_pulldown);
200 ltc6804_cfgr_modify(board_num, register_modify.mask, register_modify.value);
214 memset(®ister_modify.mask[1], 0,
sizeof(register_modify)-1);
215 register_modify.mask[0] = LTC6804_CFGR0_GPIOx_MASK;
216 register_modify.value[0] = LTC6804_CFGR0_GPIOx(ltc6804_gpio_pulldown);
219 register_modify.mask[0] |= LTC6804_CFGR0_REFON_MASK;
222 register_modify.value[0] |= LTC6804_CFGR0_REFON(refon);
224 ltc6804_cfgr_modify(board_num, register_modify.mask, register_modify.value);
238 memset(®ister_modify.mask[1], 0,
sizeof(register_modify)-1);
239 register_modify.mask[0] = LTC6804_CFGR0_GPIOx_MASK;
240 register_modify.value[0] = LTC6804_CFGR0_GPIOx(ltc6804_gpio_pulldown);
243 *((int16*)(register_modify.mask+1)) |= LTC6804_CFGR1_VUV_MASK;
244 *((int16*)(register_modify.mask+2)) |= LTC6804_CFGR2_VOV_MASK;
247 *((int16*)(register_modify.value+1)) |= LTC6804_CFGR1_VUV(vuv_value);
248 *((int16*)(register_modify.value+2)) |= LTC6804_CFGR2_VOV(vov_value);
250 ltc6804_cfgr_modify(board_num, register_modify.mask, register_modify.value);
264 memset(®ister_modify.mask[1], 0,
sizeof(register_modify)-1);
265 register_modify.mask[0] = LTC6804_CFGR0_GPIOx_MASK;
266 register_modify.value[0] = LTC6804_CFGR0_GPIOx(ltc6804_gpio_pulldown);
269 *((int16*)(register_modify.mask+4)) |= LTC6804_CFGR4_DCCx_MASK;
270 register_modify.mask[5] |= LTC6804_CFGR5_DCTO_MASK;
273 *((int16*)(register_modify.value+4)) |= LTC6804_CFGR4_DCCx(discharge_bitmap);
274 register_modify.value[5] |= LTC6804_CFGR5_DCTO(timeout_value);
276 ltc6804_cfgr_modify(board_num, register_modify.mask, register_modify.value);
284 BOOLEAN success = TRUE;
286 unsigned int16 command_code;
295 command_code = LTC6804_COMMAND_CODE_RDCFG(address);
298 ltc6804_command_code_send(command_code, TRUE);
301 if(ltc6804_register_group_read(cfgr) == TRUE)
303 *vuv_value = *((int16*)(cfgr+1)) & LTC6804_CFGR1_VUV_MASK;
304 *vov_value = (*((int16*)(cfgr+2)) & LTC6804_CFGR2_VOV_MASK) >> 4;
318 BOOLEAN success = TRUE;
320 unsigned int16 command_code;
333 command_code = LTC6804_COMMAND_CODE_RDSTATB(address);
336 ltc6804_command_code_send(command_code, TRUE);
339 if(ltc6804_register_group_read(stbr) == TRUE)
342 bit_mask_out = 0x0001;
347 for (byte_num = 2; byte_num < 5; byte_num++)
351 for (bit_num = 0; bit_num < 8; bit_num += 2)
353 if(stbr[byte_num] & bit_mask_in) *vuv_flags |= bit_mask_out;
356 if(stbr[byte_num] & bit_mask_in) *vov_flags |= bit_mask_out;
375 BOOLEAN success = TRUE;
377 unsigned int16 command_code;
386 command_code = LTC6804_COMMAND_CODE_RDSTATB(address);
389 ltc6804_command_code_send(command_code, TRUE);
392 if(ltc6804_register_group_read(stbr) == TRUE)
394 *revision = stbr[5] >> 4;
408 BOOLEAN success = TRUE;
410 unsigned int16 command_code;
419 command_code = LTC6804_COMMAND_CODE_RDCFG(address);
422 ltc6804_command_code_send(command_code, TRUE);
425 if(ltc6804_register_group_read(cfgr) == TRUE)
427 if (cfgr[0] & LTC6804_CFGR0_REFON_MASK)
450 unsigned int16 command_code;
459 command_code = LTC6804_COMMAND_CODE_CLRCELL(address);
462 ltc6804_command_code_send(command_code, FALSE);
471 unsigned int16 command_code;
479 ltc6804_get_adcopt_and_md(mode, &adcopt, &md);
482 if( ltc6804_adcopt != adcopt)
484 ltc6804_adc_opt_set(board_num, adcopt);
493 command_code = LTC6804_COMMAND_CODE_ADCV(address, md, (discharge_permitted ? LTC6804_DCP_DISCHARGE_PERMITTED : LTC6804_DCP_DISCHARGE_NOT_PERMITTED), cell_select);
496 ltc6804_command_code_send(command_code, FALSE);
504 BOOLEAN success = TRUE;
506 unsigned int16 command_code;
507 unsigned int8 reg_count;
508 unsigned int8 reg_index;
509 unsigned int8 reg_inc;
510 unsigned int8 byte_index;
517 reg_count = LTC6804_NUM_REGISTER_GROUP_READS_FOR_ALL_CELLV;
519 reg_inc = (LTC6804_COMMAND_CODE_BASE_RDCVB - LTC6804_COMMAND_CODE_BASE_RDCVA);
524 reg_count = LTC6804_NUM_REGISTER_GROUP_READS_FOR_TWO_CELLV;
525 reg_index = (cell_select - 1) / LTC6804_NUM_CELLV_ADC_PER_REGISTER_GROUP;
526 reg_inc = (LTC6804_COMMAND_CODE_BASE_RDCVC - LTC6804_COMMAND_CODE_BASE_RDCVA);
527 byte_index = ((cell_select - 1) % LTC6804_NUM_CELLV_ADC_PER_REGISTER_GROUP) *
LTC6804_ADC_SIZE;
536 command_code = LTC6804_COMMAND_CODE_RDCVA(address) + reg_index * (LTC6804_COMMAND_CODE_BASE_RDCVB - LTC6804_COMMAND_CODE_BASE_RDCVA);
541 ltc6804_command_code_send(command_code, TRUE);
544 if(ltc6804_register_group_read(cv_r) == TRUE)
551 *adc_value_ptr++ = ((int16) cv_r[byte_num + 1] << 8) + cv_r[byte_num];
556 *adc_value_ptr++ = ((int16) cv_r[byte_index + 1] << 8) + cv_r[byte_index];
560 command_code += reg_inc;
581 unsigned int16 command_code;
590 command_code = LTC6804_COMMAND_CODE_CLRAUX(address);
593 ltc6804_command_code_send(command_code, FALSE);
602 unsigned int16 command_code;
610 ltc6804_get_adcopt_and_md(mode, &adcopt, &md);
613 if( ltc6804_adcopt != adcopt)
615 ltc6804_adc_opt_set(board_num, adcopt);
624 command_code = LTC6804_COMMAND_CODE_ADAX(address, md, gpio_select);
627 ltc6804_command_code_send(command_code, FALSE);
635 BOOLEAN success = TRUE;
637 unsigned int16 command_code;
638 unsigned int8 gpio_index;
639 unsigned int8 gpio_count;
664 if(gpio_index < LTC6804_NUM_AUX_ADC_PER_REGISTER_GROUP)
667 command_code = LTC6804_COMMAND_CODE_RDAUXA(address);
672 command_code = LTC6804_COMMAND_CODE_RDAUXB(address);
676 ltc6804_command_code_send(command_code, TRUE);
679 if(ltc6804_register_group_read(avar) == TRUE)
682 byte_num = (gpio_index % LTC6804_NUM_AUX_ADC_PER_REGISTER_GROUP) *
LTC6804_ADC_SIZE;
685 *adc_value_ptr++ = ((int16) avar[byte_num + 1] << 8) + avar[byte_num];
703 void LTC6804_I2C_Write(int8 board_num, BOOLEAN start, BOOLEAN stop, int8* data_ptr, int16 num_bytes, int16 baud_khz)
706 unsigned int16 command_code;
721 command_code = LTC6804_COMMAND_CODE_WRCOMM(address);
722 ltc6804_command_code_send(command_code, TRUE);
729 *comm_ptr++ = ((start ? LTC6804_ICOM_I2C_WRITE_START : LTC6804_ICOM_I2C_WRITE_BLANK) << 4) + UPPER_NIBBLE(*data_ptr);
730 *comm_ptr++ = (LOWER_NIBBLE(*data_ptr) << 4) + ((num_bytes == 1) && stop ? LTC6804_FCOM_WRITE_I2C_NACK_STOP : LTC6804_FCOM_WRITE_I2C_NACK);
738 for(byte_num = 1; byte_num < LTC6804_NUM_COMM_BYTES_PER_REGISTER_GROUP; byte_num++)
740 *comm_ptr++ = ((num_bytes ? LTC6804_ICOM_I2C_WRITE_BLANK : LTC6804_ICOM_I2C_WRITE_NO_TRANSMIT) << 4) + UPPER_NIBBLE(*data_ptr);
741 *comm_ptr++ = (LOWER_NIBBLE(*data_ptr) << 4) + ((num_bytes == 1) && stop ? LTC6804_FCOM_WRITE_I2C_NACK_STOP : LTC6804_FCOM_WRITE_I2C_NACK);
751 ltc6804_register_group_write(comm);
754 command_code = LTC6804_COMMAND_CODE_STCOMM(address);
755 ltc6804_command_code_send(command_code, TRUE);
758 ltc6804_clock_out(bytes_to_send, baud_khz);
763 BOOLEAN
LTC6804_I2C_Read(int8 board_num, BOOLEAN start, BOOLEAN stop, int8* data_ptr, int16 num_bytes, int16 baud_khz)
765 BOOLEAN success = TRUE;
767 unsigned int16 command_code;
782 command_code = LTC6804_COMMAND_CODE_WRCOMM(address);
783 ltc6804_command_code_send(command_code, TRUE);
792 *comm_ptr++ = (LTC6804_ICOM_I2C_WRITE_START << 4) + UPPER_NIBBLE(*data_ptr);
793 *comm_ptr++ = (LOWER_NIBBLE(*data_ptr) << 4) + LTC6804_FCOM_WRITE_I2C_NACK;
797 *comm_ptr++ = ((LTC6804_ICOM_I2C_WRITE_BLANK) << 4) + UPPER_NIBBLE(LTC6804_COMM_READ_DUMMY);
798 *comm_ptr++ = (LOWER_NIBBLE(LTC6804_COMM_READ_DUMMY) << 4) + ((num_bytes == 1) && stop ? LTC6804_FCOM_WRITE_I2C_NACK_STOP : LTC6804_FCOM_WRITE_I2C_ACK);
804 for(byte_num = 1; byte_num < LTC6804_NUM_COMM_BYTES_PER_REGISTER_GROUP; byte_num++)
806 *comm_ptr++ = ((num_bytes ? LTC6804_ICOM_I2C_WRITE_BLANK : LTC6804_ICOM_I2C_WRITE_NO_TRANSMIT) << 4) + UPPER_NIBBLE(LTC6804_COMM_READ_DUMMY);
807 *comm_ptr++ = (LOWER_NIBBLE(LTC6804_COMM_READ_DUMMY) << 4) + ((num_bytes == 1) && stop ? LTC6804_FCOM_WRITE_I2C_NACK_STOP : LTC6804_FCOM_WRITE_I2C_ACK);
816 ltc6804_register_group_write(comm);
819 command_code = LTC6804_COMMAND_CODE_STCOMM(address);
820 ltc6804_command_code_send(command_code, TRUE);
823 ltc6804_clock_out(bytes_to_send, baud_khz);
826 command_code = LTC6804_COMMAND_CODE_RDCOMM(address);
827 ltc6804_command_code_send(command_code, TRUE);
830 if(ltc6804_register_group_read(comm) == TRUE)
835 while(bytes_to_send--)
837 *data_ptr = (((*comm_ptr) << 4) & 0xF0) + ((*(comm_ptr + 1)) >> 4);
861 void LTC6804_SPI_Write(int8 board_num, BOOLEAN start, BOOLEAN stop, int8* data_ptr, int16 num_bytes, int16 baud_khz)
864 unsigned int16 command_code;
879 command_code = LTC6804_COMMAND_CODE_WRCOMM(address);
880 ltc6804_command_code_send(command_code, TRUE);
886 for(byte_num = 0; byte_num < LTC6804_NUM_COMM_BYTES_PER_REGISTER_GROUP; byte_num++)
888 *comm_ptr++ = ((num_bytes ? LTC6804_ICOM_SPI_WRITE_CSB_LOW : LTC6804_ICOM_SPI_WRITE_NO_TRANSMIT) << 4) + UPPER_NIBBLE(*data_ptr);
889 *comm_ptr++ = (LOWER_NIBBLE(*data_ptr) << 4) + ((num_bytes <= 1) && stop ? LTC6804_FCOM_SPI_WRITE_CSB_HIGH : LTC6804_FCOM_SPI_WRITE_CSB_LOW);
899 ltc6804_register_group_write(comm);
902 command_code = LTC6804_COMMAND_CODE_STCOMM(address);
903 ltc6804_command_code_send(command_code, TRUE);
906 ltc6804_clock_out(bytes_to_send, baud_khz);
912 BOOLEAN
LTC6804_SPI_Read(int8 board_num, BOOLEAN start, BOOLEAN stop, int8* data_ptr, int16 num_bytes, int16 baud_khz)
914 BOOLEAN success = TRUE;
916 unsigned int16 command_code;
931 command_code = LTC6804_COMMAND_CODE_WRCOMM(address);
932 ltc6804_command_code_send(command_code, TRUE);
941 *comm_ptr++ = (LTC6804_ICOM_SPI_WRITE_CSB_LOW << 4) + UPPER_NIBBLE(*data_ptr);
942 *comm_ptr++ = (LOWER_NIBBLE(*data_ptr) << 4) + LTC6804_FCOM_SPI_WRITE_CSB_LOW;
946 *comm_ptr++ = (LTC6804_ICOM_SPI_WRITE_CSB_LOW << 4) + UPPER_NIBBLE(LTC6804_COMM_READ_DUMMY);
947 *comm_ptr++ = (LOWER_NIBBLE(LTC6804_COMM_READ_DUMMY) << 4) + ((num_bytes <= 1) && stop ? LTC6804_FCOM_SPI_WRITE_CSB_HIGH : LTC6804_FCOM_SPI_WRITE_CSB_LOW);
952 for(byte_num = 1; byte_num < LTC6804_NUM_COMM_BYTES_PER_REGISTER_GROUP; byte_num++)
954 *comm_ptr++ = (LTC6804_ICOM_SPI_WRITE_CSB_LOW << 4) + UPPER_NIBBLE(LTC6804_COMM_READ_DUMMY);
955 *comm_ptr++ = (LOWER_NIBBLE(LTC6804_COMM_READ_DUMMY) << 4) + ((num_bytes <= 1) && stop ? LTC6804_FCOM_SPI_WRITE_CSB_HIGH : LTC6804_FCOM_SPI_WRITE_CSB_LOW);
964 ltc6804_register_group_write(comm);
967 command_code = LTC6804_COMMAND_CODE_STCOMM(address);
968 ltc6804_command_code_send(command_code, TRUE);
971 ltc6804_clock_out(bytes_to_send, baud_khz);
974 command_code = LTC6804_COMMAND_CODE_RDCOMM(address);
975 ltc6804_command_code_send(command_code, TRUE);
978 if(ltc6804_register_group_read(comm) == TRUE)
983 while(bytes_to_send--)
985 *data_ptr = (((*comm_ptr) << 4) & 0xF0) + ((*(comm_ptr + 1)) >> 4);
1011 unsigned int16 remainder;
1013 remainder = ltc6804_pec_seed_value;
1015 for (
int i = 0; i < length; i++)
1017 remainder = ltc6804_pec_lookup(data[i], remainder);
1020 return (remainder * 2);
1029 void ltc6804_wakeup(
void)
1031 unsigned int32 wakeup_timestamp_new;
1051 ltc6804_wakeup_timestamp = wakeup_timestamp_new;
1057 void ltc6804_get_adcopt_and_md(int8 conversion_mode, int8* adcopt_ptr, int8* md_ptr)
1060 switch(conversion_mode)
1063 *adcopt_ptr = LTC6804_ADCOPT_0;
1064 *md_ptr = LTC6804_MD_MODE_FAST;
1067 *adcopt_ptr = LTC6804_ADCOPT_1;
1068 *md_ptr = LTC6804_MD_MODE_FAST;
1071 *adcopt_ptr = LTC6804_ADCOPT_0;
1072 *md_ptr = LTC6804_MD_MODE_NORMAL;
1075 *adcopt_ptr = LTC6804_ADCOPT_1;
1076 *md_ptr = LTC6804_MD_MODE_NORMAL;
1079 *adcopt_ptr = LTC6804_ADCOPT_1;
1080 *md_ptr = LTC6804_MD_MODE_FILTERED;
1084 *adcopt_ptr = LTC6804_ADCOPT_0;
1085 *md_ptr = LTC6804_MD_MODE_FILTERED;
1093 void ltc6804_adc_opt_set(int8 board_num, int8 adcopt)
1102 memset(®ister_modify.mask[1], 0,
sizeof(register_modify) - 1);
1103 register_modify.mask[0] = LTC6804_CFGR0_GPIOx_MASK;
1104 register_modify.value[0] = LTC6804_CFGR0_GPIOx(ltc6804_gpio_pulldown);
1107 register_modify.mask[0] |= LTC6804_CFGR0_ADCOPT_MASK;
1110 register_modify.value[0] |= LTC6804_CFGR0_ADCOPT(adcopt);
1112 ltc6804_cfgr_modify(board_num, register_modify.mask, register_modify.value);
1115 ltc6804_adcopt = adcopt;
1121 void ltc6804_command_code_send(int16 command_code, BOOLEAN reg_group_command)
1130 writebyte[0] = UPPER_BYTE(command_code);
1131 writebyte[1] = LOWER_BYTE(command_code);
1141 if (reg_group_command == FALSE)
1152 void ltc6804_register_group_write(int8* register_group)
1162 writebyte[0] = UPPER_BYTE(pec);
1163 writebyte[1] = LOWER_BYTE(pec);
1174 BOOLEAN ltc6804_register_group_read(int8* register_group)
1177 unsigned int16 pec_calc;
1183 pec_calc = ltc6804_pec_seed_value;
1189 pec_calc = ltc6804_pec_lookup(register_group[byte_num], pec_calc);
1202 if((UPPER_BYTE(pec_calc) != register_group[LTC6804_REGISTER_GROUP_SIZE]) ||
1203 (LOWER_BYTE(pec_calc) != register_group[LTC6804_REGISTER_GROUP_SIZE + 1]))
1212 void ltc6804_clock_out(int16 bytes_to_send, int16 baud_khz)
1225 for (byte_num = 0; byte_num < LTC6804_SPI_BYTES_PER_STCOMM_BYTE * bytes_to_send; byte_num++)
1243 void ltc6804_cfgr_modify(int8 board_num, int8* register_mask_ptr, int8* register_value_ptr)
1246 unsigned int16 command_code;
1249 int8 board_loop_num;
1250 int8 board_limit_num;
1260 board_loop_num = board_num;
1261 board_limit_num = board_num;
1273 command_code = LTC6804_COMMAND_CODE_RDCFG(address);
1274 ltc6804_command_code_send(command_code, TRUE);
1278 if(ltc6804_register_group_read(cfgr) == TRUE)
1284 cfgr[byte_num] &= ~(*(register_mask_ptr + byte_num));
1285 cfgr[byte_num] |= (*(register_value_ptr + byte_num));
1289 command_code = LTC6804_COMMAND_CODE_WRCFG(address);
1290 ltc6804_command_code_send(command_code, TRUE);
1293 ltc6804_register_group_write(cfgr);
1298 board_loop_num = board_limit_num = 0;
1302 }
while (board_loop_num < board_limit_num);
1308 inline unsigned int16 ltc6804_pec_lookup(
char data,
unsigned int16 remainder)
1312 addr = ((remainder >> 7) ^ data) & 0xff;
1313 remainder = (remainder << 8) ^ ltc6804_pec_table[addr];
BOOLEAN LTC6804_UVOV_Flags_Get(int8 board_num, int16 *vuv_flags, int16 *vov_flags)
Gets the LTC6804 flags indicating under-voltage and over-voltage conditions are present.
#define LTC6804_CONFIG_SPI_BUFFER_SEND_START(buffer, num_bytes)
Configures the function called to start sending a string of bytes to the LTC6804. ...
#define LTC6804_NUM_AUX_ADC
Number of auxiliary ADC measurements.
void LTC6804_Refon_Set(int8 board_num, BOOLEAN refon)
Turns the LTC6804 ADC Reference on and off.
BOOLEAN LTC6804_UVOV_Thresholds_Get(int8 board_num, unsigned int16 *vuv_value, unsigned int16 *vov_value)
Gets the LTC6804 under-voltage and over-voltage thresholds in LTC6804_UVOV_RESOLUTION units...
void LTC6804_UVOV_Thresholds_Set(int8 board_num, int16 vuv_value, int16 vov_value)
Sets the LTC6804 under-voltage and over-voltage thresholds in LTC6804_UVOV_RESOLUTION units...
void LTC6804_I2C_Write(int8 board_num, BOOLEAN start, BOOLEAN stop, int8 *data_ptr, int16 num_bytes, int16 baud_khz)
Writes a string of bytes to the LTC6804 I2C port implemented on its GPIO pins.
#define LTC6804_BROADCAST
Code for application code to indicate an LTC6804 command is to be broadcast to all boards...
void LTC6804_Dischargers_Set(int8 board_num, int16 discharge_bitmap, int16 timeout_value)
Sets the LTC6804 discharger pin levels and timeout values.
#define LTC6804_CONFIG_DELAY_US(us)
Function for delaying a specified number of us.
BOOLEAN LTC6804_Revision_Get(int8 board_num, unsigned int8 *revision)
Gets the LTC6804 revision.
void LTC6804_Init(void)
Initializes the LTC6804-2 code module.
void LTC6804_SPI_Write(int8 board_num, BOOLEAN start, BOOLEAN stop, int8 *data_ptr, int16 num_bytes, int16 baud_khz)
Writes a string of bytes to the LTC6804 SPI port implemented on its GPIO pins.
#define LTC6804_CONFIG_TIMER_RESOLUTION
Resolution of LTC6804_CONFIG_TIMER in ticks per second.
BOOLEAN LTC6804_Cell_ADC_Read(int8 board_num, LTC6804_CH_CELL_TYPE cell_select, unsigned int16 *adc_value_ptr)
Reads the LTC6804 Cell Voltage ADC conversion results.
#define LTC6804_CONFIG_SPI_SET_BAUD(baud_khz)
Configures the function called to set the baud rate to the LTC6804.
#define LTC6804_PEC_SIZE
15 bit PEC, requires int16 data type
BOOLEAN LTC6804_I2C_Read(int8 board_num, BOOLEAN start, BOOLEAN stop, int8 *data_ptr, int16 num_bytes, int16 baud_khz)
Writes one byte, and then reads a string of bytes to the LTC6804 I2C port implemented on its GPIO pin...
#define LT6804_CONFIG_CS
Configures CS pin used to communicate with LTC6804-2. Note that code module directly controls CS for ...
#define LTC6804_CONFIG_NUM_BOARDS
The number of LTC6804 addresses used in this system. This is used for loops over all available LTC680...
void LTC6804_Cell_ADC_Start(int8 board_num, LTC6804_CONVERSION_MODE_T mode, LTC6804_CH_CELL_TYPE cell_select, BOOLEAN discharge_permitted)
Starts the LTC6804 Cell Voltage ADC conversion at the specified conversion mode.
#define LTC6804_NUM_GPIO
Number of GPIO pins available on LTC6804.
LTC6804_CONVERSION_MODE_T
void LTC6804_Cell_ADC_Clear(int8 board_num)
Clears the LTC6804 Cell Voltage ADC registers.
API Header File for LTC6804-2 Multicell Battery Monitors.
#define LTC6804_CONFIG_SPI_BUFFER_RECEIVE_START(buffer, num_bytes)
Note - This LTC6804 driver is designed for a buffered SPI peripheral (DMA, Interrupt driven...
#define LTC6804_BAUD_RATE
in kHz, Max input SPI Frequency (1/tCLK from datasheet)
unsigned int16 LTC6804_PEC_Calc(char *data, int length)
Calculates the LTC6804 CRC over a string of bytes as per datasheet figure 22.
#define LTC6804_COMMAND_SIZE
bytes per command
void LTC6804_GPIO_Set(int8 board_num, int8 gpio_bitmap)
Sets the LTC6804 GPIO Pull Downs.
BOOLEAN LTC6804_SPI_Read(int8 board_num, BOOLEAN start, BOOLEAN stop, int8 *data_ptr, int16 num_bytes, int16 baud_khz)
Writes one byte, and then reads a string of bytes to the LTC6804 SPI port implemented on its GPIO pin...
#define LTC6804_CONFIG_ERROR_CRC(address, command, data_ptr, num_bytes)
Configures interface through which LTC6804-2 driver module reports its CRC errors.
#define LTC6804_CONFIG_TIMER
Configures Free Running Timer used to determine if the LTC6804 needs a LTC6804_TWAKE or LTC6804_TREAD...
void LTC6804_GPIO_ADC_Start(int8 board_num, LTC6804_CONVERSION_MODE_T mode, LTC6804_CHG_GPIO_TYPE gpio_select)
Starts the specified LTC6804 GPIO ADC conversion at the specified conversion mode.
Driver Registers for LTC6804-2 Multicell Battery Monitors.
BOOLEAN LTC6804_GPIO_ADC_Read(int8 board_num, LTC6804_CHG_GPIO_TYPE gpio_select, int16 *adc_value_ptr)
Reads the specified LTC6804 GPIO ADC conversion results.
Driver Configuration Header File for LTC6804-2 Multicell Battery Monitors.
void LTC6804_GPIO_ADC_Clear(int8 board_num)
Clears the LTC6804 GPIO ADC registers.
#define LTC6804_ADC_SIZE
16 bit ADC results
#define LTC6804_CONFIG_SPI_BUFFER_RECEIVE_BYTES_AVAILABLE(buffer)
Configures the function called to return the number of bytes received in a buffer.
#define LTC6804_CONFIG_GET_BOARD_ADDRESS(board_num)
Returns the physical address for a LTC6804 in the system given its logical address.
#define LTC6804_CONFIG_SPI_BUFFER_DONE()
Configures the function called to check if the last SPI communication to LTC6804 is done and SPI is r...
BOOLEAN LTC6804_Refon_Get(int8 board_num, int8 *refon)
Gets the LTC6804 ADC Reference status, where 1 = ON and 0 = OFF.
#define LTC6804_REGISTER_GROUP_SIZE
bytes per register group