From b3a092055abacb99b3e9d71edd26c2dd2059dd7f Mon Sep 17 00:00:00 2001 From: Thomas Tsou Date: Thu, 12 Aug 2010 16:22:04 -0700 Subject: usrp1: Add SPI transaction command to FX2 firmware The existing SPI read command is set for half-duplex 8-bit or 16-bit writes followed by an equivalent sized read. This patch adds a new command, VRQ_SPI_TRANSACT, which performs a full-duplex transaction up to 4-bytes. Since the data buffer of the USB control transfer is not available for outbound data on IN requests, the 4 bytes of write data are sent through the request parameters. Enables are sent in the previsouly unused high byte of the length parameter. The USB field mappings are shown below. Only rising edge and MSB operation is supported. Field (8-bit) Description ===== ===== bmRequestType 0x80 (USB Device IN request) bRequest 0x83 (VRQ_SPI_TRANSACT) wValueH OUT data(0) wValueL OUT data(1) wIndexH OUT data(2) wIndexL OUT data(3) wLengthH SPI enables wLengthL Number of bytes to transfer (1-4) EP0BUF IN data --- firmware/fx2/include/usrp_commands.h | 7 +++ firmware/fx2/src/usrp1/spi.c | 95 +++++++++++++++++++++++++++++++++++- firmware/fx2/src/usrp1/spi.h | 7 +++ firmware/fx2/src/usrp1/usrp_main.c | 10 +++- 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/firmware/fx2/include/usrp_commands.h b/firmware/fx2/include/usrp_commands.h index 20c28e264..02778c7e3 100644 --- a/firmware/fx2/include/usrp_commands.h +++ b/firmware/fx2/include/usrp_commands.h @@ -54,6 +54,13 @@ // wIndexL: format // len: how much to read +#define VRQ_SPI_TRANSACT 0x83 // wValueH: OUT byte 0 + // wValueL: OUT byte 1 + // wIndexH: OUT byte 2 + // wIndexL: OUT byte 3 + // wLengthH: enables + // wLengthL: transaction length + // OUT commands #define VRQ_SET_LED 0x01 // wValueL off/on {0,1}; wIndexL: which {0,1} diff --git a/firmware/fx2/src/usrp1/spi.c b/firmware/fx2/src/usrp1/spi.c index f5803c55b..0aaffea5d 100644 --- a/firmware/fx2/src/usrp1/spi.c +++ b/firmware/fx2/src/usrp1/spi.c @@ -97,13 +97,18 @@ count_bits8 (unsigned char v) static void write_byte_msb (unsigned char v); +unsigned char +transact_byte_msb (unsigned char v); + static void write_bytes_msb (const xdata unsigned char *buf, unsigned char len); static void read_bytes_msb (xdata unsigned char *buf, unsigned char len); - +static void +transact_bytes_msb (xdata unsigned char *buf, unsigned char len); + // returns non-zero if successful, else 0 unsigned char spi_read (unsigned char header_hi, unsigned char header_lo, @@ -214,7 +219,93 @@ spi_write (unsigned char header_hi, unsigned char header_lo, return 1; // success } -// ---------------------------------------------------------------- +unsigned char +spi_transact (unsigned char data0, unsigned char data1, + unsigned char data2, unsigned char data3, + unsigned char enables, xdata unsigned char *buf, + unsigned char len) +{ + if (count_bits8 (enables) > 1) + return 0; // error, too many enables set + + if (len > 4) + return 0; + + setup_enables (enables); + + buf[0] = data0; + buf[1] = data1; + buf[2] = data2; + buf[3] = data3; + + if (len != 0) + transact_bytes_msb(buf, len); + + disable_all (); + return 1; // success +} + +static unsigned char +transact_byte_msb (unsigned char v) +{ + v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit) + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; // read into bottom bit + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + v = (v << 1) | (v >> 7); + bitS_OUT = v & 0x1; + bitS_CLK = 1; + v |= bitS_IN; + bitS_CLK = 0; + + return v; +} + +static void +transact_bytes_msb (xdata unsigned char *buf, unsigned char len) +{ + while (len-- != 0){ + *buf++ = transact_byte_msb (*buf); + } +} static void write_byte_msb (unsigned char v) diff --git a/firmware/fx2/src/usrp1/spi.h b/firmware/fx2/src/usrp1/spi.h index 12bc5e544..5342b82b8 100644 --- a/firmware/fx2/src/usrp1/spi.h +++ b/firmware/fx2/src/usrp1/spi.h @@ -39,5 +39,12 @@ spi_write (unsigned char header_hi, unsigned char header_lo, unsigned char enables, unsigned char format, const xdata unsigned char *buf, unsigned char len); +// returns non-zero if successful, else 0 +unsigned char +spi_transact (unsigned char data0, unsigned char data1, + unsigned char data2, unsigned char data3, + unsigned char enables, xdata unsigned char *buf, + unsigned char len); + #endif /* INCLUDED_SPI_H */ diff --git a/firmware/fx2/src/usrp1/usrp_main.c b/firmware/fx2/src/usrp1/usrp_main.c index c7c09f8c5..b8c2e98ec 100644 --- a/firmware/fx2/src/usrp1/usrp_main.c +++ b/firmware/fx2/src/usrp1/usrp_main.c @@ -117,7 +117,7 @@ app_vendor_cmd (void) EP0BCH = 0; EP0BCL = wLengthL; break; - + case VRQ_SPI_READ: if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL)) return 0; @@ -126,6 +126,14 @@ app_vendor_cmd (void) EP0BCL = wLengthL; break; + case VRQ_SPI_TRANSACT: + if (!spi_transact (wValueH, wValueL, wIndexH, wIndexL, wLengthH, EP0BUF, wLengthL)) + return 0; + + EP0BCH = 0; + EP0BCL = wLengthL; + break; + default: return 0; } -- cgit v1.2.3