Root/tools/ant-cl/ant-cl.c

Source at commit bf2e2c30463d22b5e34fa795eb98b35a855d90ae created 11 years 1 hour ago.
By Werner Almesberger, tornado/led/led.cmp: update for new components and changed references
1/*
2 * tools/ant-cl/ant-cl.c - Antorcha control utility
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 <stdint.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <unistd.h>
18#include <string.h>
19#include <signal.h>
20#include <assert.h>
21
22#include <at86rf230.h>
23#include <atrf.h>
24#include <misctxrx.h>
25
26#include <proto.h>
27
28#include "hash.h"
29#include "plot.h"
30
31
32static int verbose = 1;
33static int debug = 0;
34
35
36static void rf_init(struct atrf_dsc *dsc, int trim, int channel)
37{
38    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
39     atrf_reg_write(dsc, REG_XOSC_CTRL,
40            (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
41    atrf_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
42    atrf_reg_write(dsc, REG_IRQ_MASK, 0xff);
43    flush_interrupts(dsc);
44    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
45    wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 1);
46}
47
48
49static void rf_send(struct atrf_dsc *dsc, void *buf, int len)
50{
51    uint8_t tmp[MAX_PSDU];
52
53    /* Copy the message to append the CRC placeholders */
54    memcpy(tmp, buf, len);
55    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON);
56    flush_interrupts(dsc);
57    atrf_buf_write(dsc, tmp, len+2);
58    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TX_START);
59    wait_for_interrupt(dsc, IRQ_TRX_END,
60        IRQ_TRX_END | IRQ_PLL_LOCK, 10);
61    atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON);
62
63    if (debug) {
64        int i;
65
66        fprintf(stderr, "\rSEND %d:", len);
67        for (i = 0; i != len; i++)
68            fprintf(stderr, " %02x", ((uint8_t *) buf)[i]);;
69        fprintf(stderr, "\n");
70    }
71}
72
73
74static int rf_recv(struct atrf_dsc *dsc, void *buf, int size, int timeout_ms)
75{
76    uint8_t irq;
77    int len;
78
79    /* Wait up to 100 ms */
80    irq = wait_for_interrupt(dsc, IRQ_TRX_END,
81        IRQ_TRX_END | IRQ_RX_START | IRQ_AMI, timeout_ms);
82    if (!irq)
83        return 0;
84    len = atrf_buf_read(dsc, buf, size);
85    if (len < 0)
86        exit(1);
87    if (len < 3) /* CRC and LQI */
88        return 0;
89    return atrf_reg_read(dsc, REG_PHY_RSSI) & RX_CRC_VALID ? len-3 : 0;
90}
91
92
93static void packet_noack(struct atrf_dsc *dsc,
94    uint8_t type, uint8_t seq, uint8_t last, const void *payload, int len)
95{
96    uint8_t tx_buf[PAYLOAD+3] = { type, seq, last };
97
98    assert(len == PAYLOAD);
99    memcpy(tx_buf+3, payload, len);
100    rf_send(dsc, tx_buf, sizeof(tx_buf));
101}
102
103
104static int recv_ack(struct atrf_dsc *dsc, uint8_t *buf, int buf_len,
105    uint8_t type, uint8_t seq, int timeout_ms)
106{
107    int got;
108
109    if (verbose)
110        write(2, ">", 1);
111    got = rf_recv(dsc, buf, buf_len, timeout_ms);
112    if (got <= 0) {
113        if (!seq && verbose)
114            write(2, "\b", 1);
115        return 0;
116    }
117
118    if (debug) {
119        int i;
120
121        fprintf(stderr, "\rRECV %d:", got);
122        for (i = 0; i != got; i++)
123            fprintf(stderr, " %02x", buf[i]);;
124        fprintf(stderr, "\n");
125    }
126
127    if (verbose)
128        write(2, "\b?", 2);
129    if (got < 3)
130        return 0;
131    if (verbose)
132        write(2, "\bA", 2);
133    if (buf[0] != type || buf[1] != seq)
134        return 0;
135    if (verbose)
136        write(2, "\b.", 2);
137    return got;
138}
139
140
141static void packet(struct atrf_dsc *dsc,
142    uint8_t type, uint8_t seq, uint8_t last, const void *payload, int len)
143{
144    uint8_t rx_buf[10];
145    int got;
146
147    while (1) {
148        packet_noack(dsc, type, seq, last, payload, len);
149        got = recv_ack(dsc, rx_buf, sizeof(rx_buf), type+1, seq, 100);
150        if (got)
151            break;
152    }
153}
154
155
156/* ----- Ping -------------------------------------------------------------- */
157
158
159static void ping(struct atrf_dsc *dsc)
160{
161    uint8_t ping[] = { PING, 0, 0 };
162    uint8_t buf[100];
163    int got, i;
164
165    rf_send(dsc, ping, sizeof(ping));
166    got = rf_recv(dsc, buf, sizeof(buf), 100);
167    if (!got)
168        return;
169    printf("%d: ", got);
170    for (i = 3; i != got; i++)
171        printf("%c", buf[i] >= ' ' && buf[i] <= '~' ? buf[i] : '?');
172    printf("\n");
173}
174
175
176/* ----- Firmware upload --------------------------------------------------- */
177
178
179static const uint8_t unlock_secret[PAYLOAD] = {
180    #include "unlock-secret.inc"
181};
182
183
184static void send_firmware(struct atrf_dsc *dsc, void *buf, int len)
185{
186    uint8_t payload[PAYLOAD];
187    uint8_t last, seq;
188
189    if (verbose)
190        write(2, "firmware ", 9);
191    last = (len+63)/64;
192    seq = 0;
193    packet_noack(dsc, RESET, 0, 0, unlock_secret, PAYLOAD);
194    packet(dsc, FIRMWARE, seq++, last, unlock_secret, PAYLOAD);
195    while (len >= PAYLOAD) {
196        packet(dsc, FIRMWARE, seq++, last, buf, PAYLOAD);
197        buf += PAYLOAD;
198        len -= PAYLOAD;
199    }
200    if (len) {
201        memcpy(payload, buf, len);
202        memset(payload+len, 0, PAYLOAD-len);
203        packet(dsc, FIRMWARE, seq++, last, payload, PAYLOAD);
204    }
205    if (verbose)
206        write(2, "\n", 1);
207}
208
209
210static void firmware(struct atrf_dsc *dsc, const char *name)
211{
212    FILE *file;
213    uint8_t fw[12*1024]; /* we have 8-12kB */
214    ssize_t len;
215
216    file = fopen(name, "r");
217    if (!file) {
218        perror(name);
219        exit(1);
220    }
221    len = fread(fw, 1, sizeof(fw), file);
222    if (len < 0) {
223        perror(name);
224        exit(1);
225    }
226    fclose(file);
227
228    send_firmware(dsc, fw, len);
229}
230
231
232/* ----- Image upload ------------------------------------------------------ */
233
234
235static const uint8_t image_secret[PAYLOAD*2] = {
236    #include "image-secret.inc"
237};
238
239
240static void send_image(struct atrf_dsc *dsc, void *buf, int len)
241{
242    uint8_t payload[PAYLOAD];
243    uint8_t last, seq;
244
245    hash_init();
246    hash_merge(image_secret, sizeof(image_secret));
247    if (verbose)
248        write(2, "image ", 6);
249
250    last = (len+63)/64+3;
251    seq = 0;
252    while (len >= PAYLOAD) {
253        packet(dsc, IMAGE, seq++, last, buf, PAYLOAD);
254        hash_merge(buf, PAYLOAD);
255        buf += PAYLOAD;
256        len -= PAYLOAD;
257    }
258    if (len) {
259        memcpy(payload, buf, len);
260        memset(payload+len, 0, PAYLOAD-len);
261        packet(dsc, IMAGE, seq++, last, payload, PAYLOAD);
262        hash_merge(payload, PAYLOAD);
263    }
264
265    /* @@@ salt */
266    packet(dsc, IMAGE, seq++, last, payload, PAYLOAD);
267    hash_merge(payload, PAYLOAD);
268    packet(dsc, IMAGE, seq++, last, payload, PAYLOAD);
269    hash_merge(payload, PAYLOAD);
270    hash_end();
271
272    /* hash */
273    hash_cp(payload, PAYLOAD, 0);
274    packet(dsc, IMAGE, seq++, last, payload, PAYLOAD);
275    hash_cp(payload, PAYLOAD, PAYLOAD);
276    packet(dsc, IMAGE, seq++, last, payload, PAYLOAD);
277
278    if (verbose)
279        write(2, "\n", 1);
280}
281
282
283static void image(struct atrf_dsc *dsc, const char *name)
284{
285    FILE *file;
286    uint8_t img[200] = { 0 };
287    ssize_t len;
288
289    if (!strcmp(name, "-")) {
290        file = stdin;
291    } else {
292        file = fopen(name, "r");
293        if (!file) {
294            perror(name);
295            exit(1);
296        }
297    }
298    len = fread(img, 1, sizeof(img), file);
299    if (len < 0) {
300        perror(name);
301        exit(1);
302    }
303    if (file != stdin)
304        fclose(file);
305
306    send_image(dsc, img, len);
307}
308
309
310/* ----- Parameter upload -------------------------------------------------- */
311
312
313static struct params params = {
314    .xa_high = XA_HIGH_DEFAULT,
315    .xa_low = XA_LOW_DEFAULT,
316    .px_fwd_left = PX_FWD_LEFT_DEFAULT,
317    .px_fwd_right = PX_FWD_RIGHT_DEFAULT,
318    .px_bwd_left = PX_BWD_LEFT_DEFAULT,
319    .px_bwd_right = PX_BWD_RIGHT_DEFAULT,
320    .tp_fwd_start = TP_FWD_START_DEFAULT,
321    .tp_bwd_start = TP_BWD_START_DEFAULT,
322    .tp_fwd_pix = TP_FWD_PIX_DEFAULT,
323    .tp_bwd_pix = TP_BWD_PIX_DEFAULT,
324};
325
326static struct map {
327    const char *name; /* NULL to mark end */
328    void *p;
329    int bytes; /* 1, 2, or 4 */
330} map[] = {
331    { "xa_high", &params.xa_high, 2 },
332    { "xa_low", &params.xa_low, 2 },
333    { "px_fwd_left", &params.px_fwd_left, 1 },
334    { "px_bwd_left", &params.px_bwd_left, 1 },
335    { "px_fwd_right", &params.px_fwd_right, 1 },
336    { "px_bwd_right", &params.px_bwd_right, 1 },
337    { "tp_fwd_start", &params.tp_fwd_start, 4 },
338    { "tp_bwd_start", &params.tp_bwd_start, 4 },
339    { "tp_fwd_pix", &params.tp_fwd_pix, 2 },
340    { "tp_bwd_pix", &params.tp_bwd_pix, 2 },
341    { NULL }
342};
343
344static int have_params = 0;
345
346
347static void add_param(const char *arg, const char *eq)
348{
349    const struct map *m;
350    size_t len;
351    unsigned long v;
352    char *end;
353    uint8_t *p;
354    int i;
355
356    len = eq-arg;
357    for (m = map; m->name; m++) {
358        if (strlen(m->name) != len)
359            continue;
360        if (!strncmp(arg, m->name, len))
361            break;
362    }
363    if (!m->name) {
364        fprintf(stderr, "unknown parameter \"%.*s\"\n",
365            (int) len, arg);
366        exit(1);
367    }
368    v = strtoul(eq+1, &end, 10);
369    if (*end) {
370        fprintf(stderr, "invalid value \"%s\"\n", eq+1);
371        exit(1);
372    }
373    p = m->p;
374    for (i = 0; i != m->bytes; i++) {
375        *p++ = v;
376        v >>= 8;
377    }
378    if (v) {
379        fprintf(stderr, "value \"%s\" is too large\n", eq+1);
380        exit(1);
381    }
382    have_params = 1;
383}
384
385
386static void send_param(struct atrf_dsc *dsc)
387{
388    uint8_t payload[PAYLOAD];
389
390    if (!have_params)
391        return;
392    hash_init();
393    hash_merge(image_secret, sizeof(image_secret));
394    if (verbose)
395        write(2, "param ", 6);
396    memset(payload, 0, PAYLOAD);
397    memcpy(payload, &params, sizeof(params));
398    packet(dsc, PARAM, 0, 4, payload, PAYLOAD);
399    hash_merge(payload, PAYLOAD);
400
401    /* @@@ salt */
402    packet(dsc, PARAM, 1, 4, payload, PAYLOAD);
403    hash_merge(payload, PAYLOAD);
404    packet(dsc, PARAM, 2, 4, payload, PAYLOAD);
405    hash_merge(payload, PAYLOAD);
406    hash_end();
407
408    /* hash */
409    hash_cp(payload, PAYLOAD, 0);
410    packet(dsc, PARAM, 3, 4, payload, PAYLOAD);
411    hash_cp(payload, PAYLOAD, PAYLOAD);
412    packet(dsc, PARAM, 4, 4, payload, PAYLOAD);
413
414    if (verbose)
415        write(2, "\n", 1);
416}
417
418
419/* ----- Reset ------------------------------------------------------------- */
420
421
422static void reset(struct atrf_dsc *dsc)
423{
424    packet_noack(dsc, RESET, 0, 0, unlock_secret, PAYLOAD);
425}
426
427
428/* ----- Samples ----------------------------------------------------------- */
429
430
431static volatile int run = 1;
432
433
434static void sigint(int sig)
435{
436    run = 0;
437}
438
439
440static int read_sample(uint8_t **s, uint16_t *t_high, uint16_t *t_low,
441    uint16_t *last)
442{
443    int v;
444
445    *t_low = *(*s)++;
446    *t_low |= *(*s)++ << 8;
447    if (*t_low < *last)
448        (*t_high)++;
449    *last = *t_low;
450    v = *(*s)++;
451    v |= *(*s)++ << 8;
452    return v;
453}
454
455
456static void samples(struct atrf_dsc *dsc, int gui)
457{
458    uint8_t buf[MAX_PSDU] = { 0, };
459    int got;
460    uint8_t *s;
461    uint16_t t_high, t_low, last;
462    int x, y;
463    double t;
464
465    buf[0] = 1;
466    packet(dsc, SAMPLE, 0, 0, buf, PAYLOAD);
467
468#ifdef GFX
469    if (gui)
470        plot_init();
471    else
472#endif
473        signal(SIGINT, sigint);
474    while (run) {
475        got = rf_recv(dsc, buf, sizeof(buf), 100);
476        if (got <= 3)
477            continue;
478        if (buf[0] != SAMPLES)
479            continue;
480        if (debug > 1) {
481            int i;
482
483            for (i = 0; i != got; i++)
484                fprintf(stderr, " %02x", buf[i]);
485            fprintf(stderr, "\n");
486        }
487        if (debug)
488            fprintf(stderr, "%d:", got);
489        s = buf+3;
490        t_high = *s++;
491        t_high |= *s++ << 8;
492        last = 0;
493        while (s < buf+got-2) {
494            x = read_sample(&s, &t_high, &t_low, &last);
495            t = (t_high << 16 | t_low)/1000000.0;
496            if (debug)
497                fprintf(stderr, "\t%11.6f %d", t, x);
498            if (!gui)
499                printf("%11.6f\t%d\t", t, x);
500
501            y = read_sample(&s, &t_high, &t_low, &last);
502            t = (t_high << 16 | t_low)/1000000.0;
503            if (debug)
504                fprintf(stderr, "\t%11.6f %d\n", t, y);
505            if (!gui)
506                printf("%11.6f\t%d\n", t, y);
507
508#ifdef GFX
509            if (gui && !plot(x, y))
510                goto quit;
511#endif
512        }
513    }
514#ifdef GFX
515quit:
516#endif
517    buf[0] = 0;
518    packet(dsc, SAMPLE, 0, 0, buf, PAYLOAD);
519}
520
521
522/* ----- Diagnostics ------------------------------------------------------- */
523
524
525static void send_diag(struct atrf_dsc *dsc, uint16_t pattern, uint16_t *v_bg)
526{
527    uint8_t payload[PAYLOAD];
528    int got, i;
529
530    hash_init();
531    hash_merge(image_secret, sizeof(image_secret));
532    if (verbose) {
533        write(2, "diag ", 5);
534        for (i = 0; i != 16; i++)
535            write(2, pattern & (1 << i) ? "*" : "-", 1);
536        write(2, " ", 1);
537    }
538    memset(payload, 0, PAYLOAD);
539    payload[0] = pattern;
540    payload[1] = pattern >> 8;
541    packet(dsc, DIAG, 0, 4, payload, PAYLOAD);
542    hash_merge(payload, PAYLOAD);
543
544    /* @@@ salt */
545    packet(dsc, DIAG, 1, 4, payload, PAYLOAD);
546    hash_merge(payload, PAYLOAD);
547    packet(dsc, DIAG, 2, 4, payload, PAYLOAD);
548    hash_merge(payload, PAYLOAD);
549    hash_end();
550
551    /* hash */
552    hash_cp(payload, PAYLOAD, 0);
553    packet(dsc, DIAG, 3, 4, payload, PAYLOAD);
554    hash_cp(payload, PAYLOAD, PAYLOAD);
555
556    while (1) {
557        packet_noack(dsc, DIAG, 4, 4, payload, PAYLOAD);
558        got = recv_ack(dsc, payload, PAYLOAD, DIAG_ACK, 4, 1000);
559        if (got >= 7)
560            break;
561    }
562    if (verbose)
563        write(2, "\n", 1);
564    for (i = 0; i != DIAG_SAMPLES; i++)
565        v_bg[i] = payload[3+2*i] | payload[4+2*i] << 8;
566}
567
568
569static void diag_1(struct atrf_dsc *dsc, uint16_t pattern)
570{
571    uint16_t v_bg[DIAG_SAMPLES];
572    int i;
573
574    send_diag(dsc, pattern, v_bg);
575    printf("%d", pattern);
576    for (i = 0; i != DIAG_SAMPLES; i++)
577        printf(" %f", 1.1*1024/v_bg[i]);
578    printf("\n");
579    fflush(stdout);
580}
581
582
583static void diag(struct atrf_dsc *dsc)
584{
585    int i;
586
587    diag_1(dsc, 0);
588    for (i = 0; i != 16; i++)
589        diag_1(dsc, 1 << i);
590    for (i = 0; i <= 16; i++)
591        diag_1(dsc, (1 << i)-1);
592}
593
594
595/* ----- Command-line processing ------------------------------------------- */
596
597
598static unsigned get_int(uint8_t *p, int n)
599{
600    unsigned v = 0;
601    int i;
602
603    for (i = 0; i != n; i++)
604        v |= *p++ << (i*8);
605    return v;
606}
607
608
609static void usage(const char *name)
610{
611    const struct map *m;
612
613    fprintf(stderr,
614"usage: %s [-d] [param=value ...] image_file\n"
615   "%6s %s [-d] -D\n"
616   "%6s %s [-d] -F firmware_file\n"
617   "%6s %s [-d] -P\n"
618   "%6s %s [-d] -R\n"
619   "%6s %s [-d] -S [-S]\n\n"
620" -D run diagnostics\n"
621" -F file firmware upload\n"
622" -P ping (version query)\n"
623" -R reset\n"
624" -S sample with output on stdout. Exit with ^C.\n"
625#ifdef GFX
626" -S -S sample with graphical output. Exit with Q.\n\n"
627#endif
628"Parameters:\n"
629    , name, "", name, "", name, "", name, "", name, "", name);
630    for (m = map; m->name; m++)
631        fprintf(stderr, " %s\t(default %u)\n",
632            m->name, get_int(m->p, m->bytes));
633    exit(1);
634}
635
636
637int main(int argc, char **argv)
638{
639    const char *fw = NULL;
640    int do_ping = 0, do_reset = 0, do_sample = 0, do_diag = 0;
641    struct atrf_dsc *dsc;
642    int c;
643
644    while ((c = getopt(argc, argv, "dDF:PRS")) != EOF)
645        switch (c) {
646        case 'd':
647            debug++;
648            break;
649        case 'D':
650            do_diag = 1;
651            break;
652        case 'F':
653            fw = optarg;
654            break;
655        case 'P':
656            do_ping = 1;
657            break;
658        case 'R':
659            do_reset = 1;
660            break;
661        case 'S':
662            do_sample++;
663            break;
664        default:
665            usage(*argv);
666        }
667
668    if (do_ping+do_reset+do_diag+!!do_sample+!!fw > 1)
669        usage(*argv);
670    if (do_ping || do_reset || do_diag || do_sample || fw) {
671        if (argc != optind)
672            usage(*argv);
673    } else {
674        if (argc == optind)
675            usage(*argv);
676    }
677
678    dsc = atrf_open(NULL);
679    if (!dsc)
680        return 1;
681
682    rf_init(dsc, 8, 15);
683    if (do_ping)
684        ping(dsc);
685    else if (do_reset)
686        reset(dsc);
687    else if (do_sample)
688        samples(dsc, do_sample > 1);
689    else if (do_diag)
690        diag(dsc);
691    else if (fw)
692        firmware(dsc, fw);
693    else {
694        const char *eq;
695
696        while (optind != argc) {
697            eq = strchr(argv[optind], '=');
698            if (!eq)
699                break;
700            add_param(argv[optind], eq);
701            optind++;
702        }
703        if (argc > optind+1)
704            usage(*argv);
705        if (optind != argc)
706            image(dsc, argv[optind]);
707        send_param(dsc);
708    }
709
710    return 0;
711}
712

Archive Download this file

Branches:
master
tornado-v1



interactive