first cut at turnon scripts for EasyTimer v2
[fw/altos] / src / drivers / ao_radio_master.c
index 6edea66dd7c96853a8b31fe7147d70662114916b..b229bd6fe1354f6209aa8b0055a390ddff6b3c78 100644 (file)
@@ -3,7 +3,8 @@
  *
  * 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.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 #include <ao_exti.h>
 #include <ao_radio_cmac.h>
 
-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 __xdata uint8_t                         ao_radio_mutex;
+static struct ao_radio_spi_reply       ao_radio_spi_reply;
+static struct ao_radio_spi_request     ao_radio_spi_request;
+static volatile uint8_t                        ao_radio_wait_mode;
+static volatile uint8_t                        ao_radio_done = 0;
+static volatile uint8_t                        ao_radio_ready = 1;
+static uint8_t                         ao_radio_mutex;
+static uint8_t                         ao_radio_aes_seq;
 
-__xdata int8_t                                 ao_radio_cmac_rssi;
+int8_t                                 ao_radio_cmac_rssi;
+
+#if 0
+#define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __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);
+       if (ao_gpio_get(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, AO_RADIO_INT)) {
+               ao_radio_ready = 1;
+               ao_wakeup((void *) &ao_radio_ready);
+       } else {
+               ao_radio_done = 1;
+               ao_wakeup((void *) &ao_radio_done);
+       }
 }
 
 static void
@@ -40,7 +54,7 @@ ao_radio_master_start(void)
 {
        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_2MHz);
 }
 
 static void
@@ -50,35 +64,51 @@ ao_radio_master_stop(void)
                       AO_RADIO_SPI_BUS);
 }
 
-
 static uint8_t
 ao_radio_master_send(void)
 {
+       uint8_t ret;
+
+       PRINTD("send %d\n", ao_radio_spi_request.len);
        ao_radio_done = 0;
-       ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
+
+       /* Wait for radio chip to be ready for a command
+        */
+
+       PRINTD("Waiting radio ready\n");
+       ao_arch_block_interrupts();
+       ao_radio_ready = ao_gpio_get(AO_RADIO_INT_PORT,
+                                    AO_RADIO_INT_PIN, AO_RADIO_INT);
+       ret = 0;
+       while (!ao_radio_ready) {
+               ret = ao_sleep((void *) &ao_radio_ready);
+               if (ret)
+                       break;
+       }
+       ao_arch_release_interrupts();
+       if (ret)
+               return 0;
+
+       PRINTD("radio_ready %d radio_done %d\n", ao_radio_ready, ao_radio_done);
+
+       /* Send the command
+        */
+       ao_radio_wait_mode = 0;
        ao_radio_master_start();
        ao_spi_send(&ao_radio_spi_request,
                    ao_radio_spi_request.len,
                    AO_RADIO_SPI_BUS);
        ao_radio_master_stop();
-       cli();
+       PRINTD("waiting for send done %d\n", ao_radio_done);
+       ao_arch_block_interrupts();
        while (!ao_radio_done)
-               if (ao_sleep(&ao_radio_done))
+               if (ao_sleep((void *) &ao_radio_done))
                        break;
-       sei();
+       ao_arch_release_interrupts();
+       PRINTD ("sent, radio done %d isr_0 %d isr_1 %d\n", ao_radio_done, isr_0_count, isr_1_count);
        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)
 {
@@ -96,14 +126,16 @@ ao_radio_put(void)
 }
 
 static void
-ao_radio_get_data(__xdata void *d, uint8_t size)
+ao_radio_get_data(void *d, uint8_t size)
 {
+       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);
+       memcpy(d, ao_radio_spi_reply.payload, size);
+       PRINTD ("fetched %d\n", size);
 }
 
 void
@@ -118,14 +150,14 @@ void
 ao_radio_send(const void *d, uint8_t size)
 {
        ao_radio_get(AO_RADIO_SPI_SEND, size);
-       ao_xmemcpy(&ao_radio_spi_request.payload, d, size);
+       memcpy(&ao_radio_spi_request.payload, d, size);
        ao_radio_master_send();
        ao_radio_put();
 }
 
 
 uint8_t
-ao_radio_recv(__xdata void *d, uint8_t size)
+ao_radio_recv(void *d, uint8_t size, uint8_t timeout)
 {
        int8_t  ret;
        uint8_t recv;
@@ -135,6 +167,7 @@ ao_radio_recv(__xdata void *d, uint8_t size)
        
        ao_radio_get(AO_RADIO_SPI_RECV, 0);
        ao_radio_spi_request.recv_len = size;
+       ao_radio_spi_request.timeout = timeout;
        recv = ao_radio_master_send();
        if (!recv) {
                ao_radio_put();
@@ -144,63 +177,79 @@ ao_radio_recv(__xdata void *d, uint8_t size)
        ao_radio_get_data(d, size);
        recv = ao_radio_spi_reply.status;
        ao_radio_put();
+
        return recv;
 }
 
-int8_t
-ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant
+static void
+ao_radio_cmac_set_key(void)
 {
-       if (len > AO_CMAC_MAX_LEN)
-               return AO_RADIO_CMAC_LEN_ERROR;
-
+       if (ao_radio_aes_seq == ao_config_aes_seq)
+               return;
        /* 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);
+       memcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN);
        ao_radio_master_send();
        ao_radio_put();
+       PRINTD ("key set\n");
+       ao_radio_aes_seq = ao_config_aes_seq;
+}
+
+int8_t
+ao_radio_cmac_send(void *packet, uint8_t len) 
+{
+       if (len > AO_CMAC_MAX_LEN)
+               return AO_RADIO_CMAC_LEN_ERROR;
+
+       ao_radio_cmac_set_key();
+
+       PRINTD ("cmac_send: send %d\n", len);
 
        /* 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);
+       memcpy(&ao_radio_spi_request.payload, packet, len);
        ao_radio_master_send();
        ao_radio_put();
+       PRINTD ("packet sent\n");
        return AO_RADIO_CMAC_OK;
 }
 
 int8_t
-ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant
+ao_radio_cmac_recv(void *packet, uint8_t len, uint16_t timeout) 
 {
        int8_t  ret;
-       uint8_t recv;
+       int8_t  recv;
 
        if (len > AO_CMAC_MAX_LEN)
                return AO_RADIO_CMAC_LEN_ERROR;
 
-       /* Set the key.
-        */
-       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();
-       ao_radio_put();
+       ao_radio_cmac_set_key();
 
        /* Recv the data
         */
-       
+       PRINTD ("queuing recv\n");
        ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0);
        ao_radio_spi_request.recv_len = len;
+       ao_radio_spi_request.timeout = timeout;
        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;
 }
 
@@ -247,7 +296,7 @@ ao_radio_test_cmd(void)
                ao_radio_test(0);
 }
 
-__code struct ao_cmds ao_radio_cmds[] = {
+const struct ao_cmds ao_radio_cmds[] = {
        { ao_radio_test_cmd,    "C <1 start, 0 stop, none both>\0Radio carrier test" },
        { 0,    NULL },
 };
@@ -260,7 +309,8 @@ ao_radio_init(void)
        ao_enable_port(AO_RADIO_INT_PORT);
        ao_exti_setup(AO_RADIO_INT_PORT,
                      AO_RADIO_INT_PIN,
-                     AO_EXTI_MODE_FALLING,
+                     AO_EXTI_MODE_RISING|AO_EXTI_MODE_FALLING,
                      ao_radio_isr);
+       ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN);
        ao_cmd_register(&ao_radio_cmds[0]);
 }