Mercurial > public > ostc4
diff Discovery/Src/motion.c @ 370:77cdfbdaca8c MotionDetection
Changed function names from shake to pitch and improved detection function: Shake might be confusing for people reading the code because pitch values are ased for calculation => changed name to pitch to be more transparent
author | ideenmodellierer |
---|---|
date | Tue, 13 Aug 2019 21:13:54 +0200 |
parents | bdf978d2a5d4 |
children | fca370f847f8 |
line wrap: on
line diff
--- a/Discovery/Src/motion.c Tue Aug 13 21:12:17 2019 +0200 +++ b/Discovery/Src/motion.c Tue Aug 13 21:13:54 2019 +0200 @@ -9,26 +9,133 @@ #include <string.h> #include <math.h> #include "motion.h" +#include "data_central.h" +#include "t7.h" #define STABLE_STATE_COUNT 2 /* number of count to declare a state as stable (at the moment based on 100ms) */ #define STABLE_STATE_TIMEOUT 5 /* Detection shall be aborted if a movement state is stable for more than 500ms */ #define MOVE_DELTA_SPEED 4 /* Delta speed needed to identify a valid movement */ -#define SHAKE_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */ -#define SHAKE_DELTA_END 10 /* Delta allowed between start and end position */ +#define PITCH_DELTA_COUNT 10 /* Delta count needed to identify a valid minima / maxima */ +#define PITCH_DELTA_END 10 /* Delta allowed between start and end position */ + + +#define SECTOR_WINDOW 40.0 /* Pitch window which is used for custom view projection */ +#define SECTOR_HYSTERY 3 /* Additional offset to avoid fast changing displays */ +#define SECTOR_BORDER 400.0 /* Define a value which is out of limit to avoid not wanted key events */ +#define SECTOR_FILTER 10 /* Define speed for calculated angle to follow real value */ + static detectionState_t detectionState = DETECT_NOTHING; -/* Detect if user is generating an pitch including return to starting position (shake) */ +static uint8_t curSector; +static uint8_t targetSector; +static uint8_t sectorSize; +static uint8_t sectorCount; + +SSector PitchSector[10]; /* max number of enabled custom views */ + + +uint8_t GetSectorForPitch(float pitch) +{ + static float lastPitch = 1000; + float newPitch; + uint8_t index; + uint8_t sector = 0; + + if(lastPitch == 1000) /* init at first call */ + { + lastPitch = pitch; + } + + newPitch = lastPitch + (pitch / SECTOR_FILTER); + + for(index = 1; index < sectorCount; index++) + { + if((pitch < PitchSector[index].upperlimit) && (pitch > PitchSector[index].lowerlimit )) + { + sector = index; + break; + } + } + lastPitch = newPitch; + return sector; +} + +void DefinePitchSectors(float centerPitch) +{ + uint8_t index; + + sectorCount = t7_GetEnabled_customviews(); + sectorSize = SECTOR_WINDOW / sectorCount; + + PitchSector[0].upperlimit = centerPitch + (SECTOR_WINDOW / 2); + PitchSector[0].lowerlimit = PitchSector[0].upperlimit - sectorSize - SECTOR_HYSTERY; + + for(index = 1; index < sectorCount; index++) + { + PitchSector[index].upperlimit = PitchSector[0].upperlimit - index * sectorSize + SECTOR_HYSTERY; + PitchSector[index].lowerlimit = PitchSector[0].upperlimit - (index + 1) * sectorSize - SECTOR_HYSTERY; + } + + PitchSector[0].upperlimit = SECTOR_BORDER; + PitchSector[index - 1].lowerlimit = SECTOR_BORDER * -1.0; + +/* get the current sector */ + curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch); + targetSector = curSector; +} + +void InitMotionDetection(void) +{ + targetSector = 0; + curSector = 0; + sectorSize = 0; + sectorCount = 0; + DefinePitchSectors(0); +} + +/* Map the current pitch value to a sector and create button event in case the sector is left */ +detectionState_t detectSectorButtonEvent(float curPitch) +{ + static uint8_t lastTargetSector = 0; + uint8_t newTargetSector; + uint8_t PitchEvent = DETECT_NOTHING; + +/* only change sector if reading is stable */ + newTargetSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch); + if(lastTargetSector == newTargetSector) + { + targetSector = newTargetSector; + } + lastTargetSector = newTargetSector; + if(targetSector != curSector) + { + if(targetSector > curSector) + { + curSector++; + PitchEvent = DETECT_POS_PITCH; + } + else + { + curSector--; + PitchEvent = DETECT_NEG_PITCH; + } + } + return PitchEvent; +} + + +/* Detect if user is generating an pitch including return to starting position */ /* This is done by feeding the past movements value per value into a state machine */ -detectionState_t detectShake(float currentPitch) +detectionState_t detectPitch(float currentPitch) { static uint8_t stableCnt = 0; static float lastPitch = 0.0; static float startPitch = 0.0; - static float minmax = 0.0; float curSpeed; - if((detectionState == DETECT_NEG_SHAKE) || (detectionState == DETECT_POS_SHAKE)) /* discard last detection */ + + if((detectionState == DETECT_NEG_PITCH) || (detectionState == DETECT_POS_PITCH)) /* discard last detection */ { detectionState = DETECT_NOTHING; } @@ -42,6 +149,11 @@ { stableCnt++; } + else + { + stableCnt=0; + } + if(stableCnt > STABLE_STATE_COUNT) { detectionState = DETECT_START; @@ -71,10 +183,9 @@ { if(stableCnt >= STABLE_STATE_COUNT) /* debounce movement */ { - if(fabsf(startPitch - currentPitch) > SHAKE_DELTA_COUNT) + if(fabsf(startPitch - currentPitch) > PITCH_DELTA_COUNT) { detectionState++; - minmax = lastPitch; } else { @@ -89,7 +200,8 @@ } break; case DETECT_MINIMA: - case DETECT_MAXIMA: if(fabsf(currentPitch - minmax ) < SHAKE_DELTA_COUNT) /* stay at maximum for short time to add a pattern for user interaction */ + case DETECT_MAXIMA: /* stay at maximum for short time to add a pattern for user interaction */ + if(fabsf(curSpeed) < MOVE_DELTA_SPEED ) { stableCnt++; } @@ -109,7 +221,7 @@ case DETECT_RISEBACK: case DETECT_FALLBACK: if(fabsf(curSpeed) < MOVE_DELTA_SPEED) { - if(fabsf(startPitch - currentPitch) < SHAKE_DELTA_END) + if(fabsf(startPitch - currentPitch) < PITCH_DELTA_END) { detectionState++; }