Root/tornado/fw/accel.c

1/*
2 * fw/accel.c - Acceleration sensor
3 *
4 * Written 2012 by Werner Almesberger
5 * Copyright 2012 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include <stddef.h>
15#include <stdbool.h>
16#include <stdint.h>
17
18#include <avr/io.h>
19#include <avr/interrupt.h>
20#define F_CPU 8000000UL
21#include <util/delay.h>
22
23#include "io.h"
24#include "accel.h"
25
26
27void (*sample)(uint16_t x, uint16_t y) = NULL;
28
29
30static bool chan_x;
31
32
33static inline void admux(bool x)
34{
35    ADMUX =
36        1 << REFS0 | /* Vref is AVcc */
37        (x ? ADC_X : ADC_Y);
38}
39
40
41static inline void adcsra(bool start)
42{
43    /*
44     * The ADC needs to run at clkADC <= 200 kHz for full resolution.
45     * At clkADC = 125 kHz, a conversion takes about 110 us.
46     */
47    ADCSRA =
48        1 << ADEN | /* enable ADC */
49        (start ? 1 << ADSC : 0) |
50        1 << ADIE | /* enable ADC interrupts */
51        6; /* clkADC = clk/64 -> 125 kHz */
52}
53
54
55uint16_t measure_ref(void)
56{
57    while (ADCSRA & (1 << ADSC));
58    adcsra(0);
59    ADMUX =
60        1 << REFS0 | /* Vref is AVcc */
61        14; /* Vbg (1.1 V) */
62    _delay_us(100);
63    adcsra(1);
64    while (ADCSRA & (1 << ADSC));
65    return ADC;
66}
67
68
69ISR(ADC_vect)
70{
71    static uint16_t last_x;
72    uint16_t v;
73
74    v = ADC;
75
76    if (chan_x) {
77        last_x = v;
78        chan_x = 0;
79        admux(0);
80        adcsra(1);
81    } else {
82        sample(last_x, v);
83    }
84}
85
86
87ISR(TIMER0_OVF_vect)
88{
89    chan_x = 1;
90    admux(1);
91    adcsra(1);
92}
93
94
95void accel_start(void)
96{
97    adcsra(0);
98
99    TCNT0 = 0;
100    OCR0A = 62; /* 8 MHz/64/62 = 2.02 kHz */
101    TCCR0A =
102        1 << WGM01 | /* WG Mode 7 (Fast PWM to OCR0A) */
103        1 << WGM00;
104    TCCR0B =
105        1 << WGM02 | /* WG Mode 7, continued */
106        1 << CS01 | /* clkIO/64 */
107        1 << CS00;
108    TIMSK0 = 1 << TOIE0; /* interrupt on overflow */
109}
110

Archive Download this file

Branches:
master
tornado-v1



interactive