ISSDK  1.8
IoT Sensing Software Development Kit
fxls896xaf_freemaster_usb_demo.c
Go to the documentation of this file.
1 /*
2  * Copyright 2021 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 /**
9  * @file fxls896xaf_freemaster_usb_demo.c
10  * @brief The fxls896xaf_freemaster_usb_demo.c file implements FreeMASTER demo using the ISSDK
11  * FXLS896xAF 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 "fxls896x_drv.h"
38 #include "systick_utils.h"
39 
40 //-----------------------------------------------------------------------
41 // Macros
42 //-----------------------------------------------------------------------
43 #define FXLS896x_NUM_REGISTERS (FXLS896x_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 FXLS896x_DATA_SIZE 6
56 //-----------------------------------------------------------------------
57 // Constants
58 //-----------------------------------------------------------------------
59 /*! @brief Defines the register write list to configure FXLS896x in Interrupt mode. */
61  /*! Set Full-scale range as 4G. */
63  /*! Clear SENS_CONFIG2 */
64  {FXLS896x_SENS_CONFIG2, 0x00, 0x00},
65  /*! Disable Self-Test. */
67  /*! Set Wake Mode ODR Rate as 12.5Hz. */
69  /*! Enable Interrupts for Data Ready Events. */
71  /*! Enable Temperature sensor. */
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},
81 
82 /*! @brief Register settings for Self-Test in X Axis (Positive polarity). */
84  /* Set Self Test Axis. */
89 
90 /*! @brief Register settings for Self-Test in X Axis (Negative polarity). */
92  /* Set Self Test Axis. */
97 
98 /*! @brief Register settings for Self-Test in Y Axis (Positive polarity). */
100  /* Set Self Test Axis. */
105 
106 /*! @brief Register settings for Self-Test in Y Axis (Negative polarity). */
108  /* Set Self Test Axis. */
113 
114 /*! @brief Register settings for Self-Test in Z Axis (Positive polarity). */
116  /* Set Self Test Axis. */
121 
122 /*! @brief Register settings for Self-Test in Z Axis (Negative polarity). */
124  /* Set Self Test Axis. */
129 
130 /*! @brief Address of Raw Accel Data in Normal Mode. */
133 
135  {.readFrom = FXLS896x_WHO_AM_I, .numBytes = 1}, __END_READ_DATA__};
136 
137 /*! @brief Prepare the register read for INT Status Register. */
139  {.readFrom = FXLS896x_INT_STATUS, .numBytes = 1}, __END_READ_DATA__};
140 
141 /*! @brief Prepare the register read for FullScale range Register. */
143  {.readFrom = FXLS896x_SENS_CONFIG1, .numBytes = 1}, __END_READ_DATA__};
144 
145 /*! @brief FXLS896x register list to read all registers */
148 
149 //-----------------------------------------------------------------------
150 // Global Variables
151 //-----------------------------------------------------------------------
152 /*! @brief This structure defines the fxls896x 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[FXLS896x_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[FXLS896x_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;
179 //-----------------------------------------------------------------------
180 /*! @brief This structure defines the fxls896x 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;
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;
203 
204 /*! @brief This structure defines the fxls896x 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)];
217 }RAW_DATA;
218 
219 /*! @brief This structure defines the fxls896x host operation type.*/
221 {
226 
228 
229 /*******************************************************************************
230  * Globals
231  ******************************************************************************/
232 
237 uint8_t prev_toggle = 1;
238 volatile bool bFxls896xIntFlag = 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 
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 FXLS896x interrupt source event.
258  * @details This function implements ISR for FXLS896x INT source.
259  * @param[in] void *.
260  * @return void.
261  */
262 void fxls896x_isr_callback(void *pUserData);
263 /*! @brief Function to apply FXLS896x register write operation.
264  * @details This function apply FXLS896x register write based on write trigger from host.
265  * @param[in] fxls896x_i2c_sensorhandle_t fxls896xDriver, FXLS896x 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  */
271 /*! @brief Function to apply FXLS896x register read operation.
272  * @details This function apply FXLS896x register read based on read trigger from host.
273  * @param[in] fxls896x_i2c_sensorhandle_t fxls896xDriver, FXLS896x 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(fxls896x_i2c_sensorhandle_t fxls896xDriver, uint8_t offset, uint8_t *value);
279 /*! @brief Function to apply FXLS896x register read-all operation.
280  * @details This function apply FXLS896x all-registers read based on read-all trigger from host.
281  * @param[in] fxls896x_i2c_sensorhandle_t fxls896xDriver, FXLS896x sensor I2C handle.
282  * @return returns the status of the operation.
283  */
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] fxls896x_allregs_t *registers, pointer to FXLS896x 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(fxls896x_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] fxls896x_offset_noise_t *offnoiseptr, pointer to FXLS896x offset noise metadata.
295  * @return void.
296  */
297 void offset_noise_init(fxls896x_offset_noise_t *offnoiseptr);
298 /*! @brief Function to measure accelerometer offset noise.
299  * @details This function measures accelerometer offset noise.
300  * @param[in] fxls896x_acceldata_t *rawData, pointer to FXLS896x rawdata metadata.
301  * @param[in/out] fxls896x_offset_noise_t *offnoiseptr, pointer to FXLS896x offset noise metadata.
302  * @param[in] float sens, FXLS896x sensitivity based on FS configuration.
303  * @return void.
304  */
305 void accel_off_noise(fxls896x_acceldata_t* rawData, fxls896x_offset_noise_t *offnoiseptr, float sens);
306 /*! @brief Function to initialize FXLS896x self test metadata.
307  * @details This function initializes FXLS896x self test metadata.
308  * @param[in/out] fxls896x_selftest_t *selftest, pointer to FXLS896x selftest metadata.
309  * @return void.
310  */
311 void selftest_init(fxls896x_selftest_t *selftest);
312 /*! @brief Function to perform FXLS896x self test.
313  * @details This function performs FXLS896x self test.
314  * @param[in] fxls896x_i2c_sensorhandle_t fxls896xDriver, FXLS896x sensor I2C handle.
315  * @param[in/out] fxls896x_selftest_t *selftest, pointer to FXLS896x selftest metadata.
316  * @return returns the status of the operation..
317  */
319 void FRM_Recorder_Init();
320 
321 /*******************************************************************************
322  * Code
323  ******************************************************************************/
324 void fxls896x_isr_callback(void *pUserData)
325 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
326  bFxls896xIntFlag = true;
327 }
328 
329 /* Create TSA table and add output variables. */
330 /*!
331  * @brief Target Side Addressable (TSA) table created for this application.
332  */
334  FMSTR_TSA_STRUCT(fxls896x_acceldata_t)
335 
336  FMSTR_TSA_STRUCT(fxls896x_allregs_t)
337  FMSTR_TSA_MEMBER(fxls896x_allregs_t, offset, FMSTR_TSA_UINT8)
338  FMSTR_TSA_MEMBER(fxls896x_allregs_t, value, FMSTR_TSA_UINT8)
339  FMSTR_TSA_MEMBER(fxls896x_allregs_t, trigger, FMSTR_TSA_UINT8)
340  FMSTR_TSA_MEMBER(fxls896x_allregs_t, read_offset, FMSTR_TSA_UINT8)
341  FMSTR_TSA_MEMBER(fxls896x_allregs_t, read_value, FMSTR_TSA_UINT8)
342  FMSTR_TSA_MEMBER(fxls896x_allregs_t, read_trigger, FMSTR_TSA_UINT8)
343  FMSTR_TSA_MEMBER(fxls896x_allregs_t, readall_value, FMSTR_TSA_UINT8)
344  FMSTR_TSA_MEMBER(fxls896x_allregs_t, readall_size, FMSTR_TSA_UINT8)
345  FMSTR_TSA_MEMBER(fxls896x_allregs_t, readall_trigger, FMSTR_TSA_UINT8)
346  FMSTR_TSA_MEMBER(fxls896x_allregs_t, trigger_accel_offnoise, FMSTR_TSA_UINT8)
347  FMSTR_TSA_MEMBER(fxls896x_allregs_t, trigger_selftest, FMSTR_TSA_UINT8)
348  FMSTR_TSA_MEMBER(fxls896x_allregs_t, fs_value, FMSTR_TSA_UINT8)
349  FMSTR_TSA_MEMBER(fxls896x_allregs_t, mods_value, FMSTR_TSA_UINT8)
350  FMSTR_TSA_MEMBER(fxls896x_allregs_t, odr_value, FMSTR_TSA_UINT8)
351  FMSTR_TSA_MEMBER(fxls896x_allregs_t, toggle, FMSTR_TSA_UINT8)
352  FMSTR_TSA_MEMBER(fxls896x_allregs_t, reg_addr, FMSTR_TSA_UINT8)
353  FMSTR_TSA_MEMBER(fxls896x_allregs_t, accel, FMSTR_TSA_FLOAT)
354  FMSTR_TSA_MEMBER(fxls896x_allregs_t, accelraw, FMSTR_TSA_SINT16)
355  FMSTR_TSA_MEMBER(fxls896x_allregs_t, sdcd, FMSTR_TSA_UINT8)
356  FMSTR_TSA_MEMBER(fxls896x_allregs_t, temp, FMSTR_TSA_SINT8)
357  FMSTR_TSA_MEMBER(fxls896x_allregs_t, selftest, FMSTR_TSA_SINT16)
358  FMSTR_TSA_MEMBER(fxls896x_allregs_t, dataready_cntr, FMSTR_TSA_UINT8)
359  FMSTR_TSA_MEMBER(fxls896x_allregs_t, timestamp, FMSTR_TSA_UINT32)
360 
361  FMSTR_TSA_STRUCT(fxls896x_offset_noise_t)
362  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, offx, FMSTR_TSA_FLOAT)
363  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, offy, FMSTR_TSA_FLOAT)
364  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, offz, FMSTR_TSA_FLOAT)
365  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, rmsx, FMSTR_TSA_FLOAT)
366  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, rmsy, FMSTR_TSA_FLOAT)
367  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, rmsz, FMSTR_TSA_FLOAT)
368  FMSTR_TSA_MEMBER(fxls896x_offset_noise_t, complete_accel_offnoise, FMSTR_TSA_UINT8)
369 
370 
371  FMSTR_TSA_STRUCT(fxls896x_selftest_t)
372  FMSTR_TSA_MEMBER(fxls896x_selftest_t, x_stoc, FMSTR_TSA_SINT16)
373  FMSTR_TSA_MEMBER(fxls896x_selftest_t, y_stoc, FMSTR_TSA_SINT16)
374  FMSTR_TSA_MEMBER(fxls896x_selftest_t, z_stoc, FMSTR_TSA_SINT16)
375  FMSTR_TSA_MEMBER(fxls896x_selftest_t, x_stof, FMSTR_TSA_SINT16)
376  FMSTR_TSA_MEMBER(fxls896x_selftest_t, y_stof, FMSTR_TSA_SINT16)
377  FMSTR_TSA_MEMBER(fxls896x_selftest_t, z_stof, FMSTR_TSA_SINT16)
378  FMSTR_TSA_MEMBER(fxls896x_selftest_t, complete_selftest, FMSTR_TSA_UINT8)
379 
380  FMSTR_TSA_RO_VAR(rawData, FMSTR_TSA_USERTYPE(fxls896x_acceldata_t))
381 
382  FMSTR_TSA_RW_VAR(registers, FMSTR_TSA_USERTYPE(fxls896x_allregs_t))
383 
384  FMSTR_TSA_RO_VAR(offnoise_data, FMSTR_TSA_USERTYPE(fxls896x_offset_noise_t))
385 
386  FMSTR_TSA_RO_VAR(selftest, FMSTR_TSA_USERTYPE(fxls896x_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 = "FXLS896x 3-Axis Accelerometer Data";
406 
407  FMSTR_RecorderCreate(1, &recBuffCfg);
408 }
409 
410 /*!
411  * @brief Main function
412  */
413 
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!!!
424 
425  /*! Initialize the MCU hardware. */
426  BOARD_InitPins();
430 
431  /*! Initialize FXLS896x_INT1 pin used by FRDM board */
432  pGpioDriver->pin_init(&FXLS896x_INT1, GPIO_DIRECTION_IN, NULL, &fxls896x_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 FXLS896x sensor driver. */
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. */
477 
478  /*! Configure the FXLS896x sensor. */
479  status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xConfigNormal);
480  if (SENSOR_ERROR_NONE != status)
481  {
482  return status;
483  }
484 
485  /*! FreeMASTER Driver Initialization */
486  FMSTR_Init();
487 
488  /*! FreeMASTER Recorder Initialization */
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 < FXLS896x_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(fxls896xDriver, 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 */
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(fxls896xDriver, 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 */
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(fxls896xDriver);
556  if (SENSOR_ERROR_NONE != status)
557  {
558  return status;
559  }
560  registers.readall_trigger = 0;
562  /*! Update drop down menu selection based on updated all register read */
564  }
565 
566  /*! Wait for data ready interrupt from the FXLS896x. */
567  if (false == bFxls896xIntFlag)
568  { /* Loop, if new sample is not available. */
570  continue;
571  }
572  else
573  { /*! Clear the data ready flag, it will be set again by the ISR. */
574  bFxls896xIntFlag = 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 FXLS896x. */
582  status = FXLS896x_I2C_ReadData(&fxls896xDriver, FXLS896x_ALL_REG_READ, registers.reg_addr);
583  if (ARM_DRIVER_OK != status)
584  {
585  return -1;
586  }
587 
588  /* Update timestamp from Systick framework. */
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 = FXLS896x_I2C_ReadData(&fxls896xDriver, cFXLS896x_whoami, (uint8_t *)&registers.reg_addr[13]);
614 
615  /*! Check the FS and apply sensitivity */
616  status = FXLS896x_I2C_ReadData(&fxls896xDriver, cFXLS896x_fs_src, &regdata);
617  if ((regdata & FXLS896x_SENS_CONFIG1_FSR_MASK) == 2)
618  {
619  sensitivity = ACCEL_4G_SENS;
620  }
621  else if ((regdata & FXLS896x_SENS_CONFIG1_FSR_MASK) == 4)
622  {
623  sensitivity = ACCEL_8G_SENS;
624  }
625  else if ((regdata & FXLS896x_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 FXLS896x */
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(fxls896xDriver, &selftest);
659  if (selftest.complete_selftest == 1)
660  {
661  registers.trigger_selftest = 0;
662 
663  /*! Re-Configure the FXLS896x sensor to default configuration */
664  status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xConfigNormal);
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  */
679 int32_t apply_register_write(fxls896x_i2c_sensorhandle_t fxls896xDriver, uint8_t offset, uint8_t value)
680 {
681  int32_t status;
682 
683  if (offset > FXLS896x_NUM_REGISTERS)
684  {
686  }
687 
688  registerwritelist_t fxls896x_register_write[] = {
689  /*! Set register offset with provided value */
690  {offset, value, 0},
692 
693  status = FXLS896x_I2C_Configure(&fxls896xDriver, fxls896x_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  */
705 int32_t apply_register_read(fxls896x_i2c_sensorhandle_t fxls896xDriver, uint8_t read_offset, uint8_t *read_value)
706 {
707  int32_t status;
708 
709  if (read_offset > FXLS896x_NUM_REGISTERS)
710  {
712  }
713 
714  registerreadlist_t fxls896x_register_read[] = {
715  /*! Set register offset with provided value */
716  {.readFrom = read_offset, .numBytes = 1}, __END_READ_DATA__};
717 
718  status = FXLS896x_I2C_ReadData(&fxls896xDriver, fxls896x_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  */
731 {
732  int32_t status;
733 
734  for (int reg_offset = FXLS896x_INT_STATUS; reg_offset <= FXLS896x_SELF_TEST_CONFIG2; reg_offset++)
735  {
736  registerreadlist_t fxls896x_register_readall[] = {
737  /*! Set register offset with provided value */
738  {.readFrom = reg_offset, .numBytes = 1}, __END_READ_DATA__};
739 
740  status = FXLS896x_I2C_ReadData(&fxls896xDriver, fxls896x_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  */
754 {
755 
757 
758  switch (caller)
759  {
760  case FXLS896x_REG_WRITE:
761 
762  /*! Update drop down option based on updated read value */
763  if(FXLS896x_SENS_CONFIG1 == registers->offset) //FS Selection
764  {
765  registers->fs_value = registers->value;
766  }
767  else if (FXLS896x_SENS_CONFIG2 == registers->offset)
768  {
769  registers->mods_value = registers->value;
770  }
771  else if (FXLS896x_SENS_CONFIG3 == registers->offset)
772  {
773  registers->odr_value = registers->value;
774  }
775  break;
776  case FXLS896x_REG_READ: //Called from Register Read
777 
778  /*! Update drop down option based on updated read value */
779  if(FXLS896x_SENS_CONFIG1 == registers->read_offset) //FS Selection
780  {
781  registers->fs_value = registers->read_value;
782  }
783  else if (FXLS896x_SENS_CONFIG2 == registers->read_offset)
784  {
785  registers->mods_value = registers->read_value;
786  }
787  else if (FXLS896x_SENS_CONFIG3 == registers->read_offset)
788  {
789  registers->odr_value = registers->read_value;
790  }
791  break;
792  case FXLS896x_ALLREG_READ: //Called from Register ReadAll
793 
794  /*! Update drop down option based on updated read values */
795  registers->fs_value = registers->reg_addr[FXLS896x_SENS_CONFIG1];
796  registers->mods_value = registers->reg_addr[FXLS896x_SENS_CONFIG2];
797  registers->odr_value = registers->reg_addr[FXLS896x_SENS_CONFIG3];
798  break;
799  default:
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  */
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 FXLS896x */
828 void accel_off_noise(fxls896x_acceldata_t* rawData, fxls896x_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  */
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 
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 = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xSTXP);break;
941  case 1:status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xSTXN);break;
942  case 2:status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xSTYP);break;
943  case 3:status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xSTYN);break;
944  case 4:status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xSTZP);break;
945  case 5:status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xSTZN);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 == bFxls896xIntFlag)
962  {
963 
964  }
965 
966  /*! Set device to Standby mode. */
968  if (ARM_DRIVER_OK != status)
969  {
970  return SENSOR_ERROR_WRITE;
971  }
972 
973 
974  bFxls896xIntFlag = false;
975  //pGpioDriver->toggle_pin(&RED_LED);
976 
977  /*! Read new raw sensor data from the FXLS896x. */
978  status = FXLS896x_I2C_ReadData(&fxls896xDriver, cFxls896xOutputNormal, &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 
The fxls896x_drv.h file describes the FXLS8964/67AF driver interface and structures.
#define FXLS896x_SENS_CONFIG2_ANIC_TEMP_EN
Definition: fxls896x.h:521
This structure defines the Write command List.
Definition: sensor_drv.h:68
#define FXLS896x_SENS_CONFIG1_FSR_4G
Definition: fxls896x.h:455
void FRM_Recorder_Init()
#define FXLS896x_SENS_CONFIG3_WAKE_ODR_12_5HZ
Definition: fxls896x.h:565
const registerwritelist_t cFxls896xSTYP[]
Register settings for Self-Test in Y Axis (Positive polarity).
#define FXLS896x_I2C_ADDR
const registerwritelist_t cFxls896xSTXP[]
Register settings for Self-Test in X Axis (Positive polarity).
status_t SMC_SetPowerModeVlpr(void *arg)
Configures the system to VLPR power mode. API name used from Kinetis family to maintain compatibility...
Definition: lpc54114.c:169
#define ACCEL_4G_SENS
#define FXLS896x_DATA_SIZE
int32_t Register_I2C_Write(ARM_DRIVER_I2C *pCommDrv, registerDeviceInfo_t *devInfo, uint16_t slaveAddress, uint8_t offset, uint8_t value, uint8_t mask, bool repeatedStart)
The interface function to write a sensor register.
This structure defines the fxls896x all registers metadata.
int16_t ZSTN[2]
#define FXLS896x_SENS_CONFIG1_ST_POL_POSITIVE
Definition: fxls896x.h:447
#define ACCEL_2G_SENS
void BOARD_DELAY_ms(uint32_t delay_ms)
Function to insert delays.
Definition: systick_utils.c:81
int32_t apply_register_write(fxls896x_i2c_sensorhandle_t fxls896xDriver, uint8_t offset, uint8_t value)
Function to apply FXLS896x register write operation.
fxls896x_offset_noise_t offnoise_data
int32_t FXLS896x_I2C_Initialize(fxls896x_i2c_sensorhandle_t *pSensorHandle, ARM_DRIVER_I2C *pBus, uint8_t index, uint16_t sAddress, uint8_t *whoami)
The interface function to initialize the sensor.
Definition: fxls896x_drv.c:239
Access structure of the GPIO Driver.
Definition: Driver_GPIO.h:38
registerDeviceInfo_t deviceInfo
Definition: fxls896x_drv.h:45
#define SMC
Definition: lpc54114.h:118
const registerreadlist_t cFXLS896x_fs_src[]
Prepare the register read for FullScale range Register.
int32_t apply_register_readall(fxls896x_i2c_sensorhandle_t fxls896xDriver)
Function to apply FXLS896x register read-all operation.
#define FXLS896x_SENS_CONFIG1_ST_AXIS_SEL_MASK
Definition: fxls896x.h:432
fxls896x_acceldata_t rawData
#define FXLS896x_SENS_CONFIG1_FSR_16G
Definition: fxls896x.h:459
int32_t perform_selftest(fxls896x_i2c_sensorhandle_t fxls896xDriver, fxls896x_selftest_t *selftest)
Function to perform FXLS896x self test.
This structure defines variables to compute self-test output change (STOC) and self-test offset (STOF...
#define __END_WRITE_DATA__
Definition: sensor_drv.h:45
typedef int32_t(DATA_FORMAT_Append_t))(void *pData
The interface function to append the data on the formated stream.
const registerreadlist_t FXLS896x_ALL_REG_READ[]
FXLS896x register list to read all registers.
FMSTR_TSA_TABLE_BEGIN(main_table)
Target Side Addressable (TSA) table created for this application.
fxls896x_selftest_t selftest
This structure defines the fxls896x raw data buffer.
Definition: fxls896x_drv.h:52
#define FXLS896x_SENS_CONFIG1_ST_POL_MASK
Definition: fxls896x.h:429
#define I2C_S_SIGNAL_EVENT
Definition: issdk_hal.h:34
#define I2C_S_DRIVER
Definition: issdk_hal.h:33
void fxls896x_isr_callback(void *pUserData)
ISR for FXLS896x interrupt source event.
#define FXLS896x_SENS_CONFIG1_ST_AXIS_SEL_EN_Z
Definition: fxls896x.h:446
const registerwritelist_t cFxls896xSTXN[]
Register settings for Self-Test in X Axis (Negative polarity).
const registerreadlist_t cFxls896xOutputNormal[]
Address of Raw Accel Data in Normal Mode.
#define FXLS896x_SENS_CONFIG1_ST_POL_NEGATIVE
Definition: fxls896x.h:449
const registerreadlist_t cFXLS896x_int_src[]
Prepare the register read for INT Status Register.
#define ACCEL_16G_SENS
#define BOARD_BootClockRUN
Definition: clock_config.h:19
This structure defines the fxls896x offset and noise calculation parameters.
const registerwritelist_t cFxls896xSTZP[]
Register settings for Self-Test in Z Axis (Positive polarity).
void(* registeridlefunction_t)(void *userParam)
This is the register idle function type.
Definition: sensor_drv.h:97
#define FXLS896x_SENS_CONFIG1_FSR_MASK
Definition: fxls896x.h:423
void accel_off_noise(fxls896x_acceldata_t *rawData, fxls896x_offset_noise_t *offnoiseptr, float sens)
Function to measure accelerometer offset noise.
fxls896x_operation_type
This structure defines the fxls8962 host operation type.
GENERIC_DRIVER_GPIO Driver_GPIO_KSDK
Definition: gpio_driver.c:177
GENERIC_DRIVER_GPIO * pGpioDriver
#define FXLS896x_INT_EN_DRDY_EN_MASK
Definition: fxls896x.h:850
This defines the sensor specific information for I2C.
Definition: fxls896x_drv.h:43
uint32_t BOARD_SystickElapsedTime_us(int32_t *pStart)
Function to compute the Elapsed Time.
Definition: systick_utils.c:64
int16_t XSTP[2]
FMSTR_REC_CFG recCfg
#define FXLS896x_SENS_CONFIG1_ST_AXIS_SEL_EN_Y
Definition: fxls896x.h:445
int16_t YSTP[2]
int32_t FXLS896x_I2C_Configure(fxls896x_i2c_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
The interface function to configure he sensor.
Definition: fxls896x_drv.c:285
#define __END_READ_DATA__
Definition: sensor_drv.h:51
int main(void)
Main function.
int32_t FXLS896x_I2C_ReadData(fxls896x_i2c_sensorhandle_t *pSensorHandle, const registerreadlist_t *pReadList, uint8_t *pBuffer)
The interface function to read the sensor data.
Definition: fxls896x_drv.c:330
const registerwritelist_t cFxls896xSTYN[]
Register settings for Self-Test in Y Axis (Negative polarity).
#define FXLS896x_SENS_CONFIG2_ANIC_TEMP_MASK
Definition: fxls896x.h:496
int16_t ZSTP[2]
ARM_DRIVER_I2C * I2Cdrv
void selftest_init(fxls896x_selftest_t *selftest)
Function to initialize FXLS896x self test metadata.
int16_t YSTN[2]
int32_t apply_register_read(fxls896x_i2c_sensorhandle_t fxls896xDriver, uint8_t offset, uint8_t *value)
Function to apply FXLS896x register read operation.
uint16_t readFrom
Definition: sensor_drv.h:80
fxls896x_i2c_sensorhandle_t fxls896xDriver
void FXLS896x_I2C_SetIdleTask(fxls896x_i2c_sensorhandle_t *pSensorHandle, registeridlefunction_t idleTask, void *userParam)
: The interface function to set the I2C Idle Task.
Definition: fxls896x_drv.c:277
const registerreadlist_t cFXLS896x_whoami[]
void(* toggle_pin)(pinID_t aPinId)
Definition: Driver_GPIO.h:48
int32_t update_dropdown_selection(fxls896x_allregs_t *registers, uint8_t caller)
Function to update dropdown selection.
#define FXLS896x_NUM_REGISTERS
int16_t XSTN[2]
uint8_t reg_addr[FXLS896x_NUM_REGISTERS]
void BOARD_SystickEnable(void)
Function to enable systicks framework.
Definition: systick_utils.c:35
status_t SMC_SetPowerModeWait(void *arg)
Configures the system to WAIT power mode. API name used from Kinetis family to maintain compatibility...
Definition: lpc54114.c:155
void offset_noise_init(fxls896x_offset_noise_t *offnoiseptr)
Function to initialize offset noise measurement.
void(* pin_init)(pinID_t aPinId, gpio_direction_t dir, void *apPinConfig, gpio_isr_handler_t aIsrHandler, void *apUserData)
Definition: Driver_GPIO.h:41
This structure defines the Read command List.
Definition: sensor_drv.h:78
ARM Systick Utilities.
FMSTR_REC_BUFF recBuffCfg
#define FXLS896x_INT1
gpioHandleKSDK_t GREEN_LED
Definition: frdm_k64f.c:188
#define I2C_S_DEVICE_INDEX
Definition: issdk_hal.h:35
volatile bool bFxls896xIntFlag
union rawdata RAW_DATA
#define ACCEL_8G_SENS
const registerwritelist_t cFxls896xConfigNormal[]
Defines the register write list to configure FXLS896x in Interrupt mode.
fxls896x_allregs_t registers
void BOARD_InitDebugConsole(void)
Definition: board.c:15
#define MAX8BITSTORAGE
#define FXLS896x_SENS_CONFIG1_ST_AXIS_SEL_DISABLED
Definition: fxls896x.h:442
enum fxls896x_operation_type fxls896x_operation_type_t
This structure defines the fxls896x host operation type.
void BOARD_InitPins(void)
Configures pin routing and optionally pin electrical features.
Definition: pin_mux.c:47
#define FXLS896x_SENS_CONFIG1_ST_AXIS_SEL_EN_X
Definition: fxls896x.h:444
const registerwritelist_t cFxls896xSTZN[]
Register settings for Self-Test in Z Axis (Negative polarity).
#define FXLS896x_INT_EN_DRDY_EN_EN
Definition: fxls896x.h:857
#define FXLS896x_SENS_CONFIG3_WAKE_ODR_MASK
Definition: fxls896x.h:551
uint8_t readall_value[FXLS896x_NUM_REGISTERS]
FMSTR_REC_VAR recVar
This structure defines the fxls8962 raw data buffer.
uint8_t byte_data[sizeof(sensor_data)]