provides interface CC2420AsyncSplitControl as AsyncSplitControl;
provides interface CC2420Receive;
provides interface CC2420Rx;
-/* provides interface ReceiveIndicator as PacketIndicator;*/
uses interface GeneralIO as CSN;
uses interface GeneralIO as FIFO;
uses interface CC2420Strobe as SACK;
uses interface CC2420Strobe as SFLUSHRX;
uses interface CC2420Strobe as SRXON;
- uses interface CC2420Strobe as SACKPEND; // JH: ACKs must have pending flag set
+ uses interface CC2420Strobe as SACKPEND;
uses interface CC2420Register as MDMCTRL1;
uses interface ReferenceTime;
uses interface FrameUtility;
uses interface CC2420Config;
-/* uses interface CC2420Packet;*/
-/* uses interface CC2420PacketBody;*/
-
- uses interface Leds;
+ uses interface CC2420Ram as RXFIFO_RAM;
}
implementation {
typedef enum {
S_STOPPED,
S_STARTING,
- S_STARTING_FLUSHRX,
S_STARTED,
S_RX_LENGTH,
S_RX_FCF,
SACK_HEADER_LENGTH = 3,
};
- ieee154_reftime_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];
- ieee154_reftime_t m_timestamp;
+ ieee154_timestamp_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];
+ ieee154_timestamp_t m_timestamp;
norace bool m_timestampValid;
uint8_t m_timestamp_head;
void flush();
void switchToUnbufferedMode();
void switchToBufferedMode();
- void startingSpiReserved();
void continueStart();
void continueStop();
task void stopContinueTask();
return SUCCESS;
}
- /***************** AsyncSplitControl ****************
- * IMPORTANT: when AsyncSplitControl.start is called,
- * the radio MUST be off !
+ /***************** AsyncSplitControl ****************/
+ /* NOTE: AsyncSplitControl does not switch the state of the radio
+ * hardware (i.e. it does not put the radio in Rx mode, this has to
+ * be done by the caller through a separate interface/component).
*/
- async command error_t AsyncSplitControl.start()
- {
- atomic {
- if (m_state != S_STOPPED){
- call Leds.led0On();
- return FAIL;
- } else {
- m_state = S_STARTING;
- if (call SpiResource.isOwner()){
- call Leds.led0On(); // internal error (debug) !
- startingSpiReserved();
- }
- if (call SpiResource.immediateRequest() == SUCCESS)
- startingSpiReserved();
- else
- call SpiResource.request();
- }
- }
- return SUCCESS;
- }
- void startingSpiReserved()
+ /**
+ * AsyncSplitControl.start should be called before radio
+ * is switched to Rx mode (or at least early enough before
+ * a packet has been received, i.e. before FIFOP changes)
+ */
+ async command error_t AsyncSplitControl.start()
{
atomic {
- if (!call FIFOP.get() || call FIFO.get()){ // FIFOP is inverted
- // there is something in RXFIFO: flush it out
- // the datasheet says at least one byte should
- // be read before flushing
- m_state = S_STARTING_FLUSHRX;
- call CSN.set();
- call CSN.clr();
- call RXFIFO.beginRead( &m_dummy, 1 ); // will continue in continueFlushStart()
- return;
+ if ( !call FIFO.get() && !call FIFOP.get() ){
+ // RXFIFO has some data (remember: FIFOP is inverted)
+ // the problem is that this messses up the timestamping
+ // so why don't we flush here ourselves?
+ // because we don't own the SPI...
+ return FAIL;
}
- }
- continueStart();
- }
-
-
- void continueFlushStart()
- {
- atomic {
- call CSN.set();
- call CSN.clr();
- call SFLUSHRX.strobe();
- call SFLUSHRX.strobe();
- call CSN.set();
- }
- continueStart();
- }
-
- void continueStart()
- {
- // RXFIFO is empty
- if (!call FIFOP.get() || call FIFO.get()){
- call Leds.led0On();
- }
- atomic {
+ ASSERT(m_state == S_STOPPED);
reset_state();
m_state = S_STARTED;
+ call InterruptFIFOP.enableFallingEdge(); // ready!
}
- call SpiResource.release();
- call InterruptFIFOP.enableFallingEdge();
- signal AsyncSplitControl.startDone(SUCCESS);
+ return SUCCESS;
}
- /***************** AsyncSplitControl ****************
+ /* AsyncSplitControl.stop:
+ *
* IMPORTANT: when AsyncSplitControl.stop is called,
- * the radio MUST NOT be off !
+ * then either
+ * 1) the radio MUST still be in RxMode
+ * 2) it was never put in RxMode after
+ * AsyncSplitControl.start() was called
+ *
+ * => The radio may be switched off only *after* the
+ * stopDone() event was signalled.
*/
async command error_t AsyncSplitControl.stop()
{
m_stop = TRUE;
call InterruptFIFOP.disable();
if (!receivingPacket)
- continueStop();
- // else stopContinueTask will be posted after
- // current Rx operation is finished, because m_stop is set
+ continueStop(); // it is safe to stop now
+ // else continueStop will be called after
+ // current Rx operation is finished
}
}
return SUCCESS;
void continueStop()
{
atomic {
+ if (!m_stop){
+ return;
+ }
m_stop = FALSE;
m_state = S_STOPPED;
}
task void stopContinueTask()
{
- if (receivingPacket){
- call Leds.led0On();
- }
+ ASSERT(receivingPacket != TRUE);
call SpiResource.release(); // may fail
atomic m_state = S_STOPPED;
signal AsyncSplitControl.stopDone(SUCCESS);
* Start frame delimiter signifies the beginning/end of a packet
* See the CC2420 datasheet for details.
*/
- async command void CC2420Receive.sfd( ieee154_reftime_t *time ) {
+ async command void CC2420Receive.sfd( ieee154_timestamp_t *time ) {
if (m_state == S_STOPPED)
return;
if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) {
uint8_t tail = ( ( m_timestamp_head + m_timestamp_size ) %
TIMESTAMP_QUEUE_SIZE );
- memcpy(&m_timestamp_queue[ tail ], time, sizeof(ieee154_reftime_t) );
+ memcpy(&m_timestamp_queue[ tail ], time, sizeof(ieee154_timestamp_t) );
m_timestamp_size++;
}
}
atomic {
switch (m_state)
{
- case S_STARTING: startingSpiReserved(); break;
- case S_STARTING_FLUSHRX: // fall through
- case S_STOPPED: call Leds.led0On();
- call SpiResource.release(); break;
+ case S_STOPPED: ASSERT(0); break; // this should never happen!
default: receive();
}
}
}
if ( m_timestamp_size ) {
- if ( rxFrameLength > 10 ) {
+ if ( rxFrameLength > 4 ) {
//((ieee154_metadata_t*) m_rxFramePtr->metadata)->timestamp = m_timestamp_queue[ m_timestamp_head ];
- memcpy(&m_timestamp, &m_timestamp_queue[ m_timestamp_head ], sizeof(ieee154_reftime_t) );
+ memcpy(&m_timestamp, &m_timestamp_queue[ m_timestamp_head ], sizeof(ieee154_timestamp_t) );
m_timestampValid = TRUE;
m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;
m_timestamp_size--;
waitForNextPacket();
break;
- case S_STARTING_FLUSHRX: continueFlushStart(); break;
-
default:
atomic receivingPacket = FALSE;
call CSN.set();
uint8_t payloadLen = ((ieee154_header_t*) m_rxFramePtr->header)->length - m_mhrLen - 2;
ieee154_metadata_t *metadata = (ieee154_metadata_t*) m_rxFramePtr->metadata;
- atomic {
- if (m_state == S_STOPPED){
- call Leds.led0On();
- return;
- }
- }
+ atomic ASSERT(m_state != S_STOPPED);
((ieee154_header_t*) m_rxFramePtr->header)->length = m_rxFramePtr->data[payloadLen+1] & 0x7f; // temp. LQI
metadata->rssi = m_rxFramePtr->data[payloadLen];
metadata->linkQuality = ((ieee154_header_t*) m_rxFramePtr->header)->length; // copy back
*/
void beginReceive() {
atomic {
- if ( m_state == S_STOPPED){
- call Leds.led0On();
+ if (m_state == S_STOPPED || m_stop){
return;
}
m_state = S_RX_LENGTH;
*/
void waitForNextPacket() {
atomic {
- receivingPacket = FALSE;
if ( m_state == S_STOPPED) {
call SpiResource.release();
return;
}
+ receivingPacket = FALSE;
if (m_stop){
continueStop();
return;