aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2014-09-23 17:24:57 +0200
committerLars-Dominik Braun <lars@6xq.net>2014-09-30 15:15:01 +0200
commit6708da2661d693f855b6f56d69af1e2fb8502463 (patch)
tree5b8eac0f6f40932417519cbdcd229caeabd8eee8
parent69cb10f51321a2443a3314c40fb2b8556aa804c0 (diff)
downloadhourglass-6708da2661d693f855b6f56d69af1e2fb8502463.tar.gz
hourglass-6708da2661d693f855b6f56d69af1e2fb8502463.tar.bz2
hourglass-6708da2661d693f855b6f56d69af1e2fb8502463.zip
Add wakeup source mechanism
Should reduce amount of cpu wakeups with expensive computations.
-rw-r--r--Makefile2
-rw-r--r--accel.c18
-rw-r--r--common.c4
-rw-r--r--common.h22
-rw-r--r--gyro.c18
-rw-r--r--i2c.c3
-rw-r--r--pwm.c5
-rw-r--r--timer.c6
-rw-r--r--ui.c13
9 files changed, 67 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index 56998e1..6d1783d 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@ CFLAGS=-Os -Wall -Wextra
all: sanduhr.hex
-sanduhr.elf: main.c i2c.c i2c.h uart.c uart.h timer.c timer.h gyro.c gyro.h accel.c accel.h common.h pwm.c pwm.h ui.c ui.h
+sanduhr.elf: main.c i2c.c i2c.h uart.c uart.h timer.c common.c timer.h gyro.c gyro.h accel.c accel.h common.h pwm.c pwm.h ui.c ui.h
avr-gcc -std=gnu99 -mmcu=$(MCU) $(CFLAGS) -o $@ $^
sanduhr.hex: sanduhr.elf
diff --git a/accel.c b/accel.c
index bd73043..ed2aa81 100644
--- a/accel.c
+++ b/accel.c
@@ -51,7 +51,13 @@ static bool reading = false;
/* data ready interrupt
*/
ISR(PCINT1_vect) {
- /* empty */
+ const bool interrupt = (PINC >> PINC1) & 0x1;
+ /* low-active */
+ if (!interrupt) {
+ enableWakeup (WAKE_ACCEL);
+ } else {
+ disableWakeup (WAKE_ACCEL);
+ }
}
void accelInit () {
@@ -79,6 +85,7 @@ void accelStart () {
}
sleepwhile (twr.status == TWST_WAIT);
puts ("accelStart done");
+ disableWakeup (WAKE_I2C);
}
/* register shake gesture
@@ -154,25 +161,26 @@ static void accelProcessHorizon () {
}
bool accelProcess () {
- if (reading) {
+ if (reading && shouldWakeup (WAKE_I2C)) {
+ disableWakeup (WAKE_I2C);
+ reading = false;
if (twr.status == TWST_OK) {
accelProcessHorizon ();
accelProcessShake ();
/* new data transfered */
- reading = false;
return true;
} else if (twr.status == TWST_ERR) {
puts ("accel i2c error: ");
fwrite ((void *) &twr.error, sizeof (twr.error), 1, stdout);
- reading = false;
}
} else {
- if (!((PINC >> PINC1) & 0x1) && twr.status == TWST_OK) {
+ if (shouldWakeup (WAKE_ACCEL) && twr.status == TWST_OK) {
/* new data available in device buffer and bus is free */
if (!twRequest (TWM_READ, LIS302DL, LIS302DL_OUTZ,
(uint8_t *) &zval, sizeof (zval))) {
puts ("cannot start read");
} else {
+ /* wakeup source is disabled by isr to prevent race condition */
reading = true;
}
}
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..e3f3195
--- /dev/null
+++ b/common.c
@@ -0,0 +1,4 @@
+#include "common.h"
+
+volatile uint8_t wakeup = 0;
+
diff --git a/common.h b/common.h
index 5957da3..fb53d4d 100644
--- a/common.h
+++ b/common.h
@@ -23,5 +23,27 @@
} \
}
+#include <stdbool.h>
+
+/* global wakeup flag, incremented by functions that interact with the main
+ * loop (i.e. not pwm) */
+extern volatile uint8_t wakeup;
+
+/* wakeup sources */
+enum {
+ WAKE_ACCEL = 0,
+ WAKE_GYRO = 1,
+ WAKE_I2C = 2,
+ WAKE_TIMER = 3,
+};
+
+#define shouldWakeup(x) (wakeup & (1 << x))
+#define enableWakeup(x) wakeup |= 1 << x;
+#include <util/atomic.h>
+#define disableWakeup(x) \
+ ATOMIC_BLOCK (ATOMIC_FORCEON) { \
+ wakeup &= ~(1 << x); \
+ }
+
#endif /* COMMON_H */
diff --git a/gyro.c b/gyro.c
index f31385d..fdf2d1f 100644
--- a/gyro.c
+++ b/gyro.c
@@ -31,7 +31,13 @@ static bool reading = false;
/* data ready interrupt
*/
ISR(PCINT0_vect) {
- /* empty */
+ const bool interrupt = (PINB >> PINB1) & 0x1;
+ /* high-active */
+ if (interrupt) {
+ enableWakeup (WAKE_GYRO);
+ } else {
+ disableWakeup (WAKE_GYRO);
+ }
}
void gyroInit () {
@@ -60,6 +66,7 @@ void gyroStart () {
}
sleepwhile (twr.status == TWST_WAIT);
puts ("gyroStart done");
+ disableWakeup (WAKE_I2C);
}
/* calculate ticks for z rotation
@@ -84,7 +91,9 @@ static void gyroProcessTicks () {
/* process gyro sensor data, returns true if new data is available
*/
bool gyroProcess () {
- if (reading) {
+ if (reading && shouldWakeup (WAKE_I2C)) {
+ disableWakeup (WAKE_I2C);
+ reading = false;
if (twr.status == TWST_OK) {
/* new data transfered, process it */
/* poor man's noise filter */
@@ -92,19 +101,18 @@ bool gyroProcess () {
zaccum += zval;
}
gyroProcessTicks ();
- reading = false;
return true;
} else if (twr.status == TWST_ERR) {
puts ("gyro i2c error");
- reading = false;
}
} else {
- if (((PINB >> PINB1) & 0x1) && twr.status == TWST_OK) {
+ if (shouldWakeup (WAKE_GYRO) && twr.status == TWST_OK) {
/* new data available in device buffer and bus is free */
if (!twRequest (TWM_READ, L3GD20, L3GD20_OUTZ,
(uint8_t *) &zval, sizeof (zval))) {
puts ("cannot start read");
} else {
+ /* wakeup source is disabled by isr to prevent race condition */
reading = true;
}
}
diff --git a/i2c.c b/i2c.c
index 00dee14..a94b3a0 100644
--- a/i2c.c
+++ b/i2c.c
@@ -255,5 +255,8 @@ ISR(TWI_vect) {
assert (0 && "nope\n");
break;
}
+ if (twr.status == TWST_ERR || twr.status == TWST_OK) {
+ enableWakeup (WAKE_I2C);
+ }
}
diff --git a/pwm.c b/pwm.c
index 568ed73..944720e 100644
--- a/pwm.c
+++ b/pwm.c
@@ -19,7 +19,6 @@ static const uint8_t offbits[2] = {(uint8_t) ~((1 << PB6) | (1 << PB7)),
(uint8_t) ~((1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5) | (1 << PD6))};
ISR(TIMER0_COMPA_vect) {
-#warning "speaker works now, led1 and 2 do not work"
if (speakerCount > 0) {
--speakerCount;
/* stop speaker after beep */
@@ -36,6 +35,8 @@ ISR(TIMER0_COMPA_vect) {
/* auto wrap-around */
count = (count+1) & (PWM_MAX_BRIGHTNESS-1);
+
+ /* no wakeup */
}
static uint8_t ledToArray (const uint8_t i) {
@@ -105,7 +106,7 @@ void pwmSet (const uint8_t i, const uint8_t value) {
}
}
-void speakerStart (const speakerMode mode) {
+void speakerStart (const speakerMode mode __unused__) {
/* 12.8ms */
speakerCount = 100;
for (uint8_t i = 0; i < PWM_MAX_BRIGHTNESS; i += 2) {
diff --git a/timer.c b/timer.c
index ce30b60..8de6157 100644
--- a/timer.c
+++ b/timer.c
@@ -22,13 +22,17 @@ ISR(TIMER1_COMPA_vect) {
time += OCR1A * US_PER_TICK;
if (hits == maxhits-1) {
OCR1A = lastcount;
+ } else if (hits >= maxhits) {
+ enableWakeup (WAKE_TIMER);
}
}
/* Check if timer was hit, return time since last restart or 0 if not hit yet
*/
uint32_t timerHit () {
- if (hits >= maxhits) {
+ if (shouldWakeup (WAKE_TIMER)) {
+ disableWakeup (WAKE_TIMER);
+
const uint32_t ret = time;
/* reset timer, start again */
hits = 0;
diff --git a/ui.c b/ui.c
index 7bd393d..9175133 100644
--- a/ui.c
+++ b/ui.c
@@ -266,14 +266,6 @@ static void doInit () {
}
}
-/* Sleep CPU
- */
-static void cpuSleep () {
- sleep_enable ();
- sleep_cpu ();
- sleep_disable ();
-}
-
/* Main loop
*/
void uiLoop () {
@@ -329,7 +321,7 @@ void uiLoop () {
while (1) {
processSensors ();
-
+
horizon newh = accelGetHorizon ();
if (newh != h) {
horizonChanged = true;
@@ -367,7 +359,8 @@ void uiLoop () {
assert (0 && "invalid ui mode");
break;
}
- cpuSleep ();
+
+ sleepwhile (wakeup == 0);
#if 0
printf ("t=%i, h=%i, s=%i\n", gyroGetZTicks (), accelGetHorizon (),