📄 smacm.nc
字号:
// need to increase neighbNav for one frag numRemain = txFragAll - txFragCount; neighbNav = numRemain * durCtrlPkt + numRemain * durDataPkt + (numRemain + numRemain - 1) * (PROC_DELAY + SIFS); dataPkt->type++; // lower 4 bits are a counter for retx sendDATA(); state = TX_PKT;#ifdef SMAC_REPORT retx++;#endif/* } else if (neighbNav >= durDataPkt + timeWaitCtrl) { sendDATA(); // can't extend but still have time to send state = TX_PKT; // if can't extend or send, retry when neighbNav timeout*/ } } else if (state == TX_PKT){ // Tx packet done waiting timer fire call RadioState.idle(); // turn on the radio radioState = RADIO_IDLE; state = IDLE; #ifdef SMAC_NO_SLEEP_CYCLE if (txRequest == 1) { uartDebug_txByte(SMAC_TX_REQUEST_IS_1); tryToSend(); } else { uartDebug_txByte(SMAC_TX_REQUEST_IS_0); }#else sleep(TRY);#endif uartDebug_txByte(state); } } }#ifndef SMAC_NO_SLEEP_CYCLE // check if it's time to send a SYNC packet if (timeToTxSync > 0) { timeToTxSync--; if (timeToTxSync == 0) { // set flag in each schedule to tx SYNC numSyncTx = numSched; for (i = 0; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes > 0) { schedTab[i].txSync = 1; } } uartDebug_txByte(TIMER_FIRE_NEED_TX_SYNC); //reset timer immediately to keep dependent timers running timeToTxSync = SYNC_PERIOD; numSyncPrd--; // for neighbor discovery if (numSyncPrd == 1) { srchNeighb = 1; } else if (numSyncPrd == 0) { srchNeighb = 0; if (numNeighb == 0) { // reset neighbor discovery timer numSyncPrd = SMAC_SRCH_NBR_SHORT_PERIOD; } else { numSyncPrd = SMAC_SRCH_NBR_LONG_PERIOD; } } if (neighbListTime > 0) { neighbListTime--; if (neighbListTime == 0) { // time to update my neighbor list if (txRequest == 0) { // No data waiting to be transmitted txRequest = 1; // temporarily disable tx when updating post update_myNeighbList(); } else { updateNeighbList = 1; // set flag to update when tx done } } } } } // update status of each schedule and arrange tx if needed for (i = 0; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes > 0) { schedTab[i].counter--; if (schedTab[i].counter == listenTime) { uartDebug_txByte(TIMER_FIRE_LISTEN_SYNC); if (i == 0) schedListen = 1; // it's my scheduled wake-up time if (nav == 0 && neighbNav == 0 && (state == SLEEP || state == IDLE)) { if (state == SLEEP && (i == 0 || schedTab[i].txSync == 1)) { wakeup(); // wake up to listen or send sync } if (schedTab[i].txSync == 1) { // start carrier sense for sending sync howToSend = SEND_SYNC; syncSched = i; backoffSlots = call Random.rand() & (uint16_t)SYNC_CW; listenBits = (DIFS + SLOTTIME * backoffSlots) * LISTEN_RATE; // start carrier sense and change state needs to be atomic // to prevent start symbol is detected between them intEnabled = inp(SREG) & 0x80; cli(); if (call CarrierSense.start(listenBits) == SUCCESS) { state = CARR_SENSE; } if (intEnabled) sei(); uartDebug_txByte(state); } } } else if (schedTab[i].counter == dataTime) { uartDebug_txByte(TIMER_FIRE_LISTEN_DATA); if (schedTab[i].txData == 1 && nav == 0 && neighbNav == 0 && (state == SLEEP || state == IDLE)) { // schedule sending of data if (state == SLEEP) wakeup(); // wake up to tx dataSched = i; tryToSend(); } } else if (schedTab[i].counter == 0) { uartDebug_txByte(TIMER_FIRE_SCHED_SLEEP); schedTab[i].counter = period; if (i == 0) { // my scheduled lisen time is over schedListen = 0; if (state == IDLE && txDelay == 0) sleep(TRY); // sleep if idle } } } }#endif#ifdef SMAC_NO_SLEEP_CYCLE // need a separate timer for updating neighbor list in fully active mode if (dataActiveTime > 0) { dataActiveTime--; if (dataActiveTime == 0) { // there is no mess with sending in fully active mode, since // sending does not check neighbor list or schedule table post update_myNeighbList(); } }#endif // tx delay timer if (txDelay > 0) { txDelay--; if (txDelay == 0) { // start sending uartDebug_txByte(TIMER_FIRE_TX_DELAY); if (howToSend == SEND_CTS) { sendCTS(); } else if (howToSend == SEND_DATA) { sendDATA(); } else if (howToSend == SEND_ACK) { sendACK(); } } } // adaptive wake-up timer if (adapTime > 0) { adapTime--; if (adapTime == 0) { uartDebug_txByte(TIMER_FIRE_ADAP_LISTEN_DONE); if (state == IDLE && txDelay == 0) sleep(TRY); } }#ifdef SMAC_NO_SLEEP_CYCLE if (retryTime > 0) { retryTime--; if (retryTime == 0) { uartDebug_txByte(TIMER_FIRE_TX_RETRY); tryToSend(); } }#endif signal MACTest.clockFire(); // signal upper layer the clock event // try to put CPU into idle mode if (state == SLEEP) call PowerManagement.adjustPower(); } event result_t CarrierSense.channelBusy() { // physical carrier sense indicate channel busy // Do nothing and stay in idle to receive a packet // Will sleep at my next sleep time if can't get a packet uartDebug_txByte(CHANNEL_BUSY_DETECTED); if (state == CARR_SENSE) { state = IDLE; uartDebug_txByte(state);#ifdef SMAC_NO_SLEEP_CYCLE retryTime = EIFS;#endif } return SUCCESS; } event result_t CarrierSense.channelIdle() { // physical carrier sense indicate channel idle // start sending uartDebug_txByte(CHANNEL_IDLE_DETECTED); if (state != CARR_SENSE) return FAIL; if (howToSend == SEND_SYNC) { sendSYNC(); } else if (howToSend == BCAST_DATA) { startBcast(); } else if (howToSend == SEND_RTS) { sendRTS(); } return SUCCESS; } event result_t PhyComm.startSymDetected(void* pkt) { uartDebug_txByte(START_SYMBOL_DETECTED); radioState = RADIO_RX; if (state == IDLE || state == CARR_SENSE) { state = BACKOFF; uartDebug_txByte(state); // put in coarse time stamp in ms ((PhyPktBuf*)pkt)->info.timeCoarse = clockTime; // put in fine/external time stamp call TimeStamp.getTime32(&(((PhyPktBuf*)pkt)->info.timestamp));#ifdef SMAC_NO_SLEEP_CYCLE retryTime = 0;#endif } else if (state == DATA_SENSE2) { // data tx started from the sender of RTS geneTime = 0; sleep(FORCE); } else { uartDebug_txByte(state); } return SUCCESS; } void handleErrPkt() { if (state == BACKOFF) state = IDLE; if (state == IDLE) {#ifdef SMAC_NO_SLEEP_CYCLE uartDebug_txByte(state); if (txRequest == 1) { uartDebug_txByte(SMAC_TX_REQUEST_IS_1); retryTime = EIFS; } else { uartDebug_txByte(SMAC_TX_REQUEST_IS_0); }#else sleep(TRY); // wait until next tx time#endif } } event void* PhyComm.rxPktDone(void* packet, char error) { char pktType; if (state == SLEEP) {#ifdef SMAC_DEBUG numSlpPkt++;#endif return packet; // if in sleep, reject any pkt. A bug occurs! } radioState = RADIO_IDLE; if (error) { // if received an erroneous pkt, a sign of collision uartDebug_txByte(RX_ERROR);#ifdef SMAC_DEBUG if (packet == NULL) numLenErr++; else numCrcErr++;#endif#ifdef SMAC_REPORT if (packet == NULL) { lenErr++; } else { crcErr++; }#endif // SMAC_REPORT handleErrPkt(); return packet; } pktType = (*((char*)packet + sizeof(PhyHeader))) >> 4; // dispatch to actual packet handlers if (pktType == DATA_PKT) { return handleDATA(packet); } else if (pktType == RTS_PKT) {#ifdef SMAC_REPORT ctrlPkts++;#endif uartDebug_txByte(RX_RTS_DONE); handleRTS(packet); } else if (pktType == CTS_PKT) {#ifdef SMAC_REPORT ctrlPkts++;#endif uartDebug_txByte(RX_CTS_DONE); handleCTS(packet); } else if (pktType == ACK_PKT) {#ifdef SMAC_REPORT ctrlPkts++;#endif uartDebug_txByte(RX_ACK_DONE); handleACK(packet);#ifndef SMAC_NO_SLEEP_CYCLE } else if (pktType == SYNC_PKT) { uartDebug_txByte(RX_SYNC_DONE);#ifdef SMAC_REPORT ctrlPkts++;#endif handleSYNC(packet);#endif // SMAC_NO_SLEEP_CYCLE } else { // unknown packet uartDebug_txByte(RX_UNKNOWN_PKT); handleErrPkt(); } return packet; } void handleRTS(void* pkt) { // internal handler for RTS MACCtrlPkt* packet; if (state != IDLE && state != BACKOFF) return; packet = (MACCtrlPkt*)pkt; if (packet->toAddr == TOS_LOCAL_ADDRESS) { recvAddr = packet->fromAddr; // remember sender's address rxFragAll = packet->type & 0xf; // lower 4 bits are number of frags lastRxFrag = 250; TRACK_NAV(packet->duration); // track neighbors' NAV // schedule sending CTS state = TX_PKT; howToSend = SEND_CTS; txDelay = SIFS; } else { // packet destined to another node // assume sender will get a CTS and tx data UPDATE_NAV(packet->duration); // keep listening until confirm sender gets a CTS or starts tx data state = DATA_SENSE1; // wait for a CTS geneTime = timeWaitCtrl; uartDebug_txByte(state); } } void handleCTS(void* pkt) { // internal handler for CTS MACCtrlPkt* packet; packet = (MACCtrlPkt*)pkt; if (packet->toAddr == TOS_LOCAL_ADDRESS) { if (state == WAIT_CTS && packet->fromAddr == sendAddr) { // cancel CTS timer geneTime = 0; // schedule sending DATA state = TX_PKT; howToSend = SEND_DATA; txDelay = SIFS; } else { handleErrPkt(); } } else { // packet destined to another node if (state == DATA_SENSE1 || state == DATA_SENSE2) { geneTime = 0; } if (state == IDLE || state == BACKOFF || state == DATA_SENSE1 || state == DATA_SENSE2) { UPDATE_NAV(packet->duration); sleep(FORCE); // avoid overhearing other's packet if (nav == 0) nav = 1; // in case duration is 0 by mistake } } } void* handleDATA(void* pkt) { // internal handler for DATA packet void* tmp; uint8_t nodeIdx, emptyIdx, seqNo, fragNo, numTxFragNew;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -