1 /*
2 * Copyright 2022 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /**
9 * @file fxls8974cf_freemaster_usb_demo.c
10 * @brief The fxls8974cf_freemaster_usb_demo.c file implements FreeMASTER demo using the ISSDK
11 * FXLS8974CF sensor driver example demonstration with interrupt mode.
12 */
13
14 //-----------------------------------------------------------------------
15 // SDK Includes
16 //-----------------------------------------------------------------------
17 #include "pin_mux.h"
18 #include "clock_config.h"
19 #include "board.h"
20 #include "fsl_debug_console.h"
21 #include "math.h"
22 #include "fsl_uart.h"
23 #include "fsl_common.h"
24 #include "freemaster.h"
25 #include "usb_device_config.h"
26 #include "freemaster_usb.h"
27 //-----------------------------------------------------------------------
28 // CMSIS Includes
29 //-----------------------------------------------------------------------
30 #include "Driver_I2C.h"
31
32 //-----------------------------------------------------------------------
33 // ISSDK Includes
34 //-----------------------------------------------------------------------
35 #include "issdk_hal.h"
36 #include "gpio_driver.h"
37 #include "fxls8974_drv.h"
38 #include "systick_utils.h"
39
40 //-----------------------------------------------------------------------
41 // Macros
42 //-----------------------------------------------------------------------
43 #define FXLS8974_NUM_REGISTERS (FXLS8974_SELF_TEST_CONFIG2 + 1)
44 #define FF_A_FFMT_THS (0x08) /* FreeFall Threshold Value. */
45 #define A_FFMT_COUNT (0x18) /* Freefall/motion debounce count value. */
46 #define PL_COUNT (0x15) /* Pulse debounce count value. */
47 #define ASLP_COUNTER (0x07) /* Auto Sleep after ~5s. */
48 #define ACCEL_2G_SENS (0.000976) /* Sensitivity factor for 2G FS */
49 #define ACCEL_4G_SENS (0.001953) /* Sensitivity factor for 4G FS */
50 #define ACCEL_8G_SENS (0.003906) /* Sensitivity factor for 8G FS */
51 #define ACCEL_16G_SENS (0.007813) /* Sensitivity factor for 16G FS */
52 #define N (100U) /* Number of samples used to measure offset/noise */
53 #define RAW_ACCEL_DATA_SIZE (6U) /* Accel Data Size */
54 #define MAX8BITSTORAGE (255U)
55 #define FXLS8974_DATA_SIZE 6
56 //-----------------------------------------------------------------------
57 // Constants
58 //-----------------------------------------------------------------------
59 /*! @brief Defines the register write list to configure FXLS8974 in Interrupt mode. */
60 const registerwritelist_t cFxls8974ConfigNormal[] = {
61 /*! Set Full-scale range as 4G. */
62 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_4G, FXLS8974_SENS_CONFIG1_FSR_MASK},
63 /*! Clear SENS_CONFIG2 */
64 {FXLS8974_SENS_CONFIG2, 0x00, 0x00},
65 /*! Disable Self-Test. */
66 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_DISABLED, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
67 /*! Set Wake Mode ODR Rate as 12.5Hz. */
68 {FXLS8974_SENS_CONFIG3, FXLS8974_SENS_CONFIG3_WAKE_ODR_12_5HZ, FXLS8974_SENS_CONFIG3_WAKE_ODR_MASK},
69 /*! Enable Interrupts for Data Ready Events. */
70 {FXLS8974_INT_EN, FXLS8974_INT_EN_DRDY_EN_EN, FXLS8974_INT_EN_DRDY_EN_MASK},
71 /*! Enable Temperature sensor. */
72 {FXLS8974_SENS_CONFIG2,FXLS8974_SENS_CONFIG2_ANIC_TEMP_EN,FXLS8974_SENS_CONFIG2_ANIC_TEMP_MASK},
73 /*! Set Self-Test ODR to 100 Hz. */
74 {0x38,0x05,0x00},
75 {0x2F,0x38,0x00},
76 {0x30,0xD8,0x00},
77 {0x33,0xC0,0x00},
78 {0x34,0xFF,0x00},
79 {0x35,0x40,0x00},
80 __END_WRITE_DATA__};
81
82 /*! @brief Register settings for Self-Test in X Axis (Positive polarity). */
83 const registerwritelist_t cFxls8974STXP[] = {
84 /* Set Self Test Axis. */
85 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_16G, FXLS8974_SENS_CONFIG1_FSR_MASK},
86 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_EN_X, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
87 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_POL_POSITIVE, FXLS8974_SENS_CONFIG1_ST_POL_MASK},
88 __END_WRITE_DATA__};
89
90 /*! @brief Register settings for Self-Test in X Axis (Negative polarity). */
91 const registerwritelist_t cFxls8974STXN[] = {
92 /* Set Self Test Axis. */
93 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_16G, FXLS8974_SENS_CONFIG1_FSR_MASK},
94 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_EN_X, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
95 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_POL_NEGATIVE, FXLS8974_SENS_CONFIG1_ST_POL_MASK},
96 __END_WRITE_DATA__};
97
98 /*! @brief Register settings for Self-Test in Y Axis (Positive polarity). */
99 const registerwritelist_t cFxls8974STYP[] = {
100 /* Set Self Test Axis. */
101 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_16G, FXLS8974_SENS_CONFIG1_FSR_MASK},
102 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_EN_Y, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
103 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_POL_POSITIVE,FXLS8974_SENS_CONFIG1_ST_POL_MASK},
104 __END_WRITE_DATA__};
105
106 /*! @brief Register settings for Self-Test in Y Axis (Negative polarity). */
107 const registerwritelist_t cFxls8974STYN[] = {
108 /* Set Self Test Axis. */
109 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_16G, FXLS8974_SENS_CONFIG1_FSR_MASK},
110 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_EN_Y, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
111 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_POL_NEGATIVE, FXLS8974_SENS_CONFIG1_ST_POL_MASK},
112 __END_WRITE_DATA__};
113
114 /*! @brief Register settings for Self-Test in Z Axis (Positive polarity). */
115 const registerwritelist_t cFxls8974STZP[] = {
116 /* Set Self Test Axis. */
117 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_16G, FXLS8974_SENS_CONFIG1_FSR_MASK},
118 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_EN_Z, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
119 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_POL_POSITIVE, FXLS8974_SENS_CONFIG1_ST_POL_MASK},
120 __END_WRITE_DATA__};
121
122 /*! @brief Register settings for Self-Test in Z Axis (Negative polarity). */
123 const registerwritelist_t cFxls8974STZN[] = {
124 /* Set Self Test Axis. */
125 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_FSR_16G, FXLS8974_SENS_CONFIG1_FSR_MASK},
126 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_EN_Z, FXLS8974_SENS_CONFIG1_ST_AXIS_SEL_MASK},
127 {FXLS8974_SENS_CONFIG1, FXLS8974_SENS_CONFIG1_ST_POL_NEGATIVE, FXLS8974_SENS_CONFIG1_ST_POL_MASK},
128 __END_WRITE_DATA__};
129
130 /*! @brief Address of Raw Accel Data in Normal Mode. */
131 const registerreadlist_t cFxls8974OutputNormal[] = {{.readFrom = FXLS8974_OUT_X_LSB, .numBytes = FXLS8974_DATA_SIZE},
132 __END_READ_DATA__};
133
134 const registerreadlist_t cFXLS8974_whoami[] = {
135 {.readFrom = FXLS8974_WHO_AM_I, .numBytes = 1}, __END_READ_DATA__};
136
137 /*! @brief Prepare the register read for INT Status Register. */
138 const registerreadlist_t cFXLS8974_int_src[] = {
139 {.readFrom = FXLS8974_INT_STATUS, .numBytes = 1}, __END_READ_DATA__};
140
141 /*! @brief Prepare the register read for FullScale range Register. */
142 const registerreadlist_t cFXLS8974_fs_src[] = {
143 {.readFrom = FXLS8974_SENS_CONFIG1, .numBytes = 1}, __END_READ_DATA__};
144
145 /*! @brief FXLS8974 register list to read all registers */
146 const registerreadlist_t FXLS8974_ALL_REG_READ[] = {{.readFrom = FXLS8974_INT_STATUS, .numBytes = FXLS8974_NUM_REGISTERS},
147 __END_READ_DATA__};
148
149 //-----------------------------------------------------------------------
150 // Global Variables
151 //-----------------------------------------------------------------------
152 /*! @brief This structure defines the fxls8974 all registers metadata.*/
153 typedef struct
154 {
155 uint8_t offset;
156 uint8_t value;
157 uint8_t trigger;
158 uint8_t read_offset;
159 uint8_t read_value;
160 uint8_t read_trigger;
161 uint8_t readall_value[FXLS8974_NUM_REGISTERS];
162 uint8_t readall_size;
163 uint8_t readall_trigger;
164 uint8_t toggle;
165 uint8_t trigger_accel_offnoise;
166 uint8_t trigger_selftest;
167 uint8_t fs_value;
168 uint8_t mods_value;
169 uint8_t odr_value;
170 uint8_t reg_addr[FXLS8974_NUM_REGISTERS];
171 uint8_t dataready_cntr;
172 float accel[3];
173 int16_t accelraw[3];
174 uint8_t sdcd;
175 int8_t temp;
176 int16_t selftest[3];
177 uint32_t timestamp;
178 } fxls8974_allregs_t;
179 //-----------------------------------------------------------------------
180 /*! @brief This structure defines the fxls8974 offset and noise calculation parameters. */
181 typedef struct
182 {
183 float offx;
184 float offy;
185 float offz;
186 float rmsx;
187 float rmsy;
188 float rmsz;
189 uint8_t complete_accel_offnoise;
190 } fxls8974_offset_noise_t;
191
192 /*! @brief This structure defines variables to compute self-test output change (STOC) and self-test offset (STOF). */
193 typedef struct
194 {
195 int16_t x_stoc;
196 int16_t y_stoc;
197 int16_t z_stoc;
198 int16_t x_stof;
199 int16_t y_stof;
200 int16_t z_stof;
201 uint8_t complete_selftest;
202 } fxls8974_selftest_t;
203
204 /*! @brief This structure defines the fxls8974 raw data buffer.*/
205 typedef struct
206 {
207 int16_t xdata; /*!< The x accel data */
208 int16_t ydata; /*!< The y accel data */
209 int16_t zdata; /*!< The z accel data */
210 } sensor_data;
211
212
213 typedef union rawdata
214 {
215 uint8_t byte_data[sizeof(sensor_data)];
216 sensor_data dat;
217 }RAW_DATA;
218
219 /*! @brief This structure defines the fxls8974 host operation type.*/
220 typedef enum fxls8974_operation_type
221 {
222 FXLS8974_REG_WRITE = 1U,
223 FXLS8974_REG_READ = 2U,
224 FXLS8974_ALLREG_READ = 3U,
225 FXLS8974_ACCEL_CONFIG_END
226
227 } fxls8974_operation_type_t;
228
229 /*******************************************************************************
230 * Globals
231 ******************************************************************************/
232
233 fxls8974_acceldata_t rawData;
234 fxls8974_allregs_t registers;
235 fxls8974_offset_noise_t offnoise_data;
236 fxls8974_selftest_t selftest;
237 uint8_t prev_toggle = 1;
238 volatile bool bFxls8974IntFlag = false;
239
240 static FMSTR_U8 recBuffer[1024*10];
241 FMSTR_REC_BUFF recBuffCfg;
242 FMSTR_REC_VAR recVar;
243 FMSTR_REC_CFG recCfg;
244
245 int32_t status, gSystick;
246 static unsigned char pipe3_rxb[512];
247 static unsigned char pipe3_txb[0x1000];
248
249 uint8_t axis=0;
250 /* variables to store self-test values (Positive(P) + / Negative(N) -) */
251 int16_t XSTP[2]={0,0},YSTP[2]={0,0},ZSTP[2]={0,0},XSTN[2]={0,0},YSTN[2]={0,0},ZSTN[2]={0,0};
252
253
254 /*******************************************************************************
255 * Local functions
256 ******************************************************************************/
257 /*! @brief ISR for FXLS8974 interrupt source event.
258 * @details This function implements ISR for FXLS8974 INT source.
259 * @param[in] void *.
260 * @return void.
261 */
262 void fxls8974_isr_callback(void *pUserData);
263 /*! @brief Function to apply FXLS8974 register write operation.
264 * @details This function apply FXLS8974 register write based on write trigger from host.
265 * @param[in] fxls8974_i2c_sensorhandle_t fxls8974Driver, FXLS8974 sensor I2C handle.
266 * @param[in] uint8_t offset, the address of the register to start writing from.
267 * @param[in] uint8_t value, value to write on register offset.
268 * @return returns the status of the operation.
269 */
270 int32_t apply_register_write(fxls8974_i2c_sensorhandle_t fxls8974Driver, uint8_t offset, uint8_t value);
271 /*! @brief Function to apply FXLS8974 register read operation.
272 * @details This function apply FXLS8974 register read based on read trigger from host.
273 * @param[in] fxls8974_i2c_sensorhandle_t fxls8974Driver, FXLS8974 sensor I2C handle.
274 * @param[in] uint8_t offset, the address of the register to read from.
275 * @param[in/out] uint8_t *value, pointer to output buffer.
276 * @return returns the status of the operation.
277 */
278 int32_t apply_register_read(fxls8974_i2c_sensorhandle_t fxls8974Driver, uint8_t offset, uint8_t *value);
279 /*! @brief Function to apply FXLS8974 register read-all operation.
280 * @details This function apply FXLS8974 all-registers read based on read-all trigger from host.
281 * @param[in] fxls8974_i2c_sensorhandle_t fxls8974Driver, FXLS8974 sensor I2C handle.
282 * @return returns the status of the operation.
283 */
284 int32_t apply_register_readall(fxls8974_i2c_sensorhandle_t fxls8974Driver);
285 /*! @brief Function to update dropdown selection.
286 * @details This function updates the dropdown selection values in real-time based on read/write/read-all triggers.
287 * @param[in/out] fxls8974_allregs_t *registers, pointer to FXLS8974 all-registers metadata.
288 * @param[in] uint8_t caller, called from which operation type.
289 * @return returns the status of the operation.
290 */
291 int32_t update_dropdown_selection(fxls8974_allregs_t *registers, uint8_t caller);
292 /*! @brief Function to initialize offset noise measurement.
293 * @details This function initializes offset noise measurement metadata.
294 * @param[in/out] fxls8974_offset_noise_t *offnoiseptr, pointer to FXLS8974 offset noise metadata.
295 * @return void.
296 */
297 void offset_noise_init(fxls8974_offset_noise_t *offnoiseptr);
298 /*! @brief Function to measure accelerometer offset noise.
299 * @details This function measures accelerometer offset noise.
300 * @param[in] fxls8974_acceldata_t *rawData, pointer to FXLS8974 rawdata metadata.
301 * @param[in/out] fxls8974_offset_noise_t *offnoiseptr, pointer to FXLS8974 offset noise metadata.
302 * @param[in] float sens, FXLS8974 sensitivity based on FS configuration.
303 * @return void.
304 */
305 void accel_off_noise(fxls8974_acceldata_t* rawData, fxls8974_offset_noise_t *offnoiseptr, float sens);
306 /*! @brief Function to initialize FXLS8974 self test metadata.
307 * @details This function initializes FXLS8974 self test metadata.
308 * @param[in/out] fxls8974_selftest_t *selftest, pointer to FXLS8974 selftest metadata.
309 * @return void.
310 */
311 void selftest_init(fxls8974_selftest_t *selftest);
312 /*! @brief Function to perform FXLS8974 self test.
313 * @details This function performs FXLS8974 self test.
314 * @param[in] fxls8974_i2c_sensorhandle_t fxls8974Driver, FXLS8974 sensor I2C handle.
315 * @param[in/out] fxls8974_selftest_t *selftest, pointer to FXLS8974 selftest metadata.
316 * @return returns the status of the operation..
317 */
318 int32_t perform_selftest(fxls8974_i2c_sensorhandle_t fxls8974Driver, fxls8974_selftest_t *selftest);
319 void FRM_Recorder_Init();
320
321 /*******************************************************************************
322 * Code
323 ******************************************************************************/
fxls8974_isr_callback(void * pUserData)324 void fxls8974_isr_callback(void *pUserData)
325 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
326 bFxls8974IntFlag = true;
327 }
328
329 /* Create TSA table and add output variables. */
330 /*!
331 * @brief Target Side Addressable (TSA) table created for this application.
332 */
333 FMSTR_TSA_TABLE_BEGIN(main_table)
FMSTR_TSA_STRUCT(fxls8974_acceldata_t)334 FMSTR_TSA_STRUCT(fxls8974_acceldata_t)
335
336 FMSTR_TSA_STRUCT(fxls8974_allregs_t)
337 FMSTR_TSA_MEMBER(fxls8974_allregs_t, offset, FMSTR_TSA_UINT8)
338 FMSTR_TSA_MEMBER(fxls8974_allregs_t, value, FMSTR_TSA_UINT8)
339 FMSTR_TSA_MEMBER(fxls8974_allregs_t, trigger, FMSTR_TSA_UINT8)
340 FMSTR_TSA_MEMBER(fxls8974_allregs_t, read_offset, FMSTR_TSA_UINT8)
341 FMSTR_TSA_MEMBER(fxls8974_allregs_t, read_value, FMSTR_TSA_UINT8)
342 FMSTR_TSA_MEMBER(fxls8974_allregs_t, read_trigger, FMSTR_TSA_UINT8)
343 FMSTR_TSA_MEMBER(fxls8974_allregs_t, readall_value, FMSTR_TSA_UINT8)
344 FMSTR_TSA_MEMBER(fxls8974_allregs_t, readall_size, FMSTR_TSA_UINT8)
345 FMSTR_TSA_MEMBER(fxls8974_allregs_t, readall_trigger, FMSTR_TSA_UINT8)
346 FMSTR_TSA_MEMBER(fxls8974_allregs_t, trigger_accel_offnoise, FMSTR_TSA_UINT8)
347 FMSTR_TSA_MEMBER(fxls8974_allregs_t, trigger_selftest, FMSTR_TSA_UINT8)
348 FMSTR_TSA_MEMBER(fxls8974_allregs_t, fs_value, FMSTR_TSA_UINT8)
349 FMSTR_TSA_MEMBER(fxls8974_allregs_t, mods_value, FMSTR_TSA_UINT8)
350 FMSTR_TSA_MEMBER(fxls8974_allregs_t, odr_value, FMSTR_TSA_UINT8)
351 FMSTR_TSA_MEMBER(fxls8974_allregs_t, toggle, FMSTR_TSA_UINT8)
352 FMSTR_TSA_MEMBER(fxls8974_allregs_t, reg_addr, FMSTR_TSA_UINT8)
353 FMSTR_TSA_MEMBER(fxls8974_allregs_t, accel, FMSTR_TSA_FLOAT)
354 FMSTR_TSA_MEMBER(fxls8974_allregs_t, accelraw, FMSTR_TSA_SINT16)
355 FMSTR_TSA_MEMBER(fxls8974_allregs_t, sdcd, FMSTR_TSA_UINT8)
356 FMSTR_TSA_MEMBER(fxls8974_allregs_t, temp, FMSTR_TSA_SINT8)
357 FMSTR_TSA_MEMBER(fxls8974_allregs_t, selftest, FMSTR_TSA_SINT16)
358 FMSTR_TSA_MEMBER(fxls8974_allregs_t, dataready_cntr, FMSTR_TSA_UINT8)
359 FMSTR_TSA_MEMBER(fxls8974_allregs_t, timestamp, FMSTR_TSA_UINT32)
360
361 FMSTR_TSA_STRUCT(fxls8974_offset_noise_t)
362 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, offx, FMSTR_TSA_FLOAT)
363 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, offy, FMSTR_TSA_FLOAT)
364 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, offz, FMSTR_TSA_FLOAT)
365 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, rmsx, FMSTR_TSA_FLOAT)
366 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, rmsy, FMSTR_TSA_FLOAT)
367 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, rmsz, FMSTR_TSA_FLOAT)
368 FMSTR_TSA_MEMBER(fxls8974_offset_noise_t, complete_accel_offnoise, FMSTR_TSA_UINT8)
369
370
371 FMSTR_TSA_STRUCT(fxls8974_selftest_t)
372 FMSTR_TSA_MEMBER(fxls8974_selftest_t, x_stoc, FMSTR_TSA_SINT16)
373 FMSTR_TSA_MEMBER(fxls8974_selftest_t, y_stoc, FMSTR_TSA_SINT16)
374 FMSTR_TSA_MEMBER(fxls8974_selftest_t, z_stoc, FMSTR_TSA_SINT16)
375 FMSTR_TSA_MEMBER(fxls8974_selftest_t, x_stof, FMSTR_TSA_SINT16)
376 FMSTR_TSA_MEMBER(fxls8974_selftest_t, y_stof, FMSTR_TSA_SINT16)
377 FMSTR_TSA_MEMBER(fxls8974_selftest_t, z_stof, FMSTR_TSA_SINT16)
378 FMSTR_TSA_MEMBER(fxls8974_selftest_t, complete_selftest, FMSTR_TSA_UINT8)
379
380 FMSTR_TSA_RO_VAR(rawData, FMSTR_TSA_USERTYPE(fxls8974_acceldata_t))
381
382 FMSTR_TSA_RW_VAR(registers, FMSTR_TSA_USERTYPE(fxls8974_allregs_t))
383
384 FMSTR_TSA_RO_VAR(offnoise_data, FMSTR_TSA_USERTYPE(fxls8974_offset_noise_t))
385
386 FMSTR_TSA_RO_VAR(selftest, FMSTR_TSA_USERTYPE(fxls8974_selftest_t))
387
388 FMSTR_TSA_TABLE_END()
389
390 FMSTR_TSA_TABLE_LIST_BEGIN()
391 FMSTR_TSA_TABLE(main_table)
392 FMSTR_TSA_TABLE_LIST_END()
393
394 /*!
395 * @brief FreeMASTER recorder initialization
396 */
397 void FRM_Recorder_Init()
398 {
399 /* Do local configuration of additional recorder */
400
401 /* Setup the additional recorder raw buffer */
402 recBuffCfg.addr = recBuffer;
403 recBuffCfg.size = sizeof(recBuffer);
404 recBuffCfg.basePeriod_ns = 0; /* Unknown period */
405 recBuffCfg.name = "FXLS8974 3-Axis Accelerometer Data";
406
407 FMSTR_RecorderCreate(1, &recBuffCfg);
408 }
409
410 /*!
411 * @brief Main function
412 */
413
main(void)414 int main(void)
415 {
416 int32_t status;
417 uint8_t whoami = 0;
418 uint8_t regdata;
419 float sensitivity = ACCEL_4G_SENS;
420
421 ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER; // Now using the shield.h value!!!
422 GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
423 fxls8974_i2c_sensorhandle_t fxls8974Driver;
424
425 /*! Initialize the MCU hardware. */
426 BOARD_InitPins();
427 BOARD_BootClockRUN();
428 BOARD_SystickEnable();
429 BOARD_InitDebugConsole();
430
431 /*! Initialize FXLS8974_INT1 pin used by FRDM board */
432 pGpioDriver->pin_init(&FXLS8974_INT1, GPIO_DIRECTION_IN, NULL, &fxls8974_isr_callback, NULL);
433
434 /*! Initialize RGB LED pin used by FRDM board */
435 pGpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
436
437 /*! FreeMASTER communication layer initialization */
438 //init_freemaster_uart();
439 /* Initialize the USB peripheral clock */
440 SystemCoreClockUpdate();
441 CLOCK_EnableUsbfs0Clock(kCLOCK_UsbSrcIrc48M, 48000000U);
442
443 /* FreeMASTER communication layer initialization */
444 FMSTR_ExampleUsbInit();
445
446 /*! Initialize the I2C driver. */
447 status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
448 if (ARM_DRIVER_OK != status)
449 {
450 return -1;
451 }
452
453 /*! Set the I2C Power mode. */
454 status = I2Cdrv->PowerControl(ARM_POWER_FULL);
455 if (ARM_DRIVER_OK != status)
456 {
457 return -1;
458 }
459
460 /*! Set the I2C bus speed. */
461 status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
462 if (ARM_DRIVER_OK != status)
463 {
464 return -1;
465 }
466
467 /*! Initialize FXLS8974 sensor driver. */
468 status = FXLS8974_I2C_Initialize(&fxls8974Driver, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, FXLS8974_I2C_ADDR,
469 &whoami);
470 if (SENSOR_ERROR_NONE != status)
471 {
472 return status;
473 }
474
475 /*! Set the task to be executed while waiting for I2C transactions to complete. */
476 FXLS8974_I2C_SetIdleTask(&fxls8974Driver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
477
478 /*! Configure the FXLS8974 sensor. */
479 status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974ConfigNormal);
480 if (SENSOR_ERROR_NONE != status)
481 {
482 return status;
483 }
484
485 /*! FreeMASTER Driver Initialization */
486 FMSTR_Init();
487
488 /*! FreeMASTER Recorder Initialization */
489 FRM_Recorder_Init();
490
491 /*! Open FreeMASTER Pipe and get a Pipe handle */
492 FMSTR_HPIPE hpipe = FMSTR_PipeOpen(3, NULL, (FMSTR_ADDR)pipe3_rxb, sizeof(pipe3_rxb), (FMSTR_ADDR)pipe3_txb, sizeof(pipe3_txb),
493 FMSTR_PIPE_TYPE_ANSI_TERMINAL, "streaming");
494
495 /*! Initialize trigger flags */
496 registers.toggle = 1;
497 registers.trigger = 0;
498 registers.read_trigger = 0;
499 registers.read_value = 0;
500 registers.readall_trigger = 0;
501 registers.trigger_accel_offnoise=0;
502 registers.trigger_selftest=0;
503 registers.dataready_cntr = 0;
504 registers.selftest[0]=0;
505 registers.selftest[1]=0;
506 registers.selftest[2]=0;
507 registers.timestamp = 0;
508
509 for(int i = 0; i < FXLS8974_NUM_REGISTERS; i++)
510 {
511 registers.readall_value[i] = 0;
512 }
513
514 for (;;) /* Forever loop */
515 {
516
517 /*! Calling Recorder#0 in execution loop for generic high-speed variables sampling. */
518 FMSTR_Recorder(0);
519
520 /*! FreeMASTER host communication polling mode */
521 FMSTR_Poll();
522
523 /*! Check for any write register trigger from Host */
524 if (registers.trigger == 1)
525 {
526 /*! Apply Register Write */
527 status = apply_register_write(fxls8974Driver, registers.offset, registers.value);
528 if (SENSOR_ERROR_NONE != status)
529 {
530 return status;
531 }
532 registers.trigger = 0;
533 /*! Update drop down menu selection based on updated register write */
534 update_dropdown_selection(®isters, FXLS8974_REG_WRITE);
535 }
536
537 /*! Check for any read register trigger from Host */
538 if (registers.read_trigger == 1)
539 {
540 /*! Apply Register Write */
541 status = apply_register_read(fxls8974Driver, registers.read_offset, &(registers.read_value));
542 if (SENSOR_ERROR_NONE != status)
543 {
544 return status;
545 }
546 registers.read_trigger = 0;
547 /*! Update drop down menu selection based on updated register read */
548 update_dropdown_selection(®isters, FXLS8974_REG_READ);
549 }
550
551 /*! Check for any read all register trigger from Host */
552 if (registers.readall_trigger == 1)
553 {
554 /*! Apply Register Write */
555 status = apply_register_readall(fxls8974Driver);
556 if (SENSOR_ERROR_NONE != status)
557 {
558 return status;
559 }
560 registers.readall_trigger = 0;
561 registers.readall_size = FXLS8974_NUM_REGISTERS;
562 /*! Update drop down menu selection based on updated all register read */
563 update_dropdown_selection(®isters, FXLS8974_ALLREG_READ);
564 }
565
566 /*! Wait for data ready interrupt from the FXLS8974. */
567 if (false == bFxls8974IntFlag)
568 { /* Loop, if new sample is not available. */
569 SMC_SetPowerModeWait(SMC);
570 continue;
571 }
572 else
573 { /*! Clear the data ready flag, it will be set again by the ISR. */
574 bFxls8974IntFlag = false;
575 pGpioDriver->toggle_pin(&GREEN_LED);
576 }
577
578 /*! Calling Recorder#1 for sampling sensor data when we get sensor data ready interrupt based on ODR. */
579 FMSTR_Recorder(1);
580
581 /*! Read new raw sensor data from the FXLS8974. */
582 status = FXLS8974_I2C_ReadData(&fxls8974Driver, FXLS8974_ALL_REG_READ, registers.reg_addr);
583 if (ARM_DRIVER_OK != status)
584 {
585 return -1;
586 }
587
588 /* Update timestamp from Systick framework. */
589 registers.timestamp +=BOARD_SystickElapsedTime_us(&gSystick);
590
591 /*! Increment data ready counter and check for rollover */
592 registers.dataready_cntr++;
593 if(MAX8BITSTORAGE == registers.dataready_cntr)
594 {
595 registers.dataready_cntr = 0;
596 }
597
598 registers.temp = registers.reg_addr[1]+25;
599 registers.sdcd = (registers.reg_addr[0] & 0x10)>>4;
600
601 /*! Convert the raw sensor data to signed 16-bit container for display to the debug port. */
602 rawData.accel[0] = (int16_t)(((int16_t)(((int16_t)registers.reg_addr[3] << 8) | registers.reg_addr[2])));
603 rawData.accel[1] = (int16_t)(((int16_t)(((int16_t)registers.reg_addr[5] << 8) | registers.reg_addr[4])));
604 rawData.accel[2] = (int16_t)(((int16_t)(((int16_t)registers.reg_addr[7] << 8) | registers.reg_addr[6])));
605
606 registers.accelraw[0] = rawData.accel[0];
607 registers.accelraw[1] = rawData.accel[1];
608 registers.accelraw[2] = rawData.accel[2];
609
610 /*! Add data log into Pipe TX */
611 FMSTR_PipePrintf(hpipe, "%d\t%d\t%d\t%d\t%d\n", registers.timestamp, registers.dataready_cntr, registers.accelraw[0], registers.accelraw[1], registers.accelraw[2]);
612
613 status = FXLS8974_I2C_ReadData(&fxls8974Driver, cFXLS8974_whoami, (uint8_t *)®isters.reg_addr[13]);
614
615 /*! Check the FS and apply sensitivity */
616 status = FXLS8974_I2C_ReadData(&fxls8974Driver, cFXLS8974_fs_src, ®data);
617 if ((regdata & FXLS8974_SENS_CONFIG1_FSR_MASK) == 2)
618 {
619 sensitivity = ACCEL_4G_SENS;
620 }
621 else if ((regdata & FXLS8974_SENS_CONFIG1_FSR_MASK) == 4)
622 {
623 sensitivity = ACCEL_8G_SENS;
624 }
625 else if ((regdata & FXLS8974_SENS_CONFIG1_FSR_MASK) == 6)
626 {
627 sensitivity = ACCEL_16G_SENS;
628 }
629 else
630 {
631 sensitivity = ACCEL_2G_SENS;
632 }
633
634 /*! Convert raw values to Gs */
635 registers.accel[0] = (float) (rawData.accel[0] * sensitivity);
636 registers.accel[1] = (float) (rawData.accel[1] * sensitivity);
637 registers.accel[2] = (float) (rawData.accel[2] * sensitivity);
638
639 if (prev_toggle != registers.toggle)
640 {
641 pGpioDriver->toggle_pin(&GREEN_LED);
642 prev_toggle = registers.toggle;
643 }
644
645 /*! Call offset and noise calculation function for FXLS8974 */
646 if (registers.trigger_accel_offnoise == 1)
647 {
648 accel_off_noise(&(rawData), &(offnoise_data), sensitivity);
649 if (offnoise_data.complete_accel_offnoise == 1)
650 {
651 registers.trigger_accel_offnoise = 0;
652 }
653 }
654
655 /*! Call self-test function */
656 if (registers.trigger_selftest == 1)
657 {
658 perform_selftest(fxls8974Driver, &selftest);
659 if (selftest.complete_selftest == 1)
660 {
661 registers.trigger_selftest = 0;
662
663 /*! Re-Configure the FXLS8974 sensor to default configuration */
664 status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974ConfigNormal);
665 if (SENSOR_ERROR_NONE != status)
666 {
667 return status;
668 }
669 }
670 }
671
672 }
673 }
674
675
676 /*!
677 * @brief Service register write trigger from Host
678 */
apply_register_write(fxls8974_i2c_sensorhandle_t fxls8974Driver,uint8_t offset,uint8_t value)679 int32_t apply_register_write(fxls8974_i2c_sensorhandle_t fxls8974Driver, uint8_t offset, uint8_t value)
680 {
681 int32_t status;
682
683 if (offset > FXLS8974_NUM_REGISTERS)
684 {
685 return SENSOR_ERROR_INVALID_PARAM;
686 }
687
688 registerwritelist_t fxls8974_register_write[] = {
689 /*! Set register offset with provided value */
690 {offset, value, 0},
691 __END_WRITE_DATA__};
692
693 status = FXLS8974_I2C_Configure(&fxls8974Driver, fxls8974_register_write);
694 if (SENSOR_ERROR_NONE != status)
695 {
696 return SENSOR_ERROR_WRITE;
697 }
698
699 return SENSOR_ERROR_NONE;
700 }
701
702 /*!
703 * @brief Service register read trigger from Host
704 */
apply_register_read(fxls8974_i2c_sensorhandle_t fxls8974Driver,uint8_t read_offset,uint8_t * read_value)705 int32_t apply_register_read(fxls8974_i2c_sensorhandle_t fxls8974Driver, uint8_t read_offset, uint8_t *read_value)
706 {
707 int32_t status;
708
709 if (read_offset > FXLS8974_NUM_REGISTERS)
710 {
711 return SENSOR_ERROR_INVALID_PARAM;
712 }
713
714 registerreadlist_t fxls8974_register_read[] = {
715 /*! Set register offset with provided value */
716 {.readFrom = read_offset, .numBytes = 1}, __END_READ_DATA__};
717
718 status = FXLS8974_I2C_ReadData(&fxls8974Driver, fxls8974_register_read, read_value);
719 if (SENSOR_ERROR_NONE != status)
720 {
721 return SENSOR_ERROR_WRITE;
722 }
723
724 return SENSOR_ERROR_NONE;
725 }
726
727 /*!
728 * @brief Service register read all trigger from Host
729 */
apply_register_readall(fxls8974_i2c_sensorhandle_t fxls8974Driver)730 int32_t apply_register_readall(fxls8974_i2c_sensorhandle_t fxls8974Driver)
731 {
732 int32_t status;
733
734 for (int reg_offset = FXLS8974_INT_STATUS; reg_offset <= FXLS8974_SELF_TEST_CONFIG2; reg_offset++)
735 {
736 registerreadlist_t fxls8974_register_readall[] = {
737 /*! Set register offset with provided value */
738 {.readFrom = reg_offset, .numBytes = 1}, __END_READ_DATA__};
739
740 status = FXLS8974_I2C_ReadData(&fxls8974Driver, fxls8974_register_readall, &(registers.readall_value[reg_offset]));
741 if (SENSOR_ERROR_NONE != status)
742 {
743 return SENSOR_ERROR_READ;
744 }
745 }
746
747 return SENSOR_ERROR_NONE;
748 }
749
750 /*!
751 * @brief Update drop down selection values based on register write, read or readall.
752 */
update_dropdown_selection(fxls8974_allregs_t * registers,uint8_t caller)753 int32_t update_dropdown_selection(fxls8974_allregs_t *registers, uint8_t caller)
754 {
755
756 int32_t status = SENSOR_ERROR_NONE;
757
758 switch (caller)
759 {
760 case FXLS8974_REG_WRITE:
761
762 /*! Update drop down option based on updated read value */
763 if(FXLS8974_SENS_CONFIG1 == registers->offset) //FS Selection
764 {
765 registers->fs_value = registers->value;
766 }
767 else if (FXLS8974_SENS_CONFIG2 == registers->offset)
768 {
769 registers->mods_value = registers->value;
770 }
771 else if (FXLS8974_SENS_CONFIG3 == registers->offset)
772 {
773 registers->odr_value = registers->value;
774 }
775 break;
776 case FXLS8974_REG_READ: //Called from Register Read
777
778 /*! Update drop down option based on updated read value */
779 if(FXLS8974_SENS_CONFIG1 == registers->read_offset) //FS Selection
780 {
781 registers->fs_value = registers->read_value;
782 }
783 else if (FXLS8974_SENS_CONFIG2 == registers->read_offset)
784 {
785 registers->mods_value = registers->read_value;
786 }
787 else if (FXLS8974_SENS_CONFIG3 == registers->read_offset)
788 {
789 registers->odr_value = registers->read_value;
790 }
791 break;
792 case FXLS8974_ALLREG_READ: //Called from Register ReadAll
793
794 /*! Update drop down option based on updated read values */
795 registers->fs_value = registers->reg_addr[FXLS8974_SENS_CONFIG1];
796 registers->mods_value = registers->reg_addr[FXLS8974_SENS_CONFIG2];
797 registers->odr_value = registers->reg_addr[FXLS8974_SENS_CONFIG3];
798 break;
799 default:
800 status = SENSOR_ERROR_INVALID_PARAM;
801 break;
802 }
803
804 return status;
805
806 }
807
808 /*******************************************************************************
809 * OFFSET NOISE CALCULATION
810 ******************************************************************************/
811
812 /*!
813 * @brief Initialize Offset-Noise Variables
814 */
offset_noise_init(fxls8974_offset_noise_t * offnoiseptr)815 void offset_noise_init(fxls8974_offset_noise_t *offnoiseptr)
816 {
817 offnoiseptr->offx = 0.0;
818 offnoiseptr->offy = 0.0;
819 offnoiseptr->offz = 0.0;
820 offnoiseptr->rmsx = 0.0;
821 offnoiseptr->rmsy = 0.0;
822 offnoiseptr->rmsz = 0.0;
823 offnoiseptr->complete_accel_offnoise = 0;
824 }
825
826
827 /* Calculate Offset & Noise for FXLS8974 */
accel_off_noise(fxls8974_acceldata_t * rawData,fxls8974_offset_noise_t * offnoiseptr,float sens)828 void accel_off_noise(fxls8974_acceldata_t* rawData, fxls8974_offset_noise_t *offnoiseptr, float sens)
829 {
830 uint16_t j;
831 static uint16_t k=0;
832 static uint16_t cntr=0;
833 static float stdx=0;
834 static float stdy=0;
835 static float stdz=0;
836 static float xx[N], yy[N], zz[N];
837 static float xm[N], ym[N], zm[N];
838 static float xsq[N], ysq[N], zsq[N];
839 float am[3];
840 static float sumx=0.0;
841 static float sumy=0.0;
842 static float sumz=0.0;
843
844 /* Init offset noise variables */
845 offset_noise_init(offnoiseptr);
846
847 cntr++;
848
849 /* Store Accel samples and calculate sum for configured N */
850 if(cntr < N)
851 {
852 am[0]=rawData->accel[0]*sens;
853 am[1]=rawData->accel[1]*sens;
854 am[2]=rawData->accel[2]*sens;
855 xx[k]=am[0];
856 yy[k]=am[1];
857 zz[k]=am[2];
858 sumx+=am[0];
859 sumy+=am[1];
860 sumz+=am[2];
861 k+=1;
862 offnoiseptr->complete_accel_offnoise = 0;
863 }
864
865 /* Measure offset and RMS */
866 if(cntr == N)
867 {
868 /* Measure average */
869 sumx=sumx/(N-1);
870 sumy=sumy/(N-1);
871 sumz=sumz/(N-1);
872
873 /* Measure offset */
874 offnoiseptr->offx=0-sumx;
875 offnoiseptr->offy=0-sumy;
876 offnoiseptr->offz=1-sumz;
877
878 /* Measure standard deviation */
879 for(j=0; j<N-1; j++)
880 {
881 xm[j]=xx[j]-sumx;
882 ym[j]=yy[j]-sumy;
883 zm[j]=zz[j]-sumz;
884
885 xsq[j]=(float)pow(xm[j],2);
886 ysq[j]=(float)pow(ym[j],2);
887 zsq[j]=(float)pow(zm[j],2);
888 stdx+=xsq[j];
889 stdy+=ysq[j];
890 stdz+=zsq[j];
891 }
892 stdx=stdx/(N-2);
893 stdy=stdy/(N-2);
894 stdz=stdz/(N-2);
895
896 /* Measure RMS */
897 offnoiseptr->rmsx=(float)pow(stdx,0.5);
898 offnoiseptr->rmsy=(float)pow(stdy,0.5);
899 offnoiseptr->rmsz=(float)pow(stdz,0.5);
900
901 /* Set the completion flag */
902 offnoiseptr->complete_accel_offnoise = 1;
903
904 /* Reset local storage */
905 cntr = k = 0;
906 sumx = sumy = sumz = 0;
907 stdx = stdy = stdz = 0;
908 }
909 }
910
911 /*!
912 * @brief Initialize Offset-Noise Variables
913 */
selftest_init(fxls8974_selftest_t * selftest)914 void selftest_init(fxls8974_selftest_t *selftest)
915 {
916 selftest->x_stoc = 0;
917 selftest->y_stoc = 0;
918 selftest->z_stoc = 0;
919 selftest->x_stof = 0;
920 selftest->y_stof = 0;
921 selftest->z_stof = 0;
922 selftest->complete_selftest = 0;
923 }
924
925
perform_selftest(fxls8974_i2c_sensorhandle_t fxls8974Driver,fxls8974_selftest_t * selftest)926 int32_t perform_selftest(fxls8974_i2c_sensorhandle_t fxls8974Driver, fxls8974_selftest_t *selftest)
927 {
928 int32_t status;
929
930 axis=0;
931
932 /* Initialize self-test parameters */
933 selftest_init(selftest);
934
935 while (axis<6)
936 {
937
938 switch(axis)
939 {
940 case 0:status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974STXP);break;
941 case 1:status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974STXN);break;
942 case 2:status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974STYP);break;
943 case 3:status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974STYN);break;
944 case 4:status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974STZP);break;
945 case 5:status = FXLS8974_I2C_Configure(&fxls8974Driver, cFxls8974STZN);break;
946 default:break;
947 }
948
949 if (ARM_DRIVER_OK != status)
950 {
951 return status;
952 }
953
954 int counter =0;
955 for(counter=0;counter<1;counter++)
956 {
957
958 // In ISR Mode we do not need to check Data Ready Register.
959 // The receipt of interrupt will indicate data is ready.
960 RAW_DATA data_ = {0x00};
961 while(false == bFxls8974IntFlag)
962 {
963
964 }
965
966 /*! Set device to Standby mode. */
967 Register_I2C_Write(&I2C_S_DRIVER,&(fxls8974Driver.deviceInfo),FXLS8974_I2C_ADDR, FXLS8974_SENS_CONFIG1,0x00,0x00,0x00);
968 if (ARM_DRIVER_OK != status)
969 {
970 return SENSOR_ERROR_WRITE;
971 }
972
973
974 bFxls8974IntFlag = false;
975 //pGpioDriver->toggle_pin(&RED_LED);
976
977 /*! Read new raw sensor data from the FXLS8974. */
978 status = FXLS8974_I2C_ReadData(&fxls8974Driver, cFxls8974OutputNormal, &data_.byte_data[0]);
979 if (ARM_DRIVER_OK != status)
980 { /* Read did not work, so loop. */
981 continue;
982 }
983
984 /* store the self-test values for each axis & for each polarity*/
985 switch(axis)
986 {
987 case 0: XSTP[counter]= data_.dat.xdata;break;
988 case 1: XSTN[counter]= data_.dat.xdata;break;
989 case 2: YSTP[counter]= data_.dat.ydata;break;
990 case 3: YSTN[counter]= data_.dat.ydata;break;
991 case 4: ZSTP[counter]= data_.dat.zdata;break;
992 case 5: ZSTN[counter]= data_.dat.zdata;break;
993 default:break;
994 }
995
996 }
997
998 BOARD_DELAY_ms(1000);
999 axis++;
1000 }
1001
1002 /* compute self-test output change*/
1003 selftest->x_stoc=(XSTP[0]-XSTN[0])/2;
1004 selftest->y_stoc=(YSTP[0]-YSTN[0])/2;
1005 selftest->z_stoc=(ZSTP[0]-ZSTN[0])/2;
1006
1007 /* compute self-test offset*/
1008 selftest->x_stof=(XSTP[0]+XSTN[0])/2;
1009 selftest->y_stof=(YSTP[0]+YSTN[0])/2;
1010 selftest->z_stof=(ZSTP[0]+ZSTN[0])/2;
1011
1012 selftest->complete_selftest = 1;
1013 return SENSOR_ERROR_NONE;
1014 }
1015
1016
1017