ISSDK  1.7
IoT Sensing Software Development Kit
pedometer.c
Go to the documentation of this file.
1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
4  * Copyright 2016-2017 NXP
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted (subject to the limitations in the disclaimer below) provided
9  * that the following conditions are met:
10  *
11  * o Redistributions of source code must retain the above copyright notice, this list
12  * of conditions and the following disclaimer.
13  *
14  * o Redistributions in binary form must reproduce the above copyright notice, this
15  * list of conditions and the following disclaimer in the documentation and/or
16  * other materials provided with the distribution.
17  *
18  * o Neither the name of the copyright holder nor the names of its
19  * contributors may be used to endorse or promote products derived from this
20  * software without specific prior written permission.
21  *
22  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /**
36  * @file pedometer.c
37 * @brief The pedometer.c file contains the interface definitions for
38 * pedometer application.
39 */
40 
41 /*******************************************************************************
42  * Includes
43  ******************************************************************************/
44 #include "pedometer.h"
45 
46 /*******************************************************************************
47  * Macros, globals
48  ******************************************************************************/
49 #define PEDOMETER_STATUS_ACTIVITY_BITNUM 0
50 #define PEDOMETER_STATUS_SUSPEND_BITNUM 3
51 #define PEDOMETER_STATUS_ACTCHG_BITNUM 4
52 #define PEDOMETER_STATUS_STEPCHG_BITNUM 5
53 #define PEDOMETER_STATUS_SUSPCHG_BITNUM 6
54 #define PEDOMETER_STATUS_MRGFLG_BITNUM 7
55 
56 #define PEDOMETER_STATUS_ACTIVITY_MASK (7 << PEDOMETER_STATUS_ACTIVITY_BITNUM)
57 #define PEDOMETER_STATUS_SUSPEND_MASK (1 << PEDOMETER_STATUS_SUSPEND_BITNUM)
58 #define PEDOMETER_STATUS_ACTCHG_MASK (1 << PEDOMETER_STATUS_ACTCHG_BITNUM)
59 #define PEDOMETER_STATUS_STEPCHG_MASK (1 << PEDOMETER_STATUS_STEPCHG_BITNUM)
60 #define PEDOMETER_STATUS_SUSPCHG_MASK (1 << PEDOMETER_STATUS_SUSPCHG_BITNUM)
61 #define PEDOMETER_STATUS_MRGFLG_MASK (1 << PEDOMETER_STATUS_MRGFLG_BITNUM)
62 
63 #define PEDOMETER_STATUS_CHG_MASK \
64  (PEDOMETER_STATUS_ACTCHG_MASK | PEDOMETER_STATUS_STEPCHG_MASK | PEDOMETER_STATUS_SUSPCHG_MASK)
65 #define SQUARED(x) ((x) * (x))
66 /* below values are the best set of value for the algorthm and computed during the algorithm definition.*/
67 /******************************************************************************
68  * Private Function Declarations
69  *****************************************************************************/
70 
71 /* Update status variables */
72 static void status_update(pedometer_t *pedometer, uint32_t events, bool suspend);
73 
74 /* Determine autonomous suspend state */
75 static bool suspend_compute(pedometer_t *pPedometer, ped_accel_t *pData);
76 
77 /* compute the debounce. */
78 static bool debounce_count(bool dbcntm, bool condition, debounce_count_t *count, debounce_count_t threshold);
79 
80 /* Cast uint32_t to uint16_t with saturate */
81 static uint16_t uint32_to_uint16(uint32_t val);
82 
83 /******************************************************************************
84  * Private Variable Definitions
85  ******************************************************************************/
86 
87 static const pedometer_t pedometer_default = {.status =
88  {
89  .version = 2,
90  },
91  .config = {
92  .sleepcount_threshold = 1,
93  .bits = {.config = 1},
94  .keynetik =
95  {
96  .height = 175,
97  .weight = 80,
98  .filtersteps = PEDO_FILTER_STEPS_DEFAULT,
99  .bits =
100  {
101  .filtertime = PEDO_FILTER_TIME_DEFAULT,
102  },
103  .speedperiod = PEDO_SPEED_PERIOD_DEFAULT,
104  .stepthreshold = PEDO_STEP_THRESHOLD_DEFAULT,
105  },
106  .stepcoalesce = 1,
107  .oneG = PEDO_ONEG_8G,
108  .frequency = PEDO_FREQHZ_DEFAULT,
109  }};
110 
111 /*******************************************************************************
112  * Code
113  ******************************************************************************/
114 
115 /*
116 ** ===================================================================
117 ** Method : pedometer_init
118 ** brief : The interface function initialize the pedometer.
119 ** params[in] : pedometer_t *pPedometer, handle to the pedometer.
120 **
121 ** ===================================================================
122 */
123 void pedometer_init(pedometer_t *pPedometer)
124 {
125  *pPedometer = pedometer_default;
126  KeynetikInitialize(pPedometer->config.oneG, pPedometer->config.frequency, &pPedometer->config.keynetik);
127  pPedometer->private.stepchg_stepcount = 0;
128 }
129 
130 /*** ===================================================================
131 ** Method : pedometer_configure
132 ** brief : The interface function to configure the pedometer
133 ** params[in] : pedometer_t *pPedometer, handle to the pedometer.
134 ** params[in] : pedometer_config_t configuration parameter.
135 ** ===================================================================
136 */
137 void pedometer_configure(pedometer_t *pPedometer, const pedometer_config_t *pConfig)
138 {
139  pPedometer->config = *pConfig;
140  KeynetikInitialize(pPedometer->config.oneG, pPedometer->config.frequency, &pPedometer->config.keynetik);
141  pPedometer->private.stepchg_stepcount = 0;
142 }
143 /*
144 ** ===================================================================
145 ** Method : pedometer_run
146 ** brief : The interface function excutes the pedometer algorithm.
147 ** params[in] : pedometer_t *pPedometer, handle to the pedometer.
148 ** params[in] : ped_accel_t data acceleration data.
149 ** ===================================================================
150 */
152 {
153  uint32_t events = 0;
154  /* if suspend, don't execute the alogrithm and save the power.*/
155  bool suspend = suspend_compute(pPedometer, pData);
156  if (!suspend)
157  {
158  events = KeynetikHandleIncomingEvent(pData->accel[0], pData->accel[1], pData->accel[2]);
159  }
160  status_update(pPedometer, events, suspend);
161  return events;
162 }
163 /*
164 ** ===================================================================
165 ** Method : status_update
166 ** brief : update the status of the pedometer output
167 ** params[in] : pedometer_t *pPedometer, handle to the pedometer.
168 ** params[in] : uint32_t events kynetic event
169 ** params[in] : bool suspend suspend flag
170 ** ===================================================================
171 */
172 static void status_update(pedometer_t *pPedometer, uint32_t events, bool suspend)
173 {
174  bool activity_stable =
175  debounce_count(pPedometer->config.bits.activity_dbcntm, !(events & KEYNETIK_ACTIVITYCHANGED),
176  &pPedometer->private.activitycount, pPedometer->config.activitycount_threshold);
177 
178  activitylevel_t activity = activity_stable ? keynetikActivityLevel : pPedometer->status.status.bits.activity;
179  uint16_t stepcount = uint32_to_uint16(keynetikStepCount);
180  uint8_t newstatus = (activity << PEDOMETER_STATUS_ACTIVITY_BITNUM) & PEDOMETER_STATUS_ACTIVITY_MASK;
181 
182  if ((newstatus ^ pPedometer->status.status.byte) & PEDOMETER_STATUS_ACTIVITY_MASK)
183  newstatus |= PEDOMETER_STATUS_ACTCHG_MASK;
184 
185  if (pPedometer->config.stepcoalesce &&
186  (stepcount - pPedometer->private.stepchg_stepcount >= pPedometer->config.stepcoalesce))
187  {
188  pPedometer->private.stepchg_stepcount = stepcount;
189  newstatus |= PEDOMETER_STATUS_STEPCHG_MASK;
190  }
191 
192  if (suspend)
193  newstatus |= PEDOMETER_STATUS_SUSPEND_MASK;
194 
195  if ((newstatus ^ pPedometer->status.status.byte) & PEDOMETER_STATUS_SUSPEND_MASK)
196  newstatus |= PEDOMETER_STATUS_SUSPCHG_MASK;
197 
198  if (newstatus & PEDOMETER_STATUS_CHG_MASK)
199  newstatus |= PEDOMETER_STATUS_MRGFLG_MASK;
200  /* Update the status such stepcount, distance, speed etc..*/
201  pPedometer->status.stepcount = uint32_to_uint16(keynetikStepCount);
202  pPedometer->status.distance = uint32_to_uint16(keynetikDistance);
203  pPedometer->status.speed = keynetikSpeed;
204  pPedometer->status.calories = uint32_to_uint16(keynetikCalories);
205  pPedometer->status.status.byte = newstatus;
206 }
207 /*
208 ** ===================================================================
209 ** Method : suspend_compute
210 ** brief : compute the suspend status.
211 ** params[in] : pedometer_t *pPedometer, handle to the pedometer.
212 ** params[in] : ped_accel_t data acceleration data.
213 ** ===================================================================
214 */
215 static bool suspend_compute(pedometer_t *pPedometer, ped_accel_t *pData)
216 {
217  /* compute the magnitude*/
218  uint32_t mag2 = SQUARED(pData->accel[0]) + SQUARED(pData->accel[1]) + SQUARED(pData->accel[2]);
219  bool stationary =
220  (mag2 > SQUARED(pPedometer->config.sleepminimum)) && (mag2 < SQUARED(pPedometer->config.sleepmaximum));
221  bool suspend = debounce_count(pPedometer->config.bits.sleep_dbcntm, stationary, &pPedometer->status.sleepcount,
222  pPedometer->config.sleepcount_threshold);
223  return (suspend);
224 }
225 /*
226 ** ===================================================================
227 ** Method : uint32_to_uint16
228 ** brief : conversion function from 32 to 16.
229 ** params[in] : uint32_t x, imput
230 ** params[in] : ped_accel_data data acceleration data.
231 ** ===================================================================
232 */
233 uint16_t uint32_to_uint16(uint32_t val)
234 {
235  if (val > 0x0000FFFF)
236  return (0xFFFF);
237  return ((uint16_t)val);
238 }
239 /*
240 ** ===================================================================
241 ** Method : debounce_count
242 ** brief : compute the debouct status.
243 ** params[in] : bool dbcntm,
244 ** params[in] : bool condition
245 ** params[in] : debounce_count_t *count,
246 ** params[in] : debounce_count_t threshold, debouce threshold
247 ** ===================================================================
248 */
249 static bool debounce_count(bool dbcntm, bool condition, debounce_count_t *count, debounce_count_t threshold)
250 {
251  if (condition)
252  {
253  /* increment count up to, but not above the threshold */
254  *count = (*count + 1) < threshold ? *count + 1 : threshold;
255  }
256  else
257  {
258  if (dbcntm)
259  *count = 0;
260  else
261  /* decrement count down to, but not below zero */
262  *count = (*count - 1) > 0 ? *count - 1 : 0;
263  }
264  return ((bool)(*count >= threshold));
265 }
pedometer_config_t config
Definition: pedometer.h:123
void pedometer_init(pedometer_t *pPedometer)
The interface function initialize the pedometer.
Definition: pedometer.c:123
This defines the configuration structure of the pedometer.
Definition: pedometer.h:72
The pedometer.h file contains the interface and structure definitions for pedometer application...
int16_t accel[3]
Definition: pedometer.h:67
#define PEDO_FREQHZ_DEFAULT
Definition: pedometer.h:57
uint16_t sleepmaximum
Definition: pedometer.h:75
struct pedometer_config_t::@291 bits
This defines the acceleration input data for the pedometer.
Definition: pedometer.h:65
#define PEDOMETER_STATUS_SUSPCHG_MASK
Definition: pedometer.c:60
uint16_t sleepminimum
Definition: pedometer.h:74
#define PEDO_STEP_THRESHOLD_DEFAULT
Definition: pedometer.h:58
#define PEDOMETER_STATUS_SUSPEND_MASK
Definition: pedometer.c:57
This defines the pedometer instance.
Definition: pedometer.h:99
KeynetikActivityLevel activitylevel_t
Definition: pedometer.h:52
#define PEDOMETER_STATUS_ACTCHG_MASK
Definition: pedometer.c:58
#define PEDOMETER_STATUS_STEPCHG_MASK
Definition: pedometer.c:59
#define PEDO_ONEG_8G
Definition: pedometer.h:54
#define PEDO_SPEED_PERIOD_DEFAULT
Definition: pedometer.h:59
debounce_count_t sleepcount_threshold
Definition: pedometer.h:76
union pedometer_t::pedometer_status_tag::@292 status
void pedometer_configure(pedometer_t *pPedometer, const pedometer_config_t *pConfig)
The interface function to configure the pedometer.
Definition: pedometer.c:137
KeynetikConfig keynetik
Definition: pedometer.h:87
int32_t pedometer_run(pedometer_t *pPedometer, ped_accel_t *pData)
The interface function excutes the pedometer algorithm.
Definition: pedometer.c:151
debounce_count_t activitycount_threshold
Definition: pedometer.h:88
typedef int32_t(DATA_FORMAT_Append_t))(void *pData
The interface function to append the data on the formated stream.
struct pedometer_t::pedometer_status_tag status
#define PEDOMETER_STATUS_CHG_MASK
Definition: pedometer.c:63
uint16_t frequency
Definition: pedometer.h:93
#define PEDO_FILTER_STEPS_DEFAULT
Definition: pedometer.h:61
struct pedometer_t::pedometer_status_tag::@292::@293 bits
#define PEDOMETER_STATUS_ACTIVITY_BITNUM
Definition: pedometer.c:49
struct pedometer_t::pedometer_private_tag private
#define SQUARED(x)
Definition: pedometer.c:65
#define PEDOMETER_STATUS_MRGFLG_MASK
Definition: pedometer.c:61
uint16_t debounce_count_t
Definition: pedometer.h:53
#define PEDOMETER_STATUS_ACTIVITY_MASK
Definition: pedometer.c:56
uint8_t stepcoalesce
Definition: pedometer.h:89
#define PEDO_FILTER_TIME_DEFAULT
Definition: pedometer.h:60