1 /*
2 * Copyright 2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /**
9 * @file fxls896x_motion_wakeup.c
10 * @brief The fxls896x_motion_wakeup.c file implements the ISSDK FXLS896xAF I2C sensor driver
11 * example demonstrating motion detection and Auto-Wake/Sleep features.
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
22 //-----------------------------------------------------------------------
23 // ISSDK Includes
24 //-----------------------------------------------------------------------
25 #include "issdk_hal.h"
26 #include "gpio_driver.h"
27 #include "fxls896x_drv.h"
28 #include "systick_utils.h"
29
30 //-----------------------------------------------------------------------
31 // CMSIS Includes
32 //-----------------------------------------------------------------------
33 #include "Driver_I2C.h"
34
35 //-----------------------------------------------------------------------
36 // Macros
37 //-----------------------------------------------------------------------
38 #define FXLS8964_DATA_SIZE 6
39 #define FXLS8964_STANDBY_MODE 0
40 #define FXLS8964_ACTIVE_MODE 1
41 //-----------------------------------------------------------------------
42 // Constants
43 //-----------------------------------------------------------------------
44 /*! @brief Register settings for configuring SDCD-OT for tap-detection and Auto-Wake/Sleep in interrupt mode. */
45 const registerwritelist_t cFxls896xAwsConfig[] = {
46 /* Set Full-scale range as 4G. */
47 {FXLS896x_SENS_CONFIG1, FXLS896x_SENS_CONFIG1_FSR_4G, FXLS896x_SENS_CONFIG1_FSR_MASK},
48 /* Set Wake ODR as 400Hz & Sleep Mode ODR as 6.25Hz. */
49 {FXLS896x_SENS_CONFIG3, FXLS896x_SENS_CONFIG3_WAKE_ODR_400HZ | FXLS896x_SENS_CONFIG3_SLEEP_ODR_6_25HZ, FXLS896x_SENS_CONFIG3_WAKE_ODR_MASK | FXLS896x_SENS_CONFIG3_SLEEP_ODR_MASK},
50 /* Enable SDCD OT for all 3 axes X, Y & Z and within-thresholds event latch disabled. */
51 {FXLS896x_SDCD_CONFIG1, FXLS896x_SDCD_CONFIG1_X_OT_EN_EN | FXLS896x_SDCD_CONFIG1_Y_OT_EN_EN | FXLS896x_SDCD_CONFIG1_Z_OT_EN_EN | FXLS896x_SDCD_CONFIG1_OT_ELE_DIS,
52 FXLS896x_SDCD_CONFIG1_X_OT_EN_MASK | FXLS896x_SDCD_CONFIG1_Y_OT_EN_MASK | FXLS896x_SDCD_CONFIG1_Z_OT_EN_MASK | FXLS896x_SDCD_CONFIG1_OT_ELE_MASK},
53 /* Enabling SDCD and Relative Data (N) � Data (N-1) mode for transient detection */
54 {FXLS896x_SDCD_CONFIG2, FXLS896x_SDCD_CONFIG2_SDCD_EN_EN | FXLS896x_SDCD_CONFIG2_REF_UPDM_SDCD_REF, FXLS896x_SDCD_CONFIG2_SDCD_EN_MASK | FXLS896x_SDCD_CONFIG2_REF_UPDM_MASK},
55 /* Set the SDCD_OT debounce count to 0 */
56 {FXLS896x_SDCD_OT_DBCNT, 0, 0},
57 /* Set the SDCD lower and upper thresholds to +/-100mg*/
58 {FXLS896x_SDCD_LTHS_LSB, 0xCC, 0},
59 {FXLS896x_SDCD_LTHS_MSB, 0xFF, 0},
60 {FXLS896x_SDCD_UTHS_LSB, 0x34, 0},
61 {FXLS896x_SDCD_UTHS_MSB, 0x00, 0},
62 /* Enable SDCD outside of thresholds event Auto-WAKE/SLEEP transition source enable. */
63 {FXLS896x_SENS_CONFIG4, FXLS896x_SENS_CONFIG4_WK_SDCD_OT_EN | FXLS896x_SENS_CONFIG4_INT_POL_ACT_HIGH, FXLS896x_SENS_CONFIG4_WK_SDCD_OT_MASK | FXLS896x_SENS_CONFIG4_INT_POL_MASK},
64 /* Set the ASLP count to 5sec */
65 {FXLS896x_ASLP_COUNT_LSB, 0xD0, 0},
66 {FXLS896x_ASLP_COUNT_MSB, 0x07, 0},
67 /* Enable Interrupts for WAKE mode. */
68 {FXLS896x_INT_EN, FXLS896x_INT_EN_WAKE_OUT_EN_EN, FXLS896x_INT_EN_WAKE_OUT_EN_MASK},
69 {FXLS896x_INT_PIN_SEL, FXLS896x_INT_PIN_SEL_WK_OUT_INT2_DIS, FXLS896x_INT_PIN_SEL_WK_OUT_INT2_MASK},
70 __END_WRITE_DATA__};
71
72 /*! @brief Read register list to read SysMode Register. */
73 const registerreadlist_t cFxls896xReadSysMode[] = {{.readFrom = FXLS896x_SYS_MODE, .numBytes = 1}, __END_READ_DATA__};
74
75 /*! @brief Read register list to read INT_STATUS Register. */
76 const registerreadlist_t cFxls896xReadIntStatus[] = {{.readFrom = FXLS896x_INT_STATUS, .numBytes = 1}, __END_READ_DATA__};
77
78 //-----------------------------------------------------------------------
79 // Global Variables
80 //-----------------------------------------------------------------------
81 volatile bool gFxls896xIntFlag = false;
82
83 ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER;
84 fxls896x_i2c_sensorhandle_t fxls896xDriver;
85 GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
86 //-----------------------------------------------------------------------
87 // Functions
88 //-----------------------------------------------------------------------
89 /*! -----------------------------------------------------------------------
90 * @brief This is the Sensor Data Ready ISR implementation.
91 * @details This function sets the flag which indicates if a new sample(s) is available for reading.
92 * @param[in] pUserData This is a void pointer to the instance of the user specific data structure for the ISR.
93 * @return void There is no return value.
94 * -----------------------------------------------------------------------*/
fxls896x_int_callback(void * pUserData)95 void fxls896x_int_callback(void *pUserData)
96 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
97 gFxls896xIntFlag = true;
98 }
99
100 /*! -----------------------------------------------------------------------
101 * @brief This is the The main function implementation.
102 * @details This function invokes board initializes routines, then then brings up the sensor and
103 * finally enters an endless loop to continuously read available samples.
104 * @param[in] void This is no input parameter.
105 * @return void There is no return value.
106 * -----------------------------------------------------------------------*/
main(void)107 int main(void)
108 {
109 int32_t status;
110 uint8_t whoami;
111 uint8_t intStatus, eventStatus = 0;
112 uint8_t sleeptowake = 0;
113 uint8_t waketosleep = 0;
114 uint8_t firsttransition = 1;
115 uint8_t onetime_modetransition = 1;
116
117 /*! Initialize the MCU hardware. */
118 BOARD_InitPins();
119 BOARD_BootClockRUN();
120 BOARD_SystickEnable();
121 BOARD_InitDebugConsole();
122
123 PRINTF("\r\n ISSDK FXLS896xAF sensor driver example to detect motion event & AWS\r\n");
124
125 /*! Initialize FXLS8964 pin used by FRDM board */
126 pGpioDriver->pin_init(&FXLS896x_INT1, GPIO_DIRECTION_IN, NULL, &fxls896x_int_callback, NULL);
127
128 /*! Initialize RGB LED pin used by FRDM board */
129 pGpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
130
131 /*! Initialize the I2C driver. */
132 status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
133 if (ARM_DRIVER_OK != status)
134 {
135 PRINTF("\r\n I2C Initialization Failed\r\n");
136 return -1;
137 }
138
139 /*! Set the I2C Power mode. */
140 status = I2Cdrv->PowerControl(ARM_POWER_FULL);
141 if (ARM_DRIVER_OK != status)
142 {
143 PRINTF("\r\n I2C Power Mode setting Failed\r\n");
144 return -1;
145 }
146
147 /*! Set the I2C bus speed. */
148 status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
149 if (ARM_DRIVER_OK != status)
150 {
151 PRINTF("\r\n I2C Control Mode setting Failed\r\n");
152 return -1;
153 }
154
155 /*! Initialize FXLS896x sensor driver. */
156 status = FXLS896x_I2C_Initialize(&fxls896xDriver, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, FXLS896x_I2C_ADDR,
157 &whoami);
158 if (ARM_DRIVER_OK != status)
159 {
160 PRINTF("\r\n Sensor Initialization Failed\r\n");
161 return -1;
162 }
163 if ((FXLS8964_WHOAMI_VALUE == whoami) || (FXLS8967_WHOAMI_VALUE == whoami))
164 {
165 PRINTF("\r\n Successfully Initialized Gemini with WHO_AM_I = 0x%X\r\n", whoami);
166 }
167 else if ((FXLS8974_WHOAMI_VALUE == whoami) || (FXLS8968_WHOAMI_VALUE == whoami))
168 {
169 PRINTF("\r\n Successfully Initialized Timandra with WHO_AM_I = 0x%X\r\n", whoami);
170 }
171 else if (FXLS8962_WHOAMI_VALUE == whoami)
172 {
173 PRINTF("\r\n Successfully Initialized Newstein with WHO_AM_I = 0x%X\r\n", whoami);
174 }
175 else
176 {
177 PRINTF("\r\n Bad WHO_AM_I = 0x%X\r\n", whoami);
178 return -1;
179 }
180
181 /*! Set the task to be executed while waiting for I2C transactions to complete. */
182 FXLS896x_I2C_SetIdleTask(&fxls896xDriver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
183
184 /*! Configure the FXLS896x sensor. */
185 status = FXLS896x_I2C_Configure(&fxls896xDriver, cFxls896xAwsConfig);
186 if (SENSOR_ERROR_NONE != status)
187 {
188 PRINTF("\r\n FXLS8964 Sensor Configuration Failed, Err = %d\r\n", status);
189 return -1;
190 }
191 PRINTF("\r\n Successfully Applied FXLS8964 Sensor Configuration\r\n");
192
193 for (;;) /* Forever loop */
194 {
195 eventStatus = 0;
196 /*! Read new raw sensor data from the FXLS8964. */
197 status = FXLS896x_I2C_ReadData(&fxls896xDriver, cFxls896xReadSysMode, &eventStatus);
198 if (ARM_DRIVER_OK != status)
199 {
200 return status;
201 }
202
203 if (eventStatus == FXLS896x_SYS_MODE_SYS_MODE_WAKE)
204 {
205 if (true == gFxls896xIntFlag)
206 {
207 if (sleeptowake == 1)
208 {
209 /*! Wake Mode Detected. */
210 PRINTF("\r\n Motion Detected....\r\n");
211 PRINTF("\r\n Motion Wake Mode Detected....SYSMODE = %d\r\n", eventStatus);
212 PRINTF("\r\n MCU woke-up on sensor motion event\r\n");
213 PRINTF("\r\n Will enter sleep mode after expiration of ASLP counter = ~5sec\r\n\r\n");
214 sleeptowake = 0;
215 }
216 pGpioDriver->set_pin(&RED_LED);
217 pGpioDriver->clr_pin(&GREEN_LED);
218 waketosleep = 1;
219 }
220 }
221 else
222 {
223 if ((waketosleep == 1) || (firsttransition == 1))
224 {
225 if (1 == onetime_modetransition)
226 {
227 onetime_modetransition = 0;
228 }
229
230 status = FXLS896x_I2C_ReadData(&fxls896xDriver, cFxls896xReadIntStatus, &intStatus);
231 if (ARM_DRIVER_OK != status)
232 {
233 return status;
234 }
235 PRINTF("\r\n ASLP counter expired....\r\n");
236 PRINTF("\r\n Going to Sleep Mode....SYSMODE = %d\r\n", eventStatus);
237 PRINTF("\r\n Putting MCU in low power sleep\r\n\r\n");
238 waketosleep = 0;
239 firsttransition = 0;
240 }
241 pGpioDriver->set_pin(&GREEN_LED);
242 pGpioDriver->clr_pin(&RED_LED);
243 sleeptowake = 1;
244 gFxls896xIntFlag = false;
245 SMC_SetPowerModeWait(SMC);
246 continue;
247 }
248 }
249 }
250