diff --git a/doc/PROTOCOL b/doc/PROTOCOL index 64173c7..0eed887 100644 --- a/doc/PROTOCOL +++ b/doc/PROTOCOL @@ -70,4 +70,4 @@ Where each sample is 4 2 Absolute time of Y sample, lower 16 bits 6 2 Y sample (0-1023) -Byte order TBD. (Defined by avr-gcc) +Byte order is little-endian. diff --git a/fw/accel.c b/fw/accel.c index 5370260..1f45d66 100644 --- a/fw/accel.c +++ b/fw/accel.c @@ -38,11 +38,15 @@ static inline void admux(bool x) static inline void adcsra(bool start) { + /* + * The ADC needs to run at clkADC <= 200 kHz for full resolution. + * At clkADC = 125 kHz, a conversion takes about 110 us. + */ ADCSRA = 1 << ADEN | /* enable ADC */ (start ? 1 << ADSC : 0) | 1 << ADIE | /* enable ADC interrupts */ - 7; /* clkADC = clk/128 -> 62.5 kHz */ + 6; /* clkADC = clk/64 -> 126 kHz */ } @@ -54,8 +58,18 @@ ISR(ADC_vect) if (sample) sample(chan_x, v); - chan_x = !chan_x; - admux(chan_x); + if (chan_x) { + chan_x = 0; + admux(0); + adcsra(1); + } +} + + +ISR(TIMER0_OVF_vect) +{ + chan_x = 1; + admux(1); adcsra(1); } @@ -63,6 +77,15 @@ ISR(ADC_vect) void accel_start(void) { adcsra(0); - admux(1); - chan_x = 1; + + TCNT0 = 0; + OCR0A = 125; /* 8 MHz/64/125 = 1 kHz */ + TCCR0A = + 1 << WGM01 | /* WG Mode 7 (Fast PWM to OCR0A) */ + 1 << WGM00; + TCCR0B = + 1 << WGM02 | /* WG Mode 7, continued */ + 1 << CS01 | /* clkIO/64 */ + 1 << CS00; + TIMSK0 = 1 << TOIE0; /* interrupt on overflow */ } diff --git a/fw/sample.c b/fw/sample.c index 7098f78..4b1fcdf 100644 --- a/fw/sample.c +++ b/fw/sample.c @@ -23,31 +23,37 @@ #include "proto.h" #include "dispatch.h" +#include "io.h" -#define MAX_PACKET 120 /* <- MAX_PSDU -3 (hdr) -2 (CRC) */ +/* @@@ keep it small for now - we're running out of RAM :-( */ +//#define MAX_PACKET 120 /* <- MAX_PSDU -3 (hdr) -2 (CRC) */ +#define MAX_PACKET 50 /* <- MAX_PSDU -3 (hdr) -2 (CRC) */ static uint8_t buf[MAX_PACKET+3] = { SAMPLES, 0, 0 }; static uint16_t *p; +static bool expect_x; static void handler(bool x, uint16_t v) { - bool first; uint32_t t; - first = p == (uint16_t *) (buf+3); - if (first && !x) + if (x != expect_x) return; - t = uptime(); - if (first) + t = uptime_irq(); + if (p == (uint16_t *) (buf+3)) *p++ = t >> 16; *p++ = t; *p++ = v; + expect_x = !expect_x; + if (x) return; if ((uint8_t *) (p+4) <= buf+MAX_PACKET) return; + rf_send(buf, (uint8_t *) p-buf); + buf[1]++; p = (uint16_t *) (buf+3); } @@ -59,6 +65,7 @@ static bool sample_first(uint8_t limit, const uint8_t *payload) cli(); sample = handler; p = (uint16_t *) (buf+3); + expect_x = 1; sei(); } else { cli(); diff --git a/fw/sweep.c b/fw/sweep.c index 059c286..3aac954 100644 --- a/fw/sweep.c +++ b/fw/sweep.c @@ -84,6 +84,17 @@ ISR(TIMER1_OVF_vect) } +uint32_t uptime_irq(void) +{ + uint32_t t; + + t = t_up+TCNT1; + if (TIFR1 & TOV1) + t += ICR1; + return t; +} + + uint32_t uptime(void) { uint32_t a, b; @@ -92,7 +103,8 @@ uint32_t uptime(void) do { cli(); a = t_up; - d = ICR1; + d = TCNT1; + cli(); b = t_up; sei(); } diff --git a/fw/sweep.h b/fw/sweep.h index 08b325e..b0113e4 100644 --- a/fw/sweep.h +++ b/fw/sweep.h @@ -29,7 +29,9 @@ struct sweep { extern volatile bool sweeping; +uint32_t uptime_irq(void); uint32_t uptime(void); + void sweep_image(const struct sweep *sweep); void sweep_init(void); diff --git a/tools/Makefile b/tools/Makefile index c4b3802..6811779 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -15,12 +15,14 @@ MAIN = antorcha CFLAGS = -g -I../fw -I../../ben-wpan/tools/include \ -I../../ben-wpan/atusb/fw/include \ - -Wall -LDLIBS = -L../../ben-wpan/tools/lib -latrf -lusb + -Wall \ + $(shell sdl-config --cflags) +LDLIBS = -L../../ben-wpan/tools/lib -latrf -lusb \ + $(shell sdl-config --libs) -lSDL_gfx -OBJS = antorcha.o hash.o +OBJS = antorcha.o hash.o plot.o -.PHONY: all update ping +.PHONY: all update ping off all: $(MAIN) @@ -32,3 +34,6 @@ update: ping: ./antorcha -P + +off: + ./antorcha /dev/null diff --git a/tools/antorcha.c b/tools/antorcha.c index d0ca4d8..f47c87c 100644 --- a/tools/antorcha.c +++ b/tools/antorcha.c @@ -22,9 +22,11 @@ #include #include -#include #include +#include "hash.h" +#include "plot.h" + static int verbose = 1; static int debug = 0; @@ -275,6 +277,74 @@ static void image(struct atrf_dsc *dsc, const char *name) } +/* ----- Samples ----------------------------------------------------------- */ + + +static void samples(struct atrf_dsc *dsc) +{ + uint8_t buf[MAX_PSDU] = { 0, }; + int got; + uint8_t *s; + uint16_t t_high, t_low, last; + int x, y; + + buf[0] = 1; + packet(dsc, SAMPLE, 0, 0, buf, PAYLOAD); + plot_init(); + while (1) { + got = rf_recv(dsc, buf, sizeof(buf)); + if (got <= 3) + continue; + if (buf[0] != SAMPLES) + continue; + if (debug > 1) { + int i; + + for (i = 0; i != got; i++) + fprintf(stderr, " %02x", buf[i]); + fprintf(stderr, "\n"); + } + if (debug) + fprintf(stderr, "%d:", got); + s = buf+3; + t_high = *s++; + t_high |= *s++ << 8; + last = 0; + while (s < buf+got-2) { + t_low = *s++; + t_low |= *s++ << 8; + if (t_low < last) + t_high++; + last = t_low; + x = *s++; + x |= *s++ << 8; + + if (debug) + fprintf(stderr, "\t%11.6f %d", + (t_high << 16 | t_low)/1000000.0, x); + + t_low = *s++; + t_low |= *s++ << 8; + if (t_low < last) + t_high++; + last = t_low; + y = *s++; + y |= *s++ << 8; + + if (debug) + fprintf(stderr, "\t%11.6f %d\n", + (t_high << 16 | t_low)/1000000.0, y); + + if (!plot(x, y)) + goto quit; + } + } +quit: + buf[0] = 0; + packet(dsc, SAMPLE, 0, 0, buf, PAYLOAD); +} + + /* ----- Command-line processing ------------------------------------------- */ @@ -284,7 +354,8 @@ static void usage(const char *name) "usage: %s [-d] image_file\n" "%6s %s [-d] -F firmware_file\n" "%6s %s [-d] -P\n" - , name, "", name, "", name); + "%6s %s [-d] -S\n" + , name, "", name, "", name, "", name); exit(1); } @@ -292,14 +363,14 @@ static void usage(const char *name) int main(int argc, char **argv) { const char *fw = NULL; - int do_ping = 0; + int do_ping = 0, do_sample = 0; struct atrf_dsc *dsc; int c; - while ((c = getopt(argc, argv, "dF:P")) != EOF) + while ((c = getopt(argc, argv, "dF:PS")) != EOF) switch (c) { case 'd': - debug = 1; + debug++; break; case 'F': fw = optarg; @@ -307,13 +378,16 @@ int main(int argc, char **argv) case 'P': do_ping = 1; break; + case 'S': + do_sample = 1; + break; default: usage(*argv); } - if (do_ping && fw) + if (do_ping+do_sample+!!fw > 1) usage(*argv); - if (do_ping || fw) { + if (do_ping || do_sample || fw) { if (argc != optind) usage(*argv); } else { @@ -328,6 +402,8 @@ int main(int argc, char **argv) rf_init(dsc, 8, 15); if (do_ping) ping(dsc); + else if (do_sample) + samples(dsc); else if (fw) firmware(dsc, fw); else diff --git a/tools/plot.c b/tools/plot.c new file mode 100644 index 0000000..bbe3d6f --- /dev/null +++ b/tools/plot.c @@ -0,0 +1,130 @@ +/* + * tools/plot.c - Sample plot + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include + +#include "SDL.h" +#include "SDL_gfxPrimitives.h" + +#include "plot.h" + + +#define XRES 1024 +#define YRES 1024 + +#define RADIUS 3 + +#define OLD_RGBA 0xffffff20 +#define NEW_RGBA 0xffffffff + + +static SDL_Surface *surf; +static int first = 1; +static int last_x, last_y; + +static SDL_Surface *back; +static SDL_Rect back_rect = { + .x = 0, + .y = 0, + .w = 2*RADIUS+1, + .h = 2*RADIUS+1, +}; + +static SDL_Rect front_rect = { + .w = 2*RADIUS+1, + .h = 2*RADIUS+1, +}; + + +int plot(int x, int y) +{ + SDL_Event event; + + if (!first) { + SDL_BlitSurface(back, &back_rect, surf, &front_rect); + SDL_LockSurface(surf); + filledCircleColor(surf, last_x, last_y, RADIUS, OLD_RGBA); + SDL_UnlockSurface(surf); + } + + front_rect.x = x; + front_rect.y = y; + x += RADIUS; + y += RADIUS; + + SDL_BlitSurface(surf, &front_rect, back, &back_rect); + SDL_LockSurface(surf); + filledCircleColor(surf, x, y, RADIUS, NEW_RGBA); + SDL_UnlockSurface(surf); + + if (!first) + SDL_UpdateRect(surf, + last_x-RADIUS, last_y-RADIUS, 2*RADIUS+1, 2*RADIUS+1); + SDL_UpdateRect(surf, x-RADIUS, y-RADIUS, 2*RADIUS+1, 2*RADIUS+1); + + first = 0; + last_x = x; + last_y = y; + + while (SDL_PollEvent(&event)) + switch (event.type) { + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_c: + SDL_LockSurface(surf); + SDL_FillRect(surf, NULL, + SDL_MapRGB(surf->format, 0, 0, 0)); + SDL_UpdateRect(surf, 0, 0, 0, 0); + SDL_UnlockSurface(surf); + break; + case SDLK_q: + return 0; + default: + break; + } + break; + case SDL_QUIT: + return 0; + default: + break; + } + + return 1; +} + + +void plot_init(void) +{ + const SDL_PixelFormat *f; + + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "SDL_init: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + surf = SDL_SetVideoMode(XRES+2*RADIUS+1, YRES+2*RADIUS+1, 0, + SDL_SWSURFACE); + if (!surf) { + fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); + exit(1); + } + + f = surf->format; + back = SDL_CreateRGBSurface(SDL_SWSURFACE, 2*RADIUS+1, 2*RADIUS+1, + f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask); + if (!back) { + fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError()); + exit(1); + } +} diff --git a/tools/plot.h b/tools/plot.h new file mode 100644 index 0000000..fb6a621 --- /dev/null +++ b/tools/plot.h @@ -0,0 +1,20 @@ +/* + * tools/plot.h - Sample plot + * + * Written 2012 by Werner Almesberger + * Copyright 2012 Werner Almesberger + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef PLOT_H +#define PLOT_H + +int plot(int x, int y); +void plot_init(void); + +#endif /* !PLOT_H */