aboutsummaryrefslogtreecommitdiff
path: root/accel.c
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2014-12-09 12:42:20 +0100
committerLars-Dominik Braun <lars@6xq.net>2014-12-09 12:42:20 +0100
commit254fb0c490c62c0e29518cab2d8b5c90a30b378c (patch)
tree0fe5007234b954d9039796387b3fc6356f824876 /accel.c
parent1d0d6f316707cbaac23b3b0b77b5d554f6e7954d (diff)
downloadhourglass-254fb0c490c62c0e29518cab2d8b5c90a30b378c.tar.gz
hourglass-254fb0c490c62c0e29518cab2d8b5c90a30b378c.tar.bz2
hourglass-254fb0c490c62c0e29518cab2d8b5c90a30b378c.zip
accel: Fix shake gesture detection
Diffstat (limited to 'accel.c')
-rw-r--r--accel.c101
1 files changed, 50 insertions, 51 deletions
diff --git a/accel.c b/accel.c
index ce44c42..350bf9f 100644
--- a/accel.c
+++ b/accel.c
@@ -1,6 +1,7 @@
#include "common.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
@@ -20,25 +21,27 @@
#define LIS302DL_OUTZ 0x2D
/* value for 1g with +-2g max; measured */
-#define ACCEL_1G_POS (55)
-#define ACCEL_1G_NEG (-55)
+#define ACCEL_1G (55)
/* offset for horizon detection */
#define ACCEL_1G_OFF (5)
-/* shake detection values; 2g for +-2g max */
-#define ACCEL_SHAKE_POS (INT8_MAX)
-#define ACCEL_SHAKE_NEG (INT8_MIN)
-/* 250ms for 100Hz data rate */
-#define ACCEL_SHAKE_TIMEOUT (25)
+/* threshold starting shake detection */
+#define ACCEL_SHAKE_START (70)
+/* difference prev and current value to get the current one registered as peak */
+#define ACCEL_SHAKE_REGISTER (120)
+/* 100ms for 100Hz data rate */
+#define ACCEL_SHAKE_TIMEOUT (10)
/* z value */
-static volatile int8_t zval = 0;
+static volatile int8_t zval = 0, zvalnormal = 0;
+
/* number of times shaken (i.e. peak level measured) */
static uint8_t shakeCount = 0;
/* if max in one direction direction has been detected give it some time to
* wait for max in the other direction */
static uint8_t shakeTimeout = 0;
-/* sign of last shake peak */
-static enum {SHAKE_NONE, SHAKE_POS, SHAKE_NEG} shakeSign = SHAKE_NONE;
+static int8_t prevShakeVal = 0;
+static uint8_t peakCount = 0;
+
/* horizon position */
/* current */
static horizon horizonSign = HORIZON_NONE;
@@ -46,6 +49,7 @@ static horizon horizonSign = HORIZON_NONE;
static uint8_t horizonStable = 0;
/* previous measurement */
static horizon horizonPrevSign = HORIZON_NONE;
+
/* currently reading from i2c */
static bool reading = false;
@@ -91,49 +95,32 @@ void accelStart () {
/* register shake gesture
*
- * “shake” means a peak in one direction followed by another one in the other
- * direction. called for every data set pulled.
+ * “shake” means three peaks in directions 1, -1, 1
*/
static void accelProcessShake () {
- /* detect shake if:
- * a) horizon is positive and accel z value is >= ACCEL_SHAKE_POS
- * b) horizon is negative and accel z value is >= ACCEL_SHAKE_POS offset by
- * the value for 1g (negative)
- * (same for negative horizon)
- */
- if (((zval >= ACCEL_SHAKE_POS &&
- horizonSign == HORIZON_POS) ||
- (zval >= (ACCEL_SHAKE_POS + ACCEL_1G_NEG) &&
- horizonSign == HORIZON_NEG)) &&
- shakeSign != SHAKE_POS) {
- /* if we did not time out (i.e. max in other direction has been
- * detected) register shake */
- if (shakeTimeout > 0) {
- ++shakeCount;
- /* correctly detect double/triple/… shakes; setting this to
- * ACCEL_SHAKE_TIMEOUT yields wrong results */
- shakeTimeout = 0;
- } else {
+ if (shakeTimeout > 0) {
+ --shakeTimeout;
+ if (abs ((int16_t) prevShakeVal - (int16_t) zvalnormal) > ACCEL_SHAKE_REGISTER) {
+ ++peakCount;
shakeTimeout = ACCEL_SHAKE_TIMEOUT;
+ prevShakeVal = zvalnormal;
+ } else if (sign (prevShakeVal) == sign (zvalnormal) &&
+ abs (zvalnormal) > abs (prevShakeVal)) {
+ /* actually we did not measure the peak yet */
+ prevShakeVal = zvalnormal;
}
- shakeSign = SHAKE_POS;
- } else if (((zval <= ACCEL_SHAKE_NEG &&
- horizonSign == HORIZON_NEG) ||
- (zval <= (ACCEL_SHAKE_NEG + ACCEL_1G_POS) &&
- horizonSign == HORIZON_POS)) &&
- shakeSign != SHAKE_NEG) {
- if (shakeTimeout > 0) {
- ++shakeCount;
- shakeTimeout = 0;
- } else {
- shakeTimeout = ACCEL_SHAKE_TIMEOUT;
- }
- shakeSign = SHAKE_NEG;
- } else {
- if (shakeTimeout > 0) {
- --shakeTimeout;
+ if (shakeTimeout == 0) {
+ /* just timed out, can register gesture now. XXX: why 3? */
+ shakeCount += peakCount/3;
}
}
+
+ /* start shake detection */
+ if (shakeTimeout == 0 && abs (zvalnormal) > ACCEL_SHAKE_START) {
+ shakeTimeout = ACCEL_SHAKE_TIMEOUT;
+ peakCount = 1;
+ prevShakeVal = zvalnormal;
+ }
}
/* register horizon change
@@ -142,12 +129,12 @@ static void accelProcessShake () {
*/
static void accelProcessHorizon () {
/* measuring approximately 1g */
- if (zval > (ACCEL_1G_POS - ACCEL_1G_OFF) &&
- zval < (ACCEL_1G_POS + ACCEL_1G_OFF) &&
+ if (zval > (ACCEL_1G - ACCEL_1G_OFF) &&
+ zval < (ACCEL_1G + ACCEL_1G_OFF) &&
horizonPrevSign == HORIZON_POS && horizonSign != HORIZON_POS) {
++horizonStable;
- } else if (zval < (ACCEL_1G_NEG + ACCEL_1G_OFF)
- && zval > (ACCEL_1G_NEG - ACCEL_1G_OFF) &&
+ } else if (zval < (-ACCEL_1G + ACCEL_1G_OFF)
+ && zval > (-ACCEL_1G - ACCEL_1G_OFF) &&
horizonPrevSign == HORIZON_NEG && horizonSign != HORIZON_NEG) {
++horizonStable;
} else {
@@ -167,6 +154,14 @@ bool accelProcess () {
reading = false;
if (twr.status == TWST_OK) {
accelProcessHorizon ();
+
+ /* calculate normalized z (i.e. without earth gravity component) */
+ if (horizonSign == HORIZON_NEG) {
+ zvalnormal = zval - (-ACCEL_1G);
+ } else if (horizonSign == HORIZON_POS) {
+ zvalnormal = zval - ACCEL_1G;
+ }
+
accelProcessShake ();
/* new data transfered */
return true;
@@ -194,6 +189,10 @@ int8_t accelGetZ () {
return zval;
}
+int8_t accelGetNormalizedZ () {
+ return zvalnormal;
+}
+
uint8_t accelGetShakeCount () {
return shakeCount;
}