Bug fixes and new features added to zigduino firmware and client.
[goodfet] / firmware / apps / radios / atmel_radio.c
index c1cd4ab..a81ccdf 100644 (file)
@@ -8,15 +8,16 @@
 
 #include "platform.h"
 #include "command.h"
 
 #include "platform.h"
 #include "command.h"
-#include <stdlib.h> //added for itoa
 
 #include "atmel_radio.h"
 #include "spi.h"
 
 
 #include "atmel_radio.h"
 #include "spi.h"
 
+uint8_t AACK_enabled;
+
 //! Handles a Chipcon SPI command.
 void atmel_radio_handle_fn( uint8_t const app,
                             uint8_t const verb,
 //! Handles a Chipcon SPI command.
 void atmel_radio_handle_fn( uint8_t const app,
                             uint8_t const verb,
-                            uint32_t const len);
+                            uint32_t const datalen32);
 
 // define the atmel_radio app's app_t
 app_t const atmel_radio_app = {
 
 // define the atmel_radio app's app_t
 app_t const atmel_radio_app = {
@@ -44,6 +45,7 @@ inline u8 reg_read(u16 addr)
 {
   return *(u8*)(TRX_REGISTER_BASEADDR + addr);
 }
 {
   return *(u8*)(TRX_REGISTER_BASEADDR + addr);
 }
+
 inline void reg_bit_write(u16 addr, u8 pos, u8 value)
 {
   u8 old, mask;
 inline void reg_bit_write(u16 addr, u8 pos, u8 value)
 {
   u8 old, mask;
@@ -53,8 +55,12 @@ inline void reg_bit_write(u16 addr, u8 pos, u8 value)
   reg_write(addr, old); //write byte
 }
 
   reg_write(addr, old); //write byte
 }
 
+void atmel_radio_clear_frame_buffer() {
+  TRXFBST = 0; //reset the frame buffer pointer to signal it was read (resets the PHR - length value)
+}
+
 
 
-void atmel_radio_set_state(u8 state) //based on zigduino-radio, radio_rfa.c
+u16 atmel_radio_set_state(u8 state) //based on zigduino-radio, radio_rfa.c
 {
   u8 cmd, retries;
   /* ensure not in state transition */
 {
   u8 cmd, retries;
   /* ensure not in state transition */
@@ -69,13 +75,19 @@ void atmel_radio_set_state(u8 state) //based on zigduino-radio, radio_rfa.c
   case BUSY_TX:
     cmd = CMD_TX_START;
     break;
   case BUSY_TX:
     cmd = CMD_TX_START;
     break;
-  default: //doesn't exist
-    cmd = CMD_RX_ON;
+  case RX_ON:
+  default: 
+    if (AACK_enabled) {
+      cmd =  CMD_RX_AACK_ON;
+      state = RX_AACK_ON;
+    } else {
+      cmd = CMD_RX_ON;
+    }
     break;
   }
 
   TRX_STATE = cmd;
     break;
   }
 
   TRX_STATE = cmd;
-  retries = 140; /* enough to receive ongoing frame */
+  retries = 180; // enough to receive ongoing frame
   do {
     if (state == (state & TRX_STATUS)) {
       break;
   do {
     if (state == (state & TRX_STATUS)) {
       break;
@@ -83,10 +95,15 @@ void atmel_radio_set_state(u8 state) //based on zigduino-radio, radio_rfa.c
     retries--;
     _delay_ms(32);
   } while (retries);
     retries--;
     _delay_ms(32);
   } while (retries);
+  if (state != (state & TRX_STATUS)) {
+    return (state & TRX_STATUS);
+  }else{
+    return 0;
+  }
 }
 
 }
 
-void atmel_radiosetup(){
-  u8 status;
+u16 atmel_radiosetup(){
+  u16 status;
   /* initialize transceiver
      code based on zigduino-radio
   */
   /* initialize transceiver
      code based on zigduino-radio
   */
@@ -106,15 +123,36 @@ void atmel_radiosetup(){
     /* clear IRQ history by reading status*/
     status = IRQ_STATUS;
   }
     /* clear IRQ history by reading status*/
     status = IRQ_STATUS;
   }
+  atmel_radio_set_state(TRX_OFF);
+
+  /* setup options for extended operating sniffing mode */
+  
+  // disable auto ack
+  CSMA_SEED_1 &= 0xEF & ~(1 << AACK_DIS_ACK); 
+  
+  // disable filtering of reserved frame types and reserve frame type processing
+  XAH_CTRL_1 &= 0xDF & ~(1 << AACK_FLTR_RES_FT);
+  XAH_CTRL_1 &= 0xEF & ~(1 << AACK_UPLD_RES_FT);
+  
+  // enable promiscuous mode
+  XAH_CTRL_1 |= 1 << AACK_PROM_MODE;
+
+  
+  // disable frame protection
+  TRX_CTRL_2 &= 0x7F &  ~(1 << RX_SAFE_MODE);
 
   // unset auto crc
   TRX_CTRL_1 &= 0xDF & ~(1 << TX_AUTO_CRC_ON);
 
 
   // unset auto crc
   TRX_CTRL_1 &= 0xDF & ~(1 << TX_AUTO_CRC_ON);
 
-  /* enter TRX_OFF state */
-  atmel_radio_set_state(TRX_OFF);
+
+  atmel_radio_clear_frame_buffer();
+
+  // extended operation mode disabled by default
+  AACK_enabled = 0;
+
 
   /* enter RX_ON state */
 
   /* enter RX_ON state */
-  atmel_radio_set_state(RX_ON);
+  return atmel_radio_set_state(RX_ON);
 
 }
 
 
 }
 
@@ -145,86 +183,121 @@ void atmel_radio_peekram(u16 addr, u8 *data, u16 len){
 }
 
 int atmel_radio_is_frame_buffer_empty() {
 }
 
 int atmel_radio_is_frame_buffer_empty() {
-  return TRXFBST == 0;
+  return 0 == TRXFBST;
 }
 
 }
 
-void atmel_radio_clear_frame_buffer() {
-  TRXFBST = 0; //reset the frame buffer pointer to signal it was read
-}
 
 
-//! Handles a Chipcon SPI command.
 void atmel_radio_handle_fn( uint8_t const app,
                             uint8_t const verb,
 void atmel_radio_handle_fn( uint8_t const app,
                             uint8_t const verb,
-                            uint32_t const len){
-
-  u16 length;
-  u8  len8;
-
+                            uint32_t const datalen32){
+
+  // cmddata -> byte
+  // cmddataword -> int
+  // cmddatalong -> long
+  u16 readlen16;
+  u16 ret;
+  u8 retries;
+  uint8_t framelen8;
   switch(verb){
   case PEEK:
   switch(verb){
   case PEEK:
-
-  case READ:
-    length=cmddataword[1]; // Backup length. Second byte
+    //case READ:
+    readlen16 = cmddataword[1]; // Backup length. Second byte
     atmel_radio_peekram(cmddataword[0], // First word is address
                         cmddata, // Return in same buffer
     atmel_radio_peekram(cmddataword[0], // First word is address
                         cmddata, // Return in same buffer
-                        length);
-    txdata(app,verb,length);
+                       readlen16); // length
+    txdata(app,verb,readlen16);
     break;
     break;
-  case WRITE:
+    //case WRITE:
   case POKE:
     atmel_radio_pokeram(cmddataword[0], // First word is address
                         cmddata+2,  // Remainder of buffer is data
   case POKE:
     atmel_radio_pokeram(cmddataword[0], // First word is address
                         cmddata+2,  // Remainder of buffer is data
-                        len-2); //Length implied by packet length
-    txdata(app,verb,len-2); //return number of poked bytes
+                        (u16) datalen32-2); //Length implied by packet length
+    txdata(app,verb, datalen32-2); //return number of poked bytes
     break;
   case SETUP:
     break;
   case SETUP:
-    atmel_radiosetup();
-    txdata(app,verb,0);
+    ret = atmel_radiosetup();
+    txdata(app, verb, ret);
     break;
 
   case ATMEL_RADIO_RX:
     break;
 
   case ATMEL_RADIO_RX:
-
-    // set to PLL_ON so frame buffer isn't clobbered
+    // ensure radio is not in the middle or receiving a packet
+    atmel_radio_set_state(RX_ON);
+    // set state to PLL_ON so frame buffer isn't clobbered
     atmel_radio_set_state(PLL_ON);
     atmel_radio_set_state(PLL_ON);
-    len8 = 8;
+
     if (!atmel_radio_is_frame_buffer_empty()) { //only if we recieved something new
     if (!atmel_radio_is_frame_buffer_empty()) { //only if we recieved something new
-      len8 = TST_RX_LENGTH; //register contains frame length
-
-      if  ((len8 > 0x80) ) { //frame too big
-        txdata(app,verb,0);
-      } else {
-        memcpy(cmddata, (void *) &TRXFBST, len8); //return in same buffer
-        atmel_radio_clear_frame_buffer();
-        txdata(app, verb, len8);
+      framelen8 = TST_RX_LENGTH; //register contains frame length
+      if  ((framelen8 > 127) ) { //frame too big
+       framelen8 = 127;
       }
       }
-    }else{
-      // didn't recieve anything new
-      txdata(app,verb,0);
+      memcpy(cmddata, (void *) &TRXFBST, framelen8); //return in same buffer
+      atmel_radio_clear_frame_buffer();
+    } else {
+      framelen8 = 0; //didn't receive anything new
     }
     // receive packets again
     atmel_radio_set_state(RX_ON);
 
     }
     // receive packets again
     atmel_radio_set_state(RX_ON);
 
+    txdata(app, verb, framelen8);
     break;
   case ATMEL_RADIO_TX:
     //prevent radio from recieving new packets
     atmel_radio_set_state(PLL_ON);
     break;
   case ATMEL_RADIO_TX:
     //prevent radio from recieving new packets
     atmel_radio_set_state(PLL_ON);
-    if (cmddata[0] > 127) { //truncate too long packets
-      cmddata[0] = 127;
+    uint8_t maxlen = 127;
+    if (cmddata[0] > maxlen) { //truncate too long packets
+      cmddata[0] = maxlen;
     }
 
     }
 
-    memcpy((void *) &TRXFBST, cmddata, cmddata[0]+1); //copy length + packet
+    memcpy((void *) &TRXFBST, cmddata, datalen32); //copy length + packet
     atmel_radio_set_state(BUSY_TX); //send packet
 
     atmel_radio_set_state(BUSY_TX); //send packet
 
+
     while (PLL_ON != (PLL_ON & TRX_STATUS)) {} //wait for TX done
     //reset the frame buffer pointer to signal it was read
     atmel_radio_clear_frame_buffer();
     atmel_radio_set_state(RX_ON);
     while (PLL_ON != (PLL_ON & TRX_STATUS)) {} //wait for TX done
     //reset the frame buffer pointer to signal it was read
     atmel_radio_clear_frame_buffer();
     atmel_radio_set_state(RX_ON);
-    txdata(app, verb, len8);
+    txdata(app, verb, 0);
 
     break;
 
     break;
+  case ATMEL_RADIO_AACK_ON:
+    if (!AACK_enabled) {
+      AACK_enabled = 1;
+      /* enter PLL_ON state */
+      atmel_radio_set_state(PLL_ON);
+      /* enter RX_ON state */
+      atmel_radio_set_state(RX_ON);
+    }
+    txdata(app, verb, 0);
+    break;
+  case ATMEL_RADIO_AACK_OFF:
+    if (AACK_enabled) {
+      AACK_enabled = 0;
+      /* enter PLL_ON state */
+      atmel_radio_set_state(PLL_ON);
+      /* enter RX_ON state */
+      atmel_radio_set_state(RX_ON);
+    }
+    txdata(app, verb, 0);
+    break;
+  case ATMEL_RADIO_AUTOCRC_ON:
+    if (0 == (TRX_CTRL_1 & (1 << TX_AUTO_CRC_ON))) { //not enabled
+      atmel_radio_set_state(TRX_OFF);
+      // can only be safely set in TRX_OFF mode
+      TRX_CTRL_1 |= 1 << TX_AUTO_CRC_ON;
+      atmel_radio_set_state(RX_ON);
+    }
 
 
-  case ATMEL_RADIO_RX_FLUSH:
-  case ATMEL_RADIO_TX_FLUSH:
+    txdata(app, verb, 0);
+    break;
+  case ATMEL_RADIO_AUTOCRC_OFF:
+    if (TRX_CTRL_1 & (1 << TX_AUTO_CRC_ON)) { //enabled
+      atmel_radio_set_state(TRX_OFF);
+      // can only be safely set in TRX_OFF mode
+      TRX_CTRL_1 &= 0xDF & ~(1 << TX_AUTO_CRC_ON);
+      atmel_radio_set_state(RX_ON);
+    }
+    txdata(app, verb, 0);
+    break;
   default:
     debugstr("Not yet supported in ATMEL_RADIO");
     txdata(app,verb,-1);
   default:
     debugstr("Not yet supported in ATMEL_RADIO");
     txdata(app,verb,-1);