From 99c604c175356a9bd4cf9636af6d4b9dd56e20ac Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 7 Oct 2017 04:47:56 -0700 Subject: [PATCH 01/45] Send single response over spi, allowing packets with zeros in them --- commands.c | 111 ++++++++++++++++++++++++++--------------- radio.c | 50 ++++++++++++------- radio.h | 4 +- spi1_alt2/serial.c | 23 ++++----- spi1_alt2/serial.h | 1 + tools/serial_rf_spy.py | 15 +++--- 6 files changed, 126 insertions(+), 78 deletions(-) diff --git a/commands.c b/commands.c index 9f8abb6..6291f1c 100644 --- a/commands.c +++ b/commands.c @@ -7,31 +7,52 @@ uint8_t interrupting_cmd = 0; +// If use_pktlen is 0, then a sentinal value of 0 determines end of packet. +// If use_pktlen is non-zero, then rx will stop at PKTLEN +uint8_t use_pktlen = 0; + typedef void (*CommandHandler)(); CommandHandler handlers[] = { - /* 0 */ 0, - /* 1 */ cmd_get_state, - /* 2 */ cmd_get_version, - /* 3 */ cmd_get_packet, - /* 4 */ cmd_send_packet, - /* 5 */ cmd_send_and_listen, - /* 6 */ cmd_update_register, - /* 7 */ cmd_reset, - /* 8 */ cmd_led, - /* 9 */ cmd_read_register + /* 0 */ 0, + /* 1 */ cmd_get_state, + /* 2 */ cmd_get_version, + /* 3 */ cmd_get_packet, + /* 4 */ cmd_old_send_packet, + /* 5 */ cmd_send_and_listen, + /* 6 */ cmd_update_register, + /* 7 */ cmd_reset, + /* 8 */ cmd_led, + /* 9 */ cmd_read_register, + /* 10 */ cmd_send_packet }; +void do_cmd(uint8_t cmd) { + if (cmd > 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { + handlers[cmd](); + } +} + +void get_command() { + uint8_t cmd; + cmd = serial_rx_byte(); + do_cmd(cmd); + if (interrupting_cmd) { + do_cmd(interrupting_cmd); + interrupting_cmd = 0; + } +} + void cmd_get_packet() { uint8_t channel; uint32_t timeout_ms; uint8_t result; channel = serial_rx_byte(); timeout_ms = serial_rx_long(); - result = get_packet_and_write_to_serial(channel, timeout_ms); + result = get_packet_and_write_to_serial(channel, timeout_ms, use_pktlen); if (result != 0) { serial_tx_byte(result); - serial_tx_byte(0); + serial_flush(); } } @@ -40,34 +61,33 @@ void cmd_get_state() { } void cmd_get_version() { - serial_tx_str("subg_rfspy 1.0"); + serial_tx_str("subg_rfspy 2.0"); } -void do_cmd(uint8_t cmd) { - if (cmd > 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { - handlers[cmd](); - } -} - -void get_command() { - uint8_t cmd; - cmd = serial_rx_byte(); - do_cmd(cmd); - if (interrupting_cmd) { - do_cmd(interrupting_cmd); - interrupting_cmd = 0; - } +// Deprecated. Relied on 0 byte to end packet +void cmd_old_send_packet() { + uint8_t channel; + uint8_t repeat_count; + uint8_t delay_ms; + channel = serial_rx_byte(); + repeat_count = serial_rx_byte(); + delay_ms = serial_rx_byte(); + send_packet_from_serial(channel, repeat_count, delay_ms, 0); + serial_flush(); } void cmd_send_packet() { uint8_t channel; uint8_t repeat_count; uint8_t delay_ms; + uint8_t len; channel = serial_rx_byte(); repeat_count = serial_rx_byte(); delay_ms = serial_rx_byte(); - send_packet_from_serial(channel, repeat_count, delay_ms); + len = serial_rx_byte(); + send_packet_from_serial(channel, repeat_count, delay_ms, len); serial_tx_byte(0); + serial_flush(); } /* Combined send and receive */ @@ -87,19 +107,19 @@ void cmd_send_and_listen() { timeout_ms = serial_rx_long(); retry_count = serial_rx_byte(); - send_packet_from_serial(send_channel, repeat_count, delay_ms); - result = get_packet_and_write_to_serial(listen_channel, timeout_ms); + send_packet_from_serial(send_channel, repeat_count, delay_ms, 0); + result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); while (result == ERROR_RX_TIMEOUT && retry_count > 0) { resend_from_tx_buf(send_channel); - result = get_packet_and_write_to_serial(listen_channel, timeout_ms); + result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); retry_count--; } if (result != 0) { // Error, and no retries left serial_tx_byte(result); - serial_tx_byte(0); + serial_flush(); } } @@ -204,17 +224,23 @@ void cmd_read_register() { case 0x1F: value = FSCAL0; break; - case 0x20: + case 0x24: + value = TEST1; + break; + case 0x25: + value = TEST0; + break; + case 0x2D: value = PA_TABLE1; break; - case 0x21: + case 0x2E: value = PA_TABLE0; break; default: value = 0x5A; } serial_tx_byte(value); - serial_tx_byte(0); + serial_flush(); } void cmd_update_register() { @@ -233,6 +259,7 @@ void cmd_update_register() { break; case 0x02: PKTLEN = value; + use_pktlen = 1; break; case 0x03: PKTCTRL1 = value; @@ -321,17 +348,23 @@ void cmd_update_register() { case 0x1F: FSCAL0 = value; break; - case 0x20: + case 0x24: + TEST1 = value; + break; + case 0x25: + TEST0 = value; + break; + case 0x2D: PA_TABLE1 = value; break; - case 0x21: + case 0x2E: PA_TABLE0 = value; break; default: rval = 2; } serial_tx_byte(rval); - serial_tx_byte(0); + serial_flush(); } void cmd_reset() { @@ -343,6 +376,6 @@ void cmd_led() { uint8_t led; uint8_t mode; led = serial_rx_byte(); - mode = serial_rx_byte(); + mode = serial_rx_byte(); led_set_mode(led, mode);//0, 1, 2 = Off, On, Auto } diff --git a/radio.c b/radio.c index c6d4a40..0b9bfdb 100644 --- a/radio.c +++ b/radio.c @@ -78,11 +78,11 @@ void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { if (MARCSTATE==MARC_STATE_RX) { d_byte = RFD; if (radio_rx_buf_len == 0) { - radio_rx_buf[0] = RSSI; + radio_rx_buf[0] = RSSI; if (radio_rx_buf[0] == 0) { radio_rx_buf[0] = 1; // Prevent RSSI of 0 from triggering end-of-packet } - radio_rx_buf[1] = packet_count; + radio_rx_buf[1] = packet_count; packet_count++; radio_rx_buf_len = 2; } @@ -136,9 +136,9 @@ void rf_isr(void) __interrupt RF_VECTOR { } -void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms) { +void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms, uint8_t len) { uint8_t s_byte; - + radio_tx_buf_len = 0; radio_tx_buf_idx = 0; underflow_count = 0; @@ -155,11 +155,18 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela s_byte = 0; } radio_tx_buf[radio_tx_buf_len++] = s_byte; - if (s_byte == 0) { - break; + if (len == 0) { + // If len == 0, then use 0 terminator to detect end of packet + if (s_byte == 0) { + break; + } + } else { + if (radio_tx_buf_len >= len) { + break; + } } - if (radio_tx_buf_len == 2) { + if (radio_tx_buf_len == 2) { // Turn on radio RFST = RFST_STX; } @@ -173,11 +180,11 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela radio_tx_buf_idx = 0; underflow_count = 0; - // delay + // delay if (delay_ms > 0) { delay(delay_ms); } - + // Turn on radio (interrupts should start again) RFST = RFST_STX; while(MARCSTATE!=MARC_STATE_TX); @@ -208,7 +215,7 @@ void resend_from_tx_buf(uint8_t channel) { while(MARCSTATE!=MARC_STATE_IDLE); } -uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms) { +uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen) { uint8_t read_idx = 0; uint8_t d_byte = 0; @@ -225,11 +232,12 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms) { RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); + led_set_state(1,1); while(1) { // Waiting for isr to put radio bytes into radio_rx_buf if (radio_rx_buf_len > read_idx) { - //led_set_state(0,1); + led_set_state(0,1); if (read_idx == 0 && radio_rx_buf_len > 2 && radio_rx_buf[2] == 0) { rval = ERROR_ZERO_DATA; @@ -238,17 +246,23 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms) { d_byte = radio_rx_buf[read_idx]; serial_tx_byte(d_byte); read_idx++; - if (read_idx > 1 && read_idx == radio_rx_buf_len && d_byte == 0) { - // End of packet. - break; + if (read_idx > 1 && read_idx == radio_rx_buf_len) { + // Check for end of packet + if (use_pktlen && read_idx == PKTLEN) { + break; + } + if (!use_pktlen && d_byte == 0) { + break; + } } } - if (timeout_ms > 0 && timerCounter > timeout_ms && radio_rx_buf_len == 0) { + if (timeout_ms > 0 && timerCounter > timeout_ms) { rval = ERROR_RX_TIMEOUT; + led_set_state(1,0); break; } - + #ifndef TI_DONGLE #else #endif @@ -262,7 +276,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms) { } } RFST = RFST_SIDLE; - //led_set_state(0,0); + led_set_state(0,0); + led_set_state(1,0); return rval; } - diff --git a/radio.h b/radio.h index a1a6fbd..08f93c3 100644 --- a/radio.h +++ b/radio.h @@ -7,9 +7,9 @@ void configure_radio(); // 0 = timed out // 1 = got packet // 2 = rx interrupted by serial -uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms); +uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen); -void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms); +void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms, uint8_t len); // Used for retry void resend_from_tx_buf(uint8_t channel); diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 77fc1a2..6303828 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -4,7 +4,7 @@ #include "serial.h" #include "radio.h" -#define SPI_BUF_LEN 220 +#define SPI_BUF_LEN 220 volatile uint8_t __xdata spi_input_buf[SPI_BUF_LEN]; volatile uint8_t input_size = 0; @@ -30,13 +30,13 @@ volatile uint8_t slave_send_size = 0; /*************************************************************************** - * - * SPI encoding: + * + * SPI encoding: * * Master sends a 0x99 byte, followed by number of bytes that will be sent. * Before second byte xfer, slave loads up buffer with number of bytes - * available. - * + * available. + * */ @@ -170,7 +170,7 @@ uint8_t serial_rx_byte() { serial_data_available = 0; } return s_data; -} +} uint16_t serial_rx_word() { return (serial_rx_byte() << 8) + serial_rx_byte(); @@ -190,9 +190,6 @@ void serial_tx_byte(uint8_t tx_byte) { } } spi_output_buf[output_head_idx] = tx_byte; - if (tx_byte == 0) { - ready_to_send = 1; - } output_head_idx++; if (output_head_idx >= SPI_BUF_LEN) { output_head_idx = 0; @@ -200,12 +197,14 @@ void serial_tx_byte(uint8_t tx_byte) { output_size++; } +void serial_flush() { + ready_to_send = 1; +} + void serial_tx_str(const char *str) { while(*str != 0) { serial_tx_byte(*str); str++; } - serial_tx_byte(0); + serial_flush(); } - - diff --git a/spi1_alt2/serial.h b/spi1_alt2/serial.h index 2b20f2b..e0dd19a 100644 --- a/spi1_alt2/serial.h +++ b/spi1_alt2/serial.h @@ -8,6 +8,7 @@ extern volatile uint8_t serial_data_available; void configure_serial(); void serial_tx_byte(uint8_t); void serial_tx_str(const char *str); +void serial_flush(); uint8_t serial_rx_byte(); uint32_t serial_rx_long(); diff --git a/tools/serial_rf_spy.py b/tools/serial_rf_spy.py index 4e4b975..0d23722 100755 --- a/tools/serial_rf_spy.py +++ b/tools/serial_rf_spy.py @@ -9,10 +9,11 @@ class SerialRfSpy: CMD_GET_STATE = 1 CMD_GET_VERSION = 2 CMD_GET_PACKET = 3 - CMD_SEND_PACKET = 4 + CMD_OLD_SEND_PACKET = 4 CMD_SEND_AND_LISTEN = 5 CMD_UPDATE_REGISTER = 6 CMD_RESET = 7 + CMD_SEND_PACKET = 8 def __init__(self, serial_port, rtscts=None): if not rtscts: @@ -24,15 +25,15 @@ def __init__(self, serial_port, rtscts=None): self.ser = serial.Serial(serial_port, 19200, rtscts=rtscts, timeout=1) self.buf = bytearray() - def do_command(self, command, param=""): + def do_command(self, command, param=""): self.send_command(command, param) return self.get_response() - def send_command(self, command, param=""): + def send_command(self, command, param=""): cmd_str = chr(command) + param self.ser.write(cmd_str) - def get_response(self, timeout=0): + def get_response(self, timeout=0): start = time.time() while 1: bytesToRead = self.ser.inWaiting() @@ -46,10 +47,10 @@ def get_response(self, timeout=0): if (timeout > 0) and (start + timeout < time.time()): return bytearray() time.sleep(0.005) - + def sync(self): while 1: - self.send_command(self.CMD_GET_STATE) + self.send_command(self.CMD_GET_STATE) data = self.get_response(1) if data == "OK": print "RileyLink " + data @@ -57,7 +58,7 @@ def sync(self): print "retry", len(data), str(data).encode('hex'), "(Do you need to run 'export RFSPY_RTSCTS=0' first?)" while 1: - self.send_command(self.CMD_GET_VERSION) + self.send_command(self.CMD_GET_VERSION) data = self.get_response(1) if len(data) >= 3: print "Version: " + data From db07bbdf9591b8fc5182de3e2976a247e47241e0 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 7 Oct 2017 16:20:39 -0700 Subject: [PATCH 02/45] Add flushes where needed --- commands.c | 4 ++-- radio.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/commands.c b/commands.c index 6291f1c..14e29d9 100644 --- a/commands.c +++ b/commands.c @@ -52,8 +52,8 @@ void cmd_get_packet() { result = get_packet_and_write_to_serial(channel, timeout_ms, use_pktlen); if (result != 0) { serial_tx_byte(result); - serial_flush(); } + serial_flush(); } void cmd_get_state() { @@ -119,8 +119,8 @@ void cmd_send_and_listen() { if (result != 0) { // Error, and no retries left serial_tx_byte(result); - serial_flush(); } + serial_flush(); } void cmd_read_register() { diff --git a/radio.c b/radio.c index 0b9bfdb..df85423 100644 --- a/radio.c +++ b/radio.c @@ -249,6 +249,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin if (read_idx > 1 && read_idx == radio_rx_buf_len) { // Check for end of packet if (use_pktlen && read_idx == PKTLEN) { + led_set_state(0,0); break; } if (!use_pktlen && d_byte == 0) { @@ -276,7 +277,6 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin } } RFST = RFST_SIDLE; - led_set_state(0,0); led_set_state(1,0); return rval; } From 828f654edf1f438de6a75b3eb3689636f73e984a Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 7 Oct 2017 19:05:25 -0700 Subject: [PATCH 03/45] Use spi input len to determine outgoing packet size --- commands.c | 23 ++++++----------------- spi1_alt2/serial.c | 4 ++++ spi1_alt2/serial.h | 1 + 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/commands.c b/commands.c index 14e29d9..e7ecc2f 100644 --- a/commands.c +++ b/commands.c @@ -18,13 +18,12 @@ CommandHandler handlers[] = { /* 1 */ cmd_get_state, /* 2 */ cmd_get_version, /* 3 */ cmd_get_packet, - /* 4 */ cmd_old_send_packet, + /* 4 */ cmd_send_packet, /* 5 */ cmd_send_and_listen, /* 6 */ cmd_update_register, /* 7 */ cmd_reset, /* 8 */ cmd_led, - /* 9 */ cmd_read_register, - /* 10 */ cmd_send_packet + /* 9 */ cmd_read_register }; void do_cmd(uint8_t cmd) { @@ -64,18 +63,6 @@ void cmd_get_version() { serial_tx_str("subg_rfspy 2.0"); } -// Deprecated. Relied on 0 byte to end packet -void cmd_old_send_packet() { - uint8_t channel; - uint8_t repeat_count; - uint8_t delay_ms; - channel = serial_rx_byte(); - repeat_count = serial_rx_byte(); - delay_ms = serial_rx_byte(); - send_packet_from_serial(channel, repeat_count, delay_ms, 0); - serial_flush(); -} - void cmd_send_packet() { uint8_t channel; uint8_t repeat_count; @@ -84,7 +71,7 @@ void cmd_send_packet() { channel = serial_rx_byte(); repeat_count = serial_rx_byte(); delay_ms = serial_rx_byte(); - len = serial_rx_byte(); + len = serial_rx_avail(); send_packet_from_serial(channel, repeat_count, delay_ms, len); serial_tx_byte(0); serial_flush(); @@ -99,6 +86,7 @@ void cmd_send_and_listen() { uint32_t timeout_ms; uint8_t retry_count; uint8_t result; + uint8_t len; send_channel = serial_rx_byte(); repeat_count = serial_rx_byte(); @@ -106,8 +94,9 @@ void cmd_send_and_listen() { listen_channel = serial_rx_byte(); timeout_ms = serial_rx_long(); retry_count = serial_rx_byte(); + len = serial_rx_avail(); - send_packet_from_serial(send_channel, repeat_count, delay_ms, 0); + send_packet_from_serial(send_channel, repeat_count, delay_ms, len); result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); while (result == ERROR_RX_TIMEOUT && retry_count > 0) { diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 6303828..3ec237a 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -157,6 +157,10 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { } } +uint8_t serial_rx_avail() { + return input_size; +} + uint8_t serial_rx_byte() { uint8_t s_data; while(!SERIAL_DATA_AVAILABLE); diff --git a/spi1_alt2/serial.h b/spi1_alt2/serial.h index e0dd19a..06876a0 100644 --- a/spi1_alt2/serial.h +++ b/spi1_alt2/serial.h @@ -11,5 +11,6 @@ void serial_tx_str(const char *str); void serial_flush(); uint8_t serial_rx_byte(); uint32_t serial_rx_long(); +uint8_t serial_rx_avail(); #endif From f81437bbe5fc687a10e47192381b7cfdbb6cd343 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 8 Oct 2017 21:06:49 -0700 Subject: [PATCH 04/45] Block flush until packet sent over spi --- spi1_alt2/serial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 3ec237a..b670588 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -203,6 +203,7 @@ void serial_tx_byte(uint8_t tx_byte) { void serial_flush() { ready_to_send = 1; + while(output_size); } void serial_tx_str(const char *str) { From eb0be186d94b11a6171a4de7b70dfca7f5958308 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 8 Oct 2017 21:07:18 -0700 Subject: [PATCH 05/45] Add compiler error to alert about unsupported serial setups --- uart0_alt1/serial.h | 3 +++ uart1_alt2/serial.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/uart0_alt1/serial.h b/uart0_alt1/serial.h index 388485a..46a4f21 100644 --- a/uart0_alt1/serial.h +++ b/uart0_alt1/serial.h @@ -1,6 +1,9 @@ #ifndef SERIAL_H #define SERIAL_H +// Needs to be updated with some kind of framing, to support packets with 0's in them +#error "This serial configuration no longer supported." + #define SERIAL_DATA_AVAILABLE URX0IF void configure_serial(); diff --git a/uart1_alt2/serial.h b/uart1_alt2/serial.h index 2b20f2b..b53338a 100644 --- a/uart1_alt2/serial.h +++ b/uart1_alt2/serial.h @@ -1,6 +1,9 @@ #ifndef SERIAL_H #define SERIAL_H +// Needs to be updated with some kind of framing, to support packets with 0's in them +#error "This serial configuration no longer supported." + #define SERIAL_DATA_AVAILABLE serial_data_available extern volatile uint8_t serial_data_available; From f7dea055ec34aa9d062c44435376e4520e408ac5 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 8 Oct 2017 21:08:39 -0700 Subject: [PATCH 06/45] Comment out led debugging --- radio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/radio.c b/radio.c index df85423..0640e5b 100644 --- a/radio.c +++ b/radio.c @@ -232,12 +232,12 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); - led_set_state(1,1); + //led_set_state(1,1); while(1) { // Waiting for isr to put radio bytes into radio_rx_buf if (radio_rx_buf_len > read_idx) { - led_set_state(0,1); + //led_set_state(0,1); if (read_idx == 0 && radio_rx_buf_len > 2 && radio_rx_buf[2] == 0) { rval = ERROR_ZERO_DATA; @@ -249,7 +249,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin if (read_idx > 1 && read_idx == radio_rx_buf_len) { // Check for end of packet if (use_pktlen && read_idx == PKTLEN) { - led_set_state(0,0); + //led_set_state(0,0); break; } if (!use_pktlen && d_byte == 0) { @@ -260,7 +260,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin if (timeout_ms > 0 && timerCounter > timeout_ms) { rval = ERROR_RX_TIMEOUT; - led_set_state(1,0); + //led_set_state(1,0); break; } @@ -277,6 +277,6 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin } } RFST = RFST_SIDLE; - led_set_state(1,0); + //led_set_state(1,0); return rval; } From 1f00d2229476d5a6e064ab443367df3c0d38ebe8 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 21 Oct 2017 04:55:44 -0700 Subject: [PATCH 07/45] temporarily change pktlen to length of actual packet during send --- commands.h | 2 +- radio.c | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/commands.h b/commands.h index 27bf649..902297b 100644 --- a/commands.h +++ b/commands.h @@ -9,6 +9,6 @@ void get_command(); // This is set when a command is received while processing a long running // command, like get_packet -extern uint8_t interrupting_cmd; +extern uint8_t interrupting_cmd; #endif diff --git a/radio.c b/radio.c index 0640e5b..5891893 100644 --- a/radio.c +++ b/radio.c @@ -138,6 +138,10 @@ void rf_isr(void) __interrupt RF_VECTOR { void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms, uint8_t len) { uint8_t s_byte; + uint8_t pktlen_save; + + pktlen_save = PKTLEN; + PKTLEN = len; radio_tx_buf_len = 0; radio_tx_buf_idx = 0; @@ -193,10 +197,15 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela while(MARCSTATE!=MARC_STATE_IDLE); repeat_count--; } + PKTLEN = pktlen_save; //led_set_state(1,0); } void resend_from_tx_buf(uint8_t channel) { + uint8_t pktlen_save; + + pktlen_save = PKTLEN; + PKTLEN = radio_tx_buf_len; RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); @@ -213,6 +222,8 @@ void resend_from_tx_buf(uint8_t channel) { // wait for sending to finish while(MARCSTATE!=MARC_STATE_IDLE); + + PKTLEN = pktlen_save; } uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen) { From 1598fd217983bf06a93de13ced508d8e2f59ce06 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 21 Oct 2017 05:50:44 -0700 Subject: [PATCH 08/45] Move register get/set code to hardware.c --- commands.c | 232 ++------------------------------------------------ hardware.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++- hardware.h | 4 +- 3 files changed, 250 insertions(+), 228 deletions(-) diff --git a/commands.c b/commands.c index e7ecc2f..39852e4 100644 --- a/commands.c +++ b/commands.c @@ -116,118 +116,7 @@ void cmd_read_register() { uint8_t addr; uint8_t value; addr = serial_rx_byte(); - switch(addr) { - case 0x00: - value = SYNC1; - break; - case 0x01: - value = SYNC0; - break; - case 0x02: - value = PKTLEN; - break; - case 0x03: - value = PKTCTRL1; - break; - case 0x04: - value = PKTCTRL0; - break; - case 0x05: - value = ADDR; - break; - case 0x06: - value = CHANNR; - break; - case 0x07: - value = FSCTRL1; - break; - case 0x08: - value = FSCTRL0; - break; - case 0x09: - value = FREQ2; - break; - case 0x0A: - value = FREQ1; - break; - case 0x0B: - value = FREQ0; - break; - case 0x0C: - value = MDMCFG4; - break; - case 0x0D: - value = MDMCFG3; - break; - case 0x0E: - value = MDMCFG2; - break; - case 0x0F: - value = MDMCFG1; - break; - case 0x10: - value = MDMCFG0; - break; - case 0x11: - value = DEVIATN; - break; - case 0x12: - value = MCSM2; - break; - case 0x13: - value = MCSM1; - break; - case 0x14: - value = MCSM0; - break; - case 0x15: - value = FOCCFG; - break; - case 0x16: - value = BSCFG; - break; - case 0x17: - value = AGCCTRL2; - break; - case 0x18: - value = AGCCTRL1; - break; - case 0x19: - value = AGCCTRL0; - break; - case 0x1A: - value = FREND1; - break; - case 0x1B: - value = FREND0; - break; - case 0x1C: - value = FSCAL3; - break; - case 0x1D: - value = FSCAL2; - break; - case 0x1E: - value = FSCAL1; - break; - case 0x1F: - value = FSCAL0; - break; - case 0x24: - value = TEST1; - break; - case 0x25: - value = TEST0; - break; - case 0x2D: - value = PA_TABLE1; - break; - case 0x2E: - value = PA_TABLE0; - break; - default: - value = 0x5A; - } + value = get_register(addr); serial_tx_byte(value); serial_flush(); } @@ -238,120 +127,13 @@ void cmd_update_register() { uint8_t rval; addr = serial_rx_byte(); value = serial_rx_byte(); - rval = 1; - switch(addr) { - case 0x00: - SYNC1 = value; - break; - case 0x01: - SYNC0 = value; - break; - case 0x02: - PKTLEN = value; - use_pktlen = 1; - break; - case 0x03: - PKTCTRL1 = value; - break; - case 0x04: - PKTCTRL0 = value; - break; - case 0x05: - ADDR = value; - break; - case 0x06: - CHANNR = value; - break; - case 0x07: - FSCTRL1 = value; - break; - case 0x08: - FSCTRL0 = value; - break; - case 0x09: - FREQ2 = value; - break; - case 0x0A: - FREQ1 = value; - break; - case 0x0B: - FREQ0 = value; - break; - case 0x0C: - MDMCFG4 = value; - break; - case 0x0D: - MDMCFG3 = value; - break; - case 0x0E: - MDMCFG2 = value; - break; - case 0x0F: - MDMCFG1 = value; - break; - case 0x10: - MDMCFG0 = value; - break; - case 0x11: - DEVIATN = value; - break; - case 0x12: - MCSM2 = value; - break; - case 0x13: - MCSM1 = value; - break; - case 0x14: - MCSM0 = value; - break; - case 0x15: - FOCCFG = value; - break; - case 0x16: - BSCFG = value; - break; - case 0x17: - AGCCTRL2 = value; - break; - case 0x18: - AGCCTRL1= value; - break; - case 0x19: - AGCCTRL0 = value; - break; - case 0x1A: - FREND1 = value; - break; - case 0x1B: - FREND0 = value; - break; - case 0x1C: - FSCAL3 = value; - break; - case 0x1D: - FSCAL2 = value; - break; - case 0x1E: - FSCAL1 = value; - break; - case 0x1F: - FSCAL0 = value; - break; - case 0x24: - TEST1 = value; - break; - case 0x25: - TEST0 = value; - break; - case 0x2D: - PA_TABLE1 = value; - break; - case 0x2E: - PA_TABLE0 = value; - break; - default: - rval = 2; + rval = set_register(addr, value); + + // If pktlen is modified, then we set use_pktlen + if (addr == 0x02) { + use_pktlen = 1; } + serial_tx_byte(rval); serial_flush(); } diff --git a/hardware.c b/hardware.c index 65abd50..fd80268 100644 --- a/hardware.c +++ b/hardware.c @@ -42,5 +42,243 @@ void led_set_state(uint8_t led, uint8_t command) BLUE_LED = command; } } - } -} \ No newline at end of file + } +} + +uint8_t get_register(uint8_t addr) { + uint8_t value; + addr = serial_rx_byte(); + switch(addr) { + case 0x00: + value = SYNC1; + break; + case 0x01: + value = SYNC0; + break; + case 0x02: + value = PKTLEN; + break; + case 0x03: + value = PKTCTRL1; + break; + case 0x04: + value = PKTCTRL0; + break; + case 0x05: + value = ADDR; + break; + case 0x06: + value = CHANNR; + break; + case 0x07: + value = FSCTRL1; + break; + case 0x08: + value = FSCTRL0; + break; + case 0x09: + value = FREQ2; + break; + case 0x0A: + value = FREQ1; + break; + case 0x0B: + value = FREQ0; + break; + case 0x0C: + value = MDMCFG4; + break; + case 0x0D: + value = MDMCFG3; + break; + case 0x0E: + value = MDMCFG2; + break; + case 0x0F: + value = MDMCFG1; + break; + case 0x10: + value = MDMCFG0; + break; + case 0x11: + value = DEVIATN; + break; + case 0x12: + value = MCSM2; + break; + case 0x13: + value = MCSM1; + break; + case 0x14: + value = MCSM0; + break; + case 0x15: + value = FOCCFG; + break; + case 0x16: + value = BSCFG; + break; + case 0x17: + value = AGCCTRL2; + break; + case 0x18: + value = AGCCTRL1; + break; + case 0x19: + value = AGCCTRL0; + break; + case 0x1A: + value = FREND1; + break; + case 0x1B: + value = FREND0; + break; + case 0x1C: + value = FSCAL3; + break; + case 0x1D: + value = FSCAL2; + break; + case 0x1E: + value = FSCAL1; + break; + case 0x1F: + value = FSCAL0; + break; + case 0x24: + value = TEST1; + break; + case 0x25: + value = TEST0; + break; + case 0x2D: + value = PA_TABLE1; + break; + case 0x2E: + value = PA_TABLE0; + break; + default: + value = 0x5A; + } + return value; +} + +uint8_t set_register(uint8_t addr, uint8_t value) { + uint8_t rval; + addr = serial_rx_byte(); + value = serial_rx_byte(); + rval = 1; + switch(addr) { + case 0x00: + SYNC1 = value; + break; + case 0x01: + SYNC0 = value; + break; + case 0x02: + PKTLEN = value; + break; + case 0x03: + PKTCTRL1 = value; + break; + case 0x04: + PKTCTRL0 = value; + break; + case 0x05: + ADDR = value; + break; + case 0x06: + CHANNR = value; + break; + case 0x07: + FSCTRL1 = value; + break; + case 0x08: + FSCTRL0 = value; + break; + case 0x09: + FREQ2 = value; + break; + case 0x0A: + FREQ1 = value; + break; + case 0x0B: + FREQ0 = value; + break; + case 0x0C: + MDMCFG4 = value; + break; + case 0x0D: + MDMCFG3 = value; + break; + case 0x0E: + MDMCFG2 = value; + break; + case 0x0F: + MDMCFG1 = value; + break; + case 0x10: + MDMCFG0 = value; + break; + case 0x11: + DEVIATN = value; + break; + case 0x12: + MCSM2 = value; + break; + case 0x13: + MCSM1 = value; + break; + case 0x14: + MCSM0 = value; + break; + case 0x15: + FOCCFG = value; + break; + case 0x16: + BSCFG = value; + break; + case 0x17: + AGCCTRL2 = value; + break; + case 0x18: + AGCCTRL1= value; + break; + case 0x19: + AGCCTRL0 = value; + break; + case 0x1A: + FREND1 = value; + break; + case 0x1B: + FREND0 = value; + break; + case 0x1C: + FSCAL3 = value; + break; + case 0x1D: + FSCAL2 = value; + break; + case 0x1E: + FSCAL1 = value; + break; + case 0x1F: + FSCAL0 = value; + break; + case 0x24: + TEST1 = value; + break; + case 0x25: + TEST0 = value; + break; + case 0x2D: + PA_TABLE1 = value; + break; + case 0x2E: + PA_TABLE0 = value; + break; + default: + rval = 2; + } + return rval; +} diff --git a/hardware.h b/hardware.h index a33521e..939c680 100644 --- a/hardware.h +++ b/hardware.h @@ -61,7 +61,9 @@ #endif void led_set_mode(uint8_t led, uint8_t new_mode); - void led_set_state(uint8_t led, uint8_t command); +uint8_t get_register(uint8_t addr); +uint8_t set_register(uint8_t addr, uint8_t value); + #endif From 5c7c2f4188f88a6434b1db70ab89d18f444fd6cc Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 21 Oct 2017 06:07:36 -0700 Subject: [PATCH 09/45] Comment out builds that are no longer supported --- build-all.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/build-all.sh b/build-all.sh index 791cc94..9d231d7 100755 --- a/build-all.sh +++ b/build-all.sh @@ -7,32 +7,32 @@ set -e # Rileylink and similar ############################################################################ # USA: -make -f Makefile.uart1_alt2 -make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL +#make -f Makefile.uart1_alt2 +#make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL make -f Makefile.spi1_alt2 # Worldwide: -make -f Makefile.uart1_alt2 RADIO_LOCALE=WW -make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW +#make -f Makefile.uart1_alt2 RADIO_LOCALE=WW +#make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW make -f Makefile.spi1_alt2 RADIO_LOCALE=WW ############################################################################ # ERF stick ############################################################################ # USA: -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL +#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF +#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL # Worldwide: -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF RADIO_LOCALE=WW -make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW +#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF RADIO_LOCALE=WW +#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW ############################################################################ # TI stick ############################################################################ # USA: -make -f Makefile.usb_ep0 -make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER +#make -f Makefile.usb_ep0 +#make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER # Worldwide: -make -f Makefile.usb_ep0 RADIO_LOCALE=WW -make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER +#make -f Makefile.usb_ep0 RADIO_LOCALE=WW +#make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER exit 0 From d207e3da571e3d3afbea9097d91d38376ce43653 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 21 Oct 2017 08:34:15 -0700 Subject: [PATCH 10/45] Add register settings specifically for rx or tx --- commands.c | 39 ++++++++++++++++++++++++++++++++++++++- commands.h | 6 ++++++ hardware.c | 28 ++++++++++++++++++++++++---- hardware.h | 19 +++++++++++++++++++ radio.c | 4 ++++ 5 files changed, 91 insertions(+), 5 deletions(-) diff --git a/commands.c b/commands.c index 39852e4..354a495 100644 --- a/commands.c +++ b/commands.c @@ -1,5 +1,6 @@ #include +#include #include "hardware.h" #include "serial.h" #include "radio.h" @@ -23,7 +24,8 @@ CommandHandler handlers[] = { /* 6 */ cmd_update_register, /* 7 */ cmd_reset, /* 8 */ cmd_led, - /* 9 */ cmd_read_register + /* 9 */ cmd_read_register, + /* 10 */ cmd_set_mode_registers, }; void do_cmd(uint8_t cmd) { @@ -42,6 +44,41 @@ void get_command() { } } +void cmd_set_mode_registers() { + uint8_t register_mode; + uint8_t count; + uint8_t addr; + uint8_t value; + int i; + mode_registers *registers; + + register_mode = serial_rx_byte(); + count = serial_rx_avail() / 2; + + switch(register_mode) { + case RegisterModeTx: + registers = &tx_registers; + break; + case RegisterModeRx: + registers = &rx_registers; + break; + default: + registers = 0x0; + break; + } + + if (registers != NULL) { + mode_registers_clear(registers); + } + for (i=0; icount = 0; +} + +void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value) { + if (mode->count < MAX_MODE_REGISTERS - 1) { + mode->registers[mode->count].addr = addr; + mode->registers[mode->count].value = value; + mode->count++; + } +} + +void mode_registers_enact(mode_registers const *mode) { + int i; + for (i=0; icount; i++) { + set_register(mode->registers[i].addr, mode->registers[i].value); + } +} diff --git a/hardware.h b/hardware.h index 939c680..244a44e 100644 --- a/hardware.h +++ b/hardware.h @@ -60,10 +60,29 @@ #define SYSTEM_CLOCK_MHZ 26 #endif +#define MAX_MODE_REGISTERS 8 + +typedef struct register_setting { + uint8_t addr; + uint8_t value; +} register_setting; + +typedef struct mode_registers { + uint8_t count; + register_setting registers[MAX_MODE_REGISTERS]; +} mode_registers; + void led_set_mode(uint8_t led, uint8_t new_mode); void led_set_state(uint8_t led, uint8_t command); + uint8_t get_register(uint8_t addr); uint8_t set_register(uint8_t addr, uint8_t value); +void mode_registers_clear(mode_registers *mode); +void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value); +void mode_registers_enact(mode_registers const *mode); + +extern mode_registers tx_registers; +extern mode_registers rx_registers; #endif diff --git a/radio.c b/radio.c index 5891893..58280bf 100644 --- a/radio.c +++ b/radio.c @@ -140,6 +140,8 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela uint8_t s_byte; uint8_t pktlen_save; + mode_registers_enact(&tx_registers); + pktlen_save = PKTLEN; PKTLEN = len; @@ -234,6 +236,8 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin reset_timer(); + mode_registers_enact(&rx_registers); + RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); From e51b74ba8abb8f16a7ae5ef78f1c980269b032d6 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 21 Oct 2017 13:56:51 -0700 Subject: [PATCH 11/45] Add response for set mode registers command --- commands.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commands.c b/commands.c index 354a495..ab9a0fe 100644 --- a/commands.c +++ b/commands.c @@ -77,6 +77,8 @@ void cmd_set_mode_registers() { mode_registers_add(registers, addr, value); } } + serial_tx_byte(0); + serial_flush(); } void cmd_get_packet() { From ad07efd4e735165ed438bbebbabf1b3bc9682534 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 4 Nov 2017 23:32:28 -0700 Subject: [PATCH 12/45] Adding encoding layer --- commands.c | 10 ++++ common.mk | 2 +- encoding.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++ encoding.h | 58 +++++++++++++++++++++++ radio.c | 20 ++++++-- radio.h | 5 ++ 6 files changed, 224 insertions(+), 6 deletions(-) create mode 100644 encoding.c create mode 100644 encoding.h diff --git a/commands.c b/commands.c index ab9a0fe..ab6af35 100644 --- a/commands.c +++ b/commands.c @@ -5,6 +5,7 @@ #include "serial.h" #include "radio.h" #include "commands.h" +#include "encoding.h" uint8_t interrupting_cmd = 0; @@ -26,6 +27,7 @@ CommandHandler handlers[] = { /* 8 */ cmd_led, /* 9 */ cmd_read_register, /* 10 */ cmd_set_mode_registers, + /* 11 */ cmd_set_sw_encoding, }; void do_cmd(uint8_t cmd) { @@ -44,6 +46,14 @@ void get_command() { } } +void cmd_set_sw_encoding() { + EncodingType encoding_type; + + encoding_type = serial_rx_byte(); + set_encoding_type(encoding_type); +} + + void cmd_set_mode_registers() { uint8_t register_mode; uint8_t count; diff --git a/common.mk b/common.mk index 4f6ec33..829508c 100755 --- a/common.mk +++ b/common.mk @@ -17,7 +17,7 @@ CFLAGS=-I. -I${SERIAL_TYPE} --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOAR default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex -common_modules = radio.rel main.rel timer.rel \ +common_modules = radio.rel main.rel timer.rel encoding.rel \ commands.rel delay.rel hardware.rel clean: diff --git a/encoding.c b/encoding.c new file mode 100644 index 0000000..e189f6b --- /dev/null +++ b/encoding.c @@ -0,0 +1,135 @@ + +#include "encoding.h" + +// Manchester encoder funcs + +static void manchester_init_encoder(EncoderState *state) { + state->manchester.offset = 2; +} + +static void manchester_add_raw_byte(EncoderState *state, uint8_t raw) { + uint16_t acc = 0; + int i; + for (i=0; i<8; i++) { + acc = (acc << 2) + 1 + (raw >> 7); + raw = raw << 1; + } + state->manchester.output[0] = acc >> 8; + state->manchester.output[1] = acc & 0xff; + state->manchester.offset = 0; +} + +static uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) { + if (state->manchester.offset > 1) { + return 0; + } + *encoded = state->manchester.output[state->manchester.offset]; + state->manchester.offset++; + return 1; +} + +// Manchester decoder funcs + +static void manchester_init_decoder(DecoderState *state) { + state->manchester.output = 0; + state->manchester.bits_avail = 0; +} + +static uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) { + uint8_t acc = 0; + int i; + for (i=0; i<8; i++) { + acc = (acc << 1); + switch(raw & 0b11) { + case 0b00: + case 0b11: + return 1; // Encoding error + case 0b10: + acc++; + } + } + state->manchester.output = (state->manchester.output << 4) + acc; + state->manchester.bits_avail += 4; + return 0; +} + +static uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) { + if (state->manchester.bits_avail < 8) { + return 0; + } + *decoded = state->manchester.output; + state->manchester.bits_avail = 0; + return 1; +} + +// Passthrough encoder +static void passthrough_init_encoder(EncoderState *state) { + state->passthrough.count = 0; +} + +static void passthrough_add_raw_byte(EncoderState *state, uint8_t raw) { + state->passthrough.count = 1; + state->passthrough.data = raw; +} + +static uint8_t passthrough_next_encoded_byte(EncoderState *state, uint8_t *encoded) { + if (state->passthrough.count < 1) { + return 0; + } + *encoded = state->passthrough.data; + state->passthrough.count--; + return 1; +} + +// passthrough decoder funcs +static void passthrough_init_decoder(DecoderState *state) { + state->passthrough.count = 0; +} + +static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t raw) { + state->passthrough.data = raw; + state->passthrough.count = 1; + return 0; +} + +static uint8_t passthrough_next_decoded_byte(DecoderState *state, uint8_t *decoded) { + if (state->passthrough.count < 1) { + return 0; + } + *decoded = state->passthrough.data; + state->passthrough.count = 0; + return 1; +} + + +// Init Encoder +void init_encoder(EncodingType encodingType, Encoder *encoder, EncoderState *state) { + switch (encodingType) { + case EncodingTypeNone: + encoder->add_raw_byte = passthrough_add_raw_byte; + encoder->next_encoded_byte = passthrough_next_encoded_byte; + passthrough_init_encoder(state); + break; + case EncodingTypeManchester: + encoder->add_raw_byte = manchester_add_raw_byte; + encoder->next_encoded_byte = manchester_next_encoded_byte; + manchester_init_encoder(state); + break; + } +} + +// Init Decoder +void init_decoder(EncodingType encodingType, Decoder *decoder, DecoderState *state) { + switch (encodingType) { + case EncodingTypeNone: + decoder->add_encoded_byte = passthrough_add_encoded_byte; + decoder->next_decoded_byte = passthrough_next_decoded_byte; + passthrough_init_decoder(state); + break; + case EncodingTypeManchester: + decoder->add_encoded_byte = manchester_add_encoded_byte; + decoder->next_decoded_byte = manchester_next_decoded_byte; + manchester_init_decoder(state); + break; + } +} diff --git a/encoding.h b/encoding.h new file mode 100644 index 0000000..03a90be --- /dev/null +++ b/encoding.h @@ -0,0 +1,58 @@ +#ifndef ENCODING_H +#define ENCODING_H + +#include + +typedef enum { + EncodingTypeNone = 0x0, + EncodingTypeManchester = 0x1 + //EncodingType4b6b = 0x02 +} EncodingType; + +typedef struct { + union { + struct { + uint8_t output[2]; + uint8_t offset; + } manchester; + struct { + uint8_t data; + uint8_t count; + } passthrough; + }; +} EncoderState; + +typedef struct { + union { + struct { + uint8_t output; + uint8_t bits_avail; + } manchester; + struct { + uint8_t data; + uint8_t count; + } passthrough; + }; +} DecoderState; + +typedef struct { + // Adds a byte to be encoded + void (*add_raw_byte)(EncoderState *state, uint8_t raw); + // encoded will be set to next available encoded byte. + // Return value is 0 if no more bytes are available. + uint8_t (*next_encoded_byte)(EncoderState *state, uint8_t *encoded); +} Encoder; + +typedef struct { + // Adds a byte for decoding. The return value will be 1 if the byte + // contains encoding errors, otherwise it will be 0. + uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t raw); + // decoded will be set to the next available decoded byte. + // Return value is 0 if no more bytes are available. + uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded); +} Decoder; + +void init_encoder(EncodingType encodingType, Encoder *encoder, EncoderState *state); +void init_decoder(EncodingType encodingType, Decoder *decoder, DecoderState *state); + +#endif // ENCODING_H diff --git a/radio.c b/radio.c index 58280bf..a1c7b60 100644 --- a/radio.c +++ b/radio.c @@ -5,6 +5,7 @@ #include "commands.h" #include "delay.h" #include "timer.h" +#include "encoding.h" #define MAX_PACKET_LEN 192 volatile uint8_t __xdata radio_tx_buf[MAX_PACKET_LEN]; @@ -15,6 +16,8 @@ volatile uint8_t radio_rx_buf_len = 0; volatile uint8_t packet_count = 1; volatile uint8_t underflow_count = 0; +EncodingType encoding_type; + void configure_radio() { /* RF settings SoC: CC1110 */ @@ -73,10 +76,17 @@ void configure_radio() RFTXRXIE = 1; } +// Set software based encoding +void set_encoding_type(EncodingType new_type) { + encoding_type = new_type; +} + + void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { uint8_t d_byte; if (MARCSTATE==MARC_STATE_RX) { - d_byte = RFD; + //d_byte = RFD; + d_byte = LQI; if (radio_rx_buf_len == 0) { radio_rx_buf[0] = RSSI; if (radio_rx_buf[0] == 0) { @@ -95,10 +105,10 @@ void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { } else { // Overflow } - if (d_byte == 0) { - RFST = RFST_SIDLE; - while(MARCSTATE!=MARC_STATE_IDLE); - } + // if (d_byte == 0) { + // RFST = RFST_SIDLE; + // while(MARCSTATE!=MARC_STATE_IDLE); + // } } else if (MARCSTATE==MARC_STATE_TX) { if (radio_tx_buf_len > radio_tx_buf_idx) { diff --git a/radio.h b/radio.h index 08f93c3..95cea21 100644 --- a/radio.h +++ b/radio.h @@ -1,6 +1,8 @@ #ifndef RADIO_H #define RADIO_H +#include "encoding.h" + void configure_radio(); // Return values: @@ -14,4 +16,7 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela // Used for retry void resend_from_tx_buf(uint8_t channel); +// Set software based encoding +void set_encoding_type(EncodingType encoding_type); + #endif From e198e770cb4749515299226df7669b95a2f3a74f Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 5 Nov 2017 16:12:38 -0800 Subject: [PATCH 13/45] Add use of decoder/encoder to send/rcv functions --- encoding.c | 24 +++++++++++------------ encoding.h | 12 ++++++------ hardware.c | 4 ++-- hardware.h | 4 ++-- radio.c | 57 ++++++++++++++++++++++++++++++++---------------------- 5 files changed, 56 insertions(+), 45 deletions(-) diff --git a/encoding.c b/encoding.c index e189f6b..58a804a 100644 --- a/encoding.c +++ b/encoding.c @@ -7,7 +7,7 @@ static void manchester_init_encoder(EncoderState *state) { state->manchester.offset = 2; } -static void manchester_add_raw_byte(EncoderState *state, uint8_t raw) { +static void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { uint16_t acc = 0; int i; for (i=0; i<8; i++) { @@ -19,7 +19,7 @@ static void manchester_add_raw_byte(EncoderState *state, uint8_t raw) { state->manchester.offset = 0; } -static uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) { +static uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { if (state->manchester.offset > 1) { return 0; } @@ -35,7 +35,7 @@ static void manchester_init_decoder(DecoderState *state) { state->manchester.bits_avail = 0; } -static uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) { +static uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant { uint8_t acc = 0; int i; for (i=0; i<8; i++) { @@ -53,7 +53,7 @@ static uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) { return 0; } -static uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) { +static uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { if (state->manchester.bits_avail < 8) { return 0; } @@ -67,12 +67,12 @@ static void passthrough_init_encoder(EncoderState *state) { state->passthrough.count = 0; } -static void passthrough_add_raw_byte(EncoderState *state, uint8_t raw) { +static void passthrough_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { state->passthrough.count = 1; state->passthrough.data = raw; } -static uint8_t passthrough_next_encoded_byte(EncoderState *state, uint8_t *encoded) { +static uint8_t passthrough_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { if (state->passthrough.count < 1) { return 0; } @@ -86,13 +86,13 @@ static void passthrough_init_decoder(DecoderState *state) { state->passthrough.count = 0; } -static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t raw) { +static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant { state->passthrough.data = raw; state->passthrough.count = 1; return 0; } -static uint8_t passthrough_next_decoded_byte(DecoderState *state, uint8_t *decoded) { +static uint8_t passthrough_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { if (state->passthrough.count < 1) { return 0; } @@ -103,8 +103,8 @@ static uint8_t passthrough_next_decoded_byte(DecoderState *state, uint8_t *decod // Init Encoder -void init_encoder(EncodingType encodingType, Encoder *encoder, EncoderState *state) { - switch (encodingType) { +void init_encoder(EncodingType encoding_type, Encoder *encoder, EncoderState *state) { + switch (encoding_type) { case EncodingTypeNone: encoder->add_raw_byte = passthrough_add_raw_byte; encoder->next_encoded_byte = passthrough_next_encoded_byte; @@ -119,8 +119,8 @@ void init_encoder(EncodingType encodingType, Encoder *encoder, EncoderState *sta } // Init Decoder -void init_decoder(EncodingType encodingType, Decoder *decoder, DecoderState *state) { - switch (encodingType) { +void init_decoder(EncodingType encoding_type, Decoder *decoder, DecoderState *state) { + switch (encoding_type) { case EncodingTypeNone: decoder->add_encoded_byte = passthrough_add_encoded_byte; decoder->next_decoded_byte = passthrough_next_decoded_byte; diff --git a/encoding.h b/encoding.h index 03a90be..d2fd044 100644 --- a/encoding.h +++ b/encoding.h @@ -37,22 +37,22 @@ typedef struct { typedef struct { // Adds a byte to be encoded - void (*add_raw_byte)(EncoderState *state, uint8_t raw); + void (*add_raw_byte)(EncoderState *state, uint8_t raw) __reentrant; // encoded will be set to next available encoded byte. // Return value is 0 if no more bytes are available. - uint8_t (*next_encoded_byte)(EncoderState *state, uint8_t *encoded); + uint8_t (*next_encoded_byte)(EncoderState *state, uint8_t *encoded) __reentrant; } Encoder; typedef struct { // Adds a byte for decoding. The return value will be 1 if the byte // contains encoding errors, otherwise it will be 0. - uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t raw); + uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t raw) __reentrant; // decoded will be set to the next available decoded byte. // Return value is 0 if no more bytes are available. - uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded); + uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded) __reentrant; } Decoder; -void init_encoder(EncodingType encodingType, Encoder *encoder, EncoderState *state); -void init_decoder(EncodingType encodingType, Decoder *decoder, DecoderState *state); +void init_encoder(EncodingType encoding_type, Encoder *encoder, EncoderState *state); +void init_decoder(EncodingType encoding_type, Decoder *decoder, DecoderState *state); #endif // ENCODING_H diff --git a/hardware.c b/hardware.c index daa15c1..0081220 100644 --- a/hardware.c +++ b/hardware.c @@ -11,8 +11,8 @@ static uint8_t green_mode = 2; static uint8_t blue_mode = 2; -mode_registers tx_registers; -mode_registers rx_registers; +mode_registers __xdata tx_registers; +mode_registers __xdata rx_registers; void led_set_mode(uint8_t led, uint8_t new_mode) { diff --git a/hardware.h b/hardware.h index 244a44e..dbb6d7a 100644 --- a/hardware.h +++ b/hardware.h @@ -82,7 +82,7 @@ void mode_registers_clear(mode_registers *mode); void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value); void mode_registers_enact(mode_registers const *mode); -extern mode_registers tx_registers; -extern mode_registers rx_registers; +extern mode_registers __xdata tx_registers; +extern mode_registers __xdata rx_registers; #endif diff --git a/radio.c b/radio.c index a1c7b60..aeef950 100644 --- a/radio.c +++ b/radio.c @@ -7,16 +7,16 @@ #include "timer.h" #include "encoding.h" -#define MAX_PACKET_LEN 192 +#define MAX_PACKET_LEN 512 volatile uint8_t __xdata radio_tx_buf[MAX_PACKET_LEN]; -volatile uint8_t radio_tx_buf_len = 0; -volatile uint8_t radio_tx_buf_idx = 0; +volatile uint16_t radio_tx_buf_len = 0; +volatile uint16_t radio_tx_buf_idx = 0; volatile uint8_t __xdata radio_rx_buf[MAX_PACKET_LEN]; -volatile uint8_t radio_rx_buf_len = 0; +volatile uint16_t radio_rx_buf_len = 0; volatile uint8_t packet_count = 1; volatile uint8_t underflow_count = 0; -EncodingType encoding_type; +EncodingType encoding_type = EncodingTypeNone; void configure_radio() { @@ -150,6 +150,11 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela uint8_t s_byte; uint8_t pktlen_save; + Encoder encoder; + EncoderState encoder_state; + + init_encoder(encoding_type, &encoder, &encoder_state); + mode_registers_enact(&tx_registers); pktlen_save = PKTLEN; @@ -165,25 +170,19 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela CHANNR = channel; //led_set_state(1,1); - while (1) { + while (len > 0) { s_byte = serial_rx_byte(); - if (radio_tx_buf_len == (MAX_PACKET_LEN - 1)) { - s_byte = 0; - } - radio_tx_buf[radio_tx_buf_len++] = s_byte; - if (len == 0) { - // If len == 0, then use 0 terminator to detect end of packet - if (s_byte == 0) { - break; - } - } else { - if (radio_tx_buf_len >= len) { + len--; + encoder.add_raw_byte(&encoder_state, s_byte); + while (encoder.next_encoded_byte(&encoder_state, &s_byte)) { + radio_tx_buf[radio_tx_buf_len++] = s_byte; + if (radio_tx_buf_len >= MAX_PACKET_LEN) { break; } } if (radio_tx_buf_len == 2) { - // Turn on radio + // Turn on radio after 2 bytes RFST = RFST_STX; } } @@ -243,11 +242,17 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin uint8_t read_idx = 0; uint8_t d_byte = 0; uint8_t rval = 0; + uint8_t encoding_error = 0; + + Decoder __xdata decoder; + DecoderState __xdata decoder_state; reset_timer(); mode_registers_enact(&rx_registers); + init_decoder(encoding_type, &decoder, &decoder_state); + RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); @@ -264,13 +269,19 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin if (radio_rx_buf_len > read_idx) { //led_set_state(0,1); - if (read_idx == 0 && radio_rx_buf_len > 2 && radio_rx_buf[2] == 0) { - rval = ERROR_ZERO_DATA; - break; - } d_byte = radio_rx_buf[read_idx]; - serial_tx_byte(d_byte); read_idx++; + + encoding_error = decoder.add_encoded_byte(&decoder_state, d_byte); + + while (decoder.next_decoded_byte(&decoder_state, &d_byte)) { + serial_tx_byte(d_byte); + } + + if (encoding_error) { + break; + } + if (read_idx > 1 && read_idx == radio_rx_buf_len) { // Check for end of packet if (use_pktlen && read_idx == PKTLEN) { From ffa5becc265e0cbe5a72d534ad0f8e836addeda4 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 5 Nov 2017 19:23:06 -0800 Subject: [PATCH 14/45] Do not decode first two bytes from radio buffer --- commands.h | 1 - radio.c | 14 ++++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/commands.h b/commands.h index d52367e..6d0b522 100644 --- a/commands.h +++ b/commands.h @@ -3,7 +3,6 @@ #define ERROR_RX_TIMEOUT 0xaa #define ERROR_CMD_INTERRUPTED 0xbb -#define ERROR_ZERO_DATA 0xcc enum RegisterMode { RegisterModeTx = 0x01, diff --git a/radio.c b/radio.c index aeef950..a042f09 100644 --- a/radio.c +++ b/radio.c @@ -272,10 +272,15 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin d_byte = radio_rx_buf[read_idx]; read_idx++; - encoding_error = decoder.add_encoded_byte(&decoder_state, d_byte); - - while (decoder.next_decoded_byte(&decoder_state, &d_byte)) { + // First two bytes are rssi and packet # + if (read_idx < 3) { serial_tx_byte(d_byte); + } else { + encoding_error = decoder.add_encoded_byte(&decoder_state, d_byte); + + while (decoder.next_decoded_byte(&decoder_state, &d_byte)) { + serial_tx_byte(d_byte); + } } if (encoding_error) { @@ -300,9 +305,6 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin break; } - #ifndef TI_DONGLE - #else - #endif // Also going to watch serial in case the client wants to interrupt rx if (SERIAL_DATA_AVAILABLE) { // Received a byte from uart while waiting for radio packet From 5f3bb408af9ccfb225d297a4666126a43959c315 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 5 Nov 2017 19:28:17 -0800 Subject: [PATCH 15/45] revert debugging hack --- radio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/radio.c b/radio.c index a042f09..8fd3e97 100644 --- a/radio.c +++ b/radio.c @@ -85,8 +85,7 @@ void set_encoding_type(EncodingType new_type) { void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { uint8_t d_byte; if (MARCSTATE==MARC_STATE_RX) { - //d_byte = RFD; - d_byte = LQI; + d_byte = RFD; if (radio_rx_buf_len == 0) { radio_rx_buf[0] = RSSI; if (radio_rx_buf[0] == 0) { From 46cb94be484d2329a638a23700e8dd7bd0d88a10 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 5 Nov 2017 20:06:10 -0800 Subject: [PATCH 16/45] Split manchester encoding out into separate module --- common.mk | 2 +- encoding.c | 62 +----------------------------------------------------- encoding.h | 11 +++------- 3 files changed, 5 insertions(+), 70 deletions(-) diff --git a/common.mk b/common.mk index 829508c..43799be 100755 --- a/common.mk +++ b/common.mk @@ -17,7 +17,7 @@ CFLAGS=-I. -I${SERIAL_TYPE} --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOAR default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex -common_modules = radio.rel main.rel timer.rel encoding.rel \ +common_modules = radio.rel main.rel timer.rel encoding.rel manchester.rel \ commands.rel delay.rel hardware.rel clean: diff --git a/encoding.c b/encoding.c index 58a804a..8d19941 100644 --- a/encoding.c +++ b/encoding.c @@ -1,66 +1,6 @@ #include "encoding.h" - -// Manchester encoder funcs - -static void manchester_init_encoder(EncoderState *state) { - state->manchester.offset = 2; -} - -static void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { - uint16_t acc = 0; - int i; - for (i=0; i<8; i++) { - acc = (acc << 2) + 1 + (raw >> 7); - raw = raw << 1; - } - state->manchester.output[0] = acc >> 8; - state->manchester.output[1] = acc & 0xff; - state->manchester.offset = 0; -} - -static uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { - if (state->manchester.offset > 1) { - return 0; - } - *encoded = state->manchester.output[state->manchester.offset]; - state->manchester.offset++; - return 1; -} - -// Manchester decoder funcs - -static void manchester_init_decoder(DecoderState *state) { - state->manchester.output = 0; - state->manchester.bits_avail = 0; -} - -static uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant { - uint8_t acc = 0; - int i; - for (i=0; i<8; i++) { - acc = (acc << 1); - switch(raw & 0b11) { - case 0b00: - case 0b11: - return 1; // Encoding error - case 0b10: - acc++; - } - } - state->manchester.output = (state->manchester.output << 4) + acc; - state->manchester.bits_avail += 4; - return 0; -} - -static uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { - if (state->manchester.bits_avail < 8) { - return 0; - } - *decoded = state->manchester.output; - state->manchester.bits_avail = 0; - return 1; -} +#include "manchester.h" // Passthrough encoder static void passthrough_init_encoder(EncoderState *state) { diff --git a/encoding.h b/encoding.h index d2fd044..62df35f 100644 --- a/encoding.h +++ b/encoding.h @@ -2,6 +2,7 @@ #define ENCODING_H #include +#include "manchester_state.h" typedef enum { EncodingTypeNone = 0x0, @@ -11,10 +12,7 @@ typedef enum { typedef struct { union { - struct { - uint8_t output[2]; - uint8_t offset; - } manchester; + struct ManchesterEncoderState manchester; struct { uint8_t data; uint8_t count; @@ -24,10 +22,7 @@ typedef struct { typedef struct { union { - struct { - uint8_t output; - uint8_t bits_avail; - } manchester; + struct ManchesterDecoderState manchester; struct { uint8_t data; uint8_t count; From cd42eb8c1133d80473695f361d82faa5a7b6322c Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 5 Nov 2017 20:12:42 -0800 Subject: [PATCH 17/45] Split manchester encoding out into separate module --- manchester.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ manchester.h | 13 ++++++++++ manchester_state.h | 14 +++++++++++ 3 files changed, 88 insertions(+) create mode 100644 manchester.c create mode 100644 manchester.h create mode 100644 manchester_state.h diff --git a/manchester.c b/manchester.c new file mode 100644 index 0000000..1018eb7 --- /dev/null +++ b/manchester.c @@ -0,0 +1,61 @@ + +#include "manchester.h" + +void manchester_init_encoder(EncoderState *state) { + state->manchester.offset = 2; +} + +void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { + uint16_t acc = 0; + int i; + for (i=0; i<8; i++) { + acc = (acc << 2) + 1 + (raw >> 7); + raw = raw << 1; + } + state->manchester.output[0] = acc >> 8; + state->manchester.output[1] = acc & 0xff; + state->manchester.offset = 0; +} + +uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { + if (state->manchester.offset > 1) { + return 0; + } + *encoded = state->manchester.output[state->manchester.offset]; + state->manchester.offset++; + return 1; +} + +// Manchester decoder funcs + +void manchester_init_decoder(DecoderState *state) { + state->manchester.output = 0; + state->manchester.bits_avail = 0; +} + +uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant { + uint8_t acc = 0; + int i; + for (i=0; i<8; i++) { + acc = (acc << 1); + switch(raw & 0b11) { + case 0b00: + case 0b11: + return 1; // Encoding error + case 0b10: + acc++; + } + } + state->manchester.output = (state->manchester.output << 4) + acc; + state->manchester.bits_avail += 4; + return 0; +} + +uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { + if (state->manchester.bits_avail < 8) { + return 0; + } + *decoded = state->manchester.output; + state->manchester.bits_avail = 0; + return 1; +} diff --git a/manchester.h b/manchester.h new file mode 100644 index 0000000..4afc90e --- /dev/null +++ b/manchester.h @@ -0,0 +1,13 @@ +#ifndef MANCHESTER_H +#define MANCHESTER_H + +#include "encoding.h" + +void manchester_init_encoder(EncoderState *state); +void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; +uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant; +void manchester_init_decoder(DecoderState *state); +uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant; +uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; + +#endif //MANCHESTER_H diff --git a/manchester_state.h b/manchester_state.h new file mode 100644 index 0000000..2856924 --- /dev/null +++ b/manchester_state.h @@ -0,0 +1,14 @@ +#ifndef MANCHESTER_STATE_H +#define MANCHESTER_STATE_H + +struct ManchesterEncoderState { + uint8_t output[2]; + uint8_t offset; +}; + +struct ManchesterDecoderState { + uint8_t output; + uint8_t bits_avail; +}; + +#endif // MANCHESTER_STATE_H From 0def453fad05d5bcc0d80e20f425777472f2391f Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 5 Nov 2017 22:03:53 -0800 Subject: [PATCH 18/45] Adding 4b6b encoding --- common.mk | 2 +- encoding.c | 15 ++++++++++-- encoding.h | 13 ++++++---- fourbsixb.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ fourbsixb.h | 13 ++++++++++ fourbsixb_state.h | 16 ++++++++++++ manchester.c | 4 +-- manchester.h | 2 +- 8 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 fourbsixb.c create mode 100644 fourbsixb.h create mode 100644 fourbsixb_state.h diff --git a/common.mk b/common.mk index 43799be..21f3cc1 100755 --- a/common.mk +++ b/common.mk @@ -18,7 +18,7 @@ CFLAGS=-I. -I${SERIAL_TYPE} --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOAR default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex common_modules = radio.rel main.rel timer.rel encoding.rel manchester.rel \ - commands.rel delay.rel hardware.rel + fourbsixb.rel commands.rel delay.rel hardware.rel clean: rm -rf output/${TARGET_BUILD} diff --git a/encoding.c b/encoding.c index 8d19941..aaa7f96 100644 --- a/encoding.c +++ b/encoding.c @@ -1,6 +1,7 @@ #include "encoding.h" #include "manchester.h" +#include "fourbsixb.h" // Passthrough encoder static void passthrough_init_encoder(EncoderState *state) { @@ -26,8 +27,8 @@ static void passthrough_init_decoder(DecoderState *state) { state->passthrough.count = 0; } -static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant { - state->passthrough.data = raw; +static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { + state->passthrough.data = encoded; state->passthrough.count = 1; return 0; } @@ -55,6 +56,11 @@ void init_encoder(EncodingType encoding_type, Encoder *encoder, EncoderState *st encoder->next_encoded_byte = manchester_next_encoded_byte; manchester_init_encoder(state); break; + case EncodingTypeFourbSixb: + encoder->add_raw_byte = fourbsixb_add_raw_byte; + encoder->next_encoded_byte = fourbsixb_next_encoded_byte; + fourbsixb_init_encoder(state); + break; } } @@ -71,5 +77,10 @@ void init_decoder(EncodingType encoding_type, Decoder *decoder, DecoderState *st decoder->next_decoded_byte = manchester_next_decoded_byte; manchester_init_decoder(state); break; + case EncodingTypeFourbSixb: + decoder->add_encoded_byte = fourbsixb_add_encoded_byte; + decoder->next_decoded_byte = fourbsixb_next_decoded_byte; + fourbsixb_init_decoder(state); + break; } } diff --git a/encoding.h b/encoding.h index 62df35f..66bc776 100644 --- a/encoding.h +++ b/encoding.h @@ -3,30 +3,33 @@ #include #include "manchester_state.h" +#include "fourbsixb_state.h" typedef enum { EncodingTypeNone = 0x0, - EncodingTypeManchester = 0x1 - //EncodingType4b6b = 0x02 + EncodingTypeManchester = 0x1, + EncodingTypeFourbSixb = 0x02 } EncodingType; typedef struct { union { - struct ManchesterEncoderState manchester; struct { uint8_t data; uint8_t count; } passthrough; + struct ManchesterEncoderState manchester; + struct FourbSixbEncoderState fourbsixb; }; } EncoderState; typedef struct { union { - struct ManchesterDecoderState manchester; struct { uint8_t data; uint8_t count; } passthrough; + struct ManchesterDecoderState manchester; + struct FourbSixbDecoderState fourbsixb; }; } DecoderState; @@ -41,7 +44,7 @@ typedef struct { typedef struct { // Adds a byte for decoding. The return value will be 1 if the byte // contains encoding errors, otherwise it will be 0. - uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t raw) __reentrant; + uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t encoded) __reentrant; // decoded will be set to the next available decoded byte. // Return value is 0 if no more bytes are available. uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded) __reentrant; diff --git a/fourbsixb.c b/fourbsixb.c new file mode 100644 index 0000000..1497578 --- /dev/null +++ b/fourbsixb.c @@ -0,0 +1,62 @@ + +#include "fourbsixb.h" + +//fileprivate let codesRev:Dictionary = [21: 0, 49: 1, 50: 2, 35: 3, 52: 4, 37: 5, 38: 6, 22: 7, 26: 8, 25: 9, 42: 10, 11: 11, 44: 12, 13: 13, 14: 14, 28: 15] + +static uint8_t __xdata codes[] = {21,49,50,35,52,37,38,22,26,25,42,11,44,13,14,28}; + +void fourbsixb_init_encoder(EncoderState *state) { + state->fourbsixb.acc = 0; + state->fourbsixb.bits_avail = 0; +} + +void fourbsixb_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { + uint16_t new_bits = (codes[raw >> 4] << 6) | codes[raw & 0xf]; + state->fourbsixb.acc = (state->fourbsixb.acc << 12) | new_bits; + state->fourbsixb.bits_avail += 12; +} + +uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { + if (state->fourbsixb.bits_avail < 8) { + return 0; + } + *encoded = state->fourbsixb.acc >> (8-state->fourbsixb.bits_avail); + state->fourbsixb.bits_avail -= 8; + return 1; +} + +void fourbsixb_init_decoder(DecoderState *state) { + state->fourbsixb.input_acc = 0; + state->fourbsixb.input_bits_avail = 0; + state->fourbsixb.output_acc = 0; + state->fourbsixb.output_bits_avail = 0; +} + +uint8_t fourbsixb_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { + uint8_t code, i; + state->fourbsixb.input_acc = (state->fourbsixb.input_acc << 8) | encoded; + state->fourbsixb.input_bits_avail += 8; + while (state->fourbsixb.input_bits_avail >= 6) { + code = (state->fourbsixb.input_acc >> (state->fourbsixb.input_bits_avail - 6)) & 0b111111; + for (i=0; i<16; i++) { + if (codes[i] == code) { + break; + } + } + if (i == 16) { + return 1; // Encoding error + } + state->fourbsixb.output_acc = (state->fourbsixb.output_acc << 4) | i; + state->fourbsixb.output_bits_avail += 4; + } + return 0; +} + +uint8_t fourbsixb_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant { + if (state->fourbsixb.output_bits_avail < 8) { + return 0; + } + *decoded = state->fourbsixb.output_acc >> (state->fourbsixb.output_bits_avail - 8); + state->fourbsixb.output_bits_avail -= 8; + return 1; +} diff --git a/fourbsixb.h b/fourbsixb.h new file mode 100644 index 0000000..4af2c0b --- /dev/null +++ b/fourbsixb.h @@ -0,0 +1,13 @@ +#ifndef FOURBSIXB_H +#define FOURBSIXB_H + +#include "encoding.h" + +void fourbsixb_init_encoder(EncoderState *state); +void fourbsixb_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; +uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant; +void fourbsixb_init_decoder(DecoderState *state); +uint8_t fourbsixb_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant; +uint8_t fourbsixb_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; + +#endif //FOURBSIXB_H diff --git a/fourbsixb_state.h b/fourbsixb_state.h new file mode 100644 index 0000000..1efe401 --- /dev/null +++ b/fourbsixb_state.h @@ -0,0 +1,16 @@ +#ifndef FOURBSIXB_STATE_H +#define FOURBSIXB_STATE_H + +struct FourbSixbEncoderState { + uint16_t acc; + uint8_t bits_avail; +}; + +struct FourbSixbDecoderState { + uint16_t input_acc; + uint8_t input_bits_avail; + uint16_t output_acc; + uint8_t output_bits_avail; +}; + +#endif // FOURBSIXB_STATE_H diff --git a/manchester.c b/manchester.c index 1018eb7..a6c7658 100644 --- a/manchester.c +++ b/manchester.c @@ -33,12 +33,12 @@ void manchester_init_decoder(DecoderState *state) { state->manchester.bits_avail = 0; } -uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant { +uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { uint8_t acc = 0; int i; for (i=0; i<8; i++) { acc = (acc << 1); - switch(raw & 0b11) { + switch(encoded & 0b11) { case 0b00: case 0b11: return 1; // Encoding error diff --git a/manchester.h b/manchester.h index 4afc90e..cef61b8 100644 --- a/manchester.h +++ b/manchester.h @@ -7,7 +7,7 @@ void manchester_init_encoder(EncoderState *state); void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant; void manchester_init_decoder(DecoderState *state); -uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant; +uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant; uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; #endif //MANCHESTER_H From d517586f399e81839004b46fdc481a944a1fffa0 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 12 Nov 2017 19:53:47 -0800 Subject: [PATCH 19/45] Decrement input bits on 4b6b --- fourbsixb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fourbsixb.c b/fourbsixb.c index 1497578..bf9300e 100644 --- a/fourbsixb.c +++ b/fourbsixb.c @@ -38,6 +38,7 @@ uint8_t fourbsixb_add_encoded_byte(DecoderState *state, uint8_t encoded) __reent state->fourbsixb.input_bits_avail += 8; while (state->fourbsixb.input_bits_avail >= 6) { code = (state->fourbsixb.input_acc >> (state->fourbsixb.input_bits_avail - 6)) & 0b111111; + state->fourbsixb.input_bits_avail -= 6; for (i=0; i<16; i++) { if (codes[i] == code) { break; From 112f206941127c7f71af73632d042c59679f70fd Mon Sep 17 00:00:00 2001 From: Eric Cooper Date: Fri, 8 Dec 2017 14:56:16 -0500 Subject: [PATCH 20/45] Introduce USES_USB instead of assuming TI dongle is always USB-attached With the debug connector, it's possible to attach a TI dongle using UART or SPI, so don't make TI_DONGLE imply USB. --- Makefile.srfstick | 36 ------------------------------------ Makefile.usb_ep0 | 2 +- build-all.sh | 2 ++ main.c | 2 +- 4 files changed, 4 insertions(+), 38 deletions(-) delete mode 100755 Makefile.srfstick diff --git a/Makefile.srfstick b/Makefile.srfstick deleted file mode 100755 index 43ff864..0000000 --- a/Makefile.srfstick +++ /dev/null @@ -1,36 +0,0 @@ -SERIAL_TYPE := usb_ep0 -SERIAL_PARAMS := -DSRF_STICK - -BOARD_TYPE := SRF_STICK -BOARD_PARAMS := -DSRF_STICK - -TARGET_DEVICE := CC1111 - - -SRC = \ - hal.c \ - usb.c \ - usb_descriptors.c - -ADB=$(SRC:.c=.adb) -ASM=$(SRC:.c=.asm) -LNK=$(SRC:.c=.lnk) -LST=$(SRC:.c=.lst) -REL=$(SRC:.c=.rel) -RST=$(SRC:.c=.rst) -SYM=$(SRC:.c=.sym) - -PCDB=$(PROGS:.hex=.cdb) -PLNK=$(PROGS:.hex=.lnk) -PMAP=$(PROGS:.hex=.map) -PMEM=$(PROGS:.hex=.mem) -PAOM=$(PROGS:.hex=) -include common.mk - -hal.rel: ${SERIAL_TYPE}/hal.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< - -usb_descriptors.rel: ${SERIAL_TYPE}/usb_descriptors.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< -usb.rel: ${SERIAL_TYPE}/usb.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< diff --git a/Makefile.usb_ep0 b/Makefile.usb_ep0 index 83ebeac..744d671 100755 --- a/Makefile.usb_ep0 +++ b/Makefile.usb_ep0 @@ -1,5 +1,5 @@ SERIAL_TYPE := usb_ep0 -SERIAL_PARAMS := -DTI_DONGLE +SERIAL_PARAMS := -DUSES_USB BOARD_TYPE := TI_DONGLE BOARD_PARAMS := -DTI_DONGLE diff --git a/build-all.sh b/build-all.sh index 791cc94..664f7aa 100755 --- a/build-all.sh +++ b/build-all.sh @@ -30,9 +30,11 @@ make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL ############################################################################ # USA: make -f Makefile.usb_ep0 +make -f Makefile.spi1_alt2 BOARD_TYPE=TI_DONGLE make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER # Worldwide: make -f Makefile.usb_ep0 RADIO_LOCALE=WW +make -f Makefile.spi1_alt2 BOARD_TYPE=TI_DONGLE RADIO_LOCALE=WW make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER exit 0 diff --git a/main.c b/main.c index ef3cd6d..bf2447a 100644 --- a/main.c +++ b/main.c @@ -21,7 +21,7 @@ void rx1_isr(void) __interrupt URX1_VECTOR; void tx1_isr(void) __interrupt UTX1_VECTOR; #endif -#if TI_DONGLE || SRF_STICK +#if USES_USB void usb_isr() __interrupt 6; #endif From f5084c13189891734bd5f65e80a995aab9542c79 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 30 Dec 2017 06:48:45 -0800 Subject: [PATCH 21/45] Flash size is 32KB, not 64KB --- common.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.mk b/common.mk index 21f3cc1..b82686d 100755 --- a/common.mk +++ b/common.mk @@ -12,7 +12,7 @@ TARGET_BUILD := ${SERIAL_TYPE}_${BOARD_TYPE}_${RADIO_LOCALE}_${CODE_LOC_NAME} CC=sdcc -LDFLAGS=--xram-loc 0xf000 --xram-size 0x1000 --code-loc ${CODE_LOC} +LDFLAGS=--xram-loc 0xf000 --xram-size 0x1000 --code-loc ${CODE_LOC} --code-size 0x8000 CFLAGS=-I. -I${SERIAL_TYPE} --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex From de0b70c580d6932ddc2f8b44485a1813d02f4c0f Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 7 Jan 2018 11:50:42 -0600 Subject: [PATCH 22/45] Updating docs with new commands --- Readme.md | 263 +++++++++++++--------------------------------------- protocol.md | 181 ++++++++++++++++++++++++++++++++++++ serial.md | 85 +++++++++++++++++ 3 files changed, 331 insertions(+), 198 deletions(-) create mode 100644 protocol.md create mode 100644 serial.md diff --git a/Readme.md b/Readme.md index ea72e6c..a29d71e 100644 --- a/Readme.md +++ b/Readme.md @@ -1,4 +1,6 @@ -# Pre-Requisites for Building subg_rfspy +# subg_rfspy + +## Pre-Requisites for Building subg_rfspy [sdcc] (http://sdcc.sourceforge.net/) package is required for this build. @@ -13,347 +15,212 @@ It's also possible to build it under Windows. The best way to do this is to: # Building -You'll need to select a build type, like `uart0_alt1`. The examples below use this value, but you'll want to use the correct one for your hardware and use case. See below for different hardware types and use cases. +You'll need to select a build type, like `spi1_alt2`. The examples below use this value, but you'll want to use the correct one for your hardware and use case. See below for different hardware types and use cases. Perform the build. The output file will be stored at output/uart0_alt1_RILEYLINK_US/uart0_alt1_RILEYLINK_US.hex - make -f Makefile.uart0_alt1 + make -f Makefile.spi1_alt2 Perform the install: - make -f Makefile.uart0_alt1 install - + make -f Makefile.spi1_alt2 install + # Radio Frequency Selection This code defaults to building firmware that is tuned to 916.5 Mhz. You can also build a 'WorldWide' firmware. This changes the default frequency to 868 and tweaks a few other settings. - make -f Makefile.uart1_alt2 RADIO_LOCALE=WW + make -f Makefile.spi1_alt2 RADIO_LOCALE=WW # RileyLink -If you are using a RileyLink via the onboard bluetooth module (which should be loaded with ble_rfspy), then you'll want to use `spi1_alt2` as your build type. - -If you are going to manually wire up to the cc1110 on the RileyLink via the debug header, use `uart1_alt2` as your build type, and use the pinout below. - -UART/SPI pins exposed on cc1110 debug header: - - PIN - SPI_alt2 / UART1_alt2 - P1.4 - CT / SSN - P1.5 - RT / SCK - P1.6 - TX / MOSI - P1.7 - RX / MISO - -# cc111x UART1_alt2 connected to the Intel Edison UART_1 - - P1.4 - CT / SSN -> UART_1_RTS (GP129) (pin 63) - P1.5 - RT / SCK -> UART_1_CTS (GP128) (pin 65) - P1.6 - TX / MOSI -> UART_1_RX (GP130) (pin 61) - P1.7 - RX / MISO -> UART_1_TX (GP131) (pin 46) - - -# UART on the WirelessThings ERF stick - -Perform the build. The output file will be stored at output/uart0_alt1_SRF_ERF_US/uart0_alt1_SRF_ERF_US.hex - - make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF - -Installation is bit more complicated, as you will need to attach connectors to -the SRF pins manually (you can't use the wiring points on the board itself). - -This [XRF blog post](http://paulswasteland.blogspot.co.uk/2015/01/building-your-own-firmware-for-ciseco.html) -maps cc-debugger connector to the XRF pin names. - -However, the XRF pins are not the same as the SRF pin locations. For that, you -can use the [SRF OpenMicros Data](http://openmicros.org/index.php/articles/88-ciseco-product-documentation/259-srf-technical-data) -to map things to the correct ERF locations. +If you are using a [RileyLink](https://github.com/ps2/rileylink) via the onboard bluetooth module (which should be loaded with ble_rfspy), then you'll want to use `spi1_alt2` as your build type. -- SRF Pin 5 - DDATA (also known as DD) -- SRF Pin 6 - DCLOCK (also known as DC) -- SRF Pin 9 - 3.3v (also known as VDD) -- SRF Pin 10 - Ground (also known as GND) -- SRF Pin 15 - Reset +# Protocol -To install the firmware: +See [protocol.md](protocol.md) - make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF install - -# USB on support on TI cc1111 USB stick (CC1111EMK868-915) AKA "Don's Dongle" - - make -f Makefile.usb_ep0 install - -Shows up as a serial device on linux. - - -# CCTL Support - -If you have [CCTL](https://github.com/oskarpearson/cctl/tree/24mhz_clock_and_erf_stick_hack) -on your device stick, you can re-program the firmware without requiring the cc-debugger. -To compile firmware that's compatible with CCTL, set the CODE_LOC and CODE_LOC_NAME parameters: - - make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL - -Then, compile the cctl writer program: - - cd /where/you/want/the/cctl/code/to/live - git clone https://github.com/oskarpearson/cctl.git - cd cctl - git checkout 24mhz_clock_and_erf_stick_hack - cd cctl-prog - make clean all - -Then connect the ERF stick over the serial port (normally /dev/ttyUSB0), and write the firmware: - - ./cctl-prog -d /dev/ttyUSB0 -f /path/to/subg_rfspy/output/uart0_alt1_SRF_ERF_WW_CCTL/uart0_alt1_SRF_ERF_WW_CCTL.hex - Waiting 10s for bootloader, reset board now - -Reset the board by disconnecting the +ve lead, and you should then see: - - ....Bootloader detected - Erasing, programming and verifying page 1 - ... - Erasing page 31 - Programming complete # Addendum -## Command List - -Different commands can be selected by sending the following numbers through the serial interface. +## Serial/Uart Support -### Interrupt: 0 - -Interrupts the current command. - -### Get State: 1 - -Check to make sure serial communications are functioning. Should return "OK" message. - -### Get Version: 2 - -Prints the current version of the software e.g. "subg_rfspy 0.8". - -### Get Packet: 3 - -Gets the latest packet of wireless data and displays it on the serial interface. - -Follow command with the desired channel to receive data from and how long to wait to -receive a packet (in milliseconds). - -### Send Packet: 4 - -Sends a packet of data from the serial interface over the wireless connection. - -Follow command with desired channel to send data over, numbers of times to resend data, the -delay between each resend (in milliseconds). - -### Send and Listen: 5 - -Sends a packet of data from the serial interface over the wireless connection and waits -to receive a packet to display over the serial interface. - -Follow command with desired channel to send data over, numbers of times to resend data, the -delay between each resend (in milliseconds), the desired channel to receive data from, the -delay between each receive retry (in milliseconds), and the number of times to retry -receiving. - -### Update Register: 6 - -Use this command to update one of the major registers with a desired value. See section Major -Registers for a list of available registers and their functions. - -Follow command with the register you want to update, and the value you want to update it to. - -### Reset: 7 - -Use this command to reset the device. - -### LED: 8 - -Use this command to manually control the LEDs on the device. - -Follow this command with the LED you want to configure (0 for green, 1 for blue) and the mode -(0 for off, 1 for on, 2 for auto). - -### Read Register: 9 - -Use this command to read the current value of one of the major registers. See Major Registers section -for a list of available registers and their functions. +Serial support is no longer supported. See [serial.md](serial.md) for +historical information. ## Frequency Channel Selection -Each channel number corresponds to a different specific frequency. Channels start with 916.5 MHz at +Each channel number corresponds to a different specific frequency. Channels start with 916.5 MHz at Channel 0 and end with 934.4 MHz at Channel 255, in steps of about 0.07 MHz. You can select different channels by adjusting the CHANNR.CHAN register. Available channels are governed by the following equation: - f_carrier = (24MHz/(2^16))*(FREQ + CHAN(256 + CHANSPC_M)*2^(CHANSPC_E - 2)) +`f_carrier = (24MHz/(2^16))*(FREQ + CHAN(256 + CHANSPC_M)*2^(CHANSPC_E - 2))` -The base frequency, FREQ, is set by the FREQ2, FREQ1, and FREQ0 registers. The value default value is +The base frequency, FREQ, is set by the FREQ2, FREQ1, and FREQ0 registers. The value default value is 2502768 (0x263070). CHANSPC_M and CHANSPC_E are used to set the channel spacing, and are contained in the registers MDMCFG0 and MDMCFG1 (bits 1:0), respectively. Their default values are 126 (0x7E) and 1. -## Major Registers +## Supported Registers -### SYNC1 (0xDF00) +### SYNC1 (0x00) Sync Word, High Byte. 8 MSB of 16-bit sync word. -### SYNC0 (0xDF01) +### SYNC0 (0x01) Sync Word, Low Byte. 8 LSB of 16-bit sync word. -### PKTLEN (0xDF02) +### PKTLEN (0x02) Packet Length. Indicates the packet length when fixed length packets are enabled. If variable length packets are used, this value indicates the maximum length packets allowed. -### PKTCTRL1 (0xDF03) +### PKTCTRL1 (0x03) Packet Automation Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### PKTCTRL0 (0xDF04) +### PKTCTRL0 (0x04) Packet Automation Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### ADDR (0xDF05) +### ADDR (0x05) Device Address. Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). -### CHANNR (0xDF06) +### CHANNR (0x06) Channel Number. The 8-bit unsigned channel number, which is multiplied by the channel spacing setting and added to the base frequency. -### FSCTRL1 (0xDF07) +### FSCTRL1 (0x07) Frequency Synthesizer Control. -### FSCTRL0 (0xDF08) +### FSCTRL0 (0x08) Frequency Synthesizer Control. Frequency offset added to the base frequency before being used by the FS. -### FREQ2 (0xDF09) +### FREQ2 (0x09) Frequency Control Word, High Byte. -### FREQ1 (0xDF0A) +### FREQ1 (0x0A) Frequency Control Word, Middle Byte. -### FREQ0 (0xDF0B) +### FREQ0 (0x0B) Frequency Control Word, Low Byte. -### MDMCFG4 (0xDF0C) +### MDMCFG4 (0x0C) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG3 (0xDF0D) +### MDMCFG3 (0x0D) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG2 (0xDF0E) +### MDMCFG2 (0x0E) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG1 (0xDF0F) +### MDMCFG1 (0x0F) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MDMCFG0 (0xDF10) +### MDMCFG0 (0x10) Modem Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### DEVIATN (0xDF11) +### DEVIATN (0x11) Modem Deviation Setting. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MCSM2 (0xDF12) +### MCSM2 (0x12) -Main Radio Control State Machine Configuration. Different bit ranges have +Main Radio Control State Machine Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MCSM1 (0xDF13) +### MCSM1 (0x13) -Main Radio Control State Machine Configuration. Different bit ranges have +Main Radio Control State Machine Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### MCSM0 (0xDF14) +### MCSM0 (0x14) -Main Radio Control State Machine Configuration. Different bit ranges have +Main Radio Control State Machine Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FOCCFG (0xDF15) +### FOCCFG (0x15) -Frequency Offset Compensation Configuration. Different bit ranges have +Frequency Offset Compensation Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### BSCFG (0xDF16) +### BSCFG (0x16) -Bit Synchronization Configuration. Different bit ranges have different +Bit Synchronization Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. - -### AGCCTRL2 (0xDF17) + +### AGCCTRL2 (0x17) AGC Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### AGCCTRL1 (0xDF18) +### AGCCTRL1 (0x18) AGC Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### AGCCTRL0 (0xDF19) +### AGCCTRL0 (0x19) AGC Control. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FREND1 (0xDF1A) +### FREND1 (0x1A) -Front End RX Configuration. Different bit ranges have different +Front End RX Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FREND0 (0xDF1B) +### FREND0 (0x1B) -Front End RX Configuration. Different bit ranges have different +Front End RX Configuration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL3 (0xDF1C) +### FSCAL3 (0x1C) -Frequency Synthesizer Calibration. Different bit ranges have +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL2 (0xDF1D) +### FSCAL2 (0x1D) -Frequency Synthesizer Calibration. Different bit ranges have different +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL1 (0xDF1E) +### FSCAL1 (0x1E) -Frequency Synthesizer Calibration. Different bit ranges have different +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. -### FSCAL0 (0xDF1F) +### FSCAL0 (0x1F) -Frequency Synthesizer Calibration. Different bit ranges have different +Frequency Synthesizer Calibration. Different bit ranges have different functions. See CC1110/CC1111 datasheet for more information. - -### PA_TABLE1 (0xDF2D) + +### PA_TABLE1 (0x2D) Power amplifier output power setting 1. -### PA_TABLE0 (0xDF2E) +### PA_TABLE0 (0x2E) Power amplifier output power setting 0. - diff --git a/protocol.md b/protocol.md new file mode 100644 index 0000000..b23d1ed --- /dev/null +++ b/protocol.md @@ -0,0 +1,181 @@ +# Subg_rfspy protocol + + +### SPI data polling + +The spi version of subg_rfspy acts as an spi slave. To start the exchange, a 0x99 byte is transferred from master, and the received value during that exchange can be ignored. The next byte sent is size of the command that will follow; the received byte indicates how much data is available. After that, all the command data and the data to be received is transferred synchronously. + +#### First Exchange: + +| master | slave | +| ------ | ------ | +| 0x99 | Ignore | + + +#### Second Exchange: + +| master | slave | +| --------- | ------------- | +| cmd_len | available_len | + + +#### Data exchange until MAX(cmd_len, available_len): + +| master | slave | +| --------- | ----------- | +| cmd[0] | available[0] | +| cmd[1] | available[1] | +| cmd[2] | available[2] | +| ... | ... | + + + +## Command List + +Different commands can be selected by sending the following numbers through the serial interface. For types larger than uint8_t, data is sent most significant byte first (msb). + +### Interrupt: 0 + +Interrupts the current command. Actually, any new command sent during a radio rx operation will interrupt the firmware, and the 0xbb response will be generated. + +| data | size | Description | +| ------- | -------- | ----------- | +| 0 | uint8_t | Command code | + +Response: CMD_INTERRUPTED (0xbb) + + +### Get State: 1 + +Check to make sure serial communications are functioning. Should return "OK" message. + +| data | size | Description | +| ------- | -------- | ----------- | +| 1 | uint8_t | Command code | + +Response: "OK" + + +### Get Version: 2 + +Prints the current version of the software. + +| data | size | Description | +| ------- | -------- | ----------- | +| 2 | uint8_t | Command code | + +Response: "subg_rfspy 1.0" + + +### Get Packet: 3 + +Gets the latest packet of wireless data and displays it on the serial interface. + +| data | size | Description | +| ------- | -------- | ----------- | +| 3 | uint8_t | Command code | +| channel | uint8_t | Channel to listen on.| +| timeout_ms | uint32_t | Time to wait before giving up in milliseconds.| + +Response: Packet data, or RX_TIMEOUT (0xaa). + +### Send Packet: 4 + +Sends a packet of data from the serial interface over the wireless connection. + +| data | size | Description | +| ------------ | ------- | ----------- | +| 4 | uint8_t | Command code | +| channel | uint8_t | Channel to send on.| +| repeat_count | uint8_t | Number of times to repeat, after the first send. | +| delay_ms | uint8_t | Delay between sending packets, in milliseconds. | + +Response: Packet data, or RX_TIMEOUT (0xaa). + +### Send and Listen: 5 + +Sends a packet of data from the serial interface over the wireless connection and waits +to receive a packet to display over the serial interface. + +| data | size | Description | +| -------------- | ------------- | ----------- | +| 5 | uint8_t | Command code | +| send_channel | uint8_t | Channel to send on.| +| repeat_count | uint8_t | Number of times to repeat, after the first send. | +| delay_ms | uint8_t | Delay between sending packets, in milliseconds. | +| listen_channel | uint8_t | Channel to listen on.| +| timeout_ms | uint32_t | Time to wait before giving up in milliseconds.| +| retry_count | uint8_t | Number of times to retry the send, if nothing is received.| +| packet_data | 0..packet_len | Raw packet data. Length is specified at the framing (spi) layer. | + +### Update Register: 6 + +Use this command to update one of the major registers with a desired value. See section Major Registers for a list of available registers and their functions. + +| data | size | Description | +| ------------ | ------- | ----------- | +| 6 | uint8_t | Command code | +| register | uint8_t | Register to update. | +| value | uint8_t | Value to set register to. | + +Returns 1 on success, 2 on invalid register. + +### Reset: 7 + +Use this command to reset the device. + +| data | size | Description | +| ------------ | ------- | ----------- | +| 7 | uint8_t | Command code | + +No response; client should wait, and then check status after 100ms or so. + +### LED: 8 + +Use this command to manually control the LEDs on the device. + +| data | size | Description | +| ------------ | ------- | ----------- | +| 8 | uint8_t | Command code | +| led_num | uint8_t | LED number (0 = green, 1 = blue) | +| led_mode | uint8_t | LED mode (0 = off, 1 = on, 2 = auto) | + +### Read Register: 9 + +Use this command to read the current value of one of the major registers. See Major Registers section +for a list of available registers and their functions. + +| data | size | Description | +| ------------ | ------- | ----------- | +| 9 | uint8_t | Command code | +| register | uint8_t | Register to read. | + +Returns the value of the register, or 0x5a if an invalid register was specified. + +### Set Mode Registers: 10 + +This command allows you to set specific values for registers during only rx or tx. + +| data | size | Description | +| ------------ | ------- | ----------- | +| 10 | uint8_t | Command code | +| mode | uint8_t | Mode to set registers for (tx = 1, rx = 2) | +| count | uint8_t | Number of registers that will follow | +| register1 | uint8_t | First register to set | +| value1 | uint8_t | Value to set for first register | +| register2 | uint8_t | Second register to set | +| value2 | uint8_t | Value to set for second register | +| ... | ... | ... | + +Returns 0. + +### Set Software Encoding: 11 + +In addition to the native encodings that the cc111x hardware can support, there is support for additional encodings built in at the software/firmware layer. + +_Note_: The manchester support differs from the hardware based manchester support by being able to detect manchester errors and mark the end of packet properly. If using software based manchester support, hardware based manchester should not be turned on (i.e. MDMCFG2.MANCHESTER_EN=0). The bitrate should be set at 2x the decoded packet data rate. + +| data | size | Description | +| ------------- | ------- | ----------- | +| 11 | uint8_t | Command code | +| encoding_type | uint8_t | Encoding type (0:none, 1:manchester, 2:4b6b) diff --git a/serial.md b/serial.md new file mode 100644 index 0000000..9b7130c --- /dev/null +++ b/serial.md @@ -0,0 +1,85 @@ +# Serial support +*Since the change to SPI framing carrying semantic information about the Length +of packets, the serial protocol no longer can be expected to work. It needs to +be updated to support some kind of framing.* + +This information is provide for users of legacy versions of the software. + +UART/SPI pins exposed on cc1110 debug header: + + PIN - SPI_alt2 / UART1_alt2 + P1.4 - CT / SSN + P1.5 - RT / SCK + P1.6 - TX / MOSI + P1.7 - RX / MISO + +# cc111x UART1_alt2 connected to the Intel Edison UART_1 + + P1.4 - CT / SSN -> UART_1_RTS (GP129) (pin 63) + P1.5 - RT / SCK -> UART_1_CTS (GP128) (pin 65) + P1.6 - TX / MOSI -> UART_1_RX (GP130) (pin 61) + P1.7 - RX / MISO -> UART_1_TX (GP131) (pin 46) + + +# UART on the WirelessThings ERF stick + +Perform the build. The output file will be stored at output/uart0_alt1_SRF_ERF_US/uart0_alt1_SRF_ERF_US.hex + + make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF + +Installation is bit more complicated, as you will need to attach connectors to +the SRF pins manually (you can't use the wiring points on the board itself). + +This [XRF blog post](http://paulswasteland.blogspot.co.uk/2015/01/building-your-own-firmware-for-ciseco.html) +maps cc-debugger connector to the XRF pin names. + +However, the XRF pins are not the same as the SRF pin locations. For that, you +can use the [SRF OpenMicros Data](http://openmicros.org/index.php/articles/88-ciseco-product-documentation/259-srf-technical-data) +to map things to the correct ERF locations. + +- SRF Pin 5 - DDATA (also known as DD) +- SRF Pin 6 - DCLOCK (also known as DC) +- SRF Pin 9 - 3.3v (also known as VDD) +- SRF Pin 10 - Ground (also known as GND) +- SRF Pin 15 - Reset + +To install the firmware: + + make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF install + +# USB on support on TI cc1111 USB stick (CC1111EMK868-915) AKA "Don's Dongle" + + make -f Makefile.usb_ep0 install + +Shows up as a serial device on linux. + + +# CCTL Support + +If you have [CCTL](https://github.com/oskarpearson/cctl/tree/24mhz_clock_and_erf_stick_hack) +on your device stick, you can re-program the firmware without requiring the cc-debugger. +To compile firmware that's compatible with CCTL, set the CODE_LOC and CODE_LOC_NAME parameters: + + make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL + +Then, compile the cctl writer program: + + cd /where/you/want/the/cctl/code/to/live + git clone https://github.com/oskarpearson/cctl.git + cd cctl + git checkout 24mhz_clock_and_erf_stick_hack + cd cctl-prog + make clean all + +Then connect the ERF stick over the serial port (normally /dev/ttyUSB0), and write the firmware: + + ./cctl-prog -d /dev/ttyUSB0 -f /path/to/subg_rfspy/output/uart0_alt1_SRF_ERF_WW_CCTL/uart0_alt1_SRF_ERF_WW_CCTL.hex + Waiting 10s for bootloader, reset board now + +Reset the board by disconnecting the +ve lead, and you should then see: + + ....Bootloader detected + Erasing, programming and verifying page 1 + ... + Erasing page 31 + Programming complete From ad018500a1504234aec8ba8009c588678c34777c Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 10 Feb 2018 10:09:45 -0800 Subject: [PATCH 23/45] Preamble changes * Allow custom preamble values * Custom preamble duration * All commands return unified response code * New unknown command response code * Switch to SDCC's medium memory model * delay() is more accurate * flip manchester bits --- commands.c | 52 +++++++-- commands.h | 7 +- common.mk | 7 +- delay.c | 21 ---- delay.h | 6 - encoding.c | 5 +- encoding.h | 10 +- fifo.c | 58 ++++++++++ fifo.h | 31 ++++++ fourbsixb.c | 16 ++- fourbsixb.h | 2 +- hardware.c | 18 ++- hardware.h | 4 + main.c | 7 +- manchester.c | 10 +- manchester.h | 2 +- packet_buffer.c | 62 +++++++++++ packet_buffer.h | 10 ++ radio.c | 261 +++++++++++++++++++++++++++----------------- radio.h | 13 ++- spi1_alt2/serial.c | 81 ++++++++++---- spi1_alt2/serial.h | 1 + timer.c | 13 ++- timer.h | 2 +- uart1_alt2/serial.c | 14 +-- 25 files changed, 504 insertions(+), 209 deletions(-) delete mode 100644 delay.c delete mode 100644 delay.h create mode 100644 fifo.c create mode 100644 fifo.h create mode 100644 packet_buffer.c create mode 100644 packet_buffer.h diff --git a/commands.c b/commands.c index ab6af35..cf7c46c 100644 --- a/commands.c +++ b/commands.c @@ -28,11 +28,18 @@ CommandHandler handlers[] = { /* 9 */ cmd_read_register, /* 10 */ cmd_set_mode_registers, /* 11 */ cmd_set_sw_encoding, + /* 12 */ cmd_set_preamble, }; void do_cmd(uint8_t cmd) { if (cmd > 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { handlers[cmd](); + } else { + while(serial_rx_avail() > 0) { + serial_rx_byte(); + } + serial_tx_byte(RESPONSE_CODE_UNKNOWN_COMMAND); + serial_flush(); } } @@ -50,10 +57,14 @@ void cmd_set_sw_encoding() { EncodingType encoding_type; encoding_type = serial_rx_byte(); - set_encoding_type(encoding_type); + if (set_encoding_type(encoding_type)) { + serial_tx_byte(RESPONSE_CODE_SUCCESS); + } else { + serial_tx_byte(RESPONSE_CODE_PARAM_ERROR); // Error: encoding type not supported + } + serial_flush(); } - void cmd_set_mode_registers() { uint8_t register_mode; uint8_t count; @@ -87,7 +98,7 @@ void cmd_set_mode_registers() { mode_registers_add(registers, addr, value); } } - serial_tx_byte(0); + serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_flush(); } @@ -105,24 +116,28 @@ void cmd_get_packet() { } void cmd_get_state() { + serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_tx_str("OK"); } void cmd_get_version() { + serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_tx_str("subg_rfspy 2.0"); } void cmd_send_packet() { uint8_t channel; uint8_t repeat_count; - uint8_t delay_ms; + uint16_t delay_ms; + uint16_t preamble_extend_ms; uint8_t len; channel = serial_rx_byte(); repeat_count = serial_rx_byte(); - delay_ms = serial_rx_byte(); + delay_ms = serial_rx_word(); + preamble_extend_ms = serial_rx_word(); len = serial_rx_avail(); - send_packet_from_serial(channel, repeat_count, delay_ms, len); - serial_tx_byte(0); + send_packet_from_serial(channel, repeat_count, delay_ms, preamble_extend_ms, len); + serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_flush(); } @@ -130,26 +145,28 @@ void cmd_send_packet() { void cmd_send_and_listen() { uint8_t send_channel; uint8_t repeat_count; - uint8_t delay_ms; + uint16_t delay_ms; uint8_t listen_channel; uint32_t timeout_ms; uint8_t retry_count; + uint16_t preamble_extend_ms; uint8_t result; uint8_t len; send_channel = serial_rx_byte(); repeat_count = serial_rx_byte(); - delay_ms = serial_rx_byte(); + delay_ms = serial_rx_word(); listen_channel = serial_rx_byte(); timeout_ms = serial_rx_long(); retry_count = serial_rx_byte(); + preamble_extend_ms = serial_rx_word(); len = serial_rx_avail(); - send_packet_from_serial(send_channel, repeat_count, delay_ms, len); + send_packet_from_serial(send_channel, repeat_count, delay_ms, preamble_extend_ms, len); result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); - while (result == ERROR_RX_TIMEOUT && retry_count > 0) { - resend_from_tx_buf(send_channel); + while (result == RESPONSE_CODE_RX_TIMEOUT && retry_count > 0) { + send_from_tx_buf(send_channel, preamble_extend_ms); result = get_packet_and_write_to_serial(listen_channel, timeout_ms, use_pktlen); retry_count--; } @@ -166,6 +183,7 @@ void cmd_read_register() { uint8_t value; addr = serial_rx_byte(); value = get_register(addr); + serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_tx_byte(value); serial_flush(); } @@ -198,4 +216,14 @@ void cmd_led() { led = serial_rx_byte(); mode = serial_rx_byte(); led_set_mode(led, mode);//0, 1, 2 = Off, On, Auto + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); +} + +void cmd_set_preamble() { + uint16_t preamble_word; + preamble_word = serial_rx_word(); + radio_set_preamble(preamble_word); + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); } diff --git a/commands.h b/commands.h index 6d0b522..dd322c2 100644 --- a/commands.h +++ b/commands.h @@ -1,8 +1,11 @@ #ifndef COMMANDS_H #define COMMANDS_H -#define ERROR_RX_TIMEOUT 0xaa -#define ERROR_CMD_INTERRUPTED 0xbb +#define RESPONSE_CODE_RX_TIMEOUT 0xaa +#define RESPONSE_CODE_CMD_INTERRUPTED 0xbb +#define RESPONSE_CODE_SUCCESS 0xdd +#define RESPONSE_CODE_PARAM_ERROR 0x11 +#define RESPONSE_CODE_UNKNOWN_COMMAND 0x22 enum RegisterMode { RegisterModeTx = 0x01, diff --git a/common.mk b/common.mk index b82686d..726ad84 100755 --- a/common.mk +++ b/common.mk @@ -12,13 +12,14 @@ TARGET_BUILD := ${SERIAL_TYPE}_${BOARD_TYPE}_${RADIO_LOCALE}_${CODE_LOC_NAME} CC=sdcc -LDFLAGS=--xram-loc 0xf000 --xram-size 0x1000 --code-loc ${CODE_LOC} --code-size 0x8000 -CFLAGS=-I. -I${SERIAL_TYPE} --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} +LDFLAGS=--xram-loc 0xf000 --model-medium --xram-size 0x1000 --code-loc ${CODE_LOC} --code-size 0x8000 +CFLAGS=-I. -I${SERIAL_TYPE} --model-medium --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex common_modules = radio.rel main.rel timer.rel encoding.rel manchester.rel \ - fourbsixb.rel commands.rel delay.rel hardware.rel + fourbsixb.rel commands.rel hardware.rel packet_buffer.rel \ + fifo.rel clean: rm -rf output/${TARGET_BUILD} diff --git a/delay.c b/delay.c deleted file mode 100644 index 2dcb956..0000000 --- a/delay.c +++ /dev/null @@ -1,21 +0,0 @@ - -#include -#include "hardware.h" - -// This factor is based on the particular instructions that -// sdcc generates for the loops -#define CYCLES_PER_LOOP 18 - -void delay(uint8_t msec) -{ - volatile uint8_t mhz_ctr; - volatile uint8_t adj_ctr; - while(msec--){ - adj_ctr = 1000 /* usec to msec */ / CYCLES_PER_LOOP; - while(adj_ctr--){ - mhz_ctr = SYSTEM_CLOCK_MHZ; - while(mhz_ctr--); - } - } -} - diff --git a/delay.h b/delay.h deleted file mode 100644 index 358b636..0000000 --- a/delay.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DELAY_H -#define DELAY_H - -void delay(uint8_t msec); - -#endif diff --git a/encoding.c b/encoding.c index aaa7f96..ab84c68 100644 --- a/encoding.c +++ b/encoding.c @@ -13,7 +13,7 @@ static void passthrough_add_raw_byte(EncoderState *state, uint8_t raw) __reentra state->passthrough.data = raw; } -static uint8_t passthrough_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { +static uint8_t passthrough_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant { if (state->passthrough.count < 1) { return 0; } @@ -30,6 +30,9 @@ static void passthrough_init_decoder(DecoderState *state) { static uint8_t passthrough_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { state->passthrough.data = encoded; state->passthrough.count = 1; + if (encoded == 0) { + return 1; + } return 0; } diff --git a/encoding.h b/encoding.h index 66bc776..bb38016 100644 --- a/encoding.h +++ b/encoding.h @@ -2,13 +2,15 @@ #define ENCODING_H #include +#include #include "manchester_state.h" #include "fourbsixb_state.h" typedef enum { EncodingTypeNone = 0x0, EncodingTypeManchester = 0x1, - EncodingTypeFourbSixb = 0x02 + EncodingTypeFourbSixb = 0x02, + MaxEncodingTypeValue = EncodingTypeFourbSixb } EncodingType; typedef struct { @@ -37,14 +39,16 @@ typedef struct { // Adds a byte to be encoded void (*add_raw_byte)(EncoderState *state, uint8_t raw) __reentrant; // encoded will be set to next available encoded byte. + // If flush is true, then encoder should return any partial bytes // Return value is 0 if no more bytes are available. - uint8_t (*next_encoded_byte)(EncoderState *state, uint8_t *encoded) __reentrant; + uint8_t (*next_encoded_byte)(EncoderState *state, uint8_t *encoded, bool flush) __reentrant; } Encoder; typedef struct { // Adds a byte for decoding. The return value will be 1 if the byte // contains encoding errors, otherwise it will be 0. - uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t encoded) __reentrant; + uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t encoded) + __reentrant; // decoded will be set to the next available decoded byte. // Return value is 0 if no more bytes are available. uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded) __reentrant; diff --git a/fifo.c b/fifo.c new file mode 100644 index 0000000..e7d326c --- /dev/null +++ b/fifo.c @@ -0,0 +1,58 @@ + + +#include +#include +#include +#include "fifo.h" + +static volatile uint8_t fifo_count(fifo_buffer const *b) { + return (b ? (b->head - b->tail) : 0); +} + +bool fifo_full(fifo_buffer const *b) { + return (b ? (fifo_count(b) == b->buffer_len) : true); +} + +bool fifo_empty(fifo_buffer const *b) { + return (b ? (fifo_count(b) == 0) : true); +} + +uint8_t fifo_peek(fifo_buffer const *b) { + if (b) { + return (b->buffer[b->tail % b->buffer_len]); + } + return 0; +} + +uint8_t fifo_get(fifo_buffer * b) { + uint8_t data_byte = 0; + + if (!fifo_empty(b)) { + data_byte = b->buffer[b->tail % b->buffer_len]; + b->tail++; + } + return data_byte; +} + +bool fifo_put(fifo_buffer * b, uint8_t data_byte) { + bool status = false; /* return value */ + + if (b) { + /* limit the ring to prevent overwriting */ + if (!fifo_full(b)) { + b->buffer[b->head % b->buffer_len] = data_byte; + b->head++; + status = true; + } + } + return status; +} + +void fifo_init(fifo_buffer * b, volatile uint8_t *buffer, uint8_t size) { + if (b) { + b->head = 0; + b->tail = 0; + b->buffer = buffer; + b->buffer_len = size; + } +} diff --git a/fifo.h b/fifo.h new file mode 100644 index 0000000..85497be --- /dev/null +++ b/fifo.h @@ -0,0 +1,31 @@ + +/* fifo queue for use with interrupt routines. Size must be power of 2 */ + +#ifndef FIFO_H +#define FIFO_H + +#include +#include + +struct fifo_buffer_t { + volatile uint8_t head; /* first byte of data */ + volatile uint8_t tail; /* last byte of data */ + volatile uint8_t *buffer; /* block of memory or array of data */ + uint8_t buffer_len; /* length of the data */ +}; +typedef struct fifo_buffer_t fifo_buffer; + +bool fifo_empty(fifo_buffer const *b); + +bool fifo_full(fifo_buffer const *b); + +uint8_t fifo_peek(fifo_buffer const *b); + +uint8_t fifo_get(fifo_buffer *b); + +bool fifo_put(fifo_buffer *b, uint8_t data_byte); + + /* size must be a power of 2 */ +void fifo_init(fifo_buffer *b, volatile uint8_t *buffer, uint8_t size); + +#endif // FIFO_H diff --git a/fourbsixb.c b/fourbsixb.c index bf9300e..30eb5e8 100644 --- a/fourbsixb.c +++ b/fourbsixb.c @@ -16,12 +16,20 @@ void fourbsixb_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { state->fourbsixb.bits_avail += 12; } -uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { - if (state->fourbsixb.bits_avail < 8) { +uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant { + if (state->fourbsixb.bits_avail < 8 && !flush) { return 0; } - *encoded = state->fourbsixb.acc >> (8-state->fourbsixb.bits_avail); - state->fourbsixb.bits_avail -= 8; + if (state->fourbsixb.bits_avail == 0) { + return 0; + } + if (flush && state->fourbsixb.bits_avail < 8) { + *encoded = state->fourbsixb.acc << (8-state->fourbsixb.bits_avail); + state->fourbsixb.bits_avail = 0; + } else { + *encoded = state->fourbsixb.acc >> (state->fourbsixb.bits_avail-8); + state->fourbsixb.bits_avail -= 8; + } return 1; } diff --git a/fourbsixb.h b/fourbsixb.h index 4af2c0b..87d1227 100644 --- a/fourbsixb.h +++ b/fourbsixb.h @@ -5,7 +5,7 @@ void fourbsixb_init_encoder(EncoderState *state); void fourbsixb_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; -uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant; +uint8_t fourbsixb_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant; void fourbsixb_init_decoder(DecoderState *state); uint8_t fourbsixb_add_encoded_byte(DecoderState *state, uint8_t raw) __reentrant; uint8_t fourbsixb_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; diff --git a/hardware.c b/hardware.c index 0081220..d5dcf80 100644 --- a/hardware.c +++ b/hardware.c @@ -6,10 +6,9 @@ #include "radio.h" #include "timer.h" #include "commands.h" -#include "delay.h" -static uint8_t green_mode = 2; -static uint8_t blue_mode = 2; +static uint8_t __xdata green_mode = 2; +static uint8_t __xdata blue_mode = 2; mode_registers __xdata tx_registers; mode_registers __xdata rx_registers; @@ -48,6 +47,15 @@ void led_set_state(uint8_t led, uint8_t command) } } +void toggle_green() { + GREEN_LED = !GREEN_LED; +} + +void toggle_blue() { + BLUE_LED = !BLUE_LED; +} + + uint8_t get_register(uint8_t addr) { uint8_t value; addr = serial_rx_byte(); @@ -168,7 +176,7 @@ uint8_t get_register(uint8_t addr) { uint8_t set_register(uint8_t addr, uint8_t value) { uint8_t rval; - rval = 1; + rval = RESPONSE_CODE_SUCCESS; switch(addr) { case 0x00: SYNC1 = value; @@ -279,7 +287,7 @@ uint8_t set_register(uint8_t addr, uint8_t value) { PA_TABLE0 = value; break; default: - rval = 2; + rval = RESPONSE_CODE_PARAM_ERROR; } return rval; } diff --git a/hardware.h b/hardware.h index dbb6d7a..5f7142c 100644 --- a/hardware.h +++ b/hardware.h @@ -75,6 +75,10 @@ typedef struct mode_registers { void led_set_mode(uint8_t led, uint8_t new_mode); void led_set_state(uint8_t led, uint8_t command); +void toggle_green(); +void toggle_blue(); + + uint8_t get_register(uint8_t addr); uint8_t set_register(uint8_t addr, uint8_t value); diff --git a/main.c b/main.c index ef3cd6d..0099ebf 100644 --- a/main.c +++ b/main.c @@ -6,7 +6,6 @@ #include "radio.h" #include "timer.h" #include "commands.h" -#include "delay.h" // SDCC needs prototypes of all ISR functions in main. not sure why, but described in section 3.8.1 void t1_isr(void) __interrupt T1_VECTOR; @@ -15,7 +14,7 @@ void rf_isr(void) __interrupt RF_VECTOR; #ifdef USES_USART1_RX_ISR void rx1_isr(void) __interrupt URX1_VECTOR; -#endif +#endif #ifdef USES_USART1_TX_ISR void tx1_isr(void) __interrupt UTX1_VECTOR; @@ -48,10 +47,10 @@ int main(void) //LED test led_set_state(0, 1); //GREEN_LED = 1; - delay(1000); + delay(200); led_set_state(0, 0); //GREEN_LED = 0; led_set_state(1, 1); //BLUE_LED = 1; - delay(1000); + delay(200); led_set_state(1, 0); //BLUE_LED = 0; configure_radio(); diff --git a/manchester.c b/manchester.c index a6c7658..58bc9e0 100644 --- a/manchester.c +++ b/manchester.c @@ -9,7 +9,7 @@ void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { uint16_t acc = 0; int i; for (i=0; i<8; i++) { - acc = (acc << 2) + 1 + (raw >> 7); + acc = (acc << 2) + 2 - (raw >> 7); raw = raw << 1; } state->manchester.output[0] = acc >> 8; @@ -17,7 +17,7 @@ void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant { state->manchester.offset = 0; } -uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant { +uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant { if (state->manchester.offset > 1) { return 0; } @@ -36,13 +36,13 @@ void manchester_init_decoder(DecoderState *state) { uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant { uint8_t acc = 0; int i; - for (i=0; i<8; i++) { + for (i=6; i>=0; i-=2) { acc = (acc << 1); - switch(encoded & 0b11) { + switch((encoded >> i) & 0b11) { case 0b00: case 0b11: return 1; // Encoding error - case 0b10: + case 0b01: acc++; } } diff --git a/manchester.h b/manchester.h index cef61b8..a4eee63 100644 --- a/manchester.h +++ b/manchester.h @@ -5,7 +5,7 @@ void manchester_init_encoder(EncoderState *state); void manchester_add_raw_byte(EncoderState *state, uint8_t raw) __reentrant; -uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded) __reentrant; +uint8_t manchester_next_encoded_byte(EncoderState *state, uint8_t *encoded, bool flush) __reentrant; void manchester_init_decoder(DecoderState *state); uint8_t manchester_add_encoded_byte(DecoderState *state, uint8_t encoded) __reentrant; uint8_t manchester_next_decoded_byte(DecoderState *state, uint8_t *decoded) __reentrant; diff --git a/packet_buffer.c b/packet_buffer.c new file mode 100644 index 0000000..518cae9 --- /dev/null +++ b/packet_buffer.c @@ -0,0 +1,62 @@ +#include + +// FIFO queue for packets + +// Adjust this based on available space as indicated in linker .mem file +#define PACKET_DATA_BUF_LEN 2000 + +// This should be PACKET_DATA_LEN / average packet size +#define PACKET_COUNT_MAX 30 + +// Circular buffers +static uint8_t __xdata packet_data_buf[PACKET_DATA_BUF_LEN]; +static uint8_t __xdata packet_lengths[PACKET_COUNT_MAX]; + +static uint16_t __xdata packet_data_buf_head; +static uint16_t __xdata packet_data_buf_tail; +static uint16_t __xdata packet_data_buf_len; +static uint8_t __xdata packet_lengths_head; +static uint8_t __xdata packet_lengths_tail; +static uint8_t __xdata packet_count; + +uint8_t enqueue_packet(const uint8_t *packet_data, uint16_t packet_len) { + uint16_t i; + + if (packet_data_buf_len + packet_len >= PACKET_DATA_BUF_LEN) { + return 0; + } + + if (packet_count + 1 >= PACKET_COUNT_MAX) { + return 0; + } + + packet_lengths[packet_lengths_head] = packet_len; + packet_lengths_head = (packet_lengths_head + 1) % PACKET_COUNT_MAX; + packet_count++; + + for (i=0; i radio_tx_buf_idx) { - d_byte = radio_tx_buf[radio_tx_buf_idx++]; - RFD = d_byte; - } else { - RFD = 0; - underflow_count++; - // We wait a few counts to make sure the radio has sent the last bytes - // before turning it off. - if (underflow_count == 2) { - RFST = RFST_SIDLE; + switch (tx_state) { + case TxStatePreambleByte0: + RFD = preamble_word >> 8; + tx_state = TxStatePreambleByte1; + break; + case TxStatePreambleByte1: + RFD = preamble_word & 0xff; + if (stop_custom_preamble_semaphore) { + tx_state = TxStateSync1; + } else { + tx_state = TxStatePreambleByte0; + } + break; + case TxStateSync1: + RFD = SYNC1; + tx_state = TxStateSync0; + break; + case TxStateSync0: + RFD = SYNC0; + tx_state = TxStateData; + break; + case TxStateData: + RFD = radio_tx_buf[radio_tx_buf_read_idx++]; + if (radio_tx_buf_read_idx >= radio_tx_buf_len) { + tx_state = TxStateDone; } + break; + case TxStateDone: + tx_underflow++; + // Letting RFD go empty will make the radio stop TX mode. + //RFD = 0; + break; } + } } @@ -145,9 +190,9 @@ void rf_isr(void) __interrupt RF_VECTOR { } -void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms, uint8_t len) { +void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t delay_ms, uint16_t preamble_extend_ms, uint8_t len) { uint8_t s_byte; - uint8_t pktlen_save; + uint8_t send_count = 0; Encoder encoder; EncoderState encoder_state; @@ -156,84 +201,98 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t dela mode_registers_enact(&tx_registers); - pktlen_save = PKTLEN; - PKTLEN = len; - - radio_tx_buf_len = 0; - radio_tx_buf_idx = 0; - underflow_count = 0; - - RFST = RFST_SIDLE; - while(MARCSTATE!=MARC_STATE_IDLE); + toggle_green(); CHANNR = channel; - //led_set_state(1,1); + radio_tx_buf_len = 0; while (len > 0) { s_byte = serial_rx_byte(); len--; encoder.add_raw_byte(&encoder_state, s_byte); - while (encoder.next_encoded_byte(&encoder_state, &s_byte)) { - radio_tx_buf[radio_tx_buf_len++] = s_byte; - if (radio_tx_buf_len >= MAX_PACKET_LEN) { - break; + while (encoder.next_encoded_byte(&encoder_state, &s_byte, len == 0)) { + if (radio_tx_buf_len+1 < TX_BUF_SIZE) { + radio_tx_buf[radio_tx_buf_len++] = s_byte; } } - - if (radio_tx_buf_len == 2) { - // Turn on radio after 2 bytes - RFST = RFST_STX; - } } - // wait for sending to finish - while(MARCSTATE!=MARC_STATE_IDLE); - - while(repeat_count > 0) { - // Reset idx to beginning of buffer - radio_tx_buf_idx = 0; - underflow_count = 0; + repeat_count += 1; + while(send_count < repeat_count) { // delay - if (delay_ms > 0) { + if (send_count > 0 && delay_ms > 0) { delay(delay_ms); } - // Turn on radio (interrupts should start again) - RFST = RFST_STX; - while(MARCSTATE!=MARC_STATE_TX); + send_from_tx_buf(channel, preamble_extend_ms); - // wait for sending to finish - while(MARCSTATE!=MARC_STATE_IDLE); - repeat_count--; + send_count++; } - PKTLEN = pktlen_save; //led_set_state(1,0); } -void resend_from_tx_buf(uint8_t channel) { +void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { uint8_t pktlen_save; + uint8_t mdmcfg2_save; + uint8_t pktctrl0_save; + mdmcfg2_save = MDMCFG2; pktlen_save = PKTLEN; - PKTLEN = radio_tx_buf_len; + pktctrl0_save = PKTCTRL0; + + if (preamble_word != 0) { + // save and turn off preamble/sync registers + MDMCFG2 &= 0b11111100; // Disable PREAMBLE/SYNC + PKTCTRL0 = (PKTCTRL0 & ~0b11) | 0b10; // Enter "infinite" tx mode + PKTLEN = 0; + stop_custom_preamble_semaphore = 0; + tx_state = TxStatePreambleByte0; + } else { + if (preamble_extend_ms) { + tx_state = TxStatePreambleDefault; + } else { + tx_state = TxStateData; + } + PKTLEN = radio_tx_buf_len; + } RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); CHANNR = channel; - // Reset idx to beginning of buffer - radio_tx_buf_idx = 0; - underflow_count = 0; + radio_tx_buf_read_idx = 0; - // Turn on radio (interrupts should start again) + // Turn on radio (interrupts will start again) RFST = RFST_STX; while(MARCSTATE!=MARC_STATE_TX); + if (preamble_extend_ms > 0) { + led_set_state(1, 1); //BLUE_LED = 1; + delay(preamble_extend_ms); + if(preamble_word==0) { + TCON |= 0b10; // Manually trigger RFTXRX vector. + } + led_set_state(1, 0); //BLUE_LED = 0; + } + + if (preamble_word != 0) { + stop_custom_preamble_semaphore = 1; + } else { + tx_state = TxStateData; + } + // wait for sending to finish - while(MARCSTATE!=MARC_STATE_IDLE); + while(MARCSTATE==MARC_STATE_TX); + + if (MARCSTATE==MARC_STATE_TX_UNDERFLOW) { + RFST = RFST_SIDLE; + } PKTLEN = pktlen_save; + MDMCFG2 = mdmcfg2_save; + PKTCTRL0 = pktctrl0_save; } uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen) { @@ -257,20 +316,24 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin CHANNR = channel; - radio_rx_buf_len = 0; + rx_len = 0; RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); //led_set_state(1,1); while(1) { - // Waiting for isr to put radio bytes into radio_rx_buf - if (radio_rx_buf_len > read_idx) { + // Waiting for isr to put radio bytes into rx_fifo + if (!fifo_empty(&rx_fifo)) { //led_set_state(0,1); - d_byte = radio_rx_buf[read_idx]; + d_byte = fifo_get(&rx_fifo); read_idx++; + // Send status code + if (read_idx == 1) { + serial_tx_byte(RESPONSE_CODE_SUCCESS); + } // First two bytes are rssi and packet # if (read_idx < 3) { serial_tx_byte(d_byte); @@ -286,20 +349,15 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin break; } - if (read_idx > 1 && read_idx == radio_rx_buf_len) { - // Check for end of packet - if (use_pktlen && read_idx == PKTLEN) { - //led_set_state(0,0); - break; - } - if (!use_pktlen && d_byte == 0) { - break; - } + // Check for end of packet + if (use_pktlen && read_idx == PKTLEN) { + //led_set_state(0,0); + break; } } if (timeout_ms > 0 && timerCounter > timeout_ms) { - rval = ERROR_RX_TIMEOUT; + rval = RESPONSE_CODE_RX_TIMEOUT; //led_set_state(1,0); break; } @@ -309,7 +367,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin // Received a byte from uart while waiting for radio packet // We will interrupt the RX and go handle the command. interrupting_cmd = serial_rx_byte(); - rval = ERROR_CMD_INTERRUPTED; + rval = RESPONSE_CODE_CMD_INTERRUPTED; break; } } @@ -317,3 +375,8 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin //led_set_state(1,0); return rval; } + +// Set software based preamble, 0 = disable +void radio_set_preamble(uint16_t p) { + preamble_word = p; +} diff --git a/radio.h b/radio.h index 95cea21..71c1327 100644 --- a/radio.h +++ b/radio.h @@ -2,6 +2,7 @@ #define RADIO_H #include "encoding.h" +#include "stdbool.h" void configure_radio(); @@ -11,12 +12,14 @@ void configure_radio(); // 2 = rx interrupted by serial uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen); -void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint8_t delay_ms, uint8_t len); +void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t delay_ms, uint16_t preamble_extend_ms, uint8_t len); -// Used for retry -void resend_from_tx_buf(uint8_t channel); +void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms); -// Set software based encoding -void set_encoding_type(EncodingType encoding_type); +// Set software based encoding. Returns false if encoding type is not supported +bool set_encoding_type(EncodingType encoding_type); + +// Set software based preamble, 0 = disable +void radio_set_preamble(uint16_t preamble_word); #endif diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index b670588..dec641b 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -20,9 +20,13 @@ volatile uint8_t ready_to_send = 0; volatile uint8_t serial_data_available; -#define SPI_MODE_WAIT 0 -#define SPI_MODE_SIZE 1 -#define SPI_MODE_XFER 2 +volatile uint8_t transferring = 0; + +#define SPI_MODE_IDLE 0 +#define SPI_MODE_SKIP_NEXT_BYTE 1 +#define SPI_MODE_TX_SIZE 2 +#define SPI_MODE_RX_SIZE 3 +#define SPI_MODE_XFER 4 volatile uint8_t spi_mode; volatile uint8_t master_send_size = 0; @@ -34,8 +38,7 @@ volatile uint8_t slave_send_size = 0; * SPI encoding: * * Master sends a 0x99 byte, followed by number of bytes that will be sent. - * Before second byte xfer, slave loads up buffer with number of bytes - * available. + * Slave sends back number of bytes available during second xfer. * */ @@ -88,30 +91,30 @@ void configure_serial() IRCON2 &= ~BIT2; // Clear UTX1IF IEN2 |= BIT3; // Enable UTX1IE interrupt + + U1DBUF = 0x44; } void rx1_isr(void) __interrupt URX1_VECTOR { uint8_t value; value = U1DBUF; - if (spi_mode == SPI_MODE_WAIT && value == 0x99) { - if (ready_to_send) { - slave_send_size = output_size; - ready_to_send = 0; - } else { - slave_send_size = 0; + if (spi_mode == SPI_MODE_TX_SIZE) { + if (value != 0x99) { + // Error! } - spi_mode = SPI_MODE_SIZE; - U1DBUF = slave_send_size; + spi_mode = SPI_MODE_RX_SIZE; return; } - if (spi_mode == SPI_MODE_SIZE) { + if (spi_mode == SPI_MODE_RX_SIZE) { master_send_size = value; if (master_send_size > 0 || slave_send_size > 0) { spi_mode = SPI_MODE_XFER; + IRCON2 |= BIT2; // Trigger UTX1IF } else { - spi_mode = SPI_MODE_WAIT; + spi_mode = SPI_MODE_IDLE; + transferring = 0; } return; } @@ -130,30 +133,56 @@ void rx1_isr(void) __interrupt URX1_VECTOR { } } if (slave_send_size == 0 && master_send_size == 0) { - spi_mode = SPI_MODE_WAIT; + spi_mode = SPI_MODE_IDLE; } } } void tx1_isr(void) __interrupt UTX1_VECTOR { IRCON2 &= ~BIT2; // Clear UTX1IF - if (spi_mode == SPI_MODE_SIZE || spi_mode == SPI_MODE_XFER) { + + if (spi_mode == SPI_MODE_SKIP_NEXT_BYTE) { + spi_mode = SPI_MODE_IDLE; + return; + } + + if (spi_mode == SPI_MODE_IDLE) { + if (ready_to_send) { + slave_send_size = output_size; + ready_to_send = 0; + U1DBUF = output_size; + } else { + U1DBUF = 0; + } + spi_mode = SPI_MODE_TX_SIZE; + return; + } + + if (spi_mode == SPI_MODE_XFER) { + // The first byte we send here is pre-emptive; transfer hasn't started + // SPI transfer starts when SSN is selected + if (U0CSR & U0CSR_ACTIVE) { + transferring = 1; + } + if (slave_send_size > 0 && output_size > 0) { slave_send_size--; - if (slave_send_size == 0 && master_send_size == 0) { - spi_mode = SPI_MODE_WAIT; - } U1DBUF = spi_output_buf[output_tail_idx]; output_size--; output_tail_idx++; if (output_tail_idx >= SPI_BUF_LEN) { output_tail_idx = 0; } + if (output_size == 0 && master_send_size == 0) { + spi_mode = SPI_MODE_SKIP_NEXT_BYTE; + } } else { - U1DBUF = 0x99; + // Filler for when we are receiving data, but not sending anything + U1DBUF = 0x98; } } else { - U1DBUF = 0x99; + // Filler + U1DBUF = 0x97; } } @@ -203,7 +232,13 @@ void serial_tx_byte(uint8_t tx_byte) { void serial_flush() { ready_to_send = 1; - while(output_size); + while(output_size > 0) { + if (transferring & !(U0CSR & U0CSR_ACTIVE)) { + // If SSN is deselected while transferring, treat as a cancel + // and flush out bytes manually until finished + IRCON2 |= BIT2; // Trigger UTX1IF + } + } } void serial_tx_str(const char *str) { diff --git a/spi1_alt2/serial.h b/spi1_alt2/serial.h index 06876a0..bbb0f25 100644 --- a/spi1_alt2/serial.h +++ b/spi1_alt2/serial.h @@ -10,6 +10,7 @@ void serial_tx_byte(uint8_t); void serial_tx_str(const char *str); void serial_flush(); uint8_t serial_rx_byte(); +uint16_t serial_rx_word(); uint32_t serial_rx_long(); uint8_t serial_rx_avail(); diff --git a/timer.c b/timer.c index d56b9b0..c77262b 100644 --- a/timer.c +++ b/timer.c @@ -22,7 +22,7 @@ void init_timer() { do { t1cnt.byte[0] = T1CNTL; - t1cnt.byte[1] = T1CNTH; + t1cnt.byte[1] = T1CNTH; } while (t1cnt.val <= 0xA000); // Stop timer @@ -46,9 +46,14 @@ void reset_timer() { void t1_isr(void) __interrupt T1_VECTOR { - if (timerCounter % 1000 == 0) { - //BLUE_LED = !BLUE_LED; - } + // if (timerCounter % 1000 == 0) { + // BLUE_LED = !BLUE_LED; + // } timerCounter++; } +void delay(uint32_t msec) { + uint32_t start_time; + start_time = timerCounter; + while(timerCounter - start_time < msec); +} diff --git a/timer.h b/timer.h index 82157a3..8f08f6c 100644 --- a/timer.h +++ b/timer.h @@ -5,6 +5,6 @@ volatile extern uint32_t timerCounter; void init_timer(); void reset_timer(); +void delay(uint32_t msec); #endif - diff --git a/uart1_alt2/serial.c b/uart1_alt2/serial.c index 70956ce..c237009 100644 --- a/uart1_alt2/serial.c +++ b/uart1_alt2/serial.c @@ -22,7 +22,7 @@ volatile uint8_t serial_data_available; void configure_serial() { - // UART1 Alt. 2 + // UART1 Alt. 2 // P1.4 - CT // P1.5 - RT // P1.6 - TX @@ -37,11 +37,11 @@ void configure_serial() // Initialize bitrate (U1BAUD.BAUD_M, U1GCR.BAUD_E) // Bitrate 19200 #if SYSTEM_CLOCK_MHZ == 26 - U1BAUD = 131; + U1BAUD = 131; #else - U1BAUD = 163; + U1BAUD = 163; #endif - U1GCR = (U0GCR&~0x1F) | 9; + U1GCR = (U0GCR&~0x1F) | 9; U1UCR |= HARDWARE_FLOW_CONTROL_CONFIG; // Flush, and configure hw flow control // Enable receive @@ -78,7 +78,7 @@ uint8_t serial_rx_byte() { serial_data_available = 0; } return s_data; -} +} uint16_t serial_rx_word() { return (serial_rx_byte() << 8) + serial_rx_byte(); @@ -88,7 +88,6 @@ uint32_t serial_rx_long() { return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); } - void serial_tx_byte(uint8_t tx_byte) { UTX1IF = 0; U1DBUF = tx_byte; @@ -103,6 +102,3 @@ void serial_tx_str(const char *str) { } serial_tx_byte(0); } - - - From c137ada8a8ae15ede8c55dd09c9d81c4a4e19adf Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 10 Feb 2018 10:16:03 -0800 Subject: [PATCH 24/45] Adding python client to communicate over spi --- client/README.md | 14 +++++ client/commands.py | 142 ++++++++++++++++++++++++++++++++++++++++++ client/listen.py | 14 +++++ client/listen_omni.py | 16 +++++ client/omni.py | 26 ++++++++ client/send_omni.py | 12 ++++ client/spilink.py | 86 +++++++++++++++++++++++++ client/test.py | 21 +++++++ 8 files changed, 331 insertions(+) create mode 100644 client/README.md create mode 100644 client/commands.py create mode 100644 client/listen.py create mode 100644 client/listen_omni.py create mode 100644 client/omni.py create mode 100644 client/send_omni.py create mode 100644 client/spilink.py create mode 100644 client/test.py diff --git a/client/README.md b/client/README.md new file mode 100644 index 0000000..83fb166 --- /dev/null +++ b/client/README.md @@ -0,0 +1,14 @@ +# Python client for interacting with subg_rfspy + +http://eblot.github.io/pyftdi/ + +# Install on mac: + +`brew install libusb` +`brew install libftdi` +`pip3 install pyftdi` + +# Hardware + +* An FT232H based board, like the [Shikra](https://int3.cc/products/the-shikra). +* A cc1110 device, like the [RileyLink](https://github.com/ps2/rileylink). If you use a RileyLink, install the [noop firmware](https://github.com/ps2/rileylink/tree/master/firmware/ble113_disabled) on the ble113. diff --git a/client/commands.py b/client/commands.py new file mode 100644 index 0000000..e24d584 --- /dev/null +++ b/client/commands.py @@ -0,0 +1,142 @@ +from array import array +from struct import * +from enum import Enum + +class ErrorCode(Enum): + PROTOCOL_SYNC = 0x00 + RX_TIMEOUT = 0xaa + COMMAND_INTERRUPTED = 0xbb + + +class ByteResponse: + def __init__(self, response_data): + if len(response_data) > 1: + raise ValueError + self.response_byte = array('B', response_data)[0] + + def __repr__(self): + return "ByteResponse(\"%d\")" % self.response_byte + + +class StringResponse: + def __init__(self, response_data): + self.response_data = array('B', response_data) + + def __repr__(self): + return "StringResponse(\"%s\")" % self.response_data.tostring().decode("UTF-8") + +class PacketResponse: + def __init__(self, response_data): + self.error_code = None + if len(response_data) < 2: + self.error_code = ErrorCode(response_data[0]) + else: + self.rssi_dec = response_data[0] + self.packet_num = response_data[1] + self.response_data = array('B', response_data[2:]) + + def __repr__(self): + if self.error_code: + return "PacketErrorResponse(%s)" % self.error_code.name + else: + hex = "".join(["%02x" % x for x in self.response_data]) + return "PacketResponse(\"%s\")" % hex + +class GetStateCommand: + def data(self): + return array('B', [1]) + + def response_type(self): + return StringResponse + +class GetVersionCommand: + def data(self): + return array('B', [2]) + + def response_type(self): + return StringResponse + +class GetPacketCommand: + def __init__(self, timeout_ms=100, channel=0): + self.channel = channel + self.timeout_ms = timeout_ms + + def data(self): + data = pack('>BBL', 3, self.channel, self.timeout_ms) + return array('B', data) + + def response_type(self): + return PacketResponse + +class SendPacketCommand: + def __init__(self, packet_data, repeat_count=0, delay_ms=5, preamble_extend_ms=0, channel=0): + self.channel = channel + self.repeat_count = repeat_count + self.delay_ms = delay_ms + self.preamble_extend_ms = preamble_extend_ms + self.packet_data = packet_data + + def data(self): + conf = pack('>BBBHH', 4, self.channel, self.repeat_count, self.delay_ms, self.preamble_extend_ms) + return array('B', conf) + self.packet_data + + def response_type(self): + return ByteResponse + +class Register(Enum): + SYNC1 = 0x00 + SYNC0 = 0x01 + PKTLEN = 0x02 + PKTCTRL1 = 0x03 + PKTCTRL0 = 0x04 + FSCTRL1 = 0x07 + FREQ2 = 0x09 + FREQ1 = 0x0a + FREQ0 = 0x0b + MDMCFG4 = 0x0c + MDMCFG3 = 0x0d + MDMCFG2 = 0x0e + MDMCFG1 = 0x0f + MDMCFG0 = 0x10 + DEVIATN = 0x11 + MCSM0 = 0x14 + FOCCFG = 0x15 + AGCCTRL2 = 0x17 + AGCCTRL1 = 0x18 + AGCCTRL0 = 0x19 + FREND1 = 0x1a + FREND0 = 0x1b + FSCAL3 = 0x1c + FSCAL2 = 0x1d + FSCAL1 = 0x1e + FSCAL0 = 0x1f + TEST1 = 0x24 + TEST0 = 0x25 + PATABLE0 = 0x2e + +class UpdateRegisterCommand: + def __init__(self, register, value): + self.register = register + self.value = value + + def data(self): + return array('B', [6, self.register.value, self.value]) + + def response_type(self): + return ByteResponse + + +class Encoding(Enum): + NONE = 0 + MANCHESTER = 1 + FOURBSIXB = 2 + +class SetSoftwareEncoding: + def __init__(self, encoding): + self.encoding = encoding + + def data(self): + return array('B', [11, self.encoding.value]) + + def response_type(self): + return ByteResponse diff --git a/client/listen.py b/client/listen.py new file mode 100644 index 0000000..a91e40e --- /dev/null +++ b/client/listen.py @@ -0,0 +1,14 @@ +from pyftdi.spi import SpiController +from spilink import SPILink +from commands import * +from array import array +import time + +link = SPILink(debug=True) +link.flush() + +print(link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) + +while True: + print(link.do_command(GetPacketCommand(timeout_ms=50000), timeout=51)) + time.sleep(0.1) diff --git a/client/listen_omni.py b/client/listen_omni.py new file mode 100644 index 0000000..f6fc746 --- /dev/null +++ b/client/listen_omni.py @@ -0,0 +1,16 @@ +from spilink import SPILink +from commands import * +from array import array +import omni + +link = SPILink(debug=True) +link.flush() + +omni.configure(link) + +# packet_data = [1,2,3,4,5,6,7,8,9] +# send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=0) +# print(link.do_command(send_cmd, timeout=5)) + +while True: + print(link.do_command(GetPacketCommand(timeout_ms=50000), timeout=51)) diff --git a/client/omni.py b/client/omni.py new file mode 100644 index 0000000..449284e --- /dev/null +++ b/client/omni.py @@ -0,0 +1,26 @@ +from commands import * + +def configure(link): + link.do_command(SetSoftwareEncoding(Encoding.MANCHESTER)) + link.set_base_frequency(433910000) + link.update_register(Register.PKTCTRL1, 0x20) + link.update_register(Register.PKTCTRL0, 0x00) + link.update_register(Register.FSCTRL1, 0x06) + link.update_register(Register.PKTCTRL1, 0x20) + link.update_register(Register.MDMCFG4, 0xCA) + link.update_register(Register.MDMCFG3, 0xBC) + link.update_register(Register.MDMCFG2, 0x06) + link.update_register(Register.MDMCFG1, 0x10) + link.update_register(Register.MDMCFG0, 0x11) + link.update_register(Register.DEVIATN, 0x47) + link.update_register(Register.MCSM0, 0x18) + link.update_register(Register.FOCCFG, 0x17) + link.update_register(Register.FSCAL3, 0xE9) + link.update_register(Register.FSCAL2, 0x2A) + link.update_register(Register.FSCAL1, 0x00) + link.update_register(Register.FSCAL0, 0x1F) + link.update_register(Register.TEST1, 0x31) + link.update_register(Register.TEST0, 0x09) + link.update_register(Register.PATABLE0, 0x84) + link.update_register(Register.SYNC1, 0xA5) + link.update_register(Register.SYNC0, 0x5A) diff --git a/client/send_omni.py b/client/send_omni.py new file mode 100644 index 0000000..63650a1 --- /dev/null +++ b/client/send_omni.py @@ -0,0 +1,12 @@ +from spilink import SPILink +from commands import * +import omni + +link = SPILink(debug=True) +link.flush() + +omni.configure(link) + +packet_data = bytearray.fromhex("000000005800000000fbf9f8fbe0ff1179fed102") +send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=0) +print(link.do_command(send_cmd, timeout=5)) diff --git a/client/spilink.py b/client/spilink.py new file mode 100644 index 0000000..5b032c7 --- /dev/null +++ b/client/spilink.py @@ -0,0 +1,86 @@ +from pyftdi.spi import SpiController +import time +from commands import * + +RILEYLINK_XTAL_FREQUENCY = 24000000 + +class SPITimeout(Exception): + pass + +class SPILink: + BIT_REV = [int('{:08b}'.format(n)[::-1], 2) for n in range(0,256)] + + def __init__(self, device='ftdi://ftdi:232h/1', debug=False): + self.device_str = device + self.debug = debug + self.ctrl = SpiController(silent_clock=False) + self.ctrl.configure(device, cs_count=1) + self.spi = self.ctrl.get_port(cs=0, freq=100000) + self.gpio = self.ctrl.get_gpio() + direction = self.gpio.direction + self.gpio.set_direction(0x30, 0x10) + self.gpio.write(0x10) + + def reset(self): + self.gpio.write(0x00) # Pull reset line low + time.sleep(0.1) + self.gpio.write(0x10) # Reset line high + time.sleep(0.8) # Wait for cc111x to boot + + def flush(self): + # Send interrupt command + _, available = self.exchange([0x99, 1], readlen=2) + data = self.exchange([], readlen=max(1,available)) + # Discard any remaining data + _, available = self.exchange([0x99, 0], readlen=2) + while (available > 0): + data = self.exchange([], readlen=available) + if self.debug: + print("discarding %s" % "".join(["%02x" % x for x in data])) + _, available = self.exchange([0x99, 0], readlen=2) + + def reverse_bits(self, data): + return [SPILink.BIT_REV[x] for x in data] + + def as_hex(self, data): + return "".join(["%02x" % x for x in data]) + + def exchange(self, data, readlen=0): + lsb_send = self.reverse_bits(data) + lsb_rcv = self.spi.exchange(lsb_send,readlen=readlen, duplex=True) + return self.reverse_bits(lsb_rcv) + + def do_command(self, command, timeout=1): + end_time = time.time() + timeout + data = command.data() + if self.debug: + print("send: %s" % self.as_hex(data)) + response = None + while(time.time() < end_time and response == None): + _, available = self.exchange([0x99, len(data)], readlen=2) + if (len(data) > 0 or available > 0): + if self.debug: + print("size exchange: master = %d, slave = %d" % (len(data), available)) + rdata = self.exchange(data, readlen=available) + else: + time.sleep(0.01) + if available > 0: + response = rdata + data = [] + + if response == None: + raise SPITimeout() + response_type = command.response_type() + if self.debug: + print("recv: %s" % self.as_hex(response)) + response_obj = response_type(response) + return response_obj + + def update_register(self, register, value): + return self.do_command(UpdateRegisterCommand(register, value)) + + def set_base_frequency(self, freq): + val = int(freq / (RILEYLINK_XTAL_FREQUENCY / pow(2,16))) + self.update_register(Register.FREQ0, val & 0xff) + self.update_register(Register.FREQ1, (val >> 8) & 0xff) + self.update_register(Register.FREQ2, (val >> 16) & 0xff) diff --git a/client/test.py b/client/test.py new file mode 100644 index 0000000..29b0ba9 --- /dev/null +++ b/client/test.py @@ -0,0 +1,21 @@ +from pyftdi.spi import SpiController +from spilink import SPILink +from commands import * +from array import array + + +link = SPILink() +link.reset() # This doesn't work when cc-debugger is connected +link.flush() + +print(link.do_command(GetStateCommand())) +print(link.do_command(GetVersionCommand())) + +print(link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) + +#packet_data = bytes.fromhex("a965a5d1a8da65a5665715555555555555") +packet_data = [1,2,3,4,5,6,7,8,9] +send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=10) +print(link.do_command(send_cmd, timeout=5)) + +print(link.do_command(GetPacketCommand(timeout_ms=50000), timeout=50)) From 1bf8b43b7fd8803173fddc47927847580cf915b9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 19 Feb 2018 21:33:09 -0800 Subject: [PATCH 25/45] Add command to reset radio registers --- build-all.sh | 10 +++++----- commands.c | 9 +++++++++ radio.c | 3 ++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/build-all.sh b/build-all.sh index f38dbe7..e45aea9 100755 --- a/build-all.sh +++ b/build-all.sh @@ -9,7 +9,7 @@ set -e # USA: #make -f Makefile.uart1_alt2 #make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL -make -f Makefile.spi1_alt2 +make -f Makefile.spi1_alt2 # Worldwide: #make -f Makefile.uart1_alt2 RADIO_LOCALE=WW #make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW @@ -29,12 +29,12 @@ make -f Makefile.spi1_alt2 RADIO_LOCALE=WW # TI stick ############################################################################ # USA: -make -f Makefile.usb_ep0 +#make -f Makefile.usb_ep0 make -f Makefile.spi1_alt2 BOARD_TYPE=TI_DONGLE -make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER +#make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER # Worldwide: -make -f Makefile.usb_ep0 RADIO_LOCALE=WW +#make -f Makefile.usb_ep0 RADIO_LOCALE=WW make -f Makefile.spi1_alt2 BOARD_TYPE=TI_DONGLE RADIO_LOCALE=WW -make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER +#make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER exit 0 diff --git a/commands.c b/commands.c index cf7c46c..8808262 100644 --- a/commands.c +++ b/commands.c @@ -29,6 +29,7 @@ CommandHandler handlers[] = { /* 10 */ cmd_set_mode_registers, /* 11 */ cmd_set_sw_encoding, /* 12 */ cmd_set_preamble, + /* 13 */ cmd_reset_radio_config }; void do_cmd(uint8_t cmd) { @@ -227,3 +228,11 @@ void cmd_set_preamble() { serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_flush(); } + +void cmd_reset_radio_config() { + configure_radio(); + set_encoding_type(EncodingTypeNone); + radio_set_preamble(0); + serial_tx_byte(RESPONSE_CODE_SUCCESS); + serial_flush(); +} diff --git a/radio.c b/radio.c index 28a66d1..85d7c96 100644 --- a/radio.c +++ b/radio.c @@ -67,7 +67,8 @@ void configure_radio() MCSM2 = 0x07; MCSM1 = 0x30; MCSM0 = 0x18; // main radio control state machine configuration - FOCCFG = 0x17; // frequency offset compensation configuration BSCFG = 0x6C; + FOCCFG = 0x17; // frequency offset compensation configuration + BSCFG = 0x6C; // bit synchronization configuration FREND1 = 0xB6; // front end tx configuration FREND0 = 0x11; // front end tx configuration FSCAL3 = 0xE9; // frequency synthesizer calibration From f4263b4a540bf1b63099fd552c5b25369c542960 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 9 Apr 2018 22:10:31 -0700 Subject: [PATCH 26/45] Use fifo for serial buffers --- fifo.c | 2 +- fifo.h | 3 ++ main.c | 10 ++-- radio.c | 2 +- spi1_alt2/serial.c | 122 ++++++++++++++++----------------------------- 5 files changed, 53 insertions(+), 86 deletions(-) diff --git a/fifo.c b/fifo.c index e7d326c..8ff2f55 100644 --- a/fifo.c +++ b/fifo.c @@ -5,7 +5,7 @@ #include #include "fifo.h" -static volatile uint8_t fifo_count(fifo_buffer const *b) { +volatile uint8_t fifo_count(fifo_buffer const *b) { return (b ? (b->head - b->tail) : 0); } diff --git a/fifo.h b/fifo.h index 85497be..fd59031 100644 --- a/fifo.h +++ b/fifo.h @@ -28,4 +28,7 @@ bool fifo_put(fifo_buffer *b, uint8_t data_byte); /* size must be a power of 2 */ void fifo_init(fifo_buffer *b, volatile uint8_t *buffer, uint8_t size); + +volatile uint8_t fifo_count(fifo_buffer const *b); + #endif // FIFO_H diff --git a/main.c b/main.c index 3f01c87..4e42bcf 100644 --- a/main.c +++ b/main.c @@ -45,17 +45,17 @@ int main(void) init_timer(); EA = 1; + configure_serial(); + configure_radio(); + //LED test led_set_state(0, 1); //GREEN_LED = 1; - delay(200); + delay(100); led_set_state(0, 0); //GREEN_LED = 0; led_set_state(1, 1); //BLUE_LED = 1; - delay(200); + delay(100); led_set_state(1, 0); //BLUE_LED = 0; - configure_radio(); - configure_serial(); - while(1) { //led_set_state(0,2); get_command(); diff --git a/radio.c b/radio.c index 85d7c96..977c05c 100644 --- a/radio.c +++ b/radio.c @@ -202,7 +202,7 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t del mode_registers_enact(&tx_registers); - toggle_green(); + //toggle_green(); CHANNR = channel; diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index dec641b..5e38335 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -3,30 +3,26 @@ #include "hardware.h" #include "serial.h" #include "radio.h" +#include "fifo.h" -#define SPI_BUF_LEN 220 +#define SPI_BUF_LEN 128 -volatile uint8_t __xdata spi_input_buf[SPI_BUF_LEN]; -volatile uint8_t input_size = 0; -volatile uint8_t input_head_idx = 0; -volatile uint8_t input_tail_idx = 0; +static fifo_buffer __xdata input_buffer; +static volatile uint8_t __xdata input_buffer_mem[SPI_BUF_LEN]; -volatile uint8_t __xdata spi_output_buf[SPI_BUF_LEN]; -volatile uint8_t output_size = 0; -volatile uint8_t output_head_idx = 0; -volatile uint8_t output_tail_idx = 0; +static fifo_buffer __xdata output_buffer; +static volatile uint8_t __xdata output_buffer_mem[SPI_BUF_LEN]; volatile uint8_t ready_to_send = 0; volatile uint8_t serial_data_available; -volatile uint8_t transferring = 0; +volatile uint8_t xfer_remaining = 0; #define SPI_MODE_IDLE 0 -#define SPI_MODE_SKIP_NEXT_BYTE 1 -#define SPI_MODE_TX_SIZE 2 -#define SPI_MODE_RX_SIZE 3 -#define SPI_MODE_XFER 4 +#define SPI_MODE_TX_SIZE 1 +#define SPI_MODE_RX_SIZE 2 +#define SPI_MODE_XFER 3 volatile uint8_t spi_mode; volatile uint8_t master_send_size = 0; @@ -93,6 +89,10 @@ void configure_serial() IEN2 |= BIT3; // Enable UTX1IE interrupt U1DBUF = 0x44; + + // Initialize fifos + fifo_init(&input_buffer, input_buffer_mem, SPI_BUF_LEN); + fifo_init(&output_buffer, output_buffer_mem, SPI_BUF_LEN); } void rx1_isr(void) __interrupt URX1_VECTOR { @@ -102,6 +102,7 @@ void rx1_isr(void) __interrupt URX1_VECTOR { if (spi_mode == SPI_MODE_TX_SIZE) { if (value != 0x99) { // Error! + return; } spi_mode = SPI_MODE_RX_SIZE; return; @@ -111,29 +112,27 @@ void rx1_isr(void) __interrupt URX1_VECTOR { master_send_size = value; if (master_send_size > 0 || slave_send_size > 0) { spi_mode = SPI_MODE_XFER; + xfer_remaining = (slave_send_size > master_send_size) ? slave_send_size : master_send_size; IRCON2 |= BIT2; // Trigger UTX1IF } else { spi_mode = SPI_MODE_IDLE; - transferring = 0; + led_set_state(1, 0); //BLUE_LED = 0; } return; } - if (spi_mode == SPI_MODE_XFER && input_size < master_send_size) { - if (input_size < SPI_BUF_LEN) { - spi_input_buf[input_head_idx] = value; - input_head_idx++; - if (input_head_idx >= SPI_BUF_LEN) { - input_head_idx = 0; - } - input_size++; - if (input_size == master_send_size) { + if (spi_mode == SPI_MODE_XFER) { + if (fifo_count(&input_buffer) < master_send_size) { + fifo_put(&input_buffer, value); + if (fifo_count(&input_buffer) == master_send_size) { master_send_size = 0; serial_data_available = 1; } } - if (slave_send_size == 0 && master_send_size == 0) { + xfer_remaining--; + if (xfer_remaining == 0) { spi_mode = SPI_MODE_IDLE; + led_set_state(1, 0); //BLUE_LED = 0; } } } @@ -141,16 +140,11 @@ void rx1_isr(void) __interrupt URX1_VECTOR { void tx1_isr(void) __interrupt UTX1_VECTOR { IRCON2 &= ~BIT2; // Clear UTX1IF - if (spi_mode == SPI_MODE_SKIP_NEXT_BYTE) { - spi_mode = SPI_MODE_IDLE; - return; - } - if (spi_mode == SPI_MODE_IDLE) { if (ready_to_send) { - slave_send_size = output_size; - ready_to_send = 0; - U1DBUF = output_size; + slave_send_size = fifo_count(&output_buffer); + U1DBUF = slave_send_size; + led_set_state(1, 1); //BLUE_LED = 0; } else { U1DBUF = 0; } @@ -159,22 +153,10 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { } if (spi_mode == SPI_MODE_XFER) { - // The first byte we send here is pre-emptive; transfer hasn't started - // SPI transfer starts when SSN is selected - if (U0CSR & U0CSR_ACTIVE) { - transferring = 1; - } - - if (slave_send_size > 0 && output_size > 0) { - slave_send_size--; - U1DBUF = spi_output_buf[output_tail_idx]; - output_size--; - output_tail_idx++; - if (output_tail_idx >= SPI_BUF_LEN) { - output_tail_idx = 0; - } - if (output_size == 0 && master_send_size == 0) { - spi_mode = SPI_MODE_SKIP_NEXT_BYTE; + if (slave_send_size > 0) { + U1DBUF = fifo_get(&output_buffer); + if (fifo_empty(&output_buffer)) { + slave_send_size = 0; } } else { // Filler for when we are receiving data, but not sending anything @@ -187,19 +169,14 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { } uint8_t serial_rx_avail() { - return input_size; + return fifo_count(&input_buffer); } uint8_t serial_rx_byte() { uint8_t s_data; - while(!SERIAL_DATA_AVAILABLE); - s_data = spi_input_buf[input_tail_idx]; - input_tail_idx++; - if (input_tail_idx >= SPI_BUF_LEN) { - input_tail_idx = 0; - } - input_size--; - if (input_size == 0) { + while(!serial_data_available); + s_data = fifo_get(&input_buffer); + if (fifo_empty(&input_buffer)) { serial_data_available = 0; } return s_data; @@ -214,31 +191,18 @@ uint32_t serial_rx_long() { } void serial_tx_byte(uint8_t tx_byte) { - if (output_size >= SPI_BUF_LEN) { - // drop oldest byte - output_size--; - output_tail_idx++; - if (output_tail_idx >= SPI_BUF_LEN) { - output_tail_idx = 0; - } - } - spi_output_buf[output_head_idx] = tx_byte; - output_head_idx++; - if (output_head_idx >= SPI_BUF_LEN) { - output_head_idx = 0; - } - output_size++; + fifo_put(&output_buffer, tx_byte); } void serial_flush() { - ready_to_send = 1; - while(output_size > 0) { - if (transferring & !(U0CSR & U0CSR_ACTIVE)) { - // If SSN is deselected while transferring, treat as a cancel - // and flush out bytes manually until finished - IRCON2 |= BIT2; // Trigger UTX1IF - } + if (fifo_empty(&output_buffer)) { + return; } + ready_to_send = 1; + led_set_state(0, 1); //GREEN_LED = 0; + while(!fifo_empty(&output_buffer)); + led_set_state(0, 0); //GREEN_LED = 0; + ready_to_send = 0; } void serial_tx_str(const char *str) { From d44f479a7e2d8ce8a13fb377f713f4228f7c3ac3 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 11 Apr 2018 16:23:37 -0700 Subject: [PATCH 27/45] SPI comms update * Simplify SPI states * Recover from out-of-sync situation by paying attention to U1CSR.ACTIVE framing * Fix bug with repeat_count of 255 --- radio.c | 18 ++++---------- spi1_alt2/serial.c | 60 ++++++++++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/radio.c b/radio.c index 977c05c..4247dcc 100644 --- a/radio.c +++ b/radio.c @@ -193,7 +193,8 @@ void rf_isr(void) __interrupt RF_VECTOR { void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t delay_ms, uint16_t preamble_extend_ms, uint8_t len) { uint8_t s_byte; - uint8_t send_count = 0; + uint16_t send_count = 0; + uint16_t total_send_count = repeat_count + 1; Encoder encoder; EncoderState encoder_state; @@ -202,8 +203,6 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t del mode_registers_enact(&tx_registers); - //toggle_green(); - CHANNR = channel; radio_tx_buf_len = 0; @@ -218,8 +217,7 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t del } } - repeat_count += 1; - while(send_count < repeat_count) { + while(send_count < total_send_count) { // delay if (send_count > 0 && delay_ms > 0) { @@ -230,7 +228,6 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t del send_count++; } - //led_set_state(1,0); } void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { @@ -242,6 +239,7 @@ void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { pktlen_save = PKTLEN; pktctrl0_save = PKTCTRL0; + if (preamble_word != 0) { // save and turn off preamble/sync registers MDMCFG2 &= 0b11111100; // Disable PREAMBLE/SYNC @@ -270,12 +268,10 @@ void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { while(MARCSTATE!=MARC_STATE_TX); if (preamble_extend_ms > 0) { - led_set_state(1, 1); //BLUE_LED = 1; delay(preamble_extend_ms); if(preamble_word==0) { TCON |= 0b10; // Manually trigger RFTXRX vector. } - led_set_state(1, 0); //BLUE_LED = 0; } if (preamble_word != 0) { @@ -294,6 +290,7 @@ void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { PKTLEN = pktlen_save; MDMCFG2 = mdmcfg2_save; PKTCTRL0 = pktctrl0_save; + } uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uint8_t use_pktlen) { @@ -321,12 +318,10 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); - //led_set_state(1,1); while(1) { // Waiting for isr to put radio bytes into rx_fifo if (!fifo_empty(&rx_fifo)) { - //led_set_state(0,1); d_byte = fifo_get(&rx_fifo); read_idx++; @@ -352,14 +347,12 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin // Check for end of packet if (use_pktlen && read_idx == PKTLEN) { - //led_set_state(0,0); break; } } if (timeout_ms > 0 && timerCounter > timeout_ms) { rval = RESPONSE_CODE_RX_TIMEOUT; - //led_set_state(1,0); break; } @@ -373,7 +366,6 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin } } RFST = RFST_SIDLE; - //led_set_state(1,0); return rval; } diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 5e38335..99337ee 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -20,9 +20,8 @@ volatile uint8_t serial_data_available; volatile uint8_t xfer_remaining = 0; #define SPI_MODE_IDLE 0 -#define SPI_MODE_TX_SIZE 1 -#define SPI_MODE_RX_SIZE 2 -#define SPI_MODE_XFER 3 +#define SPI_MODE_SIZE 1 +#define SPI_MODE_XFER 2 volatile uint8_t spi_mode; volatile uint8_t master_send_size = 0; @@ -95,28 +94,44 @@ void configure_serial() fifo_init(&output_buffer, output_buffer_mem, SPI_BUF_LEN); } +void end_transfer() { + led_set_state(1, 0); //BLUE_LED = 0; + + // Disable interrupts + TCON &= ~BIT3; // Clear URX1IF + URX1IE = 0; // Disable URX1IE interrupt + IRCON2 &= ~BIT2; // Clear UTX1IF + IEN2 &= ~BIT3; // Disable UTX1IE interrupt + + while(U1CSR & U1CSR_ACTIVE); + + spi_mode = SPI_MODE_IDLE; + + // Enable interrupts + URX1IE = 1; // Enable URX1IE interrupt + IEN2 |= BIT3; // Enable UTX1IE interrupt +} + void rx1_isr(void) __interrupt URX1_VECTOR { uint8_t value; value = U1DBUF; - if (spi_mode == SPI_MODE_TX_SIZE) { + if (spi_mode == SPI_MODE_IDLE) { if (value != 0x99) { - // Error! - return; + end_transfer(); + } else { + spi_mode = SPI_MODE_SIZE; } - spi_mode = SPI_MODE_RX_SIZE; return; } - if (spi_mode == SPI_MODE_RX_SIZE) { + if (spi_mode == SPI_MODE_SIZE) { + spi_mode = SPI_MODE_XFER; master_send_size = value; if (master_send_size > 0 || slave_send_size > 0) { - spi_mode = SPI_MODE_XFER; xfer_remaining = (slave_send_size > master_send_size) ? slave_send_size : master_send_size; - IRCON2 |= BIT2; // Trigger UTX1IF } else { - spi_mode = SPI_MODE_IDLE; - led_set_state(1, 0); //BLUE_LED = 0; + end_transfer(); } return; } @@ -131,8 +146,7 @@ void rx1_isr(void) __interrupt URX1_VECTOR { } xfer_remaining--; if (xfer_remaining == 0) { - spi_mode = SPI_MODE_IDLE; - led_set_state(1, 0); //BLUE_LED = 0; + end_transfer(); } } } @@ -148,23 +162,17 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { } else { U1DBUF = 0; } - spi_mode = SPI_MODE_TX_SIZE; return; } - if (spi_mode == SPI_MODE_XFER) { - if (slave_send_size > 0) { - U1DBUF = fifo_get(&output_buffer); - if (fifo_empty(&output_buffer)) { - slave_send_size = 0; - } - } else { - // Filler for when we are receiving data, but not sending anything - U1DBUF = 0x98; + if (slave_send_size > 0) { + U1DBUF = fifo_get(&output_buffer); + if (fifo_empty(&output_buffer)) { + slave_send_size = 0; } } else { - // Filler - U1DBUF = 0x97; + // Filler for when we are receiving data, but not sending anything + U1DBUF = 0x98; } } From 457c858c026c06bbcbec6f615cec0d4676177029 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 11 Apr 2018 21:13:18 -0700 Subject: [PATCH 28/45] Sync to SSN in non ISR code --- spi1_alt2/serial.c | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 99337ee..72eb2bd 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -17,8 +17,6 @@ volatile uint8_t ready_to_send = 0; volatile uint8_t serial_data_available; -volatile uint8_t xfer_remaining = 0; - #define SPI_MODE_IDLE 0 #define SPI_MODE_SIZE 1 #define SPI_MODE_XFER 2 @@ -94,31 +92,14 @@ void configure_serial() fifo_init(&output_buffer, output_buffer_mem, SPI_BUF_LEN); } -void end_transfer() { - led_set_state(1, 0); //BLUE_LED = 0; - - // Disable interrupts - TCON &= ~BIT3; // Clear URX1IF - URX1IE = 0; // Disable URX1IE interrupt - IRCON2 &= ~BIT2; // Clear UTX1IF - IEN2 &= ~BIT3; // Disable UTX1IE interrupt - - while(U1CSR & U1CSR_ACTIVE); - - spi_mode = SPI_MODE_IDLE; - - // Enable interrupts - URX1IE = 1; // Enable URX1IE interrupt - IEN2 |= BIT3; // Enable UTX1IE interrupt -} - void rx1_isr(void) __interrupt URX1_VECTOR { uint8_t value; value = U1DBUF; if (spi_mode == SPI_MODE_IDLE) { if (value != 0x99) { - end_transfer(); + // TODO: record out-of-sync error + } else { spi_mode = SPI_MODE_SIZE; } @@ -128,10 +109,8 @@ void rx1_isr(void) __interrupt URX1_VECTOR { if (spi_mode == SPI_MODE_SIZE) { spi_mode = SPI_MODE_XFER; master_send_size = value; - if (master_send_size > 0 || slave_send_size > 0) { - xfer_remaining = (slave_send_size > master_send_size) ? slave_send_size : master_send_size; - } else { - end_transfer(); + if (master_send_size == 0 && slave_send_size == 0) { + spi_mode = SPI_MODE_IDLE; } return; } @@ -144,9 +123,8 @@ void rx1_isr(void) __interrupt URX1_VECTOR { serial_data_available = 1; } } - xfer_remaining--; - if (xfer_remaining == 0) { - end_transfer(); + if(master_send_size == 0 && slave_send_size == 0) { + spi_mode = SPI_MODE_IDLE; } } } @@ -158,7 +136,6 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { if (ready_to_send) { slave_send_size = fifo_count(&output_buffer); U1DBUF = slave_send_size; - led_set_state(1, 1); //BLUE_LED = 0; } else { U1DBUF = 0; } @@ -182,7 +159,11 @@ uint8_t serial_rx_avail() { uint8_t serial_rx_byte() { uint8_t s_data; - while(!serial_data_available); + if (!serial_data_available) { + while(!serial_data_available); + while(U1CSR & U1CSR_ACTIVE); + spi_mode = SPI_MODE_IDLE; + } s_data = fifo_get(&input_buffer); if (fifo_empty(&input_buffer)) { serial_data_available = 0; @@ -207,9 +188,9 @@ void serial_flush() { return; } ready_to_send = 1; - led_set_state(0, 1); //GREEN_LED = 0; + led_set_state(0, 1); //GREEN_LED; while(!fifo_empty(&output_buffer)); - led_set_state(0, 0); //GREEN_LED = 0; + led_set_state(0, 0); //GREEN_LED; ready_to_send = 0; } From e95b113e28380ce7f0609b04af3adcefb2e24382 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 16 Apr 2018 17:08:36 -0700 Subject: [PATCH 29/45] Use blue led for radio diagnostics --- radio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/radio.c b/radio.c index 4247dcc..89291d3 100644 --- a/radio.c +++ b/radio.c @@ -328,6 +328,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin // Send status code if (read_idx == 1) { + led_set_state(1, 1); //BLUE_LED; serial_tx_byte(RESPONSE_CODE_SUCCESS); } // First two bytes are rssi and packet # @@ -366,6 +367,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin } } RFST = RFST_SIDLE; + led_set_state(1, 0); //BLUE_LED; return rval; } From 1126d6fd2e865975589af89b744de876852b09d4 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 20 Apr 2018 00:08:12 -0500 Subject: [PATCH 30/45] Diagnostic leds (#50) * Clean up LED diagnostic code, and fix missing volatile keyword on rx_len * Show sdcc version * Revert to static for old sdcc on circleci; need to upgrade circleci build to xenial * Use enums instead of mystery values --- build-all.sh | 2 ++ hardware.c | 64 ++++++++++++++++++++++++---------------------- hardware.h | 49 ++++++++++++++++++++++------------- main.c | 15 ++++------- radio.c | 12 ++++++--- spi1_alt2/serial.c | 4 +-- timer.c | 2 +- usb_ep0/serial.c | 14 +++++----- 8 files changed, 90 insertions(+), 72 deletions(-) diff --git a/build-all.sh b/build-all.sh index e45aea9..d3418c7 100755 --- a/build-all.sh +++ b/build-all.sh @@ -3,6 +3,8 @@ set -x set -e +sdcc --version + ############################################################################ # Rileylink and similar ############################################################################ diff --git a/hardware.c b/hardware.c index d5dcf80..11637ee 100644 --- a/hardware.c +++ b/hardware.c @@ -7,55 +7,57 @@ #include "timer.h" #include "commands.h" -static uint8_t __xdata green_mode = 2; -static uint8_t __xdata blue_mode = 2; +static LEDMode green_mode = 0; +static LEDMode blue_mode = 0; -mode_registers __xdata tx_registers; -mode_registers __xdata rx_registers; +mode_registers tx_registers; +mode_registers rx_registers; -void led_set_mode(uint8_t led, uint8_t new_mode) +void init_leds() { + // init LEDS + HARDWARE_LED_INIT; // see hardware.h + GREEN_LED_PIN = 0; + BLUE_LED_PIN = 0; + + led_set_mode(GreenLED, LEDModeOff); + led_set_mode(BlueLED, LEDModeOff); +} + + +void led_set_mode(LEDNumber led, LEDMode new_mode) { - if(led == 0){ + if(led == GreenLED){ green_mode = new_mode; - if(new_mode != 2){ - GREEN_LED = new_mode; + if(new_mode == LEDModeOn) { + GREEN_LED_PIN = LEDStateOn; + } else if (new_mode == LEDModeOff) { + GREEN_LED_PIN = LEDStateOff; } } - else if(led == 1){ + else if(led == BlueLED){ blue_mode = new_mode; - if(new_mode != 2){ - BLUE_LED = new_mode; + if(new_mode == LEDModeOn) { + BLUE_LED_PIN = LEDStateOn; + } else if (new_mode == LEDModeOff) { + BLUE_LED_PIN = LEDStateOff; } } } -void led_set_state(uint8_t led, uint8_t command) +void led_set_diagnostic(LEDNumber led, LEDState state) { - if(led == 0){ - if(green_mode == 2){ - if(command < 2){ - GREEN_LED = command; - } + if(led == GreenLED){ + if(green_mode == LEDModeDiagnostic){ + GREEN_LED_PIN = state; } } - else if(led == 1){ - if(blue_mode == 2){ - if(command < 2){ - BLUE_LED = command; - } + else if(led == BlueLED){ + if(blue_mode == LEDModeDiagnostic){ + BLUE_LED_PIN = state; } } } -void toggle_green() { - GREEN_LED = !GREEN_LED; -} - -void toggle_blue() { - BLUE_LED = !BLUE_LED; -} - - uint8_t get_register(uint8_t addr) { uint8_t value; addr = serial_rx_byte(); diff --git a/hardware.h b/hardware.h index 5f7142c..1890bb4 100644 --- a/hardware.h +++ b/hardware.h @@ -19,44 +19,44 @@ #define HARDWARE_FLOW_CONTROL_CONFIG 0xc0; /* 8N1, hw flow control, high stop bit */ #define HARDWARE_LED_INIT P0DIR |= BIT0|BIT1; -#define GREEN_LED P0_0 -#define BLUE_LED P0_1 +#define GREEN_LED_PIN P0_0 +#define BLUE_LED_PIN P0_1 #define SYSTEM_CLOCK_MHZ 24 #elif EDISON_EXPLORER #define HARDWARE_FLOW_CONTROL_CONFIG 0xc0; /* 8N1, hw flow control, high stop bit */ #define HARDWARE_LED_INIT P2DIR |= BIT3|BIT4; -#define GREEN_LED P2_3 -#define BLUE_LED P2_4 +#define GREEN_LED_PIN P2_3 +#define BLUE_LED_PIN P2_4 #define SYSTEM_CLOCK_MHZ 24 #elif TI_DONGLE #define HARDWARE_LED_INIT P1DIR |= 2; -#define GREEN_LED P1_1 -#define BLUE_LED P1_1 +#define GREEN_LED_PIN P1_1 +#define BLUE_LED_PIN P1_1 #define SYSTEM_CLOCK_MHZ 24 #elif SRF_ERF #define HARDWARE_FLOW_CONTROL_CONFIG 0x02; /* 8N1, NO flow control, high stop bit */ #define HARDWARE_LED_INIT P1DIR |= BIT7; -#define GREEN_LED P1_7 -#define BLUE_LED P1_7 +#define GREEN_LED_PIN P1_7 +#define BLUE_LED_PIN P1_7 #define SYSTEM_CLOCK_MHZ 24 #elif SRF_STICK #define HARDWARE_FLOW_CONTROL_CONFIG 0x02; /* 8N1, NO flow control, high stop bit */ #define HARDWARE_LED_INIT P1DIR |= BIT7; -#define GREEN_LED P1_7 -#define BLUE_LED P1_6 +#define GREEN_LED_PIN P1_7 +#define BLUE_LED_PIN P1_6 #define SYSTEM_CLOCK_MHZ 24 #elif TI_MINIDEV #define HARDWARE_FLOW_CONTROL_CONFIG 0xc0; /* 8N1, hw flow control, high stop bit */ #define HARDWARE_LED_INIT P1DIR |= BIT0|BIT1; -#define GREEN_LED P1_0 -#define BLUE_LED P1_1 +#define GREEN_LED_PIN P1_0 +#define BLUE_LED_PIN P1_1 #define SYSTEM_CLOCK_MHZ 26 #endif @@ -72,12 +72,25 @@ typedef struct mode_registers { register_setting registers[MAX_MODE_REGISTERS]; } mode_registers; -void led_set_mode(uint8_t led, uint8_t new_mode); -void led_set_state(uint8_t led, uint8_t command); +typedef enum { + GreenLED = 0x00, + BlueLED = 0x01 +} LEDNumber; -void toggle_green(); -void toggle_blue(); +typedef enum { + LEDModeOff = 0x00, + LEDModeOn = 0x01, + LEDModeDiagnostic = 0x02 +} LEDMode; +typedef enum LEDState { + LEDStateOff = 0x00, + LEDStateOn = 0x01 +} LEDState; + +void init_leds(); +void led_set_mode(LEDNumber led, LEDMode new_mode); +void led_set_diagnostic(LEDNumber led, LEDState state); uint8_t get_register(uint8_t addr); uint8_t set_register(uint8_t addr, uint8_t value); @@ -86,7 +99,7 @@ void mode_registers_clear(mode_registers *mode); void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value); void mode_registers_enact(mode_registers const *mode); -extern mode_registers __xdata tx_registers; -extern mode_registers __xdata rx_registers; +extern mode_registers tx_registers; +extern mode_registers rx_registers; #endif diff --git a/main.c b/main.c index 4e42bcf..5d3fb32 100644 --- a/main.c +++ b/main.c @@ -35,11 +35,7 @@ int main(void) while (CLKCON & CLKCON_OSC); SLEEP |= SLEEP_OSC_PD; - - // init LEDS - HARDWARE_LED_INIT; // see hardware.h - led_set_state(0, 0); //GREEN_LED = 0; - led_set_state(1, 0); //BLUE_LED = 0; + init_leds(); // Global interrupt enable init_timer(); @@ -49,15 +45,14 @@ int main(void) configure_radio(); //LED test - led_set_state(0, 1); //GREEN_LED = 1; + GREEN_LED_PIN = 1; delay(100); - led_set_state(0, 0); //GREEN_LED = 0; - led_set_state(1, 1); //BLUE_LED = 1; + GREEN_LED_PIN = 0; + BLUE_LED_PIN = 1; delay(100); - led_set_state(1, 0); //BLUE_LED = 0; + BLUE_LED_PIN = 0; while(1) { - //led_set_state(0,2); get_command(); } } diff --git a/radio.c b/radio.c index 89291d3..7a9e0ba 100644 --- a/radio.c +++ b/radio.c @@ -13,7 +13,7 @@ static volatile uint8_t __xdata radio_rx_buf[RX_FIFO_SIZE]; static fifo_buffer __xdata rx_fifo; -static uint8_t __xdata rx_len; +static volatile uint8_t rx_len; static volatile uint8_t __xdata radio_tx_buf[TX_BUF_SIZE]; static volatile uint8_t __xdata radio_tx_buf_read_idx; @@ -328,7 +328,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin // Send status code if (read_idx == 1) { - led_set_state(1, 1); //BLUE_LED; + led_set_diagnostic(BlueLED, LEDStateOn); serial_tx_byte(RESPONSE_CODE_SUCCESS); } // First two bytes are rssi and packet # @@ -367,7 +367,13 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin } } RFST = RFST_SIDLE; - led_set_state(1, 0); //BLUE_LED; + while(MARCSTATE!=MARC_STATE_IDLE); + + while(!fifo_empty(&rx_fifo)) { + fifo_get(&rx_fifo); + } + + led_set_diagnostic(BlueLED, LEDStateOff); return rval; } diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 72eb2bd..3315cd6 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -188,9 +188,9 @@ void serial_flush() { return; } ready_to_send = 1; - led_set_state(0, 1); //GREEN_LED; + led_set_diagnostic(GreenLED, LEDStateOn); while(!fifo_empty(&output_buffer)); - led_set_state(0, 0); //GREEN_LED; + led_set_diagnostic(GreenLED, LEDStateOff); ready_to_send = 0; } diff --git a/timer.c b/timer.c index c77262b..2442156 100644 --- a/timer.c +++ b/timer.c @@ -47,7 +47,7 @@ void reset_timer() { void t1_isr(void) __interrupt T1_VECTOR { // if (timerCounter % 1000 == 0) { - // BLUE_LED = !BLUE_LED; + // BLUE_LED_PIN = !BLUE_LED_PIN; // } timerCounter++; } diff --git a/usb_ep0/serial.c b/usb_ep0/serial.c index 0c07fa8..beb36cd 100644 --- a/usb_ep0/serial.c +++ b/usb_ep0/serial.c @@ -12,13 +12,13 @@ void configure_serial() { setup_led( ); -// led_set_state(0,1); -// led_set_state(0,0); +// led_set_diagnostic(0,1); +// led_set_diagnostic(0,0); usb_init( ); usb_enable( ); usb_up( ); usb_flush( ); - /// GREEN_LED = 1; + /// GREEN_LED_PIN = 1; } @@ -27,10 +27,10 @@ uint8_t serial_has_bytes() usb_flush( ); if (usb_pollchar() == USB_READ_AGAIN) { -// led_set_state(0,0); +// led_set_diagnostic(0,0); return 0; } -// led_set_state(0,1); +// led_set_diagnostic(0,1); return 1; } @@ -51,9 +51,9 @@ uint32_t serial_rx_long() { void flush_serial( ) { -// led_set_state(0,2); +// led_set_diagnostic(0,2); usb_flush( ); -// led_set_state(0,2); +// led_set_diagnostic(0,2); } void serial_tx_byte(uint8_t tx_byte) { From dcc8f92aceff57b9158d9885466c51ae54d950b2 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 20 Apr 2018 00:11:51 -0500 Subject: [PATCH 31/45] Functions called from ISR should be reentrant (#51) --- fifo.c | 12 ++++++------ fifo.h | 10 +++++----- packet_buffer.c | 2 +- radio.c | 5 ++++- spi1_alt2/serial.c | 4 ++-- 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/fifo.c b/fifo.c index 8ff2f55..f7858af 100644 --- a/fifo.c +++ b/fifo.c @@ -5,26 +5,26 @@ #include #include "fifo.h" -volatile uint8_t fifo_count(fifo_buffer const *b) { +volatile uint8_t fifo_count(fifo_buffer const *b) __reentrant { return (b ? (b->head - b->tail) : 0); } -bool fifo_full(fifo_buffer const *b) { +bool fifo_full(fifo_buffer const *b) __reentrant { return (b ? (fifo_count(b) == b->buffer_len) : true); } -bool fifo_empty(fifo_buffer const *b) { +bool fifo_empty(fifo_buffer const *b) __reentrant { return (b ? (fifo_count(b) == 0) : true); } -uint8_t fifo_peek(fifo_buffer const *b) { +uint8_t fifo_peek(fifo_buffer const *b) __reentrant { if (b) { return (b->buffer[b->tail % b->buffer_len]); } return 0; } -uint8_t fifo_get(fifo_buffer * b) { +uint8_t fifo_get(fifo_buffer * b) __reentrant { uint8_t data_byte = 0; if (!fifo_empty(b)) { @@ -34,7 +34,7 @@ uint8_t fifo_get(fifo_buffer * b) { return data_byte; } -bool fifo_put(fifo_buffer * b, uint8_t data_byte) { +bool fifo_put(fifo_buffer * b, uint8_t data_byte) __reentrant { bool status = false; /* return value */ if (b) { diff --git a/fifo.h b/fifo.h index fd59031..8be7a78 100644 --- a/fifo.h +++ b/fifo.h @@ -15,15 +15,15 @@ struct fifo_buffer_t { }; typedef struct fifo_buffer_t fifo_buffer; -bool fifo_empty(fifo_buffer const *b); +bool fifo_empty(fifo_buffer const *b) __reentrant; -bool fifo_full(fifo_buffer const *b); +bool fifo_full(fifo_buffer const *b) __reentrant; -uint8_t fifo_peek(fifo_buffer const *b); +uint8_t fifo_peek(fifo_buffer const *b) __reentrant; -uint8_t fifo_get(fifo_buffer *b); +uint8_t fifo_get(fifo_buffer *b) __reentrant; -bool fifo_put(fifo_buffer *b, uint8_t data_byte); +bool fifo_put(fifo_buffer *b, uint8_t data_byte) __reentrant; /* size must be a power of 2 */ void fifo_init(fifo_buffer *b, volatile uint8_t *buffer, uint8_t size); diff --git a/packet_buffer.c b/packet_buffer.c index 518cae9..4b4a45b 100644 --- a/packet_buffer.c +++ b/packet_buffer.c @@ -17,7 +17,7 @@ static uint16_t __xdata packet_data_buf_tail; static uint16_t __xdata packet_data_buf_len; static uint8_t __xdata packet_lengths_head; static uint8_t __xdata packet_lengths_tail; -static uint8_t __xdata packet_count; +static volatile uint8_t __xdata packet_count; uint8_t enqueue_packet(const uint8_t *packet_data, uint16_t packet_len) { uint16_t i; diff --git a/radio.c b/radio.c index 7a9e0ba..f1eb144 100644 --- a/radio.c +++ b/radio.c @@ -1,5 +1,6 @@ #include +#include #include "hardware.h" #include "serial.h" #include "commands.h" @@ -114,7 +115,7 @@ bool set_encoding_type(EncodingType new_type) { } } -static void put_rx(uint8_t data) { +static void put_rx(uint8_t data) __reentrant { if (!fifo_put(&rx_fifo, data)) { rx_overflow++; } @@ -315,6 +316,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin CHANNR = channel; rx_len = 0; + memset(radio_rx_buf, 0x11, RX_FIFO_SIZE); RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); @@ -366,6 +368,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin break; } } + RFST = RFST_SIDLE; while(MARCSTATE!=MARC_STATE_IDLE); diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 3315cd6..c57b018 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -7,10 +7,10 @@ #define SPI_BUF_LEN 128 -static fifo_buffer __xdata input_buffer; +static volatile fifo_buffer __xdata input_buffer; static volatile uint8_t __xdata input_buffer_mem[SPI_BUF_LEN]; -static fifo_buffer __xdata output_buffer; +static volatile fifo_buffer __xdata output_buffer; static volatile uint8_t __xdata output_buffer_mem[SPI_BUF_LEN]; volatile uint8_t ready_to_send = 0; From c9abac14e542f026e2ed993653ca2c335e089b44 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 21 May 2018 20:42:28 -0500 Subject: [PATCH 32/45] Testing framework (#52) * added mock hardware register * Emulating timer * Avoid going to idle mode before spi transfer finishes. * Handle spi out of sync errors * No need to wait for CSR deselect * build on sdcc --- Makefile.spi1_alt2 | 4 + Makefile.test | 23 ++++++ commands.c | 58 ++++++------- commands.h | 16 ++++ common.mk | 19 +++-- encoding.h | 1 + fifo.h | 1 + hardware.h | 9 +- main.c | 42 ++-------- mock_hardware.c | 99 ++++++++++++++++++++++ mock_hardware.h | 104 +++++++++++++++++++++++ packet_buffer.c | 1 + radio.c | 4 +- spi1_alt2/serial.c | 49 +++++++---- spi1_alt2/serial.h | 2 + subg_rfspy.c | 46 +++++++++++ subg_rfspy.h | 11 +++ tests.c | 202 +++++++++++++++++++++++++++++++++++++++++++++ 18 files changed, 599 insertions(+), 92 deletions(-) create mode 100755 Makefile.test create mode 100644 mock_hardware.c create mode 100644 mock_hardware.h create mode 100644 subg_rfspy.c create mode 100644 subg_rfspy.h create mode 100644 tests.c diff --git a/Makefile.spi1_alt2 b/Makefile.spi1_alt2 index 9c5d037..7048483 100755 --- a/Makefile.spi1_alt2 +++ b/Makefile.spi1_alt2 @@ -4,4 +4,8 @@ SERIAL_PARAMS := -DUSES_USART1_TX_ISR -DUSES_USART1_RX_ISR BOARD_TYPE := RILEYLINK BOARD_PARAMS := +CC := sdcc + +main_module = main.rel + include common.mk diff --git a/Makefile.test b/Makefile.test new file mode 100755 index 0000000..8c5df3f --- /dev/null +++ b/Makefile.test @@ -0,0 +1,23 @@ +SERIAL_TYPE := spi1_alt2 +SERIAL_PARAMS := -DUSES_USART1_TX_ISR -DUSES_USART1_RX_ISR + +BOARD_TYPE := MOCK_HARDWARE +BOARD_PARAMS := + +CC := gcc + +CFLAGS+=-DRUN_TESTS -g -pthread + +LDFLAGS+=-g -pthread + +main_module = tests.rel + +extra_modules = mock_hardware.rel + +include common.mk + +output/${TARGET_BUILD}/check_subg_rfspy: $(common_modules) $(extra_modules) $(REL) serial.rel + cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(extra_modules) $(REL) serial.rel -o check_subg_rfspy + +test: output/${TARGET_BUILD}/check_subg_rfspy + output/${TARGET_BUILD}/check_subg_rfspy diff --git a/commands.c b/commands.c index 8808262..a98a614 100644 --- a/commands.c +++ b/commands.c @@ -15,34 +15,7 @@ uint8_t use_pktlen = 0; typedef void (*CommandHandler)(); -CommandHandler handlers[] = { - /* 0 */ 0, - /* 1 */ cmd_get_state, - /* 2 */ cmd_get_version, - /* 3 */ cmd_get_packet, - /* 4 */ cmd_send_packet, - /* 5 */ cmd_send_and_listen, - /* 6 */ cmd_update_register, - /* 7 */ cmd_reset, - /* 8 */ cmd_led, - /* 9 */ cmd_read_register, - /* 10 */ cmd_set_mode_registers, - /* 11 */ cmd_set_sw_encoding, - /* 12 */ cmd_set_preamble, - /* 13 */ cmd_reset_radio_config -}; - -void do_cmd(uint8_t cmd) { - if (cmd > 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { - handlers[cmd](); - } else { - while(serial_rx_avail() > 0) { - serial_rx_byte(); - } - serial_tx_byte(RESPONSE_CODE_UNKNOWN_COMMAND); - serial_flush(); - } -} +void do_cmd(uint8_t cmd); void get_command() { uint8_t cmd; @@ -236,3 +209,32 @@ void cmd_reset_radio_config() { serial_tx_byte(RESPONSE_CODE_SUCCESS); serial_flush(); } + +CommandHandler handlers[] = { + /* 0 */ 0, + /* 1 */ cmd_get_state, + /* 2 */ cmd_get_version, + /* 3 */ cmd_get_packet, + /* 4 */ cmd_send_packet, + /* 5 */ cmd_send_and_listen, + /* 6 */ cmd_update_register, + /* 7 */ cmd_reset, + /* 8 */ cmd_led, + /* 9 */ cmd_read_register, + /* 10 */ cmd_set_mode_registers, + /* 11 */ cmd_set_sw_encoding, + /* 12 */ cmd_set_preamble, + /* 13 */ cmd_reset_radio_config +}; + +void do_cmd(uint8_t cmd) { + if (cmd > 0 && cmd < sizeof(handlers)/sizeof(handlers[0])) { + handlers[cmd](); + } else { + while(serial_rx_avail() > 0) { + serial_rx_byte(); + } + serial_tx_byte(RESPONSE_CODE_UNKNOWN_COMMAND); + serial_flush(); + } +} diff --git a/commands.h b/commands.h index dd322c2..3488aad 100644 --- a/commands.h +++ b/commands.h @@ -7,6 +7,22 @@ #define RESPONSE_CODE_PARAM_ERROR 0x11 #define RESPONSE_CODE_UNKNOWN_COMMAND 0x22 +enum CommandCode { + CmdGetState = 0x01, + CmdGetVersion = 0x02, + CmdGetPacket = 0x03, + CmdSendPacket = 0x04, + CmdSendAndListen = 0x05, + CmdUpdateRegister = 0x06, + CmdReset = 0x07, + CmdLED = 0x08, + CmdReadRegister = 0x09, + CmdSetModeRegisters = 0x0a, + CmdSetSWEncoding = 0x0b, + CmdSetPreamble = 0x0c, + CmdResetRadioConfig = 0x0e +}; + enum RegisterMode { RegisterModeTx = 0x01, RegisterModeRx = 0x02 diff --git a/common.mk b/common.mk index 726ad84..985ed05 100755 --- a/common.mk +++ b/common.mk @@ -10,14 +10,18 @@ CODE_LOC_NAME := STDLOC TARGET_BUILD := ${SERIAL_TYPE}_${BOARD_TYPE}_${RADIO_LOCALE}_${CODE_LOC_NAME} -CC=sdcc +CC ?= sdcc -LDFLAGS=--xram-loc 0xf000 --model-medium --xram-size 0x1000 --code-loc ${CODE_LOC} --code-size 0x8000 -CFLAGS=-I. -I${SERIAL_TYPE} --model-medium --verbose ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} +ifeq ($(CC),sdcc) + LDFLAGS+=--xram-loc 0xf000 --model-medium --xram-size 0x1000 --code-loc ${CODE_LOC} --code-size 0x8000 + CFLAGS+=--model-medium --verbose +endif + +CFLAGS+=-I. -I${SERIAL_TYPE} ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} ${SERIAL_PARAMS} default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex -common_modules = radio.rel main.rel timer.rel encoding.rel manchester.rel \ +common_modules = $(main_module) subg_rfspy.rel radio.rel timer.rel encoding.rel manchester.rel \ fourbsixb.rel commands.rel hardware.rel packet_buffer.rel \ fifo.rel @@ -33,15 +37,12 @@ serial.rel: ${SERIAL_TYPE}/serial.c # ${REL} $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< $(REL) -output/${TARGET_BUILD}/${TARGET_BUILD}.hex: $(common_modules) $(REL) serial.rel - cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(REL) serial.rel -o ${TARGET_BUILD}.hex +output/${TARGET_BUILD}/${TARGET_BUILD}.hex: $(common_modules) $(extra_modules) $(REL) serial.rel + cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(extra_modules) $(REL) serial.rel -o ${TARGET_BUILD}.hex install: output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex sudo cc-tool -n ${TARGET_DEVICE} --log install.log -ew output/${TARGET_BUILD}/${TARGET_BUILD}.hex -test: main.c output - gcc -g -o output/${TARGET_BUILD}/test -DNON_NATIVE_TEST main.c - output: mkdir output diff --git a/encoding.h b/encoding.h index bb38016..66268dc 100644 --- a/encoding.h +++ b/encoding.h @@ -3,6 +3,7 @@ #include #include +#include "hardware.h" #include "manchester_state.h" #include "fourbsixb_state.h" diff --git a/fifo.h b/fifo.h index 8be7a78..b99d2e6 100644 --- a/fifo.h +++ b/fifo.h @@ -6,6 +6,7 @@ #include #include +#include "hardware.h" struct fifo_buffer_t { volatile uint8_t head; /* first byte of data */ diff --git a/hardware.h b/hardware.h index 1890bb4..c45d9dc 100644 --- a/hardware.h +++ b/hardware.h @@ -1,11 +1,16 @@ #ifndef HARDWARE_H #define HARDWARE_H -#ifndef NON_NATIVE_TEST +#ifdef MOCK_HARDWARE +#include "mock_hardware.h" +#else #include // /usr/share/sdcc/include/mcs51/cc1110.h -#include "ioCCxx10_bitdef.h" +#define U1DBUF_write U1DBUF +#define U1DBUF_read U1DBUF #endif +#include "ioCCxx10_bitdef.h" + #define BIT0 0x1 #define BIT1 0x2 #define BIT2 0x4 diff --git a/main.c b/main.c index 5d3fb32..eb5b353 100644 --- a/main.c +++ b/main.c @@ -1,13 +1,9 @@ -/* Control a cc1110 for sub-ghz RF comms over uart. */ -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" -#include "timer.h" -#include "commands.h" +#include +#include "subg_rfspy.h" -// SDCC needs prototypes of all ISR functions in main. not sure why, but described in section 3.8.1 +// All ISR functions must be present or included in the file that contains the +// function main, as described in SDCC manual section 3.8.1 void t1_isr(void) __interrupt T1_VECTOR; void rftxrx_isr(void) __interrupt RFTXRX_VECTOR; void rf_isr(void) __interrupt RF_VECTOR; @@ -26,33 +22,5 @@ void usb_isr() __interrupt 6; int main(void) { - - // Set the system clock source to HS XOSC and max CPU speed, - // ref. [clk]=>[clk_xosc.c] - SLEEP &= ~SLEEP_OSC_PD; - while( !(SLEEP & SLEEP_XOSC_S) ); - CLKCON = (CLKCON & ~(CLKCON_CLKSPD | CLKCON_OSC)) | CLKSPD_DIV_1; - while (CLKCON & CLKCON_OSC); - SLEEP |= SLEEP_OSC_PD; - - init_leds(); - - // Global interrupt enable - init_timer(); - EA = 1; - - configure_serial(); - configure_radio(); - - //LED test - GREEN_LED_PIN = 1; - delay(100); - GREEN_LED_PIN = 0; - BLUE_LED_PIN = 1; - delay(100); - BLUE_LED_PIN = 0; - - while(1) { - get_command(); - } + subg_rfspy_main(); } diff --git a/mock_hardware.c b/mock_hardware.c new file mode 100644 index 0000000..fa58371 --- /dev/null +++ b/mock_hardware.c @@ -0,0 +1,99 @@ + +#include +#include +#include +#include "hardware.h" + +volatile uint8_t P0_0; +volatile uint8_t P0_1; +volatile uint8_t P0DIR; +volatile uint8_t P1DIR; +volatile uint8_t P1SEL; +volatile uint8_t SYNC1; +volatile uint8_t SYNC0; +volatile uint8_t PKTLEN; +volatile uint8_t PKTCTRL1; +volatile uint8_t PKTCTRL0; +volatile uint8_t FSCTRL1; +volatile uint8_t FSCTRL0; +volatile uint8_t FSCTRL1; +volatile uint8_t MDMCFG4; +volatile uint8_t MDMCFG3; +volatile uint8_t MDMCFG2; +volatile uint8_t MDMCFG1; +volatile uint8_t MDMCFG0; +volatile uint8_t TEST1; +volatile uint8_t TEST0; +volatile uint8_t PA_TABLE1; +volatile uint8_t PA_TABLE0; +volatile uint8_t AGCCTRL2; +volatile uint8_t AGCCTRL1; +volatile uint8_t AGCCTRL0; +volatile uint8_t FREQ2; +volatile uint8_t FREQ1; +volatile uint8_t FREQ0; +volatile uint8_t CHANNR; +volatile uint8_t IEN2; +volatile uint8_t RFTXRXIE; +volatile uint8_t FSCAL3; +volatile uint8_t FSCAL2; +volatile uint8_t FSCAL1; +volatile uint8_t FREND1; +volatile uint8_t FREND0; +volatile uint8_t BSCFG; +volatile uint8_t DEVIATN; +volatile uint8_t MCSM2; +volatile uint8_t MCSM1; +volatile uint8_t MCSM0; +volatile uint8_t ADDR; +volatile uint8_t FOCCFG; +volatile uint8_t FSCAL0; +volatile uint8_t MARCSTATE; +volatile uint8_t RFD; +volatile uint8_t RSSI; +volatile uint8_t RFIF; +volatile uint8_t RFST; +volatile uint8_t S1CON; +volatile uint8_t TCON; +volatile uint8_t SLEEP = 0b00000100; +volatile uint8_t CLKCON; +volatile uint8_t EA; +volatile uint8_t T1CTL; +volatile uint8_t T1CNTH; +volatile uint8_t T1CNTL; +volatile uint8_t T1CCTL0; +volatile uint8_t T1CC0H; +volatile uint8_t T1CC0L; +volatile uint8_t TIMIF; +volatile uint8_t OVFIM; +volatile uint8_t T1IE; +volatile uint8_t WDCTL; +volatile uint8_t PERCFG; +volatile uint8_t U1CSR; +volatile uint8_t U1BAUD; +volatile uint8_t U1GCR; +volatile uint8_t URX1IE; +volatile uint8_t IRCON2; +volatile uint8_t U1DBUF_write; +volatile uint8_t U1DBUF_read; + +bool mock_hardware_should_exit; + +void *run_mock_hardware(void *vargp) { + + // Mark oscillator as powered up and stable + SLEEP |= SLEEP_XOSC_S; + + printf("starting mock hardware thread\n"); + + while(!mock_hardware_should_exit) { + // Run counter + if (T1CNTL == 255) { + T1CNTH += 1; + } + T1CNTL += 1; + t1_isr(); + //printf("SLEEP = %d\n", SLEEP); + } + return NULL; +} diff --git a/mock_hardware.h b/mock_hardware.h new file mode 100644 index 0000000..80c927e --- /dev/null +++ b/mock_hardware.h @@ -0,0 +1,104 @@ +#ifndef MOCK_HARDWARE_H +#define MOCK_HARDWARE_H + +#include +#include + +#define __reentrant +#define __xdata +#define __interrupt +#define RFTXRX_VECTOR +#define RF_VECTOR +#define T1_VECTOR +#define URX1_VECTOR +#define UTX1_VECTOR + +extern volatile uint8_t P0_0; +extern volatile uint8_t P0_1; +extern volatile uint8_t P0DIR; +extern volatile uint8_t P1DIR; +extern volatile uint8_t P1SEL; +extern volatile uint8_t SYNC1; +extern volatile uint8_t SYNC0; +extern volatile uint8_t PKTLEN; +extern volatile uint8_t PKTCTRL1; +extern volatile uint8_t PKTCTRL0; +extern volatile uint8_t FSCTRL1; +extern volatile uint8_t FSCTRL0; +extern volatile uint8_t FSCTRL1; +extern volatile uint8_t MDMCFG4; +extern volatile uint8_t MDMCFG3; +extern volatile uint8_t MDMCFG2; +extern volatile uint8_t MDMCFG1; +extern volatile uint8_t MDMCFG0; +extern volatile uint8_t TEST1; +extern volatile uint8_t TEST0; +extern volatile uint8_t PA_TABLE1; +extern volatile uint8_t PA_TABLE0; +extern volatile uint8_t AGCCTRL2; +extern volatile uint8_t AGCCTRL1; +extern volatile uint8_t AGCCTRL0; +extern volatile uint8_t FREQ2; +extern volatile uint8_t FREQ1; +extern volatile uint8_t FREQ0; +extern volatile uint8_t CHANNR; +extern volatile uint8_t IEN2; +extern volatile uint8_t IEN2_RFIE; +extern volatile uint8_t RFTXRXIE; +extern volatile uint8_t FSCAL3; +extern volatile uint8_t FSCAL2; +extern volatile uint8_t FSCAL1; +extern volatile uint8_t FREND1; +extern volatile uint8_t FREND0; +extern volatile uint8_t BSCFG; +extern volatile uint8_t DEVIATN; +extern volatile uint8_t MCSM2; +extern volatile uint8_t MCSM1; +extern volatile uint8_t MCSM0; +extern volatile uint8_t ADDR; +extern volatile uint8_t FOCCFG; +extern volatile uint8_t FSCAL0; +extern volatile uint8_t MARCSTATE; +extern volatile uint8_t RFD; +extern volatile uint8_t RSSI; +extern volatile uint8_t RFIF; +extern volatile uint8_t RFST; +extern volatile uint8_t S1CON; +extern volatile uint8_t TCON; +extern volatile uint8_t SLEEP; +extern volatile uint8_t CLKCON; +extern volatile uint8_t EA; +extern volatile uint8_t T1CTL; +extern volatile uint8_t T1CNTH; +extern volatile uint8_t T1CNTL; +extern volatile uint8_t T1CCTL0; +extern volatile uint8_t T1CC0H; +extern volatile uint8_t T1CC0L; +extern volatile uint8_t TIMIF; +extern volatile uint8_t OVFIM; +extern volatile uint8_t T1IE; +extern volatile uint8_t WDCTL; +extern volatile uint8_t PERCFG; +extern volatile uint8_t U1CSR; +extern volatile uint8_t U1BAUD; +extern volatile uint8_t U1GCR; +extern volatile uint8_t URX1IE; +extern volatile uint8_t IRCON2; +extern volatile uint8_t U1DBUF_write; +extern volatile uint8_t U1DBUF_read; + +#define GREEN_LED_PIN P0_0 +#define BLUE_LED_PIN P0_1 +#define SYSTEM_CLOCK_MHZ 24 +#define HARDWARE_LED_INIT P0DIR |= BIT0|BIT1; + +void *run_tests(void *vargp); +void *run_mock_hardware(void *vargp); + +void t1_isr(void); // Timer Interrupt +void tx1_isr(void); // UTX1_VECTOR +void rx1_isr(void); // URX1_VECTOR + +extern bool mock_hardware_should_exit; + +#endif diff --git a/packet_buffer.c b/packet_buffer.c index 4b4a45b..2830d91 100644 --- a/packet_buffer.c +++ b/packet_buffer.c @@ -1,4 +1,5 @@ #include +#include "hardware.h" // FIFO queue for packets diff --git a/radio.c b/radio.c index f1eb144..c94997b 100644 --- a/radio.c +++ b/radio.c @@ -167,6 +167,8 @@ void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { // Letting RFD go empty will make the radio stop TX mode. //RFD = 0; break; + case TxStatePreambleDefault: + break; } } @@ -316,7 +318,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin CHANNR = channel; rx_len = 0; - memset(radio_rx_buf, 0x11, RX_FIFO_SIZE); + memset((void*)radio_rx_buf, 0x11, RX_FIFO_SIZE); RFST = RFST_SRX; while(MARCSTATE!=MARC_STATE_RX); diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index c57b018..df5a759 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -1,16 +1,19 @@ #include +#include +#include #include "hardware.h" +#include "subg_rfspy.h" #include "serial.h" #include "radio.h" #include "fifo.h" #define SPI_BUF_LEN 128 -static volatile fifo_buffer __xdata input_buffer; +static fifo_buffer __xdata input_buffer; static volatile uint8_t __xdata input_buffer_mem[SPI_BUF_LEN]; -static volatile fifo_buffer __xdata output_buffer; +static fifo_buffer __xdata output_buffer; static volatile uint8_t __xdata output_buffer_mem[SPI_BUF_LEN]; volatile uint8_t ready_to_send = 0; @@ -20,10 +23,12 @@ volatile uint8_t serial_data_available; #define SPI_MODE_IDLE 0 #define SPI_MODE_SIZE 1 #define SPI_MODE_XFER 2 +#define SPI_MODE_OUT_OF_SYNC 3 volatile uint8_t spi_mode; volatile uint8_t master_send_size = 0; volatile uint8_t slave_send_size = 0; +volatile uint8_t xfer_size = 0; /*************************************************************************** @@ -85,7 +90,7 @@ void configure_serial() IRCON2 &= ~BIT2; // Clear UTX1IF IEN2 |= BIT3; // Enable UTX1IE interrupt - U1DBUF = 0x44; + U1DBUF_write = 0x44; // Initialize fifos fifo_init(&input_buffer, input_buffer_mem, SPI_BUF_LEN); @@ -94,12 +99,18 @@ void configure_serial() void rx1_isr(void) __interrupt URX1_VECTOR { uint8_t value; - value = U1DBUF; + value = U1DBUF_read; + + if (spi_mode == SPI_MODE_OUT_OF_SYNC) { + if (value == 0x99) { + spi_mode = SPI_MODE_SIZE; + } + return; + } if (spi_mode == SPI_MODE_IDLE) { if (value != 0x99) { - // TODO: record out-of-sync error - + spi_mode = SPI_MODE_OUT_OF_SYNC; } else { spi_mode = SPI_MODE_SIZE; } @@ -107,8 +118,16 @@ void rx1_isr(void) __interrupt URX1_VECTOR { } if (spi_mode == SPI_MODE_SIZE) { + if (value > SPI_BUF_LEN) { + spi_mode = SPI_MODE_OUT_OF_SYNC; + return; + } spi_mode = SPI_MODE_XFER; master_send_size = value; + xfer_size = master_send_size; + if (slave_send_size > xfer_size) { + xfer_size = slave_send_size; + } if (master_send_size == 0 && slave_send_size == 0) { spi_mode = SPI_MODE_IDLE; } @@ -123,7 +142,8 @@ void rx1_isr(void) __interrupt URX1_VECTOR { serial_data_available = 1; } } - if(master_send_size == 0 && slave_send_size == 0) { + xfer_size--; + if (xfer_size == 0) { spi_mode = SPI_MODE_IDLE; } } @@ -135,21 +155,21 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { if (spi_mode == SPI_MODE_IDLE) { if (ready_to_send) { slave_send_size = fifo_count(&output_buffer); - U1DBUF = slave_send_size; + U1DBUF_write = slave_send_size; } else { - U1DBUF = 0; + U1DBUF_write = 0; } return; } if (slave_send_size > 0) { - U1DBUF = fifo_get(&output_buffer); + U1DBUF_write = fifo_get(&output_buffer); if (fifo_empty(&output_buffer)) { slave_send_size = 0; } } else { // Filler for when we are receiving data, but not sending anything - U1DBUF = 0x98; + U1DBUF_write = 0x00; } } @@ -158,11 +178,10 @@ uint8_t serial_rx_avail() { } uint8_t serial_rx_byte() { + time_t last_time; uint8_t s_data; if (!serial_data_available) { - while(!serial_data_available); - while(U1CSR & U1CSR_ACTIVE); - spi_mode = SPI_MODE_IDLE; + while(!serial_data_available && !subg_rfspy_should_exit); } s_data = fifo_get(&input_buffer); if (fifo_empty(&input_buffer)) { @@ -189,7 +208,7 @@ void serial_flush() { } ready_to_send = 1; led_set_diagnostic(GreenLED, LEDStateOn); - while(!fifo_empty(&output_buffer)); + while(!fifo_empty(&output_buffer) && !subg_rfspy_should_exit); led_set_diagnostic(GreenLED, LEDStateOff); ready_to_send = 0; } diff --git a/spi1_alt2/serial.h b/spi1_alt2/serial.h index bbb0f25..2295f50 100644 --- a/spi1_alt2/serial.h +++ b/spi1_alt2/serial.h @@ -1,6 +1,8 @@ #ifndef SERIAL_H #define SERIAL_H +#include + #define SERIAL_DATA_AVAILABLE serial_data_available extern volatile uint8_t serial_data_available; diff --git a/subg_rfspy.c b/subg_rfspy.c new file mode 100644 index 0000000..fa09b7d --- /dev/null +++ b/subg_rfspy.c @@ -0,0 +1,46 @@ +/* Control a cc1110 for sub-ghz RF comms over uart. */ + +#include +#include +#include "hardware.h" +#include "serial.h" +#include "radio.h" +#include "timer.h" +#include "commands.h" +#include "subg_rfspy.h" + +bool subg_rfspy_init_finished; +bool subg_rfspy_should_exit; + +void subg_rfspy_main() { + // Set the system clock source to HS XOSC and max CPU speed, + // ref. [clk]=>[clk_xosc.c] + SLEEP &= ~SLEEP_OSC_PD; + while( !(SLEEP & SLEEP_XOSC_S) ); + CLKCON = (CLKCON & ~(CLKCON_CLKSPD | CLKCON_OSC)) | CLKSPD_DIV_1; + while (CLKCON & CLKCON_OSC); + SLEEP |= SLEEP_OSC_PD; + + init_leds(); + + // Global interrupt enable + init_timer(); + EA = 1; + + configure_serial(); + configure_radio(); + + //LED test + GREEN_LED_PIN = 1; + delay(100); + GREEN_LED_PIN = 0; + BLUE_LED_PIN = 1; + delay(100); + BLUE_LED_PIN = 0; + + subg_rfspy_init_finished = true; + + while(!subg_rfspy_should_exit) { + get_command(); + } +} diff --git a/subg_rfspy.h b/subg_rfspy.h new file mode 100644 index 0000000..1d75ecd --- /dev/null +++ b/subg_rfspy.h @@ -0,0 +1,11 @@ +#ifndef SUBG_RFSPY_H +#define SUBG_RFSPY_H + +#include + +void subg_rfspy_main(); + +extern bool subg_rfspy_init_finished; +extern bool subg_rfspy_should_exit; + +#endif // SUBG_RFSPY_H diff --git a/tests.c b/tests.c new file mode 100644 index 0000000..214be70 --- /dev/null +++ b/tests.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include "subg_rfspy.h" +#include "serial.h" +#include "commands.h" +#include "hardware.h" + +#define RESPONSE_BUFFER_SIZE 128 + +typedef struct { + uint8_t response_code; + uint8_t data[RESPONSE_BUFFER_SIZE]; + uint8_t response_length; + bool timed_out; +} CommandResponse; + +void hexprint(const char *prefix, const uint8_t *data, int len) +{ + printf("%s", prefix); + for (int i=0; i RESPONSE_BUFFER_SIZE) { + printf("Bad response size: %d\n", len); + len = RESPONSE_BUFFER_SIZE; + } + + uint8_t throwaway_rx_buf[RESPONSE_BUFFER_SIZE]; + + // if (input) { + // hexprint("tx: ", input, len); + // } else { + // printf("tx: NULL\n"); + // } + + if (output == NULL) { + output = throwaway_rx_buf; + } + + uint8_t slave_byte; + for (int i=0; i 0) { + printf("Unexpected response data while sending command\n"); + if (slave_bytes_avail > len) { + len = slave_bytes_avail; + } + } + do_spi(data, NULL, len); + while(max_xfer_cycles--) { + tmp[0] = 0x99; + tmp[1] = 0; + do_spi(tmp, tmp, 2); + if (tmp[1] > 0) { + response.response_length = tmp[1]; + do_spi(NULL, (uint8_t*)&response, response.response_length); + break; + } + // TODO: check timeout + } + if (max_xfer_cycles <= 0) { + response.timed_out = true; + } + return response; +} + +void check_version() +{ + uint8_t cmd = CmdGetVersion; + CommandResponse response; + response = run_command(1, &cmd, 20); + assert(!response.timed_out); + assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); +} + +void check_sync_error_extra_byte() +{ + CommandResponse response; + uint8_t tmp[1]; + + // Send extra byte (not conforming to protocol) + tmp[0] = 0x99; + do_spi(tmp, tmp, 1); + + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + // Expected behavior: timeout + assert(response.timed_out); + + // Should recover + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + assert(!response.timed_out); + assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); +} + +void check_sync_error_dropped_byte() +{ + CommandResponse response; + uint8_t tmp[3]; + + // Drop byte (not conforming to protocol) + // CmdUpdateRegister should be 3 bytes, but only send 2 + tmp[0] = CmdUpdateRegister; + tmp[1] = 1; // SYNC0 + tmp[2] = 0xff; + response = run_command(2, tmp, 20); + // Expected behavior: timeout + assert(response.timed_out); + + // one failure (this data finishes the previous update register command) + // subg_rfspy responds with success, since it received enough data for + // the update register command. But we're out of sync now. + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + assert(!response.timed_out); + assert(response.response_length == 1); + + // Recovery + tmp[0] = CmdGetVersion; + response = run_command(1, tmp, 20); + assert(!response.timed_out); + assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); +} + +void *run_main(void *vargp) { + printf("starting main thread\n"); + subg_rfspy_main(); + return NULL; +} + +int main(void) +{ + #ifdef MOCK_HARDWARE + pthread_t mock_hardware_thread; + pthread_create(&mock_hardware_thread, NULL, run_mock_hardware, NULL); + #endif + + #ifdef RUN_TESTS + pthread_t run_main_thread; + pthread_create(&run_main_thread, NULL, run_main, NULL); + #endif + + while(!subg_rfspy_init_finished); + + // Run tests! + check_version(); + check_sync_error_extra_byte(); + check_sync_error_dropped_byte(); + + subg_rfspy_should_exit = true; + pthread_join(run_main_thread, NULL); + + mock_hardware_should_exit = true; + pthread_join(mock_hardware_thread, NULL); + + // If we are here, all tests passed. + printf("Tests succeeded!\n"); +} From 34dd43f8241e706440f5cdf5aae766391cec344d Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 3 Jun 2018 20:13:03 -0700 Subject: [PATCH 33/45] Fix hang when sending extended preamble with default value --- radio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/radio.c b/radio.c index c94997b..ea56a9f 100644 --- a/radio.c +++ b/radio.c @@ -273,14 +273,13 @@ void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { if (preamble_extend_ms > 0) { delay(preamble_extend_ms); if(preamble_word==0) { + tx_state = TxStateData; TCON |= 0b10; // Manually trigger RFTXRX vector. } } if (preamble_word != 0) { stop_custom_preamble_semaphore = 1; - } else { - tx_state = TxStateData; } // wait for sending to finish From 5ea13815ccf2f1421c53a37b6136a7026b53c2ce Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 4 Jun 2018 13:59:45 -0500 Subject: [PATCH 34/45] Cmd interrupt fix (#53) * Fix hanging issue when a command is interrupted * Mark fifo_count as reentrant * Make fifo operations inline, and fix spi_mode state errors with one byte responses * Remove unused file --- common.mk | 3 +- fifo.c | 58 --------------------- fifo.h | 52 ++++++++++++++++--- mock_hardware.c | 16 ++++++ radio.c | 2 +- spi1_alt2/serial.c | 124 ++++++++++++++++++++++----------------------- tests.c | 53 +++++++++++++++++-- 7 files changed, 173 insertions(+), 135 deletions(-) delete mode 100644 fifo.c diff --git a/common.mk b/common.mk index 985ed05..d5ce81f 100755 --- a/common.mk +++ b/common.mk @@ -22,8 +22,7 @@ CFLAGS+=-I. -I${SERIAL_TYPE} ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex common_modules = $(main_module) subg_rfspy.rel radio.rel timer.rel encoding.rel manchester.rel \ - fourbsixb.rel commands.rel hardware.rel packet_buffer.rel \ - fifo.rel + fourbsixb.rel commands.rel hardware.rel packet_buffer.rel clean: rm -rf output/${TARGET_BUILD} diff --git a/fifo.c b/fifo.c deleted file mode 100644 index f7858af..0000000 --- a/fifo.c +++ /dev/null @@ -1,58 +0,0 @@ - - -#include -#include -#include -#include "fifo.h" - -volatile uint8_t fifo_count(fifo_buffer const *b) __reentrant { - return (b ? (b->head - b->tail) : 0); -} - -bool fifo_full(fifo_buffer const *b) __reentrant { - return (b ? (fifo_count(b) == b->buffer_len) : true); -} - -bool fifo_empty(fifo_buffer const *b) __reentrant { - return (b ? (fifo_count(b) == 0) : true); -} - -uint8_t fifo_peek(fifo_buffer const *b) __reentrant { - if (b) { - return (b->buffer[b->tail % b->buffer_len]); - } - return 0; -} - -uint8_t fifo_get(fifo_buffer * b) __reentrant { - uint8_t data_byte = 0; - - if (!fifo_empty(b)) { - data_byte = b->buffer[b->tail % b->buffer_len]; - b->tail++; - } - return data_byte; -} - -bool fifo_put(fifo_buffer * b, uint8_t data_byte) __reentrant { - bool status = false; /* return value */ - - if (b) { - /* limit the ring to prevent overwriting */ - if (!fifo_full(b)) { - b->buffer[b->head % b->buffer_len] = data_byte; - b->head++; - status = true; - } - } - return status; -} - -void fifo_init(fifo_buffer * b, volatile uint8_t *buffer, uint8_t size) { - if (b) { - b->head = 0; - b->tail = 0; - b->buffer = buffer; - b->buffer_len = size; - } -} diff --git a/fifo.h b/fifo.h index b99d2e6..29364e0 100644 --- a/fifo.h +++ b/fifo.h @@ -16,20 +16,56 @@ struct fifo_buffer_t { }; typedef struct fifo_buffer_t fifo_buffer; -bool fifo_empty(fifo_buffer const *b) __reentrant; +inline uint8_t fifo_count(fifo_buffer const *b) { + return (b ? (b->head - b->tail) : 0); +} -bool fifo_full(fifo_buffer const *b) __reentrant; +inline bool fifo_empty(fifo_buffer const *b) { + return (b ? (fifo_count(b) == 0) : true); +} -uint8_t fifo_peek(fifo_buffer const *b) __reentrant; +inline uint8_t fifo_get(fifo_buffer * b) { + uint8_t data_byte = 0; -uint8_t fifo_get(fifo_buffer *b) __reentrant; + if (!fifo_empty(b)) { + data_byte = b->buffer[b->tail % b->buffer_len]; + b->tail++; + } + return data_byte; +} -bool fifo_put(fifo_buffer *b, uint8_t data_byte) __reentrant; +inline bool fifo_full(fifo_buffer const *b) { + return (b ? (fifo_count(b) == b->buffer_len) : true); +} - /* size must be a power of 2 */ -void fifo_init(fifo_buffer *b, volatile uint8_t *buffer, uint8_t size); +inline uint8_t fifo_peek(fifo_buffer const *b) { + if (b) { + return (b->buffer[b->tail % b->buffer_len]); + } + return 0; +} +inline bool fifo_put(fifo_buffer * b, uint8_t data_byte) { + bool status = false; /* return value */ -volatile uint8_t fifo_count(fifo_buffer const *b); + if (b) { + /* limit the ring to prevent overwriting */ + if (!fifo_full(b)) { + b->buffer[b->head % b->buffer_len] = data_byte; + b->head++; + status = true; + } + } + return status; +} + +inline void fifo_init(fifo_buffer * b, volatile uint8_t *buffer, uint8_t size) { + if (b) { + b->head = 0; + b->tail = 0; + b->buffer = buffer; + b->buffer_len = size; + } +} #endif // FIFO_H diff --git a/mock_hardware.c b/mock_hardware.c index fa58371..553fc22 100644 --- a/mock_hardware.c +++ b/mock_hardware.c @@ -94,6 +94,22 @@ void *run_mock_hardware(void *vargp) { T1CNTL += 1; t1_isr(); //printf("SLEEP = %d\n", SLEEP); + + // Watch radio strobe registers + if(RFST == RFST_SIDLE) { + MARCSTATE = MARC_STATE_IDLE; + RFST = RFST_SNOP; + } + + if(RFST == RFST_SRX) { + MARCSTATE = MARC_STATE_RX; + RFST = RFST_SNOP; + } + + if(RFST == RFST_STX) { + MARCSTATE = MARC_STATE_TX; + RFST = RFST_SNOP; + } } return NULL; } diff --git a/radio.c b/radio.c index ea56a9f..b99979d 100644 --- a/radio.c +++ b/radio.c @@ -115,7 +115,7 @@ bool set_encoding_type(EncodingType new_type) { } } -static void put_rx(uint8_t data) __reentrant { +inline void put_rx(uint8_t data) { if (!fifo_put(&rx_fifo, data)) { rx_overflow++; } diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index df5a759..ee81335 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -1,6 +1,5 @@ #include -#include #include #include "hardware.h" #include "subg_rfspy.h" @@ -97,61 +96,63 @@ void configure_serial() fifo_init(&output_buffer, output_buffer_mem, SPI_BUF_LEN); } -void rx1_isr(void) __interrupt URX1_VECTOR { +void rx1_isr(void) __interrupt URX1_VECTOR +{ uint8_t value; value = U1DBUF_read; - if (spi_mode == SPI_MODE_OUT_OF_SYNC) { - if (value == 0x99) { - spi_mode = SPI_MODE_SIZE; - } - return; - } - - if (spi_mode == SPI_MODE_IDLE) { - if (value != 0x99) { - spi_mode = SPI_MODE_OUT_OF_SYNC; - } else { - spi_mode = SPI_MODE_SIZE; - } - return; - } - - if (spi_mode == SPI_MODE_SIZE) { - if (value > SPI_BUF_LEN) { - spi_mode = SPI_MODE_OUT_OF_SYNC; - return; - } - spi_mode = SPI_MODE_XFER; - master_send_size = value; - xfer_size = master_send_size; - if (slave_send_size > xfer_size) { - xfer_size = slave_send_size; - } - if (master_send_size == 0 && slave_send_size == 0) { - spi_mode = SPI_MODE_IDLE; - } - return; - } - - if (spi_mode == SPI_MODE_XFER) { - if (fifo_count(&input_buffer) < master_send_size) { - fifo_put(&input_buffer, value); - if (fifo_count(&input_buffer) == master_send_size) { - master_send_size = 0; - serial_data_available = 1; + switch(spi_mode) + { + case SPI_MODE_OUT_OF_SYNC: + if (value == 0x99) { + spi_mode = SPI_MODE_SIZE; } - } - xfer_size--; - if (xfer_size == 0) { - spi_mode = SPI_MODE_IDLE; - } + break; + case SPI_MODE_IDLE: + if (value != 0x99) { + spi_mode = SPI_MODE_OUT_OF_SYNC; + } else { + spi_mode = SPI_MODE_SIZE; + } + break; + case SPI_MODE_SIZE: + if (value > SPI_BUF_LEN) { + spi_mode = SPI_MODE_OUT_OF_SYNC; + return; + } + master_send_size = value; + xfer_size = master_send_size; + if (slave_send_size > xfer_size) { + xfer_size = slave_send_size; + } + if (xfer_size > 0) { + spi_mode = SPI_MODE_XFER; + } else { + spi_mode = SPI_MODE_IDLE; + } + break; + case SPI_MODE_XFER: + if(xfer_size > 0) { + if (fifo_count(&input_buffer) < master_send_size) { + fifo_put(&input_buffer, value); + if (fifo_count(&input_buffer) == master_send_size) { + master_send_size = 0; + serial_data_available = 1; + } + } + xfer_size--; + } + if (xfer_size == 0) { + slave_send_size = 0; + spi_mode = SPI_MODE_IDLE; + } + break; } } -void tx1_isr(void) __interrupt UTX1_VECTOR { +void tx1_isr(void) __interrupt UTX1_VECTOR +{ IRCON2 &= ~BIT2; // Clear UTX1IF - if (spi_mode == SPI_MODE_IDLE) { if (ready_to_send) { slave_send_size = fifo_count(&output_buffer); @@ -159,25 +160,22 @@ void tx1_isr(void) __interrupt UTX1_VECTOR { } else { U1DBUF_write = 0; } - return; } - - if (slave_send_size > 0) { + else if (slave_send_size > 0) { U1DBUF_write = fifo_get(&output_buffer); - if (fifo_empty(&output_buffer)) { - slave_send_size = 0; - } } else { // Filler for when we are receiving data, but not sending anything U1DBUF_write = 0x00; } } -uint8_t serial_rx_avail() { +uint8_t serial_rx_avail() +{ return fifo_count(&input_buffer); } -uint8_t serial_rx_byte() { +uint8_t serial_rx_byte() +{ time_t last_time; uint8_t s_data; if (!serial_data_available) { @@ -190,26 +188,28 @@ uint8_t serial_rx_byte() { return s_data; } -uint16_t serial_rx_word() { +uint16_t serial_rx_word() +{ return (serial_rx_byte() << 8) + serial_rx_byte(); } -uint32_t serial_rx_long() { +uint32_t serial_rx_long() +{ return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); } -void serial_tx_byte(uint8_t tx_byte) { +void serial_tx_byte(uint8_t tx_byte) +{ fifo_put(&output_buffer, tx_byte); } -void serial_flush() { +void serial_flush() +{ if (fifo_empty(&output_buffer)) { return; } ready_to_send = 1; - led_set_diagnostic(GreenLED, LEDStateOn); while(!fifo_empty(&output_buffer) && !subg_rfspy_should_exit); - led_set_diagnostic(GreenLED, LEDStateOff); ready_to_send = 0; } diff --git a/tests.c b/tests.c index 214be70..2a09b10 100644 --- a/tests.c +++ b/tests.c @@ -73,11 +73,8 @@ void do_spi(const uint8_t *input, uint8_t *output, uint8_t len) // } } -CommandResponse run_command(uint8_t len, const uint8_t *data, int max_xfer_cycles) +void send_command(uint8_t len, const uint8_t *data) { - CommandResponse response; - - memset(&response, 0, sizeof(CommandResponse)); uint8_t tmp[2]; tmp[0] = 0x99; tmp[1] = len; @@ -90,6 +87,12 @@ CommandResponse run_command(uint8_t len, const uint8_t *data, int max_xfer_cycle } } do_spi(data, NULL, len); +} + +CommandResponse wait_for_response(int max_xfer_cycles) { + CommandResponse response; + uint8_t tmp[2]; + memset(&response, 0, sizeof(CommandResponse)); while(max_xfer_cycles--) { tmp[0] = 0x99; tmp[1] = 0; @@ -107,6 +110,13 @@ CommandResponse run_command(uint8_t len, const uint8_t *data, int max_xfer_cycle return response; } + +CommandResponse run_command(uint8_t len, const uint8_t *data, int max_xfer_cycles) +{ + send_command(len, data); + return wait_for_response(max_xfer_cycles); +} + void check_version() { uint8_t cmd = CmdGetVersion; @@ -166,6 +176,40 @@ void check_sync_error_dropped_byte() assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); } +void check_interrupting_command() +{ + CommandResponse response; + uint8_t tmp[6]; + + // Send a listening command + tmp[0] = CmdGetPacket; + tmp[1] = 1; // channel + tmp[2] = 1; // timeout(4) + tmp[3] = 0; // timeout(3) + tmp[4] = 0; // timeout(2) + tmp[5] = 0; // timeout(1) + send_command(6, tmp); + + // Interrupt it with a set register command + tmp[0] = CmdUpdateRegister; + tmp[1] = 1; // SYNC0 + tmp[2] = 0xff; + send_command(3, tmp); + + response = wait_for_response(20); + + // Expected response: command interrupted + assert(!response.timed_out); + assert(response.response_code == RESPONSE_CODE_CMD_INTERRUPTED); + + response = wait_for_response(20); + + // Expected response: command successful + assert(!response.timed_out); + assert(response.response_code == RESPONSE_CODE_SUCCESS); +} + + void *run_main(void *vargp) { printf("starting main thread\n"); subg_rfspy_main(); @@ -190,6 +234,7 @@ int main(void) check_version(); check_sync_error_extra_byte(); check_sync_error_dropped_byte(); + check_interrupting_command(); subg_rfspy_should_exit = true; pthread_join(run_main_thread, NULL); From e66f9fd9551da35d49ccdfc43a45c8ebf17f28e9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 4 Jun 2018 22:35:55 -0700 Subject: [PATCH 35/45] Wait until xfer complete before flush is considered finished --- commands.h | 2 +- spi1_alt2/serial.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/commands.h b/commands.h index 3488aad..7ff4cf4 100644 --- a/commands.h +++ b/commands.h @@ -20,7 +20,7 @@ enum CommandCode { CmdSetModeRegisters = 0x0a, CmdSetSWEncoding = 0x0b, CmdSetPreamble = 0x0c, - CmdResetRadioConfig = 0x0e + CmdResetRadioConfig = 0x0d }; enum RegisterMode { diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index ee81335..67cd908 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -210,6 +210,7 @@ void serial_flush() } ready_to_send = 1; while(!fifo_empty(&output_buffer) && !subg_rfspy_should_exit); + while(slave_send_size != 0 && !subg_rfspy_should_exit); ready_to_send = 0; } From e16a117f938d05e0cddd2dfe754de2deb7e99c3f Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Thu, 7 Jun 2018 13:50:56 -0700 Subject: [PATCH 36/45] Bump version --- commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands.c b/commands.c index a98a614..b0675d1 100644 --- a/commands.c +++ b/commands.c @@ -96,7 +96,7 @@ void cmd_get_state() { void cmd_get_version() { serial_tx_byte(RESPONSE_CODE_SUCCESS); - serial_tx_str("subg_rfspy 2.0"); + serial_tx_str("subg_rfspy 2.1"); } void cmd_send_packet() { From 0cb6226b18617bd046d7384511223762f44f0347 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 16 Jun 2018 00:18:28 -0500 Subject: [PATCH 37/45] Get tests working on gcc again (#54) --- commands.c | 3 ++- fifo.h | 4 ++++ tests.c | 7 ++++--- version.h | 6 ++++++ 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 version.h diff --git a/commands.c b/commands.c index b0675d1..9d95da2 100644 --- a/commands.c +++ b/commands.c @@ -6,6 +6,7 @@ #include "radio.h" #include "commands.h" #include "encoding.h" +#include "version.h" uint8_t interrupting_cmd = 0; @@ -96,7 +97,7 @@ void cmd_get_state() { void cmd_get_version() { serial_tx_byte(RESPONSE_CODE_SUCCESS); - serial_tx_str("subg_rfspy 2.1"); + serial_tx_str(SUBG_RFSPY_VERSION); } void cmd_send_packet() { diff --git a/fifo.h b/fifo.h index 29364e0..f7e4762 100644 --- a/fifo.h +++ b/fifo.h @@ -8,6 +8,10 @@ #include #include "hardware.h" +#ifdef __GNUC__ +#define inline static inline +#endif + struct fifo_buffer_t { volatile uint8_t head; /* first byte of data */ volatile uint8_t tail; /* last byte of data */ diff --git a/tests.c b/tests.c index 2a09b10..db3a5de 100644 --- a/tests.c +++ b/tests.c @@ -7,6 +7,7 @@ #include "serial.h" #include "commands.h" #include "hardware.h" +#include "version.h" #define RESPONSE_BUFFER_SIZE 128 @@ -123,7 +124,7 @@ void check_version() CommandResponse response; response = run_command(1, &cmd, 20); assert(!response.timed_out); - assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); + assert(strcmp((const char*)response.data, SUBG_RFSPY_VERSION) == 0); } void check_sync_error_extra_byte() @@ -144,7 +145,7 @@ void check_sync_error_extra_byte() tmp[0] = CmdGetVersion; response = run_command(1, tmp, 20); assert(!response.timed_out); - assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); + assert(strcmp((const char*)response.data, SUBG_RFSPY_VERSION) == 0); } void check_sync_error_dropped_byte() @@ -173,7 +174,7 @@ void check_sync_error_dropped_byte() tmp[0] = CmdGetVersion; response = run_command(1, tmp, 20); assert(!response.timed_out); - assert(strcmp((const char*)response.data, "subg_rfspy 2.0") == 0); + assert(strcmp((const char*)response.data, SUBG_RFSPY_VERSION) == 0); } void check_interrupting_command() diff --git a/version.h b/version.h new file mode 100644 index 0000000..91cdbbc --- /dev/null +++ b/version.h @@ -0,0 +1,6 @@ +#ifndef VERSION_H +#define VERSION_H + +#define SUBG_RFSPY_VERSION "subg_rfspy 2.1" + +#endif //VERSION_H From dfc7818e21520ef9302e02de99978c6b7c12b63a Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sat, 16 Jun 2018 00:18:36 -0500 Subject: [PATCH 38/45] Handle new 2.0 firmware protocol changes (#55) --- client/commands.py | 57 +++++++++++++++++++++++++++++----------------- client/spilink.py | 36 ++++++++++++++++++++++------- client/test.py | 23 +++++++++++-------- 3 files changed, 78 insertions(+), 38 deletions(-) diff --git a/client/commands.py b/client/commands.py index e24d584..faf6f83 100644 --- a/client/commands.py +++ b/client/commands.py @@ -2,49 +2,63 @@ from struct import * from enum import Enum -class ErrorCode(Enum): +class ResponseCode(Enum): PROTOCOL_SYNC = 0x00 + UNKNOWN_COMMAND = 0x22 RX_TIMEOUT = 0xaa COMMAND_INTERRUPTED = 0xbb - + COMMAND_SUCCESS = 0xdd + +class CommandCode(Enum): + GET_STATE = 1 + GET_VERSION = 2 + GET_PACKET = 3 + SEND_PACKET = 4 + SEND_AND_LISTEN = 5 + UPDATE_REGISTER = 6 + RESET = 7 + LED = 8 + READ_REGISTER = 9 + SET_MODE_REGISTERS = 10 + SET_SW_ENCODING = 11 + SET_PREAMBLE = 12 + RADIO_RESET_CONFIG = 13 class ByteResponse: def __init__(self, response_data): - if len(response_data) > 1: - raise ValueError - self.response_byte = array('B', response_data)[0] + self.response_code = ResponseCode(response_data[0]) + self.response_data = bytearray(response_data[1:]) def __repr__(self): - return "ByteResponse(\"%d\")" % self.response_byte + return "ByteResponse(%s, %s)" % (self.response_code, self.response_data.hex()) class StringResponse: def __init__(self, response_data): - self.response_data = array('B', response_data) + self.response_code = ResponseCode(response_data[0]) + self.response_data = array('B', response_data[1:]) def __repr__(self): return "StringResponse(\"%s\")" % self.response_data.tostring().decode("UTF-8") class PacketResponse: def __init__(self, response_data): - self.error_code = None - if len(response_data) < 2: - self.error_code = ErrorCode(response_data[0]) - else: - self.rssi_dec = response_data[0] - self.packet_num = response_data[1] - self.response_data = array('B', response_data[2:]) + self.response_code = ResponseCode(response_data[0]) + if self.response_code == ResponseCode.COMMAND_SUCCESS: + self.rssi_dec = response_data[1] + self.packet_num = response_data[2] + self.response_data = array('B', response_data[3:]) def __repr__(self): - if self.error_code: - return "PacketErrorResponse(%s)" % self.error_code.name + if self.response_code != ResponseCode.COMMAND_SUCCESS: + return "ResponseCode(%s)" % self.response_code else: hex = "".join(["%02x" % x for x in self.response_data]) return "PacketResponse(\"%s\")" % hex class GetStateCommand: def data(self): - return array('B', [1]) + return array('B', [CommandCode.GET_STATE.value]) def response_type(self): return StringResponse @@ -62,7 +76,7 @@ def __init__(self, timeout_ms=100, channel=0): self.timeout_ms = timeout_ms def data(self): - data = pack('>BBL', 3, self.channel, self.timeout_ms) + data = pack('>BBL', CommandCode.GET_PACKET.value, self.channel, self.timeout_ms) return array('B', data) def response_type(self): @@ -77,7 +91,8 @@ def __init__(self, packet_data, repeat_count=0, delay_ms=5, preamble_extend_ms=0 self.packet_data = packet_data def data(self): - conf = pack('>BBBHH', 4, self.channel, self.repeat_count, self.delay_ms, self.preamble_extend_ms) + conf = pack('>BBBHH', CommandCode.SEND_PACKET.value, self.channel, self.repeat_count, self.delay_ms, self.preamble_extend_ms) + print("Send packet cmd: %s" % conf.hex()) return array('B', conf) + self.packet_data def response_type(self): @@ -120,7 +135,7 @@ def __init__(self, register, value): self.value = value def data(self): - return array('B', [6, self.register.value, self.value]) + return array('B', [CommandCode.UPDATE_REGISTER.value, self.register.value, self.value]) def response_type(self): return ByteResponse @@ -136,7 +151,7 @@ def __init__(self, encoding): self.encoding = encoding def data(self): - return array('B', [11, self.encoding.value]) + return array('B', [CommandCode.SET_SW_ENCODING.value, self.encoding.value]) def response_type(self): return ByteResponse diff --git a/client/spilink.py b/client/spilink.py index 5b032c7..0c2db1e 100644 --- a/client/spilink.py +++ b/client/spilink.py @@ -18,7 +18,7 @@ def __init__(self, device='ftdi://ftdi:232h/1', debug=False): self.spi = self.ctrl.get_port(cs=0, freq=100000) self.gpio = self.ctrl.get_gpio() direction = self.gpio.direction - self.gpio.set_direction(0x30, 0x10) + self.gpio.set_direction(0x30, 0x10) # Add reset as output self.gpio.write(0x10) def reset(self): @@ -50,18 +50,30 @@ def exchange(self, data, readlen=0): lsb_rcv = self.spi.exchange(lsb_send,readlen=readlen, duplex=True) return self.reverse_bits(lsb_rcv) - def do_command(self, command, timeout=1): - end_time = time.time() + timeout + def send_command(self, command): data = command.data() + if len(data) == 0: + print("Empty command!") + return + if self.debug: print("send: %s" % self.as_hex(data)) response = None + _, available = self.exchange([0x99, len(data)], readlen=2) + if available > 0: + print("Unexpected data available from client while sending command.") + return + self.exchange(data, readlen=0) + + def wait_for_response(self, response_type, timeout=1): + end_time = time.time() + timeout + response = None while(time.time() < end_time and response == None): - _, available = self.exchange([0x99, len(data)], readlen=2) - if (len(data) > 0 or available > 0): + _, available = self.exchange([0x99, 0], readlen=2) + if (available > 0): if self.debug: - print("size exchange: master = %d, slave = %d" % (len(data), available)) - rdata = self.exchange(data, readlen=available) + print("response: available = %d" % available) + rdata = self.exchange([], readlen=available) else: time.sleep(0.01) if available > 0: @@ -70,12 +82,20 @@ def do_command(self, command, timeout=1): if response == None: raise SPITimeout() - response_type = command.response_type() if self.debug: print("recv: %s" % self.as_hex(response)) response_obj = response_type(response) return response_obj + def do_command(self, command, timeout=1): + self.send_command(command) + response = self.wait_for_response(command.response_type(), timeout) + if response.response_code != ResponseCode.COMMAND_INTERRUPTED: + return response + else: + print("Command interrupted...") + return self.wait_for_response(command.response_type(), timeout) + def update_register(self, register, value): return self.do_command(UpdateRegisterCommand(register, value)) diff --git a/client/test.py b/client/test.py index 29b0ba9..7798d0b 100644 --- a/client/test.py +++ b/client/test.py @@ -2,20 +2,25 @@ from spilink import SPILink from commands import * from array import array +import time - -link = SPILink() +link = SPILink(debug=True) link.reset() # This doesn't work when cc-debugger is connected -link.flush() +#link.flush() -print(link.do_command(GetStateCommand())) -print(link.do_command(GetVersionCommand())) +print("GetState:", link.do_command(GetStateCommand())) +print("GetVersion:", link.do_command(GetVersionCommand())) -print(link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) +print("SetSoftwareEncoding:", link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) #packet_data = bytes.fromhex("a965a5d1a8da65a5665715555555555555") packet_data = [1,2,3,4,5,6,7,8,9] -send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=10) -print(link.do_command(send_cmd, timeout=5)) +send_cmd = SendPacketCommand(array('B', packet_data), repeat_count=2, preamble_extend_ms=1) +print("SendPacket:", link.do_command(send_cmd, timeout=5)) + -print(link.do_command(GetPacketCommand(timeout_ms=50000), timeout=50)) +# Issue a longer listening command, and interrupt it +link.send_command(GetPacketCommand(timeout_ms=50000)) +time.sleep(0.1) +print("SetSoftwareEncoding:", link.do_command(SetSoftwareEncoding(Encoding.FOURBSIXB))) +print("GetVersionCommand:", link.do_command(GetVersionCommand())) From a65451bffaf31ac373fd4b17ce665d64dc3283e9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 22 Jun 2018 05:24:50 -0500 Subject: [PATCH 39/45] Travis ci (#57) * Adding travis build config * trigger build * trigger build * Run tests in docker container * Ensure output directory exists * Add sdcc build and break tests on purpose * Fix test * Add build status to readme * Log spi comms in tests --- .travis.yml | 10 ++++++++++ Makefile.test | 5 ++++- Readme.md | 2 ++ circle.yml | 16 ---------------- tests.c | 37 +++++++++++++++++++++++-------------- 5 files changed, 39 insertions(+), 31 deletions(-) create mode 100644 .travis.yml delete mode 100644 circle.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..26caf4f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +sudo: required +services: + - docker + +before_install: + - docker pull ps2docker/sdcc_docker + +script: + - docker run -v `pwd`:/subg_rfspy ps2docker/sdcc_docker /bin/sh -c "cd /subg_rfspy; make -f Makefile.test test" + - docker run -v `pwd`:/subg_rfspy ps2docker/sdcc_docker /bin/sh -c "cd /subg_rfspy; make -f Makefile.spi1_alt2" diff --git a/Makefile.test b/Makefile.test index 8c5df3f..2fadb6b 100755 --- a/Makefile.test +++ b/Makefile.test @@ -16,8 +16,11 @@ extra_modules = mock_hardware.rel include common.mk +output/${TARGET_BUILD}: + mkdir output/${TARGET_BUILD} + output/${TARGET_BUILD}/check_subg_rfspy: $(common_modules) $(extra_modules) $(REL) serial.rel cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(extra_modules) $(REL) serial.rel -o check_subg_rfspy -test: output/${TARGET_BUILD}/check_subg_rfspy +test: output/${TARGET_BUILD} output/${TARGET_BUILD}/check_subg_rfspy output/${TARGET_BUILD}/check_subg_rfspy diff --git a/Readme.md b/Readme.md index a29d71e..8b97c62 100644 --- a/Readme.md +++ b/Readme.md @@ -1,5 +1,7 @@ # subg_rfspy +[![Build Status](https://travis-ci.org/ps2/subg_rfspy.svg?branch=master)](https://travis-ci.org/ps2/subg_rfspy) + ## Pre-Requisites for Building subg_rfspy [sdcc] (http://sdcc.sourceforge.net/) package is required for this build. diff --git a/circle.yml b/circle.yml deleted file mode 100644 index cea9b9e..0000000 --- a/circle.yml +++ /dev/null @@ -1,16 +0,0 @@ -test: - override: - - ./build-all.sh - -dependencies: - pre: - - sudo apt-get install -y sdcc - - go get github.com/tcnksm/ghr - -deployment: - release: - branch: master - commands: - - mkdir -p output/`git describe --tags`/ - - mv output/*/*.hex output/`git describe --tags`/ - - cd output ; ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME --replace `git describe --tags` `git describe --tags`/ diff --git a/tests.c b/tests.c index db3a5de..c5cce0c 100644 --- a/tests.c +++ b/tests.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "subg_rfspy.h" #include "serial.h" #include "commands.h" @@ -45,11 +46,11 @@ void do_spi(const uint8_t *input, uint8_t *output, uint8_t len) uint8_t throwaway_rx_buf[RESPONSE_BUFFER_SIZE]; - // if (input) { - // hexprint("tx: ", input, len); - // } else { - // printf("tx: NULL\n"); - // } + if (input) { + hexprint("tx: ", input, len); + } else { + printf("tx: NULL\n"); + } if (output == NULL) { output = throwaway_rx_buf; @@ -67,11 +68,11 @@ void do_spi(const uint8_t *input, uint8_t *output, uint8_t len) tiny_sleep(); } - // if (output) { - // hexprint("rx: ", output, len); - // } else { - // printf("rx: NULL\n"); - // } + if (output) { + hexprint("rx: ", output, len); + } else { + printf("rx: NULL\n"); + } } void send_command(uint8_t len, const uint8_t *data) @@ -118,6 +119,14 @@ CommandResponse run_command(uint8_t len, const uint8_t *data, int max_xfer_cycle return wait_for_response(max_xfer_cycles); } +bool equal(int expected, int actual, const char *desc) +{ + if (expected != actual) { + fprintf(stderr, "Expected %s to equal %d, but was %d instead.\n", desc, expected, actual); + } + return expected == actual; +} + void check_version() { uint8_t cmd = CmdGetVersion; @@ -168,7 +177,7 @@ void check_sync_error_dropped_byte() tmp[0] = CmdGetVersion; response = run_command(1, tmp, 20); assert(!response.timed_out); - assert(response.response_length == 1); + assert(equal(1, response.response_length, "response.response_length")); // Recovery tmp[0] = CmdGetVersion; @@ -182,7 +191,7 @@ void check_interrupting_command() CommandResponse response; uint8_t tmp[6]; - // Send a listening command + // Send a listening command (4s timeout) tmp[0] = CmdGetPacket; tmp[1] = 1; // channel tmp[2] = 1; // timeout(4) @@ -201,13 +210,13 @@ void check_interrupting_command() // Expected response: command interrupted assert(!response.timed_out); - assert(response.response_code == RESPONSE_CODE_CMD_INTERRUPTED); + assert(equal(RESPONSE_CODE_CMD_INTERRUPTED, response.response_code, "response.response_code")); response = wait_for_response(20); // Expected response: command successful assert(!response.timed_out); - assert(response.response_code == RESPONSE_CODE_SUCCESS); + assert(equal(RESPONSE_CODE_SUCCESS, response.response_code, "response.response_code")); } From 8d2b94a65b4a1a033d30d2647ed6a6fa6ba815f9 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 22 Jun 2018 06:32:48 -0500 Subject: [PATCH 40/45] Interrupt-safe timer helpers (#56) --- radio.c | 7 +++++-- timer.c | 18 +++++++----------- timer.h | 22 ++++++++++++++++++++-- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/radio.c b/radio.c index b99979d..c9be8f4 100644 --- a/radio.c +++ b/radio.c @@ -301,11 +301,14 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin uint8_t d_byte = 0; uint8_t rval = 0; uint8_t encoding_error = 0; + uint32_t timer_start; Decoder __xdata decoder; DecoderState __xdata decoder_state; - reset_timer(); + if (timeout_ms > 0) { + read_timer(&timer_start); + } mode_registers_enact(&rx_registers); @@ -355,7 +358,7 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin } } - if (timeout_ms > 0 && timerCounter > timeout_ms) { + if (timeout_ms > 0 && check_elapsed(timer_start, timeout_ms)) { rval = RESPONSE_CODE_RX_TIMEOUT; break; } diff --git a/timer.c b/timer.c index 2442156..919c86d 100644 --- a/timer.c +++ b/timer.c @@ -1,8 +1,9 @@ #include #include "hardware.h" +#include "timer.h" -volatile uint32_t timerCounter = 0; +volatile uint32_t __timerCounter = 0; void init_timer() { union { @@ -14,6 +15,8 @@ void init_timer() { // 1000 is scaling mhz to cycles/msec, 128 is T1CTL.DIV, 2 is TICKSPD uint16_t timer_ticks_per_ms = (SYSTEM_CLOCK_MHZ * 1000) / 128 / 2; + __timerCounter = 0; + T1CTL = 0x00; // disable timer T1CNTL = 0x00; // Clear counter low @@ -40,20 +43,13 @@ void init_timer() { T1CTL = 0x0e; // TickFreq/128, modulo } -void reset_timer() { - timerCounter = 0; -} - void t1_isr(void) __interrupt T1_VECTOR { - // if (timerCounter % 1000 == 0) { - // BLUE_LED_PIN = !BLUE_LED_PIN; - // } - timerCounter++; + __timerCounter++; } void delay(uint32_t msec) { uint32_t start_time; - start_time = timerCounter; - while(timerCounter - start_time < msec); + read_timer(&start_time); + while(!check_elapsed(start_time, msec)); } diff --git a/timer.h b/timer.h index 8f08f6c..e26c112 100644 --- a/timer.h +++ b/timer.h @@ -1,10 +1,28 @@ #ifndef TIMER_H #define TIMER_H -volatile extern uint32_t timerCounter; +#include +#include + +volatile extern uint32_t __timerCounter; void init_timer(); -void reset_timer(); + void delay(uint32_t msec); +inline void read_timer(uint32_t *result) { + EA = 0; + *result = __timerCounter; + EA = 1; +} + +// Returns true if time has elapsed +inline bool check_elapsed(uint32_t start_time, uint32_t duration) { + bool rval; + EA = 0; + rval = (__timerCounter - start_time) > duration; + EA = 1; + return rval; +} + #endif From 32b3db70c2f3bbd0d784af0f28969b17e91873e2 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 22 Jun 2018 06:33:18 -0500 Subject: [PATCH 41/45] Remove old files, and update readme (#58) * Remove old files, and update readme * Avoid error on mkdir when directory already exists * remove tiny_sleep in tests --- Makefile.test | 2 +- Makefile.uart0_alt1 | 7 - Makefile.uart1_alt2 | 7 - Makefile.usb_ep0 | 37 - Readme.md | 39 +- build-all.sh | 42 -- tests.c | 2 +- uart0_alt1/serial.c | 64 -- uart0_alt1/serial.h | 15 - uart1_alt2/serial.c | 104 --- uart1_alt2/serial.h | 17 - usb_ep0/cc1111.h | 1389 ------------------------------------- usb_ep0/hal.c | 56 -- usb_ep0/hal.h | 30 - usb_ep0/serial.c | 73 -- usb_ep0/serial.h | 15 - usb_ep0/usb.c | 440 ------------ usb_ep0/usb.h | 142 ---- usb_ep0/usb_descriptors.c | 148 ---- 19 files changed, 14 insertions(+), 2615 deletions(-) delete mode 100755 Makefile.uart0_alt1 delete mode 100755 Makefile.uart1_alt2 delete mode 100755 Makefile.usb_ep0 delete mode 100755 build-all.sh delete mode 100644 uart0_alt1/serial.c delete mode 100644 uart0_alt1/serial.h delete mode 100644 uart1_alt2/serial.c delete mode 100644 uart1_alt2/serial.h delete mode 100644 usb_ep0/cc1111.h delete mode 100644 usb_ep0/hal.c delete mode 100644 usb_ep0/hal.h delete mode 100644 usb_ep0/serial.c delete mode 100644 usb_ep0/serial.h delete mode 100644 usb_ep0/usb.c delete mode 100644 usb_ep0/usb.h delete mode 100644 usb_ep0/usb_descriptors.c diff --git a/Makefile.test b/Makefile.test index 2fadb6b..05b098d 100755 --- a/Makefile.test +++ b/Makefile.test @@ -17,7 +17,7 @@ extra_modules = mock_hardware.rel include common.mk output/${TARGET_BUILD}: - mkdir output/${TARGET_BUILD} + mkdir -p output/${TARGET_BUILD} output/${TARGET_BUILD}/check_subg_rfspy: $(common_modules) $(extra_modules) $(REL) serial.rel cd output/${TARGET_BUILD} && $(CC) $(LDFLAGS) $(CFLAGS) $(common_modules) $(extra_modules) $(REL) serial.rel -o check_subg_rfspy diff --git a/Makefile.uart0_alt1 b/Makefile.uart0_alt1 deleted file mode 100755 index 79a7795..0000000 --- a/Makefile.uart0_alt1 +++ /dev/null @@ -1,7 +0,0 @@ -SERIAL_TYPE := uart0_alt1 -SERIAL_PARAMS := - -BOARD_TYPE := RILEYLINK -BOARD_PARAMS := - -include common.mk diff --git a/Makefile.uart1_alt2 b/Makefile.uart1_alt2 deleted file mode 100755 index 35a89c3..0000000 --- a/Makefile.uart1_alt2 +++ /dev/null @@ -1,7 +0,0 @@ -SERIAL_TYPE := uart1_alt2 -SERIAL_PARAMS := -DUSES_USART1_RX_ISR - -BOARD_TYPE := RILEYLINK -BOARD_PARAMS := - -include common.mk diff --git a/Makefile.usb_ep0 b/Makefile.usb_ep0 deleted file mode 100755 index 744d671..0000000 --- a/Makefile.usb_ep0 +++ /dev/null @@ -1,37 +0,0 @@ -SERIAL_TYPE := usb_ep0 -SERIAL_PARAMS := -DUSES_USB - -BOARD_TYPE := TI_DONGLE -BOARD_PARAMS := -DTI_DONGLE - -TARGET_DEVICE := CC1111 - - -SRC = \ - hal.c \ - usb.c \ - usb_descriptors.c - -ADB=$(SRC:.c=.adb) -ASM=$(SRC:.c=.asm) -LNK=$(SRC:.c=.lnk) -LST=$(SRC:.c=.lst) -REL=$(SRC:.c=.rel) -RST=$(SRC:.c=.rst) -SYM=$(SRC:.c=.sym) - -PCDB=$(PROGS:.hex=.cdb) -PLNK=$(PROGS:.hex=.lnk) -PMAP=$(PROGS:.hex=.map) -PMEM=$(PROGS:.hex=.mem) -PAOM=$(PROGS:.hex=) -include common.mk - -hal.rel: ${SERIAL_TYPE}/hal.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< - -usb_descriptors.rel: ${SERIAL_TYPE}/usb_descriptors.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< -usb.rel: ${SERIAL_TYPE}/usb.c - $(CC) $(CFLAGS) -o output/${TARGET_BUILD}/$@ -c $< - diff --git a/Readme.md b/Readme.md index 8b97c62..f00cb0f 100644 --- a/Readme.md +++ b/Readme.md @@ -4,28 +4,29 @@ ## Pre-Requisites for Building subg_rfspy -[sdcc] (http://sdcc.sourceforge.net/) package is required for this build. - - sudo apt-get install sdcc +[sdcc] (http://sdcc.sourceforge.net/) version >= 3.7.0 is required for this build. There is a [docker image](https://hub.docker.com/r/ps2docker/sdcc_docker/) available for this purpose. It's also possible to build it under Windows. The best way to do this is to: -1. install SDCC +1. install SDCC version 3.7.0 2. install Cygwin 3. use Cygwin to install make 4. Use cygwin bash to build the project -# Building - -You'll need to select a build type, like `spi1_alt2`. The examples below use this value, but you'll want to use the correct one for your hardware and use case. See below for different hardware types and use cases. +To install, you'll need [cc-tool](https://github.com/dashesy/cc-tool) -Perform the build. The output file will be stored at output/uart0_alt1_RILEYLINK_US/uart0_alt1_RILEYLINK_US.hex +# Building and Installing - make -f Makefile.spi1_alt2 +``` +make -f Makefile.spi1_alt2 install -Perform the install: +``` - make -f Makefile.spi1_alt2 install +# Building and Installing using docker +``` +docker run -v `pwd`:/subg_rfspy ps2docker/sdcc_docker /bin/sh -c "cd /subg_rfspy; make -f Makefile.spi1_alt2 +cc-tool -n CC1110 --log install.log -ew output/spi1_alt2_RILEYLINK_US_STDLOC/spi1_alt2_RILEYLINK_US_STDLOC.hex +``` # Radio Frequency Selection @@ -33,10 +34,6 @@ This code defaults to building firmware that is tuned to 916.5 Mhz. You can also make -f Makefile.spi1_alt2 RADIO_LOCALE=WW -# RileyLink - -If you are using a [RileyLink](https://github.com/ps2/rileylink) via the onboard bluetooth module (which should be loaded with ble_rfspy), then you'll want to use `spi1_alt2` as your build type. - # Protocol See [protocol.md](protocol.md) @@ -49,18 +46,6 @@ See [protocol.md](protocol.md) Serial support is no longer supported. See [serial.md](serial.md) for historical information. -## Frequency Channel Selection - -Each channel number corresponds to a different specific frequency. Channels start with 916.5 MHz at -Channel 0 and end with 934.4 MHz at Channel 255, in steps of about 0.07 MHz. You can select different -channels by adjusting the CHANNR.CHAN register. Available channels are governed by the following equation: - -`f_carrier = (24MHz/(2^16))*(FREQ + CHAN(256 + CHANSPC_M)*2^(CHANSPC_E - 2))` - -The base frequency, FREQ, is set by the FREQ2, FREQ1, and FREQ0 registers. The value default value is -2502768 (0x263070). -CHANSPC_M and CHANSPC_E are used to set the channel spacing, and are contained in the registers MDMCFG0 -and MDMCFG1 (bits 1:0), respectively. Their default values are 126 (0x7E) and 1. ## Supported Registers diff --git a/build-all.sh b/build-all.sh deleted file mode 100755 index d3418c7..0000000 --- a/build-all.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -set -x -set -e - -sdcc --version - -############################################################################ -# Rileylink and similar -############################################################################ -# USA: -#make -f Makefile.uart1_alt2 -#make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL -make -f Makefile.spi1_alt2 -# Worldwide: -#make -f Makefile.uart1_alt2 RADIO_LOCALE=WW -#make -f Makefile.uart1_alt2 CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW -make -f Makefile.spi1_alt2 RADIO_LOCALE=WW - -############################################################################ -# ERF stick -############################################################################ -# USA: -#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF -#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL -# Worldwide: -#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF RADIO_LOCALE=WW -#make -f Makefile.uart0_alt1 BOARD_TYPE=SRF_ERF CODE_LOC=0x400 CODE_LOC_NAME=CCTL RADIO_LOCALE=WW - -############################################################################ -# TI stick -############################################################################ -# USA: -#make -f Makefile.usb_ep0 -make -f Makefile.spi1_alt2 BOARD_TYPE=TI_DONGLE -#make -f Makefile.usb_ep0 CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER -# Worldwide: -#make -f Makefile.usb_ep0 RADIO_LOCALE=WW -make -f Makefile.spi1_alt2 BOARD_TYPE=TI_DONGLE RADIO_LOCALE=WW -#make -f Makefile.usb_ep0 RADIO_LOCALE=WW CODE_LOC=0x1400 CODE_LOC_NAME=CCBOOTLOADER - -exit 0 diff --git a/tests.c b/tests.c index c5cce0c..48dba27 100644 --- a/tests.c +++ b/tests.c @@ -65,7 +65,7 @@ void do_spi(const uint8_t *input, uint8_t *output, uint8_t len) output[i] = slave_byte; } rx1_isr(); - tiny_sleep(); + //tiny_sleep(); } if (output) { diff --git a/uart0_alt1/serial.c b/uart0_alt1/serial.c deleted file mode 100644 index 77b2dca..0000000 --- a/uart0_alt1/serial.c +++ /dev/null @@ -1,64 +0,0 @@ - -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" - -void configure_serial() -{ - - // UART0 Alt. 1 - // P0.2 - RX - // P0.3 - TX - // P0.4 - CT - // P0.5 - RT - - U0CSR |= 0x80; // UART Mode - PERCFG &= ~0x01; // Alternative 1 - P0SEL |= 0x3C; // P0.5 -> P0.2 - P1SEL &= ~0x3C; - - /////////////////////////////////////////////////////////////// - // Initialize bitrate (U0BAUD.BAUD_M, U0GCR.BAUD_E) - // Bitrate 19200 - U0BAUD = 163; - U0GCR = (U0GCR&~0x1F) | 9; - U0UCR |= HARDWARE_FLOW_CONTROL_CONFIG; // Flush, and configure hw flow control - - // Enable receive - U0CSR |= 0x40; - URX0IF = 0; - -} - -uint8_t serial_rx_byte() { - uint8_t s_data; - while(!SERIAL_DATA_AVAILABLE); // URX0IF - s_data = U0DBUF; - URX0IF = 0; - return s_data; -} - -uint16_t serial_rx_word() { - return (serial_rx_byte() << 8) + serial_rx_byte(); -} - -uint32_t serial_rx_long() { - return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); -} - - -void serial_tx_byte(uint8_t tx_byte) { - UTX0IF = 0; - U0DBUF = tx_byte; - while ( !UTX0IF ); - UTX0IF = 0; -} - -void serial_tx_str(const char *str) { - while(*str != 0) { - serial_tx_byte(*str); - str++; - } - serial_tx_byte(0); -} diff --git a/uart0_alt1/serial.h b/uart0_alt1/serial.h deleted file mode 100644 index 46a4f21..0000000 --- a/uart0_alt1/serial.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SERIAL_H -#define SERIAL_H - -// Needs to be updated with some kind of framing, to support packets with 0's in them -#error "This serial configuration no longer supported." - -#define SERIAL_DATA_AVAILABLE URX0IF - -void configure_serial(); -void serial_tx_byte(uint8_t); -void serial_tx_str(const char *str); -uint8_t serial_rx_byte(); -uint32_t serial_rx_long(); - -#endif diff --git a/uart1_alt2/serial.c b/uart1_alt2/serial.c deleted file mode 100644 index c237009..0000000 --- a/uart1_alt2/serial.c +++ /dev/null @@ -1,104 +0,0 @@ - -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" - -#define SERIAL_BUF_LEN 220 - -volatile uint8_t __xdata serial_input_buf[SERIAL_BUF_LEN]; -volatile uint8_t input_size = 0; -volatile uint8_t input_head_idx = 0; -volatile uint8_t input_tail_idx = 0; - -volatile uint8_t __xdata serial_output_buf[SERIAL_BUF_LEN]; -volatile uint8_t output_size = 0; -volatile uint8_t output_head_idx = 0; -volatile uint8_t output_tail_idx = 0; - -volatile uint8_t ready_to_send = 0; - -volatile uint8_t serial_data_available; - -void configure_serial() -{ - // UART1 Alt. 2 - // P1.4 - CT - // P1.5 - RT - // P1.6 - TX - // P1.7 - RX - - U1CSR |= 0x80; // UART Mode - PERCFG |= 0x02; // Alternative 2 - P1SEL |= 0xf0; // P1.7 -> P1.4 - P0SEL &= ~0x3c; - - /////////////////////////////////////////////////////////////// - // Initialize bitrate (U1BAUD.BAUD_M, U1GCR.BAUD_E) - // Bitrate 19200 -#if SYSTEM_CLOCK_MHZ == 26 - U1BAUD = 131; -#else - U1BAUD = 163; -#endif - U1GCR = (U0GCR&~0x1F) | 9; - U1UCR |= HARDWARE_FLOW_CONTROL_CONFIG; // Flush, and configure hw flow control - - // Enable receive - U1CSR |= 0x40; - URX1IF = 0; - IEN0 |= 0x88; -} - -void rx1_isr(void) __interrupt URX1_VECTOR { - URX1IF = 0; - if (input_size < SERIAL_BUF_LEN) { - serial_input_buf[input_head_idx] = U1DBUF; - input_head_idx++; - if (input_head_idx >= SERIAL_BUF_LEN) { - input_head_idx = 0; - } - input_size++; - serial_data_available = 1; - } else { - // overflow - } -} - -uint8_t serial_rx_byte() { - uint8_t s_data; - while(!SERIAL_DATA_AVAILABLE); // URX1IF - s_data = serial_input_buf[input_tail_idx]; - input_tail_idx++; - if (input_tail_idx >= SERIAL_BUF_LEN) { - input_tail_idx = 0; - } - input_size--; - if (input_size == 0) { - serial_data_available = 0; - } - return s_data; -} - -uint16_t serial_rx_word() { - return (serial_rx_byte() << 8) + serial_rx_byte(); -} - -uint32_t serial_rx_long() { - return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); -} - -void serial_tx_byte(uint8_t tx_byte) { - UTX1IF = 0; - U1DBUF = tx_byte; - while ( !UTX1IF ); - UTX1IF = 0; -} - -void serial_tx_str(const char *str) { - while(*str != 0) { - serial_tx_byte(*str); - str++; - } - serial_tx_byte(0); -} diff --git a/uart1_alt2/serial.h b/uart1_alt2/serial.h deleted file mode 100644 index b53338a..0000000 --- a/uart1_alt2/serial.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SERIAL_H -#define SERIAL_H - -// Needs to be updated with some kind of framing, to support packets with 0's in them -#error "This serial configuration no longer supported." - -#define SERIAL_DATA_AVAILABLE serial_data_available - -extern volatile uint8_t serial_data_available; - -void configure_serial(); -void serial_tx_byte(uint8_t); -void serial_tx_str(const char *str); -uint8_t serial_rx_byte(); -uint32_t serial_rx_long(); - -#endif diff --git a/usb_ep0/cc1111.h b/usb_ep0/cc1111.h deleted file mode 100644 index ac1e71c..0000000 --- a/usb_ep0/cc1111.h +++ /dev/null @@ -1,1389 +0,0 @@ -/*------------------------------------------------------------------------- - Register Declarations for the ChipCon CC1111 Processor Range - - Copyright © 2008 Keith Packard - - 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; version 2 of the License. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - - Adapted from the Cygnal C8051F12x config file which is: - - Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --------------------------------------------------------------------------*/ - -#ifndef _CC1111_H_ -#define _CC1111_H_ -#include -#include - -__sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ - -__sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -__sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ -__sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ -__sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -__sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -__sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -__sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ -__sbit __at 0xAF EA; /* Enable All */ - -#define IEN0_EA (1 << 7) -#define IEN0_STIE (1 << 5) -#define IEN0_ENCIE (1 << 4) -#define IEN0_URX1IE (1 << 3) -#define IEN0_I2SRXIE (1 << 3) -#define IEN0_URX0IE (1 << 2) -#define IEN0_ADCIE (1 << 1) -#define IEN0_RFTXRXIE (1 << 0) - -__sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ - -#define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ -#define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ -#define IEN1_T3IE (1 << 3) /* Timer 3 interrupt enable */ -#define IEN1_T2IE (1 << 2) /* Timer 2 interrupt enable */ -#define IEN1_T1IE (1 << 1) /* Timer 1 interrupt enable */ -#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ - -/* IEN2 */ -__sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ - -#define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ -#define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ -#define IEN2_UTX1IE (1 << 3) /* USART1 TX interrupt enable */ -#define IEN2_I2STXIE (1 << 3) /* I2S TX interrupt enable */ -#define IEN2_UTX0IE (1 << 2) /* USART0 TX interrupt enable */ -#define IEN2_P2IE (1 << 1) /* Port 2 interrupt enable */ -#define IEN2_USBIE (1 << 1) /* USB interrupt enable */ -#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ - -/* CLKCON 0xC6 */ -__sfr __at 0xC6 CLKCON; /* Clock Control */ - -#define CLKCON_OSC32K_RC (1 << 7) -#define CLKCON_OSC32K_XTAL (0 << 7) -#define CLKCON_OSC32K_MASK (1 << 7) -#define CLKCON_OSC_RC (1 << 6) -#define CLKCON_OSC_XTAL (0 << 6) -#define CLKCON_OSC_MASK (1 << 6) -#define CLKCON_TICKSPD_MASK (7 << 3) -# define CLKCON_TICKSPD_1 (0 << 3) -# define CLKCON_TICKSPD_1_2 (1 << 3) -# define CLKCON_TICKSPD_1_4 (2 << 3) -# define CLKCON_TICKSPD_1_8 (3 << 3) -# define CLKCON_TICKSPD_1_16 (4 << 3) -# define CLKCON_TICKSPD_1_32 (5 << 3) -# define CLKCON_TICKSPD_1_64 (6 << 3) -# define CLKCON_TICKSPD_1_128 (7 << 3) - -#define CLKCON_CLKSPD_MASK (7 << 0) -# define CLKCON_CLKSPD_1 (0 << 0) -# define CLKCON_CLKSPD_1_2 (1 << 0) -# define CLKCON_CLKSPD_1_4 (2 << 0) -# define CLKCON_CLKSPD_1_8 (3 << 0) -# define CLKCON_CLKSPD_1_16 (4 << 0) -# define CLKCON_CLKSPD_1_32 (5 << 0) -# define CLKCON_CLKSPD_1_64 (6 << 0) -# define CLKCON_CLKSPD_1_128 (7 << 0) - -/* SLEEP 0xBE */ -#define SLEEP_USB_EN (1 << 7) -#define SLEEP_XOSC_STB (1 << 6) -#define SLEEP_HFRC_STB (1 << 5) -#define SLEEP_RST_POWER (0 << 3) -#define SLEEP_RST_EXTERNAL (1 << 3) -#define SLEEP_RST_WATCHDOG (2 << 3) -#define SLEEP_RST_MASK (3 << 3) -#define SLEEP_OSC_PD (1 << 2) -#define SLEEP_MODE_PM0 (0 << 0) -#define SLEEP_MODE_PM1 (1 << 0) -#define SLEEP_MODE_PM2 (2 << 0) -#define SLEEP_MODE_PM3 (3 << 0) -#define SLEEP_MODE_MASK (3 << 0) - -/* PCON 0x87 */ -__sfr __at 0x87 PCON; /* Power Mode Control Register */ - -#define PCON_IDLE (1 << 0) - -/* - * TCON - */ -__sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ - -__sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -__sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -__sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -__sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -__sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ - -#define TCON_URX1IF (1 << 7) -#define TCON_I2SRXIF (1 << 7) -#define TCON_ADCIF (1 << 5) -#define TCON_URX0IF (1 << 3) -#define TCON_RFTXRXIF (1 << 1) - -/* - * S0CON - */ -__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ - -__sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ -__sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ - -#define S0CON_ENCIF_1 (1 << 1) -#define S0CON_ENCIF_0 (1 << 0) - -/* - * S1CON - */ -__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ - -#define S1CON_RFIF_1 (1 << 1) -#define S1CON_RFIF_0 (1 << 0) - -/* - * IRCON - */ -__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ - -__sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ -__sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -__sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -__sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -__sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -__sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ -__sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ - -#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ -#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ -#define IRCON_T2IF (1 << 2) /* Timer 2 interrupt flag. Automatically cleared */ -#define IRCON_T3IF (1 << 3) /* Timer 3 interrupt flag. Automatically cleared */ -#define IRCON_T4IF (1 << 4) /* Timer 4 interrupt flag. Automatically cleared */ -#define IRCON_P0IF (1 << 5) /* Port0 interrupt flag */ -#define IRCON_STIF (1 << 7) /* Sleep Timer interrupt flag */ - -/* - * IRCON2 - */ -__sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ - -__sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -__sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -__sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -__sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -__sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -__sbit __at 0xEB P1IF; /* Port1 interrupt flag */ -__sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ - -#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ -#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ -#define IRCON2_UTX0IF (1 << 1) /* USART0 TX interrupt flag */ -#define IRCON2_UTX1IF (1 << 2) /* USART1 TX interrupt flag (shared with I2S TX) */ -#define IRCON2_I2STXIF (1 << 2) /* I2S TX interrupt flag (shared with USART1 TX) */ -#define IRCON2_P1IF (1 << 3) /* Port1 interrupt flag */ -#define IRCON2_WDTIF (1 << 4) /* Watchdog timer interrupt flag */ - -/* - * IP1 - Interrupt Priority 1 - */ - -/* - * Interrupt priority groups: - * - * IPG0 RFTXRX RF DMA - * IPG1 ADC T1 P2INT/USB - * IPG2 URX0 T2 UTX0 - * IPG3 URX1/I2SRX T3 UTX1 / I2STX - * IPG4 ENC T4 P1INT - * IPG5 ST P0INT WDT - * - * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first - */ - -__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ -__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ - -#define IP1_IPG5 (1 << 5) -#define IP1_IPG4 (1 << 4) -#define IP1_IPG3 (1 << 3) -#define IP1_IPG2 (1 << 2) -#define IP1_IPG1 (1 << 1) -#define IP1_IPG0 (1 << 0) - -#define IP0_IPG5 (1 << 5) -#define IP0_IPG4 (1 << 4) -#define IP0_IPG3 (1 << 3) -#define IP0_IPG2 (1 << 2) -#define IP0_IPG1 (1 << 1) -#define IP0_IPG0 (1 << 0) - -/* - * Timer 1 - */ -#define T1CTL_MODE_SUSPENDED (0 << 0) -#define T1CTL_MODE_FREE (1 << 0) -#define T1CTL_MODE_MODULO (2 << 0) -#define T1CTL_MODE_UP_DOWN (3 << 0) -#define T1CTL_MODE_MASK (3 << 0) -#define T1CTL_DIV_1 (0 << 2) -#define T1CTL_DIV_8 (1 << 2) -#define T1CTL_DIV_32 (2 << 2) -#define T1CTL_DIV_128 (3 << 2) -#define T1CTL_DIV_MASK (3 << 2) -#define T1CTL_OVFIF (1 << 4) -#define T1CTL_CH0IF (1 << 5) -#define T1CTL_CH1IF (1 << 6) -#define T1CTL_CH2IF (1 << 7) - -#define T1CCTL_NO_CAPTURE (0 << 0) -#define T1CCTL_CAPTURE_RISING (1 << 0) -#define T1CCTL_CAPTURE_FALLING (2 << 0) -#define T1CCTL_CAPTURE_BOTH (3 << 0) -#define T1CCTL_CAPTURE_MASK (3 << 0) - -#define T1CCTL_MODE_CAPTURE (0 << 2) -#define T1CCTL_MODE_COMPARE (1 << 2) - -#define T1CTL_CMP_SET (0 << 3) -#define T1CTL_CMP_CLEAR (1 << 3) -#define T1CTL_CMP_TOGGLE (2 << 3) -#define T1CTL_CMP_SET_CLEAR (3 << 3) -#define T1CTL_CMP_CLEAR_SET (4 << 3) - -#define T1CTL_IM_DISABLED (0 << 6) -#define T1CTL_IM_ENABLED (1 << 6) - -#define T1CTL_CPSEL_NORMAL (0 << 7) -#define T1CTL_CPSEL_RF (1 << 7) - -/* - * Timer 3 and Timer 4 - */ - -/* Timer count */ -__sfr __at 0xCA T3CNT; -__sfr __at 0xEA T4CNT; - -/* Timer control */ - -__sfr __at 0xCB T3CTL; -__sfr __at 0xEB T4CTL; - -#define TxCTL_DIV_1 (0 << 5) -#define TxCTL_DIV_2 (1 << 5) -#define TxCTL_DIV_4 (2 << 5) -#define TxCTL_DIV_8 (3 << 5) -#define TxCTL_DIV_16 (4 << 5) -#define TxCTL_DIV_32 (5 << 5) -#define TxCTL_DIV_64 (6 << 5) -#define TxCTL_DIV_128 (7 << 5) -#define TxCTL_START (1 << 4) -#define TxCTL_OVFIM (1 << 3) -#define TxCTL_CLR (1 << 2) -#define TxCTL_MODE_FREE (0 << 0) -#define TxCTL_MODE_DOWN (1 << 0) -#define TxCTL_MODE_MODULO (2 << 0) -#define TxCTL_MODE_UP_DOWN (3 << 0) - -/* Timer 4 channel 0 compare control */ - -__sfr __at 0xCC T3CCTL0; -__sfr __at 0xCE T3CCTL1; -__sfr __at 0xEC T4CCTL0; -__sfr __at 0xEE T4CCTL1; - -#define TxCCTLy_IM (1 << 6) -#define TxCCTLy_CMP_SET (0 << 3) -#define TxCCTLy_CMP_CLEAR (1 << 3) -#define TxCCTLy_CMP_TOGGLE (2 << 3) -#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) -#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) -#define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) -#define TxCCTLy_CMP_CLEAR_SET_00 (6 << 3) -#define TxCCTLy_CMP_MODE_ENABLE (1 << 2) - -/* Timer compare value */ -__sfr __at 0xCD T3CC0; -__sfr __at 0xCF T3CC1; -__sfr __at 0xED T4CC0; -__sfr __at 0xEF T4CC1; - -/* - * Peripheral control - */ - -__sfr __at 0xf1 PERCFG; -#define PERCFG_T1CFG_ALT_1 (0 << 6) -#define PERCFG_T1CFG_ALT_2 (1 << 6) -#define PERCFG_T1CFG_ALT_MASK (1 << 6) - -#define PERCFG_T3CFG_ALT_1 (0 << 5) -#define PERCFG_T3CFG_ALT_2 (1 << 5) -#define PERCFG_T3CFG_ALT_MASK (1 << 5) - -#define PERCFG_T4CFG_ALT_1 (0 << 4) -#define PERCFG_T4CFG_ALT_2 (1 << 4) -#define PERCFG_T4CFG_ALT_MASK (1 << 4) - -#define PERCFG_U1CFG_ALT_1 (0 << 1) -#define PERCFG_U1CFG_ALT_2 (1 << 1) -#define PERCFG_U1CFG_ALT_MASK (1 << 1) - -#define PERCFG_U0CFG_ALT_1 (0 << 0) -#define PERCFG_U0CFG_ALT_2 (1 << 0) -#define PERCFG_U0CFG_ALT_MASK (1 << 0) - -/* directly addressed USB registers */ -__xdata __at (0xde00) volatile uint8_t USBADDR; -__xdata __at (0xde01) volatile uint8_t USBPOW; -__xdata __at (0xde02) volatile uint8_t USBIIF; - -__xdata __at (0xde04) volatile uint8_t USBOIF; - -__xdata __at (0xde06) volatile uint8_t USBCIF; - -# define USBCIF_SOFIF (1 << 3) -# define USBCIF_RSTIF (1 << 2) -# define USBCIF_RESUMEIF (1 << 1) -# define USBCIF_SUSPENDIF (1 << 0) - -__xdata __at (0xde07) volatile uint8_t USBIIE; - -__xdata __at (0xde09) volatile uint8_t USBOIE; - -__xdata __at (0xde0b) volatile uint8_t USBCIE; - -# define USBCIE_SOFIE (1 << 3) -# define USBCIE_RSTIE (1 << 2) -# define USBCIE_RESUMEIE (1 << 1) -# define USBCIE_SUSPENDIE (1 << 0) - -__xdata __at (0xde0c) volatile uint8_t USBFRML; -__xdata __at (0xde0d) volatile uint8_t USBFRMH; -__xdata __at (0xde0e) volatile uint8_t USBINDEX; - -/* indexed USB registers, must set USBINDEX to 0-5 */ -__xdata __at (0xde10) volatile uint8_t USBMAXI; -__xdata __at (0xde11) volatile uint8_t USBCS0; - -# define USBCS0_CLR_SETUP_END (1 << 7) -# define USBCS0_CLR_OUTPKT_RDY (1 << 6) -# define USBCS0_SEND_STALL (1 << 5) -# define USBCS0_SETUP_END (1 << 4) -# define USBCS0_DATA_END (1 << 3) -# define USBCS0_SENT_STALL (1 << 2) -# define USBCS0_INPKT_RDY (1 << 1) -# define USBCS0_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde11) volatile uint8_t USBCSIL; - -# define USBCSIL_CLR_DATA_TOG (1 << 6) -# define USBCSIL_SENT_STALL (1 << 5) -# define USBCSIL_SEND_STALL (1 << 4) -# define USBCSIL_FLUSH_PACKET (1 << 3) -# define USBCSIL_UNDERRUN (1 << 2) -# define USBCSIL_PKT_PRESENT (1 << 1) -# define USBCSIL_INPKT_RDY (1 << 0) - -__xdata __at (0xde12) volatile uint8_t USBCSIH; - -# define USBCSIH_AUTOSET (1 << 7) -# define USBCSIH_ISO (1 << 6) -# define USBCSIH_FORCE_DATA_TOG (1 << 3) -# define USBCSIH_IN_DBL_BUF (1 << 0) - -__xdata __at (0xde13) volatile uint8_t USBMAXO; -__xdata __at (0xde14) volatile uint8_t USBCSOL; - -# define USBCSOL_CLR_DATA_TOG (1 << 7) -# define USBCSOL_SENT_STALL (1 << 6) -# define USBCSOL_SEND_STALL (1 << 5) -# define USBCSOL_FLUSH_PACKET (1 << 4) -# define USBCSOL_DATA_ERROR (1 << 3) -# define USBCSOL_OVERRUN (1 << 2) -# define USBCSOL_FIFO_FULL (1 << 1) -# define USBCSOL_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde15) volatile uint8_t USBCSOH; - -# define USBCSOH_AUTOCLEAR (1 << 7) -# define USBCSOH_ISO (1 << 6) -# define USBCSOH_OUT_DBL_BUF (1 << 0) - -__xdata __at (0xde16) volatile uint8_t USBCNT0; -__xdata __at (0xde16) volatile uint8_t USBCNTL; -__xdata __at (0xde17) volatile uint8_t USBCNTH; - -__xdata __at (0xde20) volatile uint8_t USBFIFO[12]; - -/* ADC Data register, low and high */ -__sfr __at 0xBA ADCL; -__sfr __at 0xBB ADCH; -__xdata __at (0xDFBA) volatile uint16_t ADCXDATA; - -/* ADC Control Register 1 */ -__sfr __at 0xB4 ADCCON1; - -# define ADCCON1_EOC (1 << 7) /* conversion complete */ -# define ADCCON1_ST (1 << 6) /* start conversion */ - -# define ADCCON1_STSEL_MASK (3 << 4) /* start select */ -# define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ -# define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ -# define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ -# define ADCCON1_STSEL_START (3 << 4) /* set start bit */ - -# define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ -# define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ -# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ - -/* ADC Control Register 2 */ -__sfr __at 0xB5 ADCCON2; - -# define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ -# define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ -# define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ -# define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ - -# define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ -# define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ - -# define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON2_SCH_SHIFT 0 -# define ADCCON2_SCH_AIN0 (0 << 0) -# define ADCCON2_SCH_AIN1 (1 << 0) -# define ADCCON2_SCH_AIN2 (2 << 0) -# define ADCCON2_SCH_AIN3 (3 << 0) -# define ADCCON2_SCH_AIN4 (4 << 0) -# define ADCCON2_SCH_AIN5 (5 << 0) -# define ADCCON2_SCH_AIN6 (6 << 0) -# define ADCCON2_SCH_AIN7 (7 << 0) -# define ADCCON2_SCH_AIN0_AIN1 (8 << 0) -# define ADCCON2_SCH_AIN2_AIN3 (9 << 0) -# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) -# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) -# define ADCCON2_SCH_GND (0xc << 0) -# define ADCCON2_SCH_VREF (0xd << 0) -# define ADCCON2_SCH_TEMP (0xe << 0) -# define ADCCON2_SCH_VDD_3 (0xf << 0) - - -/* ADC Control Register 3 */ -__sfr __at 0xB6 ADCCON3; - -# define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ -# define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ -# define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ -# define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ -# define ADCCON3_EDIV_MASK (3 << 4) /* extral decimation */ -# define ADCCON3_EDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON3_EDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON3_EDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON3_EDIV_512 (3 << 4) /* 12 bits */ -# define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON3_ECH_SHIFT 0 -# define ADCCON3_ECH_AIN0 (0 << 0) -# define ADCCON3_ECH_AIN1 (1 << 0) -# define ADCCON3_ECH_AIN2 (2 << 0) -# define ADCCON3_ECH_AIN3 (3 << 0) -# define ADCCON3_ECH_AIN4 (4 << 0) -# define ADCCON3_ECH_AIN5 (5 << 0) -# define ADCCON3_ECH_AIN6 (6 << 0) -# define ADCCON3_ECH_AIN7 (7 << 0) -# define ADCCON3_ECH_AIN0_AIN1 (8 << 0) -# define ADCCON3_ECH_AIN2_AIN3 (9 << 0) -# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) -# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) -# define ADCCON3_ECH_GND (0xc << 0) -# define ADCCON3_ECH_VREF (0xd << 0) -# define ADCCON3_ECH_TEMP (0xe << 0) -# define ADCCON3_ECH_VDD_3 (0xf << 0) - -/* - * ADC configuration register, this selects which - * GPIO pins are to be used as ADC inputs - */ -__sfr __at 0xF2 ADCCFG; - -/* - * Watchdog timer - */ - -__sfr __at 0xc9 WDCTL; - -#define WDCTL_CLEAR_FIRST (0xa << 4) -#define WDCTL_CLEAR_SECOND (0x5 << 4) -#define WDCTL_EN (1 << 3) -#define WDCTL_MODE_WATCHDOG (0 << 2) -#define WDCTL_MODE_TIMER (1 << 2) -#define WDCTL_MODE_MASK (1 << 2) -#define WDCTL_INT_32768 (0 << 0) -#define WDCTL_INT_8192 (1 << 0) -#define WDCTL_INT_512 (2 << 0) -#define WDCTL_INT_64 (3 << 0) - -/* - * Pin selectors, these set which pins are - * using their peripheral function - */ -__sfr __at 0xF3 P0SEL; -__sfr __at 0xF4 P1SEL; -__sfr __at 0xF5 P2SEL; - -#define P2SEL_PRI3P1_USART0 (0 << 6) -#define P2SEL_PRI3P1_USART1 (1 << 6) -#define P2SEL_PRI3P1_MASK (1 << 6) -#define P2SEL_PRI2P1_USART1 (0 << 5) -#define P2SEL_PRI2P1_TIMER3 (1 << 5) -#define P2SEL_PRI2P1_MASK (1 << 5) -#define P2SEL_PRI1P1_TIMER1 (0 << 4) -#define P2SEL_PRI1P1_TIMER4 (1 << 4) -#define P2SEL_PRI1P1_MASK (1 << 4) -#define P2SEL_PRI0P1_USART0 (0 << 3) -#define P2SEL_PRI0P1_TIMER1 (1 << 3) -#define P2SEL_PRI0P1_MASK (1 << 3) -#define P2SEL_SELP2_4_GPIO (0 << 2) -#define P2SEL_SELP2_4_PERIPHERAL (1 << 2) -#define P2SEL_SELP2_4_MASK (1 << 2) -#define P2SEL_SELP2_3_GPIO (0 << 1) -#define P2SEL_SELP2_3_PERIPHERAL (1 << 1) -#define P2SEL_SELP2_3_MASK (1 << 1) -#define P2SEL_SELP2_0_GPIO (0 << 0) -#define P2SEL_SELP2_0_PERIPHERAL (1 << 0) -#define P2SEL_SELP2_0_MASK (1 << 0) - -/* - * For pins used as GPIOs, these set which are used as outputs - */ -__sfr __at 0xFD P0DIR; -__sfr __at 0xFE P1DIR; -__sfr __at 0xFF P2DIR; - -#define P2DIR_PRIP0_USART0_USART1 (0 << 6) -#define P2DIR_PRIP0_USART1_USART0 (1 << 6) -#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) -#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) -#define P2DIR_PRIP0_MASK (3 << 6) - -__sfr __at 0x8F P0INP; - -/* Select between tri-state and pull up/down - * for pins P0_0 - P0_7. - */ -#define P0INP_MDP0_7_PULL (0 << 7) -#define P0INP_MDP0_7_TRISTATE (1 << 7) -#define P0INP_MDP0_6_PULL (0 << 6) -#define P0INP_MDP0_6_TRISTATE (1 << 6) -#define P0INP_MDP0_5_PULL (0 << 5) -#define P0INP_MDP0_5_TRISTATE (1 << 5) -#define P0INP_MDP0_4_PULL (0 << 4) -#define P0INP_MDP0_4_TRISTATE (1 << 4) -#define P0INP_MDP0_3_PULL (0 << 3) -#define P0INP_MDP0_3_TRISTATE (1 << 3) -#define P0INP_MDP0_2_PULL (0 << 2) -#define P0INP_MDP0_2_TRISTATE (1 << 2) -#define P0INP_MDP0_1_PULL (0 << 1) -#define P0INP_MDP0_1_TRISTATE (1 << 1) -#define P0INP_MDP0_0_PULL (0 << 0) -#define P0INP_MDP0_0_TRISTATE (1 << 0) - -__sfr __at 0xF6 P1INP; - -/* Select between tri-state and pull up/down - * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are - * always tri-stated - */ -#define P1INP_MDP1_7_PULL (0 << 7) -#define P1INP_MDP1_7_TRISTATE (1 << 7) -#define P1INP_MDP1_6_PULL (0 << 6) -#define P1INP_MDP1_6_TRISTATE (1 << 6) -#define P1INP_MDP1_5_PULL (0 << 5) -#define P1INP_MDP1_5_TRISTATE (1 << 5) -#define P1INP_MDP1_4_PULL (0 << 4) -#define P1INP_MDP1_4_TRISTATE (1 << 4) -#define P1INP_MDP1_3_PULL (0 << 3) -#define P1INP_MDP1_3_TRISTATE (1 << 3) -#define P1INP_MDP1_2_PULL (0 << 2) -#define P1INP_MDP1_2_TRISTATE (1 << 2) - -__sfr __at 0xF7 P2INP; -/* P2INP has three extra bits which are used to choose - * between pull-up and pull-down when they are not tri-stated - */ -#define P2INP_PDUP2_PULL_UP (0 << 7) -#define P2INP_PDUP2_PULL_DOWN (1 << 7) -#define P2INP_PDUP1_PULL_UP (0 << 6) -#define P2INP_PDUP1_PULL_DOWN (1 << 6) -#define P2INP_PDUP0_PULL_UP (0 << 5) -#define P2INP_PDUP0_PULL_DOWN (1 << 5) - -/* For the P2 pins, choose between tri-state and pull up/down - * mode - */ -#define P2INP_MDP2_4_PULL (0 << 4) -#define P2INP_MDP2_4_TRISTATE (1 << 4) -#define P2INP_MDP2_3_PULL (0 << 3) -#define P2INP_MDP2_3_TRISTATE (1 << 3) -#define P2INP_MDP2_2_PULL (0 << 2) -#define P2INP_MDP2_2_TRISTATE (1 << 2) -#define P2INP_MDP2_1_PULL (0 << 1) -#define P2INP_MDP2_1_TRISTATE (1 << 1) -#define P2INP_MDP2_0_PULL (0 << 0) -#define P2INP_MDP2_0_TRISTATE (1 << 0) - -/* GPIO interrupt status flags */ -__sfr __at 0x89 P0IFG; -__sfr __at 0x8A P1IFG; -__sfr __at 0x8B P2IFG; - -#define P0IFG_USB_RESUME (1 << 7) - -__sfr __at 0x8C PICTL; -#define PICTL_P2IEN (1 << 5) -#define PICTL_P0IENH (1 << 4) -#define PICTL_P0IENL (1 << 3) -#define PICTL_P2ICON (1 << 2) -#define PICTL_P1ICON (1 << 1) -#define PICTL_P0ICON (1 << 0) - -/* GPIO pins */ -__sfr __at 0x80 P0; - -__sbit __at 0x80 P0_0; -__sbit __at 0x81 P0_1; -__sbit __at 0x82 P0_2; -__sbit __at 0x83 P0_3; -__sbit __at 0x84 P0_4; -__sbit __at 0x85 P0_5; -__sbit __at 0x86 P0_6; -__sbit __at 0x87 P0_7; - -__sfr __at 0x90 P1; - -__sbit __at 0x90 P1_0; -__sbit __at 0x91 P1_1; -__sbit __at 0x92 P1_2; -__sbit __at 0x93 P1_3; -__sbit __at 0x94 P1_4; -__sbit __at 0x95 P1_5; -__sbit __at 0x96 P1_6; -__sbit __at 0x97 P1_7; - -__sfr __at 0xa0 P2; - -__sbit __at 0xa0 P2_0; -__sbit __at 0xa1 P2_1; -__sbit __at 0xa2 P2_2; -__sbit __at 0xa3 P2_3; -__sbit __at 0xa4 P2_4; - -/* DMA controller */ -struct cc_dma_channel { - uint8_t src_high; - uint8_t src_low; - uint8_t dst_high; - uint8_t dst_low; - uint8_t len_high; - uint8_t len_low; - uint8_t cfg0; - uint8_t cfg1; -}; - -# define DMA_LEN_HIGH_VLEN_MASK (7 << 5) -# define DMA_LEN_HIGH_VLEN_LEN (0 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) -# define DMA_LEN_HIGH_VLEN (2 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) -# define DMA_LEN_HIGH_MASK (0x1f) - -# define DMA_CFG0_WORDSIZE_8 (0 << 7) -# define DMA_CFG0_WORDSIZE_16 (1 << 7) -# define DMA_CFG0_TMODE_MASK (3 << 5) -# define DMA_CFG0_TMODE_SINGLE (0 << 5) -# define DMA_CFG0_TMODE_BLOCK (1 << 5) -# define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) -# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) - -/* - * DMA triggers - */ -# define DMA_CFG0_TRIGGER_NONE 0 -# define DMA_CFG0_TRIGGER_PREV 1 -# define DMA_CFG0_TRIGGER_T1_CH0 2 -# define DMA_CFG0_TRIGGER_T1_CH1 3 -# define DMA_CFG0_TRIGGER_T1_CH2 4 -# define DMA_CFG0_TRIGGER_T2_OVFL 6 -# define DMA_CFG0_TRIGGER_T3_CH0 7 -# define DMA_CFG0_TRIGGER_T3_CH1 8 -# define DMA_CFG0_TRIGGER_T4_CH0 9 -# define DMA_CFG0_TRIGGER_T4_CH1 10 -# define DMA_CFG0_TRIGGER_IOC_0 12 -# define DMA_CFG0_TRIGGER_IOC_1 13 -# define DMA_CFG0_TRIGGER_URX0 14 -# define DMA_CFG0_TRIGGER_UTX0 15 -# define DMA_CFG0_TRIGGER_URX1 16 -# define DMA_CFG0_TRIGGER_UTX1 17 -# define DMA_CFG0_TRIGGER_FLASH 18 -# define DMA_CFG0_TRIGGER_RADIO 19 -# define DMA_CFG0_TRIGGER_ADC_CHALL 20 -# define DMA_CFG0_TRIGGER_ADC_CH0 21 -# define DMA_CFG0_TRIGGER_ADC_CH1 22 -# define DMA_CFG0_TRIGGER_ADC_CH2 23 -# define DMA_CFG0_TRIGGER_ADC_CH3 24 -# define DMA_CFG0_TRIGGER_ADC_CH4 25 -# define DMA_CFG0_TRIGGER_ADC_CH5 26 -# define DMA_CFG0_TRIGGER_ADC_CH6 27 -# define DMA_CFG0_TRIGGER_I2SRX 27 -# define DMA_CFG0_TRIGGER_ADC_CH7 28 -# define DMA_CFG0_TRIGGER_I2STX 28 -# define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_ENC_UP 30 - -# define DMA_CFG1_SRCINC_MASK (3 << 6) -# define DMA_CFG1_SRCINC_0 (0 << 6) -# define DMA_CFG1_SRCINC_1 (1 << 6) -# define DMA_CFG1_SRCINC_2 (2 << 6) -# define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) - -# define DMA_CFG1_DESTINC_MASK (3 << 4) -# define DMA_CFG1_DESTINC_0 (0 << 4) -# define DMA_CFG1_DESTINC_1 (1 << 4) -# define DMA_CFG1_DESTINC_2 (2 << 4) -# define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) - -# define DMA_CFG1_IRQMASK (1 << 3) -# define DMA_CFG1_M8 (1 << 2) - -# define DMA_CFG1_PRIORITY_MASK (3 << 0) -# define DMA_CFG1_PRIORITY_LOW (0 << 0) -# define DMA_CFG1_PRIORITY_NORMAL (1 << 0) -# define DMA_CFG1_PRIORITY_HIGH (2 << 0) - -/* - * DMAARM - DMA Channel Arm - */ - -__sfr __at 0xD6 DMAARM; - -# define DMAARM_ABORT (1 << 7) -# define DMAARM_DMAARM4 (1 << 4) -# define DMAARM_DMAARM3 (1 << 3) -# define DMAARM_DMAARM2 (1 << 2) -# define DMAARM_DMAARM1 (1 << 1) -# define DMAARM_DMAARM0 (1 << 0) - -/* - * DMAREQ - DMA Channel Start Request and Status - */ - -__sfr __at 0xD7 DMAREQ; - -# define DMAREQ_DMAREQ4 (1 << 4) -# define DMAREQ_DMAREQ3 (1 << 3) -# define DMAREQ_DMAREQ2 (1 << 2) -# define DMAREQ_DMAREQ1 (1 << 1) -# define DMAREQ_DMAREQ0 (1 << 0) - -/* - * DMA configuration 0 address - */ - -__sfr __at 0xD5 DMA0CFGH; -__sfr __at 0xD4 DMA0CFGL; - -/* - * DMA configuration 1-4 address - */ - -__sfr __at 0xD3 DMA1CFGH; -__sfr __at 0xD2 DMA1CFGL; - -/* - * DMAIRQ - DMA Interrupt Flag - */ - -__sfr __at 0xD1 DMAIRQ; - -# define DMAIRQ_DMAIF4 (1 << 4) -# define DMAIRQ_DMAIF3 (1 << 3) -# define DMAIRQ_DMAIF2 (1 << 2) -# define DMAIRQ_DMAIF1 (1 << 1) -# define DMAIRQ_DMAIF0 (1 << 0) - -/* - * UART registers - */ - -/* USART config/status registers */ -__sfr __at 0x86 U0CSR; -__sfr __at 0xF8 U1CSR; - -# define UxCSR_MODE_UART (1 << 7) -# define UxCSR_MODE_SPI (0 << 7) -# define UxCSR_RE (1 << 6) -# define UxCSR_SLAVE (1 << 5) -# define UxCSR_MASTER (0 << 5) -# define UxCSR_FE (1 << 4) -# define UxCSR_ERR (1 << 3) -# define UxCSR_RX_BYTE (1 << 2) -# define UxCSR_TX_BYTE (1 << 1) -# define UxCSR_ACTIVE (1 << 0) - -/* UART configuration registers */ -__sfr __at 0xc4 U0UCR; -__sfr __at 0xfb U1UCR; - -# define UxUCR_FLUSH (1 << 7) -# define UxUCR_FLOW_DISABLE (0 << 6) -# define UxUCR_FLOW_ENABLE (1 << 6) -# define UxUCR_D9_EVEN_PARITY (0 << 5) -# define UxUCR_D9_ODD_PARITY (1 << 5) -# define UxUCR_BIT9_8_BITS (0 << 4) -# define UxUCR_BIT9_9_BITS (1 << 4) -# define UxUCR_PARITY_DISABLE (0 << 3) -# define UxUCR_PARITY_ENABLE (1 << 3) -# define UxUCR_SPB_1_STOP_BIT (0 << 2) -# define UxUCR_SPB_2_STOP_BITS (1 << 2) -# define UxUCR_STOP_LOW (0 << 1) -# define UxUCR_STOP_HIGH (1 << 1) -# define UxUCR_START_LOW (0 << 0) -# define UxUCR_START_HIGH (1 << 0) - -/* USART General configuration registers (mostly SPI) */ -__sfr __at 0xc5 U0GCR; -__sfr __at 0xfc U1GCR; - -# define UxGCR_CPOL_NEGATIVE (0 << 7) -# define UxGCR_CPOL_POSITIVE (1 << 7) -# define UxGCR_CPHA_FIRST_EDGE (0 << 6) -# define UxGCR_CPHA_SECOND_EDGE (1 << 6) -# define UxGCR_ORDER_LSB (0 << 5) -# define UxGCR_ORDER_MSB (1 << 5) -# define UxGCR_BAUD_E_MASK (0x1f) -# define UxGCR_BAUD_E_SHIFT 0 - -/* USART data registers */ -__sfr __at 0xc1 U0DBUF; -__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -__sfr __at 0xf9 U1DBUF; -__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; - -/* USART baud rate registers, M value */ -__sfr __at 0xc2 U0BAUD; -__sfr __at 0xfa U1BAUD; - -/* Flash controller */ - -__sfr __at 0xAE FCTL; -#define FCTL_BUSY (1 << 7) -#define FCTL_SWBSY (1 << 6) -#define FCTL_CONTRD_ENABLE (1 << 4) -#define FCTL_WRITE (1 << 1) -#define FCTL_ERASE (1 << 0) - -/* Flash write data. Write two bytes here */ -__sfr __at 0xAF FWDATA; -__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; - -/* Flash write/erase address */ -__sfr __at 0xAD FADDRH; -__sfr __at 0xAC FADDRL; - -/* Flash timing */ -__sfr __at 0xAB FWT; - -/* Radio */ - -__sfr __at 0xD9 RFD; -__xdata __at (0xDFD9) volatile uint8_t RFDXADDR; - -__sfr __at 0xE9 RFIF; -#define RFIF_IM_TXUNF (1 << 7) -#define RFIF_IM_RXOVF (1 << 6) -#define RFIF_IM_TIMEOUT (1 << 5) -#define RFIF_IM_DONE (1 << 4) -#define RFIF_IM_CS (1 << 3) -#define RFIF_IM_PQT (1 << 2) -#define RFIF_IM_CCA (1 << 1) -#define RFIF_IM_SFD (1 << 0) - -__sfr __at 0x91 RFIM; -#define RFIM_IM_TXUNF (1 << 7) -#define RFIM_IM_RXOVF (1 << 6) -#define RFIM_IM_TIMEOUT (1 << 5) -#define RFIM_IM_DONE (1 << 4) -#define RFIM_IM_CS (1 << 3) -#define RFIM_IM_PQT (1 << 2) -#define RFIM_IM_CCA (1 << 1) -#define RFIM_IM_SFD (1 << 0) - -__sfr __at 0xE1 RFST; - -#define RFST_SFSTXON 0x00 -#define RFST_SCAL 0x01 -#define RFST_SRX 0x02 -#define RFST_STX 0x03 -#define RFST_SIDLE 0x04 - -__xdata __at (0xdf00) uint8_t RF[0x3c]; - -__xdata __at (0xdf2f) uint8_t RF_IOCFG2; -#define RF_IOCFG2_OFF 0x2f - -__xdata __at (0xdf30) uint8_t RF_IOCFG1; -#define RF_IOCFG1_OFF 0x30 - -__xdata __at (0xdf31) uint8_t RF_IOCFG0; -#define RF_IOCFG0_OFF 0x31 - -__xdata __at (0xdf00) uint8_t RF_SYNC1; -#define RF_SYNC1_OFF 0x00 - -__xdata __at (0xdf01) uint8_t RF_SYNC0; -#define RF_SYNC0_OFF 0x01 - -__xdata __at (0xdf02) uint8_t RF_PKTLEN; -#define RF_PKTLEN_OFF 0x02 - -__xdata __at (0xdf03) uint8_t RF_PKTCTRL1; -#define RF_PKTCTRL1_OFF 0x03 -#define PKTCTRL1_PQT_MASK (0x7 << 5) -#define PKTCTRL1_PQT_SHIFT 5 -#define PKTCTRL1_APPEND_STATUS (1 << 2) -#define PKTCTRL1_ADR_CHK_NONE (0 << 0) -#define PKTCTRL1_ADR_CHK_NO_BROADCAST (1 << 0) -#define PKTCTRL1_ADR_CHK_00_BROADCAST (2 << 0) -#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST (3 << 0) - -/* If APPEND_STATUS is used, two bytes will be added to the packet data */ -#define PKT_APPEND_STATUS_0_RSSI_MASK (0xff) -#define PKT_APPEND_STATUS_0_RSSI_SHIFT 0 -#define PKT_APPEND_STATUS_1_CRC_OK (1 << 7) -#define PKT_APPEND_STATUS_1_LQI_MASK (0x7f) -#define PKT_APPEND_STATUS_1_LQI_SHIFT 0 - -__xdata __at (0xdf04) uint8_t RF_PKTCTRL0; -#define RF_PKTCTRL0_OFF 0x04 -#define RF_PKTCTRL0_WHITE_DATA (1 << 6) -#define RF_PKTCTRL0_PKT_FORMAT_NORMAL (0 << 4) -#define RF_PKTCTRL0_PKT_FORMAT_RANDOM (2 << 4) -#define RF_PKTCTRL0_CRC_EN (1 << 2) -#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED (0 << 0) -#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE (1 << 0) - -__xdata __at (0xdf05) uint8_t RF_ADDR; -#define RF_ADDR_OFF 0x05 - -__xdata __at (0xdf06) uint8_t RF_CHANNR; -#define RF_CHANNR_OFF 0x06 - -__xdata __at (0xdf07) uint8_t RF_FSCTRL1; -#define RF_FSCTRL1_OFF 0x07 - -#define RF_FSCTRL1_FREQ_IF_SHIFT (0) - -__xdata __at (0xdf08) uint8_t RF_FSCTRL0; -#define RF_FSCTRL0_OFF 0x08 - -#define RF_FSCTRL0_FREQOFF_SHIFT (0) - -__xdata __at (0xdf09) uint8_t RF_FREQ2; -#define RF_FREQ2_OFF 0x09 - -__xdata __at (0xdf0a) uint8_t RF_FREQ1; -#define RF_FREQ1_OFF 0x0a - -__xdata __at (0xdf0b) uint8_t RF_FREQ0; -#define RF_FREQ0_OFF 0x0b - -__xdata __at (0xdf0c) uint8_t RF_MDMCFG4; -#define RF_MDMCFG4_OFF 0x0c - -#define RF_MDMCFG4_CHANBW_E_SHIFT 6 -#define RF_MDMCFG4_CHANBW_M_SHIFT 4 -#define RF_MDMCFG4_DRATE_E_SHIFT 0 - -__xdata __at (0xdf0d) uint8_t RF_MDMCFG3; -#define RF_MDMCFG3_OFF 0x0d - -#define RF_MDMCFG3_DRATE_M_SHIFT 0 - -__xdata __at (0xdf0e) uint8_t RF_MDMCFG2; -#define RF_MDMCFG2_OFF 0x0e - -#define RF_MDMCFG2_DEM_DCFILT_OFF (1 << 7) -#define RF_MDMCFG2_DEM_DCFILT_ON (0 << 7) - -#define RF_MDMCFG2_MOD_FORMAT_MASK (7 << 4) -#define RF_MDMCFG2_MOD_FORMAT_2_FSK (0 << 4) -#define RF_MDMCFG2_MOD_FORMAT_GFSK (1 << 4) -#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK (3 << 4) -#define RF_MDMCFG2_MOD_FORMAT_MSK (7 << 4) - -#define RF_MDMCFG2_MANCHESTER_EN (1 << 3) - -#define RF_MDMCFG2_SYNC_MODE_MASK (0x7 << 0) -#define RF_MDMCFG2_SYNC_MODE_NONE (0x0 << 0) -#define RF_MDMCFG2_SYNC_MODE_15_16 (0x1 << 0) -#define RF_MDMCFG2_SYNC_MODE_16_16 (0x2 << 0) -#define RF_MDMCFG2_SYNC_MODE_30_32 (0x3 << 0) -#define RF_MDMCFG2_SYNC_MODE_NONE_THRES (0x4 << 0) -#define RF_MDMCFG2_SYNC_MODE_15_16_THRES (0x5 << 0) -#define RF_MDMCFG2_SYNC_MODE_16_16_THRES (0x6 << 0) -#define RF_MDMCFG2_SYNC_MODE_30_32_THRES (0x7 << 0) - -__xdata __at (0xdf0f) uint8_t RF_MDMCFG1; -#define RF_MDMCFG1_OFF 0x0f - -#define RF_MDMCFG1_FEC_EN (1 << 7) -#define RF_MDMCFG1_FEC_DIS (0 << 7) - -#define RF_MDMCFG1_NUM_PREAMBLE_MASK (7 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_2 (0 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_3 (1 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_4 (2 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_6 (3 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_8 (4 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_12 (5 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_16 (6 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_24 (7 << 4) - -#define RF_MDMCFG1_CHANSPC_E_MASK (3 << 0) -#define RF_MDMCFG1_CHANSPC_E_SHIFT (0) - -__xdata __at (0xdf10) uint8_t RF_MDMCFG0; -#define RF_MDMCFG0_OFF 0x10 - -#define RF_MDMCFG0_CHANSPC_M_SHIFT (0) - -__xdata __at (0xdf11) uint8_t RF_DEVIATN; -#define RF_DEVIATN_OFF 0x11 - -#define RF_DEVIATN_DEVIATION_E_SHIFT 4 -#define RF_DEVIATN_DEVIATION_M_SHIFT 0 - -__xdata __at (0xdf12) uint8_t RF_MCSM2; -#define RF_MCSM2_OFF 0x12 -#define RF_MCSM2_RX_TIME_RSSI (1 << 4) -#define RF_MCSM2_RX_TIME_QUAL (1 << 3) -#define RF_MCSM2_RX_TIME_MASK (0x7) -#define RF_MCSM2_RX_TIME_SHIFT 0 -#define RF_MCSM2_RX_TIME_END_OF_PACKET (7) - -__xdata __at (0xdf13) uint8_t RF_MCSM1; -#define RF_MCSM1_OFF 0x13 -#define RF_MCSM1_CCA_MODE_ALWAYS (0 << 4) -#define RF_MCSM1_CCA_MODE_RSSI_BELOW (1 << 4) -#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING (2 << 4) -#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING (3 << 4) -#define RF_MCSM1_RXOFF_MODE_IDLE (0 << 2) -#define RF_MCSM1_RXOFF_MODE_FSTXON (1 << 2) -#define RF_MCSM1_RXOFF_MODE_TX (2 << 2) -#define RF_MCSM1_RXOFF_MODE_RX (3 << 2) -#define RF_MCSM1_TXOFF_MODE_IDLE (0 << 0) -#define RF_MCSM1_TXOFF_MODE_FSTXON (1 << 0) -#define RF_MCSM1_TXOFF_MODE_TX (2 << 0) -#define RF_MCSM1_TXOFF_MODE_RX (3 << 0) - -__xdata __at (0xdf14) uint8_t RF_MCSM0; -#define RF_MCSM0_OFF 0x14 -#define RF_MCSM0_FS_AUTOCAL_NEVER (0 << 4) -#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE (1 << 4) -#define RF_MCSM0_FS_AUTOCAL_TO_IDLE (2 << 4) -#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4 (3 << 4) -#define RF_MCSM0_MAGIC_3 (1 << 3) -#define RF_MCSM0_MAGIC_2 (1 << 2) -#define RF_MCSM0_CLOSE_IN_RX_0DB (0 << 0) -#define RF_MCSM0_CLOSE_IN_RX_6DB (1 << 0) -#define RF_MCSM0_CLOSE_IN_RX_12DB (2 << 0) -#define RF_MCSM0_CLOSE_IN_RX_18DB (3 << 0) - -__xdata __at (0xdf15) uint8_t RF_FOCCFG; -#define RF_FOCCFG_OFF 0x15 -#define RF_FOCCFG_FOC_BS_CS_GATE (1 << 5) -#define RF_FOCCFG_FOC_PRE_K_1K (0 << 3) -#define RF_FOCCFG_FOC_PRE_K_2K (1 << 3) -#define RF_FOCCFG_FOC_PRE_K_3K (2 << 3) -#define RF_FOCCFG_FOC_PRE_K_4K (3 << 3) -#define RF_FOCCFG_FOC_POST_K_PRE_K (0 << 2) -#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2 (1 << 2) -#define RF_FOCCFG_FOC_LIMIT_0 (0 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8 (1 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4 (2 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2 (3 << 0) - -__xdata __at (0xdf16) uint8_t RF_BSCFG; -#define RF_BSCFG_OFF 0x16 -#define RF_BSCFG_BS_PRE_K_1K (0 << 6) -#define RF_BSCFG_BS_PRE_K_2K (1 << 6) -#define RF_BSCFG_BS_PRE_K_3K (2 << 6) -#define RF_BSCFG_BS_PRE_K_4K (3 << 6) -#define RF_BSCFG_BS_PRE_KP_1KP (0 << 4) -#define RF_BSCFG_BS_PRE_KP_2KP (1 << 4) -#define RF_BSCFG_BS_PRE_KP_3KP (2 << 4) -#define RF_BSCFG_BS_PRE_KP_4KP (3 << 4) -#define RF_BSCFG_BS_POST_KI_PRE_KI (0 << 3) -#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2 (1 << 3) -#define RF_BSCFG_BS_POST_KP_PRE_KP (0 << 2) -#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2 (1 << 2) -#define RF_BSCFG_BS_LIMIT_0 (0 << 0) -#define RF_BSCFG_BS_LIMIT_3_125 (1 << 0) -#define RF_BSCFG_BS_LIMIT_6_25 (2 << 0) -#define RF_BSCFG_BS_LIMIT_12_5 (3 << 0) - -__xdata __at (0xdf17) uint8_t RF_AGCCTRL2; -#define RF_AGCCTRL2_OFF 0x17 - -#define RF_AGCCTRL2_MAX_DVGA_GAIN_ALL (0 << 6) -#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_1 (1 << 6) -#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_2 (2 << 6) -#define RF_AGCCTRL2_MAX_DVGA_GAIN_BUT_3 (3 << 6) -#define RF_AGCCTRL2_MAX_LNA_GAIN_0 (0 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_2_6 (1 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_6_1 (2 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_7_4 (3 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_9_2 (4 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_11_5 (5 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_14_6 (6 << 3) -#define RF_AGCCTRL2_MAX_LNA_GAIN_17_1 (7 << 3) -#define RF_AGCCTRL2_MAGN_TARGET_24dB (0 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_27dB (1 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_30dB (2 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_33dB (3 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_36dB (4 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_38dB (5 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_40dB (6 << 0) -#define RF_AGCCTRL2_MAGN_TARGET_42dB (7 << 0) - -__xdata __at (0xdf18) uint8_t RF_AGCCTRL1; -#define RF_AGCCTRL1_OFF 0x18 - -#define RF_AGCCTRL1_AGC_LNA_PRIORITY_0 (0 << 6) -#define RF_AGCCTRL1_AGC_LNA_PRIORITY_1 (1 << 6) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_DISABLE (0 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_6DB (1 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_10DB (2 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_REL_THR_14DB (3 << 4) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_DISABLE (0x8 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_BELOW (0x9 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_BELOW (0xa << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_BELOW (0xb << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_BELOW (0xc << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_BELOW (0xd << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_BELOW (0xe << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_BELOW (0xf << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_0DB (0x0 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_1DB_ABOVE (0x1 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_2DB_ABOVE (0x2 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_3DB_ABOVE (0x3 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_4DB_ABOVE (0x4 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_5DB_ABOVE (0x5 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_6DB_ABOVE (0x6 << 0) -#define RF_AGCCTRL1_CARRIER_SENSE_ABS_THR_7DB_ABOVE (0x7 << 0) - -__xdata __at (0xdf19) uint8_t RF_AGCCTRL0; -#define RF_AGCCTRL0_OFF 0x19 - -#define RF_AGCCTRL0_HYST_LEVEL_NONE (0 << 6) -#define RF_AGCCTRL0_HYST_LEVEL_LOW (1 << 6) -#define RF_AGCCTRL0_HYST_LEVEL_MEDIUM (2 << 6) -#define RF_AGCCTRL0_HYST_LEVEL_HIGH (3 << 6) -#define RF_AGCCTRL0_WAIT_TIME_8 (0 << 4) -#define RF_AGCCTRL0_WAIT_TIME_16 (1 << 4) -#define RF_AGCCTRL0_WAIT_TIME_24 (2 << 4) -#define RF_AGCCTRL0_WAIT_TIME_32 (3 << 4) -#define RF_AGCCTRL0_AGC_FREEZE_NORMAL (0 << 2) -#define RF_AGCCTRL0_AGC_FREEZE_SYNC (1 << 2) -#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_ANALOG (2 << 2) -#define RF_AGCCTRL0_AGC_FREEZE_MANUAL_BOTH (3 << 2) -#define RF_AGCCTRL0_FILTER_LENGTH_8 (0 << 0) -#define RF_AGCCTRL0_FILTER_LENGTH_16 (1 << 0) -#define RF_AGCCTRL0_FILTER_LENGTH_32 (2 << 0) -#define RF_AGCCTRL0_FILTER_LENGTH_64 (3 << 0) - -__xdata __at (0xdf1a) uint8_t RF_FREND1; -#define RF_FREND1_OFF 0x1a - -#define RF_FREND1_LNA_CURRENT_SHIFT 6 -#define RF_FREND1_LNA2MIX_CURRENT_SHIFT 4 -#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT 2 -#define RF_FREND1_MIX_CURRENT_SHIFT 0 - -__xdata __at (0xdf1b) uint8_t RF_FREND0; -#define RF_FREND0_OFF 0x1b - -#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK (0x3 << 4) -#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT 4 -#define RF_FREND0_PA_POWER_MASK (0x7) -#define RF_FREND0_PA_POWER_SHIFT 0 - -__xdata __at (0xdf1c) uint8_t RF_FSCAL3; -#define RF_FSCAL3_OFF 0x1c - -__xdata __at (0xdf1d) uint8_t RF_FSCAL2; -#define RF_FSCAL2_OFF 0x1d - -__xdata __at (0xdf1e) uint8_t RF_FSCAL1; -#define RF_FSCAL1_OFF 0x1e - -__xdata __at (0xdf1f) uint8_t RF_FSCAL0; -#define RF_FSCAL0_OFF 0x1f - -__xdata __at (0xdf23) uint8_t RF_TEST2; -#define RF_TEST2_OFF 0x23 - -#define RF_TEST2_NORMAL_MAGIC 0x88 -#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC 0x81 - -__xdata __at (0xdf24) uint8_t RF_TEST1; -#define RF_TEST1_OFF 0x24 - -#define RF_TEST1_TX_MAGIC 0x31 -#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC 0x35 - -__xdata __at (0xdf25) uint8_t RF_TEST0; -#define RF_TEST0_OFF 0x25 - -#define RF_TEST0_7_2_MASK (0xfc) -#define RF_TEST0_VCO_SEL_CAL_EN (1 << 1) -#define RF_TEST0_0_MASK (1) - -/* These are undocumented, and must be computed - * using the provided tool. - */ -__xdata __at (0xdf27) uint8_t RF_PA_TABLE7; -#define RF_PA_TABLE7_OFF 0x27 - -__xdata __at (0xdf28) uint8_t RF_PA_TABLE6; -#define RF_PA_TABLE6_OFF 0x28 - -__xdata __at (0xdf29) uint8_t RF_PA_TABLE5; -#define RF_PA_TABLE5_OFF 0x29 - -__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4; -#define RF_PA_TABLE4_OFF 0x2a - -__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3; -#define RF_PA_TABLE3_OFF 0x2b - -__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2; -#define RF_PA_TABLE2_OFF 0x2c - -__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1; -#define RF_PA_TABLE1_OFF 0x2d - -__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0; -#define RF_PA_TABLE0_OFF 0x2e - -__xdata __at (0xdf36) uint8_t RF_PARTNUM; -#define RF_PARTNUM_OFF 0x36 - -__xdata __at (0xdf37) uint8_t RF_VERSION; -#define RF_VERSION_OFF 0x37 - -__xdata __at (0xdf38) uint8_t RF_FREQEST; -#define RF_FREQEST_OFF 0x38 - -__xdata __at (0xdf39) uint8_t RF_LQI; -#define RF_LQI_OFF 0x39 - -#define RF_LQI_CRC_OK (1 << 7) -#define RF_LQI_LQI_EST_MASK (0x7f) - -__xdata __at (0xdf3a) uint8_t RF_RSSI; -#define RF_RSSI_OFF 0x3a - -__xdata __at (0xdf3b) uint8_t RF_MARCSTATE; -#define RF_MARCSTATE_OFF 0x3b - -#define RF_MARCSTATE_MASK 0x1f -#define RF_MARCSTATE_SLEEP 0x00 -#define RF_MARCSTATE_IDLE 0x01 -#define RF_MARCSTATE_VCOON_MC 0x03 -#define RF_MARCSTATE_REGON_MC 0x04 -#define RF_MARCSTATE_MANCAL 0x05 -#define RF_MARCSTATE_VCOON 0x06 -#define RF_MARCSTATE_REGON 0x07 -#define RF_MARCSTATE_STARTCAL 0x08 -#define RF_MARCSTATE_BWBOOST 0x09 -#define RF_MARCSTATE_FS_LOCK 0x0a -#define RF_MARCSTATE_IFADCON 0x0b -#define RF_MARCSTATE_ENDCAL 0x0c -#define RF_MARCSTATE_RX 0x0d -#define RF_MARCSTATE_RX_END 0x0e -#define RF_MARCSTATE_RX_RST 0x0f -#define RF_MARCSTATE_TXRX_SWITCH 0x10 -#define RF_MARCSTATE_RX_OVERFLOW 0x11 -#define RF_MARCSTATE_FSTXON 0x12 -#define RF_MARCSTATE_TX 0x13 -#define RF_MARCSTATE_TX_END 0x14 -#define RF_MARCSTATE_RXTX_SWITCH 0x15 -#define RF_MARCSTATE_TX_UNDERFLOW 0x16 - - -__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; -#define RF_PKTSTATUS_OFF 0x3c - -#define RF_PKTSTATUS_CRC_OK (1 << 7) -#define RF_PKTSTATUS_CS (1 << 6) -#define RF_PKTSTATUS_PQT_REACHED (1 << 5) -#define RF_PKTSTATUS_CCA (1 << 4) -#define RF_PKTSTATUS_SFD (1 << 3) - -__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; -#define RF_VCO_VC_DAC_OFF 0x3d - -/* AES engine */ - -__sfr __at 0xB1 ENCDI; -__sfr __at 0xB2 ENCDO; -__xdata __at (0xDFB1) volatile uint8_t ENCDIXADDR; -__xdata __at (0xDFB2) volatile uint8_t ENCDOXADDR; - -__sfr __at 0xB3 ENCCCS; - -#define ENCCCS_MODE_CBC (0 << 4) -#define ENCCCS_MODE_CFB (1 << 4) -#define ENCCCS_MODE_OFB (2 << 4) -#define ENCCCS_MODE_CTR (3 << 4) -#define ENCCCS_MODE_ECB (4 << 4) -#define ENCCCS_MODE_CBC_MAC (5 << 4) -#define ENCCCS_RDY (1 << 3) -#define ENCCCS_CMD_ENCRYPT (0 << 1) -#define ENCCCS_CMD_DECRYPT (1 << 1) -#define ENCCCS_CMD_LOAD_KEY (2 << 1) -#define ENCCCS_CMD_LOAD_IV (3 << 1) -#define ENCCCS_START (1 << 0) - -#endif diff --git a/usb_ep0/hal.c b/usb_ep0/hal.c deleted file mode 100644 index f74304b..0000000 --- a/usb_ep0/hal.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * CC Bootloader - Hardware Abstraction Layer - * - * Fergus Noble (c) 2011 - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "cc1111.h" - -void setup_led() { - // Setup LED and turn it off - P1DIR |= 2; - P1_1 = 0; -} - -void led_on() { - P1_1 = 1; -} - -void led_off() { - P1_1 = 0; -} - -void usb_up() { - // Bring up the USB link -#ifdef TI_DONGLE - P1DIR |= 1; - P1_0 = 1; -#elif SRF_STICK - P2DIR |= 1; - P2_0 = 1; -#endif -} - -void usb_down() { - // Bring down the USB link -#ifdef TI_DONGLE - P1_0 = 0; - P1DIR &= ~1; -#elif SRF_STICK - P2_0 = 0; - P2DIR &= ~1; -#endif -} diff --git a/usb_ep0/hal.h b/usb_ep0/hal.h deleted file mode 100644 index 1e1075c..0000000 --- a/usb_ep0/hal.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * CC Bootloader - Hardware Abstraction Layer - * - * Fergus Noble (c) 2011 - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _HAL_H_ -#define _HAL_H_ - -void setup_led(); -void led_on(); -void led_off(); - -void usb_up(); -void usb_down(); - -#endif // _HAL_H_ diff --git a/usb_ep0/serial.c b/usb_ep0/serial.c deleted file mode 100644 index beb36cd..0000000 --- a/usb_ep0/serial.c +++ /dev/null @@ -1,73 +0,0 @@ - -#include -#include "hardware.h" -#include "serial.h" -#include "radio.h" -#include "hal.h" -#include "usb.h" - -// extern int SERIAL_DATA_AVAILABLE = 0; - -void configure_serial() -{ - - setup_led( ); -// led_set_diagnostic(0,1); -// led_set_diagnostic(0,0); - usb_init( ); - usb_enable( ); - usb_up( ); - usb_flush( ); - /// GREEN_LED_PIN = 1; - -} - -uint8_t serial_has_bytes() -{ - - usb_flush( ); - if (usb_pollchar() == USB_READ_AGAIN) { -// led_set_diagnostic(0,0); - return 0; - } -// led_set_diagnostic(0,1); - return 1; -} - - -uint8_t serial_rx_byte() { - // return (uint8_t) usb_getc( ); - char c = usb_getchar( ); - return (uint8_t) c; -} - -uint16_t serial_rx_word() { - return (serial_rx_byte() << 8) + serial_rx_byte(); -} - -uint32_t serial_rx_long() { - return ((uint32_t)serial_rx_word() << 16) + serial_rx_word(); -} - - -void flush_serial( ) { -// led_set_diagnostic(0,2); - usb_flush( ); -// led_set_diagnostic(0,2); -} - -void serial_tx_byte(uint8_t tx_byte) { - // return usb_putc(tx_byte); - usb_putchar( tx_byte); - usb_flush( ); -} - -void serial_tx_str(const char *str) { - while(*str != 0) { - serial_tx_byte(*str); - str++; - } - serial_tx_byte(0); - usb_flush( ); -} - diff --git a/usb_ep0/serial.h b/usb_ep0/serial.h deleted file mode 100644 index 8cbc08e..0000000 --- a/usb_ep0/serial.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef SERIAL_H -#define SERIAL_H - -#define SERIAL_DATA_AVAILABLE serial_has_bytes( ) - -void configure_serial(); -void serial_tx_byte(uint8_t); -void serial_tx_str(const char *str); -void run_command_from_serial(); -uint8_t serial_rx_byte(); -uint8_t serial_has_bytes(); -uint32_t serial_rx_long(); -void flush_serial( ); - -#endif diff --git a/usb_ep0/usb.c b/usb_ep0/usb.c deleted file mode 100644 index 3923bf9..0000000 --- a/usb_ep0/usb.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * CC Bootloader - USB CDC class (serial) driver - * - * Adapted from AltOS code by Fergus Noble (c) 2011 - * AltOS code Copyright © 2009 Keith Packard - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "cc1111.h" -#include "usb.h" - -static __xdata uint16_t usb_in_bytes; -static __xdata uint16_t usb_in_bytes_last; -static __xdata uint16_t usb_out_bytes; -volatile static __xdata uint8_t usb_iif; -static __xdata uint8_t usb_running; - -static void usb_set_interrupts() -{ - // IN interrupts on the control an IN endpoints - USBIIE = (1 << USB_CONTROL_EP) | (1 << USB_IN_EP); - // OUT interrupts on the OUT endpoint - USBOIE = (1 << USB_OUT_EP); - // Only care about reset - USBCIE = USBCIE_RSTIE; -} - -struct usb_setup { - uint8_t dir_type_recip; - uint8_t request; - uint16_t value; - uint16_t index; - uint16_t length; -}; // } __xdata usb_setup; -__xdata static struct usb_setup usb_setup; - -__xdata uint8_t usb_ep0_state; -const uint8_t * __xdata usb_ep0_in_data; -__xdata uint8_t usb_ep0_in_len; -__xdata uint8_t usb_ep0_in_buf[2]; -__xdata uint8_t usb_ep0_out_len; -__xdata uint8_t *__xdata usb_ep0_out_data; -__xdata uint8_t usb_configuration; - -// Send an IN data packet -static void usb_ep0_flush() -{ - __xdata uint8_t this_len; - __xdata uint8_t cs0; - - // If the IN packet hasn't been picked up, just return - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_INPKT_RDY) - return; - - this_len = usb_ep0_in_len; - if (this_len > USB_CONTROL_SIZE) - this_len = USB_CONTROL_SIZE; - cs0 = USBCS0_INPKT_RDY; - if (this_len != USB_CONTROL_SIZE) { - cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END; - usb_ep0_state = USB_EP0_IDLE; - } - usb_ep0_in_len -= this_len; - while (this_len--) - USBFIFO[0] = *usb_ep0_in_data++; - USBINDEX = 0; - USBCS0 = cs0; -} - -__xdata static struct usb_line_coding usb_line_coding = {115200, 0, 0, 8}; - -// Walk through the list of descriptors and find a match -static void usb_get_descriptor(uint16_t value) -{ - __xdata uint8_t * descriptor; - // uint8_t *__xdata descriptor; - __xdata uint8_t type = value >> 8; - __xdata uint8_t index = value; - - descriptor = usb_descriptors; - while (descriptor[0] != 0) { - if (descriptor[1] == type && index-- == 0) { - if (type == USB_DESC_CONFIGURATION) - usb_ep0_in_len = descriptor[2]; - else - usb_ep0_in_len = descriptor[0]; - usb_ep0_in_data = descriptor; - break; - } - descriptor += descriptor[0]; - } -} - -// Read data from the ep0 OUT fifo -static void usb_ep0_fill() -{ - __xdata uint8_t len; - - USBINDEX = 0; - len = USBCNT0; - if (len > usb_ep0_out_len) - len = usb_ep0_out_len; - usb_ep0_out_len -= len; - while (len--) - *usb_ep0_out_data++ = USBFIFO[0]; -} - -void usb_ep0_queue_byte (uint8_t a) -{ - usb_ep0_in_buf[usb_ep0_in_len++] = a; -} - -void usb_set_address (uint8_t address) -{ - usb_running = 1; - USBADDR = address | 0x80; - while (USBADDR & 0x80) {} -} - -static void usb_set_configuration() -{ - // Set the IN max packet size, double buffered - USBINDEX = USB_IN_EP; - USBMAXI = USB_IN_SIZE >> 3; - USBCSIH |= USBCSIH_IN_DBL_BUF; - - // Set the OUT max packet size, double buffered - USBINDEX = USB_OUT_EP; - USBMAXO = USB_OUT_SIZE >> 3; - USBCSOH = USBCSOH_OUT_DBL_BUF; -} - -static void usb_ep0_setup() -{ - // Pull the setup packet out of the fifo - usb_ep0_out_data = (__xdata uint8_t *) &usb_setup; - usb_ep0_out_len = 8; - usb_ep0_fill(); - if (usb_ep0_out_len != 0) - return; - - // Figure out how to ACK the setup packet - if (usb_setup.dir_type_recip & USB_DIR_IN) { - if (usb_setup.length) - usb_ep0_state = USB_EP0_DATA_IN; - else - usb_ep0_state = USB_EP0_IDLE; - } else { - if (usb_setup.length) - usb_ep0_state = USB_EP0_DATA_OUT; - else - usb_ep0_state = USB_EP0_IDLE; - } - USBINDEX = 0; - if (usb_ep0_state == USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - - usb_ep0_in_data = usb_ep0_in_buf; - usb_ep0_in_len = 0; - switch(usb_setup.dir_type_recip & USB_SETUP_TYPE_MASK) { - case USB_TYPE_STANDARD: - switch(usb_setup.dir_type_recip & USB_SETUP_RECIP_MASK) { - case USB_RECIP_DEVICE: - switch(usb_setup.request) { - case USB_REQ_GET_STATUS: - usb_ep0_queue_byte(0); - usb_ep0_queue_byte(0); - break; - case USB_REQ_SET_ADDRESS: - usb_set_address(usb_setup.value); - break; - case USB_REQ_GET_DESCRIPTOR: - usb_get_descriptor(usb_setup.value); - break; - case USB_REQ_GET_CONFIGURATION: - usb_ep0_queue_byte(usb_configuration); - break; - case USB_REQ_SET_CONFIGURATION: - usb_configuration = usb_setup.value; - usb_set_configuration(); - break; - } - break; - case USB_RECIP_INTERFACE: - #pragma disable_warning 110 - switch(usb_setup.request) { - case USB_REQ_GET_STATUS: - usb_ep0_queue_byte(0); - usb_ep0_queue_byte(0); - break; - case USB_REQ_GET_INTERFACE: - usb_ep0_queue_byte(0); - break; - case USB_REQ_SET_INTERFACE: - break; - } - break; - case USB_RECIP_ENDPOINT: - switch(usb_setup.request) { - case USB_REQ_GET_STATUS: - usb_ep0_queue_byte(0); - usb_ep0_queue_byte(0); - break; - } - break; - } - break; - case USB_TYPE_CLASS: - switch (usb_setup.request) { - case SET_LINE_CODING: - usb_ep0_out_len = 7; - usb_ep0_out_data = (__xdata uint8_t *) &usb_line_coding; - break; - case GET_LINE_CODING: - usb_ep0_in_len = 7; - usb_ep0_in_data = (uint8_t *) &usb_line_coding; - break; - case SET_CONTROL_LINE_STATE: - break; - } - break; - } - if (usb_ep0_state != USB_EP0_DATA_OUT) { - if (usb_setup.length < usb_ep0_in_len) - usb_ep0_in_len = usb_setup.length; - usb_ep0_flush(); - } -} - -// End point 0 receives all of the control messages. -// This function must be called periodically to process ep0 messages. -static void usb_ep0() -{ - __xdata uint8_t cs0; - - // If the ep0 flag has been set by the USB interrupt then do some processing - if (usb_iif & 1) - { - usb_iif &= ~1; // clear flag - - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_SETUP_END) { - usb_ep0_state = USB_EP0_IDLE; - USBCS0 = USBCS0_CLR_SETUP_END; - } - if (cs0 & USBCS0_SENT_STALL) { - usb_ep0_state = USB_EP0_IDLE; - USBCS0 &= ~USBCS0_SENT_STALL; - } - if (usb_ep0_state == USB_EP0_DATA_IN && - (cs0 & USBCS0_INPKT_RDY) == 0) - { - usb_ep0_flush(); - } - if (cs0 & USBCS0_OUTPKT_RDY) { - switch (usb_ep0_state) { - case USB_EP0_IDLE: - usb_ep0_setup(); - break; - case USB_EP0_DATA_OUT: - usb_ep0_fill(); - if (usb_ep0_out_len == 0) - usb_ep0_state = USB_EP0_IDLE; - USBINDEX = 0; - if (usb_ep0_state == USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - break; - } - } - } -} - -// This interrupt is shared with port 2, -// so when we hook that up, fix this -void usb_isr() __interrupt 6 -{ - USBIF = 0; - usb_iif |= USBIIF; - usb_ep0(); - - if (USBCIF & USBCIF_RSTIF) - usb_set_interrupts(); -} - -// Wait for a free IN buffer -static void usb_in_wait() -{ - while (1) { - USBINDEX = USB_IN_EP; - if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) - break; - while (!(usb_iif & (1 << USB_IN_EP))) {} - } -} - -// Send the current IN packet -static void usb_in_send() -{ - USBINDEX = USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - usb_in_bytes_last = usb_in_bytes; - usb_in_bytes = 0; -} - -void usb_flush() -{ - if (!usb_running) - return; - - // If there are pending bytes, or if the last packet was full, - // send another IN packet - if (usb_in_bytes || (usb_in_bytes_last == USB_IN_SIZE)) { - usb_in_wait(); - usb_in_send(); - } -} - -void usb_putchar(char c) __reentrant -{ - if (!usb_running) - return; - - usb_in_wait(); - - // Queue a byte, sending the packet when full - USBFIFO[USB_IN_EP << 1] = c; - if (++usb_in_bytes == USB_IN_SIZE) - usb_in_send(); -} - -char usb_pollchar() -{ - char c; - if (usb_out_bytes == 0) { - USBINDEX = USB_OUT_EP; - if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return USB_READ_AGAIN; - usb_out_bytes = (USBCNTH << 8) | USBCNTL; - if (usb_out_bytes == 0) { - USBINDEX = USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - return USB_READ_AGAIN; - } - } - --usb_out_bytes; - c = USBFIFO[USB_OUT_EP << 1]; - if (usb_out_bytes == 0) { - USBINDEX = USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - } - return c; -} - -char usb_getchar() -{ - char c; - while ((c = usb_pollchar()) == USB_READ_AGAIN) - { - while (!(USBOIF & (1 << USB_OUT_EP))) {} - } - return c; -} - -void usb_enable() -{ - // Turn on the USB controller - SLEEP |= SLEEP_USB_EN; - - usb_set_configuration(); - usb_set_interrupts(); - - // enable USB interrupts - IEN2 |= IEN2_USBIE; - - // Clear any pending interrupts - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; - USBIF = 0; -} - -void usb_disable() -{ - // Disable USB interrupts - USBIIE = 0; - USBOIE = 0; - USBCIE = 0; - IEN2 &= ~IEN2_USBIE; - - // Clear any pending interrupts - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; - - // Turn off the USB controller - SLEEP &= ~SLEEP_USB_EN; -} - -void usb_init() -{ - // Init ep0 - usb_ep0_state = USB_EP0_IDLE; - usb_iif = 0; - usb_enable(); -} - -void usb_readline(char* buff) { - char c; - while ((c = usb_getchar()) != '\n') { - *buff++ = c; - } - *buff = 0; -} - -void usb_putstr(char* buff) { - while (*buff) { - usb_putchar(*buff++); - } - usb_flush(); -} - diff --git a/usb_ep0/usb.h b/usb_ep0/usb.h deleted file mode 100644 index f421cc4..0000000 --- a/usb_ep0/usb.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * CC Bootloader - USB CDC class (serial) driver - * - * Adapted from AltOS code by Fergus Noble (c) 2011 - * AltOS code Copyright © 2009 Keith Packard - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _USB_H_ -#define _USB_H_ - -// External interface - -void usb_init(); -void usb_disable(); -void usb_enable(); -char usb_getchar(); -void usb_putchar(char c); -void usb_flush(); - -void usb_putstr(char* buff); -void usb_readline(char* buff); - -char usb_pollchar(); - -// End external interface - -// USB interrupt handler -void usb_isr() __interrupt 6; - -#define USB_SETUP_DIR_MASK (0x01 << 7) -#define USB_SETUP_TYPE_MASK (0x03 << 5) -#define USB_SETUP_RECIP_MASK (0x1f) - -#define USB_DIR_OUT 0 -#define USB_DIR_IN (1 << 7) - -#define USB_TYPE_STANDARD 0 -#define USB_TYPE_CLASS (1 << 5) -#define USB_TYPE_VENDOR (2 << 5) -#define USB_TYPE_RESERVED (3 << 5) - -#define USB_RECIP_DEVICE 0 -#define USB_RECIP_INTERFACE 1 -#define USB_RECIP_ENDPOINT 2 -#define USB_RECIP_OTHER 3 - -// Standard requests -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -#define USB_DESC_DEVICE 1 -#define USB_DESC_CONFIGURATION 2 -#define USB_DESC_STRING 3 -#define USB_DESC_INTERFACE 4 -#define USB_DESC_ENDPOINT 5 -#define USB_DESC_DEVICE_QUALIFIER 6 -#define USB_DESC_OTHER_SPEED 7 -#define USB_DESC_INTERFACE_POWER 8 - -#define USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define USB_CONTROL_EP 0 -#define USB_INT_EP 1 -#define USB_OUT_EP 4 -#define USB_IN_EP 5 -#define USB_CONTROL_SIZE 32 - -// Double buffer IN and OUT EPs, so each -// gets half of the available space -// -// Ah, but USB bulk packets can only come in 8, 16, 32 and 64 -// byte sizes, so we'll use 64 for everything -#define USB_IN_SIZE 64 -#define USB_OUT_SIZE 64 - -#define USB_EP0_IDLE 0 -#define USB_EP0_DATA_IN 1 -#define USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -// CDC definitions -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -// Data structure for GET_LINE_CODING / SET_LINE_CODING class requests -struct usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -}; - -#define USB_READ_AGAIN ((char) -1) - -#define USB_VID 0x1d50 -#define USB_PID 0x8001 - -// iManufacturer -#define USB_iManufacturer_LEN 0x16 -#define USB_iManufacturer_STRING "Nightscout" -#define USB_iManufacturer_UCS2 'N', 0, 'i', 0, 'g', 0, 'h', 0, 't', 0, 's', 0, 'c', 0, 'o', 0, 'u', 0, 't', 0 -// iProduct -#define USB_iProduct_LEN 0x16 -#define USB_iProduct_STRING "subg_rfspy" -#define USB_iProduct_UCS2 's', 0, 'u', 0, 'b', 0, 'g', 0, '_', 0, 'r', 0, 'f', 0, 's', 0, 'p', 0, 'y', 0 -// iSerial -#define USB_iSerial_LEN 0x0e -#define USB_iSerial_STRING "000002" -#define USB_iSerial_UCS2 '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '2', 0 - -// extern __code __at(0x00aa) uint8_t usb_descriptors[]; -extern __xdata uint8_t usb_descriptors[]; - -#endif // _USB_H_ diff --git a/usb_ep0/usb_descriptors.c b/usb_ep0/usb_descriptors.c deleted file mode 100644 index f63b500..0000000 --- a/usb_ep0/usb_descriptors.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * CC Bootloader - USB descriptors - * - * Adapted from AltOS code by Fergus Noble (c) 2011 - * AltOS code Copyright © 2009 Keith Packard - * - * 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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "cc1111.h" -#include "usb.h" - -// USB descriptors in one giant block of bytes -// __code __at(0x00aa) uint8_t usb_descriptors [] = -__xdata uint8_t usb_descriptors [] = -{ - // Device descriptor - 0x12, - USB_DESC_DEVICE, - LE_WORD(0x0110), // bcdUSB - 0x02, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - USB_CONTROL_SIZE, // bMaxPacketSize - LE_WORD(USB_VID), // idVendor - LE_WORD(USB_PID), // idProduct - LE_WORD(0x010), // bcdDevice - 0x01, // iManufacturer - 0x02, // iProduct - 0x03, // iSerialNumber - 0x01, // bNumConfigurations - - // Configuration descriptor - 0x09, - USB_DESC_CONFIGURATION, - LE_WORD(67), // wTotalLength - 0x02, // bNumInterfaces - 0x01, // bConfigurationValue - 0x00, // iConfiguration - 0xC0, // bmAttributes - 0x32, // bMaxPower - - // Control class interface - 0x09, - USB_DESC_INTERFACE, - 0x00, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x01, // bNumEndPoints - 0x02, // bInterfaceClass - 0x02, // bInterfaceSubClass - 0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module - 0x00, // iInterface - - // Header functional descriptor - 0x05, - CS_INTERFACE, - 0x00, // bDescriptor SubType Header - LE_WORD(0x0110), // CDC version 1.1 - - // Call management functional descriptor - 0x05, - CS_INTERFACE, - 0x01, // bDescriptor SubType Call Management - 0x01, // bmCapabilities = device handles call management - 0x01, // bDataInterface call management interface number - - // ACM functional descriptor - 0x04, - CS_INTERFACE, - 0x02, // bDescriptor SubType Abstract Control Management - 0x02, // bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) - - // Union functional descriptor - 0x05, - CS_INTERFACE, - 0x06, // bDescriptor SubType Union Functional descriptor - 0x00, // bMasterInterface - 0x01, // bSlaveInterface0 - - // Notification EP - 0x07, - USB_DESC_ENDPOINT, - USB_INT_EP|0x80, // bEndpointAddress - 0x03, // bmAttributes = intr - LE_WORD(8), // wMaxPacketSize - 0x0A, // bInterval - - // Data class interface descriptor - 0x09, - USB_DESC_INTERFACE, - 0x01, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x02, // bNumEndPoints - 0x0A, // bInterfaceClass = data - 0x00, // bInterfaceSubClass - 0x00, // bInterfaceProtocol - 0x00, // iInterface - - // Data EP OUT - 0x07, - USB_DESC_ENDPOINT, - USB_OUT_EP, // bEndpointAddress - 0x02, // bmAttributes = bulk - LE_WORD(USB_OUT_SIZE), // wMaxPacketSize - 0x00, // bInterval - - // Data EP in - 0x07, - USB_DESC_ENDPOINT, - USB_IN_EP|0x80, // bEndpointAddress - 0x02, // bmAttributes = bulk - LE_WORD(USB_IN_SIZE), // wMaxPacketSize - 0x00, // bInterval - - // String descriptors - 0x04, - USB_DESC_STRING, - LE_WORD(0x0409), - - // iManufacturer - USB_iManufacturer_LEN, - USB_DESC_STRING, - USB_iManufacturer_UCS2, - - // iProduct - USB_iProduct_LEN, - USB_DESC_STRING, - USB_iProduct_UCS2, - - // iSerial - USB_iSerial_LEN, - USB_DESC_STRING, - USB_iSerial_UCS2, - - // Terminating zero - 0 -}; From cea782c40fd04c0c801a771f989a1b1bd9901808 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 22 Jun 2018 06:36:47 -0500 Subject: [PATCH 42/45] fix test building --- timer.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/timer.h b/timer.h index e26c112..2c96aeb 100644 --- a/timer.h +++ b/timer.h @@ -4,6 +4,11 @@ #include #include +#ifdef __GNUC__ +#define inline static inline +#endif + + volatile extern uint32_t __timerCounter; void init_timer(); From d2dd020419fd70fb9111553c78e6c7b9851d701a Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Fri, 22 Jun 2018 06:39:54 -0500 Subject: [PATCH 43/45] sleep needed for test timing --- tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.c b/tests.c index 48dba27..c5cce0c 100644 --- a/tests.c +++ b/tests.c @@ -65,7 +65,7 @@ void do_spi(const uint8_t *input, uint8_t *output, uint8_t len) output[i] = slave_byte; } rx1_isr(); - //tiny_sleep(); + tiny_sleep(); } if (output) { From 02d9af98f5779a4e1f3299d845a2c892cc999642 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Sun, 24 Jun 2018 23:33:58 -0500 Subject: [PATCH 44/45] Statistics (#59) * Add statistics tracking and reporting * Move more vars from pdata to xdata. * Make sure hardware and __xdata are included earlier in tests.c * success code before data, and rx count before tx --- commands.c | 26 ++++++++++++++++++++++++-- commands.h | 3 ++- common.mk | 2 +- encoding.h | 3 +-- hardware.c | 4 ++-- hardware.h | 4 ++-- radio.c | 19 +++++++++---------- spi1_alt2/serial.c | 18 +++++++++++++++++- spi1_alt2/serial.h | 2 ++ statistics.c | 9 +++++++++ statistics.h | 14 ++++++++++++++ subg_rfspy.c | 4 ++-- subg_rfspy.h | 4 ++-- tests.c | 2 +- 14 files changed, 88 insertions(+), 26 deletions(-) create mode 100644 statistics.c create mode 100644 statistics.h diff --git a/commands.c b/commands.c index 9d95da2..388b490 100644 --- a/commands.c +++ b/commands.c @@ -7,6 +7,8 @@ #include "commands.h" #include "encoding.h" #include "version.h" +#include "statistics.h" +#include "timer.h" uint8_t interrupting_cmd = 0; @@ -211,7 +213,26 @@ void cmd_reset_radio_config() { serial_flush(); } -CommandHandler handlers[] = { +void cmd_get_statistics() +{ + uint32_t uptime_ms; + + serial_tx_byte(RESPONSE_CODE_SUCCESS); + read_timer(&uptime_ms); + serial_tx_long(uptime_ms); + serial_tx_word(radio_rx_overflow_count); + serial_tx_word(radio_rx_fifo_overflow_count); + serial_tx_word(packet_rx_count); + serial_tx_word(packet_tx_count); + serial_tx_word(crc_failure_count); + serial_tx_word(spi_sync_failure_count); + serial_tx_word(0); // Placeholder + serial_tx_word(0); // Placeholder + serial_flush(); +} + + +CommandHandler __xdata handlers[] = { /* 0 */ 0, /* 1 */ cmd_get_state, /* 2 */ cmd_get_version, @@ -225,7 +246,8 @@ CommandHandler handlers[] = { /* 10 */ cmd_set_mode_registers, /* 11 */ cmd_set_sw_encoding, /* 12 */ cmd_set_preamble, - /* 13 */ cmd_reset_radio_config + /* 13 */ cmd_reset_radio_config, + /* 14 */ cmd_get_statistics }; void do_cmd(uint8_t cmd) { diff --git a/commands.h b/commands.h index 7ff4cf4..26bd27a 100644 --- a/commands.h +++ b/commands.h @@ -20,7 +20,8 @@ enum CommandCode { CmdSetModeRegisters = 0x0a, CmdSetSWEncoding = 0x0b, CmdSetPreamble = 0x0c, - CmdResetRadioConfig = 0x0d + CmdResetRadioConfig = 0x0d, + CmdGetStatistics = 0x0e }; enum RegisterMode { diff --git a/common.mk b/common.mk index d5ce81f..73624ea 100755 --- a/common.mk +++ b/common.mk @@ -22,7 +22,7 @@ CFLAGS+=-I. -I${SERIAL_TYPE} ${RADIO_LOCALE_DEF} -D${BOARD_TYPE} ${BOARD_PARAMS} default: output output/${TARGET_BUILD} output/${TARGET_BUILD}/${TARGET_BUILD}.hex common_modules = $(main_module) subg_rfspy.rel radio.rel timer.rel encoding.rel manchester.rel \ - fourbsixb.rel commands.rel hardware.rel packet_buffer.rel + fourbsixb.rel commands.rel hardware.rel packet_buffer.rel statistics.rel clean: rm -rf output/${TARGET_BUILD} diff --git a/encoding.h b/encoding.h index 66268dc..490b1e3 100644 --- a/encoding.h +++ b/encoding.h @@ -48,8 +48,7 @@ typedef struct { typedef struct { // Adds a byte for decoding. The return value will be 1 if the byte // contains encoding errors, otherwise it will be 0. - uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t encoded) - __reentrant; + uint8_t (*add_encoded_byte)(DecoderState *state, uint8_t encoded) __reentrant; // decoded will be set to the next available decoded byte. // Return value is 0 if no more bytes are available. uint8_t (*next_decoded_byte)(DecoderState *state, uint8_t *decoded) __reentrant; diff --git a/hardware.c b/hardware.c index 11637ee..03c8d48 100644 --- a/hardware.c +++ b/hardware.c @@ -10,8 +10,8 @@ static LEDMode green_mode = 0; static LEDMode blue_mode = 0; -mode_registers tx_registers; -mode_registers rx_registers; +mode_registers __xdata tx_registers; +mode_registers __xdata rx_registers; void init_leds() { // init LEDS diff --git a/hardware.h b/hardware.h index c45d9dc..068b4a9 100644 --- a/hardware.h +++ b/hardware.h @@ -104,7 +104,7 @@ void mode_registers_clear(mode_registers *mode); void mode_registers_add(mode_registers *mode, uint8_t addr, uint8_t value); void mode_registers_enact(mode_registers const *mode); -extern mode_registers tx_registers; -extern mode_registers rx_registers; +extern mode_registers __xdata tx_registers; +extern mode_registers __xdata rx_registers; #endif diff --git a/radio.c b/radio.c index c9be8f4..81f91e8 100644 --- a/radio.c +++ b/radio.c @@ -7,6 +7,7 @@ #include "timer.h" #include "encoding.h" #include "fifo.h" +#include "statistics.h" #include "radio.h" #define RX_FIFO_SIZE 32 @@ -23,13 +24,7 @@ static volatile uint8_t __xdata radio_tx_buf_len; static volatile uint16_t __xdata preamble_word; static volatile uint8_t stop_custom_preamble_semaphore; -// Error stats -volatile uint16_t __xdata rx_overflow; -volatile uint16_t __xdata tx_underflow; -volatile uint16_t __xdata packet_count; - // TX States - enum TxState { TxStatePreambleByte0 = 0x00, TxStatePreambleByte1 = 0x01, @@ -117,7 +112,7 @@ bool set_encoding_type(EncodingType new_type) { inline void put_rx(uint8_t data) { if (!fifo_put(&rx_fifo, data)) { - rx_overflow++; + radio_rx_fifo_overflow_count++; } } @@ -127,8 +122,7 @@ void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { d_byte = RFD; if (rx_len == 0) { put_rx(RSSI); - put_rx(packet_count); - packet_count++; + put_rx(packet_rx_count & 0xff); rx_len = 2; } put_rx(d_byte); @@ -163,7 +157,6 @@ void rftxrx_isr(void) __interrupt RFTXRX_VECTOR { } break; case TxStateDone: - tx_underflow++; // Letting RFD go empty will make the radio stop TX mode. //RFD = 0; break; @@ -184,6 +177,7 @@ void rf_isr(void) __interrupt RF_VECTOR { } else if(RFIF & 0x40) // RX overflow { + radio_rx_overflow_count++; RFIF &= ~0x40; // Clear module interrupt flag } else if(RFIF & 0x20) // RX timeout @@ -242,6 +236,7 @@ void send_from_tx_buf(uint8_t channel, uint16_t preamble_extend_ms) { pktlen_save = PKTLEN; pktctrl0_save = PKTCTRL0; + packet_tx_count++; if (preamble_word != 0) { // save and turn off preamble/sync registers @@ -380,6 +375,10 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin fifo_get(&rx_fifo); } + if (rval == 0) { + packet_rx_count++; + } + led_set_diagnostic(BlueLED, LEDStateOff); return rval; } diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index 67cd908..f2106e8 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -5,6 +5,7 @@ #include "subg_rfspy.h" #include "serial.h" #include "radio.h" +#include "statistics.h" #include "fifo.h" #define SPI_BUF_LEN 128 @@ -110,6 +111,7 @@ void rx1_isr(void) __interrupt URX1_VECTOR break; case SPI_MODE_IDLE: if (value != 0x99) { + spi_sync_failure_count++; spi_mode = SPI_MODE_OUT_OF_SYNC; } else { spi_mode = SPI_MODE_SIZE; @@ -117,6 +119,7 @@ void rx1_isr(void) __interrupt URX1_VECTOR break; case SPI_MODE_SIZE: if (value > SPI_BUF_LEN) { + spi_sync_failure_count++; spi_mode = SPI_MODE_OUT_OF_SYNC; return; } @@ -176,7 +179,6 @@ uint8_t serial_rx_avail() uint8_t serial_rx_byte() { - time_t last_time; uint8_t s_data; if (!serial_data_available) { while(!serial_data_available && !subg_rfspy_should_exit); @@ -203,6 +205,20 @@ void serial_tx_byte(uint8_t tx_byte) fifo_put(&output_buffer, tx_byte); } +void serial_tx_word(uint16_t tx_word) +{ + fifo_put(&output_buffer, tx_word >> 8); + fifo_put(&output_buffer, tx_word & 0xff); +} + +void serial_tx_long(uint32_t tx_long) +{ + fifo_put(&output_buffer, tx_long >> 24); + fifo_put(&output_buffer, (tx_long >> 16) & 0xff); + fifo_put(&output_buffer, (tx_long >> 8) & 0xff); + fifo_put(&output_buffer, tx_long & 0xff); +} + void serial_flush() { if (fifo_empty(&output_buffer)) { diff --git a/spi1_alt2/serial.h b/spi1_alt2/serial.h index 2295f50..52c1425 100644 --- a/spi1_alt2/serial.h +++ b/spi1_alt2/serial.h @@ -9,6 +9,8 @@ extern volatile uint8_t serial_data_available; void configure_serial(); void serial_tx_byte(uint8_t); +void serial_tx_word(uint16_t tx_word); +void serial_tx_long(uint32_t tx_long); void serial_tx_str(const char *str); void serial_flush(); uint8_t serial_rx_byte(); diff --git a/statistics.c b/statistics.c new file mode 100644 index 0000000..b8ca8c4 --- /dev/null +++ b/statistics.c @@ -0,0 +1,9 @@ + +#include "statistics.h" + +volatile uint16_t radio_rx_overflow_count; +volatile uint16_t radio_rx_fifo_overflow_count; +uint16_t packet_rx_count; +uint16_t packet_tx_count; +uint16_t crc_failure_count; +volatile uint16_t spi_sync_failure_count; diff --git a/statistics.h b/statistics.h new file mode 100644 index 0000000..445043f --- /dev/null +++ b/statistics.h @@ -0,0 +1,14 @@ +#ifndef STATISTICS_H +#define STATISTICS_H + +#include + +volatile extern uint16_t radio_rx_overflow_count; +volatile extern uint16_t radio_rx_fifo_overflow_count; +volatile extern uint16_t serial_rx_overflow_count; +extern uint16_t packet_tx_count; +extern uint16_t packet_rx_count; +extern uint16_t crc_failure_count; +volatile extern uint16_t spi_sync_failure_count; + +#endif //STATISTICS_H diff --git a/subg_rfspy.c b/subg_rfspy.c index fa09b7d..999f91f 100644 --- a/subg_rfspy.c +++ b/subg_rfspy.c @@ -9,8 +9,8 @@ #include "commands.h" #include "subg_rfspy.h" -bool subg_rfspy_init_finished; -bool subg_rfspy_should_exit; +bool __xdata subg_rfspy_init_finished; +bool __xdata subg_rfspy_should_exit; void subg_rfspy_main() { // Set the system clock source to HS XOSC and max CPU speed, diff --git a/subg_rfspy.h b/subg_rfspy.h index 1d75ecd..1298901 100644 --- a/subg_rfspy.h +++ b/subg_rfspy.h @@ -5,7 +5,7 @@ void subg_rfspy_main(); -extern bool subg_rfspy_init_finished; -extern bool subg_rfspy_should_exit; +extern bool __xdata subg_rfspy_init_finished; +extern bool __xdata subg_rfspy_should_exit; #endif // SUBG_RFSPY_H diff --git a/tests.c b/tests.c index c5cce0c..e19e61c 100644 --- a/tests.c +++ b/tests.c @@ -4,10 +4,10 @@ #include #include #include +#include "hardware.h" #include "subg_rfspy.h" #include "serial.h" #include "commands.h" -#include "hardware.h" #include "version.h" #define RESPONSE_BUFFER_SIZE 128 From de25f35f6e3c47373c94a0ab7ddf83a907e99c92 Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Mon, 25 Jun 2018 21:46:37 -0500 Subject: [PATCH 45/45] Watchdog timer (#60) * bump version * fix tests * Feed wdt during send repeats, and during delays * Add 5s timeout for flushing responses * Make mock clock run a little slower, to allow tests to pass --- hardware.h | 8 ++++++++ mock_hardware.c | 25 +++++++++++++++++++------ mock_hardware.h | 4 ++++ radio.c | 4 ++++ spi1_alt2/serial.c | 27 ++++++++++++++++++++++++--- subg_rfspy.c | 3 +++ timer.c | 6 ++++-- timer.h | 5 ----- version.h | 2 +- 9 files changed, 67 insertions(+), 17 deletions(-) diff --git a/hardware.h b/hardware.h index 068b4a9..9fa78d1 100644 --- a/hardware.h +++ b/hardware.h @@ -107,4 +107,12 @@ void mode_registers_enact(mode_registers const *mode); extern mode_registers __xdata tx_registers; extern mode_registers __xdata rx_registers; +#define WDCLP1 0xA0 // Clear pattern 1 +#define WDCLP2 0x50 // Clear pattern 2 + +inline void feed_watchdog() { + WDCTL = WDCLP1 | WDCTL_EN; + WDCTL = WDCLP2 | WDCTL_EN; +} + #endif diff --git a/mock_hardware.c b/mock_hardware.c index 553fc22..46b0572 100644 --- a/mock_hardware.c +++ b/mock_hardware.c @@ -2,8 +2,10 @@ #include #include #include +#include #include "hardware.h" + volatile uint8_t P0_0; volatile uint8_t P0_1; volatile uint8_t P0DIR; @@ -79,21 +81,32 @@ volatile uint8_t U1DBUF_read; bool mock_hardware_should_exit; +// This is 10x normal clock speed +#define MOCK_CLOCK_TICK_RATE 0.0001 + void *run_mock_hardware(void *vargp) { + clock_t start_time; // Mark oscillator as powered up and stable SLEEP |= SLEEP_XOSC_S; printf("starting mock hardware thread\n"); + start_time = clock(); + while(!mock_hardware_should_exit) { - // Run counter - if (T1CNTL == 255) { - T1CNTH += 1; + + double elapsed = ((double)(clock() - start_time))/CLOCKS_PER_SEC; + + if (elapsed > MOCK_CLOCK_TICK_RATE) { + // Run counter + if (T1CNTL == 255) { + T1CNTH += 1; + } + T1CNTL += 1; + t1_isr(); + start_time = clock(); } - T1CNTL += 1; - t1_isr(); - //printf("SLEEP = %d\n", SLEEP); // Watch radio strobe registers if(RFST == RFST_SIDLE) { diff --git a/mock_hardware.h b/mock_hardware.h index 80c927e..7d80e9a 100644 --- a/mock_hardware.h +++ b/mock_hardware.h @@ -4,6 +4,10 @@ #include #include +#ifdef __GNUC__ +#define inline static inline +#endif + #define __reentrant #define __xdata #define __interrupt diff --git a/radio.c b/radio.c index 81f91e8..7d389fc 100644 --- a/radio.c +++ b/radio.c @@ -220,6 +220,7 @@ void send_packet_from_serial(uint8_t channel, uint8_t repeat_count, uint16_t del if (send_count > 0 && delay_ms > 0) { delay(delay_ms); } + feed_watchdog(); send_from_tx_buf(channel, preamble_extend_ms); @@ -321,6 +322,9 @@ uint8_t get_packet_and_write_to_serial(uint8_t channel, uint32_t timeout_ms, uin while(MARCSTATE!=MARC_STATE_RX); while(1) { + + feed_watchdog(); + // Waiting for isr to put radio bytes into rx_fifo if (!fifo_empty(&rx_fifo)) { diff --git a/spi1_alt2/serial.c b/spi1_alt2/serial.c index f2106e8..f723c73 100644 --- a/spi1_alt2/serial.c +++ b/spi1_alt2/serial.c @@ -7,8 +7,10 @@ #include "radio.h" #include "statistics.h" #include "fifo.h" +#include "timer.h" #define SPI_BUF_LEN 128 +#define FLUSH_TIMEOUT_MS 5000 static fifo_buffer __xdata input_buffer; static volatile uint8_t __xdata input_buffer_mem[SPI_BUF_LEN]; @@ -181,7 +183,9 @@ uint8_t serial_rx_byte() { uint8_t s_data; if (!serial_data_available) { - while(!serial_data_available && !subg_rfspy_should_exit); + while(!serial_data_available && !subg_rfspy_should_exit) { + feed_watchdog(); + } } s_data = fifo_get(&input_buffer); if (fifo_empty(&input_buffer)) { @@ -221,12 +225,29 @@ void serial_tx_long(uint32_t tx_long) void serial_flush() { + uint32_t start_time; + if (fifo_empty(&output_buffer)) { return; } + + // Waiting for tx isr to ask for data + read_timer(&start_time); ready_to_send = 1; - while(!fifo_empty(&output_buffer) && !subg_rfspy_should_exit); - while(slave_send_size != 0 && !subg_rfspy_should_exit); + while(!fifo_empty(&output_buffer) && !subg_rfspy_should_exit) { + feed_watchdog(); + if (check_elapsed(start_time, FLUSH_TIMEOUT_MS)) { + break; + } + } + + // Waiting to finish spi transfer + while(slave_send_size != 0 && !subg_rfspy_should_exit) { + feed_watchdog(); + if (check_elapsed(start_time, FLUSH_TIMEOUT_MS)) { + break; + } + } ready_to_send = 0; } diff --git a/subg_rfspy.c b/subg_rfspy.c index 999f91f..d781ee6 100644 --- a/subg_rfspy.c +++ b/subg_rfspy.c @@ -40,6 +40,9 @@ void subg_rfspy_main() { subg_rfspy_init_finished = true; + // Start watchdog at 1s interval + WDCTL = WDCTL_EN; + while(!subg_rfspy_should_exit) { get_command(); } diff --git a/timer.c b/timer.c index 919c86d..9485ef2 100644 --- a/timer.c +++ b/timer.c @@ -16,7 +16,7 @@ void init_timer() { uint16_t timer_ticks_per_ms = (SYSTEM_CLOCK_MHZ * 1000) / 128 / 2; __timerCounter = 0; - + T1CTL = 0x00; // disable timer T1CNTL = 0x00; // Clear counter low @@ -51,5 +51,7 @@ void t1_isr(void) __interrupt T1_VECTOR void delay(uint32_t msec) { uint32_t start_time; read_timer(&start_time); - while(!check_elapsed(start_time, msec)); + while(!check_elapsed(start_time, msec)) { + feed_watchdog(); + } } diff --git a/timer.h b/timer.h index 2c96aeb..e26c112 100644 --- a/timer.h +++ b/timer.h @@ -4,11 +4,6 @@ #include #include -#ifdef __GNUC__ -#define inline static inline -#endif - - volatile extern uint32_t __timerCounter; void init_timer(); diff --git a/version.h b/version.h index 91cdbbc..047028b 100644 --- a/version.h +++ b/version.h @@ -1,6 +1,6 @@ #ifndef VERSION_H #define VERSION_H -#define SUBG_RFSPY_VERSION "subg_rfspy 2.1" +#define SUBG_RFSPY_VERSION "subg_rfspy 2.2" #endif //VERSION_H