diff --git a/atusd/ERRATA b/atusd/ERRATA index 9bb63d2..4d024cf 100644 --- a/atusd/ERRATA +++ b/atusd/ERRATA @@ -6,3 +6,7 @@ - the footprint of the transistor (Q1) is reversed :-( It works after converting the chip from SOT to PLCC. + +- not an erratum, but with experiments showing power-on reset to be + reliable, we can consider removing the hardware reset circuit. This will + also simplify the layout. diff --git a/atusd/tools/Makefile b/atusd/tools/Makefile index c3c48a2..77925e4 100644 --- a/atusd/tools/Makefile +++ b/atusd/tools/Makefile @@ -1,5 +1,5 @@ CC=mipsel-openwrt-linux-gcc -CFLAGS=-Wall +CFLAGS=-Wall -I../../atrf/fw/include MAIN = try OBJS = $(MAIN).c lib/atusd.o diff --git a/atusd/tools/lib/atusd.c b/atusd/tools/lib/atusd.c index 96bed59..111aea5 100644 --- a/atusd/tools/lib/atusd.c +++ b/atusd/tools/lib/atusd.c @@ -5,6 +5,9 @@ #include #include +#include "at86rf230.h" +#include "atusd.h" + enum { VDD_OFF = 1 << 6, /* VDD disable, PD06 */ @@ -25,6 +28,7 @@ enum { #define GPIO(n) REG(0x10000+(n)) #define MSC(n) REG(0x21000+(n)) +#define PDPIN GPIO(0x300) /* port D pin level */ #define PDDATS GPIO(0x314) /* port D data set */ #define PDDATC GPIO(0x318) /* port D data clear */ #define PDFUNS GPIO(0x344) /* port D function set */ @@ -142,6 +146,12 @@ void atusd_cycle(struct atusd_dsc *dsc) /* start MMC clock output */ MSC_STRPCL = 2; + + /* + * Give power time to stabilize and the chip time to reset. + * Experiments show that even usleep(0) is long enough. + */ + usleep(10*1000); } @@ -161,3 +171,101 @@ void atusd_reset(struct atusd_dsc *dsc) PDDATS = nSEL; PDDATC = SLP_TR; } + + +static void spi_begin(struct atusd_dsc *dsc) +{ + PDDATC = nSEL; +} + + +static void spi_end(struct atusd_dsc *dsc) +{ + PDDATS = nSEL; +} + + +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) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + PDDATC = SCLK; + if (v & mask) + PDDATS = MxSx; + else + PDDATC = MxSx; + PDDATS = SCLK; + } +} + + +static uint8_t spi_recv(struct atusd_dsc *dsc) +{ + uint8_t res = 0; + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + PDDATC = SCLK; + if (PDPIN & MxSx) + res |= mask; + PDDATS = 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); +} + + +void atusd_reg_write(struct atusd_dsc *dsc, uint8_t reg, uint8_t v) +{ + spi_begin(dsc); + spi_send(dsc, AT86RF230_REG_WRITE | reg); + spi_send(dsc, v); + spi_end(dsc); +} + + +uint8_t atusd_reg_read(struct atusd_dsc *dsc, uint8_t reg) +{ + uint8_t res; + + spi_begin(dsc); + spi_send_partial(dsc, AT86RF230_REG_READ| reg); + spi_data_in(dsc); + res = spi_recv(dsc); + spi_finish(dsc); + spi_data_out(dsc); + spi_end(dsc); + return res; +} diff --git a/atusd/tools/lib/atusd.h b/atusd/tools/lib/atusd.h index 8304df6..b626b65 100644 --- a/atusd/tools/lib/atusd.h +++ b/atusd/tools/lib/atusd.h @@ -1,3 +1,9 @@ +#ifndef ATUSD_H +#define ATUSD_H + +#include + + struct atusd_dsc; @@ -5,3 +11,7 @@ struct atusd_dsc *atusd_open(void); void atusd_close(struct atusd_dsc *dsc); void atusd_cycle(struct atusd_dsc *dsc); void atusd_reset(struct atusd_dsc *dsc); +void atusd_reg_write(struct atusd_dsc *dsc, uint8_t reg, uint8_t v); +uint8_t atusd_reg_read(struct atusd_dsc *dsc, uint8_t reg); + +#endif /* ATUSD_H */ diff --git a/atusd/tools/try.c b/atusd/tools/try.c index 4f28e1a..c753130 100644 --- a/atusd/tools/try.c +++ b/atusd/tools/try.c @@ -1,19 +1,28 @@ +#include #include #include +#include "at86rf230.h" #include "lib/atusd.h" int main(void) { struct atusd_dsc *dsc; - char tmp; + uint8_t part, version, man_id_0, man_id_1; dsc = atusd_open(); - read(1, &tmp, 1); -fprintf(stderr, "cycling\n"); + atusd_cycle(dsc); - read(1, &tmp, 1); +// atusd_reset(dsc); + + part = atusd_reg_read(dsc, REG_PART_NUM); + version = atusd_reg_read(dsc, REG_VERSION_NUM); + man_id_0 = atusd_reg_read(dsc, REG_MAN_ID_0); + man_id_1 = atusd_reg_read(dsc, REG_MAN_ID_1); + printf("part 0x%02x version %u manufacturer xxxx%02x%02x\n", + part, version, man_id_1, man_id_0); + atusd_close(dsc); return 0;