diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | gyroscope.c | 84 | ||||
-rw-r--r-- | gyroscope.h | 13 | ||||
-rw-r--r-- | i2c.h | 3 | ||||
-rw-r--r-- | main.c | 34 | ||||
-rw-r--r-- | timer.c | 2 |
6 files changed, 114 insertions, 24 deletions
@@ -2,7 +2,7 @@ MCU = atmega88 all: sanduhr.hex -sanduhr.elf: main.c i2c.c i2c.h uart.c uart.h timer.c timer.h +sanduhr.elf: main.c i2c.c i2c.h uart.c uart.h timer.c timer.h gyroscope.c gyroscope.h avr-gcc -std=gnu99 -mmcu=$(MCU) -Os -o $@ $^ sanduhr.hex: sanduhr.elf diff --git a/gyroscope.c b/gyroscope.c new file mode 100644 index 0000000..0f932c2 --- /dev/null +++ b/gyroscope.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/sleep.h> + +#include "i2c.h" +#include "gyroscope.h" + +/* device address */ +#define L3GD20 0b11010100 +/* registers */ +#define L3GD20_WHOAMI 0xf +#define L3GD20_CTRLREG1 0x20 +#define L3GD20_CTRLREG3 0x22 +#define L3GD20_CTRLREG4 0x23 + +#define sleepwhile(cond) \ + sleep_enable (); \ + while (cond) { sleep_cpu (); } \ + sleep_disable (); + +/* the first interrupt is lost */ +volatile bool drdy = true; +volatile int16_t val[3] = {0, 0, 0}; + +/* data ready interrupt + */ +ISR(PCINT0_vect) { + drdy = true; +} + +void gyroscopeInit () { + /* set PB1 to input, with pull-up */ + DDRB = (DDRB & ~((1 << PB1))); + PORTB = (PORTB | (1 << PB1)); + /* enable interrupt PCI0 */ + PCICR = (1 << PCIE0); + /* enable interrupts on PB1/PCINT1 */ + PCMSK0 = (1 << 1); +} + +/* XXX: make nonblocking */ +void gyroscopeStart () { + /* XXX: implement multi-write */ + /* disable power-down-mode */ + if (!twWrite (L3GD20, L3GD20_CTRLREG1, 0b00001111)) { + printf ("cannot start write\n"); + } + sleepwhile (twr.status == TWST_WAIT); + printf ("final twi status was %i\n", twr.status); + + /* enable drdy interrupt */ + if (!twWrite (L3GD20, L3GD20_CTRLREG3, 0b00001000)) { + printf ("cannot start write\n"); + } + sleepwhile (twr.status == TWST_WAIT); + printf ("final twi status was %i\n", twr.status); + + /* select 500dps */ + if (!twWrite (L3GD20, L3GD20_CTRLREG4, 0b00010000)) { + printf ("cannot start write\n"); + } + sleepwhile (twr.status == TWST_WAIT); + printf ("final twi status was %i\n", twr.status); +} + +bool gyroscopeRead () { + if (drdy) { + drdy = false; + + if (!twReadMulti (L3GD20, 0x28, (uint8_t *) val, 6)) { + printf ("cannot start read\n"); + } + + return true; + } else { + return false; + } +} + +volatile const int16_t *gyroscopeGet () { + return val; +} + diff --git a/gyroscope.h b/gyroscope.h new file mode 100644 index 0000000..20ef373 --- /dev/null +++ b/gyroscope.h @@ -0,0 +1,13 @@ +#ifndef GYROSCOPE_H +#define GYROSCOPE_H + +#include <stdbool.h> +#include <stdint.h> + +void gyroscopeInit (); +void gyroscopeStart (); +bool gyroscopeRead (); +volatile const int16_t *gyroscopeGet (); + +#endif /* GYROSCOPE_H */ + @@ -33,9 +33,6 @@ typedef struct { extern volatile twReq twr; /* i2c device addresses */ -#define L3GD20 0b11010100 -#define L3GD20_WHOAMI 0xf -#define L3GD20_CTRLREG1 0x20 #define LIS302DL 0b00111000 #define LIS302DL_WHOAMI 0xf #define LIS302DL_CTRLREG1 0x20 @@ -11,6 +11,7 @@ #include "i2c.h" #include "uart.h" #include "timer.h" +#include "gyroscope.h" static void ledInit () { /* set led1,led2 to output */ @@ -42,36 +43,29 @@ int main () { ledInit (); twInit (); uartInit (); + gyroscopeInit (); set_sleep_mode (SLEEP_MODE_IDLE); - + printf ("initialization done\n"); /* global interrupt enable */ sei (); - /* disable power-down-mode */ - if (!twWrite (LIS302DL, LIS302DL_CTRLREG1, 0b01000111)) { - printf ("cannot start write\n"); - } - sleepwhile (twr.status == TWST_WAIT); - printf ("final twi status was %i\n", twr.status); + gyroscopeStart (); - timerStart (); - unsigned char seconds = 0; + //timerStart (); while (1) { - uint8_t val[6]; - - sleepwhile (!timerHit ()); - ++seconds; - printf ("running for %u seconds\n", seconds); + //sleepwhile (!timerHit ()); + //printf ("running for %u seconds\n", seconds); - if (!twReadMulti (LIS302DL, 0x28, val, 6)) { - printf ("cannot start read\n"); - } + sleepwhile (!gyroscopeRead ()); sleepwhile (twr.status == TWST_WAIT); - printf ("%i/%i/%i\n", (int8_t) val[1], (int8_t) val[3], - (int8_t) val[5]); + + volatile const int16_t *val = gyroscopeGet (); + printf ("%i/%i/%i\n", val[0], val[1], val[2]); + + _delay_ms (50); } - timerStop (); + //timerStop (); /* global interrupt disable */ cli (); @@ -6,6 +6,8 @@ volatile unsigned char count = 0; volatile unsigned char hit = 0; +/* XXX: use high-res timer1 for doing this + */ ISR(TIMER0_OVF_vect) { /* there seems to be no mode of operation which disconnects pin OC0A _and_ * clears the value */ |