ShivaTeja Thoutam / ADBMS2950
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers adi_bms_utility.cpp Source File

adi_bms_utility.cpp

00001 /**
00002 ********************************************************************************
00003 *
00004 * @file:    adi_bms_utility.c
00005 *
00006 * @brief:   This file contains utility functions implementation.
00007 *
00008 * @details:
00009 *
00010 *******************************************************************************
00011 Copyright(c) 2020 Analog Devices, Inc. All Rights Reserved. This software is
00012 proprietary & confidential to Analog Devices, Inc. and its licensors. By using
00013 this software you agree to the terms of the associated Analog Devices License
00014 Agreement.
00015 *******************************************************************************
00016 */
00017 /*! \addtogroup BMS_Driver
00018 *  @{
00019 */
00020 
00021 /*! \addtogroup Driver_Utility
00022 *  @{
00023 */
00024 
00025 /*!<
00026 This documentation provides details about BMS driver APIs and their usage.
00027 Using the BMS Driver Application can:
00028 - Read/Write the configuration registers of the BMS devices stacked in daisy chaining.
00029 - Send commands and Read the Cell Voltages, Aux Voltages and Status registers (Sum of cells, Internal Die temperature etc.)
00030 */
00031 
00032 /*============= I N C L U D E S =============*/
00033 /*============== D E F I N E S ===============*/
00034 /*============= E X T E R N A L S ============*/
00035 /*============= E N U M E R A T O R S ============*/
00036 
00037 #include "adbms2950.h"
00038 #include "pal.h"
00039 /*!<**************************************** BMS Driver APIs definitions ********************************************/
00040 
00041 /*!<
00042 * @brief Precomputed CRC15 Table
00043 */
00044 const uint16_t Crc15Table[256] =
00045 {
00046   0x0000,0xc599, 0xceab, 0xb32, 0xd8cf, 0x1d56, 0x1664, 0xd3fd, 0xf407, 0x319e, 0x3aac,
00047   0xff35, 0x2cc8, 0xe951, 0xe263, 0x27fa, 0xad97, 0x680e, 0x633c, 0xa6a5, 0x7558, 0xb0c1,
00048   0xbbf3, 0x7e6a, 0x5990, 0x9c09, 0x973b, 0x52a2, 0x815f, 0x44c6, 0x4ff4, 0x8a6d, 0x5b2e,
00049   0x9eb7, 0x9585, 0x501c, 0x83e1, 0x4678, 0x4d4a, 0x88d3, 0xaf29, 0x6ab0, 0x6182, 0xa41b,
00050   0x77e6, 0xb27f, 0xb94d, 0x7cd4, 0xf6b9, 0x3320, 0x3812, 0xfd8b, 0x2e76, 0xebef, 0xe0dd,
00051   0x2544, 0x2be, 0xc727, 0xcc15, 0x98c, 0xda71, 0x1fe8, 0x14da, 0xd143, 0xf3c5, 0x365c,
00052   0x3d6e, 0xf8f7,0x2b0a, 0xee93, 0xe5a1, 0x2038, 0x7c2, 0xc25b, 0xc969, 0xcf0, 0xdf0d,
00053   0x1a94, 0x11a6, 0xd43f, 0x5e52, 0x9bcb, 0x90f9, 0x5560, 0x869d, 0x4304, 0x4836, 0x8daf,
00054   0xaa55, 0x6fcc, 0x64fe, 0xa167, 0x729a, 0xb703, 0xbc31, 0x79a8, 0xa8eb, 0x6d72, 0x6640,
00055   0xa3d9, 0x7024, 0xb5bd, 0xbe8f, 0x7b16, 0x5cec, 0x9975, 0x9247, 0x57de, 0x8423, 0x41ba,
00056   0x4a88, 0x8f11, 0x57c, 0xc0e5, 0xcbd7, 0xe4e, 0xddb3, 0x182a, 0x1318, 0xd681, 0xf17b,
00057   0x34e2, 0x3fd0, 0xfa49, 0x29b4, 0xec2d, 0xe71f, 0x2286, 0xa213, 0x678a, 0x6cb8, 0xa921,
00058   0x7adc, 0xbf45, 0xb477, 0x71ee, 0x5614, 0x938d, 0x98bf, 0x5d26, 0x8edb, 0x4b42, 0x4070,
00059   0x85e9, 0xf84, 0xca1d, 0xc12f, 0x4b6, 0xd74b, 0x12d2, 0x19e0, 0xdc79, 0xfb83, 0x3e1a, 0x3528,
00060   0xf0b1, 0x234c, 0xe6d5, 0xede7, 0x287e, 0xf93d, 0x3ca4, 0x3796, 0xf20f, 0x21f2, 0xe46b, 0xef59,
00061   0x2ac0, 0xd3a, 0xc8a3, 0xc391, 0x608, 0xd5f5, 0x106c, 0x1b5e, 0xdec7, 0x54aa, 0x9133, 0x9a01,
00062   0x5f98, 0x8c65, 0x49fc, 0x42ce, 0x8757, 0xa0ad, 0x6534, 0x6e06, 0xab9f, 0x7862, 0xbdfb, 0xb6c9,
00063   0x7350, 0x51d6, 0x944f, 0x9f7d, 0x5ae4, 0x8919, 0x4c80, 0x47b2, 0x822b, 0xa5d1, 0x6048, 0x6b7a,
00064   0xaee3, 0x7d1e, 0xb887, 0xb3b5, 0x762c, 0xfc41, 0x39d8, 0x32ea, 0xf773, 0x248e, 0xe117, 0xea25,
00065   0x2fbc, 0x846, 0xcddf, 0xc6ed, 0x374, 0xd089, 0x1510, 0x1e22, 0xdbbb, 0xaf8, 0xcf61, 0xc453,
00066   0x1ca, 0xd237, 0x17ae, 0x1c9c, 0xd905, 0xfeff, 0x3b66, 0x3054, 0xf5cd, 0x2630, 0xe3a9, 0xe89b,
00067   0x2d02, 0xa76f, 0x62f6, 0x69c4, 0xac5d, 0x7fa0, 0xba39, 0xb10b, 0x7492, 0x5368, 0x96f1, 0x9dc3,
00068   0x585a, 0x8ba7, 0x4e3e, 0x450c, 0x8095
00069 };
00070 
00071 /**
00072 *******************************************************************************
00073 * Function: Pec15_Calc
00074 * @brief CRC15 Pec Calculation Function
00075 *
00076 * @details This function calculates and return the CRC15 value
00077 *
00078 * Parameters:
00079 * @param [in]   Len Data length
00080 *
00081 * @param [in] *data    Data pointer
00082 *
00083 * @return CRC15_Value
00084 *
00085 *******************************************************************************
00086 */
00087 uint16_t Pec15_Calc
00088 (
00089 uint8_t len, /*!< Number of bytes that will be used to calculate a PEC */
00090 uint8_t *data /*!< Array of data that will be used to calculate  a PEC */
00091 )
00092 {
00093   uint16_t remainder,addr;
00094   remainder = 16; /*!< initialize the PEC */
00095   for (uint8_t i = 0; i<len; i++) /*!< loops for each byte in data array */
00096   {
00097     addr = (((remainder>>7)^data[i])&0xff);/*!< calculate PEC table address */
00098     remainder = ((remainder<<8)^Crc15Table[addr]);
00099   }
00100   return(remainder*2);/*!< The CRC15 has a 0 in the LSB so the remainder must be multiplied by 2 */
00101 }
00102 
00103 /**
00104 *******************************************************************************
00105 * Function: Pec10_Calc
00106 * @brief CRC10 Pec Calculation Function
00107 *
00108 * @details This function calculates and return the CRC15 value
00109 *
00110 * Parameters:
00111 * @param [in]   Len Data length
00112 *
00113 * @param [in] *data    Data pointer
00114 *
00115 * @return CRC15_Value
00116 *
00117 *******************************************************************************
00118 */
00119 uint16_t pec10_calc(bool rx_cmd, int len, uint8_t *data)
00120 {
00121   uint16_t remainder = 16; /*!< PEC_SEED;   0000010000 */
00122   uint16_t polynom = 0x8F; /*!< x10 + x7 + x3 + x2 + x + 1 <- the CRC15 polynomial         100 1000 1111   48F */
00123 
00124   /*!< Perform modulo-2 division, a byte at a time. */
00125   for (uint8_t pbyte = 0; pbyte < len; ++pbyte)
00126   {
00127     /*!< Bring the next byte into the remainder. */
00128     remainder ^= (uint16_t)(data[pbyte] << 2);
00129     /*!< Perform modulo-2 division, a bit at a time.*/
00130     for (uint8_t bit_ = 8; bit_ > 0; --bit_)
00131     {
00132       /*!< Try to divide the current data bit. */
00133       if ((remainder & 0x200) > 0)/*!<equivalent to remainder & 2^14 simply check for MSB */
00134       {
00135         remainder = (uint16_t)((remainder << 1));
00136         remainder = (uint16_t)(remainder ^ polynom);
00137       }
00138       else
00139       {
00140         remainder = (uint16_t)(remainder << 1);
00141       }
00142     }
00143   }
00144   if (rx_cmd == true)
00145   {
00146     remainder ^= (uint16_t)((data[len] & 0xFC) << 2);
00147     /*!< Perform modulo-2 division, a bit at a time */
00148     for (uint8_t bit_ = 6; bit_ > 0; --bit_)
00149     {
00150       /*!< Try to divide the current data bit */
00151       if ((remainder & 0x200) > 0)/*!<equivalent to remainder & 2^14 simply check for MSB*/
00152       {
00153         remainder = (uint16_t)((remainder << 1));
00154         remainder = (uint16_t)(remainder ^ polynom);
00155       }
00156       else
00157       {
00158         remainder = (uint16_t)((remainder << 1));
00159       }
00160     }
00161   }
00162   return ((uint16_t)(remainder & 0x3FF));
00163 }
00164 
00165 /**
00166 *******************************************************************************
00167 * Function: spiSendCmd
00168 * @brief Send command over SPI
00169 *
00170 * @details This function send bms command in spi line
00171 *
00172 * Parameters:
00173 * @param [in]   tIC      Total IC
00174 *
00175 * @param [in]  *ic      cell_asic structure pointer
00176 *
00177 * @param [in]  tx_cmd   Tx command byte array
00178 *
00179 * @return None
00180 *
00181 *******************************************************************************
00182 */
00183 void spiSendCmd(uint8_t tx_cmd[2])
00184 {
00185   uint8_t cmd[4];
00186   uint16_t cmd_pec;
00187   cmd[0] = tx_cmd[0];
00188   cmd[1] =  tx_cmd[1];
00189   cmd_pec = Pec15_Calc(2, cmd);
00190   cmd[2] = (uint8_t)(cmd_pec >> 8);
00191   cmd[3] = (uint8_t)(cmd_pec);
00192   adBmsCsLow();
00193   spiWriteBytes(&cmd[0], 4);
00194   adBmsCsHigh();
00195 }
00196 
00197 /**
00198 *******************************************************************************
00199 * Function: spiReadData
00200 * @brief Spi Read Data, Lower Level function for adBmsReadData
00201 *
00202 * @details This function send command to DUT and read command corrospond data byte.
00203 *
00204 * Parameters:
00205 * @param [in]   tIC     Total IC
00206 *
00207 * @param [in]  tx_cmd   Tx command bytes
00208 *
00209 * @param [in]  *rx_data Rx data pointer
00210 *
00211 * @param [in]  *pec_error Pec error pointer
00212 *
00213 * @param [in]  *cmd_cntr command counter pointer
00214 *
00215 * @return None
00216 *
00217 *******************************************************************************
00218 */
00219 void spiReadData
00220 (
00221 uint8_t tIC,
00222 uint8_t tx_cmd[2],
00223 uint8_t *rx_data,
00224 uint8_t *pec_error,
00225 uint8_t *cmd_cntr,
00226 uint8_t regData_size
00227 )
00228 {
00229   uint8_t *data, *copyArray, src_address = 0;
00230   uint16_t cmd_pec, received_pec, calculated_pec;
00231   uint8_t BYTES_IN_REG = regData_size;
00232   uint8_t RX_BUFFER = (regData_size * tIC);
00233 
00234   data = (uint8_t *)calloc(RX_BUFFER, sizeof(uint8_t));
00235   copyArray = (uint8_t *)calloc(BYTES_IN_REG, sizeof(uint8_t));
00236   if((data == NULL) || (copyArray == NULL))
00237   {
00238     printMsg("Failed to allocate spi read data memory");
00239     exit(0);
00240   }
00241   else
00242   {
00243     uint8_t cmd[4];
00244     cmd[0] = tx_cmd[0];
00245     cmd[1] = tx_cmd[1];
00246     cmd_pec = Pec15_Calc(2, cmd);
00247     cmd[2] = (uint8_t)(cmd_pec >> 8);
00248     cmd[3] = (uint8_t)(cmd_pec);
00249     adBmsWakeupIc(tIC);
00250     adBmsCsLow();
00251     spiWriteReadBytes(&cmd[0], &data[0], RX_BUFFER);                 /*!< Read the configuration data of all ICs on the daisy chain into readdata array */
00252     adBmsCsHigh();
00253     for (uint8_t current_ic = 0; current_ic < tIC; current_ic++)     /*!< executes for each ic in the daisy chain and packs the data */
00254     {                                                                                                                                     /*!< Into the r_comm array as well as check the received data for any bit errors */
00255       for (uint8_t current_byte = 0; current_byte < (BYTES_IN_REG-2); current_byte++)
00256       {
00257         rx_data[(current_ic*BYTES_IN_REG)+current_byte] = data[current_byte + (current_ic*BYTES_IN_REG)];
00258       }
00259       /*!< Get command counter value */
00260       cmd_cntr[current_ic] = (data[(current_ic * BYTES_IN_REG) + (BYTES_IN_REG - 2)] >> 2);
00261       /*!< Get received pec value from ic*/
00262       received_pec = (uint16_t)(((data[(current_ic * BYTES_IN_REG) + (BYTES_IN_REG - 2)] & 0x03) << 8) | data[(current_ic * BYTES_IN_REG) + (BYTES_IN_REG - 1)]);
00263       /*!< Copy each ic correspond data + pec value for calculate data pec */
00264       memcpy(&copyArray[0], &data[src_address], BYTES_IN_REG);
00265       src_address = ((current_ic+1) * (regData_size));
00266       /*!< Calculate data pec */
00267       calculated_pec = (uint16_t)pec10_calc(true, (BYTES_IN_REG-2), &copyArray[0]);
00268       /*!< Match received pec with calculated pec */
00269       if (received_pec == calculated_pec){ pec_error[current_ic] = 0; }/*!< If no error is there value set to 0 */
00270       else{ pec_error[current_ic] = 1; }                               /*!< If error is there value set to 1 */
00271     }
00272   }
00273   free(data);
00274   free(copyArray);
00275 }
00276 
00277 /**
00278 *******************************************************************************
00279 * Function: spiWriteData
00280 * @brief write data over SPI, Lower Level function for adBmsWriteData
00281 *
00282 * @details This function write the data into bms ic
00283 *
00284 * Parameters:
00285 * @param [in]   tIC      Total IC
00286 *
00287 * @param [in]  tx_cmd   Tx command bytes
00288 *
00289 * @param [in]  *data   Data pointer
00290 *
00291 * @return None
00292 *
00293 *******************************************************************************
00294 */
00295 void spiWriteData
00296 (
00297 uint8_t tIC,
00298 uint8_t tx_cmd[2],
00299 uint8_t *data
00300 )
00301 {
00302   uint8_t BYTES_IN_REG = TX_DATA;
00303   uint8_t CMD_LEN = 4 + (RX_DATA * tIC);
00304   uint16_t data_pec, cmd_pec;
00305   uint8_t *cmd, copyArray[TX_DATA], src_address = 0;
00306   uint8_t cmd_index;
00307   cmd = (uint8_t *)calloc(CMD_LEN, sizeof(uint8_t));
00308   if(cmd == NULL)
00309   {
00310     printMsg("Failed to allocate cmd array memory");
00311     exit(0);
00312   }
00313   else
00314   {
00315     cmd[0] = tx_cmd[0];
00316     cmd[1] = tx_cmd[1];
00317     cmd_pec = Pec15_Calc(2, cmd);
00318     cmd[2] = (uint8_t)(cmd_pec >> 8);
00319     cmd[3] = (uint8_t)(cmd_pec);
00320     cmd_index = 4;
00321     /*!< executes for each LTC68xx, this loops starts with the last IC on the stack */
00322     for (uint8_t current_ic = tIC; current_ic > 0; current_ic--)
00323     {
00324       src_address = ((current_ic-1) * TX_DATA);
00325       /*!< The first configuration written is received by the last IC in the daisy chain */
00326       for (uint8_t current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)
00327       {
00328         cmd[cmd_index] = data[((current_ic-1)*6)+current_byte];
00329         cmd_index = cmd_index + 1;
00330       }
00331       /*!< Copy each ic correspond data + pec value for calculate data pec */
00332       memcpy(&copyArray[0], &data[src_address], TX_DATA); /*!< dst, src, size */
00333       /*!< calculating the PEC for each Ics configuration register data */
00334       data_pec = (uint16_t)pec10_calc(true,BYTES_IN_REG, &copyArray[0]);
00335       cmd[cmd_index] = (uint8_t)(data_pec >> 8);
00336       cmd_index = cmd_index + 1;
00337       cmd[cmd_index] = (uint8_t)data_pec;
00338       cmd_index = cmd_index + 1;
00339     }
00340     adBmsCsLow();
00341     spiWriteBytes(&cmd[0], CMD_LEN);
00342     adBmsCsHigh();
00343   }
00344   free(cmd);
00345 }
00346 
00347 /**
00348 *******************************************************************************
00349 * Function: adBmsReadData
00350 * @brief Adbms Read Data From Bms ic.
00351 *
00352 * @details This function sends the command read payload, parse data put it in structure and check pec error.(Ex: RDCFGA)
00353 *
00354 * Parameters:
00355 * @param [in]   tIC      Total IC
00356 *
00357 * @param [in]  *ic      cell_asic stucture pointer
00358 *
00359 * @param [in]  cmd_arg   command bytes
00360 *
00361 * @param [in]  TYPE   Enum type of resistor
00362 *
00363 * @param [in]  GRP   Enum type of resistor group
00364 *
00365 * @return None
00366 *
00367 *******************************************************************************
00368 */
00369 void adBmsReadData(uint8_t tIC, cell_asic *ic, uint8_t cmd_arg[2], TYPE type, GRP group)
00370 {
00371   uint16_t rBuff_size;
00372   uint8_t regData_size;
00373   if(group == ALL_GRP)
00374   {
00375     if(type == Rdalla){rBuff_size = RDALLA_SIZE; regData_size = RDALLA_SIZE;}
00376     else if(type == Rdallb){rBuff_size = RDALLB_SIZE; regData_size = RDALLB_SIZE;}
00377     else if(type == Rdcall){rBuff_size = RDCALL_SIZE; regData_size = RDCALL_SIZE;}
00378     else if(type == Rdasall){rBuff_size = RDASALL_SIZE; regData_size = RDASALL_SIZE;}
00379     else
00380     {
00381       printMsg("Read All cmd wrong type select");
00382     }
00383   }
00384   else{rBuff_size = (tIC * RX_DATA); regData_size = RX_DATA;}
00385   uint8_t *read_buffer, *pec_error, *cmd_count;
00386   read_buffer = (uint8_t *)calloc(rBuff_size, sizeof(uint8_t));
00387   pec_error = (uint8_t *)calloc(tIC, sizeof(uint8_t));
00388   cmd_count = (uint8_t *)calloc(tIC, sizeof(uint8_t));
00389   if((pec_error == NULL) || (cmd_count == NULL) || (read_buffer == NULL))
00390   {
00391     printMsg("Failed to allocate memory");
00392     exit(0);
00393   }
00394   else
00395   {
00396     spiReadData(tIC, &cmd_arg[0], &read_buffer[0], &pec_error[0], &cmd_count[0], regData_size);
00397     switch (type)
00398     {
00399     case Config:
00400       adBms2950ParseConfig(tIC, ic, group, &read_buffer[0]);
00401       for (uint8_t cic = 0; cic < tIC; cic++)
00402       {
00403         ic[cic].cccrc.cfgr_pec = pec_error[cic];
00404       }
00405       break;
00406 
00407     case Vr:
00408       adBms2950VrParseData(tIC, ic, group, &read_buffer[0]);
00409       for (uint8_t cic = 0; cic < tIC; cic++)
00410       {
00411         ic[cic].cccrc.vr_pec = pec_error[cic];
00412       }
00413       break;
00414 
00415     case Rvr:
00416       adBms2950RedVrParseData(tIC, ic, group, &read_buffer[0]);
00417       for (uint8_t cic = 0; cic < tIC; cic++)
00418       {
00419         ic[cic].cccrc.rvr_pec = pec_error[cic];
00420       }
00421       break;
00422 
00423     case Cr:
00424       adBms2950ParseCurrentRegData(tIC, ic, &read_buffer[0]);
00425       for (uint8_t cic = 0; cic < tIC; cic++)
00426       {
00427         ic[cic].cccrc.cr_pec = pec_error[cic];
00428       }
00429       break;
00430 
00431     case Vbat:
00432       adBms2950ParseVbatRegData(tIC, ic, &read_buffer[0]);
00433       for (uint8_t cic = 0; cic < tIC; cic++)
00434       {
00435         ic[cic].cccrc.vbat_pec = pec_error[cic];
00436       }
00437       break;
00438 
00439     case Ivbat:
00440       adBms2950ParseIVbatRegData(tIC, ic, &read_buffer[0]);
00441       for (uint8_t cic = 0; cic < tIC; cic++)
00442       {
00443         ic[cic].cccrc.ivbat_pec = pec_error[cic];
00444       }
00445       break;
00446 
00447     case Oc:
00448       adBms2950ParseOcRegData(tIC, ic, &read_buffer[0]);
00449       for (uint8_t cic = 0; cic < tIC; cic++)
00450       {
00451         ic[cic].cccrc.oc_pec = pec_error[cic];
00452       }
00453       break;
00454 
00455     case AvgCr:
00456       adBms2950ParseAvgCurrentRegData(tIC, ic, &read_buffer[0]);
00457       for (uint8_t cic = 0; cic < tIC; cic++)
00458       {
00459         ic[cic].cccrc.avgcr_pec = pec_error[cic];
00460       }
00461       break;
00462 
00463     case AvgVbat:
00464       adBms2950ParseAvgVbatRegData(tIC, ic, &read_buffer[0]);
00465       for (uint8_t cic = 0; cic < tIC; cic++)
00466       {
00467         ic[cic].cccrc.avgvbat_pec = pec_error[cic];
00468       }
00469       break;
00470 
00471     case AvgIvbat:
00472       adBms2950ParseAvgIVbatRegData(tIC, ic, &read_buffer[0]);
00473       for (uint8_t cic = 0; cic < tIC; cic++)
00474       {
00475         ic[cic].cccrc.avgivbat_pec = pec_error[cic];
00476       }
00477       break;
00478 
00479     case Status:
00480       adBms2950ParseStatus(tIC, ic, group, &read_buffer[0]);
00481       for (uint8_t cic = 0; cic < tIC; cic++)
00482       {
00483         ic[cic].cccrc.stat_pec = pec_error[cic];
00484       }
00485       break;
00486 
00487     case Comm:
00488       adBms2950ParseComm(tIC, ic, &read_buffer[0]);
00489       for (uint8_t cic = 0; cic < tIC; cic++)
00490       {
00491         ic[cic].cccrc.comm_pec = pec_error[cic];
00492       }
00493       break;
00494 
00495     case SID:
00496       adBms2950ParseSID(tIC, ic, &read_buffer[0]);
00497       for (uint8_t cic = 0; cic < tIC; cic++)
00498       {
00499         ic[cic].cccrc.sid_pec = pec_error[cic];
00500       }
00501       break;
00502 
00503     case Rdalla:
00504       // TBD
00505       break;
00506 
00507     case Rdallb:
00508       // TBD
00509       break;
00510 
00511     case Rdcall:
00512       // TBD
00513       break;
00514 
00515     case Rdasall:
00516       // TBD
00517       break;
00518 
00519     default:
00520       break;
00521     }
00522   }
00523   free(read_buffer);
00524   free(pec_error);
00525   free(cmd_count);
00526 }
00527 /**
00528 *******************************************************************************
00529 * Function: adBmsWriteData
00530 * @brief Adbms Write Data into Bms ic.
00531 *
00532 * @details This function write the data to DUT. (EX: WRCFGA)
00533 *
00534 * Parameters:
00535 * @param [in]   tIC      Total IC
00536 *
00537 * @param [in]  *ic      cell_asic stucture pointer
00538 *
00539 * @param [in]  cmd_arg   command bytes
00540 *
00541 * @param [in]  TYPE   Enum type of resistor
00542 *
00543 * @param [in]  GRP   Enum type of resistor group
00544 *
00545 * @return None
00546 *
00547 *******************************************************************************
00548 */
00549 void adBmsWriteData(uint8_t tIC, cell_asic *ic, uint8_t cmd_arg[2], TYPE type, GRP group)
00550 {
00551   uint8_t data_len = TX_DATA, write_size = (TX_DATA * tIC);
00552   uint8_t *write_buffer = (uint8_t *)calloc(write_size, sizeof(uint8_t));
00553   if(write_buffer == NULL)
00554   {
00555     printMsg("Failed to allocate write_buffer array memory");
00556     exit(0);
00557   }
00558   else
00559   {
00560     switch (type)
00561     {
00562     case Config:
00563       switch (group)
00564       {
00565       case A:
00566         adBms2950CreateConfiga(tIC, &ic[0]);
00567         for (uint8_t cic = 0; cic < tIC; cic++)
00568         {
00569           for (uint8_t data = 0; data < data_len; data++)
00570           {
00571             write_buffer[(cic * data_len) + data] = ic[cic].configa.tx_data[data];
00572           }
00573         }
00574         break;
00575       case B:
00576         adBms2950CreateConfigb(tIC, &ic[0]);
00577         for (uint8_t cic = 0; cic < tIC; cic++)
00578         {
00579           for (uint8_t data = 0; data < data_len; data++)
00580           {
00581             write_buffer[(cic * data_len) + data] = ic[cic].configb.tx_data[data];
00582           }
00583         }
00584         break;
00585       }
00586       break;
00587 
00588     case Comm:
00589       adBms2950CreateComm(tIC, &ic[0]);
00590       for (uint8_t cic = 0; cic < tIC; cic++)
00591       {
00592         for (uint8_t data = 0; data < data_len; data++)
00593         {
00594           write_buffer[(cic * data_len) + data] = ic[cic].com.tx_data[data];
00595         }
00596       }
00597       break;
00598 
00599     case Clrflag:
00600       adBms2950CreateClrflagData(tIC, &ic[0]);
00601       for (uint8_t cic = 0; cic < tIC; cic++)
00602       {
00603         for (uint8_t data = 0; data < data_len; data++)
00604         {
00605           write_buffer[(cic * data_len) + data] = ic[cic].clrflag.tx_data[data];
00606         }
00607       }
00608       break;
00609 
00610     default:
00611       break;
00612     }
00613   }
00614   adBmsWakeupIc(tIC);
00615   spiWriteData(tIC, cmd_arg, &write_buffer[0]);
00616   free(write_buffer);
00617 }
00618 
00619 /**
00620 *******************************************************************************
00621 * Function: adBmsPollAdc
00622 * @brief PLADC Command.
00623 *
00624 * @details Send poll adc command and retun adc conversion count.
00625 *
00626 * Parameters:
00627 *
00628 * @param [in]  tIC      Total IC
00629 *
00630 * @param [in]  *ic      cell_asic structure pointer
00631 *
00632 * @param [in]  tx_cmd   Tx command byte
00633 *
00634 * @return Pladc_count(uint32_t)
00635 *
00636 *******************************************************************************
00637 */
00638 uint32_t adBmsPollAdc(uint8_t tx_cmd[2])
00639 {
00640   uint32_t pladc_count = 0;
00641   uint8_t cmd[4];
00642   uint16_t cmd_pec;
00643   uint8_t read_data = 0x00;
00644   uint8_t SDO_Line = 0xFF;
00645   cmd[0] = tx_cmd[0];
00646   cmd[1] = tx_cmd[1];
00647   cmd_pec = Pec15_Calc(2, cmd);
00648   cmd[2] = (uint8_t)(cmd_pec >> 8);
00649   cmd[3] = (uint8_t)(cmd_pec);
00650   startTimer();
00651   adBmsCsLow();
00652   spiWriteBytes(&cmd[0], 4);
00653   do{
00654     spiReadBytes(&read_data, 1);
00655   }while(!(read_data == SDO_Line));
00656   adBmsCsHigh();
00657   pladc_count = getTimCount();
00658   stopTimer();
00659   return(pladc_count);
00660 }
00661 
00662 /** @}*/
00663 /** @}*/