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