foxBMS - Unit Tests  1.3.0
The foxBMS Unit Tests API Documentation
mxm_1785x_tools.c
Go to the documentation of this file.
1 /**
2  *
3  * @copyright © 2010 - 2022, 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 mxm_1785x_tools.c
44  * @author foxBMS Team
45  * @date 2020-07-15 (date of creation)
46  * @updated 2022-05-30 (date of last update)
47  * @version v1.3.0
48  * @ingroup DRIVERS
49  * @prefix MXM
50  *
51  * @brief This is a collection of helper functions for the MAX1785x ICs
52  *
53  * @details This collection of helper functions for the MAX1785x ICs helps to
54  * calculate the lsb and msb for register values and similar tasks.
55  *
56  */
57 
58 /*========== Includes =======================================================*/
59 #include "mxm_1785x_tools.h"
60 
61 #include "mxm_register_map.h"
62 
63 /*========== Macros and Definitions =========================================*/
64 /** length of a byte */
65 #define MXM_TOOLS_LENGTH_BYTE (8u)
66 
67 /*========== Static Constant and Variable Definitions =======================*/
68 
69 /*========== Extern Constant and Variable Definitions =======================*/
70 
71 /*========== Static Function Prototypes =====================================*/
72 /**
73  * @brief Find Position of first set bit in bitmask
74  * @details Searches a bitmask starting from the lowest bit and returns the
75  * position of the first set bit.
76  * @param[in] bitmask bitmask that should be searched
77  * @return position of first set bit
78  */
79 static uint8_t MXM_FirstSetBit(uint16_t bitmask);
80 
81 /*========== Static Function Implementations ================================*/
82 static uint8_t MXM_FirstSetBit(uint16_t bitmask) {
83  /* AXIVION Routine Generic-MissingParameterAssert: bitmask: parameter accepts whole range */
84  uint8_t retval = 0;
85  while (((bitmask >> retval) & 1u) == 0u) {
86  retval++;
87  /* exit if every entry is zero */
88  if (retval >= 16u) {
89  break;
90  }
91  }
92  return retval;
93 }
94 
95 /*========== Extern Function Implementations ================================*/
97  /* AXIVION Disable Style Generic-NoMagicNumbers: This test function uses magic numbers to test predefined values. */
98 
99  /* bitmasks containing only zeros should return first bit set 16 */
101 
103 
105 
107 
108  /* AXIVION Enable Style Generic-NoMagicNumbers: */
109 
110  return STD_OK;
111 }
112 
113 extern void MXM_Convert(
114  uint8_t lsb,
115  uint8_t msb,
116  uint16_t *pTarget,
117  MXM_CONVERSION_TYPE_e convType,
118  uint32_t fullScaleReference_mV) {
119  FAS_ASSERT(pTarget != NULL_PTR);
120  /* AXIVION Routine Generic-MissingParameterAssert: lsb: parameter accepts whole range */
121  /* AXIVION Routine Generic-MissingParameterAssert: msb: parameter accepts whole range */
122  /* AXIVION Routine Generic-MissingParameterAssert: convType: parameter accepts whole range */
123  /* AXIVION Routine Generic-MissingParameterAssert: fullScaleReference_mV: parameter accepts whole range */
124  uint16_t temporaryVoltage = 0;
125  MXM_ExtractValueFromRegister(lsb, msb, MXM_REG_ADC_14BIT_VALUE, &temporaryVoltage);
126 
127  temporaryVoltage = temporaryVoltage + (uint16_t)1u;
128  const uint32_t scaledVoltageUnipolar_mV = (temporaryVoltage * fullScaleReference_mV) / 0x3FFFu;
129 
130  switch (convType) {
132  /* not yet supported */
134  break;
137  if (scaledVoltageUnipolar_mV > (uint16_t)UINT16_MAX) {
138  *pTarget = UINT16_MAX;
139  } else {
140  *pTarget = (uint16_t)scaledVoltageUnipolar_mV;
141  }
142  break;
143  default:
144  /* we should not be here */
146  break;
147  }
148 }
149 
151  /* AXIVION Disable Style Generic-NoMagicNumbers: This test function uses magic numbers to test predefined values. */
152 
154 
155  /* low scale */
156  uint8_t msb = 0x00u;
157  uint8_t lsb = 0x00u;
158  uint16_t voltage = 1;
159  MXM_Convert(lsb, msb, &voltage, conversionType, 5000);
160  FAS_ASSERT(voltage == 0u);
161 
162  /* half scale */
163  msb = 0x80u;
164  lsb = 0x00u;
165  voltage = 0;
166  MXM_Convert(lsb, msb, &voltage, conversionType, 5000);
167  FAS_ASSERT(voltage == 2500u);
168 
169  /* full scale */
170  msb = 0xFFu;
171  lsb = 0xFCu;
172  voltage = 0;
173  MXM_Convert(lsb, msb, &voltage, conversionType, 5000);
174  FAS_ASSERT(voltage == 5000u);
175 
176  /* AXIVION Enable Style Generic-NoMagicNumbers: */
177 
178  return STD_OK;
179 }
180 
181 extern void MXM_ExtractValueFromRegister(uint8_t lsb, uint8_t msb, MXM_REG_BM bitmask, uint16_t *pValue) {
182  /* input sanitation */
183  FAS_ASSERT(pValue != NULL_PTR);
184  /* AXIVION Routine Generic-MissingParameterAssert: lsb: parameter accepts whole range */
185  /* AXIVION Routine Generic-MissingParameterAssert: msb: parameter accepts whole range */
186  /* AXIVION Routine Generic-MissingParameterAssert: bitmask: parameter accepts whole range */
187 
188  /* find lowest bit that is 1 in bitmask */
189  uint8_t start = MXM_FirstSetBit(bitmask);
190 
191  /* apply bitmask to MSB */
192  uint16_t msbBitmask = (bitmask & MXM_BM_MSB);
193  uint8_t msbMasked = msb & ((uint8_t)(msbBitmask >> MXM_TOOLS_LENGTH_BYTE));
194 
195  /* shift LSB into right position if lsb is used */
196  if (start < MXM_TOOLS_LENGTH_BYTE) {
197  /* apply bitmask to LSB */
198  uint8_t lsbMasked = lsb & ((uint8_t)(bitmask & MXM_BM_LSB));
199  *pValue = ((uint16_t)lsbMasked >> start);
200  /* add MSB at right position */
201  *pValue = (((uint16_t)msbMasked << (MXM_TOOLS_LENGTH_BYTE - start)) | *pValue);
202  } else if (start == MXM_TOOLS_LENGTH_BYTE) {
203  *pValue = (uint16_t)msbMasked;
204  } else {
205  *pValue = ((uint16_t)msbMasked >> (start - MXM_TOOLS_LENGTH_BYTE));
206  }
207 }
208 
210  /* AXIVION Disable Style Generic-NoMagicNumbers: This test function uses magic numbers to test predefined values. */
211  uint8_t lsb = 0x31u;
212  uint8_t msb = 0x85u;
213  uint16_t value = 0x00u;
215  FAS_ASSERT(value == 0x853u);
216 
218  FAS_ASSERT(value == 0x01u);
219 
220  lsb = 0xFCu;
221  msb = 0xFFu;
222  value = 0x00u;
224  FAS_ASSERT(value == 0x3FFFu);
225 
226  lsb = 0xFEu;
227  msb = 0x7Fu;
228  value = 0x00u;
230  FAS_ASSERT(value == 0x1FFFu);
231 
232  /* AXIVION Enable Style Generic-NoMagicNumbers: */
233 
234  return STD_OK;
235 }
236 
237 extern void MXM_Unipolar14BitInto16Bit(uint16_t inputValue, uint8_t *lsb, uint8_t *msb) {
238  FAS_ASSERT(lsb != NULL_PTR);
239  FAS_ASSERT(msb != NULL_PTR);
240  /* AXIVION Routine Generic-MissingParameterAssert: inputValue: parameter accepts whole range */
241 
242  uint16_t workingCopy = inputValue;
243  /* left shift into 16bit position */
244  workingCopy = workingCopy << 2u;
245 
246  /* bitmask LSB */
247  *lsb = (uint8_t)(workingCopy & MXM_BM_LSB);
248  /* shift MSB into lower byte (workingCopy is 16bit) */
249  *msb = (uint8_t)(workingCopy >> MXM_TOOLS_LENGTH_BYTE);
250 }
251 
252 extern uint16_t MXM_VoltageIntoUnipolar14Bit(uint16_t voltage_mV, uint16_t fullscaleReference_mV) {
253  /* AXIVION Routine Generic-MissingParameterAssert: voltage_mV: parameter accepts whole range */
254  /* AXIVION Routine Generic-MissingParameterAssert: fullscaleReference_mV: parameter accepts whole range */
255 
256  uint32_t temporaryVoltage = voltage_mV;
257  /* multiply by the 14bit fullscale */
258  temporaryVoltage = temporaryVoltage * 0x3FFFu;
259  /* return divided by fullscale_reference */
260  return (uint16_t)(temporaryVoltage / fullscaleReference_mV);
261 }
262 
264  const uint16_t moduleNumber,
265  uint8_t *pStringNumber,
266  uint16_t *pModuleNumberInString) {
267  FAS_ASSERT(pStringNumber != NULL_PTR);
268  FAS_ASSERT(pModuleNumberInString != NULL_PTR);
269  /* the module number cannot be higher than the highest module in the daisy-chain */
270  FAS_ASSERT(moduleNumber < MXM_MAXIMUM_NR_OF_MODULES);
271  /* the module number cannot be higher than number of maximum modules in the string */
273 
274  /* calculate string number */
275  *pStringNumber = (uint8_t)(moduleNumber / BS_NR_OF_MODULES_PER_STRING);
276  FAS_ASSERT(*pStringNumber <= BS_NR_OF_STRINGS);
277  /* calculate module number and handle edge-case BS_NR_OF_MODULES_PER_STRING == 1 */
278  if (1u == BS_NR_OF_MODULES_PER_STRING) {
279  *pModuleNumberInString = 0u;
280  } else {
281  *pModuleNumberInString = moduleNumber % BS_NR_OF_MODULES_PER_STRING;
282  }
283  FAS_ASSERT(*pModuleNumberInString <= BS_NR_OF_MODULES_PER_STRING);
284 }
285 
286 /*========== Externalized Static Function Implementations (Unit Test) =======*/
#define BS_NR_OF_STRINGS
Number of parallel strings in the battery pack.
#define BS_NR_OF_MODULES_PER_STRING
number of modules in a string
#define FAS_ASSERT(x)
Assertion macro that asserts that x is true.
Definition: fassert.h:237
#define FAS_TRAP
Define that evaluates to essential boolean false thus tripping an assert.
Definition: fassert.h:115
STD_RETURN_TYPE_e
Definition: fstd_types.h:81
@ STD_OK
Definition: fstd_types.h:82
#define NULL_PTR
Null pointer.
Definition: fstd_types.h:76
#define must_check_return
Allows functions to generate warnings in GCC for unused returns.
Definition: general.h:88
#define MXM_BM_LSB
Monitoring Register LSB.
#define MXM_BM_MSB
Monitoring Register MSB.
#define MXM_BM_NULL
Monitoring Register Null byte.
#define MXM_REG_VERSION_VER
Monitoring Register Version/Silicon Version.
#define MXM_REG_VERSION_MOD
Monitoring Register Version/Model.
#define MXM_REG_ADC_14BIT_VALUE
Monitoring Register 14bit ADC value.
static uint8_t MXM_FirstSetBit(uint16_t bitmask)
Find Position of first set bit in bitmask.
void MXM_Unipolar14BitInto16Bit(uint16_t inputValue, uint8_t *lsb, uint8_t *msb)
convert a unipolar 14bit-value and shifts it into the 16bit-format
void MXM_ConvertModuleToString(const uint16_t moduleNumber, uint8_t *pStringNumber, uint16_t *pModuleNumberInString)
Get the string and module number from a global module number.
STD_RETURN_TYPE_e must_check_return MXM_ConvertTest(void)
Test the MXM_Convert()-function.
#define MXM_TOOLS_LENGTH_BYTE
STD_RETURN_TYPE_e must_check_return MXM_FirstSetBitTest(void)
Test MXM_FirstSetBit().
uint16_t MXM_VoltageIntoUnipolar14Bit(uint16_t voltage_mV, uint16_t fullscaleReference_mV)
convert a voltage value into a unipolar 14bit value
STD_RETURN_TYPE_e must_check_return MXM_ExtractValueFromRegisterTest(void)
Test MXM_ExtractValueFromRegister().
void MXM_Convert(uint8_t lsb, uint8_t msb, uint16_t *pTarget, MXM_CONVERSION_TYPE_e convType, uint32_t fullScaleReference_mV)
Convert a measurement value to a voltage value.
void MXM_ExtractValueFromRegister(uint8_t lsb, uint8_t msb, MXM_REG_BM bitmask, uint16_t *pValue)
Extract a value from a single register.
This is a collection of helper functions for the MAX1785x ICs.
MXM_CONVERSION_TYPE_e
@ MXM_CONVERSION_BIPOLAR
@ MXM_CONVERSION_UNIPOLAR
@ MXM_CONVERSION_BLOCK_VOLTAGE
#define MXM_MAXIMUM_NR_OF_MODULES
Maximum number of modules.
Register map of the MAX1785x monitoring IC.
uint16_t MXM_REG_BM
Type for register access for monitoring ICs.