1 /*
2  * Copyright (c) 2015 - 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 mma845x_interrupt.c
11 *   @brief The mma845x_interrupt.c file implements the ISSDK MMA845x sensor driver
12 *        example demonstration with Interrupt mode.
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 "mma845x_drv.h"
34 
35 //-----------------------------------------------------------------------
36 // Constants
37 //-----------------------------------------------------------------------
38 /*! Prepare the register write list to configure MMA845x in non-FIFO and ISR mode. */
39 const registerwritelist_t mma845x_Config_Isr[] = {
40     /*! Configure the MMA845x CTRL_REG1 to set mode to STANDBY and odr to 12.5Hz. */
41     {MMA845x_CTRL_REG1, MMA845x_CTRL_REG1_MODE_STANDBY | MMA845x_CTRL_REG1_DR_12DOT5HZ, 0},
42     /*! Configure the MMA845x to disable FIFO */
43     {MMA845x_F_SETUP, MMA845x_F_SETUP_F_MODE_FIFODISABLED, 0},
44     /*! Configure the MMA845x CTRL_REG2 to set the Oversampling mode to High Resolution. */
45     {MMA845x_CTRL_REG2, MMA845x_CTRL_REG2_MODS_HIGHRES, 0},
46     /*! Configure the MMA845x CTRL_REG3 to set the Interrupt polarity to ACTIVE high. */
47     {MMA845x_CTRL_REG3, MMA845x_CTRL_REG3_IPOL_HIGH, 0},
48     /*! Configure the MMA845x CTRL_REG4 to enable the data ready interrupt. */
49     {MMA845x_CTRL_REG4, MMA845x_CTRL_REG4_INT_EN_DRDY_ENABLED, 0},
50     /*! Configure the MMA845x CTRL_REG5 to route Interrupt to INT1 pin. */
51     {MMA845x_CTRL_REG5, MMA845x_CTRL_REG5_INT_CFG_DRDY_INT1, 0},
52     __END_WRITE_DATA__};
53 
54 /*! Prepare the register read list to read the Data Ready Status from MMA845x. */
55 const registerreadlist_t MMA845x_Data_Ready[] = {{.readFrom = MMA845x_STATUS, .numBytes = 1}, __END_READ_DATA__};
56 
57 /*! Prepare the register read list to read the raw Accel data from MMA845x. */
58 const registerreadlist_t mma845x_Output_Values[] = {
59     {.readFrom = MMA845x_OUT_X_MSB, .numBytes = MMA845x_ACCEL_DATA_SIZE}, __END_READ_DATA__};
60 
61 //-----------------------------------------------------------------------
62 // Global Variables
63 //-----------------------------------------------------------------------
64 volatile bool mma845xInterrupt = false;
65 
66 //-----------------------------------------------------------------------
67 // Functions
68 //-----------------------------------------------------------------------
69 /*! -----------------------------------------------------------------------
70  *  @brief       This is the Sensor Data Ready ISR implementation.
71  *  @details     This function sets the flag which indicates if a new sample(s) is available for reading.
72  *  @param[in]   pUserData This is a void pointer to the instance of the user specific data structure for the ISR.
73  *  @return      void  There is no return value.
74  *  @constraints None
75  *  @reeentrant  Yes
76  *  -----------------------------------------------------------------------*/
mma845x_isr(void * pUserData)77 void mma845x_isr(void *pUserData)
78 { /*! @brief Set flag to indicate Sensor has signalled data ready. */
79     mma845xInterrupt = true;
80 }
81 
82 /*! -----------------------------------------------------------------------
83  *  @brief       This is the The main function implementation.
84  *  @details     This function invokes board initializes routines, then then brings up the sensor and
85  *               finally enters an endless loop to continuously read available samples.
86  *  @param[in]   void This is no input parameter.
87  *  @return      void  There is no return value.
88  *  @constraints None
89  *  @reeentrant  No
90  *  -----------------------------------------------------------------------*/
main(void)91 int main(void)
92 {
93     int32_t status;
94     uint8_t data[MMA845x_ACCEL_DATA_SIZE];
95     mma845x_acceldata_t rawData;
96 
97     ARM_DRIVER_I2C *I2Cdrv = &I2C_S_DRIVER; // Now using the shield.h value!!!
98     mma845x_i2c_sensorhandle_t MMA845xdrv;
99     GENERIC_DRIVER_GPIO *gpioDriver = &Driver_GPIO_KSDK;
100 
101     /*! Initialize the MCU hardware. */
102     BOARD_InitPins();
103     BOARD_BootClockRUN();
104     BOARD_InitDebugConsole();
105 
106     PRINTF("\r\n ISSDK MMA845x sensor driver example for interrupt mode.\r\n");
107 
108     /*! Initialize INT1 pin used by FRDM board */
109     gpioDriver->pin_init(&MMA845x_INT1, GPIO_DIRECTION_IN, NULL, &mma845x_isr, NULL);
110     /*! Initialize RGB LED pin used by FRDM board */
111     gpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
112 
113     /*! Initialize the I2C driver. */
114     status = I2Cdrv->Initialize(I2C_S_SIGNAL_EVENT);
115     if (ARM_DRIVER_OK != status)
116     {
117         PRINTF("\r\n I2C Initialization Failed\r\n");
118         return -1;
119     }
120 
121     /*! Set the I2C Power mode. */
122     status = I2Cdrv->PowerControl(ARM_POWER_FULL);
123     if (ARM_DRIVER_OK != status)
124     {
125         PRINTF("\r\n I2C Power Mode setting Failed\r\n");
126         return -1;
127     }
128 
129     /*! Set the I2C bus speed. */
130     status = I2Cdrv->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
131     if (ARM_DRIVER_OK != status)
132     {
133         PRINTF("\r\n I2C Control Mode setting Failed\r\n");
134         return -1;
135     }
136 
137     /*! Initialize the MMA845x sensor driver. */
138     status = MMA845x_I2C_Initialize(&MMA845xdrv, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, MMA845x_I2C_ADDR,
139                                     MMA8451_WHO_AM_I_WHOAMI_VALUE);
140     if (SENSOR_ERROR_NONE != status)
141     {
142         PRINTF("\r\n Sensor Initialization Failed\r\n");
143         return -1;
144     }
145     PRINTF("\r\n Successfully Initiliazed Sensor\r\n");
146 
147     /*!  Set the task to be executed while waiting for I2C transactions to complete. */
148     MMA845x_I2C_SetIdleTask(&MMA845xdrv, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
149 
150     /*! Configure the MMA845x sensor driver with No FIFO mode. */
151     status = MMA845x_I2C_Configure(&MMA845xdrv, mma845x_Config_Isr);
152     if (SENSOR_ERROR_NONE != status)
153     {
154         PRINTF("\r\n MMA845x Sensor Configuration Failed, Err = %d\r\n", status);
155         return -1;
156     }
157     PRINTF("\r\n Successfully Applied MMA845x Sensor Configuration\r\n");
158 
159     for (;;) /* Forever loop */
160     {        /* In ISR Mode we do not need to check Data Ready Register.
161               * The receipt of interrupt will indicate data is ready. */
162         if (false == mma845xInterrupt)
163         { /* Loop, if new sample is not available. */
164             SMC_SetPowerModeWait(SMC);
165             continue;
166         }
167         else
168         { /*! Clear the data ready flag, it will be set again by the ISR. */
169             mma845xInterrupt = false;
170             gpioDriver->toggle_pin(&GREEN_LED);
171         }
172 
173         /*! Read the raw sensor data from the MMA845x. */
174         status = MMA845x_I2C_ReadData(&MMA845xdrv, mma845x_Output_Values, data);
175         if (ARM_DRIVER_OK != status)
176         {
177             PRINTF("\r\n Read Failed. \r\n");
178             return -1;
179         }
180 
181         /*! Convert the raw sensor data to signed 16-bit container for display to the debug port. */
182         rawData.accel[0] = ((int16_t)data[0] << 8) | data[1];
183         rawData.accel[0] /= 4;
184         rawData.accel[1] = ((int16_t)data[2] << 8) | data[3];
185         rawData.accel[1] /= 4;
186         rawData.accel[2] = ((int16_t)data[4] << 8) | data[5];
187         rawData.accel[2] /= 4;
188 
189         /* NOTE: PRINTF is relatively expensive in terms of CPU time, specially when used with-in execution loop. */
190         PRINTF("\r\n Accel X = %d  Y = %d  Z = %d\r\n", rawData.accel[0], rawData.accel[1], rawData.accel[2]);
191         ASK_USER_TO_RESUME(100); /* Ask for user input after processing 100 samples. */
192     }
193 }
194