interface MacSend;
interface MacReceive;
interface Packet;
- interface LocalTime<T32khz> as LocalTime32khz;
interface Sleeptime;
interface Teamgeist;
interface ChannelCongestion;
interface Alarm<T32khz, uint16_t> as Timer;
interface Alarm<T32khz, uint16_t> as SampleTimer;
- interface Counter<T32khz,uint16_t> as Counter32khz16;
+ interface LocalTime<T32khz> as LocalTime32kHz;
+
+ interface Duplicate;
+ interface TimeDiff16;
+ interface TimeDiff32;
+
async command am_addr_t amAddress();
/*
interface GeneralIO as Led0;
// DEFAULT_SLEEP_TIME=1625,
// DEFAULT_SLEEP_TIME=3250,
// DEFAULT_SLEEP_TIME=6500,
- // DEFAULT_SLEEP_TIME=9750,
- DEFAULT_SLEEP_TIME=16384,
- // DEFAULT_SLEEP_TIME=32768U,
+ // DEFAULT_SLEEP_TIME=8192,
+ // DEFAULT_SLEEP_TIME=16384,
+ DEFAULT_SLEEP_TIME=32768U,
+ // DEFAULT_SLEEP_TIME=65535U,
DATA_DETECT_TIME=17,
RX_SETUP_TIME=102, // time to set up receiver
TX_SETUP_TIME=58, // time to set up transmitter
// the duration of a send ACK
ACK_DURATION = SUB_HEADER_TIME + SUB_FOOTER_TIME,
MAX_SHORT_RETRY=9,
- MAX_LONG_RETRY=1,
- MAX_AGE=2*MAX_LONG_RETRY*MAX_SHORT_RETRY,
- MSG_TABLE_ENTRIES=20,
+ MAX_LONG_RETRY=3,
TOKEN_ACK_FLAG = 64,
TOKEN_ACK_MASK = 0x3f,
INVALID_SNR = 0xffff,
};
/**************** Module Global Variables *****************/
- typedef union
- {
- uint32_t op;
- struct {
- uint16_t lo;
- uint16_t hi;
- };
- } ui32parts_t;
-
/* flags */
typedef enum {
SWITCHING = 1,
TEAMGEIST_ACTIVE=128
} flags_t;
- /* duplicate suppression */
- typedef struct knownMessage_t {
- am_addr_t src;
- uint8_t token;
- uint8_t age;
- } knownMessage_t;
-
- knownMessage_t knownMsgTable[MSG_TABLE_ENTRIES];
uint8_t flags = 0;
uint8_t checkCounter = 0;
uint8_t shortRetryCounter = 0;
uint16_t localSleeptime = DEFAULT_SLEEP_TIME;
uint16_t rssiValue = 0;
uint32_t restLaufzeit = 0;
-
- uint16_t counter2sec = 127;
+
uint32_t rxTime = 0;
am_id_t teamgeistType = 0;
uint8_t congestionLevel = 0;
-
+
message_t *txBufPtr = NULL;
uint16_t txLen = 0;
red_mac_header_t *txMacHdr = NULL;
message_t ackMsg;
uint16_t MIN_BACKOFF_MASK;
-
+
/****** Secure switching of radio modes ***/
void interruptBackoffTimer();
}
}
- /**************** Helper functions ************************/
+ /**************** Helper functions ************************/
void computeBackoff();
void checkSend() {
sT = networkSleeptime;
}
if(msg == NULL) return;
- macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, NULL);
+ macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, sizeof(red_mac_header_t) + length);
macHdr->repetitionCounter = sT/(length * BYTE_TIME + SUB_HEADER_TIME + SUB_FOOTER_TIME +
TX_GAP_TIME) + 1;
atomic {
txStat.maxRepCounter = macHdr->repetitionCounter;
txStat.creationTime = getMetadata(msg)->time;
#endif
+ getMetadata(msg)->maxRepetitions = macHdr->repetitionCounter;
+ }
+ }
+
+ void storeStrength(message_t *m) {
+ if(rssiValue != INVALID_SNR) {
+ (getMetadata(txBufPtr))->strength = rssiValue;
+ }
+ else {
+ if(call RssiAdcResource.isOwner()) {
+ (getMetadata(txBufPtr))->strength = call ChannelMonitorData.readSnr();
+ }
+ else {
+ (getMetadata(txBufPtr))->strength = 1;
+ }
}
}
}
return repeat;
}
-
+
void signalSendDone(error_t error) {
message_t *m;
error_t e = error;
#endif
longRetryCounter = 0;
shortRetryCounter = 0;
- if(rssiValue != INVALID_SNR) {
- (getMetadata(m))->strength = rssiValue;
- }
- else {
- (getMetadata(m))->strength = call ChannelMonitorData.readSnr();
- }
+ storeStrength(m);
if(isFlagSet(&flags, CANCEL_SEND)) {
e = ECANCEL;
}
}
void interruptBackoffTimer() {
- uint16_t now;
if(call Timer.isRunning()) {
- restLaufzeit = call Timer.getAlarm();
+ restLaufzeit = call TimeDiff16.computeDelta(call Timer.getAlarm(), call Timer.getNow());
call Timer.stop();
- now = call Timer.getNow();
- if(restLaufzeit >= now) {
- restLaufzeit = restLaufzeit - now;
- }
- else {
- restLaufzeit = (uint16_t)(-1) - restLaufzeit + now;
- }
if(restLaufzeit > MIN_BACKOFF_MASK << MAX_LONG_RETRY) {
restLaufzeit = call Random.rand16() & ZERO_BACKOFF_MASK;
}
}
bool isNewMsg(message_t* msg) {
- bool rVal = TRUE;
- uint8_t i;
- for(i=0; i < MSG_TABLE_ENTRIES; i++) {
- if((getHeader(msg)->src == knownMsgTable[i].src) &&
- (((getHeader(msg)->token) & TOKEN_ACK_MASK) == knownMsgTable[i].token) &&
- (knownMsgTable[i].age < MAX_AGE)) {
- knownMsgTable[i].age = 0;
- rVal = FALSE;
- break;
- }
- }
- return rVal;
- }
-
- unsigned findOldest() {
- unsigned i;
- unsigned oldIndex = 0;
- unsigned age = knownMsgTable[oldIndex].age;
- for(i = 1; i < MSG_TABLE_ENTRIES; i++) {
- if(age < knownMsgTable[i].age) {
- oldIndex = i;
- age = knownMsgTable[i].age;
- }
- }
- return oldIndex;
- }
+ return call Duplicate.isNew(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
+ }
void rememberMsg(message_t* msg) {
- unsigned oldest = findOldest();
- knownMsgTable[oldest].src = getHeader(msg)->src;
- knownMsgTable[oldest].token = (getHeader(msg)->token) & TOKEN_ACK_MASK;
- knownMsgTable[oldest].age = 0;
+ call Duplicate.remember(getHeader(msg)->src, (getHeader(msg)->token) & TOKEN_ACK_MASK);
}
void prepareAck(message_t* msg) {
getHeader(&ackMsg)->dest = getHeader(msg)->src;
getHeader(&ackMsg)->type = getHeader(msg)->type;
#ifdef REDMAC_DEBUG
- repCounter = ((red_mac_header_t *)call SubPacket.getPayload(msg, NULL))->repetitionCounter;
+ repCounter = ((red_mac_header_t *)
+ call SubPacket.getPayload(msg, sizeof(red_mac_header_t)))->repetitionCounter;
#endif
}
uint32_t calcGeneratedTime(red_mac_header_t *m) {
return rxTime - m->time - TIME_CORRECTION;
}
-
/**************** Init ************************/
command error_t Init.init(){
- uint8_t i;
atomic {
macState = INIT;
seqNo = call Random.rand16() % TOKEN_ACK_FLAG;
- for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
- knownMsgTable[i].age = MAX_AGE;
- }
for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < networkSleeptime; ) {
MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
}
return call SubPacket.maxPayloadLength() - sizeof(red_mac_header_t);
}
- command void* Packet.getPayload(message_t* msg, uint8_t* len) {
- nx_uint8_t *payload = (nx_uint8_t *)call SubPacket.getPayload(msg, len);
- if (len != NULL) {
- *len -= sizeof(red_mac_header_t);
- }
+ command void* Packet.getPayload(message_t* msg, uint8_t len) {
+ nx_uint8_t *payload = (nx_uint8_t *)call SubPacket.getPayload(msg, len + sizeof(red_mac_header_t));
return (void*)(payload + sizeof(red_mac_header_t));
}
}
}
}
- else if(macState == INIT) {
- // sdDebug(167);
- post StartDoneTask();
- }
else if(macState == STOP) {
// sdDebug(168);
post StopDoneTask();
if(seqNo >= TOKEN_ACK_FLAG) seqNo = 1;
#ifdef REDMAC_PERFORMANCE
txStat.payloadLength = txLen;
- txStat.interfaceTime = call LocalTime32khz.get();
+ txStat.interfaceTime = call LocalTime32kHz.get();
#endif
}
else {
if(macState == CCA) {
computeBackoff();
#ifdef REDMAC_PERFORMANCE
- call Performance.macDetectedOnCca();
+ call Performance.macDetectedOnCca();
#endif
}
if(macState != RX_ACK) {
rxStat.duplicate = PERF_NEW_MSG;
#endif
// sdDebug(194);
- if(rssiValue != INVALID_SNR) {
- (getMetadata(m))->strength = rssiValue;
- }
- else {
- if(call RssiAdcResource.isOwner()) {
- (getMetadata(m))->strength = call ChannelMonitorData.readSnr();
- }
- else {
- (getMetadata(m))->strength = 1;
- }
- }
+ storeStrength(msg);
getMetadata(msg)->time = calcGeneratedTime((red_mac_header_t*) payload);
getMetadata(msg)->ack = WAS_NOT_ACKED;
m = signal MacReceive.receiveDone(msg);
#endif
}
}
+#ifdef REDMAC_PERFORMANCE
+ else {
+ rxStat.duplicate = PERF_REPEATED_MSG;
+ }
+#endif
if(needsAckRx(msg, &level) && (action != RX)) {
// sdDebug(197);
action = CCA_ACK;
else {
// sdDebug(199);
action = RX;
-#ifdef REDMAC_PERFORMANCE
- rxStat.duplicate = PERF_REPEATED_MSG;
-#endif
}
}
else {
}
else {
// sdDebug(201);
- action = RX;
+ action = SLEEP;
}
}
else if(macState == RX_ACK_P) {
if(error == SUCCESS) {
if(ackIsForMe(msg)) {
// sdDebug(202);
- if(rssiValue != INVALID_SNR) {
- (getMetadata(txBufPtr))->strength = rssiValue;
- }
- else {
- if(call RssiAdcResource.isOwner()) {
- (getMetadata(txBufPtr))->strength = call ChannelMonitorData.readSnr();
- }
- else {
- (getMetadata(txBufPtr))->strength = 1;
- }
- }
- (getMetadata(txBufPtr))->ack = WAS_ACKED;
- if(isFlagSet(&flags, TEAMGEIST_ACTIVE) && (getHeader(txBufPtr)->type == teamgeistType)) {
+ getMetadata(txBufPtr)->ack = WAS_ACKED;
+ getMetadata(txBufPtr)->repetitions = txMacHdr->repetitionCounter;
+ if(isFlagSet(&flags, TEAMGEIST_ACTIVE) &&
+ (getHeader(txBufPtr)->type == teamgeistType))
+ {
signal Teamgeist.gotAck(txBufPtr, getHeader(msg)->src,
getMetadata(txBufPtr)->strength);
}
action = SLEEP;
}
else {
- updateLongRetryCounters();
- action = RX;
+ // sdDebug(203);
+ updateLongRetryCounters(); // this will eventually schedule the right backoff
+ macState = SLEEP; // so much traffic is going on -- take a nap
+ setSleepMode();
+ action = INIT; // a difficult way to say: do nothing
}
}
else {
if(call Timer.isRunning()) {
- sdDebug(204);
+ // sdDebug(204);
action = RX_ACK;
}
else {
macState = RX_ACK;
setRxMode();
call Timer.start(RX_ACK_TIMEOUT);
- sdDebug(220);
+ // sdDebug(220);
checkCounter = 0;
}
else if(macState == TX_ACK) {
checkCounter = 0;
macState = RX;
setRxMode();
- sdDebug(221);
+ // sdDebug(221);
#ifdef REDMAC_DEBUG
// sdDebug(40000U + repCounter);
#endif
async event void RadioTimeStamping.receivedSFD( uint16_t time ) {
if(call RssiAdcResource.isOwner()) call ChannelMonitorData.getSnr();
if(macState == RX_P) {
- rxTime = call LocalTime32khz.get();
+ rxTime = call LocalTime32kHz.get();
call ChannelMonitor.rxSuccess();
}
}
async event void RadioTimeStamping.transmittedSFD( uint16_t time, message_t* p_msg ) {
- uint32_t now;
- uint32_t mTime;
if((macState == TX) && (p_msg == txBufPtr)) {
- now = call LocalTime32khz.get();
- mTime = getMetadata(p_msg)->time;
- if(now >= mTime) {
- txMacHdr->time = now - mTime;
- }
- else {
- // assume a clock wrap here
- txMacHdr->time = (uint32_t)(-1) - mTime + now;
- }
- }
- }
-
- async command uint32_t LocalTime32khz.get() {
- ui32parts_t time;
- atomic {
- time.lo = call Counter32khz16.get();
- time.hi = counter2sec;
- if(call Counter32khz16.isOverflowPending()) ++time.hi;
+ txMacHdr->time =
+ call TimeDiff32.computeDelta(call LocalTime32kHz.get(), getMetadata(p_msg)->time);
}
- return time.op;
}
- async event void Counter32khz16.overflow() {
- ++counter2sec;
- }
-
-
/****** Timer ******************************/
void checkOnBusy() {
setTxMode();
#ifdef REDMAC_PERFORMANCE
call Performance.macIdleOnCca();
- txStat.txModeTime = call LocalTime32khz.get();
+ txStat.txModeTime = call LocalTime32kHz.get();
#endif
}
}
// sdDebug(244);
macState = TX_ACK;
setTxMode();
- sdDebug(20000 + getHeader(&ackMsg)->dest);
+ // sdDebug(20000 + getHeader(&ackMsg)->dest);
#ifdef REDMAC_PERFORMANCE
call Performance.macTxAckStats(getHeader(&ackMsg)->type,
getHeader(&ackMsg)->dest,
}
else if(macState == RX_ACK) {
if(prepareRepetition()) {
- sdDebug(253);
+ // sdDebug(253);
macState = TX;
setTxMode();
}
else {
if(needsAckTx(txBufPtr)) {
- sdDebug(254);
+ // sdDebug(254);
#ifdef REDMAC_PERFORMANCE
call Performance.macAckTimeout();
#endif
}
else if(macState == TX_ACK) {
setTxMode();
- sdDebug(10000 + getHeader(&ackMsg)->dest);
+ // sdDebug(10000 + getHeader(&ackMsg)->dest);
}
else if(macState == SLEEP) {
if(isFlagSet(&flags, SWITCHING)) {
/****** SampleTimer ******************************/
- task void ageMsgsTask() {
- unsigned i;
- atomic {
- for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
- if(knownMsgTable[i].age <= MAX_AGE) ++knownMsgTable[i].age;
- }
- }
- }
-
async event void SampleTimer.fired() {
call SampleTimer.start(localSleeptime);
// sdDebug(270);
setRxMode();
call Timer.stop();
}
- post ageMsgsTask();
}
/***** Sleeptime **********************************/