atomic {
if (rState == RADIO_TX)
signal Send.sendDone(txMsg,FAIL);
- else
- signal SplitControl.startDone(FAIL);
+ else
+ signal SplitControl.startDone(err);
}
} else {
atomic {
if(enableCCA==TRUE) {
if(SUCCESS != post readRssi()) {
signal Send.sendDone(txMsg,FAIL);
- return;
}
- }
+ return;
+ }
else {
post send();
return;
}
}
}
- if(SUCCESS != post readRssi())
- signal SplitControl.startDone(FAIL);
+ signal SplitControl.startDone(err);
}
}
}
switch (maType) {
case RSSI_CLR:
- if((float)value < MAX(RSSI_RX_MA,RSSI_RX_MA))
+ if((float)value < MAX(RSSI_RX_MA,RSSI_CLR_MA))
RSSI_CLR_MA = (RSSI_CLR_MA*(MA_LENGTH - 1)+ value )/(MA_LENGTH);
break;
signal Send.sendDone(msg, err);
}
- command void* Send.getPayload(message_t* m) {
+ command void* Send.getPayload(message_t* m,uint8_t len) {
return m->data;
}
return FAIL;
}
- command uint8_t Receive.payloadLength(message_t* msg) {
- return call SubReceive.payloadLength(msg);
- }
-
- command void *Receive.getPayload(message_t* msg, uint8_t* len) {
- return call SubReceive.getPayload(msg, len);
- }
-
task void readRssi() {
if(SUCCESS!=call Rssi.getRssi()) {
#endif
#ifndef DEFAULT_DUTY_PERIOD
-#define DEFAULT_DUTY_PERIOD 1000
+#define DEFAULT_DUTY_PERIOD 80
#endif
/* Copyright (c) 2007 Shockfish SA
-* All rights reserved.
-*
-* Permission to use, copy, modify, and distribute this software and its
-* documentation for any purpose, without fee, and without written
-* agreement is hereby granted, provided that the above copyright
-* notice, the (updated) modification history and the author appear in
-* all copies of this source code.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
-* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
-* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
-* OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-* THE POSSIBILITY OF SUCH DAMAGE.
-*/
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written
+ * agreement is hereby granted, provided that the above copyright
+ * notice, the (updated) modification history and the author appear in
+ * all copies of this source code.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, LOSS OF USE, DATA,
+ * OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
/**
* @author Maxime Muller
}
event void SubControl.startDone(error_t err) {
- if(!err) {
+
+ if(err==SUCCESS) {
if(sleepTime > 0) {// keep radio on for a while
call OffTimer.stop();
call OnTimer.startOneShot(DELAY_AFTER_RECEIVE);
event void OffTimer.fired() {
if (SUCCESS==call SubControl.start()) {
- if (sleepTime > 0)
- call LPLControl.setMode(RX);
- if (sleepTime == 0) // radio always on
- call LPLControl.setMode(IDLE);
- } else call OffTimer.startOneShot(sleepTime);
- //}
+ if (sleepTime > 0)
+ call LPLControl.setMode(RX);
+ if (sleepTime == 0) // radio always on
+ call LPLControl.setMode(IDLE);
+ }
+ else
+ call OffTimer.startOneShot(sleepTime);
}
event void OnTimer.fired() {
if(SUCCESS != call SubSend.send(curTxMsg,curTxMsgLength)) {
call LPLControl.setMode(IDLE);
call OffTimer.startOneShot(sleepTime);
-
sendDone(FAIL);
- }
+ }
}
/*
if(call LowPowerListening.getRxSleepInterval(curTxMsg)
> ONE_MESSAGE) {
txSeqNo+=0x02;
- if (AM_BROADCAST_ADDR != call AMPacket.destination(curTxMsg))
+ if (AM_BROADCAST_ADDR != call AMPacket.destination(curTxMsg)) {
getHeader(curTxMsg)->ack = txSeqNo|0x01;
- else
+ } else
getHeader(curTxMsg)->ack = txSeqNo&0xFE;
call CsmaControl.enableCca();
event void SendTimeout.fired() {
atomic {
- if (rState == RADIO_TX) // let sendDone occur
- rState = RADIO_ON;
+ if (rState == RADIO_TX) // let sendDone occur
+ rState = RADIO_ON;
}
call OffTimer.startOneShot(DELAY_AFTER_RECEIVE);
}
}
event void SubSend.sendDone(message_t *msg, error_t err) {
- if(rState == RADIO_TX
- && call SendTimeout.isRunning())
- if ( AM_BROADCAST_ADDR != call AMPacket.destination(msg)
- && call PacketAcknowledgements.wasAcked(msg)) {
+
+ if(rState == RADIO_TX
+ && call SendTimeout.isRunning()) {
+ if ( AM_BROADCAST_ADDR != call AMPacket.destination(msg)
+ && err==SUCCESS) {
+ call SendTimeout.stop();
sendDone(err);
- return;
- }
- else { // ack timeout or bcast msg
+ } else { // ack timeout or bcast msg
call CsmaControl.disableCca();
- if(SUCCESS!=post sendPkt())
+ if(SUCCESS!=post sendPkt()) {
+
sendDone(FAIL);
- return;
+ }
}
- sendDone(err);
+ }
+ else {
+ sendDone(err);
+
+ }
}
command error_t Send.cancel(message_t *msg) {
return call SubSend.maxPayloadLength();
}
- command void *Send.getPayload(message_t* msg) {
- return call SubSend.getPayload(msg);
+ command void *Send.getPayload(message_t* msg, uint8_t len) {
+ return call SubSend.getPayload(msg,len);
}
/*
*/
event message_t *SubReceive.receive(message_t *msg,void *payload, uint8_t len) {
- if ((getHeader(msg)->ack & 0xFE ) == lastSeqNo
- && call AMPacket.destination(msg) == AM_BROADCAST_ADDR) {
- return msg;
- } else {
- lastSeqNo = getHeader(msg)->ack & 0xFE;
- if(!call SendTimeout.isRunning()) {
- // catched a packet between pktSend
- call OffTimer.startOneShot(DELAY_AFTER_RECEIVE);
- }
+ if ((getHeader(msg)->ack & 0xFE ) == lastSeqNo
+ && call AMPacket.destination(msg) == AM_BROADCAST_ADDR) {
+ return msg;
+ } else {
+ lastSeqNo = getHeader(msg)->ack & 0xFE;
+ if(!call SendTimeout.isRunning()) {
+ // catched a packet between pktSend
+ call OffTimer.startOneShot(DELAY_AFTER_RECEIVE);
+ }
- return signal Receive.receive(msg,payload,len);
+ return signal Receive.receive(msg,payload,len);
}
}
- command void *Receive.getPayload(message_t* msg, uint8_t* len) {
- return call SubReceive.getPayload(msg, len);
- }
-
- command uint8_t Receive.payloadLength(message_t* msg) {
- return call SubReceive.payloadLength(msg);
- }
-
uint16_t getActualDutyCycle(uint16_t dutyCycle) {
if(dutyCycle > 10000) {
return 10000;
return call Packet.getPayload(m, len);
}
- task void sendDoneTask() {
+ task void sendDoneTask() {
txMsgSendDonePtr = txMsgPtr;
txMsgPtr=NULL;
signal Send.sendDone(txMsgSendDonePtr, SUCCESS);
}
+ task void sendDoneNoAckTask() {
+ txMsgSendDonePtr = txMsgPtr;
+ txMsgPtr=NULL;
+ signal Send.sendDone(txMsgSendDonePtr, ENOACK);
+ }
+
+
command error_t SplitControl.start() {
error_t err;
err = call PhySplitControl.start();
- task void sendAck() {
- atomic {
- ((xe1205_metadata_t*)((uint8_t*)ackMsgPtr->footer + sizeof(xe1205_footer_t)))->length = sizeof(ackMsg_t);
- ((xe1205_header_t*)(&ackMsg.data - sizeof(xe1205_header_t)))->group = \
- (getHeader((message_t*)rxMsgPtr))->group;
- ((xe1205_header_t*)(ackMsgPtr->data - sizeof(xe1205_header_t)))->type = \
- ((xe1205_header_t*)(rxMsgPtr->data - sizeof(xe1205_header_t)))->type;
- ((xe1205_header_t*)(ackMsgPtr->data - sizeof(xe1205_header_t)))->dest = \
- ((xe1205_header_t*)(rxMsgPtr->data - sizeof(xe1205_header_t)))->source;
- ((xe1205_header_t*)(ackMsgPtr->data - sizeof(xe1205_header_t)))->source = TOS_NODE_ID;
- ((ackMsg_t*)(ackMsgPtr->data))->pl = ackPayload;
-
- txMsgPtr = ackMsgPtr;
- }
- _len = sizeof(ackMsg_t);
- sendRadioOn(ACK_CODE);
- }
+ task void sendAck() {
+ atomic {
+ ((xe1205_metadata_t*)((uint8_t*)ackMsgPtr->footer + sizeof(xe1205_footer_t)))->length = sizeof(ackMsg_t);
+ ((xe1205_header_t*)(&ackMsg.data - sizeof(xe1205_header_t)))->group = \
+ (getHeader((message_t*)rxMsgPtr))->group;
+ ((xe1205_header_t*)(ackMsgPtr->data - sizeof(xe1205_header_t)))->type = \
+ ((xe1205_header_t*)(rxMsgPtr->data - sizeof(xe1205_header_t)))->type;
+ ((xe1205_header_t*)(ackMsgPtr->data - sizeof(xe1205_header_t)))->dest = \
+ ((xe1205_header_t*)(rxMsgPtr->data - sizeof(xe1205_header_t)))->source;
+ ((xe1205_header_t*)(ackMsgPtr->data - sizeof(xe1205_header_t)))->source = TOS_NODE_ID;
+ ((ackMsg_t*)(ackMsgPtr->data))->pl = ackPayload;
+
+ txMsgPtr = ackMsgPtr;
+ }
+ _len = sizeof(ackMsg_t);
+ sendRadioOn(ACK_CODE);
+ }
command error_t Send.cancel(message_t* msg) {
/* Cancel is unsupported for now. */
txPhyHdr.length = _len;
txRunningCRC=0;
getMetadata(txMsgPtr)->length = _len;
- if (((xe1205_header_t*)( (uint8_t*)txMsgPtr->data - sizeof(xe1205_header_t)))->ack==1) {
+ if ((((xe1205_header_t*)( (uint8_t*)txMsgPtr->data - sizeof(xe1205_header_t)))->ack & 0x01)==0x01) {
call XE1205PhyRxTx.enableAck(TRUE);
}
txIndex = min(sizeof(xe1205_header_t) + _len + sizeof(xe1205_footer_t),
sendingAck=TRUE;
memcpy(txBuf, ackPreamble, sizeof(ackPreamble));
memcpy(txBuf + sizeof(pktPreamble), &txPhyHdr, sizeof(txPhyHdr));
-
- post signalPacketReceived();
+
break;
}
uint8_t sendDones = 0;
async event void XE1205PhyRxTx.sendFrameDone(error_t err) __attribute__ ((noinline)) {
sendDones++;
- if(sendingAck==FALSE)
- if(err==SUCCESS) {
+ if(sendingAck==FALSE) {
+ switch (err) {
+
+ case SUCCESS:
if (post sendDoneTask() != SUCCESS)
xe1205check(2, FAIL);
- } else {
+ break;
+
+ case ENOACK:
+ if(post sendDoneNoAckTask() !=SUCCESS)
+ xe1205check(2, FAIL);
+ break;
+
+ default:
if (post sendDoneFailTask() != SUCCESS)
xe1205check(2, FAIL);
}
- else {
+ } else {
+
txMsgPtr = NULL;
- sendingAck=FALSE;
+ sendingAck=FALSE;
+ post signalPacketReceived();
}
}
}
command void* Packet.getPayload(message_t* msg, uint8_t len) {
- if (len <= TOSH_DATA_LENGTH) {
- return (void*)msg->data;
- }
- else {
- return NULL;
- }
+ if (len <= TOSH_DATA_LENGTH) {
+ return (void*)msg->data;
+ }
+ else {
+ return NULL;
+ }
}
async command error_t PacketAcknowledgements.requestAck(message_t* msg) {
uint32_t nrxmsgs;
+
async event void XE1205PhyRxTx.rxFrameEnd(char* data, uint8_t len, error_t status) __attribute__ ((noinline)) {
if (status != SUCCESS){ return;}
}
}
+
+ async event void XE1205PhyRxTx.rxAckEnd(char* data, uint8_t len, error_t status) __attribute__ ((noinline)) {
+
+ sendingAck=FALSE;
+
+ if (status != SUCCESS) {
+ post sendDoneNoAckTask();
+ return;
+ }
+
+ if (rxBufPtr) {
+ post sendDoneNoAckTask();
+ return; // this could happen whenever rxFrameBegin was called with rxBufPtr still active
+ }
+
+ rxBufPtr = (data + sizeof(xe1205_phy_header_t));
+
+ checkCrcAndUnwhiten(rxBufPtr, rxPhyHdr.whitening, rxPhyHdr.length);
+
+ if (!getFooter(rxMsgPtr)->crc) {
+ post sendDoneNoAckTask();
+ atomic rxBufPtr = NULL;
+ return;
+ }
+
+ getMetadata((message_t*) rxMsgPtr)->strength = call XE1205PhyRssi.readRxRssi();
+ getMetadata((message_t*) rxMsgPtr)->length = rxPhyHdr.length;
+
+ if ((getHeader((message_t*)rxMsgPtr))->dest == TOS_NODE_ID) {
+ post sendDoneTask();
+ } else {
+ post sendDoneNoAckTask();
+ }
+ atomic rxBufPtr = NULL;
+ }
+
async event void XE1205PhyRssi.rssiDone(uint8_t _rssi) { }
}
call SpiResourceConfig.release();
atomic {
if (state == RADIO_STARTING){
- post startDone();}
+
+ post startDone();
+ }
if (state == RADIO_RX_ACK) {
enableAck=FALSE;
signal XE1205PhyRxTx.sendFrameDone(FAIL);
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;
+ 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()
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;
- }
+ 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;
call XE1205PatternConf.loadAckPatternHasBus();
armPatternDetect();
call SpiResourceTX.release();
-
call Alarm32khz16.start(usecs_to_jiffies(8000));
atomic {
call Interrupt0.enableRisingEdge();
} else {
enableAck = FALSE;
- signal XE1205PhyRxTx.sendFrameDone(SUCCESS);
+ signal XE1205PhyRxTx.rxAckEnd(rxFrame, rxFrameLen + headerLen, SUCCESS);
}
-
-
-
return;
case RADIO_RX_HEADER:
case RADIO_RX_PACKET:
if (rssiRange!=RSSI_OFF) {
- readRssi();
- return;
- }
+ readRssi();
+ return;
+ }
stats_rxOverruns++;
signal XE1205PhyRxTx.rxFrameEnd(NULL, 0, FAIL);
return;
case RADIO_RSSI:
- readRssi();
+ readRssi();
return;
case RADIO_RX_ACK: // ack timeout
}
- signal XE1205PhyRxTx.sendFrameDone(FAIL);
+ signal XE1205PhyRxTx.sendFrameDone(ENOACK);
return;
default:
-
-
+
return;
}
async event void rxFrameEnd(char* data, uint8_t len, error_t status);
+ /**
+ * Signalled at end of a Ack reception.
+ *
+ * @param data pointer to Ack (at first byte of header)
+ * @param len length of the Ack
+ * @param status SUCCESS if packet received ok, ERROR if packet reception was aborted.
+ *
+ */
+ async event void rxAckEnd(char* data, uint8_t len, error_t status);
+
+
/**
* Set header size, ie number of bytes at start of packet to be read and passed along
* with the rxFrameBegin() event.