interface MacReceive;
interface Packet;
interface LocalTime<T32khz> as LocalTime32khz;
- interface SleepTime;
+ interface Sleeptime;
interface Teamgeist;
interface ChannelCongestion;
}
interface Alarm<T32khz, uint16_t> as SampleTimer;
interface Counter<T32khz,uint16_t> as Counter32khz16;
async command am_addr_t amAddress();
+/*
+ interface GeneralIO as Led0;
+ interface GeneralIO as Led1;
+ interface GeneralIO as Led2;
+ interface GeneralIO as Led3;
+*/
#ifdef REDMAC_DEBUG
interface SerialDebug;
#endif
+#ifdef REDMAC_PERFORMANCE
+ interface Performance;
+#endif
+
}
}
implementation
void sdDebug(uint16_t p) {
call SerialDebug.putPlace(p);
}
+ uint8_t repCounter;
#else
void sdDebug(uint16_t p) {};
#endif
+#ifdef REDMAC_PERFORMANCE
+ macTxStat_t txStat;
+ macRxStat_t rxStat;
+#endif
+
/**************** Module Global Constants *****************/
enum {
-/*
- BYTE_TIME=13, // byte at 38400 kBit/s, 4b6b encoded
- PREAMBLE_BYTE_TIME=9, // byte at 38400 kBit/s, no coding
- PHY_HEADER_TIME=51, // 6 Phy Preamble at 38400
-*/
- BYTE_TIME=10, // byte at 49000 kBit/s, 4b6b encoded
- PREAMBLE_BYTE_TIME=7, // byte at 49000 kBit/s, no coding
- PHY_HEADER_TIME=40, // 6 Phy Preamble at 49000
-/*
- BYTE_TIME=12, // byte at 40960 kBit/s, 4b6b encoded
- PREAMBLE_BYTE_TIME=8, // byte at 40960 kBit/s, no coding
- PHY_HEADER_TIME=48, // 6 Phy Preamble at 40960
-*/
- SUB_HEADER_TIME=PHY_HEADER_TIME + sizeof(tda5250_header_t)*BYTE_TIME,
+ BYTE_TIME=21, // byte at 23405 kBit/s, 4b6b encoded
+ PREAMBLE_BYTE_TIME=14, // byte at 23405 kBit/s, no coding
+ PHY_HEADER_TIME=84, // 6 Phy Preamble at 23405 bits/s
+ TIME_CORRECTION=16, // difference between txSFD and rxSFD: 475us
+
+ SUB_HEADER_TIME=PHY_HEADER_TIME + sizeof(message_header_t)*BYTE_TIME,
SUB_FOOTER_TIME=2*BYTE_TIME, // 2 bytes crc
// DEFAULT_SLEEP_TIME=1625,
// DEFAULT_SLEEP_TIME=3250,
// DEFAULT_SLEEP_TIME=6500,
// DEFAULT_SLEEP_TIME=9750,
DEFAULT_SLEEP_TIME=16384,
+ // DEFAULT_SLEEP_TIME=32768U,
DATA_DETECT_TIME=17,
- RX_SETUP_TIME=111, // time to set up receiver
- TX_SETUP_TIME=69, // time to set up transmitter
- ADDED_DELAY = PREAMBLE_BYTE_TIME,
- RX_ACK_TIMEOUT = RX_SETUP_TIME + PHY_HEADER_TIME + 2*ADDED_DELAY + 19,
- TX_GAP_TIME=RX_ACK_TIMEOUT + TX_SETUP_TIME + 11,
+ RX_SETUP_TIME=102, // time to set up receiver
+ TX_SETUP_TIME=58, // time to set up transmitter
+ ADDED_DELAY = 30,
+ RX_ACK_TIMEOUT = RX_SETUP_TIME + PHY_HEADER_TIME + ADDED_DELAY + 30,
+ TX_GAP_TIME = RX_ACK_TIMEOUT + TX_SETUP_TIME + 33,
// the duration of a send ACK
ACK_DURATION = SUB_HEADER_TIME + SUB_FOOTER_TIME,
- MAX_SHORT_RETRY=7,
- MAX_LONG_RETRY=2,
+ MAX_SHORT_RETRY=9,
+ MAX_LONG_RETRY=3,
MAX_AGE=2*MAX_LONG_RETRY*MAX_SHORT_RETRY,
MSG_TABLE_ENTRIES=20,
TOKEN_ACK_FLAG = 64,
TOKEN_ACK_MASK = 0x3f,
- /* correct the difference between the transmittedSFD and the receivedSFD
- that appears due to buffering, measured value on an osci is 320us, so this
- value is actually 10.48576
- */
- TIME_CORRECTION = 10,
INVALID_SNR = 0xffff,
// PREAMBLE_LONG = 5,
// PREAMBLE_SHORT = 2,
} knownMessage_t;
knownMessage_t knownMsgTable[MSG_TABLE_ENTRIES];
- uint8_t flags;
- uint8_t checkCounter;
- uint8_t shortRetryCounter;
- uint8_t longRetryCounter;
- uint16_t sleepTime;
- uint16_t rssiValue;
- uint32_t restLaufzeit;
-
- message_t *txBufPtr;
- uint16_t txLen;
- red_mac_header_t *txMacHdr;
+ uint8_t flags = 0;
+ uint8_t checkCounter = 0;
+ uint8_t shortRetryCounter = 0;
+ uint8_t longRetryCounter = 0;
+ uint16_t networkSleeptime = DEFAULT_SLEEP_TIME;
+ uint16_t localSleeptime = DEFAULT_SLEEP_TIME;
+ uint16_t rssiValue = 0;
+ uint32_t restLaufzeit = 0;
- uint16_t seqNo;
- message_t ackMsg;
+ uint16_t counter2sec = 127;
+ uint32_t rxTime = 0;
- uint16_t counter2sec;
- uint32_t rxTime;
+ am_id_t teamgeistType = 0;
- am_id_t teamgeistType;
+ uint8_t congestionLevel = 0;
+
+ message_t *txBufPtr = NULL;
+ uint16_t txLen = 0;
+ red_mac_header_t *txMacHdr = NULL;
+ uint16_t seqNo;
+ message_t ackMsg;
- uint8_t congestionLevel;
uint16_t MIN_BACKOFF_MASK;
/****** Secure switching of radio modes ***/
if(call RadioModes.RxMode() == FAIL) {
post SetRxModeTask();
}
+ else {
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macRxMode();
+#endif
+ }
requestAdc();
}
if(call RadioModes.SleepMode() == FAIL) {
post SetSleepModeTask();
}
+ else {
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macSleepMode();
+#endif
+ }
}
task void SetSleepModeTask() {
if(call RadioModes.TxMode() == FAIL) {
post SetTxModeTask();
}
+ else {
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macTxMode();
+#endif
+ }
}
task void SetTxModeTask() {
checkCounter = 0;
setRxMode();
}
- else {
- if(txBufPtr) sdDebug(41);
- if(shortRetryCounter) sdDebug(42);
- if(isFlagSet(&flags, MESSAGE_PREPARED)) sdDebug(43);
+/* else {
+ if(txBufPtr) // sdDebug(41);
+ if(shortRetryCounter) // sdDebug(42);
+ if(isFlagSet(&flags, MESSAGE_PREPARED)) // sdDebug(43);
if(txBufPtr) {
- if(macState == SLEEP) sdDebug(44);
- if(!isFlagSet(&flags, RESUME_BACKOFF)) sdDebug(45);
- if(!call Timer.isRunning()) sdDebug(46);
+ if(macState == SLEEP) // sdDebug(44);
+ if(!isFlagSet(&flags, RESUME_BACKOFF)) // sdDebug(45);
+ if(!call Timer.isRunning()) // sdDebug(46);
}
}
+*/
}
uint32_t backoff(uint8_t counter) {
atomic {
msg = txBufPtr;
length = txLen;
- sT = sleepTime;
+ sT = networkSleeptime;
}
if(msg == NULL) return;
macHdr = (red_mac_header_t *)call SubPacket.getPayload(msg, NULL);
call Timer.start(backoff(longRetryCounter));
}
}
+#ifdef REDMAC_PERFORMANCE
+ txStat.type = getHeader(msg)->type;
+ txStat.to = getHeader(msg)->dest;
+ txStat.token = getHeader(msg)->token;
+ txStat.maxRepCounter = macHdr->repetitionCounter;
+ txStat.creationTime = getMetadata(msg)->time;
+#endif
+ getMetadata(msg)->maxRepetitions = macHdr->repetitionCounter;
}
}
m = txBufPtr;
txBufPtr = NULL;
txLen = 0;
+#ifdef REDMAC_PERFORMANCE
+ txStat.repCounter = txMacHdr->repetitionCounter;
+ txStat.longRetry = longRetryCounter;
+ txStat.shortRetry = shortRetryCounter;
+#endif
longRetryCounter = 0;
shortRetryCounter = 0;
if(rssiValue != INVALID_SNR) {
clearFlag(&flags, MESSAGE_PREPARED);
clearFlag(&flags, CANCEL_SEND);
}
- sdDebug(3000 + e);
- sdDebug(4000 + getHeader(m)->type);
+ // sdDebug(3000 + e);
+ // sdDebug(4000 + getHeader(m)->type);
signal MacSend.sendDone(m, e);
+#ifdef REDMAC_PERFORMANCE
+ txStat.success = e;
+ txStat.strength = getMetadata(m)->strength;
+ call Performance.macTxMsgStats(&txStat);
+#endif
}
void updateRetryCounters() {
longRetryCounter++;
shortRetryCounter = 1;
if(longRetryCounter > MAX_LONG_RETRY) {
- sdDebug(60);
+ // sdDebug(60);
signalSendDone(FAIL);
}
}
longRetryCounter++;
shortRetryCounter = 1;
if(longRetryCounter > MAX_LONG_RETRY) {
- sdDebug(70);
+ // sdDebug(70);
signalSendDone(FAIL);
} else {
post PrepareMsgTask();
uint16_t now;
if(call Timer.isRunning()) {
restLaufzeit = call Timer.getAlarm();
- call Timer.stop();
- now = call Timer.getNow();
+ call Timer.stop();
+ now = call Timer.getNow();
if(restLaufzeit >= now) {
restLaufzeit = restLaufzeit - now;
}
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)) {
+ if((knownMsgTable[i].age < MAX_AGE) &&
+ (getHeader(msg)->src == knownMsgTable[i].src) &&
+ (((getHeader(msg)->token) & TOKEN_ACK_MASK) == knownMsgTable[i].token)) {
knownMsgTable[i].age = 0;
rVal = FALSE;
break;
getHeader(&ackMsg)->src = call amAddress();
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;
+#endif
}
uint32_t calcGeneratedTime(red_mac_header_t *m) {
uint8_t i;
atomic {
macState = INIT;
- flags = 0;
- checkCounter = 0;
- rssiValue = 0;
- restLaufzeit = 0;
seqNo = call Random.rand16() % TOKEN_ACK_FLAG;
- txBufPtr = NULL;
- txLen = 0;
- txMacHdr = NULL;
- sleepTime = DEFAULT_SLEEP_TIME;
for(i = 0; i < MSG_TABLE_ENTRIES; i++) {
knownMsgTable[i].age = MAX_AGE;
}
- for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < sleepTime; ) {
+ for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < networkSleeptime; ) {
MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
}
MIN_BACKOFF_MASK >>= 2;
- shortRetryCounter = 0;
- longRetryCounter = 0;
- counter2sec = 127;
- rxTime = 0;
- teamgeistType = 0;
}
#ifdef REDMAC_DEBUG
call SerialDebug.putShortDesc("RedMacP");
task void StartDoneTask() {
// sdDebug(90);
atomic {
- call SampleTimer.start(sleepTime);
+ call SampleTimer.start(localSleeptime);
macState = SLEEP;
setFlag(&flags, TEAMGEIST_ACTIVE);
teamgeistType = signal Teamgeist.observedAMType();
}
async event void RadioModes.SleepModeDone() {
- sdDebug(160);
+ // sdDebug(160);
atomic {
clearFlag(&flags, SWITCHING);
if(isFlagSet(&flags, ACTION_DETECTED)) {
} else {
if(congestionLevel > 0) congestionLevel--;
}
- if(congestionLevel > 3) sdDebug(2000 + congestionLevel);
+ // if(congestionLevel > 3) // sdDebug(2000 + congestionLevel);
if(macState == SLEEP) {
// sdDebug(161);
if(!call Timer.isRunning()) {
}
}
}
- else if(macState == INIT) {
- // sdDebug(167);
- post StartDoneTask();
- }
else if(macState == STOP) {
// sdDebug(168);
post StopDoneTask();
atomic {
if((shortRetryCounter == 0) && (txBufPtr == NULL)) {
clearFlag(&flags, MESSAGE_PREPARED);
- sdDebug(5000 + getHeader(msg)->type);
+ // sdDebug(5000 + getHeader(msg)->type);
shortRetryCounter = 1;
longRetryCounter = 1;
txBufPtr = msg;
txLen = len + sizeof(red_mac_header_t);
seqNo++;
if(seqNo >= TOKEN_ACK_FLAG) seqNo = 1;
+#ifdef REDMAC_PERFORMANCE
+ txStat.payloadLength = txLen;
+ txStat.interfaceTime = call LocalTime32khz.get();
+#endif
}
else {
// sdDebug(171);
error_t err = FAIL;
atomic {
if(msg == txBufPtr) {
- sdDebug(320);
+ // sdDebug(320);
setFlag(&flags, CANCEL_SEND);
shortRetryCounter = MAX_SHORT_RETRY + 2;
longRetryCounter = MAX_LONG_RETRY + 2;
if(macState == SLEEP) {
- sdDebug(321);
+ // sdDebug(321);
signalSendDone(ECANCEL);
}
else {
- sdDebug(322);
+ // sdDebug(322);
}
- sdDebug(1000 + macState);
+ // sdDebug(1000 + macState);
err = SUCCESS;
}
else {
- sdDebug(323);
- sdDebug(1100 + macState);
+ // sdDebug(323);
+ // sdDebug(1100 + macState);
}
}
return err;
setFlag(&flags, ACTION_DETECTED);
call ChannelMonitor.rxSuccess();
if(macState <= CCA_ACK) {
- if(macState == CCA) computeBackoff();
+ if(macState == CCA) {
+ computeBackoff();
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macDetectedOnCca();
+#endif
+ }
if(macState != RX_ACK) {
macState = RX_P;
} else {
uint32_t nav = 0;
uint8_t level = 0;
bool isCnt;
-
+#ifdef REDMAC_PERFORMANCE
+ rxStat.duplicate = PERF_UNKNOWN;
+ rxStat.repCounter = 0xff;
+#endif
// sdDebug(190);
if(macState == RX_P) {
// sdDebug(191);
if(!isCnt) {
// sdDebug(193);
if(isNewMsg(msg)) {
+#ifdef REDMAC_PERFORMANCE
+ rxStat.duplicate = PERF_NEW_MSG;
+#endif
// sdDebug(194);
if(rssiValue != INVALID_SNR) {
(getMetadata(m))->strength = rssiValue;
(getMetadata(m))->strength = 1;
}
}
- (getMetadata(msg))->time = calcGeneratedTime((red_mac_header_t*) payload);
+ getMetadata(msg)->time = calcGeneratedTime((red_mac_header_t*) payload);
+ getMetadata(msg)->ack = WAS_NOT_ACKED;
m = signal MacReceive.receiveDone(msg);
// assume a buffer swap -- if buffer is not swapped, assume that the
// message was not successfully delivered to upper layers
} else {
// sdDebug(196);
action = RX;
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macQueueFull();
+#endif
}
}
+#ifdef REDMAC_PERFORMANCE
+ else {
+ rxStat.duplicate = PERF_REPEATED_MSG;
+ }
+#endif
if(needsAckRx(msg, &level) && (action != RX)) {
// sdDebug(197);
action = CCA_ACK;
(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);
}
- sdDebug(203);
+ // sdDebug(203);
signalSendDone(SUCCESS);
+ // sdDebug(30000 + getHeader(msg)->src);
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 {
- // sdDebug(205);
+ sdDebug(205);
updateLongRetryCounters();
action = RX;
}
action = INIT;
}
if(action == CCA_ACK) {
- prepareAck(msg);
macState = CCA_ACK;
- call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + (ADDED_DELAY>>level));
+ if(call Random.rand16() & 2) {
+ call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + 16 - level*8 + ADDED_DELAY);
+ }
+ else {
+ macState = TX_ACK;
+ call Timer.start(RX_SETUP_TIME - TX_SETUP_TIME + 16);
+ }
+ prepareAck(msg);
}
else if(action == RX_ACK) {
macState = RX_ACK;
}
else {
setFlag(&flags, RESUME_BACKOFF);
- restLaufzeit = nav + backoff(longRetryCounter);
+ restLaufzeit = call Random.rand16() & ZERO_BACKOFF_MASK;
}
setSleepMode();
}
else {
// sdDebug(207);
}
+#ifdef REDMAC_PERFORMANCE
+ if(error == SUCCESS) {
+ rxStat.type = getHeader(msg)->type;
+ rxStat.from = getHeader(msg)->src;
+ rxStat.to = getHeader(msg)->dest;
+ rxStat.token = getHeader(msg)->token;
+ if(!isControl(msg)) rxStat.repCounter = ((red_mac_header_t*)payload)->repetitionCounter;
+ rxStat.payloadLength = len;
+ rxStat.strength = rssiValue;
+ rxStat.creationTime = getMetadata(msg)->time;
+ call Performance.macRxStats(&rxStat);
+ }
+#endif
return m;
}
async event void PacketSend.sendDone(message_t* msg, error_t error) {
if(macState == TX) {
- // sdDebug(220);
macState = RX_ACK;
setRxMode();
call Timer.start(RX_ACK_TIMEOUT);
+ // sdDebug(220);
checkCounter = 0;
}
else if(macState == TX_ACK) {
checkCounter = 0;
macState = RX;
setRxMode();
+ // sdDebug(221);
+#ifdef REDMAC_DEBUG
+ // sdDebug(40000U + repCounter);
+#endif
}
}
if((macState == RX) || (macState == CCA) || (macState == CCA_ACK)) {
if(macState == CCA) {
computeBackoff();
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macBusyOnCca();
+#endif
}
requestAdc();
// sdDebug(230);
// sdDebug(243);
macState = TX;
setTxMode();
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macIdleOnCca();
+ txStat.txModeTime = call LocalTime32khz.get();
+#endif
}
}
else if(macState == CCA_ACK) {
// sdDebug(244);
macState = TX_ACK;
setTxMode();
+ // sdDebug(20000 + getHeader(&ackMsg)->dest);
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macTxAckStats(getHeader(&ackMsg)->type,
+ getHeader(&ackMsg)->dest,
+ getHeader(&ackMsg)->token);
+#endif
}
}
else {
if(needsAckTx(txBufPtr)) {
// sdDebug(254);
+#ifdef REDMAC_PERFORMANCE
+ call Performance.macAckTimeout();
+#endif
updateLongRetryCounters();
}
else {
setSleepMode();
}
}
+ else if(macState == TX_ACK) {
+ setTxMode();
+ // sdDebug(10000 + getHeader(&ackMsg)->dest);
+ }
else if(macState == SLEEP) {
if(isFlagSet(&flags, SWITCHING)) {
// sdDebug(256);
}
async event void SampleTimer.fired() {
- call SampleTimer.start(sleepTime);
+ call SampleTimer.start(localSleeptime);
// sdDebug(270);
if((macState == SLEEP) && (!isFlagSet(&flags, SWITCHING))) {
clearFlag(&flags, ACTION_DETECTED);
post ageMsgsTask();
}
- /***** SleepTime **********************************/
- async command void SleepTime.setSleepTime(uint16_t sT) {
+ /***** Sleeptime **********************************/
+ async command void Sleeptime.setLocalSleeptime(uint16_t sT) {
+ atomic localSleeptime = sT;
+ }
+
+ async command uint16_t Sleeptime.getLocalSleeptime() {
+ uint16_t st;
+ atomic st = localSleeptime;
+ return st;
+ }
+
+ async command void Sleeptime.setNetworkSleeptime(uint16_t sT) {
atomic {
- sleepTime = sT;
+ networkSleeptime = sT;
for(MIN_BACKOFF_MASK = 1; MIN_BACKOFF_MASK < sT; ) {
MIN_BACKOFF_MASK = (MIN_BACKOFF_MASK << 1) + 1;
}
}
}
- async command uint16_t SleepTime.getSleepTime() {
+ async command uint16_t Sleeptime.getNetworkSleeptime() {
uint16_t st;
- atomic st = sleepTime;
+ atomic st = networkSleeptime;
return st;
}
event void ChannelMonitorControl.updateNoiseFloorDone() {
if(macState == INIT) {
// sdDebug(290);
- call Timer.start(call Random.rand16() % DEFAULT_SLEEP_TIME);
+ call Timer.start(call Random.rand16() % localSleeptime);
setSleepMode();
} else {
// sdDebug(291);
}
default async event void ChannelCongestion.congestionEvent(uint8_t level) {}
-
+
/***** unused Radio Modes events **************************/
async event void RadioModes.TimerModeDone() {}