1 /*
2  * Copyright (c) 2015-2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /**
10  * @file  fxls8962_fifo_spi.c
11  *  @brief The fxls8962_fifo_spi.c file implements the ISSDK FXLS8962 SPI sensor driver
12  *         example demonstration for FIFO Mode.
13  */
14 
15 //-----------------------------------------------------------------------
16 // SDK Includes
17 //-----------------------------------------------------------------------
18 #include "pin_mux.h"
19 #include "clock_config.h"
20 #include "board.h"
21 #include "fsl_debug_console.h"
22 
23 //-----------------------------------------------------------------------
24 // ISSDK Includes
25 //-----------------------------------------------------------------------
26 #include "issdk_hal.h"
27 #include "gpio_driver.h"
28 #include "fxls8962_drv.h"
29 #include "systick_utils.h"
30 
31 //-----------------------------------------------------------------------
32 // CMSIS Includes
33 //-----------------------------------------------------------------------
34 #include "Driver_SPI.h"
35 
36 //-----------------------------------------------------------------------
37 // Macros
38 //-----------------------------------------------------------------------
39 #define FXLS8962_DATA_SIZE (6)
40 #define FXLS8962_FIFO_WMRK_SIZE (16)
41 
42 /*******************************************************************************
43  * Constants
44  ******************************************************************************/
45 /*! @brief Register settings for FIFO (buffered) mode. */
46 const registerwritelist_t cFxls8962ConfigFIFO[] = {
47     /* Set Full-scale range as 2G. */
48     {FXLS8962_SENS_CONFIG1, FXLS8962_SENS_CONFIG1_FSR_2G, FXLS8962_SENS_CONFIG1_FSR_MASK},
49     /* Set Wake Mode ODR Rate as 12.5Hz. */
50     {FXLS8962_SENS_CONFIG3, FXLS8962_SENS_CONFIG3_WAKE_ODR_12_5HZ, FXLS8962_SENS_CONFIG3_WAKE_ODR_MASK},
51     /* Set Buffering Mode as Stop-when-Full.  */
52     {FXLS8962_BUF_CONFIG1, FXLS8962_BUF_CONFIG1_BUF_MODE_STOP_MODE, FXLS8962_BUF_CONFIG1_BUF_MODE_MASK},
53     /* Set FIFO Water Mark. */
54     {FXLS8962_BUF_CONFIG2, FXLS8962_FIFO_WMRK_SIZE, FXLS8962_BUF_CONFIG2_BUF_WMRK_MASK},
55     /* Enable Interrupts for FIFO Watermark Events. */
56     {FXLS8962_INT_EN, FXLS8962_INT_EN_BUF_EN_EN, FXLS8962_INT_EN_BUF_EN_MASK},
57     __END_WRITE_DATA__};
58 
59 /*! @brief Address of Raw Accel Data in FIFO Mode. */
60 const registerreadlist_t cFxls8962OutputFIF0[] = {
61     {.readFrom = FXLS8962_BUF_X_LSB, .numBytes = FXLS8962_DATA_SIZE * FXLS8962_FIFO_WMRK_SIZE}, __END_READ_DATA__};
62 
63 /*******************************************************************************
64  * Global Variables
65  ******************************************************************************/
66 volatile bool gFxls8962DataReady = false;
67 
68 /*******************************************************************************
69  * Code
70  ******************************************************************************/
71 /*!
72  * @brief The Data ready ISR callback function
73  */
fxls8962_int_data_ready_callback(void * pUserData)74 void fxls8962_int_data_ready_callback(void *pUserData)
75 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
76     gFxls8962DataReady = true;
77 }
78 
79 /*!
80  * @brief Main function
81  */
main(void)82 int main(void)
83 {
84     int32_t status;
85     uint8_t i, data[FXLS8962_DATA_SIZE * FXLS8962_FIFO_WMRK_SIZE];
86     fxls8962_acceldata_t rawData;
87 
88     GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
89     ARM_DRIVER_SPI *pSPIdriver = &SPI_S_DRIVER;
90     fxls8962_spi_sensorhandle_t fxls8962Driver;
91 
92     /*! Initialize the MCU hardware. */
93     BOARD_InitPins();
94     BOARD_BootClockRUN();
95     BOARD_SystickEnable();
96     BOARD_InitDebugConsole();
97 
98     PRINTF("\r\n ISSDK FXLS8962 sensor driver example demonstration for SPI with FIFO Mode.\r\n");
99 
100     /*! Initialize FXLS8962 pin used by FRDM board */
101     pGpioDriver->pin_init(&FXLS8962_INT1, GPIO_DIRECTION_IN, NULL, &fxls8962_int_data_ready_callback, NULL);
102 
103     /*! Initialize RGB LED pin used by FRDM board */
104     pGpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
105 
106     /*! Initialize the SPI driver. */
107     status = pSPIdriver->Initialize(SPI_S_SIGNAL_EVENT);
108     if (ARM_DRIVER_OK != status)
109     {
110         PRINTF("\r\n SPI Initialization Failed\r\n");
111         return -1;
112     }
113 
114     /*! Set the SPI Power mode. */
115     status = pSPIdriver->PowerControl(ARM_POWER_FULL);
116     if (ARM_DRIVER_OK != status)
117     {
118         PRINTF("\r\n SPI Power Mode setting Failed\r\n");
119         return -1;
120     }
121 
122     /*! Set the SPI Slave speed. */
123     status = pSPIdriver->Control(ARM_SPI_MODE_MASTER | ARM_SPI_CPOL0_CPHA0, SPI_S_BAUDRATE);
124     if (ARM_DRIVER_OK != status)
125     {
126         PRINTF("\r\n SPI Control Mode setting Failed\r\n");
127         return -1;
128     }
129 
130     /*! Initialize FXLS8962 sensor driver. */
131     status = FXLS8962_SPI_Initialize(&fxls8962Driver, &SPI_S_DRIVER, SPI_S_DEVICE_INDEX, &FXLS8962_CS,
132                                      FXLS8962_WHOAMI_VALUE);
133     if (SENSOR_ERROR_NONE != status)
134     {
135         PRINTF("\r\n FXLS8962 Sensor Initialization Failed\r\n");
136         return -1;
137     }
138     PRINTF("\r\n Successfully Initiliazed FXLS8962 Sensor\r\n");
139 
140     /*!  Set the task to be executed while waiting for SPI transactions to complete. */
141     FXLS8962_SPI_SetIdleTask(&fxls8962Driver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
142 
143     /*! Configure the FXLS8962 sensor. */
144     status = FXLS8962_SPI_Configure(&fxls8962Driver, cFxls8962ConfigFIFO);
145     if (SENSOR_ERROR_NONE != status)
146     {
147         PRINTF("\r\n FXLS8962 Sensor Configuration Failed, Err = %d\r\n", status);
148         return -1;
149     }
150     PRINTF("\r\n Successfully Applied FXLS8962 Sensor Configuration\r\n");
151 
152     gFxls8962DataReady = false;
153     for (;;) /* Forever loop */
154     {        /* In ISR Mode we do not need to check Data Ready Register.
155               * The receipt of interrupt will indicate data is ready. */
156         if (false == gFxls8962DataReady)
157         { /* Loop, if new sample is not available. */
158             SMC_SetPowerModeWait(SMC);
159             continue;
160         }
161         else
162         { /*! Clear the data ready flag, it will be set again by the ISR. */
163             gFxls8962DataReady = false;
164             pGpioDriver->toggle_pin(&GREEN_LED);
165         }
166 
167         /*! Read new raw sensor data from the FXLS8962. */
168         status = FXLS8962_SPI_ReadData(&fxls8962Driver, cFxls8962OutputFIF0, data);
169         if (ARM_DRIVER_OK != status)
170         {
171             PRINTF("\r\n Read Failed. \r\n");
172             return -1;
173         }
174 
175         for (i = 0; i < FXLS8962_FIFO_WMRK_SIZE; i++)
176         { /*! Convert the raw sensor data to signed 16-bit container for display to the debug port. */
177             rawData.accel[0] = ((int16_t)data[i * FXLS8962_DATA_SIZE + 1] << 8) | data[i * FXLS8962_DATA_SIZE + 0];
178             rawData.accel[1] = ((int16_t)data[i * FXLS8962_DATA_SIZE + 3] << 8) | data[i * FXLS8962_DATA_SIZE + 2];
179             rawData.accel[2] = ((int16_t)data[i * FXLS8962_DATA_SIZE + 5] << 8) | data[i * FXLS8962_DATA_SIZE + 4];
180         }
181 
182         /*! Display to the debug port the last sample.
183          *  NOTE: PRINTF is relatively expensive in terms of CPU time, specially when used with-in execution loop. */
184         PRINTF("\r\nX=%5d Y=%5d Z=%5d\r\n", rawData.accel[0], rawData.accel[1], rawData.accel[2]);
185         ASK_USER_TO_RESUME(8); /* Ask for user input after processing 8 FIFOs. */
186     }
187 }
188