comparison Discovery/Src/motion.c @ 373:7b981f8bdd41 MotionDetection

Add scroll event by pitch angle detection: Add a function to scroll through the custom view in case the computer is not in the typical center position Refine Pitch Detection: Changed implementation to use sectors for detection. Increased detection window
author ideenmodellierer
date Sun, 08 Sep 2019 13:45:17 +0200
parents fca370f847f8
children 834e087505ec
comparison
equal deleted inserted replaced
372:75eedde05ff6 373:7b981f8bdd41
5 * Author: Thorsten Sonntag 5 * Author: Thorsten Sonntag
6 */ 6 */
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <string.h> 9 #include <string.h>
10 #include <stdlib.h>
10 #include <math.h> 11 #include <math.h>
11 #include "motion.h" 12 #include "motion.h"
12 #include "data_central.h" 13 #include "data_central.h"
13 #include "t7.h" 14 #include "t7.h"
14 #include "settings.h" 15 #include "settings.h"
18 #define MOVE_DELTA_SPEED 4 /* Delta speed needed to identify a valid movement */ 19 #define MOVE_DELTA_SPEED 4 /* Delta speed needed to identify a valid movement */
19 #define PITCH_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */ 20 #define PITCH_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */
20 #define PITCH_DELTA_END 10 /* Delta allowed between start and end position */ 21 #define PITCH_DELTA_END 10 /* Delta allowed between start and end position */
21 22
22 23
23 #define SECTOR_WINDOW 40.0 /* Pitch window which is used for custom view projection */ 24 #define SECTOR_WINDOW 80.0 /* Pitch window which is used for custom view projection */
24 #define SECTOR_HYSTERY 3 /* Additional offset to avoid fast changing displays */ 25 #define SECTOR_HYSTERY 3 /* Additional offset to avoid fast changing displays */
25 #define SECTOR_BORDER 400.0 /* Define a value which is out of limit to avoid not wanted key events */ 26 #define SECTOR_BORDER 400.0 /* Define a value which is out of limit to avoid not wanted key events */
26 #define SECTOR_FILTER 10 /* Define speed for calculated angle to follow real value */ 27 #define SECTOR_FILTER 10 /* Define speed for calculated angle to follow real value */
27 28
28 #define SECTOR_MAX 10 /* maximum number of sectors */ 29 #define SECTOR_MAX 20 /* maximum number of sectors */
29 30 #define SECTOR_SCROLL 6 /* number of sectors used for scroll detection */
30 static detectionState_t detectionState = DETECT_NOTHING; 31
31 32 detectionState_t detectionState = DETECT_NOTHING;
32 static uint8_t curSector; 33
34 uint8_t curSector;
33 static uint8_t targetSector; 35 static uint8_t targetSector;
34 static uint8_t sectorSize; 36 static uint8_t sectorSize;
35 static uint8_t sectorCount; 37 static uint8_t sectorCount;
36 38
37 SSector PitchSector[10]; /* max number of enabled custom views */ 39 SSector PitchSector[SECTOR_MAX]; /* max number of enabled custom views */
38 40
39 41
40 uint8_t GetSectorForPitch(float pitch) 42 uint8_t GetSectorForPitch(float pitch)
41 { 43 {
42 static float lastPitch = 1000; 44 static float lastPitch = 1000;
68 uint8_t index; 70 uint8_t index;
69 71
70 if(numOfSectors == CUSTOMER_DEFINED_VIEWS) 72 if(numOfSectors == CUSTOMER_DEFINED_VIEWS)
71 { 73 {
72 sectorCount = t7_GetEnabled_customviews(); 74 sectorCount = t7_GetEnabled_customviews();
73 if(sectorCount > 5) 75 if(sectorCount > 7)
74 { 76 {
75 sectorCount = 5; /* more views are hard to manually control */ 77 sectorCount = 7; /* more views are hard to manually control */
76 } 78 }
77 } 79 }
78 else 80 else
81 if(numOfSectors != CUSTOMER_KEEP_LAST_SECTORS)
79 { 82 {
80 sectorCount = numOfSectors; 83 sectorCount = numOfSectors;
81 } 84 }
82 sectorSize = SECTOR_WINDOW / sectorCount; 85 sectorSize = SECTOR_WINDOW / sectorCount;
83 86
108 switch(settingsGetPointer()->MotionDetection) 111 switch(settingsGetPointer()->MotionDetection)
109 { 112 {
110 case MOTION_DETECT_SECTOR: DefinePitchSectors(0,CUSTOMER_DEFINED_VIEWS); 113 case MOTION_DETECT_SECTOR: DefinePitchSectors(0,CUSTOMER_DEFINED_VIEWS);
111 break; 114 break;
112 case MOTION_DETECT_MOVE: DefinePitchSectors(0,SECTOR_MAX); 115 case MOTION_DETECT_MOVE: DefinePitchSectors(0,SECTOR_MAX);
116 break;
117 case MOTION_DETECT_SCROLL: DefinePitchSectors(0,SECTOR_SCROLL);
113 break; 118 break;
114 default: 119 default:
115 break; 120 break;
116 } 121 }
117 122
145 } 150 }
146 } 151 }
147 return PitchEvent; 152 return PitchEvent;
148 } 153 }
149 154
150 155 /* Check if pitch is not in center position and trigger a button action if needed */
156 detectionState_t detectScrollButtonEvent(float curPitch)
157 {
158 static uint8_t delayscroll = 0; /* slow dow the number of scroll events */
159
160 uint8_t PitchEvent = DETECT_NOTHING;
161 uint8_t newSector;
162
163 if(delayscroll == 0)
164 {
165 newSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
166 /* for scroll detection the motion windoe is split into 6 sectors => set event accoring to the sector number*/
167 switch(newSector)
168 {
169 case 0:
170 case 1: PitchEvent = DETECT_POS_PITCH;
171 break;
172 case 4:
173 case 5: PitchEvent = DETECT_NEG_PITCH;
174 break;
175 default:
176 break;
177 }
178 if(PitchEvent != DETECT_NOTHING)
179 {
180 delayscroll = 5;
181 }
182 }
183 else
184 {
185 delayscroll--;
186 }
187 return PitchEvent;
188 }
189
190
191 uint8_t sectorhist[20];
192 uint8_t sectorindex = 0;
151 /* Detect if user is generating an pitch including return to starting position */ 193 /* Detect if user is generating an pitch including return to starting position */
152 /* This is done by feeding the past movements value per value into a state machine */ 194 /* This is done by feeding the past movements value per value into a state machine */
153 detectionState_t detectPitch(float currentPitch) 195 detectionState_t detectPitch(float currentPitch)
154 { 196 {
197 static uint8_t lastSector = 0;
198 static uint8_t startSector = 0;
155 static uint8_t stableCnt = 0; 199 static uint8_t stableCnt = 0;
156 static float lastPitch = 0.0;
157 static float startPitch = 0.0;
158 float curSpeed;
159
160 200
161 if((detectionState == DETECT_NEG_PITCH) || (detectionState == DETECT_POS_PITCH)) /* discard last detection */ 201 if((detectionState == DETECT_NEG_PITCH) || (detectionState == DETECT_POS_PITCH)) /* discard last detection */
162 { 202 {
163 detectionState = DETECT_NOTHING; 203 detectionState = DETECT_NOTHING;
164 } 204 }
165 205
206 curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
207
208 sectorhist[sectorindex++] = curSector;
209 if(sectorindex == 20) sectorindex=0;
210
211 /* feed value into state machine */
212 switch (detectionState)
213 {
214 case DETECT_NOTHING: if(curSector == lastSector) /* detect a stable condition before evaluating for the next move */
215 {
216 stableCnt++;
217 }
218 else
219 {
220 stableCnt=0;
221 }
222
223 if(stableCnt > STABLE_STATE_COUNT)
224 {
225 detectionState = DETECT_START;
226 stableCnt = 0;
227 startSector = lastSector;
228 }
229 break;
230 case DETECT_START: if(curSector != lastSector)
231 {
232 if(abs(curSector - startSector) > 1)
233 {
234 if(curSector > lastSector)
235 {
236 detectionState = DETECT_POS_MOVE;
237 }
238 else
239 {
240 detectionState = DETECT_NEG_MOVE;
241 }
242 stableCnt = 0;
243 startSector = lastSector;
244 }
245 else
246 {
247 stableCnt++; /* reset start sector in case of slow movement */
248 }
249 // startPitch = lastPitch;
250 }
251 break;
252 case DETECT_NEG_MOVE:
253 case DETECT_POS_MOVE: if(curSector != lastSector) /* still moving? */
254 {
255 stableCnt++;
256 }
257 else
258 {
259 // if(stableCnt >= 1) /* debounce movement */
260 {
261 if(abs(startSector - curSector) > 2)
262 {
263 detectionState++;
264 stableCnt = 0;
265 }
266 else
267 {
268 // detectionState = DETECT_NOTHING;
269 stableCnt++; /* maybe on the boundary of a sector => handle as stable */
270 }
271 }
272 #if 0
273 else
274 {
275 // detectionState = DETECT_NOTHING;
276 stableCnt++; /* maybe on the boundary of a sector => handle as stable */
277 }
278 #endif
279 }
280 break;
281 case DETECT_MINIMA:
282 case DETECT_MAXIMA: /* stay at maximum for short time to add a pattern for user interaction */
283 if(curSector == lastSector)
284 {
285 stableCnt++;
286 }
287 else
288 {
289 if(stableCnt > 0) /* restart movement after a short break? */
290 {
291 detectionState++;
292 stableCnt = 0;
293 }
294 else
295 {
296 // detectionState = DETECT_NOTHING;
297 stableCnt++; /* maybe on the boundary of a sector => handle as stable */
298 }
299 }
300 break;
301 case DETECT_RISEBACK:
302 case DETECT_FALLBACK: if(curSector == lastSector) /* check if we are back at start position at end of movement */
303 {
304 if(abs(startSector - curSector) <= 1) //(curSector == startSector)
305 {
306 detectionState++;
307 stableCnt = 0;
308 }
309 else
310 {
311 // detectionState = DETECT_NOTHING;
312 stableCnt++; /* maybe on the boundary of a sector => handle as stable */
313 }
314 }
315 else
316 {
317 stableCnt++;
318 }
319 break;
320 default:
321 detectionState = DETECT_NOTHING;
322 break;
323
324 }
325 lastSector = curSector;
326 if(stableCnt > STABLE_STATE_TIMEOUT)
327 {
328 detectionState = DETECT_NOTHING;
329 stableCnt = 0;
330 }
331
332 #if 0
166 curSpeed = currentPitch - lastPitch; 333 curSpeed = currentPitch - lastPitch;
167 334
168 /* feed value into state machine */ 335 /* feed value into state machine */
169 switch (detectionState) 336 switch (detectionState)
170 { 337 {
261 detectionState = DETECT_NOTHING; 428 detectionState = DETECT_NOTHING;
262 stableCnt = 0; 429 stableCnt = 0;
263 } 430 }
264 431
265 lastPitch = currentPitch; 432 lastPitch = currentPitch;
433 #endif
266 return detectionState; 434 return detectionState;
267 } 435 }