]> mj.ucw.cz Git - home-hw.git/blobdiff - bsb/firmware/main.c
BSB: Receiving works
[home-hw.git] / bsb / firmware / main.c
index e7237e1cf5101cc6f7fdb8b269a34fa5c2773e8e..4e10dc5b563dab8d32eba3ead6e497155df6376c 100644 (file)
@@ -30,12 +30,14 @@ static void clock_init(void)
        rcc_periph_clock_enable(RCC_GPIOB);
        rcc_periph_clock_enable(RCC_GPIOC);
        rcc_periph_clock_enable(RCC_USART1);
+       rcc_periph_clock_enable(RCC_USART3);
        rcc_periph_clock_enable(RCC_USB);
 
        rcc_periph_reset_pulse(RST_GPIOA);
        rcc_periph_reset_pulse(RST_GPIOB);
        rcc_periph_reset_pulse(RST_GPIOC);
        rcc_periph_reset_pulse(RST_USART1);
+       rcc_periph_reset_pulse(RST_USART3);
        rcc_periph_reset_pulse(RST_USB);
 }
 
@@ -84,7 +86,7 @@ void sys_tick_handler(void)
 
 static void tick_init(void)
 {
-       systick_set_frequency(1000, 72000000);
+       systick_set_frequency(1000, CPU_CLOCK_MHZ * 1000000);
        systick_counter_enable();
        systick_interrupt_enable();
 }
@@ -99,10 +101,18 @@ static void delay_ms(uint ms)
 /*** BSB ***/
 
 #define BSB_MAX_SIZE 32
-#define BSB_RX_TIMEOUT 2  // 1-2 ms => 2-4 byte periods of silence
+#define BSB_RX_TIMEOUT 10  // ms
+
+#define DEBUG_BSB
+#ifdef DEBUG_BSB
+#define BSB_DEBUG(x...) debug_printf(x)
+#else
+#define BSB_DEBUG(x...) do { } while (0)
+#endif
 
 static byte bsb_rx_buf[BSB_MAX_SIZE];
 static byte bsb_rx_len;
+static u16 bsb_rx_crc;
 static volatile u32 bsb_rx_timestamp;
 
 // Passing received frames to the main loop
@@ -116,26 +126,49 @@ struct bsb_stat {
        u32 rx_invalid;
        u32 rx_overruns;
        u32 rx_timeouts;
+       u32 rx_bad_crc;
+       u32 rx_ok;
 };
 
 static struct bsb_stat bsb_stat;
 
+static u16 bsb_crc_update(u16 crc, byte data)
+{
+       crc = crc ^ (data << 8);
+       for (uint i=0; i<8; i++) {
+               if (crc & 0x8000)
+                       crc = (crc << 1) ^ 0x1021;
+               else
+                       crc <<= 1;
+       }
+       return crc;
+}
+
 void usart3_isr(void)
 {
        u32 status = USART_SR(USART3);
 
        if (status & USART_SR_RXNE) {
-               uint ch = usart_recv(USART3);
+               uint ch = ~usart_recv(USART3) & 0xff;
                bsb_rx_timestamp = ms_ticks;
+               BSB_DEBUG(" %02x", ch);
 
                if (status & (USART_SR_FE | USART_SR_ORE | USART_SR_NE)) {
                        bsb_stat.rx_errors++;
                        bsb_rx_len = 0;
-               } else if (!bsb_rx_len && ch != 0xdc) {
-                       // Waiting for start of frame
-                       bsb_stat.rx_noise++;
+               } else if (!bsb_rx_len) {
+                       // Start of frame
+                       if (ch == 0xdc) {
+                               bsb_rx_buf[bsb_rx_len++] = ch;
+                               bsb_rx_crc = bsb_crc_update(0, ch);
+                               BSB_DEBUG("<");
+                       } else {
+                               bsb_stat.rx_noise++;
+                               BSB_DEBUG("?");
+                       }
                } else {
                        bsb_rx_buf[bsb_rx_len++] = ch;
+                       bsb_rx_crc = bsb_crc_update(bsb_rx_crc, ch);
                        if (bsb_rx_len < 4) {
                                // First three bytes: SOF, source addr, destination addr
                        } else if (bsb_rx_len == 4) {
@@ -143,19 +176,28 @@ void usart3_isr(void)
                                if (bsb_rx_buf[3] < 7 || bsb_rx_buf[3] > BSB_MAX_SIZE) {
                                        bsb_stat.rx_invalid++;
                                        bsb_rx_len = 0;
+                                       BSB_DEBUG("!L");
                                }
                        } else if (bsb_rx_len == bsb_rx_buf[3]) {
-                               // Received a complete frame: pass it to the main loop
-                               if (bsb_rx_frame_len) {
-                                       // The previous one was not sent yet
-                                       bsb_stat.rx_overruns++;
+                               // Received a complete frame: check CRC and pass it to the main loop
+                               if (bsb_rx_crc) {
+                                       bsb_stat.rx_bad_crc++;
+                                       BSB_DEBUG("!C");
                                } else {
-                                       memcpy(bsb_rx_frame, bsb_rx_buf, bsb_rx_buf[3]);
-                                       barrier();
-                                       bsb_rx_frame_len = bsb_rx_buf[3];
-                                       bsb_rx_frame_led = 100;
+                                       if (bsb_rx_frame_len) {
+                                               // The previous one was not sent yet
+                                               bsb_stat.rx_overruns++;
+                                               BSB_DEBUG("!O");
+                                       } else {
+                                               memcpy(bsb_rx_frame, bsb_rx_buf, bsb_rx_buf[3]);
+                                               bsb_rx_frame_len = bsb_rx_buf[3];
+                                               bsb_stat.rx_ok++;
+                                               BSB_DEBUG(".");
+                                       }
                                        gpio_clear(GPIOB, GPIO1);
+                                       bsb_rx_frame_led = 100;
                                }
+                               bsb_rx_len = 0;
                        }
                }
        }
@@ -166,7 +208,7 @@ static void bsb_init(void)
        usart_set_baudrate(USART3, 4800);
        usart_set_databits(USART3, 9);
        usart_set_stopbits(USART3, USART_STOPBITS_1);
-       usart_set_mode(USART3, USART_MODE_TX_RX);
+       usart_set_mode(USART3, USART_MODE_RX);
        usart_set_parity(USART3, USART_PARITY_ODD);
        usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE);
 
@@ -292,7 +334,7 @@ static enum usbd_request_return_codes control_cb(
                return USBD_REQ_NOTSUPP;
 
        // We support reading of statistics via control requests
-       debug_printf("USB: Control request: Read statistics\n");
+       debug_printf("USB: Reading statistics\n");
        uint n = MIN(*len, sizeof(bsb_stat));
        memcpy(*buf, (char *) &bsb_stat, n);
        *len = n;
@@ -443,9 +485,10 @@ int main(void)
                // Packet timeouts
                cm_disable_interrupts();
                barrier();
-               if (bsb_rx_len && (bsb_rx_timestamp - ms_ticks) >= BSB_RX_TIMEOUT) {
+               if (bsb_rx_len && ms_ticks - bsb_rx_timestamp >= BSB_RX_TIMEOUT) {
                        bsb_rx_len = 0;
                        bsb_stat.rx_timeouts++;
+                       BSB_DEBUG("!T");
                }
                if (bsb_rx_frame_led) {
                        if (!--bsb_rx_frame_led)