From 600275946454f816656a80f6e3ae15f4d3b3d2fa Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Wed, 19 Jan 2011 17:52:10 -0300 Subject: [PATCH] tools/atrf-txrx/perdump: new utility to analyze a PER dump - Makefile: added perdump - perdump.h, perdump.c: read and analyze a PER dump in pcap format - per-text.c: report PER test results as text on the console --- tools/atrf-txrx/Makefile | 12 ++- tools/atrf-txrx/per-text.c | 92 ++++++++++++++++++++++ tools/atrf-txrx/perdump.c | 153 +++++++++++++++++++++++++++++++++++++ tools/atrf-txrx/perdump.h | 28 +++++++ 4 files changed, 283 insertions(+), 2 deletions(-) create mode 100644 tools/atrf-txrx/per-text.c create mode 100644 tools/atrf-txrx/perdump.c create mode 100644 tools/atrf-txrx/perdump.h diff --git a/tools/atrf-txrx/Makefile b/tools/atrf-txrx/Makefile index 56bd71e..18b37f3 100644 --- a/tools/atrf-txrx/Makefile +++ b/tools/atrf-txrx/Makefile @@ -1,8 +1,8 @@ # # atrf-txrx/Makefile - Build the TX/RX test utility # -# Written 2010 by Werner Almesberger -# Copyright 2010 Werner Almesberger +# Written 2010, 2011 by Werner Almesberger +# Copyright 2010, 2011 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 @@ -16,3 +16,11 @@ MAIN = atrf-txrx include ../Makefile.common LDLIBS += -lm +CFLAGS += -g + +all: perdump + +perdump: perdump.o per-text.o + +clean:: + rm -f perdump.o per-text.o diff --git a/tools/atrf-txrx/per-text.c b/tools/atrf-txrx/per-text.c new file mode 100644 index 0000000..b0d34a6 --- /dev/null +++ b/tools/atrf-txrx/per-text.c @@ -0,0 +1,92 @@ +/* + * atrf-txrx/per-text.h - Report PER on console as text + * + * Written 2011 by Werner Almesberger + * Copyright 2011 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 "perdump.h" + + +static char line[65] = ""; +static int packets = 0, garbled = 0, bad = 0, skipped = 0; +static int is_bad = 0; + + +static void flush(void) +{ + if (*line) + printf("%s\n", line); + *line = 0; +} + + +static void text_undecided(int symbols) +{ + int i; + + flush(); + for (i = 0; i != symbols/4; i++) + putchar('?'); + putchar('\n'); +} + + +static void text_packet(int symbols, int skip) +{ + int i; + + flush(); + skipped += skip; + if (skip < 4) + for (i = 0; i != skip; i++) + putchar('\n'); + else + printf("\n(%d)\n\n", skip); + for (i = 0; i != symbols/4; i++) + line[i] = '-'; + line[i] = 0; + packets++; + is_bad = 0; +} + + +static void text_error(int symbol) +{ + line[symbol >> 2] = '*'; + if (!is_bad) { + bad++; + is_bad = 1; + } +} + + +static void text_finish(void) +{ + double per; + + flush(); + if (packets+garbled) + per = (double) (bad+garbled)/(packets+garbled); + else + per = 0; + printf("\n%d total, %d bad, %d garbled, PER %f%%. %d skipped.\n", + packets+garbled, bad, garbled, 100*per, skipped); +} + + +struct result_ops text_ops = { + .begin = NULL, + .undecided = text_undecided, + .packet = text_packet, + .error = text_error, + .finish = text_finish, +}; diff --git a/tools/atrf-txrx/perdump.c b/tools/atrf-txrx/perdump.c new file mode 100644 index 0000000..3056d33 --- /dev/null +++ b/tools/atrf-txrx/perdump.c @@ -0,0 +1,153 @@ +/* + * atrf-txrx/perdump.c - Analyze and dump a recorded PER test + * + * Written 2011 by Werner Almesberger + * Copyright 2011 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 +#include + +#include "pcap.h" +#include "perdump.h" + + +#define MAX_PSDU 127 + + +static const struct result_ops *ops; + + +static void analyze(uint8_t *buf, int len) +{ + static int last = -1; + int freq[256]; + uint8_t best = 0; + int i; + + for (i = 0; i != 256; i++) + freq[i] = 0; + for (i = 0; i != len; i++) { + freq[buf[i]]++; + if (!i || freq[buf[i]] > freq[best]) + best = buf[i]; + } + if (freq[best] <= len >> 1 && freq[best] != len) { + ops->undecided(len*2); + if (last != -1) + last++; /* probably :-) */ + return; + } + ops->packet(len*2, last == -1 ? 0 : (uint8_t) (best-last-1)); + last = best; + for (i = 0; i != len; i++) { + uint8_t delta = buf[i] ^ best; + + if (delta & 0x0f) + ops->error(i*2); + if (delta & 0xf0) + ops->error(i*2+1); + } + +} + + +static int pcap_record(FILE *file, const char *name) +{ + struct pcap_pkthdr hdr; + uint8_t buf[MAX_PSDU]; + size_t got; + + got = fread(&hdr, sizeof(hdr), 1, file); + if (!got) { + if (ferror(file)) { + perror(name); + exit(1); + } + return 0; + } + if (hdr.caplen > MAX_PSDU) { + fprintf(stderr, "packet too big %u > %u\n", + hdr.caplen, MAX_PSDU); + exit(1); + } + got = fread(buf, hdr.caplen, 1, file); + if (!got) { + if (ferror(file)) { + perror(name); + exit(1); + } + fprintf(stderr, "file truncated\n"); + exit(1); + } + analyze(buf, hdr.caplen); + return 1; +} + + +static void process_pcap(const char *name) +{ + FILE *file; + struct pcap_file_header hdr; + size_t got; + + file = fopen(name, "r"); + if (!file) { + perror(name); + exit(1); + } + got = fread(&hdr, sizeof(hdr), 1, file); + if (!got) { + if (ferror(file)) { + perror(name); + exit(1); + } + return; + return; + } + if (hdr.magic != PCAP_FILE_MAGIC) { + fprintf(stderr, "unrecognized magic number 0x%08x " + "(expected 0x%08x)\n", hdr.magic, PCAP_FILE_MAGIC); + exit(1); + } + if (hdr.version_major != 2) { + fprintf(stderr, "unrecognized major number %u (expected %u)\n", + hdr.version_major, 2); + exit(1); + } + if (hdr.linktype != DLT_IEEE802_15_4) { + fprintf(stderr, "unrecognized link type 0x%x " + "(expected 0x%0x)\n", hdr.linktype, DLT_IEEE802_15_4); + exit(1); + } + if (ops->begin) + ops->begin(); + while (pcap_record(file, name)); + if (ops->finish) + ops->finish(); + fclose(file); +} + + +static void usage(const char *name) +{ + fprintf(stderr, "usage: %s pcap-file\n", name); + exit(1); +} + + +int main(int argc, char **argv) +{ + if (argc != 2) + usage(*argv); + ops = &text_ops; + process_pcap(argv[1]); + return 0; +} diff --git a/tools/atrf-txrx/perdump.h b/tools/atrf-txrx/perdump.h new file mode 100644 index 0000000..9d2b0c0 --- /dev/null +++ b/tools/atrf-txrx/perdump.h @@ -0,0 +1,28 @@ +/* + * atrf-txrx/perdump.h - Analyze and dump a recorded PER test + * + * Written 2011 by Werner Almesberger + * Copyright 2011 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 PERDUMP_H +#define PERDUMP_H + +struct result_ops { + void (*begin)(void); + void (*undecided)(int symbols); + void (*packet)(int symbols, int skip); + void (*error)(int symbol); + void (*finish)(void); +}; + + +extern struct result_ops text_ops; + +#endif /* !PERDUMP_H */