1 /*
2 * Copyright 2019 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 /**
9 * @file mma865x_auto-wake-sleep.c
10 * @brief The mma865x_auto-wake-sleep.c file implements the ISSDK MMA865x
11 * sensor example demonstrating configuring MMA8652 Accel and enabling
12 * detection motion detection event.
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 "mma865x_drv.h"
34
35 //-----------------------------------------------------------------------
36 // Macros
37 //-----------------------------------------------------------------------
38 #define MT_FFMT_THS 0x07 /* Motion Threshold Value. */
39 #define MT_FFMT_COUNT 0x00
40 #define ASLP_COUNT 0x14
41
42 //-----------------------------------------------------------------------
43 // Constants
44 //-----------------------------------------------------------------------
45 const registerwritelist_t mma865x_autowake_motiondet_config[] = {
46 /* A_FFMT_CFG to be Raise event flag on measured X & Y-axis acceleration above/below threshold & detect motion */
47 {MMA865x_FF_MT_CFG, MMA865x_FF_MT_CFG_OAE_MOTION | MMA865x_FF_MT_CFG_YEFE_EN | MMA865x_FF_MT_CFG_XEFE_EN,
48 MMA865x_FF_MT_CFG_OAE_MASK | MMA865x_FF_MT_CFG_YEFE_MASK | MMA865x_FF_MT_CFG_XEFE_MASK},
49 /* Set Motion detection threshold. */
50 {MMA865x_FF_MT_THS, MT_FFMT_THS, MMA865x_FF_MT_THS_THS_MASK},
51 /* Set thresholds to be used by the system to start the pulse-event detection procedure */
52 {MMA865x_FF_MT_COUNT, MT_FFMT_COUNT, 0},
53 {MMA865x_ASLP_COUNT, ASLP_COUNT, 0},
54 /* Configure MMA8652 in standby mode, normal read and noise mode, 800Hz ODR and sleep frequency of 1.56Hz */
55 {MMA865x_CTRL_REG1, MMA865x_CTRL_REG1_ACTIVE_STANDBY | MMA865x_CTRL_REG1_F_READ_NORMAL | MMA865x_CTRL_REG1_DR_800HZ | MMA865x_CTRL_REG1_ASLP_RATE_1_56HZ,
56 MMA865x_CTRL_REG1_ACTIVE_MASK | MMA865x_CTRL_REG1_F_READ_MASK | MMA865x_CTRL_REG1_DR_MASK | MMA865x_CTRL_REG1_ASLP_RATE_MASK},
57 /* Configure MMA8652 in low power wake mode and enable auto-sleep. */
58 {MMA865x_CTRL_REG2, MMA865x_CTRL_REG2_MODS_LP | MMA865x_CTRL_REG2_SLPE_EN | MMA865x_CTRL_REG2_SMODS_LP,
59 MMA865x_CTRL_REG2_MODS_MASK | MMA865x_CTRL_REG2_SLPE_MASK | MMA865x_CTRL_REG2_SMODS_MASK},
60 /* Configure INT1/INT2 interrupt logic polarity to Active high and enable motion function in sleep mode. */
61 {MMA865x_CTRL_REG3, MMA865x_CTRL_REG3_IPOL_ACTIVE_HIGH | MMA865x_CTRL_REG3_WAKE_FF_MT_EN,
62 MMA865x_CTRL_REG3_IPOL_MASK | MMA865x_CTRL_REG3_WAKE_FF_MT_MASK},
63 /* Enable FFMT interrupts. */
64 {MMA865x_CTRL_REG4, MMA865x_CTRL_REG4_INT_EN_FF_MT_EN, MMA865x_CTRL_REG4_INT_EN_FF_MT_MASK},
65 {MMA865x_CTRL_REG5, MMA865x_CTRL_REG5_INT_CFG_FF_MT_INT1, MMA865x_CTRL_REG5_INT_CFG_FF_MT_MASK}, /*! INT1 Pin */
66 __END_WRITE_DATA__};
67
68 /*! @brief Read register list for MMA8562 to read SysMode Register. */
69 const registerreadlist_t gMma8562ReadSysMode[] = {{.readFrom = MMA865x_SYSMOD, .numBytes = 1}, __END_READ_DATA__};
70
71 //-----------------------------------------------------------------------
72 // Global Variables
73 //-----------------------------------------------------------------------
74 volatile bool gMma865xIntFlag = false;
75
76 //-----------------------------------------------------------------------
77 // Functions
78 //-----------------------------------------------------------------------
79 /*! -----------------------------------------------------------------------
80 * @brief This is the Sensor ISR implementation.
81 * @details This function sets the flag which indicates if a new sample(s) is available for reading or new
82 * event has occurred.
83 * @param[in] pUserData This is a void pointer to the instance of the user specific data structure for the ISR.
84 * @return void There is no return value.
85 * @constraints None
86 * @reeentrant Yes
87 * -----------------------------------------------------------------------*/
mma865x_isr_callback(void * pUserData)88 void mma865x_isr_callback(void *pUserData)
89 { /*! @brief Set flag to indicate Sensor has detected an event. */
90 gMma865xIntFlag = true;
91 }
92
93 /*! -----------------------------------------------------------------------
94 * @brief This is the The main function implementation.
95 * @details This function invokes board initializes routines, then then brings up the sensor and
96 * finally enters an endless loop to continuously read available samples.
97 * @param[in] void This is no input parameter.
98 * @return void There is no return value.
99 * @constraints None
100 * @reeentrant No
101 * -----------------------------------------------------------------------*/
main(void)102 int main(void)
103 {
104 int32_t status;
105 uint8_t eventStatus = 0;
106 uint8_t wake = 0;
107 uint8_t sleep = 0;
108 uint8_t sleepflag = 1;
109 uint16_t eventDetectionCount = 0;
110
111 ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER; // Now using the shield.h value!!!
112 mma865x_i2c_sensorhandle_t mma865xDriver;
113 GENERIC_DRIVER_GPIO *gpioDriver = &Driver_GPIO_KSDK;
114
115 /*! Initialize the MCU hardware. */
116 BOARD_InitPins();
117 BOARD_BootClockRUN();
118 BOARD_InitDebugConsole();
119
120 PRINTF("\r\n ISSDK MMA865x sensor example demonstration for Auto Wake Sleep feature.\r\n");
121
122 /*! Initialize MMA865x pin used by FRDM board */
123 gpioDriver->pin_init(&MMA8652_INT1, GPIO_DIRECTION_IN, NULL, &mma865x_isr_callback, NULL);
124
125 /*! Initialize RGB LED pin used by FRDM board */
126 gpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
127 /*! Initialize RGB LED pin used by FRDM board */
128 gpioDriver->pin_init(&RED_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
129
130 /*! Initialize the I2C driver. */
131 status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
132 if (ARM_DRIVER_OK != status)
133 {
134 PRINTF("\r\n I2C Initialization Failed\r\n");
135 return -1;
136 }
137
138 /*! Set the I2C Power mode. */
139 status = I2Cdrv->PowerControl(ARM_POWER_FULL);
140 if (ARM_DRIVER_OK != status)
141 {
142 PRINTF("\r\n I2C Power Mode setting Failed\r\n");
143 return -1;
144 }
145
146 /*! Set the I2C bus speed. */
147 status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
148 if (ARM_DRIVER_OK != status)
149 {
150 PRINTF("\r\n I2C Control Mode setting Failed\r\n");
151 return -1;
152 }
153
154 /*! Initialize the MMA865x sensor driver. */
155 status = MMA865x_I2C_Initialize(&mma865xDriver, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, MMA8652_I2C_ADDR,
156 MMA8652_WHOAMI_VALUE);
157 if (SENSOR_ERROR_NONE != status)
158 {
159 PRINTF("\r\n Sensor Initialization Failed\r\n");
160 return -1;
161 }
162 PRINTF("\r\n Successfully Initialized Sensor\r\n");
163
164 /*! Set the task to be executed while waiting for I2C transactions to complete. */
165 MMA865x_I2C_SetIdleTask(&mma865xDriver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
166
167 status = MMA865x_I2C_Configure(&mma865xDriver, mma865x_autowake_motiondet_config);
168
169 if (SENSOR_ERROR_NONE != status)
170 {
171 PRINTF("\r\n MMA865x Sensor Configuration Failed, Err = %d \r\n", status);
172 return -1;
173 }
174 PRINTF("\r\n Successfully Applied MMA865x Sensor Configuration for Auto-Wake-Sleep Mode\r\n\r\n");
175 PRINTF("\r\n MMA865x is now active and detecting sudden motion gesture of lifting up the board... \r\n\r\n");
176
177 for (;;) /* Forever loop */
178 {
179
180 eventStatus = 0;
181
182 status = MMA865x_I2C_ReadData(&mma865xDriver, gMma8562ReadSysMode, &eventStatus);
183 if (ARM_DRIVER_OK != status)
184 {
185 return status;
186 }
187
188 /*! Check whether Motion Interrupt has occurred and event status is Wake mode */
189 if ((eventStatus == MMA865x_SYSMOD_SYSMOD_WAKE))
190 {
191 if (true == gMma865xIntFlag)
192 {
193 if (wake == 1)
194 {
195 /*! Wake Mode Detected. */
196 eventDetectionCount++;
197 PRINTF("\r\n Sensor Detected Motion!!!\r\n");
198 PRINTF("\r\n Waking up MCU on motion detection event\r\n");
199 PRINTF("\r\n Total Motion Detection Events captured = %d\r\n", eventDetectionCount);
200 PRINTF("\r\n Will enter sleep mode automatically on expiry of ASLP Count = ~6sec\r\n");
201 PRINTF("\r\n ==================================================================\r\n\r\n");
202 wake = 0;
203 }
204 gpioDriver->set_pin(&RED_LED);
205 gpioDriver->clr_pin(&GREEN_LED);
206 sleep = 1;
207 }
208 }
209 else
210 {
211 if ((sleep == 1) || (sleepflag == 1))
212 {
213 PRINTF("\r\n No-Motion Detected - ASLP Counter = ~6sec Expired\r\n");
214 PRINTF("\r\n Going to Sleep Mode...\r\n");
215 PRINTF("\r\n Putting MCU in low power sleep\r\n");
216 PRINTF("\r\n ==================================================================\r\n\r\n");
217 sleep = 0;
218 sleepflag = 0;
219 }
220 gpioDriver->set_pin(&GREEN_LED);
221 gpioDriver->clr_pin(&RED_LED);
222 wake = 1;
223 /*! Clear the sensor event interrupt flag, it will be set again by the ISR. */
224 gMma865xIntFlag = false;
225 /*! Put MCU in low-power sleep. */
226 SMC_SetPowerModeWait(SMC);
227 continue;
228 }
229 }
230 }
231