mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-11-29 12:24:39 +02:00
atrf-path: option -P to load a min/max profile; pass/fail indication in GUI
- sweep.h (MIN_DIFF, MAX_DIFF, struct sweep): added min/max profile - sweep.h (do_sweep), atrf-path.c (do_half_sweep, do_sweep): compare result against limits and return pass/fail decision - sweep.h (N_CHAN), atrf-path.c (do_half_sweep, do_sweeps), gui.c (N_CHAN): declare number of channels in one central place instead of scattering it all around the program - atrf-path.c (do_read_profile, read_profile, usage, main): new option -P to read a min/max profile - gui.c (indicate, main): moved indicator to separate function and improved blink logic - gui.c (OVER_RGBA, UNDER_RGBA, indicate, main): change color to indicate pass/fail
This commit is contained in:
parent
a7d9dfd258
commit
a1fc867bf2
@ -15,6 +15,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "at86rf230.h"
|
#include "at86rf230.h"
|
||||||
|
|
||||||
@ -110,28 +111,44 @@ static void sample(const struct sweep *sweep, int cont_tx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void do_half_sweep(const struct sweep *sweep, int cont_tx,
|
static int do_half_sweep(const struct sweep *sweep, int cont_tx,
|
||||||
struct sample *res)
|
struct sample *res)
|
||||||
{
|
{
|
||||||
int chan;
|
int i, chan;
|
||||||
|
int fail = 0;
|
||||||
|
|
||||||
if (sweep->cont_tx && sweep->cont_tx != cont_tx)
|
if (sweep->cont_tx && sweep->cont_tx != cont_tx)
|
||||||
return;
|
return 0;
|
||||||
for (chan = 11; chan <= 26; chan++) {
|
chan = 11;
|
||||||
|
for (i = 0; i != N_CHAN; i++) {
|
||||||
set_channel(sweep->rx, chan);
|
set_channel(sweep->rx, chan);
|
||||||
set_channel(sweep->tx, chan);
|
set_channel(sweep->tx, chan);
|
||||||
usleep(155); /* table 7-2, tTR19 */
|
usleep(155); /* table 7-2, tTR19 */
|
||||||
|
|
||||||
sample(sweep, cont_tx, res, chan == 11 && !sweep->cont_tx);
|
sample(sweep, cont_tx, res, chan == 11 && !sweep->cont_tx);
|
||||||
|
if (res->avg > sweep->max[i])
|
||||||
|
fail = 1;
|
||||||
|
if (!fail && res->avg < sweep->min[i])
|
||||||
|
fail = -1;
|
||||||
|
|
||||||
res += 2;
|
res += 2;
|
||||||
|
chan++;
|
||||||
}
|
}
|
||||||
|
return fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void do_sweep(const struct sweep *sweep, struct sample *res)
|
int do_sweep(const struct sweep *sweep, struct sample *res)
|
||||||
{
|
{
|
||||||
do_half_sweep(sweep, CONT_TX_M500K, res);
|
int fail1, fail2;
|
||||||
do_half_sweep(sweep, CONT_TX_P500K, res+1);
|
|
||||||
|
fail1 = do_half_sweep(sweep, CONT_TX_M500K, res);
|
||||||
|
fail2 = do_half_sweep(sweep, CONT_TX_P500K, res+1);
|
||||||
|
if (fail1 > 0 || fail2 > 0)
|
||||||
|
return 1;
|
||||||
|
if (fail1 < 0 || fail2 < 0)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -154,7 +171,7 @@ static void print_sweep(const struct sweep *sweep, const struct sample *res)
|
|||||||
|
|
||||||
static void do_sweeps(const struct sweep *sweep, int sweeps)
|
static void do_sweeps(const struct sweep *sweep, int sweeps)
|
||||||
{
|
{
|
||||||
struct sample res[16*2]; /* 16 channels, 2 offsets */
|
struct sample res[N_CHAN*2]; /* 2 offsets per channel */
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i != sweeps; i++) {
|
for (i = 0; i != sweeps; i++) {
|
||||||
@ -166,6 +183,85 @@ static void do_sweeps(const struct sweep *sweep, int sweeps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int do_read_profile(const char *name, struct sweep *sweep)
|
||||||
|
{
|
||||||
|
FILE *file;
|
||||||
|
char buf[300];
|
||||||
|
int got;
|
||||||
|
char *p;
|
||||||
|
double min = MIN_DIFF, max = MAX_DIFF;
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
file = fopen(name, "r");
|
||||||
|
if (!file) {
|
||||||
|
perror(name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
while (fgets(buf, sizeof(buf), file)) {
|
||||||
|
p = strchr(buf, '\n');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
p = strchr(buf, '#');
|
||||||
|
if (p)
|
||||||
|
*p = 0;
|
||||||
|
for (p = buf; *p && isspace(*p); p++);
|
||||||
|
if (!*p)
|
||||||
|
continue;
|
||||||
|
got = sscanf(buf, "%lf %lf", &min, &max);
|
||||||
|
switch (got) {
|
||||||
|
case 0:
|
||||||
|
fprintf(stderr, "can't parse \"%s\"\n", buf);
|
||||||
|
exit(1);
|
||||||
|
case 1:
|
||||||
|
max = MAX_DIFF;
|
||||||
|
/* fall through */
|
||||||
|
case 2:
|
||||||
|
if (min < MIN_DIFF) {
|
||||||
|
fprintf(stderr, "minimum is %g dBm\n",
|
||||||
|
MIN_DIFF);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (max > MAX_DIFF) {
|
||||||
|
fprintf(stderr, "maximum is %g dBm\n",
|
||||||
|
MAX_DIFF);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (min > max) {
|
||||||
|
fprintf(stderr, "lower bound > upper bound\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (n == N_CHAN) {
|
||||||
|
fprintf(stderr, "too many channels\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
sweep->min[n] = min;
|
||||||
|
sweep->max[n] = max;
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void read_profile(const char *name, struct sweep *sweep)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
n = do_read_profile(name, sweep);
|
||||||
|
|
||||||
|
while (n != N_CHAN) {
|
||||||
|
sweep->min[n] = MIN_DIFF;
|
||||||
|
sweep->max[n] = MAX_DIFF;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void usage(const char *name)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -175,15 +271,16 @@ static void usage(const char *name)
|
|||||||
"%6s %s -g common_args [[sweeps] samples]\n"
|
"%6s %s -g common_args [[sweeps] samples]\n"
|
||||||
#endif
|
#endif
|
||||||
"\n"
|
"\n"
|
||||||
" common args: [-p power] [-t trim_tx [-t trim_rx]] [-T offset]\n"
|
" common args: [-p power] [-P profile] [-t trim_tx [-t trim_rx]]\n"
|
||||||
" driver_tx[:arg] driver_rx[:arg]\n\n"
|
" [-T offset] driver_tx[:arg] driver_rx[:arg]\n\n"
|
||||||
|
|
||||||
#ifdef HAVE_GFX
|
#ifdef HAVE_GFX
|
||||||
" -g display results graphically\n"
|
" -g display results graphically\n"
|
||||||
#endif
|
#endif
|
||||||
" -p power transmit power, 0 to 15 (default %d)\n"
|
" -p power transmit power, 0 to 15 (default %d)\n"
|
||||||
" -t trim trim capacitor, 0 to 15 (default %d)\n"
|
" -P profile load profile for pass/fail decisions\n"
|
||||||
" -T offset constant wave offset in MHz, -0.5 or +0.5 (default: scan both)\n"
|
" -t trim trim capacitor, 0 to 15 (default %d)\n"
|
||||||
|
" -T offset constant wave offset in MHz, -0.5 or +0.5 (default: scan both)\n"
|
||||||
|
|
||||||
, name,
|
, name,
|
||||||
#ifdef HAVE_GFX
|
#ifdef HAVE_GFX
|
||||||
@ -206,12 +303,13 @@ int main(int argc, char **argv)
|
|||||||
};
|
};
|
||||||
int graphical = 0;
|
int graphical = 0;
|
||||||
int power = DEFAULT_POWER;
|
int power = DEFAULT_POWER;
|
||||||
|
const char *profile = NULL;
|
||||||
int sweeps = 1;
|
int sweeps = 1;
|
||||||
unsigned long tmp;
|
unsigned long tmp;
|
||||||
char *end;
|
char *end;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
while ((c = getopt(argc, argv, "gp:t:T:")) != EOF)
|
while ((c = getopt(argc, argv, "gp:P:t:T:")) != EOF)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case'g':
|
case'g':
|
||||||
graphical = 1;
|
graphical = 1;
|
||||||
@ -223,6 +321,9 @@ int main(int argc, char **argv)
|
|||||||
usage(*argv);
|
usage(*argv);
|
||||||
power = tmp;
|
power = tmp;
|
||||||
break;
|
break;
|
||||||
|
case 'P':
|
||||||
|
profile = optarg;
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
tmp = strtoul(optarg, &end, 0);
|
tmp = strtoul(optarg, &end, 0);
|
||||||
if (*end || tmp > 15)
|
if (*end || tmp > 15)
|
||||||
@ -270,6 +371,8 @@ int main(int argc, char **argv)
|
|||||||
usage(*argv);
|
usage(*argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
read_profile(profile, &sweep);
|
||||||
|
|
||||||
sweep.tx = atrf_open(tx_drv);
|
sweep.tx = atrf_open(tx_drv);
|
||||||
if (!sweep.tx)
|
if (!sweep.tx)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -29,11 +29,10 @@
|
|||||||
#define XRES 320
|
#define XRES 320
|
||||||
#define YRES 240
|
#define YRES 240
|
||||||
|
|
||||||
#define N_CHAN 16
|
|
||||||
|
|
||||||
|
|
||||||
#define FG_RGBA 0xffffffff /* measurement color */
|
#define FG_RGBA 0xffffffff /* measurement color */
|
||||||
#define OK_RGBA 0x00ff00ff
|
#define OK_RGBA 0x00ff00ff
|
||||||
|
#define OVER_RGBA 0xffff00ff
|
||||||
|
#define UNDER_RGBA 0xff0000ff
|
||||||
|
|
||||||
#define CHAN_STEP 20 /* 4 pixels/MHz */
|
#define CHAN_STEP 20 /* 4 pixels/MHz */
|
||||||
#define SIDE_STEP 2
|
#define SIDE_STEP 2
|
||||||
@ -84,6 +83,33 @@ static void draw(SDL_Surface *s, const struct sample *res, int cont_tx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void indicate(SDL_Surface *s, int fail)
|
||||||
|
{
|
||||||
|
static uint32_t last = 0;
|
||||||
|
uint32_t color;
|
||||||
|
|
||||||
|
switch (fail) {
|
||||||
|
case 0:
|
||||||
|
color = OK_RGBA;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
color = OVER_RGBA;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
color = UNDER_RGBA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (color == last)
|
||||||
|
color = 0;
|
||||||
|
last = color;
|
||||||
|
|
||||||
|
filledCircleColor(s, STATUS_X, STATUS_Y, STATUS_R, color);
|
||||||
|
aacircleColor(s, STATUS_X, STATUS_Y, STATUS_R, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void clear(SDL_Surface *s)
|
static void clear(SDL_Surface *s)
|
||||||
{
|
{
|
||||||
SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 0, 0, 0));
|
SDL_FillRect(s, NULL, SDL_MapRGB(s->format, 0, 0, 0));
|
||||||
@ -124,6 +150,7 @@ void gui(const struct sweep *sweep, int sweeps)
|
|||||||
SDL_Surface *surf;
|
SDL_Surface *surf;
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
int cycle = 0;
|
int cycle = 0;
|
||||||
|
int fail;
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||||
fprintf(stderr, "SDL_init: %s\n", SDL_GetError());
|
fprintf(stderr, "SDL_init: %s\n", SDL_GetError());
|
||||||
@ -145,19 +172,14 @@ void gui(const struct sweep *sweep, int sweeps)
|
|||||||
event.type == SDL_QUIT)
|
event.type == SDL_QUIT)
|
||||||
return;
|
return;
|
||||||
tstart();
|
tstart();
|
||||||
do_sweep(sweep, res);
|
fail = do_sweep(sweep, res);
|
||||||
tstop();
|
tstop();
|
||||||
|
|
||||||
SDL_LockSurface(surf);
|
SDL_LockSurface(surf);
|
||||||
|
|
||||||
clear(surf);
|
clear(surf);
|
||||||
|
|
||||||
if (cycle++ & 1) {
|
indicate(surf, fail);
|
||||||
filledCircleColor(surf, STATUS_X, STATUS_Y, STATUS_R,
|
|
||||||
OK_RGBA);
|
|
||||||
aacircleColor(surf, STATUS_X, STATUS_Y, STATUS_R,
|
|
||||||
OK_RGBA);
|
|
||||||
}
|
|
||||||
draw(surf, res, sweep->cont_tx);
|
draw(surf, res, sweep->cont_tx);
|
||||||
|
|
||||||
SDL_UnlockSurface(surf);
|
SDL_UnlockSurface(surf);
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
#include "atrf.h"
|
#include "atrf.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define N_CHAN 16
|
||||||
|
|
||||||
|
#define MIN_DIFF -97.0 /* RSSI(min)-TX(max) = -94 - 3 */
|
||||||
|
#define MAX_DIFF 7.0 /* RSSI(max)-TX(min) = -10 - (-17) */
|
||||||
|
|
||||||
|
|
||||||
struct sweep {
|
struct sweep {
|
||||||
struct atrf_dsc *tx;
|
struct atrf_dsc *tx;
|
||||||
struct atrf_dsc *rx;
|
struct atrf_dsc *rx;
|
||||||
@ -27,6 +33,8 @@ struct sweep {
|
|||||||
int power;
|
int power;
|
||||||
uint8_t cont_tx;
|
uint8_t cont_tx;
|
||||||
int samples;
|
int samples;
|
||||||
|
double min[N_CHAN];
|
||||||
|
double max[N_CHAN];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sample {
|
struct sample {
|
||||||
@ -35,6 +43,14 @@ struct sample {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void do_sweep(const struct sweep *sweep, struct sample *res);
|
/*
|
||||||
|
* do_sweep returns whether the signal is within the limits:
|
||||||
|
*
|
||||||
|
* 1: at least one sample is above the maximum
|
||||||
|
* 0: all samples are between minimum and maximum
|
||||||
|
* -1: at least one sample below the minimum, and none above the maximum
|
||||||
|
*/
|
||||||
|
|
||||||
|
int do_sweep(const struct sweep *sweep, struct sample *res);
|
||||||
|
|
||||||
#endif /* !SWEEP_H */
|
#endif /* !SWEEP_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user