foxBMS  1.2.1
The foxBMS Battery Management System API Documentation
ltc_6806.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2021, Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from
20  * this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * We kindly request you to use one or more of the following phrases to refer to
34  * foxBMS in your hardware, software, documentation or advertising materials:
35  *
36  * - ″This product uses parts of foxBMS®″
37  * - ″This product includes parts of foxBMS®″
38  * - ″This product is derived from foxBMS®″
39  *
40  */
41 
42 /**
43  * @file ltc_6806.c
44  * @author foxBMS Team
45  * @date 2019-09-01 (date of creation)
46  * @updated 2021-12-07 (date of last update)
47  * @ingroup DRIVERS
48  * @prefix LTC
49  *
50  * @brief Driver for the LTC monitoring chip.
51  *
52  */
53 
54 /*========== Includes =======================================================*/
55 /* clang-format off */
56 #include "ltc.h"
57 #include "ltc_6806_cfg.h"
58 /* clang-format on */
59 
60 #include "HL_spi.h"
61 #include "HL_system.h"
62 
63 #include "database.h"
64 #include "diag.h"
65 #include "io.h"
66 #include "ltc_pec.h"
67 #include "pex.h"
68 #include "os.h"
69 #include "afe_plausibility.h"
70 
71 /*========== Macros and Definitions =========================================*/
72 
73 /**
74  * TI port expander register addresses
75  * @{
76  */
77 #define LTC_PORT_EXPANDER_TI_INPUT_REG_ADR (0x00u)
78 #define LTC_PORT_EXPANDER_TI_OUTPUT_REG_ADR (0x01u)
79 #define LTC_PORT_EXPANDER_TI_CONFIG_REG_ADR (0x03u)
80 /**@}*/
81 
82 /**
83  * Value of the LSB in mV
84  */
85 #if LTC_HIRNG == 0u
86 #define LTC_FUEL_CELL_LSB_RESOLUTION_mV (1.5f)
87 #else
88 #define LTC_FUEL_CELL_LSB_RESOLUTION_mV (3.0f)
89 #endif
90 
91 /**
92  * Value for positive full scale measurement for fuel cell
93  */
94 #define LTC_FUELCELL_POSITIVE_FULLSCALE_RANGE_mV ((int16_t)((0x7FF * LTC_FUEL_CELL_LSB_RESOLUTION_mV)))
95 
96 /**
97  * Value for negative full scale measurement for fuel cell
98  */
99 #define LTC_FUELCELL_NEGATIVE_FULLSCALE_RANGE_mV \
100  ((int16_t)((((~0x001) + 1) & 0x7FF) * (-LTC_FUEL_CELL_LSB_RESOLUTION_mV)))
101 
102 /*========== Static Constant and Variable Definitions =======================*/
103 /**
104  * PEC buffer for RX and TX
105  * @{
106  */
107 #pragma SET_DATA_SECTION(".sharedRAM")
110 #pragma SET_DATA_SECTION()
111 /**@}*/
112 
113 /** index of used cells */
114 static uint16_t ltc_used_cells_index[BS_NR_OF_STRINGS] = {0};
115 /** local copies of database tables */
116 /**@{*/
121 /**@}*/
122 /** stores information on the detected open wires locally */
124 static LTC_ERRORTABLE_s ltc_errorTable = {0}; /*!< init in LTC_ResetErrorTable-function */
125 
126 /** local definition of plausible cell voltage values for the LTC 6806 */
129  .minimumPlausibleVoltage_mV = -5000,
130 };
131 
132 /*========== Extern Constant and Variable Definitions =======================*/
133 
135  .timer = 0,
136  .statereq = {.request = LTC_STATE_NO_REQUEST, .string = 0xFFu},
138  .substate = 0,
139  .laststate = LTC_STATEMACH_UNINITIALIZED,
140  .lastsubstate = 0,
141  .adcModereq = LTC_ADCMODE_FAST_DCP0,
142  .adcMode = LTC_ADCMODE_FAST_DCP0,
143  .adcMeasChreq = LTC_ADCMEAS_UNDEFINED,
144  .adcMeasCh = LTC_ADCMEAS_UNDEFINED,
145  .numberOfMeasuredMux = 32,
146  .triggerentry = 0,
147  .ErrRetryCounter = 0,
148  .ErrRequestCounter = 0,
149  .VoltageSampleTime = 0,
150  .muxSampleTime = 0,
151  .commandDataTransferTime = 3,
152  .commandTransferTime = 3,
153  .gpioClocksTransferTime = 3,
154  .muxmeas_seqptr = NULL_PTR,
155  .muxmeas_seqendptr = NULL_PTR,
156  .muxmeas_nr_end = 0,
157  .first_measurement_made = false,
158  .ltc_muxcycle_finished = STD_NOT_OK,
159  .check_spi_flag = STD_NOT_OK,
160  .balance_control_done = STD_NOT_OK,
161  .transmit_ongoing = false,
162  .dummyByte_ongoing = STD_NOT_OK,
163  .ltcData.pSpiInterface = spi_ltcInterface,
164  .ltcData.txBuffer = ltc_TxPecBuffer,
165  .ltcData.rxBuffer = ltc_RxPecBuffer,
166  .ltcData.frameLength = LTC_N_BYTES_FOR_DATA_TRANSMISSION,
167  .ltcData.cellVoltage = &ltc_cellvoltage,
168  .ltcData.cellTemperature = &ltc_celltemperature,
169  .ltcData.balancingFeedback = NULL_PTR,
170  .ltcData.balancingControl = NULL_PTR,
171  .ltcData.slaveControl = NULL_PTR,
172  .ltcData.openWireDetection = &ltc_openWireDetection,
173  .ltcData.errorTable = &ltc_errorTable,
174  .ltcData.allGpioVoltages = &ltc_allgpiovoltage,
175  .ltcData.openWire = &ltc_openwire,
176  .ltcData.usedCellIndex = ltc_used_cells_index,
177  .currentString = 0u,
178  .requestedString = 0u,
179 };
180 
181 static uint16_t ltc_cmdWRCFG[4] = {0x00, 0x01, 0x3D, 0x6E};
182 static uint16_t ltc_cmdRDCFG[4] = {0x00, 0x02, 0x2B, 0x0A};
183 
184 /* static uint16_t ltc_cmdRDAUXA[4] = {0x00, 0x0C, 0xEF, 0xCC};
185 static uint16_t ltc_cmdRDAUXB[4] = {0x00, 0x0E, 0x72, 0x9A};
186 static uint16_t ltc_cmdRDAUXC[4] = {0x00, 0x0D, 0x64, 0xFE};
187 static uint16_t ltc_cmdRDAUXD[4] = {0x00, 0x0F, 0xF9, 0xA8}; */
188 
189 static uint16_t ltc_cmdRDCVA_Fuelcell[4] = {0x00, 0x04, 0x07, 0xC2};
190 static uint16_t ltc_cmdRDCVB_Fuelcell[4] = {0x00, 0x05, 0x8C, 0xF0};
191 static uint16_t ltc_cmdRDCVC_Fuelcell[4] = {0x00, 0x06, 0x9A, 0x94};
192 static uint16_t ltc_cmdRDCVD_Fuelcell[4] = {0x00, 0x07, 0x11, 0xA6};
193 static uint16_t ltc_cmdRDCVE_Fuelcell[4] = {0x00, 0x08, 0x5E, 0x52};
194 static uint16_t ltc_cmdRDCVF_Fuelcell[4] = {0x00, 0x09, 0xD5, 0x60};
195 static uint16_t ltc_cmdRDCVG_Fuelcell[4] = {0x00, 0x0A, 0xC3, 0x04};
196 static uint16_t ltc_cmdRDCVH_Fuelcell[4] = {0x00, 0x0B, 0x48, 0x36};
197 static uint16_t ltc_cmdRDCVI_Fuelcell[4] = {0x00, 0x0C, 0xEF, 0xCC};
198 
199 /* static uint16_t ltc_cmdMUTE[4] = {0x00, 0x28, 0xE8, 0x0E}; !< MUTE discharging via S pins */
200 /* static uint16_t ltc_cmdUNMUTE[4] = {0x00, 0x29, 0x63, 0x3C}; !< UN-MUTE discharging via S pins */
201 
202 static uint16_t ltc_cmdADCV_normal_Fuelcell[4] = {0x04, 0x40, 0xED, 0xB0}; /*!< All cells, normal mode */
203 
204 /* GPIOs */
205 /* static uint16_t ltc_cmdADAX_normal_GPIO1[4] = {0x05, 0x61, 0x58, 0x92}; !< Single channel, GPIO 1, normal mode */
206 /* static uint16_t ltc_cmdADAX_filtered_GPIO1[4] = {0x05, 0xE1, 0x1C, 0xB4}; !< Single channel, GPIO 1, filtered mode */
207 /* static uint16_t ltc_cmdADAX_fast_GPIO1[4] = {0x04, 0xE1, 0x94, 0xF8}; !< Single channel, GPIO 1, fast mode */
208 /* static uint16_t ltc_cmdADAX_normal_GPIO2[4] = {0x05, 0x62, 0x4E, 0xF6}; !< Single channel, GPIO 2, normal mode */
209 /* static uint16_t ltc_cmdADAX_filtered_GPIO2[4] = {0x05, 0xE2, 0x0A, 0xD0}; !< Single channel, GPIO 2, filtered mode */
210 /* static uint16_t ltc_cmdADAX_fast_GPIO2[4] = {0x04, 0xE2, 0x82, 0x9C}; !< Single channel, GPIO 2, fast mode */
211 /* static uint16_t ltc_cmdADAX_normal_GPIO3[4] = {0x05, 0x63, 0xC5, 0xC4}; !< Single channel, GPIO 3, normal mode */
212 /* static uint16_t ltc_cmdADAX_filtered_GPIO3[4] = {0x05, 0xE3, 0x81, 0xE2}; !< Single channel, GPIO 3, filtered mode */
213 /* static uint16_t ltc_cmdADAX_fast_GPIO3[4] = {0x04, 0xE3, 0x09, 0xAE}; !< Single channel, GPIO 3, fast mode */
214 /* static uint16_t ltc_cmdADAX_normal_GPIO4[4] = {0x05, 0x64, 0x62, 0x3E}; !< Single channel, GPIO 4, normal mode */
215 /* static uint16_t ltc_cmdADAX_filtered_GPIO4[4] = {0x05, 0xE4, 0x26, 0x18}; !< Single channel, GPIO 4, filtered mode */
216 /* static uint16_t ltc_cmdADAX_fast_GPIO4[4] = {0x04, 0xE4, 0xAE, 0x54}; !< Single channel, GPIO 4, fast mode */
217 /* static uint16_t ltc_cmdADAX_normal_GPIO5[4] = {0x05, 0x65, 0xE9, 0x0C}; !< Single channel, GPIO 5, normal mode */
218 /* static uint16_t ltc_cmdADAX_filtered_GPIO5[4] = {0x05, 0xE5, 0xAD, 0x2A}; !< Single channel, GPIO 5, filtered mode */
219 /* static uint16_t ltc_cmdADAX_fast_GPIO5[4] = {0x04, 0xE5, 0x25, 0x66}; !< Single channel, GPIO 5, fast mode */
220 /* static uint16_t ltc_cmdADAX_normal_ALLGPIOS[4] = {0x05, 0x60, 0xD3, 0xA0}; !< All channels, normal mode */
221 /* static uint16_t ltc_cmdADAX_filtered_ALLGPIOS[4] =
222  {0x05, 0xE0, 0x97, 0x86}; !< All channels, filtered mode */
223 /* static uint16_t ltc_cmdADAX_fast_ALLGPIOS[4] = {0x04, 0xE0, 0x1F, 0xCA}; !< All channels, fast mode */
224 
225 /* Open-wire */
227  {0x07, 0xC0, 0xBA, 0x70}; /*!< Broadcast, Pull-up current, All cells, normal mode, 100ms */
229  {0x06, 0xC0, 0x32, 0x3C}; /*!< Broadcast, Pull-down current, All cells, normal mode, 100ms */
230 
231 /*========== Static Function Prototypes =====================================*/
232 static void LTC_SetFirstMeasurementCycleFinished(LTC_STATE_s *ltc_state);
233 static void LTC_Initialize_Database(LTC_STATE_s *ltc_state);
234 static void LTC_SaveLastStates(LTC_STATE_s *ltc_state);
235 static void LTC_StateTransition(LTC_STATE_s *ltc_state, LTC_STATEMACH_e state, uint8_t substate, uint16_t timer_ms);
236 static void LTC_CondBasedStateTransition(
237  LTC_STATE_s *ltc_state,
238  STD_RETURN_TYPE_e retVal,
239  DIAG_ID_e diagCode,
240  LTC_STATEMACH_e state_ok,
241  uint8_t substate_ok,
242  uint16_t timer_ms_ok,
243  LTC_STATEMACH_e state_nok,
244  uint8_t substate_nok,
245  uint16_t timer_ms_nok);
246 
247 static void LTC_ResetErrorTable(LTC_STATE_s *ltc_state);
249  SPI_INTERFACE_CONFIG_s *pSpiInterface,
250  uint16_t *pTxBuff,
251  uint16_t *pRxBuff,
252  uint32_t frameLength);
253 
255  SPI_INTERFACE_CONFIG_s *pSpiInterface,
256  LTC_ADCMODE_e adcMode,
257  LTC_ADCMEAS_CHAN_e adcMeasCh);
259  SPI_INTERFACE_CONFIG_s *pSpiInterface,
260  LTC_ADCMODE_e adcMode,
261  uint8_t PUP);
262 
264  LTC_STATE_s *ltc_state,
265  uint16_t *pRxBuff,
266  uint8_t registerSet,
267  uint8_t stringNumber);
268 
270  LTC_STATE_s *ltc_state,
271  uint16_t *DataBufferSPI_RX_with_PEC,
272  uint8_t stringNumber);
274  uint16_t *Command,
275  SPI_INTERFACE_CONFIG_s *pSpiInterface,
276  uint16_t *pTxBuff,
277  uint16_t *pRxBuff,
278  uint32_t frameLength);
279 
280 static uint32_t LTC_GetSPIClock(SPI_INTERFACE_CONFIG_s *pSpiInterface);
281 static void LTC_SetTransferTimes(LTC_STATE_s *ltc_state);
282 
284 
285 /*========== Static Function Implementations ================================*/
286 /**
287  * @brief in the database, initializes the fields related to the LTC drivers.
288  *
289  * This function loops through all the LTC-related data fields in the database
290  * and sets them to 0. It should be called in the initialization or re-initialization
291  * routine of the LTC driver.
292  *
293  * @param ltc_state: state of the ltc state machine
294  *
295  */
296 static void LTC_Initialize_Database(LTC_STATE_s *ltc_state) {
297  uint16_t i = 0;
298 
299  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
300  ltc_state->ltcData.cellVoltage->state = 0;
301  for (i = 0; i < BS_NR_OF_BAT_CELLS; i++) {
302  ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber][i] = 0;
303  ltc_state->ltcData.openWireDetection->openWirePup[stringNumber][i] = 0;
304  ltc_state->ltcData.openWireDetection->openWirePdown[stringNumber][i] = 0;
305  ltc_state->ltcData.openWireDetection->openWireDelta[stringNumber][i] = 0;
306  }
307 
308  ltc_state->ltcData.cellTemperature->state = 0;
309  for (i = 0; i < BS_NR_OF_TEMP_SENSORS_PER_STRING; i++) {
310  ltc_state->ltcData.cellTemperature->cellTemperature_ddegC[stringNumber][i] = 0;
311  }
312 
313  ltc_state->ltcData.allGpioVoltages->state = 0;
314  for (i = 0; i < (BS_NR_OF_MODULES * BS_NR_OF_GPIOS_PER_MODULE); i++) {
315  ltc_state->ltcData.allGpioVoltages->gpioVoltages_mV[stringNumber][i] = 0;
316  }
317 
318  for (i = 0; i < (BS_NR_OF_MODULES * (BS_NR_OF_CELLS_PER_MODULE + 1)); i++) {
319  ltc_state->ltcData.openWire->openwire[stringNumber][i] = 0;
320  }
321  ltc_state->ltcData.openWire->state = 0;
322  }
323 
324  DATA_WRITE_DATA(ltc_state->ltcData.cellVoltage, ltc_state->ltcData.cellTemperature, ltc_state->ltcData.openWire);
325 }
326 
327 /**
328  * @brief Saves the last state and the last substate
329  *
330  * @param ltc_state: state of the ltc state machine
331  */
332 static void LTC_SaveLastStates(LTC_STATE_s *ltc_state) {
333  ltc_state->laststate = ltc_state->state;
334  ltc_state->lastsubstate = ltc_state->substate;
335 }
336 
337 /**
338  * @brief function for setting LTC_Trigger state transitions
339  *
340  * @param ltc_state: state of the ltc state machine
341  * @param state: state to transition into
342  * @param substate: substate to transition into
343  * @param timer_ms: transition into state, substate after timer elapsed
344  */
345 static void LTC_StateTransition(LTC_STATE_s *ltc_state, LTC_STATEMACH_e state, uint8_t substate, uint16_t timer_ms) {
346  ltc_state->state = state;
347  ltc_state->substate = substate;
348  ltc_state->timer = timer_ms;
349 }
350 
351 /**
352  * @brief condition-based state transition depending on retVal
353  *
354  * If retVal is #STD_OK, after timer_ms_ok is elapsed the LTC statemachine will
355  * transition into state_ok and substate_ok, otherwise after timer_ms_nok the
356  * statemachine will transition to state_nok and substate_nok. Depending on
357  * value of retVal the corresponding diagnosis entry will be called.
358  *
359  * @param ltc_state: state of the ltc state machine
360  * @param retVal: condition to determine if statemachine will transition into ok or nok states
361  * @param diagCode: symbolic IDs for diagnosis entry, called with #DIAG_EVENT_OK if retVal is #STD_OK, #DIAG_EVENT_NOT_OK otherwise
362  * @param state_ok state to transition into if retVal is #STD_OK
363  * @param substate_ok: substate to transition into if retVal is #STD_OK
364  * @param timer_ms_ok: transition into state_ok, substate_ok after timer_ms_ok elapsed
365  * @param state_nok: state to transition into if retVal is #STD_NOT_OK
366  * @param substate_nok: substate to transition into if retVal is #STD_NOT_OK
367  * @param timer_ms_nok: transition into state_nok, substate_nok after timer_ms_nok elapsed
368  */
370  LTC_STATE_s *ltc_state,
371  STD_RETURN_TYPE_e retVal,
372  DIAG_ID_e diagCode,
373  LTC_STATEMACH_e state_ok,
374  uint8_t substate_ok,
375  uint16_t timer_ms_ok,
376  LTC_STATEMACH_e state_nok,
377  uint8_t substate_nok,
378  uint16_t timer_ms_nok) {
379  if ((retVal != STD_OK)) {
381  LTC_StateTransition(ltc_state, state_nok, substate_nok, timer_ms_nok);
382  } else {
383  DIAG_Handler(diagCode, DIAG_EVENT_OK, DIAG_STRING, ltc_state->currentString);
384  LTC_StateTransition(ltc_state, state_ok, substate_ok, timer_ms_ok);
385  }
386 }
387 
388 /*========== Extern Function Implementations ================================*/
389 extern void LTC_SaveVoltages(LTC_STATE_s *ltc_state, uint8_t stringNumber) {
390  /* Pointer validity check */
391  FAS_ASSERT(ltc_state != NULL_PTR);
392 
393  /* Iterate over all cell to:
394  *
395  * 1. Check open-wires and set respective cell measurements to invalid
396  * 2. Perform minimum/maximum measurement value plausibility check
397  * 3. Calculate string values
398  */
399  STD_RETURN_TYPE_e cellVoltageMeasurementValid = STD_OK;
400  int32_t stringVoltage_mV = 0;
401  uint16_t numberValidMeasurements = 0;
402  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
403  for (uint8_t c = 0u; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
404  /* ------- 1. Check open-wires -----------------
405  * Is cell N input not open wire &&
406  * Is cell N+1 input not open wire &&
407  * Is cell voltage valid because of previous PEC error
408  * If so, everything okay, else set cell voltage measurement to invalid.
409  */
410  if ((ltc_state->ltcData.openWire->openwire[stringNumber][(m * (BS_NR_OF_CELLS_PER_MODULE + 1u)) + c] ==
411  0u) &&
412  (ltc_state->ltcData.openWire->openwire[stringNumber][(m * (BS_NR_OF_CELLS_PER_MODULE + 1u)) + c + 1u] ==
413  0u) &&
414  ((ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] & (0x01u << c)) == 0u)) {
415  /* Cell voltage is valid -> perform minimum/maximum plausibility check */
416 
417  /* ------- 2. Perform minimum/maximum measurement range check ---------- */
419  ltc_state->ltcData.cellVoltage
420  ->cellVoltage_mV[stringNumber][(m * BS_NR_OF_CELLS_PER_MODULE) + c],
422  /* Cell voltage is valid -> calculate string voltage */
423  /* -------- 3. Calculate string values ------------- */
424  stringVoltage_mV += ltc_state->ltcData.cellVoltage
425  ->cellVoltage_mV[stringNumber][(m * BS_NR_OF_CELLS_PER_MODULE) + c];
426  numberValidMeasurements++;
427  } else {
428  /* Invalidate cell voltage measurement */
429  ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << c);
430  cellVoltageMeasurementValid = STD_NOT_OK;
431  }
432  } else {
433  /* Set cell voltage measurement value invalid, if not already invalid because of PEC Error */
434  ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][m] |= (0x01u << c);
435  cellVoltageMeasurementValid = STD_NOT_OK;
436  }
437  }
438  }
439  DIAG_CheckEvent(cellVoltageMeasurementValid, DIAG_ID_AFE_CELL_VOLTAGE_MEAS_ERROR, DIAG_STRING, stringNumber);
440  ltc_state->ltcData.cellVoltage->packVoltage_mV[stringNumber] = stringVoltage_mV;
441  ltc_state->ltcData.cellVoltage->nrValidCellVoltages[stringNumber] = numberValidMeasurements;
442 
443  /* Increment state variable each time new values are written into database */
444  ltc_state->ltcData.cellVoltage->state++;
445 
446  DATA_WRITE_DATA(ltc_state->ltcData.cellVoltage);
447 }
448 
449 extern void LTC_SaveTemperatures(LTC_STATE_s *ltc_state, uint8_t stringNumber) {
450  STD_RETURN_TYPE_e cellTemperatureMeasurementValid = STD_OK;
451  uint16_t numberValidMeasurements = 0;
452  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
453  for (uint8_t c = 0u; c < BS_NR_OF_TEMP_SENSORS_PER_MODULE; c++) {
454  /* ------- 1. Check valid flag -----------------
455  * Is cell temperature valid because of previous PEC error
456  * If so, everything okay, else set cell temperature measurement to invalid.
457  */
458  if ((ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] & (0x01u << c)) == 0u) {
459  /* Cell temperature is valid -> perform minimum/maximum plausibility check */
460 
461  /* ------- 2. Perform minimum/maximum measurement range check ---------- */
462  if (STD_OK ==
464  ltc_state->ltcData.cellTemperature
465  ->cellTemperature_ddegC[stringNumber][(m * BS_NR_OF_TEMP_SENSORS_PER_MODULE) + c])) {
466  numberValidMeasurements++;
467  } else {
468  /* Invalidate cell temperature measurement */
469  ltc_state->ltcData.cellTemperature->invalidCellTemperature[stringNumber][m] |= (0x01u << c);
470  cellTemperatureMeasurementValid = STD_NOT_OK;
471  }
472  } else {
473  /* Already invalid because of PEC Error */
474  cellTemperatureMeasurementValid = STD_NOT_OK;
475  }
476  }
477  }
479  cellTemperatureMeasurementValid, DIAG_ID_AFE_CELL_TEMPERATURE_MEAS_ERROR, DIAG_STRING, stringNumber);
480 
481  ltc_state->ltcData.cellTemperature->nrValidTemperatures[stringNumber] = numberValidMeasurements;
482  ltc_state->ltcData.cellTemperature->state++;
484 }
485 
486 /**
487  * @brief stores the measured GPIOs in the database.
488  *
489  * This function loops through the data of all modules in the LTC daisy-chain that are
490  * stored in the ltc_allgpiovoltage buffer and writes them in the database.
491  * At each write iteration, the variable named "state" and related to voltages in the
492  * database is incremented.
493  *
494  * @param ltc_state: state of the ltc state machine
495  *
496  */
497 extern void LTC_SaveAllGPIOMeasurement(LTC_STATE_s *ltc_state) {
498  ltc_state->ltcData.allGpioVoltages->state++;
500 }
501 
502 /**
503  * @brief re-entrance check of LTC state machine trigger function
504  *
505  * This function is not re-entrant and should only be called time- or event-triggered.
506  * It increments the triggerentry counter from the state variable ltc_state.
507  * It should never be called by two different processes, so if it is the case, triggerentry
508  * should never be higher than 0 when this function is called.
509  *
510  * @param ltc_state: state of the ltc state machine
511  *
512  * @return retval 0 if no further instance of the function is active, 0xff else
513  *
514  */
515 uint8_t LTC_CheckReEntrance(LTC_STATE_s *ltc_state) {
516  uint8_t retval = 0;
517 
519  if (!ltc_state->triggerentry) {
520  ltc_state->triggerentry++;
521  } else {
522  retval = 0xFF; /* multiple calls of function */
523  }
525 
526  return (retval);
527 }
528 
529 /**
530  * @brief gets the current state request.
531  *
532  * This function is used in the functioning of the LTC state machine.
533  *
534  * @param ltc_state: state of the ltc state machine
535  *
536  * @return retval current state request, taken from LTC_STATE_REQUEST_e
537  */
539  LTC_REQUEST_s retval = {.request = LTC_STATE_NO_REQUEST, .string = 0x0u};
540 
542  retval.request = ltc_state->statereq.request;
543  retval.string = ltc_state->statereq.string;
545 
546  return (retval);
547 }
548 
549 /**
550  * @brief gets the current state.
551  *
552  * This function is used in the functioning of the LTC state machine.
553  *
554  * @param ltc_state: state of the ltc state machine
555  *
556  * @return current state, taken from LTC_STATEMACH_e
557  */
559  return ltc_state->state;
560 }
561 
562 /**
563  * @brief transfers the current state request to the state machine.
564  *
565  * This function takes the current state request from ltc_state and transfers it to the state machine.
566  * It resets the value from ltc_state to LTC_STATE_NO_REQUEST
567  *
568  * @param ltc_state state of the ltc state machine
569  * @param pBusIDptr bus ID, main or backup (deprecated)
570  * @param pAdcModeptr LTC ADCmeasurement mode (fast, normal or filtered)
571  * @param pAdcMeasChptr number of channels measured for GPIOS (one at a time for multiplexers or all five GPIOs)
572  *
573  * @return retVal current state request, taken from LTC_STATE_REQUEST_e
574  *
575  */
577  LTC_STATE_s *ltc_state,
578  uint8_t *pBusIDptr,
579  LTC_ADCMODE_e *pAdcModeptr,
580  LTC_ADCMEAS_CHAN_e *pAdcMeasChptr) {
581  LTC_REQUEST_s retval = {.request = LTC_STATE_NO_REQUEST, .string = 0x0u};
582 
584  retval.request = ltc_state->statereq.request;
585  retval.string = ltc_state->statereq.string;
586  ltc_state->requestedString = ltc_state->statereq.string;
587  *pAdcModeptr = ltc_state->adcModereq;
588  *pAdcMeasChptr = ltc_state->adcMeasChreq;
590  ltc_state->statereq.string = 0x0u;
592 
593  return (retval);
594 }
595 
597  LTC_RETURN_TYPE_e retVal = LTC_ERROR;
598 
600  retVal = LTC_CheckStateRequest(ltc_state, statereq);
601 
602  if ((retVal == LTC_OK) || (retVal == LTC_BUSY_OK) || (retVal == LTC_OK_FROM_ERROR)) {
603  ltc_state->statereq.request = statereq.request;
604  ltc_state->statereq.string = statereq.string;
605  }
607 
608  return (retVal);
609 }
610 
611 void LTC_Trigger(LTC_STATE_s *ltc_state) {
612  STD_RETURN_TYPE_e retVal = STD_OK;
613  LTC_REQUEST_s statereq = {.request = LTC_STATE_NO_REQUEST, .string = 0x0u};
614  uint8_t tmpbusID = 0;
617  STD_RETURN_TYPE_e continueFunction = STD_OK;
618 
619  FAS_ASSERT(ltc_state != NULL_PTR);
620 
621  /* Check re-entrance of function */
622  if (LTC_CheckReEntrance(ltc_state) > 0u) {
623  continueFunction = STD_NOT_OK;
624  }
625 
626  if (ltc_state->check_spi_flag == STD_NOT_OK) {
627  if (ltc_state->timer > 0u) {
628  if ((--ltc_state->timer) > 0u) {
629  ltc_state->triggerentry--;
630  continueFunction = STD_NOT_OK; /* handle state machine only if timer has elapsed */
631  }
632  }
633  } else {
634  if (AFE_IsTransmitOngoing(ltc_state) == true) {
635  if (ltc_state->timer > 0u) {
636  if ((--ltc_state->timer) > 0u) {
637  ltc_state->triggerentry--;
638  continueFunction = STD_NOT_OK; /* handle state machine only if timer has elapsed */
639  }
640  }
641  }
642  }
643 
644  if (continueFunction == STD_OK) {
645  switch (ltc_state->state) {
646  /****************************UNINITIALIZED***********************************/
648  /* waiting for Initialization Request */
649  statereq = LTC_TransferStateRequest(ltc_state, &tmpbusID, &tmpadcMode, &tmpadcMeasCh);
650  if (statereq.request == LTC_STATE_INIT_REQUEST) {
651  LTC_SaveLastStates(ltc_state);
652  LTC_Initialize_Database(ltc_state);
653  LTC_ResetErrorTable(ltc_state);
656  ltc_state->adcMode = tmpadcMode;
657  ltc_state->adcMeasCh = tmpadcMeasCh;
658  } else if (statereq.request == LTC_STATE_NO_REQUEST) {
659  /* no actual request pending */
660  } else {
661  ltc_state->ErrRequestCounter++; /* illegal request pending */
662  }
663  break;
664 
665  /****************************INITIALIZATION**********************************/
667 
668  LTC_SetTransferTimes(ltc_state);
669  if (ltc_state->substate == LTC_INIT_STRING) {
670  LTC_SaveLastStates(ltc_state);
671  ltc_state->spiSeqPtr = ltc_state->ltcData.pSpiInterface;
673  ltc_state->spiSeqEndPtr = ltc_state->ltcData.pSpiInterface + BS_NR_OF_STRINGS;
676  } else if (ltc_state->substate == LTC_ENTRY_INITIALIZATION) {
677  LTC_SaveLastStates(ltc_state);
678  retVal = LTC_TransmitWakeUp(ltc_state->spiSeqPtr); /* Send dummy byte to wake up the daisy chain */
680  ltc_state,
681  retVal,
689 
690  } else if (ltc_state->substate == LTC_RE_ENTRY_INITIALIZATION) {
691  LTC_SaveLastStates(ltc_state);
692  retVal =
693  LTC_TransmitWakeUp(ltc_state->spiSeqPtr); /* Send dummy byte again to wake up the daisy chain */
695  ltc_state,
696  retVal,
704 
705  } else if (ltc_state->substate == LTC_START_INIT_INITIALIZATION) {
706  LTC_SaveLastStates(ltc_state);
707  ltc_state->check_spi_flag = STD_OK;
708  AFE_SetTransmitOngoing(ltc_state);
709  retVal = LTC_Init(
710  ltc_state->spiSeqPtr,
711  ltc_state->ltcData.txBuffer,
712  ltc_state->ltcData.rxBuffer,
713  ltc_state->ltcData.frameLength); /* Initialize main LTC loop */
714  ltc_state->lastsubstate = ltc_state->substate;
717  ltc_state,
721 
722  } else if (ltc_state->substate == LTC_CHECK_INITIALIZATION) {
723  /* Read values written in config register, currently unused */
724  LTC_SaveLastStates(ltc_state);
725  AFE_SetTransmitOngoing(ltc_state);
726  retVal = LTC_RX(
727  ltc_cmdRDCFG,
728  ltc_state->spiSeqPtr,
729  ltc_state->ltcData.txBuffer,
730  ltc_state->ltcData.rxBuffer,
731  ltc_state->ltcData.frameLength); /* Read config register */
733  ltc_state,
737 
738  } else if (ltc_state->substate == LTC_EXIT_INITIALIZATION) {
739  LTC_SaveLastStates(ltc_state);
740  ++ltc_state->spiSeqPtr;
741  ++ltc_state->currentString;
742  if (ltc_state->spiSeqPtr >= ltc_state->spiSeqEndPtr) {
745  } else {
748  }
749  }
750  break;
751 
752  /****************************INITIALIZED*************************************/
754  LTC_SaveLastStates(ltc_state);
756  break;
757 
758  /****************************START MEASUREMENT*******************************/
760 
763 
764  ltc_state->spiSeqPtr = ltc_state->ltcData.pSpiInterface;
766  ltc_state->spiSeqEndPtr = ltc_state->ltcData.pSpiInterface + BS_NR_OF_STRINGS;
767  ltc_state->currentString = 0u;
768 
769  ltc_state->check_spi_flag = STD_NOT_OK;
770  retVal = LTC_StartVoltageMeasurement(ltc_state->spiSeqPtr, ltc_state->adcMode, ltc_state->adcMeasCh);
771 
773  ltc_state,
774  retVal,
782 
783  break;
784 
785  /****************************START MEASUREMENT CONTINUE*******************************/
786  /* Do not reset SPI interface pointer */
788 
791 
792  ltc_state->check_spi_flag = STD_NOT_OK;
793  retVal = LTC_StartVoltageMeasurement(ltc_state->spiSeqPtr, ltc_state->adcMode, ltc_state->adcMeasCh);
794 
796  ltc_state,
797  retVal,
805 
806  break;
807 
808  /****************************READ VOLTAGE************************************/
810 
812  ltc_state->check_spi_flag = STD_OK;
813  AFE_SetTransmitOngoing(ltc_state);
814  retVal = LTC_RX(
816  ltc_state->spiSeqPtr,
817  ltc_state->ltcData.txBuffer,
818  ltc_state->ltcData.rxBuffer,
819  ltc_state->ltcData.frameLength);
821  ltc_state,
822  retVal,
830  break;
831 
832  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_B_RDCVB_READVOLTAGE) {
833  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
836  ltc_state, ltc_state->ltcData.rxBuffer, 0u, ltc_state->currentString);
837 
838  AFE_SetTransmitOngoing(ltc_state);
839  retVal = LTC_RX(
841  ltc_state->spiSeqPtr,
842  ltc_state->ltcData.txBuffer,
843  ltc_state->ltcData.rxBuffer,
844  ltc_state->ltcData.frameLength);
846  ltc_state,
847  retVal,
855  break;
856 
857  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_C_RDCVC_READVOLTAGE) {
858  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
861  ltc_state, ltc_state->ltcData.rxBuffer, 1u, ltc_state->currentString);
862 
863  AFE_SetTransmitOngoing(ltc_state);
864  retVal = LTC_RX(
866  ltc_state->spiSeqPtr,
867  ltc_state->ltcData.txBuffer,
868  ltc_state->ltcData.rxBuffer,
869  ltc_state->ltcData.frameLength);
871  ltc_state,
872  retVal,
880  break;
881 
882  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_D_RDCVD_READVOLTAGE) {
883  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
886  ltc_state, ltc_state->ltcData.rxBuffer, 2u, ltc_state->currentString);
887 
888  AFE_SetTransmitOngoing(ltc_state);
889  retVal = LTC_RX(
891  ltc_state->spiSeqPtr,
892  ltc_state->ltcData.txBuffer,
893  ltc_state->ltcData.rxBuffer,
894  ltc_state->ltcData.frameLength);
896  ltc_state,
897  retVal,
905  break;
906 
907  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_E_RDCVE_READVOLTAGE) {
908  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
911  ltc_state, ltc_state->ltcData.rxBuffer, 3u, ltc_state->currentString);
912 
913  AFE_SetTransmitOngoing(ltc_state);
914  retVal = LTC_RX(
916  ltc_state->spiSeqPtr,
917  ltc_state->ltcData.txBuffer,
918  ltc_state->ltcData.rxBuffer,
919  ltc_state->ltcData.frameLength);
921  ltc_state,
922  retVal,
930  break;
931 
932  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_F_RDCVF_READVOLTAGE) {
933  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
936  ltc_state, ltc_state->ltcData.rxBuffer, 4u, ltc_state->currentString);
937 
938  AFE_SetTransmitOngoing(ltc_state);
939  retVal = LTC_RX(
941  ltc_state->spiSeqPtr,
942  ltc_state->ltcData.txBuffer,
943  ltc_state->ltcData.rxBuffer,
944  ltc_state->ltcData.frameLength);
946  ltc_state,
947  retVal,
955  break;
956 
957  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_G_RDCVG_READVOLTAGE) {
958  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
961  ltc_state, ltc_state->ltcData.rxBuffer, 5u, ltc_state->currentString);
962 
963  AFE_SetTransmitOngoing(ltc_state);
964  retVal = LTC_RX(
966  ltc_state->spiSeqPtr,
967  ltc_state->ltcData.txBuffer,
968  ltc_state->ltcData.rxBuffer,
969  ltc_state->ltcData.frameLength);
971  ltc_state,
972  retVal,
980  break;
981 
982  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_H_RDCVH_READVOLTAGE) {
983  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
986  ltc_state, ltc_state->ltcData.rxBuffer, 6u, ltc_state->currentString);
987 
988  AFE_SetTransmitOngoing(ltc_state);
989  retVal = LTC_RX(
991  ltc_state->spiSeqPtr,
992  ltc_state->ltcData.txBuffer,
993  ltc_state->ltcData.rxBuffer,
994  ltc_state->ltcData.frameLength);
996  ltc_state,
997  retVal,
1005  break;
1006 
1007  } else if (ltc_state->substate == LTC_READ_VOLTAGE_REGISTER_I_RDCVI_READVOLTAGE) {
1008  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
1011  ltc_state, ltc_state->ltcData.rxBuffer, 7u, ltc_state->currentString);
1012 
1013  AFE_SetTransmitOngoing(ltc_state);
1014  retVal = LTC_RX(
1016  ltc_state->spiSeqPtr,
1017  ltc_state->ltcData.txBuffer,
1018  ltc_state->ltcData.rxBuffer,
1019  ltc_state->ltcData.frameLength);
1021  ltc_state,
1022  retVal,
1030  break;
1031 
1032  } else if (ltc_state->substate == LTC_EXIT_READVOLTAGE) {
1033  retVal = LTC_RX_PECCheck(ltc_state, ltc_state->ltcData.rxBuffer, ltc_state->currentString);
1036  ltc_state, ltc_state->ltcData.rxBuffer, 8u, ltc_state->currentString);
1037 
1038  /* Switch to different state if read voltage state is reused
1039  * e.g. open-wire check... */
1040  if (ltc_state->reusageMeasurementMode == LTC_NOT_REUSED) {
1041  LTC_SaveVoltages(ltc_state, ltc_state->currentString);
1042 
1043  ++ltc_state->spiSeqPtr;
1044  ++ltc_state->currentString;
1045  if (ltc_state->spiSeqPtr >= ltc_state->spiSeqEndPtr) {
1046  if (LTC_IsFirstMeasurementCycleFinished(ltc_state) == false) {
1048  }
1049  statereq = LTC_TransferStateRequest(ltc_state, &tmpbusID, &tmpadcMode, &tmpadcMeasCh);
1050  if (statereq.request == LTC_STATE_OPENWIRE_CHECK_REQUEST) {
1051  if (statereq.string < BS_NR_OF_STRINGS) {
1052  ltc_state->spiSeqPtr = ltc_state->ltcData.pSpiInterface + statereq.string;
1053  ltc_state->requestedString = statereq.string;
1054  /* This is necessary because the state machine will go through read voltage measurement registers */
1055  ltc_state->currentString = statereq.string;
1058  ltc_state,
1062  }
1063  } else {
1066  ltc_state->check_spi_flag = STD_NOT_OK;
1067  }
1068  } else {
1071  ltc_state->check_spi_flag = STD_NOT_OK;
1072  }
1073  } else if (ltc_state->reusageMeasurementMode == LTC_REUSE_READVOLT_FOR_ADOW_PUP) {
1075  ltc_state,
1079  } else if (ltc_state->reusageMeasurementMode == LTC_REUSE_READVOLT_FOR_ADOW_PDOWN) {
1081  ltc_state,
1085  }
1086  }
1087  break;
1088 
1089  /**************************OPEN-WIRE CHECK*******************************/
1092  /* Run ADOW command with PUP = 1 */
1093  ltc_state->adcMode = LTC_OW_MEASUREMENT_MODE;
1094  ltc_state->check_spi_flag = STD_NOT_OK;
1095 
1096  retVal = LTC_StartOpenWireMeasurement(ltc_state->spiSeqPtr, ltc_state->adcMode, 1);
1097  if (retVal == STD_OK) {
1099 
1101  ltc_state,
1105 
1106  ltc_state->resendCommandCounter--;
1107 
1108  /* Check how many retries are left */
1109  if (ltc_state->resendCommandCounter == 0) {
1110  /* Switch to read voltage state to read cell voltages */
1111 
1113  ltc_state,
1117 
1118  /* Reuse read voltage register */
1120  }
1121  } else {
1125  }
1126  } else if (ltc_state->substate == LTC_READ_VOLTAGES_PULLUP_OPENWIRE_CHECK) {
1127  /* Previous state: Read voltage -> information stored in voltage buffer */
1129 
1130  /* Copy data from voltage struct into open-wire struct */
1131  for (uint16_t i = 0u; i < BS_NR_OF_BAT_CELLS; i++) {
1132  ltc_state->ltcData.openWireDetection->openWirePup[ltc_state->requestedString][i] =
1133  ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][i];
1134  }
1135 
1136  /* Set number of ADOW retries - send ADOW command with pull-down two times */
1139  ltc_state,
1143 
1144  } else if (ltc_state->substate == LTC_REQUEST_PULLDOWN_CURRENT_OPENWIRE_CHECK) {
1145  /* Run ADOW command with PUP = 0 */
1146  ltc_state->adcMode = LTC_OW_MEASUREMENT_MODE;
1147  ltc_state->check_spi_flag = STD_NOT_OK;
1148 
1149  retVal = LTC_StartOpenWireMeasurement(ltc_state->spiSeqPtr, ltc_state->adcMode, 0);
1150  if (retVal == STD_OK) {
1152 
1154  ltc_state,
1158 
1159  ltc_state->resendCommandCounter--;
1160 
1161  /* Check how many retries are left */
1162  if (ltc_state->resendCommandCounter == 0) {
1163  /* Switch to read voltage state to read cell voltages */
1164 
1166  ltc_state,
1170 
1171  /* Reuse read voltage register */
1173  }
1174  } else {
1178  }
1179  } else if (ltc_state->substate == LTC_READ_VOLTAGES_PULLDOWN_OPENWIRE_CHECK) {
1180  /* Previous state: Read voltage -> information stored in voltage buffer */
1182 
1183  /* Copy data from voltage struct into open-wire struct */
1184  for (uint16_t i = 0u; i < BS_NR_OF_BAT_CELLS; i++) {
1185  ltc_state->ltcData.openWireDetection->openWirePdown[ltc_state->requestedString][i] =
1186  ltc_state->ltcData.cellVoltage->cellVoltage_mV[ltc_state->requestedString][i];
1187  }
1188 
1191 
1192  } else if (ltc_state->substate == LTC_PERFORM_OPENWIRE_CHECK) {
1193  /* Perform actual open-wire check */
1194 
1195  /* Take difference between pull-up and pull-down measurement */
1196  for (uint16_t i = 1u; i < BS_NR_OF_BAT_CELLS; i++) {
1197  ltc_state->ltcData.openWireDetection->openWireDelta[ltc_state->requestedString][i] = (int32_t)(
1198  ltc_state->ltcData.openWireDetection->openWirePup[ltc_state->requestedString][i] -
1199  ltc_state->ltcData.openWireDetection->openWirePdown[ltc_state->requestedString][i]);
1200  }
1201 
1202  /* PDOWN or PUP positive or negative full scale value: C(N) or C(N-1) open*/
1203  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
1204  /* PUP */
1205  for (uint8_t p = 0u; p < BS_NR_OF_CELLS_PER_MODULE; p++) {
1206  if ((ltc_state->ltcData.openWireDetection
1207  ->openWirePup[ltc_state->requestedString][p + (m * BS_NR_OF_CELLS_PER_MODULE)] ==
1209  (ltc_state->ltcData.openWireDetection
1210  ->openWirePup[ltc_state->requestedString][p + (m * BS_NR_OF_CELLS_PER_MODULE)] ==
1212  ltc_state->ltcData.openWire
1213  ->openwire[ltc_state->requestedString][p + (m * (BS_NR_OF_CELLS_PER_MODULE))] = 1;
1214  ltc_state->ltcData.openWire->openwire[ltc_state->requestedString]
1215  [(p + 1u) + (m * (BS_NR_OF_CELLS_PER_MODULE))] = 1;
1216  }
1217  if ((ltc_state->ltcData.openWireDetection
1218  ->openWirePdown[ltc_state->requestedString][p + (m * BS_NR_OF_CELLS_PER_MODULE)] ==
1220  (ltc_state->ltcData.openWireDetection
1221  ->openWirePdown[ltc_state->requestedString][p + (m * BS_NR_OF_CELLS_PER_MODULE)] ==
1223  ltc_state->ltcData.openWire
1224  ->openwire[ltc_state->requestedString][p + (m * (BS_NR_OF_CELLS_PER_MODULE))] = 1;
1225  ltc_state->ltcData.openWire->openwire[ltc_state->requestedString]
1226  [(p + 1u) + (m * (BS_NR_OF_CELLS_PER_MODULE))] = 1;
1227  }
1228  }
1229  }
1230 
1231  /* data sheet page 28: "for all values of n from 1 to 36: If CELL Delta(n+1) < -200mV then C(n) is open" */
1232  for (uint8_t m = 0u; m < BS_NR_OF_MODULES; m++) {
1233  /* ltc_state->ltcData.openWireDelta parsed from 1 to (BS_NR_OF_CELLS_PER_MODULE-1) */
1234  for (uint8_t c = 1u; c < BS_NR_OF_CELLS_PER_MODULE; c++) {
1235  /* If delta cell(n+1) < -200mV: open-wire at C(n) */
1236  if (ltc_state->ltcData.openWireDetection
1237  ->openWireDelta[ltc_state->requestedString][c + (m * BS_NR_OF_CELLS_PER_MODULE)] <
1239  ltc_state->ltcData.openWire
1240  ->openwire[ltc_state->requestedString][c + (m * BS_NR_OF_CELLS_PER_MODULE)] = 1;
1241  }
1242  }
1243  }
1244 
1245  ltc_state->ltcData.openWire->nrOpenWires[ltc_state->requestedString] = 0;
1246  for (uint16_t c = 0u; c < (BS_NR_OF_MODULES * (BS_NR_OF_CELLS_PER_MODULE + 1)); c++) {
1247  if (ltc_state->ltcData.openWire->openwire[ltc_state->requestedString][c] == 1) {
1248  ltc_state->ltcData.openWire->nrOpenWires[ltc_state->requestedString]++;
1249  }
1250  }
1251 
1252  /* Write database entry */
1253  DATA_WRITE_DATA(ltc_state->ltcData.openWire);
1254  /* Start new measurement cycle */
1256  }
1257  break;
1258 
1259  /****************************DEFAULT**************************/
1260  default:
1261  /* invalid state */
1263  break;
1264  }
1265 
1266  ltc_state->triggerentry--; /* reentrance counter */
1267  } /* continueFunction */
1268 }
1269 
1270 /**
1271  * @brief saves the voltage values read from the LTC daisy-chain.
1272  *
1273  * After a voltage measurement was initiated to measure the voltages of the cells,
1274  * the result is read via SPI from the daisy-chain.
1275  * There are 6 register to read _(A,B,C,D,E,F,G,H,I) to get all cell voltages.
1276  * Only one register can be read at a time.
1277  * This function is called to store the result from the transmission in a buffer.
1278  *
1279  * @param ltc_state state of the ltc state machine
1280  * @param pRxBuff receive buffer
1281  * @param registerSet voltage register that was read (voltage register A,B,C,D,E,F,G,H or I)
1282  * @param stringNumber string addressed
1283  *
1284  */
1286  LTC_STATE_s *ltc_state,
1287  uint16_t *pRxBuff,
1288  uint8_t registerSet,
1289  uint8_t stringNumber) {
1290  uint16_t cellOffset = 0;
1291  uint16_t val_ui = 0;
1292  int16_t voltage = 0;
1293  uint64_t bitmask = 0;
1294  uint16_t buffer_LSB = 0;
1295  uint16_t buffer_MSB = 0;
1296 
1297  cellOffset = registerSet * 4u;
1298 
1299  /* Calculate bitmask for valid flags */
1300  bitmask |= 0x0Full << cellOffset; /* 0x0F: four voltages in each register */
1301 
1302  /* reinitialize index counter at begin of cycle */
1303  if (cellOffset == 0u) {
1304  (ltc_state->ltcData.usedCellIndex[stringNumber]) = 0u;
1305  }
1306 
1307  /* Retrieve data without command and CRC*/
1308  for (uint8_t m = 0u; m < LTC_N_LTC; m++) {
1309  uint8_t incrementations = 0u;
1310 
1311  /* parse all four voltages (4 * 12bits) contained in one register */
1312  for (uint8_t c = 0u; c < 4u; c++) {
1313  switch (c) {
1314  case 0u:
1315  buffer_MSB = pRxBuff[4u + (m * 8u)];
1316  buffer_LSB = (pRxBuff[4u + 1u + (m * 8u)]) >> 4u;
1317  val_ui = (uint16_t)(buffer_LSB | (buffer_MSB << 4u));
1318  break;
1319  case 1u:
1320  buffer_MSB = pRxBuff[4u + 1u + (m * 8u)] & 0x0Fu;
1321  buffer_LSB = (pRxBuff[4u + 2u + (m * 8u)]);
1322  val_ui = (uint16_t)(buffer_LSB | (buffer_MSB << 8u));
1323  break;
1324  case 2u:
1325  buffer_MSB = pRxBuff[4u + 3u + (m * 8u)];
1326  buffer_LSB = (pRxBuff[4u + 4u + (m * 8u)]) >> 4u;
1327  val_ui = (uint16_t)(buffer_LSB | (buffer_MSB << 4u));
1328  break;
1329  case 3u:
1330  buffer_MSB = pRxBuff[4u + 4u + (m * 8u)] & 0x0Fu;
1331  buffer_LSB = (pRxBuff[4u + 5u + (m * 8u)]);
1332  val_ui = (uint16_t)(buffer_LSB | (buffer_MSB << 8u));
1333  break;
1334  default:
1335  break;
1336  }
1337 
1338  /* Check signed bit if measured value is negative or not */
1339  if ((val_ui & (1u << (12u - 1u))) == 0u) {
1340  voltage = (int16_t)(((val_ui & 0x7FFu)) * LTC_FUEL_CELL_LSB_RESOLUTION_mV); /* Unit mV */
1341  } else {
1342  voltage = (int16_t)(((((~val_ui) + 1) & 0x7FF)) * (-LTC_FUEL_CELL_LSB_RESOLUTION_mV)); /* Unit mV */
1343  }
1344 
1345  if (ltc_state->ltcData.errorTable->PEC_valid[stringNumber][m] == true) {
1346  ltc_state->ltcData.cellVoltage->cellVoltage_mV[stringNumber]
1347  [(ltc_state->ltcData.usedCellIndex[stringNumber]) +
1348  (m * BS_NR_OF_CELLS_PER_MODULE)] = voltage;
1349  bitmask = ~bitmask; /* negate bitmask to only validate flags of this voltage register */
1350  ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][(m / LTC_NUMBER_OF_LTC_PER_MODULE)] &=
1351  bitmask;
1352  } else {
1353  /* PEC_valid == false: Invalidate only flags of this voltage register */
1354  ltc_state->ltcData.cellVoltage->invalidCellVoltage[stringNumber][(m / LTC_NUMBER_OF_LTC_PER_MODULE)] |=
1355  bitmask;
1356  }
1357 
1358  (ltc_state->ltcData.usedCellIndex[stringNumber])++;
1359  incrementations++;
1360 
1361  if ((ltc_state->ltcData.usedCellIndex[stringNumber]) > BS_NR_OF_CELLS_PER_MODULE) {
1362  break;
1363  }
1364  }
1365 
1366  /* Restore start value for next module in the daisy-chain. Only
1367  * decrement used cell index if current module is not the last
1368  * module in the daisy-chain. */
1369  if ((m + 1u) < LTC_N_LTC) {
1370  (ltc_state->ltcData.usedCellIndex[stringNumber]) -= incrementations;
1371  }
1372  }
1373 }
1374 
1375 /**
1376  * @brief initialize the daisy-chain.
1377  *
1378  * To initialize the LTC6804 daisy-chain, a dummy byte (0x00) is sent.
1379  *
1380  * @param pSpiInterface pointer to SPI configuration
1381  * @param pTxBuff transmit buffer
1382  * @param pRxBuff receive buffer
1383  * @param frameLength number of words to transmit
1384  *
1385  * @return retVal #STD_OK if dummy byte was sent correctly by SPI, #STD_NOT_OK otherwise
1386  *
1387  */
1389  SPI_INTERFACE_CONFIG_s *pSpiInterface,
1390  uint16_t *pTxBuff,
1391  uint16_t *pRxBuff,
1392  uint32_t frameLength) {
1393  STD_RETURN_TYPE_e retVal = STD_NOT_OK;
1394 
1395  uint8_t PEC_Check[6];
1396  uint16_t PEC_result = 0;
1397 
1398  /* now construct the message to be sent: it contains the wanted data, PLUS the needed PECs */
1399  pTxBuff[0] = ltc_cmdWRCFG[0];
1400  pTxBuff[1] = ltc_cmdWRCFG[1];
1401  pTxBuff[2] = ltc_cmdWRCFG[2];
1402  pTxBuff[3] = ltc_cmdWRCFG[3];
1403 
1404  /* set REFON bit to 1 */
1405  /* data for the configuration */
1406  for (uint16_t i = 0u; i < LTC_N_LTC; i++) {
1407  /* 3F = disable all pull-downs, 40: REFON = 1 */
1408  pTxBuff[4u + (i * 8u)] = 0x3F;
1409  pTxBuff[5u + (i * 8u)] = (LTC_HIRNG << 7u) | 0x40u;
1410  pTxBuff[6u + (i * 8u)] = 0x00;
1411  pTxBuff[7u + (i * 8u)] = 0x00;
1412  pTxBuff[8u + (i * 8u)] = 0x00;
1413  pTxBuff[9u + (i * 8u)] = 0x00;
1414 
1415  PEC_Check[0] = pTxBuff[4u + (i * 8u)];
1416  PEC_Check[1] = pTxBuff[5u + (i * 8u)];
1417  PEC_Check[2] = pTxBuff[6u + (i * 8u)];
1418  PEC_Check[3] = pTxBuff[7u + (i * 8u)];
1419  PEC_Check[4] = pTxBuff[8u + (i * 8u)];
1420  PEC_Check[5] = pTxBuff[9u + (i * 8u)];
1421 
1422  PEC_result = LTC_pec15_calc(6, PEC_Check);
1423  pTxBuff[10u + (i * 8u)] = (PEC_result >> 8u) & 0xFFu;
1424  pTxBuff[11u + (i * 8u)] = PEC_result & 0xFFu;
1425  } /* end for */
1426 
1427  retVal = LTC_TransmitReceiveData(pSpiInterface, pTxBuff, pRxBuff, frameLength);
1428 
1429  return retVal;
1430 }
1431 
1432 /**
1433  * @brief resets the error table.
1434  *
1435  * This function should be called during initialization or before starting a new measurement cycle
1436  *
1437  * @param ltc_state: state of the ltc state machine
1438  *
1439  */
1440 static void LTC_ResetErrorTable(LTC_STATE_s *ltc_state) {
1441  uint16_t i = 0;
1442 
1443  for (uint8_t stringNumber = 0u; stringNumber < BS_NR_OF_STRINGS; stringNumber++) {
1444  for (i = 0; i < LTC_N_LTC; i++) {
1445  ltc_state->ltcData.errorTable->PEC_valid[stringNumber][i] = false;
1446  ltc_state->ltcData.errorTable->mux0[stringNumber][i] = 0;
1447  ltc_state->ltcData.errorTable->mux1[stringNumber][i] = 0;
1448  ltc_state->ltcData.errorTable->mux2[stringNumber][i] = 0;
1449  ltc_state->ltcData.errorTable->mux3[stringNumber][i] = 0;
1450  }
1451  }
1452 }
1453 
1454 /**
1455  * @brief tells the LTC daisy-chain to start measuring the voltage on all cells.
1456  *
1457  * This function sends an instruction to the daisy-chain via SPI, in order to start voltage measurement for all cells.
1458  *
1459  * @param pSpiInterface pointer to SPI configuration
1460  * @param adcMode LTC ADCmeasurement mode (fast, normal or filtered)
1461  * @param adcMeasCh number of cell voltage measured (2 cells or all cells)
1462  *
1463  * @return retVal #STD_OK if dummy byte was sent correctly by SPI, #STD_NOT_OK otherwise
1464  *
1465  */
1467  SPI_INTERFACE_CONFIG_s *pSpiInterface,
1468  LTC_ADCMODE_e adcMode,
1469  LTC_ADCMEAS_CHAN_e adcMeasCh) {
1470  STD_RETURN_TYPE_e retVal = STD_OK;
1471 
1472  retVal = LTC_TransmitCommand(pSpiInterface, ltc_cmdADCV_normal_Fuelcell);
1473 
1474  return retVal;
1475 }
1476 
1477 /**
1478  * @brief tells LTC daisy-chain to start measuring the voltage on GPIOS.
1479  *
1480  * This function sends an instruction to the daisy-chain via SPI to start the measurement.
1481  *
1482  * @param pSpiInterface pointer to SPI configuration
1483  * @param adcMode LTC ADCmeasurement mode (fast, normal or filtered)
1484  * @param PUP pull-up bit for pull-up or pull-down current (0: pull-down, 1: pull-up)
1485  *
1486  * @return retVal #STD_OK if command was sent correctly by SPI, #STD_NOT_OK otherwise
1487  *
1488  */
1490  SPI_INTERFACE_CONFIG_s *pSpiInterface,
1491  LTC_ADCMODE_e adcMode,
1492  uint8_t PUP) {
1493  STD_RETURN_TYPE_e retval = STD_NOT_OK;
1494 
1495  if (PUP == 0u) {
1496  /* pull-down current */
1498  } else if (PUP == 1u) {
1499  /* pull-up current */
1500  retval = LTC_TransmitCommand(pSpiInterface, ltc_BC_cmdADOW_PUP_100ms_fuelcell);
1501  }
1502 
1503  return retval;
1504 }
1505 
1506 /**
1507  * @brief checks if the data received from the daisy-chain is not corrupt.
1508  *
1509  * This function computes the PEC (CRC) from the data received by the daisy-chain.
1510  * It compares it with the PEC sent by the LTCs.
1511  * If there are errors, the array the error table is updated to locate the LTCs in daisy-chain
1512  * that transmitted corrupt data.
1513  *
1514  * @param ltc_state state of the ltc state machine
1515  * @param DataBufferSPI_RX_with_PEC data obtained from the SPI transmission
1516  * @param stringNumber string addressed
1517  *
1518  * @return retVal STD_OK if PEC check is OK, STD_NOT_OK otherwise
1519  *
1520  */
1522  LTC_STATE_s *ltc_state,
1523  uint16_t *DataBufferSPI_RX_with_PEC,
1524  uint8_t stringNumber) {
1525  uint16_t i = 0;
1526  STD_RETURN_TYPE_e retVal = STD_OK;
1527  uint8_t PEC_TX[2];
1528  uint16_t PEC_result = 0;
1529  uint8_t PEC_Check[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1530 
1531  /* check all PECs and put data without command and PEC in DataBufferSPI_RX (easier to use) */
1532  for (i = 0; i < LTC_N_LTC; i++) {
1533  PEC_Check[0] = DataBufferSPI_RX_with_PEC[4u + (i * 8u)];
1534  PEC_Check[1] = DataBufferSPI_RX_with_PEC[5u + (i * 8u)];
1535  PEC_Check[2] = DataBufferSPI_RX_with_PEC[6u + (i * 8u)];
1536  PEC_Check[3] = DataBufferSPI_RX_with_PEC[7u + (i * 8u)];
1537  PEC_Check[4] = DataBufferSPI_RX_with_PEC[8u + (i * 8u)];
1538  PEC_Check[5] = DataBufferSPI_RX_with_PEC[9u + (i * 8u)];
1539 
1540  PEC_result = LTC_pec15_calc(6, PEC_Check);
1541  PEC_TX[0] = (uint8_t)((PEC_result >> 8u) & 0xFFu);
1542  PEC_TX[1] = (uint8_t)(PEC_result & 0xFFu);
1543 
1544  /* if calculated PEC not equal to received PEC */
1545  if ((PEC_TX[0] != DataBufferSPI_RX_with_PEC[10u + (i * 8u)]) ||
1546  (PEC_TX[1] != DataBufferSPI_RX_with_PEC[11u + (i * 8u)])) {
1547  /* update error table of the corresponding LTC only if PEC check is activated */
1548  if (LTC_DISCARD_PEC == false) {
1549  ltc_state->ltcData.errorTable->PEC_valid[stringNumber][i] = false;
1550  retVal = STD_NOT_OK;
1551  } else {
1552  ltc_state->ltcData.errorTable->PEC_valid[stringNumber][i] = true;
1553  }
1554  } else {
1555  /* update error table of the corresponding LTC */
1556  ltc_state->ltcData.errorTable->PEC_valid[stringNumber][i] = true;
1557  }
1558  }
1559  return retVal;
1560 }
1561 
1562 /**
1563  * @brief send command to the LTC daisy-chain and receives data from the LTC daisy-chain.
1564  *
1565  * This is the core function to receive data from the LTC6804 daisy-chain.
1566  * A 2 byte command is sent with the corresponding PEC. Example: read configuration register (RDCFG).
1567  * Only command has to be set, the function calculates the PEC automatically.
1568  * The data send is:
1569  * 2 bytes (COMMAND) 2 bytes (PEC)
1570  * The data received is:
1571  * 6 bytes (LTC1) 2 bytes (PEC) + 6 bytes (LTC2) 2 bytes (PEC) + 6 bytes (LTC3) 2 bytes (PEC) + ... + 6 bytes (LTC{LTC_N_LTC}) 2 bytes (PEC)
1572  *
1573  * The function does not check the PECs. This has to be done elsewhere.
1574  *
1575  * @param Command command sent to the daisy-chain
1576  * @param pSpiInterface pointer to SPI configuration
1577  * @param pTxBuff transmit buffer
1578  * @param pRxBuff receive buffer
1579  * @param frameLength number of words to transmit
1580  *
1581  * @return statusSPI #STD_OK if SPI transmission is OK, #STD_NOT_OK otherwise
1582  *
1583  */
1585  uint16_t *Command,
1586  SPI_INTERFACE_CONFIG_s *pSpiInterface,
1587  uint16_t *pTxBuff,
1588  uint16_t *pRxBuff,
1589  uint32_t frameLength) {
1590  STD_RETURN_TYPE_e statusSPI = STD_OK;
1591  uint16_t i = 0;
1592 
1593  /* DataBufferSPI_RX_with_PEC contains the data to receive.
1594  The transmission function checks the PECs.
1595  It constructs DataBufferSPI_RX, which contains the received data without PEC (easier to use). */
1596 
1597  for (i = 0; i < LTC_N_BYTES_FOR_DATA_TRANSMISSION; i++) {
1598  pTxBuff[i] = 0x00;
1599  }
1600 
1601  pTxBuff[0] = Command[0];
1602  pTxBuff[1] = Command[1];
1603  pTxBuff[2] = Command[2];
1604  pTxBuff[3] = Command[3];
1605 
1606  statusSPI = LTC_TransmitReceiveData(pSpiInterface, pTxBuff, pRxBuff, frameLength);
1607 
1608  return statusSPI;
1609 }
1610 
1611 /**
1612  * @brief gets the frequency of the SPI clock.
1613  *
1614  * This function reads the configuration from the SPI handle directly.
1615  *
1616  * @param pSpiInterface pointer to SPI configuration
1617  *
1618  * @return frequency of the SPI clock
1619  */
1620 static uint32_t LTC_GetSPIClock(SPI_INTERFACE_CONFIG_s *pSpiInterface) {
1621  uint32_t SPI_Clock = 0;
1622  uint32_t prescaler = 0;
1623 
1624  /* if (LTC_SPI_INSTANCE == SPI2 || LTC_SPI_INSTANCE == SPI3) { */
1625  /* SPI2 and SPI3 are connected to APB1 (PCLK1) */
1626  /* The prescaler setup bits LTC_SPI_PRESCALER corresponds to the bits 5:3 in the SPI_CR1 register */
1627  /* Reference manual p.909 */
1628  /* The shift by 3 puts the bits 5:3 to the first position */
1629  /* Division are made by powers of 2 which corresponds to shifting to the right */
1630  /* Then 0 corresponds to divide by 2, 1 corresponds to divide by 4... so 1 has to be added to the value of the configuration bits */
1631 
1632  /* SPI_Clock = HAL_RCC_GetPCLK1Freq()>>((LTC_SPI_PRESCALER>>3)+1);
1633  } */
1634 
1635  /* if (LTC_SPI_INSTANCE == SPI1 || LTC_SPI_INSTANCE == SPI4 || LTC_SPI_INSTANCE == SPI5 || LTC_SPI_INSTANCE == SPI6) { */
1636  /* SPI1, SPI4, SPI5 and SPI6 are connected to APB2 (PCLK2) */
1637  /* The prescaler setup bits LTC_SPI_PRESCALER corresponds to the bits 5:3 in the SPI_CR1 register */
1638  /* Reference manual p.909 */
1639  /* The shift by 3 puts the bits 5:3 to the first position */
1640  /* Division are made by powers of 2 which corresponds to shifting to the right */
1641  /* Then 0 corresponds to divide by 2, 1 corresponds to divide by 4... so 1 has to be added to the value of the configuration bits */
1642 
1643  /* SPI_Clock = HAL_RCC_GetPCLK2Freq()>>((LTC_SPI_PRESCALER>>3)+1);
1644  } */
1645 
1646  /* Get SPI prescaler */
1647  prescaler = ((pSpiInterface->pNode->FMT0) >> 8u) & 0xFFu;
1648  SPI_Clock = (uint32_t)(AVCLK1_FREQ * 1000000u) / (prescaler + 1u);
1649 
1650  return SPI_Clock;
1651 }
1652 
1653 /**
1654  * @brief sets the transfer time needed to receive/send data with the LTC daisy-chain.
1655  *
1656  * This function gets the clock frequency and uses the number of LTCs in the daisy-chain.
1657  *
1658  * @param ltc_state: state of the ltc state machine
1659  *
1660  */
1661 static void LTC_SetTransferTimes(LTC_STATE_s *ltc_state) {
1662  uint32_t transferTime_us = 0;
1663  uint32_t SPI_Clock = 0;
1664 
1665  SPI_Clock = LTC_GetSPIClock(ltc_state->ltcData.pSpiInterface);
1666 
1667  /* Transmission of a command and data */
1668  /* Multiplication by 1000*1000 to get us */
1669  transferTime_us = (8u * 1000u * 1000u) / (SPI_Clock);
1670  transferTime_us *= LTC_N_BYTES_FOR_DATA_TRANSMISSION;
1671  transferTime_us = transferTime_us + LTC_SPI_WAKEUP_WAIT_TIME_US;
1672  ltc_state->commandDataTransferTime = (transferTime_us / 1000u) + 1u;
1673 
1674  /* Transmission of a command */
1675  /* Multiplication by 1000*1000 to get us */
1676  transferTime_us = ((4u) * 8u * 1000u * 1000u) / (SPI_Clock);
1677  transferTime_us = transferTime_us + LTC_SPI_WAKEUP_WAIT_TIME_US;
1678  ltc_state->commandTransferTime = (transferTime_us / 1000u) + 1u;
1679 
1680  /* Transmission of a command + 9 clocks */
1681  /* Multiplication by 1000*1000 to get us */
1682  transferTime_us = ((4u + 9u) * 8u * 1000u * 1000u) / (SPI_Clock);
1683  transferTime_us = transferTime_us + LTC_SPI_WAKEUP_WAIT_TIME_US;
1684  ltc_state->gpioClocksTransferTime = (transferTime_us / 1000u) + 1u;
1685 }
1686 
1687 /**
1688  * @brief checks the state requests that are made.
1689  *
1690  * This function checks the validity of the state requests.
1691  * The results of the checked is returned immediately.
1692  *
1693  * @param ltc_state: state of the ltc state machine
1694  * @param statereq state request to be checked
1695  *
1696  * @return result of the state request that was made, taken from #LTC_RETURN_TYPE_e
1697  */
1699  LTC_RETURN_TYPE_e retVal = LTC_OK;
1700  if (statereq.string >= BS_NR_OF_STRINGS) {
1701  retVal = LTC_ILLEGAL_REQUEST;
1702  } else if (ltc_state->statereq.request == LTC_STATE_NO_REQUEST) {
1703  /* init only allowed from the uninitialized state */
1704  if (statereq.request == LTC_STATE_INIT_REQUEST) {
1705  if (ltc_state->state == LTC_STATEMACH_UNINITIALIZED) {
1706  retVal = LTC_OK;
1707  } else {
1708  retVal = LTC_ALREADY_INITIALIZED;
1709  }
1710  } else {
1711  retVal = LTC_OK;
1712  }
1713  } else {
1714  retVal = LTC_REQUEST_PENDING;
1715  }
1716  return retVal;
1717 }
1718 
1720  bool retval = false;
1721 
1723  retval = ltc_state->first_measurement_made;
1725 
1726  return retval;
1727 }
1728 
1729 /**
1730  * @brief sets the measurement initialization status.
1731  */
1734  ltc_state->first_measurement_made = true;
1736 }
1737 
1738 extern void LTC_monitoringPinInit(void) {
1739  /* Set 3rd PE pins to enable daisy chains */
1756 }
1757 
1758 /*========== Externalized Static Function Implementations (Unit Test) =======*/
1759 #ifdef UNITY_UNIT_TEST
1760 uint8_t TEST_LTC_CheckReEntrance(LTC_STATE_s *ltc_state) {
1761  return LTC_CheckReEntrance(ltc_state);
1762 }
1763 
1764 extern void TEST_LTC_SetFirstMeasurementCycleFinished(LTC_STATE_s *ltc_state) {
1766 }
1767 
1768 /** this define is used for creating the declaration of a function for variable extraction */
1769 #define TEST_LTC_DEFINE_GET(VARIABLE) \
1770  extern void TEST_LTC_Get_##VARIABLE(uint8_t data[4]) { \
1771  for (uint8_t i = 0u; i < 4u; i++) { \
1772  data[i] = (uint8_t)(VARIABLE)[i]; \
1773  } \
1774  }
1775 
1776 TEST_LTC_DEFINE_GET(ltc_cmdWRCFG);
1777 TEST_LTC_DEFINE_GET(ltc_cmdRDCFG);
1778 TEST_LTC_DEFINE_GET(ltc_cmdRDCVA_Fuelcell);
1779 TEST_LTC_DEFINE_GET(ltc_cmdRDCVB_Fuelcell);
1780 TEST_LTC_DEFINE_GET(ltc_cmdRDCVC_Fuelcell);
1781 TEST_LTC_DEFINE_GET(ltc_cmdRDCVD_Fuelcell);
1782 TEST_LTC_DEFINE_GET(ltc_cmdRDCVE_Fuelcell);
1783 TEST_LTC_DEFINE_GET(ltc_cmdRDCVF_Fuelcell);
1784 TEST_LTC_DEFINE_GET(ltc_cmdRDCVG_Fuelcell);
1785 TEST_LTC_DEFINE_GET(ltc_cmdRDCVH_Fuelcell);
1786 TEST_LTC_DEFINE_GET(ltc_cmdRDCVI_Fuelcell);
1787 TEST_LTC_DEFINE_GET(ltc_cmdADCV_normal_Fuelcell);
1788 TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PUP_100ms_fuelcell);
1789 TEST_LTC_DEFINE_GET(ltc_BC_cmdADOW_PDOWN_100ms_fuelcell);
1790 #endif
STD_RETURN_TYPE_e AFE_PlausibilityCheckTempMinMax(const int16_t celltemperature_ddegC)
Cell temperature plausibility check.
STD_RETURN_TYPE_e AFE_PlausibilityCheckVoltageMeasurementRange(const int16_t cellvoltage_mV, const AFE_PLAUSIBILITY_VALUES_s plausibleValues)
Cell voltage measurement range plausibility check.
plausibility checks for cell voltage and cell temperatures
#define BS_NR_OF_STRINGS
#define BS_NR_OF_CELLS_PER_MODULE
number of battery cells per battery module (parallel cells are counted as one)
#define BS_NR_OF_MODULES
number of modules in battery pack
#define BS_NR_OF_TEMP_SENSORS_PER_MODULE
number of temperature sensors per battery module
#define BS_NR_OF_GPIOS_PER_MODULE
Number of GPIOs on the LTC IC.
#define BS_NR_OF_TEMP_SENSORS_PER_STRING
#define BS_NR_OF_BAT_CELLS
Database module header.
#define DATA_WRITE_DATA(...)
Definition: database.h:86
@ DATA_BLOCK_ID_CELL_TEMPERATURE_BASE
Definition: database_cfg.h:95
@ DATA_BLOCK_ID_OPEN_WIRE_BASE
Definition: database_cfg.h:81
@ DATA_BLOCK_ID_CELL_VOLTAGE_BASE
Definition: database_cfg.h:94
@ DATA_BLOCK_ID_ALL_GPIO_VOLTAGES_BASE
Definition: database_cfg.h:82
DIAG_RETURNTYPE_e DIAG_Handler(DIAG_ID_e diag_id, DIAG_EVENT_e event, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_Handler provides generic error handling, based on diagnosis group.
Definition: diag.c:226
STD_RETURN_TYPE_e DIAG_CheckEvent(STD_RETURN_TYPE_e cond, DIAG_ID_e diag_id, DIAG_IMPACT_LEVEL_e impact, uint32_t data)
DIAG_CheckEvent provides a simple interface to check an event for STD_OK.
Definition: diag.c:353
Diagnosis driver header.
@ DIAG_STRING
Definition: diag_cfg.h:249
@ DIAG_EVENT_NOT_OK
Definition: diag_cfg.h:236
@ DIAG_EVENT_OK
Definition: diag_cfg.h:235
enum DIAG_ID DIAG_ID_e
@ DIAG_ID_AFE_CELL_VOLTAGE_MEAS_ERROR
Definition: diag_cfg.h:170
@ DIAG_ID_AFE_CELL_TEMPERATURE_MEAS_ERROR
Definition: diag_cfg.h:171
@ DIAG_ID_LTC_PEC
Definition: diag_cfg.h:161
@ DIAG_ID_LTC_SPI
Definition: diag_cfg.h:160
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:239
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:110
@ STD_NOT_OK
Definition: fstd_types.h:82
@ STD_OK
Definition: fstd_types.h:81
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:75
enum STD_RETURN_TYPE STD_RETURN_TYPE_e
Header for the driver for the IO module.
Headers for the driver for the LTC monitoring chip.
static uint16_t ltc_cmdRDCVI_Fuelcell[4]
Definition: ltc_6806.c:197
uint16_t ltc_TxPecBuffer[LTC_N_BYTES_FOR_DATA_TRANSMISSION]
Definition: ltc_6806.c:109
static STD_RETURN_TYPE_e LTC_StartVoltageMeasurement(SPI_INTERFACE_CONFIG_s *pSpiInterface, LTC_ADCMODE_e adcMode, LTC_ADCMEAS_CHAN_e adcMeasCh)
tells the LTC daisy-chain to start measuring the voltage on all cells.
Definition: ltc_6806.c:1466
static DATA_BLOCK_ALL_GPIO_VOLTAGES_s ltc_allgpiovoltage
Definition: ltc_6806.c:119
static uint32_t LTC_GetSPIClock(SPI_INTERFACE_CONFIG_s *pSpiInterface)
gets the frequency of the SPI clock.
Definition: ltc_6806.c:1620
static DATA_BLOCK_CELL_VOLTAGE_s ltc_cellvoltage
Definition: ltc_6806.c:117
static STD_RETURN_TYPE_e LTC_StartOpenWireMeasurement(SPI_INTERFACE_CONFIG_s *pSpiInterface, LTC_ADCMODE_e adcMode, uint8_t PUP)
tells LTC daisy-chain to start measuring the voltage on GPIOS.
Definition: ltc_6806.c:1489
static uint16_t ltc_cmdRDCVA_Fuelcell[4]
Definition: ltc_6806.c:189
LTC_STATEMACH_e LTC_GetState(LTC_STATE_s *ltc_state)
gets the current state.
Definition: ltc_6806.c:558
bool LTC_IsFirstMeasurementCycleFinished(LTC_STATE_s *ltc_state)
gets the measurement initialization status.
Definition: ltc_6806.c:1719
static const AFE_PLAUSIBILITY_VALUES_s ltc_plausibleCellVoltages6806
Definition: ltc_6806.c:127
static void LTC_StateTransition(LTC_STATE_s *ltc_state, LTC_STATEMACH_e state, uint8_t substate, uint16_t timer_ms)
function for setting LTC_Trigger state transitions
Definition: ltc_6806.c:345
void LTC_SaveAllGPIOMeasurement(LTC_STATE_s *ltc_state)
stores the measured GPIOs in the database.
Definition: ltc_6806.c:497
static void LTC_SetFirstMeasurementCycleFinished(LTC_STATE_s *ltc_state)
sets the measurement initialization status.
Definition: ltc_6806.c:1732
static LTC_RETURN_TYPE_e LTC_CheckStateRequest(LTC_STATE_s *ltc_state, LTC_REQUEST_s statereq)
checks the state requests that are made.
Definition: ltc_6806.c:1698
LTC_RETURN_TYPE_e LTC_SetStateRequest(LTC_STATE_s *ltc_state, LTC_REQUEST_s statereq)
sets the current state request of the state variable ltc_state.
Definition: ltc_6806.c:596
static uint16_t ltc_cmdRDCVD_Fuelcell[4]
Definition: ltc_6806.c:192
static void LTC_SetTransferTimes(LTC_STATE_s *ltc_state)
sets the transfer time needed to receive/send data with the LTC daisy-chain.
Definition: ltc_6806.c:1661
static uint16_t ltc_cmdRDCVG_Fuelcell[4]
Definition: ltc_6806.c:195
static uint16_t ltc_cmdRDCVH_Fuelcell[4]
Definition: ltc_6806.c:196
static uint16_t ltc_cmdRDCVE_Fuelcell[4]
Definition: ltc_6806.c:193
static uint16_t ltc_cmdRDCFG[4]
Definition: ltc_6806.c:182
static void LTC_SaveLastStates(LTC_STATE_s *ltc_state)
Saves the last state and the last substate.
Definition: ltc_6806.c:332
LTC_REQUEST_s LTC_TransferStateRequest(LTC_STATE_s *ltc_state, uint8_t *pBusIDptr, LTC_ADCMODE_e *pAdcModeptr, LTC_ADCMEAS_CHAN_e *pAdcMeasChptr)
transfers the current state request to the state machine.
Definition: ltc_6806.c:576
void LTC_SaveTemperatures(LTC_STATE_s *ltc_state, uint8_t stringNumber)
stores the measured temperatures and the measured multiplexer feedbacks in the database.
Definition: ltc_6806.c:449
static uint16_t ltc_used_cells_index[BS_NR_OF_STRINGS]
Definition: ltc_6806.c:114
#define LTC_FUEL_CELL_LSB_RESOLUTION_mV
Definition: ltc_6806.c:86
static void LTC_SaveRXtoVoltagebuffer_Fuelcell(LTC_STATE_s *ltc_state, uint16_t *pRxBuff, uint8_t registerSet, uint8_t stringNumber)
saves the voltage values read from the LTC daisy-chain.
Definition: ltc_6806.c:1285
LTC_REQUEST_s LTC_GetStateRequest(LTC_STATE_s *ltc_state)
gets the current state request.
Definition: ltc_6806.c:538
void LTC_SaveVoltages(LTC_STATE_s *ltc_state, uint8_t stringNumber)
stores the measured voltages in the database.
Definition: ltc_6806.c:389
#define LTC_FUELCELL_NEGATIVE_FULLSCALE_RANGE_mV
Definition: ltc_6806.c:99
static STD_RETURN_TYPE_e LTC_Init(SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16_t *pTxBuff, uint16_t *pRxBuff, uint32_t frameLength)
initialize the daisy-chain.
Definition: ltc_6806.c:1388
static void LTC_ResetErrorTable(LTC_STATE_s *ltc_state)
resets the error table.
Definition: ltc_6806.c:1440
LTC_STATE_s ltc_stateBase
Definition: ltc_6806.c:134
static uint16_t ltc_cmdRDCVF_Fuelcell[4]
Definition: ltc_6806.c:194
static uint16_t ltc_cmdRDCVB_Fuelcell[4]
Definition: ltc_6806.c:190
static LTC_ERRORTABLE_s ltc_errorTable
Definition: ltc_6806.c:124
static void LTC_Initialize_Database(LTC_STATE_s *ltc_state)
in the database, initializes the fields related to the LTC drivers.
Definition: ltc_6806.c:296
void LTC_Trigger(LTC_STATE_s *ltc_state)
trigger function for the LTC driver state machine.
Definition: ltc_6806.c:611
uint8_t LTC_CheckReEntrance(LTC_STATE_s *ltc_state)
re-entrance check of LTC state machine trigger function
Definition: ltc_6806.c:515
#define LTC_FUELCELL_POSITIVE_FULLSCALE_RANGE_mV
Definition: ltc_6806.c:94
static DATA_BLOCK_OPEN_WIRE_s ltc_openwire
Definition: ltc_6806.c:120
uint16_t ltc_RxPecBuffer[LTC_N_BYTES_FOR_DATA_TRANSMISSION]
Definition: ltc_6806.c:108
void LTC_monitoringPinInit(void)
Sets the transceiver pins to enable LTC6820 IC.
Definition: ltc_6806.c:1738
static LTC_OPENWIRE_DETECTION_s ltc_openWireDetection
Definition: ltc_6806.c:123
static void LTC_CondBasedStateTransition(LTC_STATE_s *ltc_state, STD_RETURN_TYPE_e retVal, DIAG_ID_e diagCode, LTC_STATEMACH_e state_ok, uint8_t substate_ok, uint16_t timer_ms_ok, LTC_STATEMACH_e state_nok, uint8_t substate_nok, uint16_t timer_ms_nok)
condition-based state transition depending on retVal
Definition: ltc_6806.c:369
static uint16_t ltc_BC_cmdADOW_PDOWN_100ms_fuelcell[4]
Definition: ltc_6806.c:228
static uint16_t ltc_cmdWRCFG[4]
Definition: ltc_6806.c:181
static STD_RETURN_TYPE_e LTC_RX_PECCheck(LTC_STATE_s *ltc_state, uint16_t *DataBufferSPI_RX_with_PEC, uint8_t stringNumber)
checks if the data received from the daisy-chain is not corrupt.
Definition: ltc_6806.c:1521
static DATA_BLOCK_CELL_TEMPERATURE_s ltc_celltemperature
Definition: ltc_6806.c:118
static uint16_t ltc_BC_cmdADOW_PUP_100ms_fuelcell[4]
Definition: ltc_6806.c:226
static uint16_t ltc_cmdRDCVC_Fuelcell[4]
Definition: ltc_6806.c:191
static uint16_t ltc_cmdADCV_normal_Fuelcell[4]
Definition: ltc_6806.c:202
static STD_RETURN_TYPE_e LTC_RX(uint16_t *Command, SPI_INTERFACE_CONFIG_s *pSpiInterface, uint16_t *pTxBuff, uint16_t *pRxBuff, uint32_t frameLength)
send command to the LTC daisy-chain and receives data from the LTC daisy-chain.
Definition: ltc_6806.c:1584
Header for the configuration for the LTC 6806 monitoring IC.
#define LTC_STATEMACH_DAISY_CHAIN_FIRST_INITIALIZATION_TIME
Definition: ltc_6806_cfg.h:176
#define LTC_TRANSMISSION_TIMEOUT
Definition: ltc_6806_cfg.h:145
#define LTC_FUELCELL_NORMAL_ALL_CELLS_MS
Definition: ltc_6806_cfg.h:167
#define LTC_TransmitCommand(spi_ltcInterface, command)
Definition: ltc_6806_cfg.h:299
#define LTC_STATEMACH_SHORTTIME
Definition: ltc_6806_cfg.h:170
#define LTC_DISCARD_PEC
Definition: ltc_6806_cfg.h:88
#define LTC_NUMBER_OF_LTC_PER_MODULE
Definition: ltc_6806_cfg.h:103
#define LTC_HIRNG
Definition: ltc_6806_cfg.h:110
#define LTC_VOLTAGE_MEASUREMENT_MODE
Definition: ltc_6806_cfg.h:124
#define LTC_ADOW_THRESHOLD
Definition: ltc_6806_cfg.h:116
#define LTC_FUEL_CELL_ADOW_TIME_MS
Definition: ltc_6806_cfg.h:113
#define LTC_TransmitReceiveData(spi_ltcInterface, txbuf, rxbuf, length)
Definition: ltc_6806_cfg.h:302
#define LTC_SPI_WAKEUP_WAIT_TIME_US
Definition: ltc_6806_cfg.h:164
#define LTC_TransmitWakeUp(spi_ltcInterface)
Definition: ltc_6806_cfg.h:295
#define LTC_NMBR_REQ_ADOW_COMMANDS
Definition: ltc_6806_cfg.h:289
#define LTC_OW_MEASUREMENT_MODE
Definition: ltc_6806_cfg.h:139
#define LTC_STATEMACH_DAISY_CHAIN_SECOND_INITIALIZATION_TIME
Definition: ltc_6806_cfg.h:181
bool AFE_IsTransmitOngoing(LTC_STATE_s *pLtcState)
gets the SPI transmit status.
Definition: ltc_afe_dma.c:73
void AFE_SetTransmitOngoing(LTC_STATE_s *pLtcState)
sets the SPI transmit status.
Definition: ltc_afe_dma.c:77
#define LTC_N_BYTES_FOR_DATA_TRANSMISSION
Definition: ltc_cfg.h:77
#define LTC_N_LTC
Definition: ltc_cfg.h:66
@ LTC_RE_ENTRY_INITIALIZATION
Definition: ltc_defs.h:176
@ LTC_ENTRY_INITIALIZATION
Definition: ltc_defs.h:174
@ LTC_START_INIT_INITIALIZATION
Definition: ltc_defs.h:175
@ LTC_EXIT_INITIALIZATION
Definition: ltc_defs.h:179
@ LTC_CHECK_INITIALIZATION
Definition: ltc_defs.h:178
@ LTC_INIT_STRING
Definition: ltc_defs.h:173
@ LTC_STATE_INIT_REQUEST
Definition: ltc_defs.h:364
@ LTC_STATE_OPENWIRE_CHECK_REQUEST
Definition: ltc_defs.h:386
@ LTC_STATE_NO_REQUEST
Definition: ltc_defs.h:390
@ LTC_REQUEST_PULLDOWN_CURRENT_OPENWIRE_CHECK
Definition: ltc_defs.h:235
@ LTC_READ_VOLTAGES_PULLDOWN_OPENWIRE_CHECK
Definition: ltc_defs.h:236
@ LTC_READ_VOLTAGES_PULLUP_OPENWIRE_CHECK
Definition: ltc_defs.h:234
@ LTC_REQUEST_PULLUP_CURRENT_OPENWIRE_CHECK
Definition: ltc_defs.h:233
@ LTC_PERFORM_OPENWIRE_CHECK
Definition: ltc_defs.h:237
LTC_STATEMACH_e
Definition: ltc_defs.h:117
@ LTC_STATEMACH_INITIALIZATION
Definition: ltc_defs.h:120
@ LTC_STATEMACH_UNINITIALIZED
Definition: ltc_defs.h:119
@ LTC_STATEMACH_STARTMEAS_CONTINUE
Definition: ltc_defs.h:148
@ LTC_STATEMACH_OPENWIRE_CHECK
Definition: ltc_defs.h:140
@ LTC_STATEMACH_READVOLTAGE
Definition: ltc_defs.h:126
@ LTC_STATEMACH_INITIALIZED
Definition: ltc_defs.h:122
@ LTC_STATEMACH_STARTMEAS
Definition: ltc_defs.h:125
LTC_ADCMEAS_CHAN_e
Definition: ltc_defs.h:103
@ LTC_ADCMEAS_UNDEFINED
Definition: ltc_defs.h:104
@ LTC_ADCMEAS_ALLCHANNEL_CELLS
Definition: ltc_defs.h:105
LTC_RETURN_TYPE_e
Definition: ltc_defs.h:396
@ LTC_BUSY_OK
Definition: ltc_defs.h:398
@ LTC_ILLEGAL_REQUEST
Definition: ltc_defs.h:400
@ LTC_ALREADY_INITIALIZED
Definition: ltc_defs.h:407
@ LTC_ERROR
Definition: ltc_defs.h:406
@ LTC_OK_FROM_ERROR
Definition: ltc_defs.h:405
@ LTC_REQUEST_PENDING
Definition: ltc_defs.h:399
@ LTC_OK
Definition: ltc_defs.h:397
@ LTC_READ_VOLTAGE_REGISTER_F_RDCVF_READVOLTAGE
Definition: ltc_defs.h:195
@ LTC_READ_VOLTAGE_REGISTER_A_RDCVA_READVOLTAGE
Definition: ltc_defs.h:190
@ LTC_READ_VOLTAGE_REGISTER_D_RDCVD_READVOLTAGE
Definition: ltc_defs.h:193
@ LTC_READ_VOLTAGE_REGISTER_G_RDCVG_READVOLTAGE
Definition: ltc_defs.h:196
@ LTC_READ_VOLTAGE_REGISTER_I_RDCVI_READVOLTAGE
Definition: ltc_defs.h:198
@ LTC_READ_VOLTAGE_REGISTER_B_RDCVB_READVOLTAGE
Definition: ltc_defs.h:191
@ LTC_EXIT_READVOLTAGE
Definition: ltc_defs.h:199
@ LTC_READ_VOLTAGE_REGISTER_H_RDCVH_READVOLTAGE
Definition: ltc_defs.h:197
@ LTC_READ_VOLTAGE_REGISTER_E_RDCVE_READVOLTAGE
Definition: ltc_defs.h:194
@ LTC_READ_VOLTAGE_REGISTER_C_RDCVC_READVOLTAGE
Definition: ltc_defs.h:192
@ LTC_REUSE_READVOLT_FOR_ADOW_PUP
Definition: ltc_defs.h:496
@ LTC_REUSE_READVOLT_FOR_ADOW_PDOWN
Definition: ltc_defs.h:497
@ LTC_NOT_REUSED
Definition: ltc_defs.h:495
LTC_ADCMODE_e
Definition: ltc_defs.h:92
@ LTC_ADCMODE_UNDEFINED
Definition: ltc_defs.h:93
@ LTC_ADCMODE_FAST_DCP0
Definition: ltc_defs.h:94
@ LTC_ENTRY
Definition: ltc_defs.h:160
Declaration of the OS wrapper interface.
void OS_ExitTaskCritical(void)
Exit Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:125
void OS_EnterTaskCritical(void)
Enter Critical interface function for use in FreeRTOS-Tasks and FreeRTOS-ISR.
Definition: os_freertos.c:121
void PEX_SetPin(uint8_t portExpander, uint8_t pin)
sets pin to high.
Definition: pex.c:320
void PEX_SetPinDirectionOutput(uint8_t portExpander, uint8_t pin)
sets pin to input.
Definition: pex.c:393
Header for the driver for the NXP PCA9539 port expander module.
#define PEX_PIN16
Definition: pex_cfg.h:94
#define PEX_PIN13
Definition: pex_cfg.h:91
#define PEX_PIN10
Definition: pex_cfg.h:88
#define PEX_PORT_EXPANDER3
Definition: pex_cfg.h:75
#define PEX_PIN17
Definition: pex_cfg.h:95
#define PEX_PIN12
Definition: pex_cfg.h:90
#define PEX_PIN15
Definition: pex_cfg.h:93
#define PEX_PIN11
Definition: pex_cfg.h:89
#define PEX_PIN14
Definition: pex_cfg.h:92
SPI_INTERFACE_CONFIG_s spi_ltcInterface[BS_NR_OF_STRINGS]
Definition: spi_cfg.c:200
struct definition for plausibility values of an AFE
const int16_t maximumPlausibleVoltage_mV
DATA_BLOCK_ID_e uniqueId
Definition: database_cfg.h:111
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:302
uint16_t gpioVoltages_mV[BS_NR_OF_STRINGS][BS_NR_OF_MODULES *BS_NR_OF_GPIOS_PER_MODULE]
Definition: database_cfg.h:304
int16_t cellTemperature_ddegC[BS_NR_OF_STRINGS][BS_NR_OF_TEMP_SENSORS_PER_STRING]
Definition: database_cfg.h:139
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:137
uint16_t invalidCellTemperature[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:141
uint16_t nrValidTemperatures[BS_NR_OF_STRINGS]
Definition: database_cfg.h:142
uint16_t nrValidCellVoltages[BS_NR_OF_STRINGS]
Definition: database_cfg.h:127
int16_t cellVoltage_mV[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: database_cfg.h:124
uint64_t invalidCellVoltage[BS_NR_OF_STRINGS][BS_NR_OF_MODULES]
Definition: database_cfg.h:126
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:121
int32_t packVoltage_mV[BS_NR_OF_STRINGS]
Definition: database_cfg.h:123
uint16_t nrOpenWires[BS_NR_OF_STRINGS]
Definition: database_cfg.h:292
DATA_BLOCK_HEADER_s header
Definition: database_cfg.h:290
uint8_t openwire[BS_NR_OF_STRINGS][BS_NR_OF_MODULES *(BS_NR_OF_CELLS_PER_MODULE+1u)]
Definition: database_cfg.h:294
LTC_OPENWIRE_DETECTION_s * openWireDetection
Definition: ltc_defs.h:446
DATA_BLOCK_ALL_GPIO_VOLTAGES_s * allGpioVoltages
Definition: ltc_defs.h:443
DATA_BLOCK_CELL_VOLTAGE_s * cellVoltage
Definition: ltc_defs.h:438
DATA_BLOCK_CELL_TEMPERATURE_s * cellTemperature
Definition: ltc_defs.h:439
uint16_t * txBuffer
Definition: ltc_defs.h:435
LTC_ERRORTABLE_s * errorTable
Definition: ltc_defs.h:447
SPI_INTERFACE_CONFIG_s * pSpiInterface
Definition: ltc_defs.h:434
uint16_t * rxBuffer
Definition: ltc_defs.h:436
uint16_t * usedCellIndex
Definition: ltc_defs.h:445
uint32_t frameLength
Definition: ltc_defs.h:437
DATA_BLOCK_OPEN_WIRE_s * openWire
Definition: ltc_defs.h:444
uint8_t PEC_valid[BS_NR_OF_STRINGS][LTC_N_LTC]
Definition: ltc_defs.h:70
uint8_t mux3[BS_NR_OF_STRINGS][LTC_N_LTC]
Definition: ltc_defs.h:74
uint8_t mux2[BS_NR_OF_STRINGS][LTC_N_LTC]
Definition: ltc_defs.h:73
uint8_t mux0[BS_NR_OF_STRINGS][LTC_N_LTC]
Definition: ltc_defs.h:71
uint8_t mux1[BS_NR_OF_STRINGS][LTC_N_LTC]
Definition: ltc_defs.h:72
int16_t openWirePup[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: ltc_defs.h:79
int32_t openWireDelta[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: ltc_defs.h:81
int16_t openWirePdown[BS_NR_OF_STRINGS][BS_NR_OF_BAT_CELLS]
Definition: ltc_defs.h:80
LTC_STATE_REQUEST_e request
Definition: ltc_defs.h:512
uint8_t string
Definition: ltc_defs.h:513
uint32_t commandDataTransferTime
Definition: ltc_defs.h:544
LTC_DATAPTR_s ltcData
Definition: ltc_defs.h:579
LTC_ADCMODE_e adcModereq
Definition: ltc_defs.h:531
LTC_REQUEST_s statereq
Definition: ltc_defs.h:523
uint8_t triggerentry
Definition: ltc_defs.h:542
SPI_INTERFACE_CONFIG_s * spiSeqPtr
Definition: ltc_defs.h:569
uint32_t commandTransferTime
Definition: ltc_defs.h:545
SPI_INTERFACE_CONFIG_s * spiSeqEndPtr
Definition: ltc_defs.h:570
uint8_t substate
Definition: ltc_defs.h:525
LTC_STATEMACH_e laststate
Definition: ltc_defs.h:526
uint8_t lastsubstate
Definition: ltc_defs.h:527
LTC_ADCMEAS_CHAN_e adcMeasCh
Definition: ltc_defs.h:533
LTC_REUSE_MODE_e reusageMeasurementMode
Definition: ltc_defs.h:559
uint32_t gpioClocksTransferTime
Definition: ltc_defs.h:547
uint16_t timer
Definition: ltc_defs.h:521
uint8_t resendCommandCounter
Definition: ltc_defs.h:566
LTC_STATEMACH_e state
Definition: ltc_defs.h:524
uint8_t spiNumberInterfaces
Definition: ltc_defs.h:571
LTC_ADCMODE_e adcMode
Definition: ltc_defs.h:528
uint8_t currentString
Definition: ltc_defs.h:572
uint32_t ErrRequestCounter
Definition: ltc_defs.h:541
STD_RETURN_TYPE_e check_spi_flag
Definition: ltc_defs.h:564
bool first_measurement_made
Definition: ltc_defs.h:561
uint8_t requestedString
Definition: ltc_defs.h:573
LTC_ADCMEAS_CHAN_e adcMeasChreq
Definition: ltc_defs.h:535
spiBASE_t * pNode
Definition: spi_cfg.h:141