Root/tornado/fw/tornado.c

1#include <stdbool.h>
2#include <stdint.h>
3
4#include <avr/interrupt.h>
5#include <avr/pgmspace.h>
6#define F_CPU 8000000UL
7#include <util/delay.h>
8
9#include "io.h"
10#include "led.h"
11#include "mmc.h"
12#include "accel.h"
13
14
15#define HIGH(port) \
16    (MASK(port, CARD_nPWR) | \
17    MASK(port, SW_N) | MASK(port, SW_E) | MASK(port, SW_S) | \
18    MASK(port, SW_W) | MASK(port, SW_SW))
19
20#define OUTPUTS(port) \
21    (MASK(port, CARD_nPWR) | MASK(port, CARD_CLK) | \
22    MASK(port, LED_DS) | MASK(port, LED_LCLK) | MASK(port, LED_SCLK))
23
24
25#if 0
26
27/*
28 * @@@ For testing, connect the LED bar via the 8:10 card slot, so that it
29 * can be disconnected without soldering.
30 */
31
32#define SCLK CARD_DAT1
33#define LCLK CARD_DAT0
34#define DS CARD_CLK
35#define VDD CARD_CMD
36
37#else
38
39#define SCLK LED_SCLK
40#define LCLK LED_LCLK
41#define DS LED_DS
42
43#endif
44
45
46static void send(uint8_t pattern[N_LEDS/8])
47{
48    uint8_t i, j, mask;
49
50    for (i = 0; i != N_LEDS/8; i++) {
51        mask = 1;
52        for (j = 0; j != 8; j++) {
53            if (pattern[i] & mask)
54                SET(DS);
55            else
56                CLR(DS);
57            SET(SCLK);
58            CLR(SCLK);
59            mask <<= 1;
60        }
61    }
62    SET(LCLK);
63    CLR(LCLK);
64}
65
66
67static inline void admux(bool x)
68{
69    ADMUX =
70        1 << REFS0 | /* Vref is AVcc */
71        (x ? ADC_X : ADC_Y);
72}
73
74
75static inline void adcsra(bool start)
76{
77    /*
78     * The ADC needs to run at clkADC <= 200 kHz for full resolution.
79     * At clkADC = 125 kHz, a conversion takes about 110 us.
80     */
81    ADCSRA =
82        1 << ADEN | /* enable ADC */
83        (start ? 1 << ADSC : 0) |
84        1 << ADIE | /* enable ADC interrupts */
85        6; /* clkADC = clk/64 -> 125 kHz */
86}
87
88
89static uint16_t adc(bool x)
90{
91    adcsra(0);
92    admux(x);
93    adcsra(1);
94    while (ADCSRA & (1 << ADSC));
95    return ADC;
96}
97
98
99#define E_SHIFT 8 /* ~ 0.06 */
100#define M_SHIFT 11 /* ~ 2/sample_rate */
101
102#define HYSTERESIS 9 /* 1 g / 3 */
103
104
105static const uint8_t img[] PROGMEM = {
106    #include "img.inc"
107};
108
109
110static uint8_t one[LED_BYTES] =
111    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
112
113static volatile uint16_t sample_t = 0, sample_v;
114
115
116static void zxing(uint16_t x, uint16_t y)
117{
118    static uint32_t e = (uint32_t) 512 << E_SHIFT;
119    static uint32_t m = (uint32_t) 512 << M_SHIFT;
120    int16_t d;
121    static bool up = 0;
122    static bool on = 0;
123    static const prog_uint8_t *p;
124    static uint16_t cols = 0;
125
126    sample_t++;
127    sample_v = x;
128
129    e = x+(e-(e >> E_SHIFT));
130    m = x+(m-(m >> M_SHIFT));
131    d = (e >> E_SHIFT)-(m >> M_SHIFT);
132    if (up) {
133        if (d < -HYSTERESIS)
134            up = 0;
135    } else {
136        if (d > HYSTERESIS) {
137            up = 1;
138            p = img;
139            cols = sizeof(img)/LED_BYTES;
140            on = 1;
141        }
142    }
143    if (cols) {
144        led_show_pgm(p);
145        p += 8;
146        cols--;
147    } else {
148        led_off();
149    }
150}
151
152
153static void panic(void)
154{
155    cli();
156    while (1) {
157        led_show(one);
158        _delay_ms(100);
159        led_off();
160        _delay_ms(100);
161    }
162}
163
164
165int main(void)
166{
167    PORTB = HIGH(B);
168    PORTC = HIGH(C);
169    PORTD = HIGH(D);
170    DDRB = OUTPUTS(B);
171    DDRC = OUTPUTS(C);
172    DDRD = OUTPUTS(D);
173
174    CLR(CARD_nPWR);
175    CLR(SCLK);
176    CLR(LCLK);
177    OUT(SCLK);
178    OUT(LCLK);
179    OUT(DS);
180
181#ifdef VDD
182    SET(VDD);
183    OUT(VDD);
184#endif
185
186    led_init();
187
188#if 0
189    led_show(one);
190
191    if (!mmc_init())
192        panic();
193    if (!mmc_begin_write(0))
194        panic();
195
196    uint16_t n = 0;
197
198    for (n = 0; n != 512; n += 2) {
199        mmc_write(n);
200        mmc_write(n >> 8);
201    }
202
203    if (!mmc_end_write())
204        panic();
205
206    if (!mmc_begin_write(n))
207        panic();
208
209    for (; n != 1024; n += 2) {
210        mmc_write(n);
211        mmc_write(n >> 8);
212    }
213
214    if (!mmc_end_write())
215        panic();
216
217    _delay_ms(1000);
218
219    led_off();
220
221    while (1);
222#endif
223
224#if 1
225    uint16_t last_t = 0;
226    uint32_t n = 0;
227
228    sample = zxing;
229    /* MMC doesn't work when running from battery, probably because we
230       have no regulation. Just disable it for now. */
231#if 0
232    if (!mmc_init())
233        panic();
234#endif
235    accel_start();
236    sei();
237while (1);
238    while (1) {
239        uint16_t t, v;
240
241        if (!(n & 511)) {
242            if (n && !mmc_end_write())
243                panic();
244            if (!mmc_begin_write(n))
245                panic();
246        }
247
248#if 0
249    t = n;
250    v = 0;
251#else
252        do {
253            cli();
254            t = sample_t;
255            v = sample_v;
256            sei();
257        }
258        while (t == last_t);
259#endif
260
261        last_t = t;
262        mmc_write(t);
263        mmc_write(t >> 8);
264        mmc_write(v);
265        mmc_write(v >> 8);
266        n += 4;
267    }
268#endif
269
270#if 0
271    static uint8_t p[LED_BYTES];
272    uint8_t mode = 0;
273    uint16_t n = 0, v;
274
275    while (1) {
276        while (!PIN(SW_SW));
277        if (!PIN(SW_N))
278            mode = 0;
279        if (!PIN(SW_E))
280            mode = 1;
281        if (!PIN(SW_S))
282            mode = 2;
283        switch (mode) {
284        case 1:
285            n = adc(0);
286            p[0] = n;
287            p[1] = n >> 8;
288            p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0;
289            send(p);
290            break;
291        case 2:
292            n = adc(1);
293            p[0] = n;
294            p[1] = n >> 8;
295            p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0;
296            send(p);
297            break;
298        default:
299            v = 63-n;
300            if (n & 64)
301                p[(v >> 3) & 7] &= ~(1 << (v & 7));
302            else
303                p[(v >> 3) & 7] |= 1 << (v & 7);
304            led_show(p);
305            n++;
306        }
307        _delay_ms(100);
308    }
309#endif
310}
311

Archive Download this file

Branches:
master
tornado-v1



interactive