1 /*
2 * Copyright (c) 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_orientation_detection.c
11 * @brief The fxls8962_orientation_detection.c file implements the ISSDK FXLS8962 sensor
12 * driver example demonstration for Motion Activated Orientation detection.
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 // CMSIS Includes
25 //-----------------------------------------------------------------------
26 #include "Driver_I2C.h"
27
28 //-----------------------------------------------------------------------
29 // ISSDK Includes
30 //-----------------------------------------------------------------------
31 #include "issdk_hal.h"
32 #include "gpio_driver.h"
33 #include "fxls8962_drv.h"
34 #include "systick_utils.h"
35
36 //-----------------------------------------------------------------------
37 // Macros
38 //-----------------------------------------------------------------------
39 #define MD_SDCD_WT_DBCNT 0x00 /* Debounce count value. */
40 #define OT_SDCD_WT_DBCNT 0x09 /* Debounce count value. */
41 #define SDCD_LTHS_LSB 0xC0 /* Lower Threshold LSB value. */
42 #define SDCD_LTHS_MSB 0x0F /* Lower Threshold MSB value. */
43 #define SDCD_UTHS_LSB 0x40 /* Upper Threshold LSB value. */
44 #define SDCD_UTHS_MSB 0x00 /* Upper Threshold MSB value. */
45
46 //-----------------------------------------------------------------------
47 // Constants
48 //-----------------------------------------------------------------------
49 /*! @brief Register Start Motion Detect Mode Register Write List. */
50 const registerwritelist_t cFxls8962ConfigMotionDetect[] = {
51 /* Set Wake Mode ODR Rate as 0.781Hz. */
52 {FXLS8962_SENS_CONFIG3, FXLS8962_SENS_CONFIG3_WAKE_ODR_0_781HZ, FXLS8962_SENS_CONFIG3_WAKE_ODR_MASK},
53 {FXLS8962_SENS_CONFIG4, FXLS8962_SENS_CONFIG4_DRDY_PUL_DIS, FXLS8962_SENS_CONFIG4_DRDY_PUL_MASK},
54 {FXLS8962_INT_EN, FXLS8962_INT_EN_SDCD_OT_EN_EN, 0},
55 {FXLS8962_ORIENT_CONFIG, FXLS8962_ORIENT_CONFIG_ORIENT_ENABLE_DIS, FXLS8962_ORIENT_CONFIG_ORIENT_ENABLE_MASK},
56 {FXLS8962_SDCD_CONFIG1,
57 FXLS8962_SDCD_CONFIG1_X_OT_EN_EN | FXLS8962_SDCD_CONFIG1_Y_OT_EN_EN | FXLS8962_SDCD_CONFIG1_Z_OT_EN_EN, 0},
58 {FXLS8962_SDCD_CONFIG2, FXLS8962_SDCD_CONFIG2_SDCD_EN_EN | FXLS8962_SDCD_CONFIG2_REF_UPDM_SDCD_REF |
59 FXLS8962_SDCD_CONFIG2_OT_DBCTM_CLEARED | FXLS8962_SDCD_CONFIG2_WT_DBCTM_CLEARED,
60 0},
61 /* Set SDCD Debounce counter value. */
62 {FXLS8962_SDCD_WT_DBCNT, MD_SDCD_WT_DBCNT, 0},
63 /* Set SDCD Lower Threshold LSB value. */
64 {FXLS8962_SDCD_LTHS_LSB, SDCD_LTHS_LSB, 0},
65 /* Set SDCD Lower Threshold MSB value. */
66 {FXLS8962_SDCD_LTHS_MSB, SDCD_LTHS_MSB, 0},
67 /* Set SDCH Upper Threshold LSB value. */
68 {FXLS8962_SDCD_UTHS_LSB, SDCD_UTHS_LSB, 0},
69 /* Set SDCH Upper Threshold MSB value. */
70 {FXLS8962_SDCD_UTHS_MSB, SDCD_UTHS_MSB, 0},
71 __END_WRITE_DATA__};
72
73 /*! @brief Register Start Motion Detect Mode Register Write List. */
74 const registerwritelist_t cFxls8962ConfigOrientDetect[] = {
75 /* Set Wake Mode ODR Rate as 1.563Hz. */
76 {FXLS8962_SENS_CONFIG3, FXLS8962_SENS_CONFIG3_WAKE_ODR_1_563HZ, FXLS8962_SENS_CONFIG3_WAKE_ODR_MASK},
77 /* Pulse Generation Enabled */
78 {FXLS8962_SENS_CONFIG4, FXLS8962_SENS_CONFIG4_DRDY_PUL_EN, FXLS8962_SENS_CONFIG4_DRDY_PUL_MASK},
79 {FXLS8962_INT_EN, FXLS8962_INT_EN_DRDY_EN_EN, 0},
80 {FXLS8962_ORIENT_CONFIG, FXLS8962_ORIENT_CONFIG_ORIENT_ENABLE_EN, FXLS8962_ORIENT_CONFIG_ORIENT_ENABLE_MASK},
81 {FXLS8962_SDCD_CONFIG1, FXLS8962_SDCD_CONFIG1_WT_ELE_EN | FXLS8962_SDCD_CONFIG1_X_WT_EN_EN |
82 FXLS8962_SDCD_CONFIG1_Y_WT_EN_EN | FXLS8962_SDCD_CONFIG1_Z_WT_EN_EN,
83 0},
84 {FXLS8962_SDCD_CONFIG2, FXLS8962_SDCD_CONFIG2_SDCD_EN_EN | FXLS8962_SDCD_CONFIG2_REF_UPDM_SDCD_REF |
85 FXLS8962_SDCD_CONFIG2_OT_DBCTM_CLEARED | FXLS8962_SDCD_CONFIG2_WT_DBCTM_CLEARED,
86 0},
87 /* Set SDCD Debounce counter value. */
88 {FXLS8962_SDCD_WT_DBCNT, OT_SDCD_WT_DBCNT, 0},
89 /* Set SDCD Lower Threshold LSB value. */
90 {FXLS8962_SDCD_LTHS_LSB, SDCD_LTHS_LSB, 0},
91 /* Set SDCD Lower Threshold MSB value. */
92 {FXLS8962_SDCD_LTHS_MSB, SDCD_LTHS_MSB, 0},
93 /* Set SDCH Upper Threshold LSB value. */
94 {FXLS8962_SDCD_UTHS_LSB, SDCD_UTHS_LSB, 0},
95 /* Set SDCH Upper Threshold MSB value. */
96 {FXLS8962_SDCD_UTHS_MSB, SDCD_UTHS_MSB, 0},
97 __END_WRITE_DATA__};
98
99 /*! @brief Address of SDCD Status Register. */
100 const registerreadlist_t cFxls8962SDCDEvent[] = {{.readFrom = FXLS8962_SDCD_INT_SRC2, .numBytes = 1},
101 __END_READ_DATA__};
102
103 const registerreadlist_t cFxls8962OutputOrientStatus[] = {{.readFrom = FXLS8962_ORIENT_STATUS, .numBytes = 1},
104 __END_READ_DATA__};
105
106 //-----------------------------------------------------------------------
107 // Global Variables
108 //-----------------------------------------------------------------------
109 volatile bool gFxls8962EventReady;
110
111 //-----------------------------------------------------------------------
112 // Functions
113 //-----------------------------------------------------------------------
114 /*! -----------------------------------------------------------------------
115 * @brief This is the Sensor Data Ready ISR implementation.
116 * @details This function sets the flag which indicates if a new sample(s) is available for reading.
117 * @param[in] pUserData This is a void pointer to the instance of the user specific data structure for the ISR.
118 * @return void There is no return value.
119 * @constraints None
120 * @reeentrant Yes
121 * -----------------------------------------------------------------------*/
fxls8962_int_callback(void * pUserData)122 void fxls8962_int_callback(void *pUserData)
123 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
124 gFxls8962EventReady = true;
125 }
126
127 /*! -----------------------------------------------------------------------
128 * @brief This is the The main function implementation.
129 * @details This function invokes board initializes routines, then then brings up the sensor and
130 * finally enters an endless loop to continuously read available samples.
131 * @param[in] void This is no input parameter.
132 * @return void There is no return value.
133 * @constraints None
134 * @reeentrant No
135 * -----------------------------------------------------------------------*/
main(void)136 int main(void)
137 {
138 int32_t status;
139 bool motionDetect;
140 uint8_t orientStatus;
141
142 ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER; // Now using the shield.h value!!!
143 fxls8962_i2c_sensorhandle_t fxls8962Driver;
144 GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
145
146 /*! Initialize the MCU hardware. */
147 BOARD_InitPins();
148 BOARD_BootClockRUN();
149 BOARD_SystickEnable();
150 BOARD_InitDebugConsole();
151
152 PRINTF("\r\n ISSDK FXLS8962 sensor driver example for Orientation and Motion Detection.\r\n");
153
154 /*! Initialize FXLS8962 pin used by FRDM board */
155 pGpioDriver->pin_init(&FXLS8962_INT1, GPIO_DIRECTION_IN, NULL, &fxls8962_int_callback, NULL);
156
157 /*! Initialize the I2C driver. */
158 status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
159 if (ARM_DRIVER_OK != status)
160 {
161 PRINTF("\r\n I2C Initialization Failed\r\n");
162 return -1;
163 }
164
165 /*! Set the I2C Power mode. */
166 status = I2Cdrv->PowerControl(ARM_POWER_FULL);
167 if (ARM_DRIVER_OK != status)
168 {
169 PRINTF("\r\n I2C Power Mode setting Failed\r\n");
170 return -1;
171 }
172
173 /*! Set the I2C bus speed. */
174 status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
175 if (ARM_DRIVER_OK != status)
176 {
177 PRINTF("\r\n I2C Control Mode setting Failed\r\n");
178 return -1;
179 }
180
181 /*! Initialize FXLS8962 sensor driver. */
182 status = FXLS8962_I2C_Initialize(&fxls8962Driver, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, FXLS8962_I2C_ADDR,
183 FXLS8962_WHOAMI_VALUE);
184 if (SENSOR_ERROR_NONE != status)
185 {
186 PRINTF("\r\n Sensor Initialization Failed\r\n");
187 return -1;
188 }
189 PRINTF("\r\n Successfully Initiliazed Sensor\r\n");
190
191 /*! Set the task to be executed while waiting for I2C transactions to complete. */
192 FXLS8962_I2C_SetIdleTask(&fxls8962Driver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
193
194 for (;;) /* Forever loop for Motion Detection */
195 {
196 /* Apply FXLS8962 Configuration for Motion Detection. */
197 status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962ConfigMotionDetect);
198 if (SENSOR_ERROR_NONE != status)
199 {
200 PRINTF("\r\n Write FXLS8962 Motion Configuration Failed!\r\n");
201 return -1;
202 }
203
204 motionDetect = true;
205 gFxls8962EventReady = false;
206 PRINTF("\r\n Waiting for Motion | MCU going to Deep Sleep Mode ...\r\n");
207
208 for (;;) /* Loop for Orientation Detection */
209 { /* In ISR Mode we do not need to check Data Ready Register.
210 * The receipt of interrupt will indicate event is ready. */
211 if (false == gFxls8962EventReady)
212 { /* Loop, if new sample is not available. */
213 SMC_SetPowerModeWait(SMC);
214 continue;
215 }
216 else
217 { /*! Clear the data ready flag, it will be set again by the ISR. */
218 gFxls8962EventReady = false;
219 }
220
221 if (motionDetect)
222 { /*! Display that a Motion event has been detected. */
223 PRINTF("\r\n Motion detected ...\r\n");
224
225 /* Apply FXLS8962 Configuration for Orientation Detection. */
226 status = FXLS8962_I2C_Configure(&fxls8962Driver, cFxls8962ConfigOrientDetect);
227 if (SENSOR_ERROR_NONE != status)
228 {
229 PRINTF("\r\n Write FXLS8962 Orientation Configuration Failed!\r\n");
230 return -1;
231 }
232 motionDetect = false;
233 }
234 else
235 { /*! Read the Orientation Status from the FXLS8962. */
236 status = FXLS8962_I2C_ReadData(&fxls8962Driver, cFxls8962OutputOrientStatus, &orientStatus);
237 if (ARM_DRIVER_OK != status)
238 {
239 PRINTF("\r\n Read Orientation Failed!\r\n");
240 return -1;
241 }
242
243 if (((orientStatus & FXLS8962_ORIENT_STATUS_NEW_ORIENT_MASK) ==
244 FXLS8962_ORIENT_STATUS_NEW_ORIENT_CHANGED) &&
245 ((orientStatus & FXLS8962_ORIENT_STATUS_LO_MASK) == FXLS8962_ORIENT_STATUS_LO_NOT_DETECTED))
246 {
247 if ((orientStatus & FXLS8962_ORIENT_STATUS_LAPO_MASK) == FXLS8962_ORIENT_STATUS_LAPO_UP)
248 {
249 PRINTF("\r\n Portrait Up ...\r\n");
250 }
251 if ((orientStatus & FXLS8962_ORIENT_STATUS_LAPO_MASK) == FXLS8962_ORIENT_STATUS_LAPO_DOWN)
252 {
253 PRINTF("\r\n Portrait Down ...\r\n");
254 }
255 if ((orientStatus & FXLS8962_ORIENT_STATUS_LAPO_MASK) == FXLS8962_ORIENT_STATUS_LAPO_RIGHT)
256 {
257 PRINTF("\r\n Landscape Right ...\r\n");
258 }
259 if ((orientStatus & FXLS8962_ORIENT_STATUS_LAPO_MASK) == FXLS8962_ORIENT_STATUS_LAPO_LEFT)
260 {
261 PRINTF("\r\n Landscape Left ...\r\n");
262 }
263 }
264
265 if (((orientStatus & FXLS8962_ORIENT_STATUS_NEW_ORIENT_MASK) ==
266 FXLS8962_ORIENT_STATUS_NEW_ORIENT_CHANGED) &&
267 ((orientStatus & FXLS8962_ORIENT_STATUS_LO_MASK) == FXLS8962_ORIENT_STATUS_LO_DETECTED))
268 {
269 if ((orientStatus & FXLS8962_ORIENT_STATUS_BAFRO_MASK) == FXLS8962_ORIENT_STATUS_BAFRO_FRONT)
270 {
271 PRINTF("\r\n Front Side ...\r\n");
272 }
273 if ((orientStatus & FXLS8962_ORIENT_STATUS_BAFRO_MASK) == FXLS8962_ORIENT_STATUS_BAFRO_BACK)
274 {
275 PRINTF("\r\n Back Side ...\r\n");
276 }
277 }
278
279 status = FXLS8962_I2C_ReadData(&fxls8962Driver, cFxls8962SDCDEvent, &orientStatus);
280 if (ARM_DRIVER_OK != status)
281 {
282 PRINTF("\r\n Read SDCD Failed!\r\n");
283 return -1;
284 }
285 if ((orientStatus & FXLS8962_SDCD_INT_SRC2_WT_EA_MASK) == FXLS8962_SDCD_INT_SRC2_WT_EA_EVENT_YES)
286 {
287 break;
288 }
289 }
290 }
291 }
292 }
293