]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/xe1205/phy/XE1205PhyP.nc
added ack, received packet strength, LPL (compile with PFLAGS +=-DLOW_POWER_LISTENING)
[tinyos-2.x.git] / tos / chips / xe1205 / phy / XE1205PhyP.nc
index 92bbbfd46bb6c383748a26bf952e9344404ba32b..377ad953ea75bcbd57de65b10428968b6143a9a5 100644 (file)
 #include "Timer.h"
 
 module XE1205PhyP {
-  provides interface XE1205PhyRxTx;
+    provides interface XE1205PhyRxTx;
+    provides interface XE1205PhyRssi;
 
-  provides interface Init @atleastonce();
-  provides interface SplitControl @atleastonce();
+    provides interface Init @atleastonce();
+    provides interface SplitControl @atleastonce();
 
-  uses interface Resource as SpiResourceTX;
-  uses interface Resource as SpiResourceRX;
-  uses interface Resource as SpiResourceConfig;
+    uses interface Resource as SpiResourceTX;
+    uses interface Resource as SpiResourceRX;
+    uses interface Resource as SpiResourceConfig;
+    uses interface Resource as SpiResourceRssi;
 
-  uses interface XE1205PhySwitch;
-  uses interface XE1205IrqConf;
-  uses interface XE1205Fifo;
+    uses interface XE1205PhySwitch;
+    uses interface XE1205IrqConf;
+    uses interface XE1205Fifo;
+    uses interface XE1205RssiConf;
+    uses interface XE1205PatternConf;
 
-  uses interface GpioInterrupt as Interrupt0;
-  uses interface GpioInterrupt as Interrupt1;
+    uses interface GpioInterrupt as Interrupt0;
+    uses interface GpioInterrupt as Interrupt1;
 
-  uses interface Alarm<T32khz,uint16_t> as Alarm32khz16;
+    uses interface Alarm<T32khz,uint16_t> as Alarm32khz16;
 #if 0
-  uses interface GeneralIO as Dpin;
+    uses interface GeneralIO as Dpin;
 #endif
 }
 implementation {
 
 #include "xe1205debug.h"
 
-  char* txBuf = NULL;
-  uint8_t rxFrameIndex = 0;
-  uint8_t rxFrameLen = 0;
-  uint8_t nextTxLen=0;
-  uint8_t nextRxLen;
-  char rxFrame[xe1205_mtu];
-  uint8_t headerLen = 4;
-
-  uint16_t stats_rxOverruns;
-
-  typedef enum { // remember to update busy() and off(), start(), stop() if states are added
-    RADIO_LISTEN=0, 
-    RADIO_RX_HEADER=1, 
-    RADIO_RX_PACKET=2, 
-    RADIO_RX_PACKET_LAST=3, 
-    RADIO_TX=4,
-    RADIO_SLEEP=5, 
-    RADIO_STARTING=6 
-  } phy_state_t;
-
-  phy_state_t state = RADIO_SLEEP;
-
-  void armPatternDetect();
-
-  ////////////////////////////////////////////////////////////////////////////////////
-  //
-  // jiffy/microseconds/bytetime conversion functions.
-  //
-  ////////////////////////////////////////////////////////////////////////////////////
-
-  // 1 jiffie = 1/32768 = 30.52us; 
-  // we approximate to 32us for quicker computation and also to account for interrupt/processing overhead.
-  inline uint32_t usecs_to_jiffies(uint32_t usecs) {
-    return usecs >> 5;
-  }
-
-  command error_t Init.init() 
-  { 
+    char* txBuf = NULL;
+    uint8_t rxFrameIndex = 0;
+    uint8_t rxFrameLen = 0;
+    uint8_t nextTxLen=0;
+    uint8_t nextRxLen;
+    char rxFrame[xe1205_mtu];
+    uint8_t headerLen = 4;
+
+    uint16_t stats_rxOverruns;
+
+    enum {
+       RSSI_RANGE_LOW=1,
+       RSSI_RANGE_HIGH=2,
+       RSSI_OFF=0,
+    };
+    uint8_t rssiRange = RSSI_OFF;
+    norace uint8_t rssiL,rssiH;
+    uint8_t * rLow = &rssiL;
+    uint8_t * rHigh = &rssiH;
+
+
+    bool enableAck = FALSE;
+
+    typedef enum { // remember to update busy() and off(), start(), stop() if states are added
+       RADIO_LISTEN=0, 
+       RADIO_RX_HEADER=1, 
+       RADIO_RX_PACKET=2, 
+       RADIO_RX_PACKET_LAST=3, 
+       RADIO_TX=4,
+       RADIO_SLEEP=5, 
+       RADIO_STARTING=6,
+       RADIO_RSSI=7,
+       RADIO_RX_ACK=8,
+       RADIO_TX_ACK=9
+    } phy_state_t;
+
+    phy_state_t state = RADIO_SLEEP;
+
+
+    void armPatternDetect();
+
+    ////////////////////////////////////////////////////////////////////////////////////
+    //
+    // jiffy/microseconds/bytetime conversion functions.
+    //
+    ////////////////////////////////////////////////////////////////////////////////////
+
+    // 1 jiffie = 1/32768 = 30.52us; 
+    // we approximate to 32us for quicker computation and also to account for interrupt/processing overhead.
+    inline uint32_t usecs_to_jiffies(uint32_t usecs) {
+       return usecs >> 5;
+    }
+
+    command error_t Init.init() 
+    { 
 #if 0
-    call Dpin.makeOutput();
+       call Dpin.makeOutput();
 #endif
-    call XE1205PhySwitch.sleepMode();
-    call XE1205PhySwitch.antennaOff();
-    return SUCCESS;
-  }
-
-  task void startDone() {
-    signal SplitControl.startDone(SUCCESS);
-  }
-
-  event void SpiResourceTX.granted() {  }
-  event void SpiResourceRX.granted() {  }
-  event void SpiResourceConfig.granted() { 
-    armPatternDetect();
-    call SpiResourceConfig.release();
-
-    atomic {
-      if (state == RADIO_STARTING) post startDone();
-      call Interrupt0.enableRisingEdge();
-      state = RADIO_LISTEN;
+       call XE1205PhySwitch.sleepMode();
+       call XE1205PhySwitch.antennaOff();
+       return SUCCESS;
     }
-  }
-
 
-  task void stopDone() {
-    signal SplitControl.stopDone(SUCCESS);
-  }
+    task void startDone() {    
+       signal SplitControl.startDone(SUCCESS);
+    }
 
-  command error_t SplitControl.start() 
-  {
-    atomic {
-      if (state != RADIO_SLEEP) return EBUSY;
-      state = RADIO_STARTING;
+    event void SpiResourceTX.granted() {  }
+    event void SpiResourceRX.granted() {  }
+    event void SpiResourceConfig.granted() { 
+       armPatternDetect();
+       call SpiResourceConfig.release();
+       atomic {
+           if (state == RADIO_STARTING){
+               post startDone();}
+           if (state == RADIO_RX_ACK) { 
+               enableAck=FALSE; 
+               signal XE1205PhyRxTx.sendFrameDone(FAIL);
+           }
+           state = RADIO_LISTEN;
+
+           call Interrupt0.enableRisingEdge();
+       }
     }
+    event void SpiResourceRssi.granted() {  }
 
-    call XE1205PhySwitch.rxMode();
-    call XE1205PhySwitch.antennaRx();
-
-    call Alarm32khz16.start(usecs_to_jiffies(XE1205_Sleep_to_RX_Time));
-    return SUCCESS;
-  }
-
-  command error_t SplitControl.stop() 
-  {
-    atomic {
-      call XE1205PhySwitch.sleepMode();
-      call XE1205PhySwitch.antennaOff();
-      state = RADIO_SLEEP;
-      call Interrupt0.disable();
-      call Interrupt1.disable();
+    task void stopDone() {
+       signal SplitControl.stopDone(SUCCESS);
     }
-    post stopDone();
-    return SUCCESS;
-  }
-
-  default event void SplitControl.startDone(error_t error) { }
-  default event void SplitControl.stopDone(error_t error) { }
-
-  async command bool XE1205PhyRxTx.busy() {
-    atomic return (state != RADIO_LISTEN &&
-                  state != RADIO_SLEEP &&
-                  state != RADIO_STARTING);
-  }
-
-  async command bool XE1205PhyRxTx.off() {
-    atomic return (state == RADIO_SLEEP ||
-                  state == RADIO_STARTING);
-  }
-
-  void armPatternDetect() 
-  {
-    // small chance of a pattern arriving right after we arm, 
-    // and IRQ0 hasn't been enabled yet, so we would miss the interrupt
-    // xxx maybe this can also be addressed with periodic timer?
-    xe1205check(2, call XE1205IrqConf.armPatternDetector(TRUE));
-    xe1205check(1, call XE1205IrqConf.clearFifoOverrun(TRUE));  
-  }
-
-  async command void XE1205PhyRxTx.setRxHeaderLen(uint8_t l) 
-  {
-    if (l > 8) l = 8;
-    if (!l) return;
-    headerLen = l;
-  }
-
-  async command uint8_t XE1205PhyRxTx.getRxHeaderLen() {
-    return headerLen;
-  }
-
-  void computeNextRxLength() 
-  {
-    uint8_t n = rxFrameLen - rxFrameIndex; 
-    
-    // for timesync and such, we want the end of the packet to coincide with a fifofull event, 
-    // so that we know precisely when last byte was received 
-
-    if (n > 16) {
-      if (n < 32) nextRxLen = n - 16; else nextRxLen = 15;
-    } 
-    else {
-      nextRxLen = n;
+
+    command error_t SplitControl.start() 
+    {
+
+           atomic {
+               if (state == RADIO_LISTEN){ post startDone(); return SUCCESS;}
+               if (state != RADIO_SLEEP) return EBUSY;
+               state = RADIO_STARTING;
+           }
+           call XE1205PhySwitch.rxMode();
+           call XE1205PhySwitch.antennaRx();
+           
+           
+           call Alarm32khz16.start(usecs_to_jiffies(XE1205_Sleep_to_RX_Time));
+           return SUCCESS;
     }
-  }
 
+    command error_t SplitControl.stop() 
+    {
+       atomic {
+           if (!call XE1205PhyRxTx.busy()) {
+               
+               call XE1205PhySwitch.sleepMode();
+               call XE1205PhySwitch.antennaOff();
+               state = RADIO_SLEEP;
+               call Interrupt0.disable();
+               call Interrupt1.disable();
+               post stopDone();
+               return SUCCESS;
+           } else return FAIL;
+       }
 
-  async command error_t XE1205PhyRxTx.sendFrame(char* data, uint8_t frameLen)  __attribute__ ((noinline)) 
-  {
-    error_t status;
+    }
+
+ default event void SplitControl.startDone(error_t error) { }
+ default event void SplitControl.stopDone(error_t error) { }
+ default async event void XE1205PhyRssi.rssiDone(uint8_t _rssi) { }
+
+ async command bool XE1205PhyRxTx.busy() {
+     atomic return (state != RADIO_LISTEN &&
+                   state != RADIO_SLEEP);
+ }
+
+ async command bool XE1205PhyRxTx.off() {
+     atomic return (state == RADIO_SLEEP ||
+                   state == RADIO_STARTING);
+ }
+
+
+ async command void XE1205PhyRxTx.enableAck(bool onOff) {
+     atomic enableAck = onOff;
+ }
+
+
+ void armPatternDetect() 
+ {
+     // small chance of a pattern arriving right after we arm, 
+     // and IRQ0 hasn't been enabled yet, so we would miss the interrupt
+     // xxx maybe this can also be addressed with periodic timer?
+     call XE1205IrqConf.armPatternDetector(TRUE);
+     call XE1205IrqConf.clearFifoOverrun(TRUE);  
+ }
+
+ async command void XE1205PhyRxTx.setRxHeaderLen(uint8_t l) 
+ {
+     if (l > 8) l = 8;
+     if (!l) return;
+     headerLen = l;
+ }
+
+ async command uint8_t XE1205PhyRxTx.getRxHeaderLen() {
+     return headerLen;
+ }
+
+ void computeNextRxLength() 
+ {
+     uint8_t n = rxFrameLen - rxFrameIndex; 
+    
+     // for timesync and such, we want the end of the packet to coincide with a fifofull event, 
+     // so that we know precisely when last byte was received 
+
+     if (n > 16) {
+        if (n < 32) nextRxLen = n - 16; else nextRxLen = 15;
+     } 
+     else {
+        nextRxLen = n;
+     }
+ }
+
+ command uint8_t  XE1205PhyRssi.readRxRssi() {
+     return rssiTab[(rssiH<<2) |rssiL];
+ }
+
+ task void rssiDone() {
+
+     signal XE1205PhyRssi.rssiDone( rssiTab[(rssiH<<2) |rssiL]);
+ }
+
+ void readRssi() {
+     if(rssiRange ==RSSI_RANGE_LOW ) {
+        rssiRange = RSSI_RANGE_HIGH;
+        call XE1205RssiConf.getRssi(rLow);
+        call XE1205RssiConf.setRssiRange(TRUE);
+        call Alarm32khz16.start(usecs_to_jiffies(call XE1205RssiConf.getRssiMeasurePeriod_us()));
+     } else {
+        call XE1205RssiConf.getRssi(rHigh);
+        call XE1205RssiConf.setRssiMode(FALSE);
+
+        if(state == RADIO_RSSI) {
+            armPatternDetect();
+            call SpiResourceRssi.release();
+            call Interrupt0.enableRisingEdge();
+            atomic state = RADIO_LISTEN;
+            signal XE1205PhyRssi.rssiDone( rssiTab[(rssiH<<2) |rssiL]);
+        } else { // go on with rx of packet
+            call Alarm32khz16.start(3000);
+        }
+        rssiRange = RSSI_OFF;
+     }
+ }
+
+
+ error_t getRssi() {
+     error_t err;
+
+     if(call SpiResourceRssi.immediateRequest() != SUCCESS) {
+        return FAIL;
+     }
+     err = call XE1205RssiConf.setRssiMode(TRUE);
+     err = ecombine(err,call XE1205RssiConf.setRssiRange(FALSE));
+     rssiRange=RSSI_RANGE_LOW;
+     call Alarm32khz16.start(usecs_to_jiffies(call XE1205RssiConf.getRssiMeasurePeriod_us()));
+     return err;
+ }
+
+
+ async command error_t XE1205PhyRssi.getRssi() {
+     error_t err;
+     atomic {
+        if (state != RADIO_LISTEN&&rssiRange==RSSI_OFF) return EBUSY;
+        if (call XE1205PhyRxTx.off()) {
+            return EOFF;
+        }
+        err=getRssi();
+        if (SUCCESS ==err) {
+            state = RADIO_RSSI;
+        }
+        return err;
+     }
+ }
+
+ async command error_t XE1205PhyRxTx.sendFrame(char* data, uint8_t frameLen)  __attribute__ ((noinline)) 
+ {
+     error_t status;
    
-    if (frameLen < 6) return EINVAL;
+     if (frameLen < 6) return EINVAL;
 
-    atomic {
-      if (state == RADIO_SLEEP) return EOFF;
-      if (state != RADIO_LISTEN) return EBUSY;
-      if (frameLen == 0 || frameLen > xe1205_mtu + 7) return EINVAL; // 7 = 4 preamble + 3 sync
-      
-      call XE1205PhySwitch.txMode(); // it takes 100us to switch from rx to tx, ie less than one byte at 76kbps
-      call Interrupt0.disable();
-
-      status = call SpiResourceTX.immediateRequest();
-      xe1205check(3, status);
-      if (status != SUCCESS) {
-       call XE1205PhySwitch.rxMode(); 
-       call SpiResourceConfig.request();
-       return status;
-      }
-      call XE1205PhySwitch.antennaTx();
-      state = RADIO_TX;
-    }
+     atomic {
+        if (state == RADIO_SLEEP) return EOFF;
 
-    status = call XE1205Fifo.write(data, frameLen);
-    // cannot happen with current SPI implementation (at least with NoDma)
+        if (call XE1205PhyRxTx.busy()) return EBUSY;
+        if (frameLen == 0 || frameLen > xe1205_mtu + 7) return EINVAL; // 7 = 4 preamble + 3 sync
+      
+        call XE1205PhySwitch.txMode(); // it takes 100us to switch from rx to tx, ie less than one byte at 76kbps
+        call Interrupt0.disable();
+
+        status = call SpiResourceTX.immediateRequest();
+        xe1205check(3, status);
+        if (status != SUCCESS) {
+            call XE1205PhySwitch.rxMode(); 
+            call SpiResourceConfig.request();
+            return status;
+        }
+        call XE1205PhySwitch.antennaTx();
+        state = RADIO_TX;
+        
+     }
+
+
+     call XE1205Fifo.write(data, frameLen);
+     atomic {
+       
+        txBuf = signal XE1205PhyRxTx.continueSend(&nextTxLen);
+     }
+     if (nextTxLen) {
+        call Interrupt0.enableFallingEdge();
+     } else {
+        call Interrupt0.disable();
+        call Interrupt1.enableRisingEdge();
+     }
+     // cannot happen with current SPI implementation (at least with NoDma)
 #if 0
-    if (status != SUCCESS) {
-      xe1205error(8, status);
-      call XE1205PhySwitch.rxMode(); 
-      call XE1205PhySwitch.antennaRx();
-      armPatternDetect();
-      call SpiResourceTX.release();
-      atomic {
-       call Interrupt0.enableRisingEdge();
-       state = RADIO_LISTEN;
-      }
-      return status;
-    }
+     if (status != SUCCESS) {
+        xe1205error(8, status);
+        call XE1205PhySwitch.rxMode(); 
+        call XE1205PhySwitch.antennaRx();
+        call XE1205PatternConf.loadDataPatternHasBus();
+        armPatternDetect();
+        call SpiResourceTX.release();
+        atomic {
+            call Interrupt0.enableRisingEdge();
+            state = RADIO_LISTEN;
+        }
+        return status;
+     }
 #endif
 
-    return SUCCESS;
-  }
-
-
-
-  uint16_t rxByte=0;
-
-  /**
-   * In transmit: nTxFifoEmpty. (ie after the last byte has been *read out of the fifo*)
-   * In receive: write_byte. 
-   */
-  async event void Interrupt0.fired()  __attribute__ ((noinline)) 
-  { 
-    error_t status;
-
-    switch (state) {
-
-    case RADIO_LISTEN:
-      rxByte=1;
-      state = RADIO_RX_HEADER;
-      status = call SpiResourceRX.immediateRequest();
-      xe1205check(4, status);
-      if (status != SUCCESS) {
-       state = RADIO_LISTEN;
-       call Interrupt0.disable(); // because pattern detector won't be rearmed right away
-       call SpiResourceConfig.request();
-       return;
-      }
-      return;
-
-    case RADIO_RX_HEADER:
-      rxByte++;
-      if (rxByte == 2) {
-       call Alarm32khz16.start(3000);
-      }
-
-      if (rxByte == headerLen + 1) {
-       call Interrupt0.disable();
-       xe1205check(8, call XE1205Fifo.read(rxFrame, headerLen));
-       call Interrupt1.enableRisingEdge();
-      }
-      return;
-
-    case RADIO_TX:
-
-      call Interrupt0.disable(); // avoid spurious IRQ0s from nTxFifoEmpty rebounding briefly after first byte is written.
-                                 // note that we should really wait till writedone() to re-enable either interrupt.
-      xe1205check(5, call XE1205Fifo.write(txBuf, nextTxLen));
-      return;
-
-    default:
-      return;
-    }
-  }
+     return SUCCESS;
+ }
 
 
 
-  /**
-   * In transmit: TxStopped. (ie after the last byte has been *sent*)
-   * In receive: Fifofull.
-   */
-  async event void Interrupt1.fired()  __attribute__ ((noinline)) 
-  { 
-    switch (state) {
+ uint16_t rxByte=0;
 
-    case RADIO_RX_PACKET:
-      xe1205check(9, call XE1205Fifo.read(&rxFrame[rxFrameIndex], nextRxLen));
-      call Interrupt1.disable(); // in case it briefly goes back to full just after we read first byte
-      rxFrameIndex += nextRxLen;
-      computeNextRxLength();
-      
-      if (nextRxLen==0) {
-       state = RADIO_RX_PACKET_LAST;
-      }
-
-      return;
-
-    case RADIO_RX_HEADER: // somehow the FIFO has filled before we finished reading the header bytes
-      call Interrupt1.disable();
-      call Alarm32khz16.stop();
-      signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
-      armPatternDetect();
-      call SpiResourceRX.release();
-      atomic {
-       call Interrupt0.enableRisingEdge();
-       state = RADIO_LISTEN;
-      }
-      return;
-
-    case RADIO_TX:
-
-      call Interrupt1.disable();
-      call XE1205PhySwitch.rxMode(); 
-      call XE1205PhySwitch.antennaRx();
-      signal XE1205PhyRxTx.sendFrameDone();
-      armPatternDetect();
-      call SpiResourceTX.release();
-      atomic {
-       call Interrupt0.enableRisingEdge();
-       state = RADIO_LISTEN;
-      }
-      return;
-
-    default:
-      return;
-    }
-  }
-
-  async event void XE1205Fifo.readDone(error_t error) {
-    xe1205check(6, error);
-    switch(state) {
-    case RADIO_RX_HEADER:
-      rxFrameLen = signal XE1205PhyRxTx.rxFrameBegin(rxFrame, headerLen);
-      if (rxFrameLen <= headerLen) {
-       call Interrupt1.disable();
-       call Alarm32khz16.stop();
-       signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
-       armPatternDetect();
-       call SpiResourceRX.release();
-       atomic {
-         call Interrupt0.enableRisingEdge();
-         state = RADIO_LISTEN;
-       }
-       return;
-      }
-
-      rxFrameIndex = headerLen;
-      computeNextRxLength();
-      state = RADIO_RX_PACKET;
-      return;
-
-    case RADIO_RX_PACKET_LAST:
-      call Alarm32khz16.stop();
-      signal XE1205PhyRxTx.rxFrameEnd(rxFrame, rxFrameLen + headerLen, SUCCESS);
-      armPatternDetect(); 
-      call SpiResourceRX.release();
-      atomic {
-       call Interrupt0.enableRisingEdge();
-       state = RADIO_LISTEN;
-      }
-      return;
-
-    case RADIO_RX_PACKET:
-      call Interrupt1.enableRisingEdge();
-      return;
-
-    default:
-      xe1205check(10, FAIL);
-      return;
-    }
-  }
-
-  async event void XE1205Fifo.writeDone(error_t error)  __attribute__ ((noinline)) { 
-    xe1205check(7, error);
-    switch(state) {
-    case RADIO_TX:
-      txBuf = signal XE1205PhyRxTx.continueSend(&nextTxLen);
-      if (nextTxLen) {
-       call Interrupt0.enableFallingEdge();
-      } else {
-       call Interrupt0.disable();
-       call Interrupt1.enableRisingEdge();
-      }
-      return;
-    default:
-      xe1205check(11, FAIL);
-    }
-  }
-
-  async event void Alarm32khz16.fired() {
-
-    switch(state) {
-
-    case RADIO_STARTING:
-      call SpiResourceConfig.request();
-      return;
-
-    case RADIO_RX_HEADER:
-    case RADIO_RX_PACKET:
-      stats_rxOverruns++;
-      signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
-      armPatternDetect(); 
-      call SpiResourceRX.release();
-      atomic {
-       call Interrupt0.enableRisingEdge();
-       state = RADIO_LISTEN;
-      }
-      return;
-    default:
-    }
+ /**
+  * In transmit: nTxFifoEmpty. (ie after the last byte has been *read out of the fifo*)
+  * In receive: write_byte. 
+  */
+ async event void Interrupt0.fired() __attribute__ ((noinline)) 
+ { 
+     error_t status;
+    
+     switch (state) {
+
+     case RADIO_RX_ACK:
+        
+        call Alarm32khz16.stop();
+     case RADIO_LISTEN:
+        rxByte=1;
+        atomic state = RADIO_RX_HEADER;
+        status = call SpiResourceRX.immediateRequest();
+        atomic {
+        if (status != SUCCESS) {
+            state = RADIO_LISTEN;
+            call Interrupt0.disable(); // because pattern detector won't be rearmed right away
+            call SpiResourceConfig.request();
+            return;
+        }
+        }
+        call Alarm32khz16.start(3000);
+        return;
+
+     case RADIO_RX_HEADER:
+        rxByte++;
+        if (rxByte == 2) {
+            call Alarm32khz16.start(3000);
+        }
+        if (rxByte == headerLen + 1) {
+            call Interrupt0.disable();
+            call XE1205Fifo.read(rxFrame, headerLen);
+            call Interrupt1.enableRisingEdge();
+        }
+
+        return;
+
+     case RADIO_TX:
+        call Interrupt0.disable(); // avoid spurious IRQ0s from nTxFifoEmpty rebounding briefly after first byte is written.
+        // note that we should really wait till writedone() to re-enable either interrupt.
+        call XE1205Fifo.write(txBuf, nextTxLen);
+        txBuf = signal XE1205PhyRxTx.continueSend(&nextTxLen);
+        if (nextTxLen) {
+            call Interrupt0.enableFallingEdge();
+        } else {
+            call Interrupt0.disable();
+            call Interrupt1.enableRisingEdge();
+        }
+        return;
+
+     case RADIO_RSSI: // trigged while getting rssi
+        call Interrupt0.disable(); // because pattern detector won't be rearmed right away
+        return;
+
+     default:
+        
+        return;
+     }
+ }
+
+
+
+ /**
+  * In transmit: TxStopped. (ie after the last byte has been *sent*)
+  * In receive: Fifofull.
+  */
+ async event void Interrupt1.fired()  __attribute__ ((noinline)) 
+ { 
+
+     switch (state) {
+
+     case RADIO_RX_PACKET:
+        call Interrupt1.disable(); // in case it briefly goes back to full just after we read first byte
+        call XE1205Fifo.read(&rxFrame[rxFrameIndex], nextRxLen);
+
+        rxFrameIndex += nextRxLen;
+        computeNextRxLength();
+        if (nextRxLen==0) {
+            state = RADIO_RX_PACKET_LAST;
+        }
+        return;
+
+     case RADIO_RX_HEADER: // somehow the FIFO has filled before we finished reading the header bytes
+
+        call Interrupt1.disable();
+        call Alarm32khz16.stop();
+
+        signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
+        call XE1205PatternConf.loadDataPatternHasBus();
+        armPatternDetect();
+        call SpiResourceRX.release();
+        atomic {            
+            call Interrupt0.enableRisingEdge();
+            state = RADIO_LISTEN;
+        }
+        return;
+
+     case RADIO_TX:
+
+        call Interrupt1.disable();
+        call XE1205PhySwitch.rxMode(); 
+        call XE1205PhySwitch.antennaRx();
+        if (enableAck==FALSE) {
+            call XE1205PatternConf.loadDataPatternHasBus();
+            armPatternDetect();
+            signal XE1205PhyRxTx.sendFrameDone(SUCCESS);
+            call SpiResourceTX.release();
+            atomic {
+                call Interrupt0.enableRisingEdge();
+                state = RADIO_LISTEN;
+            }
+        } else {
+
+            call XE1205PatternConf.loadAckPatternHasBus();
+            armPatternDetect();
+            call SpiResourceTX.release();
+            
+            call Alarm32khz16.start(usecs_to_jiffies(8000));
+            atomic {
+                call Interrupt0.enableRisingEdge();
+                state = RADIO_RX_ACK;
+            }
+        }
+
+        return;
+
+     default:
+        return;
+     }
+ }
+
+
+
+ async event void XE1205Fifo.readDone(error_t error) {
+
+     switch(state) {
+     case RADIO_RX_HEADER:
+        rxFrameLen = signal XE1205PhyRxTx.rxFrameBegin(rxFrame, headerLen);
+        if (rxFrameLen <= headerLen) {
+            call Interrupt1.disable();
+            call Alarm32khz16.stop();
+
+            signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
+            call XE1205PatternConf.loadDataPatternHasBus();
+            armPatternDetect();
+            call SpiResourceRX.release();
+            atomic {
+                state = RADIO_LISTEN;
+                call Interrupt0.enableRisingEdge();
+            }
+            return;
+        }
+        atomic {
+            if(rssiRange==RSSI_OFF) {
+                getRssi();
+            }
+        }
+        rxFrameIndex = headerLen;
+        computeNextRxLength();
+        state = RADIO_RX_PACKET;
+
+        return;
+
+     case RADIO_RX_PACKET_LAST:
+        call Alarm32khz16.stop();
+
+        atomic {
+            call XE1205PatternConf.loadDataPatternHasBus();
+            armPatternDetect(); 
+            state = RADIO_LISTEN;
+            call Interrupt0.enableRisingEdge();
+            call SpiResourceRX.release();
+        }
+        if( enableAck == FALSE) {
+            signal XE1205PhyRxTx.rxFrameEnd(rxFrame, rxFrameLen + headerLen, SUCCESS); 
+
+        } else {
+            enableAck = FALSE;
+            signal XE1205PhyRxTx.sendFrameDone(SUCCESS);
+        }
+
+        
+
+
+
+        return;
+
+     case RADIO_RX_PACKET:
+
+        call Interrupt1.enableRisingEdge();
+        return;
+
+     default:
+        xe1205check(10, FAIL);
+        return;
+     }
+ }
+
+ async event void XE1205Fifo.writeDone(error_t error)  __attribute__ ((noinline)) { 
+
+ }
+   
+
+ async event void Alarm32khz16.fired() {
+
+     switch(state) {
+
+     case RADIO_STARTING:
+        call SpiResourceConfig.request();      
+        return;
+
+     case RADIO_LISTEN:
+     case RADIO_RX_HEADER:
+     case RADIO_RX_PACKET:
+        if (rssiRange!=RSSI_OFF) {
+                readRssi();
+                return;
+            }
+        stats_rxOverruns++;
+
+        signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
+        call XE1205PatternConf.loadDataPatternHasBus();
+        armPatternDetect(); 
+        call SpiResourceRX.release();
+
+        atomic {
+            state = RADIO_LISTEN;
+            call Interrupt0.enableRisingEdge();
+        }
+
+        return;
+
+     case RADIO_RSSI:
+            readRssi();
+        return;
+
+     case RADIO_RX_ACK: // ack timeout
+
+        enableAck = FALSE;
+        call SpiResourceRX.immediateRequest();
+            
+        signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
+       
+        call XE1205PatternConf.loadDataPatternHasBus();
+
+        armPatternDetect();
+
+        call SpiResourceRX.release();
+        
+        atomic {
+            state = RADIO_LISTEN;
+            call Interrupt0.enableRisingEdge();
+
+        }
+
+        signal XE1205PhyRxTx.sendFrameDone(FAIL);
+        return;
+     default:
+   
+
+        return;
+     }
 
 }
+ }
 
 
 }