-/*
- * Copyright (c) 2005-2006 Arch Rock Corporation
+/*
+ * Copyright (c) 2005-2006 Arch Rock Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
#include "CC2420.h"
+#include "CC2420TimeSyncMessage.h"
#include "crc.h"
#include "message.h"
-module CC2420TransmitP {
+module CC2420TransmitP @safe() {
provides interface Init;
provides interface StdControl;
provides interface CC2420Transmit as Send;
provides interface RadioBackoff;
- provides interface RadioTimeStamping as TimeStamp;
provides interface ReceiveIndicator as EnergyIndicator;
provides interface ReceiveIndicator as ByteIndicator;
uses interface Alarm<T32khz,uint32_t> as BackoffTimer;
uses interface CC2420Packet;
uses interface CC2420PacketBody;
+ uses interface PacketTimeStamp<T32khz,uint32_t>;
+ uses interface PacketTimeSyncOffset;
uses interface GpioCapture as CaptureSFD;
uses interface GeneralIO as CCA;
uses interface GeneralIO as CSN;
S_SFD,
S_EFD,
S_ACK_WAIT,
- S_LOAD_CANCEL,
- S_TX_CANCEL,
- S_CCA_CANCEL,
+ S_CANCEL,
} cc2420_transmit_state_t;
// This specifies how many jiffies the stack should wait after a
CC2420_ABORT_PERIOD = 320
};
- norace message_t *m_msg;
+ norace message_t * ONE_NOK m_msg;
norace bool m_cca;
/***************** Prototypes ****************/
- error_t send( message_t *p_msg, bool cca );
+ error_t send( message_t * ONE p_msg, bool cca );
error_t resend( bool cca );
void loadTXFIFO();
void attemptSend();
/**************** Send Commands ****************/
- async command error_t Send.send( message_t* p_msg, bool useCca ) {
+ async command error_t Send.send( message_t* ONE p_msg, bool useCca ) {
return send( p_msg, useCca );
}
atomic {
switch( m_state ) {
case S_LOAD:
- m_state = S_LOAD_CANCEL;
- break;
-
case S_SAMPLE_CCA:
- m_state = S_CCA_CANCEL;
- break;
-
case S_BEGIN_TRANSMIT:
- m_state = S_TX_CANCEL;
+ m_state = S_CANCEL;
break;
default:
}
-
+ inline uint32_t getTime32(uint16_t time)
+ {
+ uint32_t recent_time=call BackoffTimer.getNow();
+ return recent_time + (int16_t)(time - recent_time);
+ }
+
/**
* The CaptureSFD event is actually an interrupt from the capture pin
* which is connected to timing circuitry and timer modules. This
* would have picked up and executed had our microcontroller been fast enough.
*/
async event void CaptureSFD.captured( uint16_t time ) {
+ uint32_t time32;
+ uint8_t sfd_state = 0;
atomic {
+ time32 = getTime32(time);
switch( m_state ) {
case S_SFD:
m_state = S_EFD;
sfdHigh = TRUE;
+ // in case we got stuck in the receive SFD interrupts, we can reset
+ // the state here since we know that we are not receiving anymore
+ m_receiving = FALSE;
call CaptureSFD.captureFallingEdge();
- signal TimeStamp.transmittedSFD( time, m_msg );
+ call PacketTimeStamp.set(m_msg, time32);
+ if (call PacketTimeSyncOffset.isSet(m_msg)) {
+ uint8_t absOffset = sizeof(message_header_t)-sizeof(cc2420_header_t)+call PacketTimeSyncOffset.get(m_msg);
+ timesync_radio_t *timesync = (timesync_radio_t *)((nx_uint8_t*)m_msg+absOffset);
+ // set timesync event time as the offset between the event time and the SFD interrupt time (TEP 133)
+ *timesync -= time32;
+ call CSN.clr();
+ call TXFIFO_RAM.write( absOffset, (uint8_t*)timesync, sizeof(timesync_radio_t) );
+ call CSN.set();
+ //restoring the event time to the original value
+ *timesync += time32;
+ }
+
if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
// This is an ack packet, don't release the chip's SPI bus lock.
abortSpiRelease = TRUE;
releaseSpiResource();
call BackoffTimer.stop();
-
- if ( ( ( (call CC2420PacketBody.getHeader( m_msg ))->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7 ) == IEEE154_TYPE_DATA ) {
- (call CC2420PacketBody.getMetadata( m_msg ))->time = time;
- }
-
if ( call SFD.get() ) {
break;
}
/** Fall Through because the next interrupt was already received */
-
+
case S_EFD:
sfdHigh = FALSE;
call CaptureSFD.captureRisingEdge();
/** Fall Through because the next interrupt was already received */
default:
- if ( !m_receiving ) {
+ /* this is the SFD for received messages */
+ if ( !m_receiving && sfdHigh == FALSE ) {
sfdHigh = TRUE;
call CaptureSFD.captureFallingEdge();
- signal TimeStamp.receivedSFD( time );
- call CC2420Receive.sfd( time );
+ // safe the SFD pin status for later use
+ sfd_state = call SFD.get();
+ call CC2420Receive.sfd( time32 );
m_receiving = TRUE;
m_prev_time = time;
if ( call SFD.get() ) {
// wait for the next interrupt before moving on
return;
}
+ // if SFD.get() = 0, then an other interrupt happened since we
+ // reconfigured CaptureSFD! Fall through
}
- sfdHigh = FALSE;
- call CaptureSFD.captureRisingEdge();
- m_receiving = FALSE;
- if ( time - m_prev_time < 10 ) {
- call CC2420Receive.sfd_dropped();
+ if ( sfdHigh == TRUE ) {
+ sfdHigh = FALSE;
+ call CaptureSFD.captureRisingEdge();
+ m_receiving = FALSE;
+ /* if sfd_state is 1, then we fell through, but at the time of
+ * saving the time stamp the SFD was still high. Thus, the timestamp
+ * is valid.
+ * if the sfd_state is 0, then either we fell through and SFD
+ * was low while we safed the time stamp, or we didn't fall through.
+ * Thus, we check for the time between the two interrupts.
+ * FIXME: Why 10 tics? Seams like some magic number...
+ */
+ if ((sfd_state == 0) && (time - m_prev_time < 10) ) {
+ call CC2420Receive.sfd_dropped();
+ if (m_msg)
+ call PacketTimeStamp.clear(m_msg);
+ }
+ break;
}
- break;
-
}
}
}
uint8_t* ack_buf;
uint8_t length;
- if ( type == IEEE154_TYPE_ACK ) {
+ if ( type == IEEE154_TYPE_ACK && m_msg) {
ack_header = call CC2420PacketBody.getHeader( ack_msg );
msg_header = call CC2420PacketBody.getHeader( m_msg );
attemptSend();
break;
- case S_LOAD_CANCEL:
- case S_CCA_CANCEL:
- case S_TX_CANCEL:
+ case S_CANCEL:
call CSN.clr();
call SFLUSHTX.strobe();
call CSN.set();
atomic {
m_state = S_STARTED;
}
+ signal Send.sendDone( m_msg, ECANCEL );
break;
default:
error_t error ) {
call CSN.set();
- if ( m_state == S_LOAD_CANCEL ) {
+ if ( m_state == S_CANCEL ) {
atomic {
call CSN.clr();
call SFLUSHTX.strobe();
}
releaseSpiResource();
m_state = S_STARTED;
-
+ signal Send.sendDone( m_msg, ECANCEL );
+
} else if ( !m_cca ) {
atomic {
- if (m_state == S_LOAD_CANCEL) {
- m_state = S_TX_CANCEL;
- } else {
- m_state = S_BEGIN_TRANSMIT;
- }
+ m_state = S_BEGIN_TRANSMIT;
}
attemptSend();
} else {
releaseSpiResource();
atomic {
- if (m_state == S_LOAD_CANCEL) {
- m_state = S_CCA_CANCEL;
- } else {
- m_state = S_SAMPLE_CCA;
- }
+ m_state = S_SAMPLE_CCA;
}
signal RadioBackoff.requestInitialBackoff(m_msg);
}
break;
- case S_CCA_CANCEL:
- m_state = S_TX_CANCEL;
- /** Fall Through */
-
case S_BEGIN_TRANSMIT:
- case S_TX_CANCEL:
+ case S_CANCEL:
if ( acquireSpiResource() == SUCCESS ) {
attemptSend();
}
* @param *p_msg Pointer to the message that needs to be sent
* @param cca TRUE if this transmit should use clear channel assessment
*/
- error_t send( message_t* p_msg, bool cca ) {
+ error_t send( message_t* ONE p_msg, bool cca ) {
atomic {
- if (m_state == S_LOAD_CANCEL
- || m_state == S_CCA_CANCEL
- || m_state == S_TX_CANCEL) {
+ if (m_state == S_CANCEL) {
return ECANCEL;
}
error_t resend( bool cca ) {
atomic {
- if (m_state == S_LOAD_CANCEL
- || m_state == S_CCA_CANCEL
- || m_state == S_TX_CANCEL) {
+ if (m_state == S_CANCEL) {
return ECANCEL;
}
bool congestion = TRUE;
atomic {
- if (m_state == S_TX_CANCEL) {
+ if (m_state == S_CANCEL) {
call SFLUSHTX.strobe();
releaseSpiResource();
call CSN.set();
m_state = S_STARTED;
+ signal Send.sendDone( m_msg, ECANCEL );
return;
}
m_tx_power = tx_power;
- call TXFIFO.write( (uint8_t*)header, header->length - 1);
+ {
+ uint8_t tmpLen __DEPUTY_UNUSED__ = header->length - 1;
+ call TXFIFO.write(TCAST(uint8_t * COUNT(tmpLen), header), header->length - 1);
+ }
}
void signalDone( error_t err ) {
call ChipSpiResource.attemptRelease();
signal Send.sendDone( m_msg, err );
}
-
-
-
- /***************** Tasks ****************/
-
- /***************** Defaults ****************/
- default async event void TimeStamp.transmittedSFD( uint16_t time, message_t* p_msg ) {
- }
-
- default async event void TimeStamp.receivedSFD( uint16_t time ) {
- }
-
}