Mercurial > public > ostc4
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 } |