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