1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-23 04:57:10 +02:00
ben-wpan/tools/atrf-gpio/atben.c

188 lines
3.5 KiB
C
Raw Normal View History

/*
* atrf-gpio/atben.c - ATBEN-specific GPIO driver
*
* 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 <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "at86rf230.h"
#include "atrf.h"
#include "atrf-gpio.h"
static struct pin {
const char *name;
int bit;
} pins[] = {
{ "SCLK", 11 },
{ "MISO", 10 },
{ "SLP_TR", 9 },
{ "MOSI", 8 },
{ "nSEL", 13 },
{ "IRQ", 12 },
{ NULL, 0 }
};
static uint32_t orig_dat, orig_pe, orig_dir;
static uint32_t changed = 0;
/* ----- Ben hardware ------------------------------------------------------ */
static volatile uint32_t *pdpin, *pddat, *pddats, *pddatc;
static volatile uint32_t *pdpe, *pdpes, *pdpec;
static volatile uint32_t *pddir, *pddirs, *pddirc;
static void ben_setup(struct atrf_dsc *dsc)
{
volatile void *base = atrf_ben_regs(dsc);
pdpin = base+0x10300;
pddat = base+0x10310;
pddats = base+0x10314;
pddatc = base+0x10318;
pdpe = base+0x10330;
pdpes = base+0x10334;
pdpec = base+0x10338;
pddir = base+0x10360;
pddirs = base+0x10364;
pddirc = base+0x10368;
}
/* ----- Diagnostic dump --------------------------------------------------- */
static char decode_cfg(uint32_t bit)
{
if (*pddir & bit)
return *pddat & bit ? '1' : '0';
return *pdpe & bit ? 'Z' : 'R';
}
static void dump_pd(uint32_t expect, uint32_t got, uint32_t mask)
{
const struct pin *pin;
fprintf(stderr, "name\tcfg exp got\n");
for (pin = pins; pin->name; pin++) {
uint32_t bit = 1 << pin->bit;
fprintf(stderr, "%s\t%c %c %d",
pin->name, decode_cfg(bit),
mask & bit ? expect & bit ? '1' : '0' : '-',
!!(got & bit));
if ((expect ^ got) & mask & bit)
fprintf(stderr, "\t***");
fputc('\n', stderr);
}
}
static void restore_gpios(void)
{
*pddats = orig_dat & changed;
*pddatc = ~orig_dat & changed;
*pdpes = orig_pe & changed;
*pdpec = ~orig_pe & changed;
*pddirs = orig_dir & changed;
*pddirc = ~orig_dir & changed;
}
/* ----- Decode and apply pattern ------------------------------------------ */
void do_atben(struct atrf_dsc *dsc, const char *pattern, const char *next)
{
static int first = 1;
uint32_t read = 0, expect = 0;
const struct pin *pin = pins;
uint32_t got;
const char *p;
if (first) {
ben_setup(dsc);
orig_dat = *pddat;
orig_pe = *pdpe;
orig_dir = *pddir;
atexit(restore_gpios);
first = 0;
}
for (p = pattern; *p; p++) {
uint32_t bit;
if (!pin->name) {
fprintf(stderr, "too many pins in \"%s\"\n", pattern);
exit(1);
}
bit = 1 << pin->bit;
switch (*p) {
case '0':
*pddatc = bit;
*pddirs = bit;
break;
case '1':
*pddats = bit;
*pddirs = bit;
break;
case 'H':
expect |= bit;
/* fall through */
case 'L':
read |= bit;
/* fall through */
case 'Z':
*pdpec = bit;
*pddirc = bit;
break;
case 'h':
expect |= bit;
/* fall through */
case 'l':
case 'o':
read |= bit;
/* fall through */
case 'z':
*pddirc = bit;
*pdpes = bit;
break;
case 'x':
pin++;
continue;
default:
continue;
}
changed |= bit;
pin++;
}
usleep(1000);
got = *pdpin;
if ((got & read) != expect) {
dump_pd(expect, got, read);
fprintf(stderr, "at \"%s\", next \"%s\"\n", pattern, next);
exit(1);
}
}