mirror of
git://projects.qi-hardware.com/ben-wpan.git
synced 2024-11-22 18:19:23 +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
|
TARGET_ONLY_DIRS=lib
|
||||||
|
|
||||||
include ../Makefile.recurse
|
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)
|
static void usage(const char *name)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", name);
|
fprintf(stderr, "usage: %s\n", name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@ static void sweep(struct atspi_dsc *dsc)
|
|||||||
|
|
||||||
for (chan = 11; chan <= 26; chan++) {
|
for (chan = 11; chan <= 26; chan++) {
|
||||||
atspi_reg_write(dsc, REG_PHY_CC_CCA, 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
|
* No need to explicitly wait for the PPL lock - going USB-SPI
|
||||||
* is pretty slow, leaving the transceiver plenty of time.
|
* 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_reset_rf(dsc);
|
||||||
atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
|
atspi_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF);
|
||||||
|
#ifdef HAVE_USB /* @@@ yeah, ugly */
|
||||||
atspi_reg_write(dsc, REG_XOSC_CTRL,
|
atspi_reg_write(dsc, REG_XOSC_CTRL,
|
||||||
(XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim);
|
(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 */
|
atspi_reg_write(dsc, REG_TRX_CTRL_0, 0); /* disable CLKM */
|
||||||
|
|
||||||
return dsc;
|
return dsc;
|
||||||
@ -66,6 +70,11 @@ static struct atspi_dsc *init_txrx(int trim)
|
|||||||
static void set_channel(struct atspi_dsc *dsc, int channel)
|
static void set_channel(struct atspi_dsc *dsc, int channel)
|
||||||
{
|
{
|
||||||
atspi_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | 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");
|
fprintf(stderr, "Ready.\n");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
while (!atspi_interrupt(dsc))
|
||||||
|
usleep(10);
|
||||||
irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
|
irq = atspi_reg_read(dsc, REG_IRQ_STATUS);
|
||||||
if (atspi_error(dsc))
|
if (atspi_error(dsc))
|
||||||
exit(1);
|
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);
|
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_buf_read(struct atspi_dsc *dsc, void *buf, int size);
|
||||||
|
|
||||||
|
int atspi_interrupt(struct atspi_dsc *dsc);
|
||||||
|
|
||||||
#endif /* !ATSPI_H */
|
#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);
|
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 {
|
enum {
|
||||||
VDD_OFF = 1 << 6, /* VDD disable, PD06 */
|
VDD_OFF = 1 << 2, /* VDD disable, PD02 */
|
||||||
MxSx = 1 << 8, /* CMD, PD08 */
|
MOSI = 1 << 8, /* CMD, PD08 */
|
||||||
CLK = 1 << 9, /* CLK, PD09 */
|
CLK = 1 << 9, /* CLK, PD09 */
|
||||||
SCLK = 1 << 10, /* DAT0, PD10 */
|
MISO = 1 << 10, /* DAT0, PD10 */
|
||||||
SLP_TR = 1 << 11, /* DAT1, PD11 */
|
SCLK = 1 << 11, /* DAT1, PD11 */
|
||||||
IRQ = 1 << 12, /* DAT2, PD12 */
|
IRQ = 1 << 12, /* DAT2, PD12 */
|
||||||
nSEL = 1 << 13, /* DAT3/CD, PD13 */
|
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.
|
* 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);
|
usleep(10*1000);
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ static void atusd_cycle(struct atusd_dsc *dsc)
|
|||||||
MSC_STRPCL = 1;
|
MSC_STRPCL = 1;
|
||||||
|
|
||||||
/* drive all outputs low (including the MMC bus clock) */
|
/* 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 */
|
/* make the MMC bus clock a regular output */
|
||||||
PDFUNC = CLK;
|
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. */
|
/* Power drains within about 20 ms. Wait 100 ms to be sure. */
|
||||||
usleep(100*1000);
|
usleep(100*1000);
|
||||||
|
|
||||||
/* drive nSS high */
|
/* drive MOSI and nSS high */
|
||||||
PDDATS = nSEL;
|
PDDATS = MOSI | nSEL;
|
||||||
|
|
||||||
/* supply power */
|
/* precharge the capacitors to avoid current surge */
|
||||||
PDDATC = VDD_OFF;
|
wait_for_power();
|
||||||
|
|
||||||
/* return the bus clock output to the MMC controller */
|
/* return the bus clock output to the MMC controller */
|
||||||
PDFUNS = CLK;
|
PDFUNS = CLK;
|
||||||
@ -107,30 +107,13 @@ static void atusd_cycle(struct atusd_dsc *dsc)
|
|||||||
/* start MMC clock output */
|
/* start MMC clock output */
|
||||||
MSC_STRPCL = 2;
|
MSC_STRPCL = 2;
|
||||||
|
|
||||||
|
/* supply power */
|
||||||
|
PDDATC = VDD_OFF;
|
||||||
|
|
||||||
wait_for_power();
|
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 ------------------------------------------ */
|
/* ----- 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)
|
static void spi_send(struct atusd_dsc *dsc, uint8_t v)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
|
|
||||||
for (mask = 0x80; mask; mask >>= 1) {
|
for (mask = 0x80; mask; mask >>= 1) {
|
||||||
PDDATC = SCLK;
|
|
||||||
if (v & mask)
|
if (v & mask)
|
||||||
PDDATS = MxSx;
|
PDDATS = MOSI;
|
||||||
else
|
else
|
||||||
PDDATC = MxSx;
|
PDDATC = MOSI;
|
||||||
PDDATS = SCLK;
|
PDDATS = SCLK;
|
||||||
|
PDDATC = SCLK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,29 +150,15 @@ static uint8_t spi_recv(struct atusd_dsc *dsc)
|
|||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
|
|
||||||
for (mask = 0x80; mask; mask >>= 1) {
|
for (mask = 0x80; mask; mask >>= 1) {
|
||||||
PDDATC = SCLK;
|
if (PDPIN & MISO)
|
||||||
if (PDPIN & MxSx)
|
|
||||||
res |= mask;
|
res |= mask;
|
||||||
PDDATS = SCLK;
|
PDDATS = SCLK;
|
||||||
|
PDDATC = SCLK;
|
||||||
}
|
}
|
||||||
PDDATC = SCLK;
|
|
||||||
return res;
|
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 ------------------------------------------------- */
|
/* ----- Driver operations ------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
@ -216,6 +167,7 @@ static void atusd_reset_rf(void *handle)
|
|||||||
struct atusd_dsc *dsc = handle;
|
struct atusd_dsc *dsc = handle;
|
||||||
|
|
||||||
atusd_cycle(dsc);
|
atusd_cycle(dsc);
|
||||||
|
wait_for_power();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -243,15 +195,18 @@ static void *atusd_open(void)
|
|||||||
|
|
||||||
/* set the output levels */
|
/* set the output levels */
|
||||||
PDDATS = nSEL | VDD_OFF;
|
PDDATS = nSEL | VDD_OFF;
|
||||||
PDDATC = SCLK | SLP_TR;
|
PDDATC = SCLK;
|
||||||
|
|
||||||
/* take the GPIOs away from the MMC controller */
|
/* take the GPIOs away from the MMC controller */
|
||||||
PDFUNC = MxSx | SCLK | SLP_TR | IRQ | nSEL;
|
PDFUNC = MOSI | MISO | SCLK | IRQ | nSEL;
|
||||||
PDFUNS = CLK;
|
PDFUNS = CLK;
|
||||||
|
|
||||||
/* set the pin directions */
|
/* set the pin directions */
|
||||||
PDDIRC = IRQ;
|
PDDIRC = MISO | IRQ;
|
||||||
PDDIRS = MxSx | CLK | SCLK | SLP_TR | nSEL;
|
PDDIRS = MOSI | CLK | SCLK | nSEL;
|
||||||
|
|
||||||
|
/* let capacitors precharge */
|
||||||
|
wait_for_power();
|
||||||
|
|
||||||
/* enable power */
|
/* enable power */
|
||||||
PDDATC = VDD_OFF;
|
PDDATC = VDD_OFF;
|
||||||
@ -286,7 +241,7 @@ static void atusd_close(void *arg)
|
|||||||
PDDATS = VDD_OFF;
|
PDDATS = VDD_OFF;
|
||||||
|
|
||||||
/* make all MMC pins inputs */
|
/* 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;
|
uint8_t res;
|
||||||
|
|
||||||
spi_begin(dsc);
|
spi_begin(dsc);
|
||||||
spi_send_partial(dsc, AT86RF230_REG_READ| reg);
|
spi_send(dsc, AT86RF230_REG_READ | reg);
|
||||||
spi_data_in(dsc);
|
|
||||||
res = spi_recv(dsc);
|
res = spi_recv(dsc);
|
||||||
spi_finish(dsc);
|
|
||||||
spi_data_out(dsc);
|
|
||||||
spi_end(dsc);
|
spi_end(dsc);
|
||||||
return res;
|
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 -------------------------------------------------- */
|
/* ----- Driver interface -------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
@ -328,8 +319,7 @@ struct atspi_driver atusd_driver = {
|
|||||||
.reset_rf = atusd_reset_rf,
|
.reset_rf = atusd_reset_rf,
|
||||||
.reg_write = atusd_reg_write,
|
.reg_write = atusd_reg_write,
|
||||||
.reg_read = atusd_reg_read,
|
.reg_read = atusd_reg_read,
|
||||||
#if 0
|
|
||||||
.buf_write = atusd_buf_write,
|
.buf_write = atusd_buf_write,
|
||||||
.buf_read = atusd_buf_read,
|
.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);
|
uint8_t (*reg_read)(void *dsc, uint8_t reg);
|
||||||
void (*buf_write)(void *dsc, const void *buf, int size);
|
void (*buf_write)(void *dsc, const void *buf, int size);
|
||||||
int (*buf_read)(void *dsc, void *buf, int size);
|
int (*buf_read)(void *dsc, void *buf, int size);
|
||||||
|
int (*interrupt)(void *dsc);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* !DRIVER_H */
|
#endif /* !DRIVER_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user