X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Fxe1205%2Fphy%2FXE1205PhyP.nc;h=377ad953ea75bcbd57de65b10428968b6143a9a5;hb=f05e333221d21758aa1d1ab77929e5d0238f5370;hp=92bbbfd46bb6c383748a26bf952e9344404ba32b;hpb=07cb7526acbee26f169c11ce35918bf4c7137321;p=tinyos-2.x.git diff --git a/tos/chips/xe1205/phy/XE1205PhyP.nc b/tos/chips/xe1205/phy/XE1205PhyP.nc index 92bbbfd4..377ad953 100644 --- a/tos/chips/xe1205/phy/XE1205PhyP.nc +++ b/tos/chips/xe1205/phy/XE1205PhyP.nc @@ -39,410 +39,607 @@ #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 as Alarm32khz16; + uses interface Alarm 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; + } - } + } }