📄 smacm.nc
字号:
cntRadioTime = 0;#endif#ifdef SMAC_REPORT lenErr=0; crcErr=0; retx=0; ctrlPkts=0;#endif // SMAC_REPORT // initialize UART debugging uartDebug_init(); uartDebug_txByte(state); //uartDebug_txByte(durCtrlPkt); //uartDebug_txByte(timeWaitCtrl); //uartDebug_txByte(listenTime); // initialize random number generator call Random.init(); // initialize and start clock call Clock.start(); //initialize physical layer call PhyControl.init(); return SUCCESS; } result_t getNodeIdx(uint16_t nodeAddr, uint8_t* nodeIdx, uint8_t* emptyIdx) { // get the index of a node in the neighbor list // emptyIdx is the first empty entry in the neighbor list uint8_t i, foundEmpty; // return SMAC_MAX_NUM_NEIGHB if cannot find it *nodeIdx = SMAC_MAX_NUM_NEIGHB; *emptyIdx = SMAC_MAX_NUM_NEIGHB; foundEmpty = 0; for (i = 0; i < SMAC_MAX_NUM_NEIGHB; i++) { if (neighbList[i].state > 0 && neighbList[i].nodeId == nodeAddr) { // a known neighbor *nodeIdx = i; return TRUE; } else if (neighbList[i].state == 0 && foundEmpty == 0) { foundEmpty = 1; *emptyIdx = i; } } return FALSE; } command uint32_t MACPerformance.getTime() { return clockTime; } command uint16_t MACPerformance.getPeriod() {#ifdef SMAC_NO_SLEEP_CYCLE return 0;#else return period;#endif } command void* MACPerformance.countRadioTime(char start) {#ifdef SMAC_PERFORMANCE // start/stop counting time of radio in different states if (start) { radioTime.sleepTime = 0; radioTime.idleTime = 0; radioTime.rxTime = 0; radioTime.txTime = 0; cntRadioTime = 1; } else { cntRadioTime = 0; } return &radioTime;#else return 0;#endif } void setMySched(MACSyncPkt* packet, uint16_t refTime) { // switch my schedule (first entry of schedule table) // now only happens when the first neighbor is found // follow the schedule in syncPkt schedTab[0].counter = refTime; //packet->sleepTime; schedTab[0].txSync = 1; // need to broadcast my schedule schedTab[0].numNodes++; // 2 nodes on this schedule now schedState++; numSyncTx = 1; // only have one schedule to send SYNC // fill in the field in my syncPkt syncPkt.state = schedState; // add my first neighbor neighbList[0].state = packet->state; neighbList[0].nodeId = packet->fromAddr; neighbList[0].schedId = 0; neighbList[0].active = 1; neighbList[0].txSeqNo = 0; neighbList[0].rxSeqNo = SMAC_MAX_SYNC_SEQ_NO; numNeighb = 1; //start setting timer for update neighbor list neighbListTime = UPDATE_NEIGHB_PERIOD; } void checkMySched() { // check if I am the only one on schedTab[0] // if yes, should switch and follow the next available schedule // happens when an old node switches to a new schedule // and when I drop some inactive nodes from neighbor list(updating) uint8_t i, schedId; schedId = 0; if (schedTab[0].numNodes == 1 && numSched > 1 && numNeighb > 0) { for (i = 1; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes > 0) { // switch to next schedule schedTab[0].counter = schedTab[i].counter; schedTab[0].txSync = 1; schedTab[0].txData = schedTab[i].txData; schedTab[0].numNodes = schedTab[i].numNodes + 1; // delete this schedule schedTab[i].numNodes = 0; numSched--; schedId = i; break; } } if (schedId > 0){ schedState++; // fill in the field in my syncPkt syncPkt.state = schedState; // update my neighbor list which relative to this schedId for (i = 0; i < SMAC_MAX_NUM_NEIGHB; i++) { if (neighbList[i].state > 0 ) if (neighbList[i].schedId == schedId) neighbList[i].schedId = 0; } } } } task void update_myNeighbList() {#ifdef SMAC_NO_SLEEP_CYCLE // in fully active mode, directly update neighbor list uint8_t i; for (i = 0; i < SMAC_MAX_NUM_NEIGHB; i++) { if (neighbList[i].state > 0 ){ if (neighbList[i].active != 1){ // this node is not active recently neighbList[i].state = 0; numNeighb--; signal LinkState.nodeGone(neighbList[i].nodeId); } else { neighbList[i].active = 0; } } } if (numNeighb > 0) { dataActiveTime = DATA_ACTIVE_PERIOD; // reset timer }#else //we should update the schedTab[].numNodes before we call checkMySched() //to ensure the next available schedule is correct check_schedFlag(); update_neighbList(); updateNeighbList = 0; schedTab[0].chkSched = 0; // did checkMySched() in update_neighbList() txRequest = 0;#endif } void update_neighbList() { // update neighbor list, // if the node is not active (moved away or died) for a certain time, // need to drop it from neighbor list uint8_t i, schedId; for (i = 0; i < SMAC_MAX_NUM_NEIGHB; i++) { if (neighbList[i].state > 0 ){ if (neighbList[i].active != 1){ // this node is not active recently schedId = neighbList[i].schedId; schedTab[schedId].numNodes--; if (schedTab[schedId].numNodes == 0) numSched--; neighbList[i].state = 0; numNeighb--; signal LinkState.nodeGone(neighbList[i].nodeId); }else neighbList[i].active = 0; } } // maybe the inactive nodes were dropped from schedTab[0] // check if I am the only one on schedTab[0] // if yes, I should follow the next available schedule checkMySched(); if (numNeighb > 0) { neighbListTime = UPDATE_NEIGHB_PERIOD; // reset timer } } void check_schedFlag() { uint8_t i; // decrease the numNodes in the old schedule first for (i = 1; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes > 0 && schedTab[i].chkSched == 1){ schedTab[i].chkSched = 0; schedTab[i].numNodes--; if (schedTab[i].numNodes == 0) numSched--; } } } command result_t MACControl.start() { // only available in NO_SLEEP_CYCLE mode#ifdef SMAC_NO_SLEEP_CYCLE wakeup();#endif return SUCCESS; } command result_t MACControl.stop() { // only available in NO_SLEEP_CYCLE mode#ifdef SMAC_NO_SLEEP_CYCLE sleep(FORCE);#endif return SUCCESS; } void sleep(char manner) { // try or force to enter sleep mode // if manner == FORCE, turn off radio immediately // if manner == TRY, check other status. May stay in idle. if (state == SLEEP) return; if (manner == FORCE || (radioState == RADIO_IDLE && srchNeighb == 0 && schedListen == 0)) { call RadioState.sleep(); // turn off the radio radioState = RADIO_SLEEP; state = SLEEP;#ifdef SMAC_DEBUG numSleeps++;#endif signal MACTest.MACSleep(); // signal upper layer } else { state = IDLE; } uartDebug_txByte(state); } void wakeup() { // wake up from sleep, turn on radio and signal upper layer if (state != SLEEP) return; call RadioState.idle(); // turn on the radio radioState = RADIO_IDLE; state = IDLE; uartDebug_txByte(state);#ifdef SMAC_DEBUG numWakeups++;#endif signal MACTest.MACWakeup(); // signal upper layer } void tryToSend() { // try to send a buffered packet uint16_t backoffSlots, listenBits; char intEnabled; if (state == IDLE && nav == 0 && neighbNav == 0) { if (sendAddr == TOS_BCAST_ADDR) { howToSend = BCAST_DATA; } else { howToSend = SEND_RTS; } backoffSlots = call Random.rand() & (uint16_t)DATA_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 (state != IDLE) { uartDebug_txByte(TRYTOSEND_FAIL_NOT_IDLE); } if (nav != 0) { uartDebug_txByte(TRYTOSEND_FAIL_NAV); } if (neighbNav != 0) { uartDebug_txByte(TRYTOSEND_FAIL_NEIGHBNAV); } } return; } command result_t MACComm.broadcastMsg(void* data, uint8_t length) { char intEnabled;#ifndef SMAC_NO_SLEEP_CYCLE uint8_t i; if (numNeighb == 0) return FAIL;#endif // Don't accept Tx request if I have already accepted a request if (data == 0 || length == 0 || length > PHY_MAX_PKT_LEN) { if (data == 0) { uartDebug_txByte(SMAC_BCAST_REQUEST_REJECTED_DATA_IS_0); } if (length == 0 || length > PHY_MAX_PKT_LEN) { uartDebug_txByte(SMAC_BCAST_REQUEST_REJECTED_PKTLEN_ERROR); } return FAIL; } // 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_BCAST_REQUEST_REJECTED_TXREQUEST_IS_1); return FAIL; } dataPkt = (MACHeader*)data; txPktLen = length; sendAddr = TOS_BCAST_ADDR; // fill in MAC header fields dataPkt->type = DATA_PKT << 4; // higher 4 bits dataPkt->toAddr = TOS_BCAST_ADDR; dataPkt->fromAddr = TOS_LOCAL_ADDRESS; dataPkt->duration = 0; dataPkt->seqFragNo = bcastSeqNo; bcastSeqNo++;#ifdef SMAC_NO_SLEEP_CYCLE // try to send now tryToSend();#else // set flag in each schedule numBcast = numSched; for (i = 0; i < SMAC_MAX_NUM_SCHED; i++) { if (schedTab[i].numNodes > 0) { schedTab[i].txData = 1; } }#endif return SUCCESS; } command result_t MACComm.unicastMsg(void* data, uint8_t length, uint16_t toAddr, uint8_t numFrags) { uint8_t nodeIdx, emptyIdx;#ifndef SMAC_NO_SLEEP_CYCLE uint8_t schedId;#endif char intEnabled; // sanity check if (data == 0 || length == 0 || length > PHY_MAX_PKT_LEN || numFrags == 0 || numFrags > 8) { if (data == 0) { uartDebug_txByte(SMAC_UCAST_REQUEST_REJECTED_DATA_IS_0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -