📄 smacm.nc
字号:
} if (length == 0 || length > PHY_MAX_PKT_LEN) { uartDebug_txByte(SMAC_UCAST_REQUEST_REJECTED_PKTLEN_ERROR); } if (numFrags == 0) { uartDebug_txByte(SMAC_UCAST_REQUEST_REJECTED_NUMFRAGS_IS_0); } return FAIL; } getNodeIdx(toAddr, &nodeIdx, &emptyIdx);#ifndef SMAC_NO_SLEEP_CYCLE if (nodeIdx == SMAC_MAX_NUM_NEIGHB) { // unknown neighbor return FAIL; } else { schedId = neighbList[nodeIdx].schedId; }#endif // Don't accept Tx request if I have already accepted a request // disable interrupt when check the value of txRequest intEnabled = inp(SREG) & 0x80; cli(); if (txRequest == 0) { txRequest = 1; if (intEnabled) sei(); } else { if (intEnabled) sei(); uartDebug_txByte(SMAC_UCAST_REQUEST_REJECTED_TXREQUEST_IS_1); return FAIL; } dataPkt = (MACHeader*)data; sendAddr = toAddr; txPktLen = length; txFragAll = numFrags; txFragCount = 0; numRetry = 0; numExtend = 0; // calculate duration of data packet/fragment durDataPkt = (PRE_PKT_BYTES + length * ENCODE_RATIO) * 8 / BANDWIDTH + 1; // fill in MAC header fields except duration dataPkt->type = DATA_PKT << 4; // higher 4 bits dataPkt->toAddr = sendAddr; dataPkt->fromAddr = TOS_LOCAL_ADDRESS; if (nodeIdx < SMAC_MAX_NUM_NEIGHB) { // known neighbor dataPkt->seqFragNo = neighbList[nodeIdx].txSeqNo << 3; //higher 5 bits neighbList[nodeIdx].txSeqNo = (neighbList[nodeIdx].txSeqNo++) & 0x1f; }#ifdef SMAC_NO_SLEEP_CYCLE // try to send now tryToSend();#else // set flag for data transmission dataSched = schedId; schedTab[schedId].txData = 1;#endif return SUCCESS; } command result_t MACComm.txNextFrag(void* data) { // Send subsequent fragments if (state != TX_NEXT_FRAG || data == 0) return FAIL; dataPkt = (MACHeader*)data; // fill in MAC header fields except duration dataPkt->type = DATA_PKT << 4; // data pkt dataPkt->toAddr = sendAddr; dataPkt->fromAddr = TOS_LOCAL_ADDRESS; dataPkt->seqFragNo++; // = txFragCount; // fragNo <= 7 if (neighbNav >= (SIFS + durDataPkt + timeWaitCtrl)) { // schedule to send this fragment state = TX_PKT; howToSend = SEND_DATA; txDelay = SIFS; } // else will retry when neighbNav timeout return SUCCESS; } command result_t MACComm.txReset() { // force MAC to drop currently buffered tx packet // so that it will accept a new one#ifndef SMAC_NO_SLEEP_CYCLE uint8_t i; for (i = 0; i < SMAC_MAX_NUM_SCHED; i++) { schedTab[i].txData = 0; }#endif txRequest = 0; return SUCCESS; } void startBcast() { // broadcast data directly; don't use RTS/CTS#ifdef SMAC_DEBUG *((char*)dataPkt + sizeof(MACHeader) + 10) = numLenErr; *((char*)dataPkt + sizeof(MACHeader) + 11) = numCrcErr; *((char*)dataPkt + sizeof(MACHeader) + 12) = numSlpPkt; *((char*)dataPkt + sizeof(MACHeader) + 13) = numCTStimeout; *((char*)dataPkt + sizeof(MACHeader) + 14) = numDATAtimeout; *((char*)dataPkt + sizeof(MACHeader) + 15) = numACKtimeout; *((char*)dataPkt + sizeof(MACHeader) + 17) = numSleeps; *((char*)dataPkt + sizeof(MACHeader) + 18) = numWakeups; *((char*)dataPkt + sizeof(MACHeader) + 19) = neighbNav; *((char*)dataPkt + sizeof(MACHeader) + 20) = syncDiff1; *((char*)dataPkt + sizeof(MACHeader) + 21) = syncDiff2; *(uint16_t*)((char*)dataPkt + sizeof(MACHeader) + 22) = schedTab[0].counter; *(uint16_t*)((char*)dataPkt + sizeof(MACHeader) + 24) = schedTab[1].counter;#endif#ifdef SMAC_TX_TIME_STAMP dataPkt->txTimeStamp = clockTime;#endif call PhyComm.txPkt(dataPkt, txPktLen); radioState = RADIO_TX; state = TX_PKT; geneTime = TX_PKT_DONE_TIME; } void txMsgDone() { // update schedTab and neighbList if flags are set when txRequest=1 update_schedTab_neighbList(); // prepare to tx next msg txRequest = 0;#ifdef SMAC_NO_SLEEP_CYCLE state = IDLE; uartDebug_txByte(state);#else schedTab[dataSched].txData = 0; sleep(TRY);#endif signal MACComm.unicastDone(dataPkt, txFragCount); } void update_schedTab_neighbList() { //update schedTab and neighbList if flag is set //we should update the schedTab[].numNodes before we call checkMySched() //to ensure the next available schedule is correct check_schedFlag(); if (updateNeighbList == 1) { update_neighbList(); updateNeighbList = 0; schedTab[0].chkSched = 0; //we already did checkMySched() in update_neighbList() }else if (schedTab[0].chkSched == 1) { checkMySched(); schedTab[0].chkSched = 0; } } event result_t PhyComm.txPktDone(void* packet) { char pktType; geneTime = 0; radioState = RADIO_IDLE; if (packet == 0 || state != TX_PKT) return FAIL; // CHECK if needed pktType = (*((char*)packet + sizeof(PhyHeader))) >> 4; switch (pktType) { // the type field case SYNC_PKT: schedTab[syncSched].txSync = 0; state = IDLE; // reset SYNC timer after sending to my schedule if (syncSched == 0) timeToTxSync = SYNC_PERIOD; if (numSyncTx > 0) { numSyncTx--; // SYNC is done for one schedule if (numSyncTx == 0) syncSeqNo++; // increase sequence number } uartDebug_txByte(TX_SYNC_DONE); break; case RTS_PKT: // track neighbors' NAV, need to clear it if CTS timeout TRACK_NAV(((MACCtrlPkt*)packet)->duration); // just sent RTS, set timer for CTS timeout state = WAIT_CTS; geneTime = timeWaitCtrl; uartDebug_txByte(TX_RTS_DONE); break; case CTS_PKT: // just sent CTS // track my neighbors' NAV // they update NAV and go to sleep after recv CTS TRACK_NAV(((MACCtrlPkt*)packet)->duration); state = WAIT_DATA; // no data timeout, just use neighbors' NAV // since they went to sleep, just wait data for the entire time uartDebug_txByte(TX_CTS_DONE); break; case DATA_PKT: if (((MACHeader*)packet)->toAddr == TOS_BCAST_ADDR) { uartDebug_txByte(TX_BCAST_DONE);#ifdef SMAC_NO_SLEEP_CYCLE state = IDLE; uartDebug_txByte(state); txRequest = 0; signal MACComm.broadcastDone(dataPkt);#else // broadcast data is done for one schedule schedTab[dataSched].txData = 0; sleep(TRY); numBcast--; if (numBcast == 0) { // broadcast is done for all schedules // update schedTab and neighbList if flags are set when txRequest=1 update_schedTab_neighbList(); txRequest = 0; signal MACComm.broadcastDone(dataPkt); }#endif } else { // unicast is done state = WAIT_ACK; // waiting for ACK, set timer for ACK timeout geneTime = timeWaitCtrl; uartDebug_txByte(TX_UCAST_DONE); } break; case ACK_PKT: TRACK_NAV(((MACCtrlPkt*)packet)->duration); // in case tx extended. // MAC stay in WAIT_DATA state until neighbNav becomes zero state = WAIT_DATA; uartDebug_txByte(TX_ACK_DONE); break; } return SUCCESS; } void tryToResend(uint8_t delay) { // try to re-send a packet when CTS or ACK timeout if (numRetry < SMAC_RETRY_LIMIT) { numRetry++;#ifdef SMAC_NO_SLEEP_CYCLE state = IDLE; uartDebug_txByte(state); if (delay == 0) tryToSend(); else retryTime = delay;#else // wait unitl receiver's next wake-up time sleep(TRY);#endif } else { // reached retry limit, give up Tx txMsgDone(); // with txFragCount < txFragAll; } } void adaptiveListen() { // adaptively wake-up at the end of current transmission. Will try to // send only if the buffered packet is unicast. Since my next-hop // neighbor may not be aware of the Tx of my previous-hop neighbor, // broadcast now is unreliable. if (srchNeighb == 1 || schedTab[0].counter > dataTime + listenTime || schedTab[0].counter < dataTime) { adapTime = dataTime; // set timer to bring me back to sleep if (state == SLEEP) wakeup(); else state = IDLE; uartDebug_txByte(state); if (txRequest == 1 && sendAddr != TOS_BCAST_ADDR && (schedTab[dataSched].counter > dataTime + listenTime || schedTab[dataSched].counter < dataTime)) { tryToSend(); } } else { sleep(TRY); } } event void Clock.fire() { // handle clock event uint8_t numRemain;#ifndef SMAC_NO_SLEEP_CYCLE uint8_t i; char intEnabled; uint16_t backoffSlots, listenBits;#endif#ifdef SMAC_PERFORMANCE if (cntRadioTime) { if (radioState == RADIO_SLEEP) radioTime.sleepTime++; else if (radioState == RADIO_IDLE) radioTime.idleTime++; else if (radioState == RADIO_RX) radioTime.rxTime++; else if (radioState == RADIO_TX) radioTime.txTime++; }#endif // advance clock clockTime++; // NAV timer if (nav > 0) { nav--; if (nav == 0) { // my neighbor is done Tx/Rx uartDebug_txByte(TIMER_FIRE_NAV);#if defined SMAC_NO_SLEEP_CYCLE wakeup(); if (txRequest == 1) { uartDebug_txByte(SMAC_TX_REQUEST_IS_1); tryToSend(); } else { uartDebug_txByte(SMAC_TX_REQUEST_IS_0); }#elif defined SMAC_NO_ADAPTIVE_LISTEN if (srchNeighb == 1) wakeup();#else adaptiveListen();#endif } } // timer to track my neighbor's NAV if (neighbNav > 0) { neighbNav--; if (neighbNav == 0) { // used up reserved Tx/Rx time uartDebug_txByte(TIMER_FIRE_NEIGHBOR_NAV); if (state == WAIT_ACK || state == TX_NEXT_FRAG) { // last tx is not done within reserved time tryToResend(0); // try to resend now } else { // could be in sleep, idle or wait_data state#if defined SMAC_NO_SLEEP_CYCLE state = IDLE; uartDebug_txByte(state); if (txRequest == 1) { uartDebug_txByte(SMAC_TX_REQUEST_IS_1); tryToSend(); } else { uartDebug_txByte(SMAC_TX_REQUEST_IS_0); }#elif defined SMAC_NO_ADAPTIVE_LISTEN sleep(TRY);#else adaptiveListen();#endif } } } // generic timer if (geneTime > 0) { geneTime--; if (geneTime == 0) { if (state == DATA_SENSE1) { uartDebug_txByte(TIMER_FIRE_DATA_SENSE1); // didn't see a CTS reply to a previous RTS geneTime = timeWaitCtrl; state = DATA_SENSE2; uartDebug_txByte(state); } else if (state == DATA_SENSE2) { uartDebug_txByte(TIMER_FIRE_DATA_SENSE2); // didn't see data tx, sender of RTS didn't get a CTS nav = 0; // cancel my NAV#ifdef SMAC_NO_SLEEP_CYCLE state = IDLE; uartDebug_txByte(state); if (txRequest == 1) { uartDebug_txByte(SMAC_TX_REQUEST_IS_1); tryToSend(); } else { uartDebug_txByte(SMAC_TX_REQUEST_IS_0); }#else sleep(TRY);#endif } else if (state == WAIT_CTS) { // CTS timeout uartDebug_txByte(TIMER_FIRE_WAIT_CTS);#ifdef SMAC_DEBUG numCTStimeout++;#endif neighbNav = 0; // neighbors won't follow my reserved time tryToResend(EIFS); // wait neighbors in data_sense2 } else if (state == WAIT_ACK) { // ACK timeout uartDebug_txByte(TIMER_FIRE_WAIT_ACK);#ifdef SMAC_DEBUG numACKtimeout++;#endif if (numExtend < SMAC_EXTEND_LIMIT && neighbNav > durDataPkt) { // can extend tx time numExtend++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -