mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-11-22 12:12:50 +02:00
Updated atusd driver for new hardware. Make use of the interrupt line.
- tools/lib/atusd.c (spi_send_partial, spi_send): removed the old spi_send and renamed spi_send_partial to spi_send - tools/lib/atusd.c (atusd_cycle, spi_send, spi_recv, atusd_open): updated for removal of SLP_TR and split of MxSx into MOSI and MISO - tools/lib/atusd.c (atusd_reset_rf, atusd_open): added delays to precharge the capacitors - tools/lib/atusd.c (atusd_reset, spi_data_in, spi_data_out, spi_finish): removed functions for obsolete hardware features - tools/lib/atusd.c (atusd_reg_read): removed calls to removed functions - tools/lib/atusd.c (atusd_buf_write, atusd_buf_read, atusd_driver): new buffer read/write functions - tools/atspi-txrx/atspi-txrx.c (init_txrx): set the internal osciallator trim only in the USB version. Switch to the external oscillator in the uSD version. - tools/atspi-rssi/atspi-rssi.c (sweep), tools/atspi-txrx/atspi-txrx.c (set_channel): wait for the PLL to settle after setting the channel - tools/include/atspi.h, tools/lib/atspi.c (atspi_interrupt), tools/lib/driver.h (struct atspi_driver), tools/lib/atusd.c (atusd_interrupt): new function to poll the interrupt line - tools/atspi-txrx/atspi-txrx.c (receive): only read REG_IRQ_STATUS if there is a pending interrupt - tools/atspi-id/atspi-id.c (usage): print "usage:" as well - tools/Makefile (upload): upload the atspi tools to the Ben
This commit is contained in:
parent
284b557434
commit
18eec557d0
@ -15,3 +15,8 @@ DIRS=atspi-id atspi-reset atspi-rssi atspi-trim atspi-txrx
|
||||
TARGET_ONLY_DIRS=lib
|
||||
|
||||
include ../Makefile.recurse
|
||||
|
||||
.PHONY: upload
|
||||
|
||||
upload:
|
||||
scp `for n in $(DIRS); do echo $$n/$$n; done` ben:
|
||||
|
@ -127,7 +127,7 @@ static void show_info(struct atspi_dsc *dsc)
|
||||
|
||||
static void usage(const char *name)
|
||||
{
|
||||
fprintf(stderr, "%s\n", name);
|
||||
fprintf(stderr, "usage: %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,8 @@ static void sweep(struct atspi_dsc *dsc)
|
||||
|
||||
for (chan = 11; chan <= 26; chan++) {
|
||||
atspi_reg_write(dsc, REG_PHY_CC_CCA, chan);
|
||||
/* 150 us, according to AVR2001 section 3.5 */
|
||||
usleep(1000);
|
||||
/*
|
||||
* No need to explicitly wait for the PPL lock - going USB-SPI
|
||||
* is pretty slow, leaving the transceiver plenty of time.
|
||||
|
@ -55,8 +55,12 @@ static struct atspi_dsc *init_txrx(int trim)
|
||||
|
||||
atspi_reset_rf(dsc);
|
||||
atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
|
||||
#ifdef HAVE_USB /* @@@ yeah, ugly */
|
||||
atspi_reg_write(dsc, REG_XOSC_CTRL,
|
||||
(XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
|
||||
#else
|
||||
atspi_reg_write(dsc, REG_XOSC_CTRL, XTAL_MODE_EXT << XTAL_MODE_SHIFT);
|
||||
#endif
|
||||
atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
|
||||
|
||||
return dsc;
|
||||
@ -66,6 +70,11 @@ static struct atspi_dsc *init_txrx(int trim)
|
||||
static void set_channel(struct atspi_dsc *dsc, int channel)
|
||||
{
|
||||
atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel);
|
||||
/*
|
||||
* 150 us, according to AVR2001 section 3.5. Note that we should just
|
||||
* wait for the PPL_LOCK interrupt.
|
||||
*/
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
|
||||
@ -93,6 +102,8 @@ static void receive(struct atspi_dsc *dsc)
|
||||
|
||||
fprintf(stderr, "Ready.\n");
|
||||
while (1) {
|
||||
while (!atspi_interrupt(dsc))
|
||||
usleep(10);
|
||||
irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
|
||||
if (atspi_error(dsc))
|
||||
exit(1);
|
||||
|
@ -36,4 +36,6 @@ uint8_t atspi_reg_read(struct atspi_dsc *dsc, uint8_t reg);
|
||||
void atspi_buf_write(struct atspi_dsc *dsc, const void *buf, int size);
|
||||
int atspi_buf_read(struct atspi_dsc *dsc, void *buf, int size);
|
||||
|
||||
int atspi_interrupt(struct atspi_dsc *dsc);
|
||||
|
||||
#endif /* !ATSPI_H */
|
||||
|
@ -121,3 +121,10 @@ int atspi_buf_read(struct atspi_dsc *dsc, void *buf, int size)
|
||||
{
|
||||
return dsc->driver->buf_read(dsc->handle, buf, size);
|
||||
}
|
||||
|
||||
|
||||
int atspi_interrupt(struct atspi_dsc *dsc)
|
||||
{
|
||||
return
|
||||
dsc->driver->interrupt ? dsc->driver->interrupt(dsc->handle) : 1;
|
||||
}
|
||||
|
@ -23,11 +23,11 @@
|
||||
|
||||
|
||||
enum {
|
||||
VDD_OFF = 1 << 6, /* VDD disable, PD06 */
|
||||
MxSx = 1 << 8, /* CMD, PD08 */
|
||||
VDD_OFF = 1 << 2, /* VDD disable, PD02 */
|
||||
MOSI = 1 << 8, /* CMD, PD08 */
|
||||
CLK = 1 << 9, /* CLK, PD09 */
|
||||
SCLK = 1 << 10, /* DAT0, PD10 */
|
||||
SLP_TR = 1 << 11, /* DAT1, PD11 */
|
||||
MISO = 1 << 10, /* DAT0, PD10 */
|
||||
SCLK = 1 << 11, /* DAT1, PD11 */
|
||||
IRQ = 1 << 12, /* DAT2, PD12 */
|
||||
nSEL = 1 << 13, /* DAT3/CD, PD13 */
|
||||
};
|
||||
@ -72,7 +72,7 @@ static void wait_for_power(void)
|
||||
{
|
||||
/*
|
||||
* Give power time to stabilize and the chip time to reset.
|
||||
* Experiments show that even usleep(0) is long enough.
|
||||
* Power takes about 2 ms to ramp up. We wait 10 ms to be sure.
|
||||
*/
|
||||
usleep(10*1000);
|
||||
}
|
||||
@ -84,7 +84,7 @@ static void atusd_cycle(struct atusd_dsc *dsc)
|
||||
MSC_STRPCL = 1;
|
||||
|
||||
/* drive all outputs low (including the MMC bus clock) */
|
||||
PDDATC = MxSx | CLK | SCLK | SLP_TR | nSEL;
|
||||
PDDATC = MOSI | CLK | SCLK | nSEL;
|
||||
|
||||
/* make the MMC bus clock a regular output */
|
||||
PDFUNC = CLK;
|
||||
@ -95,11 +95,11 @@ static void atusd_cycle(struct atusd_dsc *dsc)
|
||||
/* Power drains within about 20 ms. Wait 100 ms to be sure. */
|
||||
usleep(100*1000);
|
||||
|
||||
/* drive nSS high */
|
||||
PDDATS = nSEL;
|
||||
/* drive MOSI and nSS high */
|
||||
PDDATS = MOSI | nSEL;
|
||||
|
||||
/* supply power */
|
||||
PDDATC = VDD_OFF;
|
||||
/* precharge the capacitors to avoid current surge */
|
||||
wait_for_power();
|
||||
|
||||
/* return the bus clock output to the MMC controller */
|
||||
PDFUNS = CLK;
|
||||
@ -107,30 +107,13 @@ static void atusd_cycle(struct atusd_dsc *dsc)
|
||||
/* start MMC clock output */
|
||||
MSC_STRPCL = 2;
|
||||
|
||||
/* supply power */
|
||||
PDDATC = VDD_OFF;
|
||||
|
||||
wait_for_power();
|
||||
}
|
||||
|
||||
|
||||
#if 0 /* we probably won't need this anymore */
|
||||
static void atusd_reset(struct atusd_dsc *dsc)
|
||||
{
|
||||
/* activate reset */
|
||||
PDDATS = SLP_TR;
|
||||
PDDATC = nSEL;
|
||||
|
||||
/*
|
||||
* Data sheet says 625 ns, programmer's guide says 6 us. Whom do we
|
||||
* trust ?
|
||||
*/
|
||||
usleep(6);
|
||||
|
||||
/* release reset */
|
||||
PDDATS = nSEL;
|
||||
PDDATC = SLP_TR;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* ----- Low-level SPI operations ------------------------------------------ */
|
||||
|
||||
|
||||
@ -146,35 +129,17 @@ static void spi_end(struct atusd_dsc *dsc)
|
||||
}
|
||||
|
||||
|
||||
static void spi_data_in(struct atusd_dsc *dsc)
|
||||
{
|
||||
PDDIRC = MxSx;
|
||||
}
|
||||
|
||||
|
||||
static void spi_data_out(struct atusd_dsc *dsc)
|
||||
{
|
||||
PDDIRS = MxSx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Send a sequence of bytes but leave the clock high on the last bit, so that
|
||||
* we can turn around the data line for reads.
|
||||
*/
|
||||
|
||||
static void spi_send_partial(struct atusd_dsc *dsc, uint8_t v)
|
||||
static void spi_send(struct atusd_dsc *dsc, uint8_t v)
|
||||
{
|
||||
uint8_t mask;
|
||||
|
||||
for (mask = 0x80; mask; mask >>= 1) {
|
||||
PDDATC = SCLK;
|
||||
if (v & mask)
|
||||
PDDATS = MxSx;
|
||||
PDDATS = MOSI;
|
||||
else
|
||||
PDDATC = MxSx;
|
||||
PDDATC = MOSI;
|
||||
PDDATS = SCLK;
|
||||
PDDATC = SCLK;
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,29 +150,15 @@ static uint8_t spi_recv(struct atusd_dsc *dsc)
|
||||
uint8_t mask;
|
||||
|
||||
for (mask = 0x80; mask; mask >>= 1) {
|
||||
PDDATC = SCLK;
|
||||
if (PDPIN & MxSx)
|
||||
if (PDPIN & MISO)
|
||||
res |= mask;
|
||||
PDDATS = SCLK;
|
||||
PDDATC = SCLK;
|
||||
}
|
||||
PDDATC = SCLK;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void spi_finish(struct atusd_dsc *dsc)
|
||||
{
|
||||
PDDATC = SCLK;
|
||||
}
|
||||
|
||||
|
||||
static void spi_send(struct atusd_dsc *dsc, uint8_t v)
|
||||
{
|
||||
spi_send_partial(dsc, v);
|
||||
spi_finish(dsc);
|
||||
}
|
||||
|
||||
|
||||
/* ----- Driver operations ------------------------------------------------- */
|
||||
|
||||
|
||||
@ -216,6 +167,7 @@ static void atusd_reset_rf(void *handle)
|
||||
struct atusd_dsc *dsc = handle;
|
||||
|
||||
atusd_cycle(dsc);
|
||||
wait_for_power();
|
||||
}
|
||||
|
||||
|
||||
@ -243,15 +195,18 @@ static void *atusd_open(void)
|
||||
|
||||
/* set the output levels */
|
||||
PDDATS = nSEL | VDD_OFF;
|
||||
PDDATC = SCLK | SLP_TR;
|
||||
PDDATC = SCLK;
|
||||
|
||||
/* take the GPIOs away from the MMC controller */
|
||||
PDFUNC = MxSx | SCLK | SLP_TR | IRQ | nSEL;
|
||||
PDFUNC = MOSI | MISO | SCLK | IRQ | nSEL;
|
||||
PDFUNS = CLK;
|
||||
|
||||
/* set the pin directions */
|
||||
PDDIRC = IRQ;
|
||||
PDDIRS = MxSx | CLK | SCLK | SLP_TR | nSEL;
|
||||
PDDIRC = MISO | IRQ;
|
||||
PDDIRS = MOSI | CLK | SCLK | nSEL;
|
||||
|
||||
/* let capacitors precharge */
|
||||
wait_for_power();
|
||||
|
||||
/* enable power */
|
||||
PDDATC = VDD_OFF;
|
||||
@ -286,7 +241,7 @@ static void atusd_close(void *arg)
|
||||
PDDATS = VDD_OFF;
|
||||
|
||||
/* make all MMC pins inputs */
|
||||
PDDIRC = MxSx | CLK | SCLK | SLP_TR | IRQ | nSEL;
|
||||
PDDIRC = MOSI | MISO | CLK | SCLK | IRQ | nSEL;
|
||||
}
|
||||
|
||||
|
||||
@ -307,16 +262,52 @@ static uint8_t atusd_reg_read(void *handle, uint8_t reg)
|
||||
uint8_t res;
|
||||
|
||||
spi_begin(dsc);
|
||||
spi_send_partial(dsc, AT86RF230_REG_READ| reg);
|
||||
spi_data_in(dsc);
|
||||
spi_send(dsc, AT86RF230_REG_READ | reg);
|
||||
res = spi_recv(dsc);
|
||||
spi_finish(dsc);
|
||||
spi_data_out(dsc);
|
||||
spi_end(dsc);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static void atusd_buf_write(void *handle, const void *buf, int size)
|
||||
{
|
||||
struct atusd_dsc *dsc = handle;
|
||||
|
||||
spi_begin(dsc);
|
||||
spi_send(dsc, AT86RF230_BUF_WRITE);
|
||||
spi_send(dsc, size);
|
||||
while (size--)
|
||||
spi_send(dsc, *(uint8_t *) buf++);
|
||||
spi_end(dsc);
|
||||
}
|
||||
|
||||
|
||||
static int atusd_buf_read(void *handle, void *buf, int size)
|
||||
{
|
||||
struct atusd_dsc *dsc = handle;
|
||||
uint8_t len, i;
|
||||
|
||||
spi_begin(dsc);
|
||||
spi_send(dsc, AT86RF230_BUF_READ);
|
||||
len = spi_recv(dsc);
|
||||
len++; /* LQI */
|
||||
if (len > size)
|
||||
len = size;
|
||||
for (i = 0; i != len; i++)
|
||||
*(uint8_t *) buf++ = spi_recv(dsc);
|
||||
spi_end(dsc);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int atusd_interrupt(void *handle)
|
||||
{
|
||||
struct atusd_dsc *dsc = handle;
|
||||
|
||||
return !!(PDPIN & IRQ);
|
||||
}
|
||||
|
||||
|
||||
/* ----- Driver interface -------------------------------------------------- */
|
||||
|
||||
|
||||
@ -328,8 +319,7 @@ struct atspi_driver atusd_driver = {
|
||||
.reset_rf = atusd_reset_rf,
|
||||
.reg_write = atusd_reg_write,
|
||||
.reg_read = atusd_reg_read,
|
||||
#if 0
|
||||
.buf_write = atusd_buf_write,
|
||||
.buf_read = atusd_buf_read,
|
||||
#endif
|
||||
.interrupt = atusd_interrupt,
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ struct atspi_driver {
|
||||
uint8_t (*reg_read)(void *dsc, uint8_t reg);
|
||||
void (*buf_write)(void *dsc, const void *buf, int size);
|
||||
int (*buf_read)(void *dsc, void *buf, int size);
|
||||
int (*interrupt)(void *dsc);
|
||||
};
|
||||
|
||||
#endif /* !DRIVER_H */
|
||||
|
Loading…
Reference in New Issue
Block a user