altos: Mostly working SPI radio link
authorKeith Packard <keithp@keithp.com>
Wed, 29 Aug 2012 01:13:02 +0000 (18:13 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 29 Aug 2012 06:00:23 +0000 (23:00 -0700)
This includes long delays to avoid overrunning the cc1111 input,
otherwise it works pretty well. The delays mean that we can't capture
the reply to a cmac command though, so more work is needed.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/cc1111/ao_arch_funcs.h
src/cc1111/ao_spi.c
src/drivers/ao_radio_master.c
src/drivers/ao_radio_slave.c

index 5e2fc13db1ab808f8a6e5eda1607d5fe871626d5..8f1cc09476e099766247de88705fe3bbd22bb54d 100644 (file)
@@ -77,6 +77,14 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant;
 #define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len)
 #define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len)
 
+#if AO_SPI_SLAVE
+void
+ao_spi_send_wait(void);
+
+void
+ao_spi_recv_wait(void);
+#endif
+
 void
 ao_spi_init(void);
 
index 2b4fd186aa843b0435100d985aece4a9b3365dd7..39d459f1f224ebcf9af1bdfd5d4f91fceb4f852b 100644 (file)
@@ -171,16 +171,20 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant
 #endif
        ao_dma_start(ao_spi_dma_out_id);
        ao_dma_trigger(ao_spi_dma_out_id);
-#if AO_SPI_SLAVE
-       __critical while (!ao_spi_dma_out_done)
-                          ao_sleep(&ao_spi_dma_out_done);
-#else
+#if !AO_SPI_SLAVE
        __critical while (!ao_spi_dma_in_done)
                ao_sleep(&ao_spi_dma_in_done);
 #endif
 }
 
-
+#if AO_SPI_SLAVE
+void
+ao_spi_send_wait(void)
+{
+       __critical while (!ao_spi_dma_out_done)
+               ao_sleep(&ao_spi_dma_out_done);
+}
+#endif
 
 /* Receive bytes over SPI.
  *
@@ -221,11 +225,19 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant
 #if !AO_SPI_SLAVE
        ao_dma_start(ao_spi_dma_out_id);
        ao_dma_trigger(ao_spi_dma_out_id);
-#endif
        __critical while (!ao_spi_dma_in_done)
                ao_sleep(&ao_spi_dma_in_done);
+#endif
 }
 
+#if AO_SPI_SLAVE
+void
+ao_spi_recv_wait(void)
+{
+       __critical while (!ao_spi_dma_in_done)
+               ao_sleep(&ao_spi_dma_in_done);
+}
+#endif
 
 void
 ao_spi_init(void)
index 6edea66dd7c96853a8b31fe7147d70662114916b..bfbcb1f8d757e7336806f1b0fdb60a805a801624 100644 (file)
 
 static __xdata struct ao_radio_spi_reply       ao_radio_spi_reply;
 static __xdata struct ao_radio_spi_request     ao_radio_spi_request;
-static __xdata uint8_t                         ao_radio_done;
+static volatile __xdata uint8_t                        ao_radio_done = 1;
 static __xdata uint8_t                         ao_radio_mutex;
 
 __xdata int8_t                                 ao_radio_cmac_rssi;
 
+#if 0
+#define PRINTD(...) do { printf ("\r%s: ", __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(...) 
+#endif
+
 static void
 ao_radio_isr(void)
 {
        ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
        ao_radio_done = 1;
-       ao_wakeup(&ao_radio_done);
+       ao_wakeup((void *) &ao_radio_done);
+}
+
+static void
+ao_radio_master_delay(void)
+{
+//     uint16_t        i;
+//     for (i = 0; i < 1000; i++)
+//             ao_arch_nop();
+       ao_delay(1);
 }
 
 static void
 ao_radio_master_start(void)
 {
+       ao_radio_master_delay();
        ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
                       AO_RADIO_SPI_BUS,
-                      AO_SPI_SPEED_1MHz);
+                      AO_SPI_SPEED_200kHz);
 }
 
 static void
@@ -48,12 +64,15 @@ ao_radio_master_stop(void)
 {
        ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS,
                       AO_RADIO_SPI_BUS);
+//     ao_delay(1);
 }
 
-
 static uint8_t
 ao_radio_master_send(void)
 {
+       if (!ao_radio_done)
+               printf ("radio not done in ao_radio_master_send\n");
+       PRINTD("send %d\n", ao_radio_spi_request.len);
        ao_radio_done = 0;
        ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
        ao_radio_master_start();
@@ -63,22 +82,17 @@ ao_radio_master_send(void)
        ao_radio_master_stop();
        cli();
        while (!ao_radio_done)
-               if (ao_sleep(&ao_radio_done))
+               if (ao_sleep((void *) &ao_radio_done)) {
+                       printf ("ao_radio_master awoken\n");
                        break;
+               }
        sei();
+       PRINTD ("sent, radio done %d\n", ao_radio_done);
+       if (!ao_radio_done)
+               printf ("radio didn't finish after ao_radio_master_send\n");
        return ao_radio_done;
 }
 
-static void
-ao_radio_master_recv(uint16_t len)
-{
-       ao_radio_master_start();
-       ao_spi_recv(&ao_radio_spi_reply,
-                   len,
-                   AO_RADIO_SPI_BUS);
-       ao_radio_master_stop();
-}
-
 static void
 ao_radio_get(uint8_t req, uint8_t len)
 {
@@ -98,12 +112,23 @@ ao_radio_put(void)
 static void
 ao_radio_get_data(__xdata void *d, uint8_t size)
 {
+       uint8_t ret;
+
+       PRINTD ("send fetch req\n");
+       ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN;
+       ao_radio_spi_request.request = AO_RADIO_SPI_RECV_FETCH;
+       ao_radio_spi_request.recv_len = size;
+       ret = ao_radio_master_send();
+       PRINTD ("fetch req sent %d\n", ret);
+
+       PRINTD ("fetch\n");
        ao_radio_master_start();
        ao_spi_recv(&ao_radio_spi_reply,
                    AO_RADIO_SPI_REPLY_HEADER_LEN + size,
                    AO_RADIO_SPI_BUS);
        ao_radio_master_stop();
        ao_xmemcpy(d, ao_radio_spi_reply.payload, size);
+       PRINTD ("fetched %d\n", size);
 }
 
 void
@@ -142,8 +167,11 @@ ao_radio_recv(__xdata void *d, uint8_t size)
                return 0;
        }
        ao_radio_get_data(d, size);
+
        recv = ao_radio_spi_reply.status;
+
        ao_radio_put();
+
        return recv;
 }
 
@@ -153,20 +181,25 @@ ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant
        if (len > AO_CMAC_MAX_LEN)
                return AO_RADIO_CMAC_LEN_ERROR;
 
+       PRINTD ("cmac_send: send %d\n", len);
        /* Set the key.
         */
+       PRINTD ("set key\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
        ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
        ao_radio_master_send();
        ao_radio_put();
+       PRINTD ("key set\n");
 
        /* Send the data
         */
        
+       PRINTD ("sending packet\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len);
        ao_xmemcpy(&ao_radio_spi_request.payload, packet, len);
        ao_radio_master_send();
        ao_radio_put();
+       PRINTD ("packet sent\n");
        return AO_RADIO_CMAC_OK;
 }
 
@@ -174,33 +207,40 @@ int8_t
 ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
 {
        int8_t  ret;
-       uint8_t recv;
+       int8_t  recv;
 
        if (len > AO_CMAC_MAX_LEN)
                return AO_RADIO_CMAC_LEN_ERROR;
 
        /* Set the key.
         */
+       PRINTD ("setting key\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN);
        ao_radio_spi_request.timeout = timeout;
        ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
-       ao_radio_master_send();
+       recv = ao_radio_master_send();
        ao_radio_put();
+       PRINTD ("key set: %d\n", recv);
 
        /* Recv the data
         */
-       
+       PRINTD ("queuing recv\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0);
        ao_radio_spi_request.recv_len = len;
        recv = ao_radio_master_send();
+       PRINTD ("recv queued: %d\n", recv);
        if (!recv) {
                ao_radio_put();
                ao_radio_recv_abort();
                return AO_RADIO_CMAC_TIMEOUT;
        }
+
+       PRINTD ("fetching data\n");
        ao_radio_get_data(packet, len);
        recv = ao_radio_spi_reply.status;
+       ao_radio_cmac_rssi = ao_radio_spi_reply.rssi;
        ao_radio_put();
+       PRINTD ("data fetched: %d %d\n", recv, ao_radio_cmac_rssi);
        return recv;
 }
 
index 9dff511b313288cfdd48b799027e1fa1028a9fc2..ab23894fd31b8e3bbf7452128bbc753c9e862ad2 100644 (file)
@@ -34,17 +34,24 @@ ao_radio_slave_signal(void)
        ao_arch_nop();
        ao_arch_nop();
        ao_arch_nop();
-       ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0);
+       ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1);
 }
 
 static void
 ao_radio_slave_spi(void)
 {
+       uint8_t need_signal = 0;
+
+       ao_spi_get_slave(AO_RADIO_SLAVE_BUS);
        for (;;) {
-               ao_spi_get_slave(AO_RADIO_SLAVE_BUS);
-               ao_spi_recv(&ao_radio_spi_request, (2 << 13) | sizeof (ao_radio_spi_request), AO_RADIO_SLAVE_BUS);
-               ao_spi_put_slave(AO_RADIO_SLAVE_BUS);
-               ao_led_for(AO_LED_RED, AO_MS_TO_TICKS(1000));
+               ao_spi_recv(&ao_radio_spi_request,
+                           (2 << 13) | sizeof (ao_radio_spi_request),
+                           AO_RADIO_SLAVE_BUS);
+               if (need_signal) {
+                       ao_radio_slave_signal();
+                       need_signal = 0;
+               }
+               ao_spi_recv_wait();
                switch (ao_radio_spi_request.request) {
                case AO_RADIO_SPI_RECV:
                case AO_RADIO_SPI_CMAC_RECV:
@@ -53,44 +60,43 @@ ao_radio_slave_spi(void)
                        ao_radio_spi_recv_len = ao_radio_spi_request.recv_len;
                        ao_radio_spi_recv_timeout = ao_radio_spi_request.timeout;
                        ao_wakeup(&ao_radio_spi_recv_len);
-                       break;
+                       continue;
                case AO_RADIO_SPI_RECV_FETCH:
-                       ao_spi_get_slave(AO_RADIO_SLAVE_BUS);
                        ao_spi_send(&ao_radio_spi_reply,
-                                   ao_radio_spi_request.recv_len + AO_RADIO_SPI_REPLY_HEADER_LEN,
+                                   ao_radio_spi_request.recv_len,
                                    AO_RADIO_SLAVE_BUS);
-                       ao_spi_put_slave(AO_RADIO_SLAVE_BUS);
-                       break;
+                       ao_radio_slave_signal();
+                       ao_spi_send_wait();
+                       continue;
                case AO_RADIO_SPI_RECV_ABORT:
                        ao_radio_recv_abort();
                        break;
                case AO_RADIO_SPI_SEND:
                        ao_config.radio_setting = ao_radio_spi_request.setting;
-                       ao_radio_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN);
-                       ao_radio_slave_signal();
+                       ao_radio_send(&ao_radio_spi_request.payload,
+                                     ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN);
                        break;
 
                case AO_RADIO_SPI_CMAC_SEND:
                        ao_config.radio_setting = ao_radio_spi_request.setting;
-                       ao_radio_cmac_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN);
-                       ao_radio_slave_signal();
+                       ao_radio_cmac_send(&ao_radio_spi_request.payload,
+                                          ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN);
                        break;
                        
                case AO_RADIO_SPI_CMAC_KEY:
                        ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN);
-                       ao_radio_slave_signal();
                        break;
 
                case AO_RADIO_SPI_TEST_ON:
+                       ao_config.radio_setting = ao_radio_spi_request.setting;
                        ao_radio_test(1);
-                       ao_radio_slave_signal();
                        break;
 
                case AO_RADIO_SPI_TEST_OFF:
                        ao_radio_test(0);
-                       ao_radio_slave_signal();
                        break;
                }
+               need_signal = 1;
        }
 }