changeset 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 75eedde05ff6
children ef1b8579166c
files Discovery/Inc/motion.h Discovery/Inc/text_multilanguage.h Discovery/Src/base.c Discovery/Src/motion.c Discovery/Src/tMenuEditSystem.c Discovery/Src/text_multilanguage.c
diffstat 6 files changed, 210 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/Discovery/Inc/motion.h	Mon Aug 19 17:50:55 2019 +0200
+++ b/Discovery/Inc/motion.h	Sun Sep 08 13:45:17 2019 +0200
@@ -10,13 +10,15 @@
 
 
 /* exported data types */
-#define CUSTOMER_DEFINED_VIEWS	(100u)	/* value will cause the function to detect the numer of selected views */
+#define CUSTOMER_DEFINED_VIEWS	(100u)	/* value will cause the function to detect the number of selected views */
+#define CUSTOMER_KEEP_LAST_SECTORS	(200u)	/* do not update number of sectors, just define the new center position */
 
 typedef enum
 {
 		MOTION_DETECT_OFF = 0,
 		MOTION_DETECT_SECTOR,
-		MOTION_DETECT_MOVE
+		MOTION_DETECT_MOVE,
+		MOTION_DETECT_SCROLL
 } MotionDetectMethod_t;
 
 typedef enum
@@ -43,5 +45,6 @@
 void DefinePitchSectors(float centerAngle, uint8_t numOfSectors);
 detectionState_t detectPitch(float currentPitch);
 detectionState_t detectSectorButtonEvent(float curPitch);
+detectionState_t detectScrollButtonEvent(float curPitch);
 
 #endif /* INC_MOTION_H_ */
--- a/Discovery/Inc/text_multilanguage.h	Mon Aug 19 17:50:55 2019 +0200
+++ b/Discovery/Inc/text_multilanguage.h	Sun Sep 08 13:45:17 2019 +0200
@@ -278,6 +278,7 @@
 		TXT2BYTE_MoCtrlNone,
 		TXT2BYTE_MoCtrlPitch,
 		TXT2BYTE_MoCtrlSector,
+		TXT2BYTE_MoCtrlScroll,
 		/* */
 		TXT2BYTE_DecoDataLost,
 		TXT2BYTE_Info,
--- a/Discovery/Src/base.c	Mon Aug 19 17:50:55 2019 +0200
+++ b/Discovery/Src/base.c	Sun Sep 08 13:45:17 2019 +0200
@@ -494,6 +494,8 @@
         			break;
         		case MOTION_DETECT_SECTOR: pitchstate = detectSectorButtonEvent(stateRealGetPointer()->lifeData.compass_pitch);
         			break;
+        		case MOTION_DETECT_SCROLL: pitchstate = detectScrollButtonEvent(stateRealGetPointer()->lifeData.compass_pitch);
+        		     break;
         		default:
         			pitchstate = DETECT_NOTHING;
         			break;
@@ -902,9 +904,9 @@
 						if ((status.page == PageDive) && (status.line == 0))
 						{
 							tHome_change_customview_button_pressed(action);
-							if((settingsGetPointer()->MotionDetection == MOTION_DETECT_SECTOR) && (action == ACTION_BUTTON_ENTER))  /* Button pressed while sector detection is active => calibrate to current pitch value */
+							if((settingsGetPointer()->MotionDetection != MOTION_DETECT_OFF) && (action == ACTION_BUTTON_ENTER))  /* Button pressed while motion detection is active => calibrate to current pitch value */
 							{
-								DefinePitchSectors(stateRealGetPointer()->lifeData.compass_pitch,CUSTOMER_DEFINED_VIEWS);
+								DefinePitchSectors(stateRealGetPointer()->lifeData.compass_pitch,CUSTOMER_KEEP_LAST_SECTORS);
 							}
 						}
 						else if (status.page == PageSurface)
--- a/Discovery/Src/motion.c	Mon Aug 19 17:50:55 2019 +0200
+++ b/Discovery/Src/motion.c	Sun Sep 08 13:45:17 2019 +0200
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 #include <string.h>
+#include <stdlib.h>
 #include <math.h>
 #include "motion.h"
 #include "data_central.h"
@@ -20,21 +21,22 @@
 #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_WINDOW				80.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 */
 
-#define SECTOR_MAX					10		/* maximum number of sectors */
+#define SECTOR_MAX					20		/* maximum number of sectors */
+#define SECTOR_SCROLL				6		/* number of sectors used for scroll detection */
 
-static detectionState_t detectionState = DETECT_NOTHING;
+detectionState_t detectionState = DETECT_NOTHING;
 
-static uint8_t curSector;
+uint8_t curSector;
 static uint8_t targetSector;
 static uint8_t sectorSize;
 static uint8_t sectorCount;
 
-SSector PitchSector[10];			/* max number of enabled custom views */
+SSector PitchSector[SECTOR_MAX];			/* max number of enabled custom views */
 
 
 uint8_t GetSectorForPitch(float pitch)
@@ -70,12 +72,13 @@
 	if(numOfSectors == CUSTOMER_DEFINED_VIEWS)
 	{
 		sectorCount =  t7_GetEnabled_customviews();
-		if(sectorCount > 5)
+		if(sectorCount > 7)
 		{
-			sectorCount = 5;	/* more views are hard to manually control */
+			sectorCount = 7;	/* more views are hard to manually control */
 		}
 	}
 	else
+	if(numOfSectors != CUSTOMER_KEEP_LAST_SECTORS)
 	{
 		sectorCount = numOfSectors;
 	}
@@ -111,6 +114,8 @@
 			break;
 		case MOTION_DETECT_MOVE: DefinePitchSectors(0,SECTOR_MAX);
 			break;
+		case MOTION_DETECT_SCROLL: DefinePitchSectors(0,SECTOR_SCROLL);
+			break;
 		default:
 			break;
 	}
@@ -147,22 +152,184 @@
 	return PitchEvent;
 }
 
+/* Check if pitch is not in center position and trigger a button action if needed */
+detectionState_t detectScrollButtonEvent(float curPitch)
+{
+	static uint8_t	delayscroll = 0;		/* slow dow the number of scroll events */
 
+	uint8_t PitchEvent = DETECT_NOTHING;
+	uint8_t newSector;
+
+	if(delayscroll == 0)
+	{
+		newSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
+		/* for scroll detection the motion windoe is split into 6 sectors => set event accoring to the sector number*/
+		switch(newSector)
+		{
+			case 0:
+			case 1:	PitchEvent = DETECT_POS_PITCH;
+				break;
+			case 4:
+			case 5:	PitchEvent = DETECT_NEG_PITCH;
+				break;
+			default:
+				break;
+		}
+		if(PitchEvent != DETECT_NOTHING)
+		{
+			delayscroll = 5;
+		}
+	}
+	else
+	{
+		delayscroll--;
+	}
+	return PitchEvent;
+}
+
+
+uint8_t sectorhist[20];
+uint8_t sectorindex = 0;
 /* 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 detectPitch(float currentPitch)
 {
+	static uint8_t lastSector = 0;
+	static uint8_t startSector = 0;
 	static uint8_t stableCnt = 0;
-	static float lastPitch = 0.0;
-	static float startPitch = 0.0;
-	float curSpeed;
-
 
 	if((detectionState == DETECT_NEG_PITCH) || (detectionState == DETECT_POS_PITCH))	/* discard last detection */
 	{
 		detectionState = DETECT_NOTHING;
 	}
 
+	curSector = GetSectorForPitch(stateRealGetPointer()->lifeData.compass_pitch);
+
+	sectorhist[sectorindex++] = curSector;
+	if(sectorindex == 20) sectorindex=0;
+
+	/* feed value into state machine */
+	switch (detectionState)
+	{
+			case DETECT_NOTHING: 	if(curSector == lastSector)	/* detect a stable condition before evaluating for the next move */
+									{
+										stableCnt++;
+									}
+									else
+									{
+										stableCnt=0;
+									}
+
+									if(stableCnt > STABLE_STATE_COUNT)
+									{
+										detectionState = DETECT_START;
+										stableCnt = 0;
+										startSector = lastSector;
+									}
+				break;
+			case DETECT_START:		if(curSector != lastSector)
+									{
+										if(abs(curSector - startSector) > 1)
+										{
+											if(curSector > lastSector)
+											{
+												detectionState = DETECT_POS_MOVE;
+											}
+											else
+											{
+												detectionState = DETECT_NEG_MOVE;
+											}
+											stableCnt = 0;
+											startSector = lastSector;
+										}
+										else
+										{
+											stableCnt++;		/* reset start sector in case of slow movement */
+										}
+								//		startPitch = lastPitch;
+									}
+				break;
+			case DETECT_NEG_MOVE:
+			case DETECT_POS_MOVE:	if(curSector != lastSector) /* still moving?  */
+									{
+										stableCnt++;
+									}
+									else
+									{
+				//						if(stableCnt >= 1)	/* debounce movement */
+										{
+											if(abs(startSector - curSector) > 2)
+											{
+												detectionState++;
+												stableCnt = 0;
+											}
+											else
+											{
+											//	detectionState = DETECT_NOTHING;
+												stableCnt++;	/* maybe on the boundary of a sector => handle as stable */
+											}
+										}
+#if 0
+										else
+										{
+									//		detectionState = DETECT_NOTHING;
+											stableCnt++;	/* maybe on the boundary of a sector => handle as stable */
+										}
+#endif
+									}
+				break;
+			case DETECT_MINIMA:
+			case DETECT_MAXIMA:		/* stay at maximum for short time to add a pattern for user interaction */
+									if(curSector == lastSector)
+									{
+										stableCnt++;
+									}
+									else
+									{
+										if(stableCnt > 0)	/* restart movement after a short break? */
+										{
+											detectionState++;
+											stableCnt = 0;
+										}
+										else
+										{
+								//			detectionState = DETECT_NOTHING;
+											stableCnt++;	/* maybe on the boundary of a sector => handle as stable */
+										}
+									}
+				break;
+			case DETECT_RISEBACK:
+			case DETECT_FALLBACK:	if(curSector == lastSector)		/* check if we are back at start position at end of movement */
+									{
+										if(abs(startSector - curSector) <= 1) //(curSector == startSector)
+										{
+											detectionState++;
+											stableCnt = 0;
+										}
+										else
+										{
+																		//			detectionState = DETECT_NOTHING;
+																					stableCnt++;	/* maybe on the boundary of a sector => handle as stable */
+										}
+									}
+									else
+									{
+										stableCnt++;
+									}
+				break;
+			default:
+				detectionState = DETECT_NOTHING;
+				break;
+
+	}
+	lastSector = curSector;
+	if(stableCnt > STABLE_STATE_TIMEOUT)
+	{
+		detectionState = DETECT_NOTHING;
+		stableCnt = 0;
+	}
+
+#if 0
 	curSpeed = currentPitch - lastPitch;
 
 	/* feed value into state machine */
@@ -263,5 +430,6 @@
 	}
 
 	lastPitch = currentPitch;
+#endif
 	return detectionState;
 }
--- a/Discovery/Src/tMenuEditSystem.c	Mon Aug 19 17:50:55 2019 +0200
+++ b/Discovery/Src/tMenuEditSystem.c	Sun Sep 08 13:45:17 2019 +0200
@@ -155,6 +155,7 @@
 
     pSettings->cv_configuration ^= 1 << (cv_changelist[line-1]);
     WriteSettings = 1;
+    InitMotionDetection(); /* consider new view setup for view selection by motion */
     exitMenuEdit_to_Menu_with_Menu_Update();
 }
 
@@ -925,6 +926,9 @@
 		case MOTION_DETECT_SECTOR:
 			text[5] = TXT2BYTE_MoCtrlSector;
 			break;
+		case MOTION_DETECT_SCROLL:
+			text[5] = TXT2BYTE_MoCtrlScroll;
+					break;
 		default:
 			snprintf(&text[4],2,"%u",settingsGetPointer()->MotionDetection);
 		break;
@@ -1075,20 +1079,24 @@
     uint8_t newValue;
     switch(settingsGetPointer()->MotionDetection)
     {
-    case 0:
-        newValue = 1;
+    case MOTION_DETECT_OFF:
+        newValue = MOTION_DETECT_MOVE;
         break;
-    case 1:
-        newValue = 2;
+    case MOTION_DETECT_MOVE:
+        newValue = MOTION_DETECT_SECTOR;
         break;
-    case 2:
-        newValue = 0;
+    case MOTION_DETECT_SECTOR:
+        newValue = MOTION_DETECT_SCROLL;
         break;
+    case MOTION_DETECT_SCROLL:
+    	newValue = MOTION_DETECT_OFF;
+    	break;
     default:
-        newValue = 0;
+        newValue = MOTION_DETECT_OFF;
         break;
     }
     settingsGetPointer()->MotionDetection = newValue;
+    InitMotionDetection();
     return UNSPECIFIC_RETURN;
 }
 
--- a/Discovery/Src/text_multilanguage.c	Mon Aug 19 17:50:55 2019 +0200
+++ b/Discovery/Src/text_multilanguage.c	Sun Sep 08 13:45:17 2019 +0200
@@ -1287,6 +1287,11 @@
 static uint8_t text_IT_MoCtrlSector[] = "Sector";
 static uint8_t text_ES_MoCtrlSector[] = "Sector";
 
+static uint8_t text_EN_MoCtrlScroll[] = "Scroll";
+static uint8_t text_DE_MoCtrlScroll[] = "Karussell";
+static uint8_t text_FR_MoCtrlScroll[] = "Scroll";
+static uint8_t text_IT_MoCtrlScroll[] = "Scroll";
+static uint8_t text_ES_MoCtrlScroll[] = "Scroll";
 
 // Menu SYS2 Reset RTE and Firmware Update During Bluetooth Connection
 static uint8_t text_EN_DecoDataLost[] = "Decompression data will be lost";
@@ -1746,6 +1751,7 @@
 	{(uint8_t)TXT2BYTE_MoCtrlNone,		{text_EN_MoCtrlNone, text_DE_MoCtrlNone, text_FR_MoCtrlNone, text_IT_MoCtrlNone, text_ES_MoCtrlNone}},
 	{(uint8_t)TXT2BYTE_MoCtrlPitch,		{text_EN_MoCtrlPitch, text_DE_MoCtrlPitch, text_FR_MoCtrlPitch, text_IT_MoCtrlPitch, text_ES_MoCtrlPitch}},
 	{(uint8_t)TXT2BYTE_MoCtrlSector,	{text_EN_MoCtrlSector, text_DE_MoCtrlSector, text_FR_MoCtrlSector, text_IT_MoCtrlSector, text_ES_MoCtrlSector}},
+	{(uint8_t)TXT2BYTE_MoCtrlScroll,	{text_EN_MoCtrlScroll, text_DE_MoCtrlScroll, text_FR_MoCtrlScroll, text_IT_MoCtrlScroll, text_ES_MoCtrlScroll}},
     {(uint8_t)TXT2BYTE_DecoDataLost,	{text_EN_DecoDataLost, text_DE_DecoDataLost, text_FR_DecoDataLost, text_IT_DecoDataLost, text_ES_DecoDataLost}},
     {(uint8_t)TXT2BYTE_Info,			{text_EN_Info, text_DE_Info, text_FR_Info, text_IT_Info, text_ES_Info}},
     {(uint8_t)TXT2BYTE_Korrekturwerte,  {text_EN_Korrekturwerte, text_DE_Korrekturwerte, text_FR_Korrekturwerte, text_IT_Korrekturwerte, text_ES_Korrekturwerte}},