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 mma9553_demo.c
11 * @brief The mma9553_demo.c file implements the ISSDK MMA9553L sensor driver
12 * example demonstration as a Accelerometer in I2C Mode.
13 */
14
15 /* SDK Includes */
16 #include "board.h"
17 #include "pin_mux.h"
18 #include "fsl_lptmr.h"
19 #include "clock_config.h"
20
21 /* CMSIS Includes */
22 #include "Driver_I2C.h"
23
24 /* ISSDK Includes */
25 #include "issdk_hal.h"
26 #include "gpio_driver.h"
27 #include "mma9553_drv.h"
28 #include "host_io_uart.h"
29 #include "systick_utils.h"
30 #include "auto_detection_service.h"
31
32 /*******************************************************************************
33 * Macros
34 ******************************************************************************/
35 #define SAMPLING_RATE_ms (100) /* Timeout for the ODR Timer. */
36 #define MMA9553_ACCEL_DATA_SIZE (6) /* 2 byte X,Y,Z Axis Data each. */
37 #define mma9553_en_callback LPTMR0_IRQHandler /* Timer timeout Callback. */
38
39 #define MMA9553_STREAM_DATA_SIZE (10)
40
41 /*! @brief Unique Name for this application which should match the target GUI pkg name. */
42 #define APPLICATION_NAME "MMA9553 Pedometer Demo"
43 /*! @brief Version to distinguish between instances the same application based on target Shield and updates. */
44 #define APPLICATION_VERSION "2.5"
45
46 /*******************************************************************************
47 * Constants
48 ******************************************************************************/
49 /*! Prepare the register write list to configure MMA9553L in 30Hz Mode. */
50 const registercommandlist_t cMma9553Config30Hz[] = {
51 {SetFSRange_2g, 0, sizeof(SetFSRange_2g)}, /* Set FS Range 2G */
52 {SetSampleRate_30Hz, 0, sizeof(SetSampleRate_30Hz)}, /* Set Sensor Sampling Rate 30Hz */
53 {SetAFEPriority_for30Hz, 0, sizeof(SetAFEPriority_for30Hz)}, /* Set AFE Priority for 30Hz Sampling Rate */
54 {SetMBoxPriority_for30Hz, 0, sizeof(SetMBoxPriority_for30Hz)}, /* Set MBox Priority for 30Hz Sampling Rate */
55 __END_WRITE_CMD__};
56
57 /*! Prepare the register read list to read the raw Accel data from MMA9553. */
58 const registerreadlist_t cMma9553ReadRawOutput[] = {
59 {.readFrom = MMA9553_XYZ_DATA_OFFSET, .numBytes = MMA9553_ACCEL_DATA_SIZE}, __END_READ_DATA__};
60
61 /*******************************************************************************
62 * Globals
63 ******************************************************************************/
64 char boardString[ADS_MAX_STRING_LENGTH] = {0}, shieldString[ADS_MAX_STRING_LENGTH] = {0},
65 embAppName[ADS_MAX_STRING_LENGTH] = {0};
66 volatile bool bStreamingEnabled = false, bMma9553DataReady = false, bMma9553Ready = false;
67 uint8_t gStreamID; /* The auto assigned Stream ID. */
68 int32_t gSystick;
69 GENERIC_DRIVER_GPIO *pGpioDriver = &Driver_GPIO_KSDK;
70
71 /*******************************************************************************
72 * Functions
73 ******************************************************************************/
74 /* LPTMR based ODR Callback function. */
mma9553_en_callback(void)75 void mma9553_en_callback(void)
76 {
77 LPTMR_ClearStatusFlags(LPTMR0, kLPTMR_TimerCompareFlag);
78 bMma9553DataReady = true;
79 }
80
81 /* Handler for Device Info and Streaming Control Commands. */
process_host_command(uint8_t tag,uint8_t * hostCommand,uint8_t * hostResponse,size_t * hostMsgSize,size_t respBufferSize)82 bool process_host_command(
83 uint8_t tag, uint8_t *hostCommand, uint8_t *hostResponse, size_t *hostMsgSize, size_t respBufferSize)
84 {
85 bool success = false;
86
87 /* If it is Host requesting Device Info, send Board Name and Shield Name. */
88 if (tag == HOST_PRO_INT_DEV_TAG)
89 { /* Byte 1 : Payload - Length of APPLICATION_NAME (b)
90 * Bytes=b : Payload Application Name
91 * Byte b+1 : Payload - Length of BOARD_NAME (s)
92 * Bytes=s : Payload Board Name
93 * Byte b+s+2 : Payload - Length of SHIELD_NAME (v)
94 * Bytes=v : Payload Shield Name */
95
96 size_t appNameLen = strlen(embAppName);
97 size_t boardNameLen = strlen(boardString);
98 size_t shieldNameLen = strlen(shieldString);
99
100 if (respBufferSize >= boardNameLen + shieldNameLen + appNameLen + 3)
101 { /* We have sufficient buffer. */
102 *hostMsgSize = 0;
103 }
104 else
105 {
106 return false;
107 }
108
109 hostResponse[*hostMsgSize] = appNameLen;
110 *hostMsgSize += 1;
111
112 memcpy(hostResponse + *hostMsgSize, embAppName, appNameLen);
113 *hostMsgSize += appNameLen;
114
115 hostResponse[*hostMsgSize] = boardNameLen;
116 *hostMsgSize += 1;
117
118 memcpy(hostResponse + *hostMsgSize, boardString, boardNameLen);
119 *hostMsgSize += boardNameLen;
120
121 hostResponse[*hostMsgSize] = shieldNameLen;
122 *hostMsgSize += 1;
123
124 memcpy(hostResponse + *hostMsgSize, shieldString, shieldNameLen);
125 *hostMsgSize += shieldNameLen;
126
127 return true;
128 }
129
130 /* If it is Host sending Streaming Commands, take necessary actions. */
131 if ((tag == (HOST_PRO_INT_CMD_TAG | HOST_PRO_CMD_W_CFG_TAG)) &&
132 (*hostMsgSize == HOST_MSG_CMD_ACT_OFFSET - HOST_MSG_LEN_LSB_OFFSET))
133 { /* Byte 1 : Payload - Operation Code (Start/Stop Operation Code)
134 * Byte 2 : Payload - Stream ID (Target Stream for carrying out operation) */
135 switch (hostCommand[0]) /* Execute desired operation (Start/Stop) on the requested Stream. */
136 {
137 case HOST_CMD_START:
138 if (hostCommand[1] == gStreamID && bMma9553Ready && bStreamingEnabled == false)
139 {
140 BOARD_SystickStart(&gSystick);
141 bStreamingEnabled = true;
142 success = true;
143 }
144 break;
145 case HOST_CMD_STOP:
146 if (hostCommand[1] == gStreamID && bMma9553Ready && bStreamingEnabled == true)
147 {
148 pGpioDriver->clr_pin(&GREEN_LED);
149 bStreamingEnabled = false;
150 success = true;
151 }
152 break;
153 default:
154 break;
155 }
156 *hostMsgSize = 0; /* Zero payload in response. */
157 }
158
159 return success;
160 }
161
162 /*!
163 * @brief Main function
164 */
main(void)165 int main(void)
166 {
167 int32_t status;
168 uint8_t streamingPacket[STREAMING_HEADER_LEN + MMA9553_STREAM_DATA_SIZE];
169
170 lptmr_config_t lptmrConfig;
171 mma9553_i2c_sensorhandle_t mma9553Driver;
172 mma9553_acceldata_t rawData = {.timestamp = 0};
173
174 ARM_DRIVER_I2C *pI2Cdriver = &I2C_S_DRIVER;
175 ARM_DRIVER_USART *pUartDriver = &HOST_S_DRIVER;
176
177 /*! Initialize the MCU hardware */
178 BOARD_BootClockRUN();
179 BOARD_SystickEnable();
180
181 /* Create the Short Application Name String for ADS. */
182 sprintf(embAppName, "%s:%s", APPLICATION_NAME, APPLICATION_VERSION);
183
184 /* Run ADS. */
185 BOARD_RunADS(embAppName, boardString, shieldString, ADS_MAX_STRING_LENGTH);
186
187 /* Create the Full Application Name String for Device Info Response. */
188 sprintf(embAppName, "%s:%s:%s", SHIELD_NAME, APPLICATION_NAME, APPLICATION_VERSION);
189
190 /*! Initialize RGB LED pin used by FRDM board */
191 pGpioDriver->pin_init(&GREEN_LED, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
192
193 /* Initialize ODR Timer. */
194 LPTMR_GetDefaultConfig(&lptmrConfig);
195 LPTMR_Init(LPTMR0, &lptmrConfig);
196 LPTMR_EnableInterrupts(LPTMR0, kLPTMR_TimerInterruptEnable);
197 LPTMR_SetTimerPeriod(LPTMR0, MSEC_TO_COUNT(SAMPLING_RATE_ms, CLOCK_GetFreq(kCLOCK_LpoClk)));
198 EnableIRQ(LPTMR0_IRQn);
199
200 /*! Initialize the I2C driver. */
201 status = pI2Cdriver->Initialize(I2C_S_SIGNAL_EVENT);
202 if (ARM_DRIVER_OK != status)
203 {
204 return -1;
205 }
206
207 /*! Set the I2C Power mode. */
208 status = pI2Cdriver->PowerControl(ARM_POWER_FULL);
209 if (ARM_DRIVER_OK != status)
210 {
211 return -1;
212 }
213
214 /*! Set the I2C bus speed. */
215 status = pI2Cdriver->Control(ARM_I2C_BUS_SPEED, ARM_I2C_BUS_SPEED_FAST);
216 if (ARM_DRIVER_OK != status)
217 {
218 return -1;
219 }
220
221 /*! Initialize the UART driver. */
222 status = pUartDriver->Initialize(HOST_S_SIGNAL_EVENT);
223 if (ARM_DRIVER_OK != status)
224 {
225 return -1;
226 }
227
228 /*! Set the UART Power mode. */
229 status = pUartDriver->PowerControl(ARM_POWER_FULL);
230 if (ARM_DRIVER_OK != status)
231 {
232 return -1;
233 }
234
235 /*! Set UART Baud Rate. */
236 status = pUartDriver->Control(ARM_USART_MODE_ASYNCHRONOUS, BOARD_DEBUG_UART_BAUDRATE);
237 if (ARM_DRIVER_OK != status)
238 {
239 return -1;
240 }
241
242 /*! Initialize the MMA9553 sensor driver. */
243 status = MMA9553_I2C_Initialize(&mma9553Driver, &I2C_S_DRIVER, I2C_S_DEVICE_INDEX, MMA9553_I2C_ADDR);
244 if (SENSOR_ERROR_NONE == status)
245 {
246 /*! Set the task to be executed while waiting for I2C transactions to complete. */
247 MMA9553_I2C_SetIdleTask(&mma9553Driver, (registeridlefunction_t)SMC_SetPowerModeVlpr, SMC);
248
249 /*! Configure the MMA9553 sensor driver with 30Hz Mode settings. */
250 status = MMA9553_I2C_Configure(&mma9553Driver, cMma9553Config30Hz);
251 if (SENSOR_ERROR_NONE == status)
252 {
253 bMma9553Ready = true;
254 }
255 }
256
257 /*! Initialize streaming and assign a Stream ID. */
258 gStreamID =
259 Host_IO_Init(pUartDriver, (void *)mma9553Driver.pCommDrv, &mma9553Driver.deviceInfo, NULL, MMA9553_I2C_ADDR);
260 /* Confirm if a valid Stream ID has been allocated for this stream. */
261 if (0 == gStreamID)
262 {
263 bMma9553Ready = false;
264 }
265 else
266 {
267 /*! Populate streaming header. */
268 Host_IO_Add_ISO_Header(gStreamID, streamingPacket, MMA9553_STREAM_DATA_SIZE);
269 pGpioDriver->clr_pin(&GREEN_LED);
270 }
271
272 LPTMR_StartTimer(LPTMR0);
273 for (;;) /* Forever loop */
274 { /* Call UART Non-Blocking Receive. */
275 Host_IO_Receive(process_host_command, HOST_FORMAT_HDLC);
276
277 /* Process packets only if streaming has been enabled by Host and ODR Timer ISR has expired. */
278 if (false == bStreamingEnabled || false == bMma9553DataReady)
279 {
280 SMC_SetPowerModeWait(SMC); /* Power save, wait if nothing to do. */
281 continue;
282 }
283 else
284 { /*! Clear the data ready flag, it will be set again by the ISR. */
285 bMma9553DataReady = false;
286 pGpioDriver->toggle_pin(&GREEN_LED);
287 }
288
289 /*! Read the raw sensor data from the MMA9553. */
290 status = MMA9553_I2C_CommandResponse(&mma9553Driver, NULL, cMma9553ReadRawOutput, (uint8_t *)&rawData.accel);
291 if (ARM_DRIVER_OK != status)
292 {
293 continue;
294 }
295
296 /* Update timestamp from Systick framework. */
297 rawData.timestamp += BOARD_SystickElapsedTime_us(&gSystick);
298
299 /* Copy Raw samples to Streaming Buffer. */
300 memcpy(streamingPacket + STREAMING_HEADER_LEN, &rawData, MMA9553_STREAM_DATA_SIZE);
301 /* Send streaming packet to Host. */
302 Host_IO_Send(streamingPacket, sizeof(streamingPacket), HOST_FORMAT_HDLC);
303 }
304 }
305