Root/
Source at commit 45f14d214ab31fe28644ef8f61552a3e25330ccf created 11 years 3 months ago. By Werner Almesberger, tornado/fw/tornado.c: experimental code to log ADC samples to memory card | |
---|---|
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 | |
46 | static 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 | |
67 | static inline void admux(bool x) |
68 | { |
69 | ADMUX = |
70 | 1 << REFS0 | /* Vref is AVcc */ |
71 | (x ? ADC_X : ADC_Y); |
72 | } |
73 | |
74 | |
75 | static 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 | |
89 | static 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 3 /* ~ 0.1 */ |
100 | #define M_SHIFT 11 /* ~ 1/sample_rate */ |
101 | |
102 | #define HYSTERESIS 14 |
103 | |
104 | |
105 | static const uint8_t img[] PROGMEM = { |
106 | #include "img.inc" |
107 | }; |
108 | |
109 | |
110 | static uint8_t one[LED_BYTES] = |
111 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
112 | |
113 | static volatile uint16_t sample_t = 0, sample_v; |
114 | |
115 | |
116 | static void zxing(uint16_t x, uint16_t y) |
117 | { |
118 | static uint16_t e = 512 << E_SHIFT; |
119 | static uint32_t m = 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 | return; |
129 | |
130 | e = y+(e-(e >> E_SHIFT)); |
131 | m = y+(m-(m >> M_SHIFT)); |
132 | d = (e >> E_SHIFT)-(m >> M_SHIFT); |
133 | if (up) { |
134 | if (d < -HYSTERESIS) |
135 | up = 0; |
136 | } else { |
137 | if (d > HYSTERESIS) { |
138 | up = 1; |
139 | p = img; |
140 | cols = sizeof(img)/LED_BYTES; |
141 | on = 1; |
142 | } |
143 | } |
144 | if (cols) { |
145 | led_show_pgm(p); |
146 | p += 8; |
147 | cols--; |
148 | } else { |
149 | led_off(); |
150 | } |
151 | } |
152 | |
153 | |
154 | static void panic(void) |
155 | { |
156 | cli(); |
157 | while (1) { |
158 | led_show(one); |
159 | _delay_ms(100); |
160 | led_off(); |
161 | _delay_ms(100); |
162 | } |
163 | } |
164 | |
165 | |
166 | int main(void) |
167 | { |
168 | PORTB = HIGH(B); |
169 | PORTC = HIGH(C); |
170 | PORTD = HIGH(D); |
171 | DDRB = OUTPUTS(B); |
172 | DDRC = OUTPUTS(C); |
173 | DDRD = OUTPUTS(D); |
174 | |
175 | CLR(CARD_nPWR); |
176 | CLR(SCLK); |
177 | CLR(LCLK); |
178 | OUT(SCLK); |
179 | OUT(LCLK); |
180 | OUT(DS); |
181 | |
182 | #ifdef VDD |
183 | SET(VDD); |
184 | OUT(VDD); |
185 | #endif |
186 | |
187 | led_init(); |
188 | |
189 | #if 0 |
190 | led_show(one); |
191 | |
192 | if (!mmc_init()) |
193 | panic(); |
194 | if (!mmc_begin_write(0)) |
195 | panic(); |
196 | |
197 | uint16_t n = 0; |
198 | |
199 | for (n = 0; n != 512; n += 2) { |
200 | mmc_write(n); |
201 | mmc_write(n >> 8); |
202 | } |
203 | |
204 | if (!mmc_end_write()) |
205 | panic(); |
206 | |
207 | if (!mmc_begin_write(n)) |
208 | panic(); |
209 | |
210 | for (; n != 1024; n += 2) { |
211 | mmc_write(n); |
212 | mmc_write(n >> 8); |
213 | } |
214 | |
215 | if (!mmc_end_write()) |
216 | panic(); |
217 | |
218 | _delay_ms(1000); |
219 | |
220 | led_off(); |
221 | |
222 | while (1); |
223 | #endif |
224 | |
225 | #if 1 |
226 | uint16_t last_t = 0; |
227 | uint32_t n = 0; |
228 | |
229 | sample = zxing; |
230 | if (!mmc_init()) |
231 | panic(); |
232 | accel_start(); |
233 | sei(); |
234 | while (1) { |
235 | uint16_t t, v; |
236 | |
237 | if (!(n & 511)) { |
238 | if (n && !mmc_end_write()) |
239 | panic(); |
240 | if (!mmc_begin_write(n)) |
241 | panic(); |
242 | } |
243 | |
244 | #if 0 |
245 | t = n; |
246 | v = 0; |
247 | #else |
248 | do { |
249 | cli(); |
250 | t = sample_t; |
251 | v = sample_v; |
252 | sei(); |
253 | } |
254 | while (t == last_t); |
255 | #endif |
256 | |
257 | last_t = t; |
258 | mmc_write(t); |
259 | mmc_write(t >> 8); |
260 | mmc_write(v); |
261 | mmc_write(v >> 8); |
262 | n += 4; |
263 | } |
264 | #endif |
265 | |
266 | #if 0 |
267 | static uint8_t p[LED_BYTES]; |
268 | uint8_t mode = 0; |
269 | uint16_t n = 0, v; |
270 | |
271 | while (1) { |
272 | while (!PIN(SW_SW)); |
273 | if (!PIN(SW_N)) |
274 | mode = 0; |
275 | if (!PIN(SW_E)) |
276 | mode = 1; |
277 | if (!PIN(SW_S)) |
278 | mode = 2; |
279 | switch (mode) { |
280 | case 1: |
281 | n = adc(0); |
282 | p[0] = n; |
283 | p[1] = n >> 8; |
284 | p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0; |
285 | send(p); |
286 | break; |
287 | case 2: |
288 | n = adc(1); |
289 | p[0] = n; |
290 | p[1] = n >> 8; |
291 | p[2] = p[3] = p[4] = p[5] = p[6] = p[7] = 0; |
292 | send(p); |
293 | break; |
294 | default: |
295 | v = 63-n; |
296 | if (n & 64) |
297 | p[(v >> 3) & 7] &= ~(1 << (v & 7)); |
298 | else |
299 | p[(v >> 3) & 7] |= 1 << (v & 7); |
300 | led_show(p); |
301 | n++; |
302 | } |
303 | _delay_ms(100); |
304 | } |
305 | #endif |
306 | } |
307 |
Branches:
master
tornado-v1