+ 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_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.rxAckEnd(rxFrame, rxFrameLen + headerLen, 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(ENOACK);
+ return;
+ default:
+
+ return;
+ }
+
+ }