📄 smacm.nc
字号:
result_t knownNeighb; MACHeader* packet = (MACHeader*)pkt; // check if it is from a known neighbor knownNeighb = getNodeIdx(packet->fromAddr, &nodeIdx, &emptyIdx);#ifdef SMAC_NO_SLEEP_CYCLE if (!knownNeighb && emptyIdx != SMAC_MAX_NUM_NEIGHB) { // put the new node into neighbor list, if there is room nodeIdx = emptyIdx; neighbList[nodeIdx].state = 1; neighbList[nodeIdx].nodeId = packet->fromAddr; neighbList[nodeIdx].schedId = 0; neighbList[nodeIdx].active = 1; neighbList[nodeIdx].txSeqNo = 0; neighbList[nodeIdx].rxSeqNo = SMAC_MAX_UCAST_SEQ_NO; numNeighb++; // increment number of neighbors if (numNeighb == 1) { // start timer to update neighbor list dataActiveTime = DATA_ACTIVE_PERIOD; } signal LinkState.nodeJoin(packet->fromAddr); knownNeighb = TRUE; }#endif if (packet->toAddr == TOS_BCAST_ADDR) { // broadcast packet uartDebug_txByte(RX_BCAST_DONE);#ifdef SMAC_NO_SLEEP_CYCLE if (state == BACKOFF) state = IDLE; uartDebug_txByte(state); if (state == IDLE) { if (txRequest == 1) { uartDebug_txByte(SMAC_TX_REQUEST_IS_1); tryToSend(); } else { uartDebug_txByte(SMAC_TX_REQUEST_IS_0); } }#else sleep(TRY);#endif if (knownNeighb) { signal LinkState.rxBcastPkt(packet->fromAddr, packet->seqFragNo); } tmp = signal MACComm.rxMsgDone(packet); return tmp; } else if (packet->toAddr == TOS_LOCAL_ADDRESS) { // unicast packet // could receive data in idle, backoff and wait_data state uartDebug_txByte(RX_UCAST_DONE); if (state == WAIT_DATA && packet->fromAddr == recvAddr) { // Should track neighbors' NAV, in case tx extended TRACK_NAV(packet->duration); // schedule sending ACK state = TX_PKT; howToSend = SEND_ACK; txDelay = SIFS; // check neighbor list fragNo = packet->seqFragNo & 0x7; // lower 3 bits if (!knownNeighb) { // unknow neighbor // just pass data up if (lastRxFrag != fragNo) { // new fragment lastRxFrag = fragNo; tmp = signal MACComm.rxMsgDone(packet); return tmp; } } else { // a know neighbor // update link quality and check duplicate seqNo = packet->seqFragNo >> 3; // higher 5 bits numTxFragNew = (packet->type & 0xf) + 1; // reTx + original Tx if (neighbList[nodeIdx].rxSeqNo != seqNo) { // new msg neighbList[nodeIdx].rxSeqNo = seqNo; lastRxFrag = fragNo; numTxFragOld = numTxFragNew; numTx1Msg = numTxFragNew; numRx1Msg = 1; // first fragment received if (lastRxFrag == rxFragAll - 1) { // only 1 frag in this msg signal LinkState.rxUcastPkt(recvAddr, seqNo, numTx1Msg, numRx1Msg); } tmp = signal MACComm.rxMsgDone(packet); return tmp; } else { // the same msg numTx1Msg += numTxFragNew; numRx1Msg++; if (lastRxFrag != fragNo) { // new fragment lastRxFrag = fragNo; if (lastRxFrag == rxFragAll - 1) { // all frags received signal LinkState.rxUcastPkt(recvAddr, seqNo, numTx1Msg, numRx1Msg); } tmp = signal MACComm.rxMsgDone(packet); return tmp; } else { // duplicated fragment numTx1Msg -= numTxFragOld; if (lastRxFrag == rxFragAll - 1) { // last fragment signal LinkState.rxUcastPkt(recvAddr, seqNo, numTx1Msg, numRx1Msg); } } numTxFragOld = numTxFragNew; } } } else { handleErrPkt(); } } else { // unicast packet destined to another node if (state == IDLE || state == BACKOFF) { UPDATE_NAV(packet->duration); sleep(FORCE); // avoid overhearing other's packet if (nav == 0) nav = 1; // in case duration is 0 by mistake } } return pkt; } void handleACK(void* pkt) { // internal handler for ACK packet MACCtrlPkt* packet; packet = (MACCtrlPkt*)pkt; if (packet->toAddr == TOS_LOCAL_ADDRESS) { if (state == WAIT_ACK && packet->fromAddr == sendAddr) { // cancel ACK timer geneTime = 0; txFragCount++; // number of successfully transmitted frags if (txFragCount < txFragAll) { state = TX_NEXT_FRAG; uartDebug_txByte(state); if (signal MACComm.txFragDone(dataPkt) == FAIL) txMsgDone(); } else { // no more fragment, tx done txMsgDone(); } } else { handleErrPkt(); } } else { // packet destined to another node if (state == IDLE || state == BACKOFF) { UPDATE_NAV(packet->duration); sleep(FORCE); if (nav == 0) nav = 1; } } } void handleSYNC(void* pkt) { // internal handler for SYNC packet MACSyncPkt* packet = (MACSyncPkt*)pkt; uint8_t i, nodeId, emptyId, schedId; uint16_t refTime, rxDelay; char timeDiff; // if carrier sense failed and received a sync pkt, go back to idle if (state == BACKOFF) { state = IDLE; uartDebug_txByte(state); } // calculate Rx delay of sync packet // adjust TX_TRANSITION_TIME to make rxDelay calculated correctly rxDelay = (uint16_t)(clockTime - ((PhyPktBuf*)pkt)->info.timeCoarse) + PRE_PKT_BYTES * 8 / BANDWIDTH + TX_TRANSITION_TIME; //uartDebug_txByte1(rxDelay); // sanity check if (rxDelay < durSyncPkt - 2 || rxDelay > durSyncPkt + 10) return; refTime = packet->sleepTime - rxDelay;#ifdef SMAC_DEBUG // output syncDiff1 in every data packet syncDiff1 = schedTab[0].counter - refTime; //uartDebug_txByte1(syncDiff1);#endif if (numNeighb == 0) { // I have no neighbor now setMySched(packet, refTime); // follow this schedule signal LinkState.nodeJoin(packet->fromAddr); signal LinkState.rxSyncPkt(packet->fromAddr, packet->seqNo);#ifdef SMAC_SLAVE_SCHED timeToTxSync = 1; // will send SYNC and enter low duty cycles#endif return; } // check if sender is on my neighbor list if (getNodeIdx(packet->fromAddr, &nodeId, &emptyId)) { //a known neighbor schedId = neighbList[nodeId].schedId; if (neighbList[nodeId].state == packet->state) { // update the existing schedule schedTab[schedId].counter = refTime; //packet->sleepTime; neighbList[nodeId].active = 1; signal LinkState.rxSyncPkt(packet->fromAddr, packet->seqNo); return; } else { // the node just changed schedule if (schedTab[schedId].numNodes == 1 && txRequest == 1) // set flag to decrement numNodes after tx pkt is done schedTab[schedId].chkSched = 1; else // decrement number of nodes on old schedule schedTab[schedId].numNodes--; } } else { // a new neighbor // if neighbor list is full, drop the node if (emptyId == SMAC_MAX_NUM_NEIGHB) return; } // now it's either a new node or an old node switching to a new schedule // check if its schedule is a known one to me schedId = SMAC_MAX_NUM_SCHED; for (i = 0; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes > 0) { timeDiff = schedTab[i].counter - refTime; if (timeDiff > -GUARDTIME && timeDiff < GUARDTIME) { schedTab[i].counter = refTime; // packet->sleepTime; schedTab[i].numNodes++; // it will follow this schedule schedId = i; break;#ifdef SMAC_DEBUG } else { syncDiff2 = timeDiff; //bigger GUARDTIME only#endif } } } if (schedId == SMAC_MAX_NUM_SCHED) { // unknow schedule // add an entry to the schedule table if (numSched < SMAC_MAX_NUM_SCHED){ for (i = 0; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes == 0) { // found an empty entry schedTab[i].counter = refTime; //packet->sleepTime; schedTab[i].txSync = 1; // need send sync schedTab[i].txData = 0; schedTab[i].numNodes = 1; // 1st node following this sched schedId = i; numSched++; // increment number of schedules break; } } } } if (nodeId == SMAC_MAX_NUM_NEIGHB) { // a new node // if no room in schedule table for a new schedule, drop the new node if (schedId == SMAC_MAX_NUM_SCHED) return; // add it to my neighbor list -- we know there's still room neighbList[emptyId].state = packet->state; neighbList[emptyId].nodeId = packet->fromAddr; neighbList[emptyId].schedId = schedId; neighbList[emptyId].active = 1; neighbList[emptyId].txSeqNo = 0; neighbList[emptyId].rxSeqNo = SMAC_MAX_UCAST_SEQ_NO; numNeighb++; // increment number of neighbors signal LinkState.nodeJoin(packet->fromAddr); } else { // old node switches to a new schedule // if no room in schedule table, delete the old node if (schedId == SMAC_MAX_NUM_SCHED) { neighbList[nodeId].state = 0; numNeighb--; // decrement number of neighbors } else { neighbList[nodeId].state = packet->state; neighbList[nodeId].schedId = schedId; neighbList[nodeId].active = 1; } // maybe the old node switches from schedTab[0] // check if I am the only one on schedTab[0] now // if yes, I should follow the next available schedule if (txRequest == 0) { checkMySched(); } else { // set flag to call checkMySched() when txRequest becomes 0 schedTab[0].chkSched = 1; } } //uartDebug_txByte(numNeighb); signal LinkState.rxSyncPkt(packet->fromAddr, packet->seqNo); } void sendRTS() { // construct and send RTS packet ctrlPkt.type = (RTS_PKT << 4) + txFragAll; ctrlPkt.toAddr = sendAddr; // reserve time for CTS + all fragments + all ACKs ctrlPkt.duration = (txFragAll + 1) * durCtrlPkt + txFragAll * durDataPkt + (txFragAll + txFragAll + 1) * (PROC_DELAY + SIFS); // send RTS call PhyComm.txPkt(&ctrlPkt, sizeof(ctrlPkt)); radioState = RADIO_TX; state = TX_PKT; geneTime = TX_PKT_DONE_TIME; uartDebug_txByte(state); } void sendCTS() { // construct and send CTS // input duration is the duration field from received RTS pkt ctrlPkt.type = CTS_PKT << 4; ctrlPkt.toAddr = recvAddr; // should track neighbors' NAV as soon as RTS is received ctrlPkt.duration = neighbNav - durCtrlPkt; // send CTS call PhyComm.txPkt(&ctrlPkt, sizeof(ctrlPkt)); geneTime = TX_PKT_DONE_TIME; radioState = RADIO_TX; uartDebug_txByte(state); } void sendDATA() { // send a unicast data packet // assume all MAC header fields have been filled except the duration#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 // neighbNav tracks the time I have left for tx dataPkt->duration = neighbNav - durDataPkt; call PhyComm.txPkt(dataPkt, txPktLen); radioState = RADIO_TX; geneTime = TX_PKT_DONE_TIME; uartDebug_txByte(state); } void sendACK() { // construct and send ACK ctrlPkt.type = ACK_PKT << 4; ctrlPkt.toAddr = recvAddr; // stick to neighbNav -- should update it when rx data packet ctrlPkt.duration = neighbNav - durCtrlPkt; call PhyComm.txPkt(&ctrlPkt, sizeof(ctrlPkt)); radioState = RADIO_TX; geneTime = TX_PKT_DONE_TIME; } void sendSYNC() { // construct and send SYNC packet syncPkt.sleepTime = schedTab[0].counter; syncPkt.seqNo = syncSeqNo; call PhyComm.txPkt(&syncPkt, sizeof(syncPkt)); radioState = RADIO_TX; state = TX_PKT; geneTime = TX_PKT_DONE_TIME; uartDebug_txByte(state); } // default internal time stamp. // To use external time stamp, provide wiring at application default command void TimeStamp.getTime32(uint32_t *timePtr) { *timePtr = clockTime; } // default command to if PowerManagement is not used default async command uint8_t PowerManagement.adjustPower() { return 1; } // default do-nothing handler for LinkState interface default event void LinkState.nodeJoin(uint16_t nodeAddr) { } default event void LinkState.nodeGone(uint16_t nodeAddr) { } default event void LinkState.rxSyncPk
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -