📄 defaultlplp.nc
字号:
if(call SplitControlState.getState() == S_OFF) { // Everything is off right now, start SplitControl and try again return EOFF; } if(call SendState.requestState(S_LPL_SENDING) == SUCCESS) { currentSendMsg = msg; currentSendLen = len; // In case our off timer is running... call OffTimer.stop(); call SendDoneTimer.stop(); if(call RadioPowerState.getState() == S_ON) { initializeSend(); return SUCCESS; } else { post startRadio(); } return SUCCESS; } return EBUSY; } command error_t Send.cancel(message_t *msg) { if(currentSendMsg == msg) { call SendState.toIdle(); call SendDoneTimer.stop(); startOffTimer(); return call SubSend.cancel(msg); } return FAIL; } command uint8_t Send.maxPayloadLength() { return call SubSend.maxPayloadLength(); } command void *Send.getPayload(message_t* msg, uint8_t len) { return call SubSend.getPayload(msg, len); } /***************** RadioBackoff Events ****************/ async event void RadioBackoff.requestInitialBackoff(message_t *msg) { if((call CC2420PacketBody.getMetadata(msg))->rxInterval > ONE_MESSAGE) { call RadioBackoff.setInitialBackoff( call Random.rand16() % (0x4 * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF); } } async event void RadioBackoff.requestCongestionBackoff(message_t *msg) { if((call CC2420PacketBody.getMetadata(msg))->rxInterval > ONE_MESSAGE) { call RadioBackoff.setCongestionBackoff( call Random.rand16() % (0x3 * CC2420_BACKOFF_PERIOD) + CC2420_MIN_BACKOFF); } } async event void RadioBackoff.requestCca(message_t *msg) { } /***************** DutyCycle Events ***************/ /** * A transmitter was detected. You must now take action to * turn the radio off when the transaction is complete. */ event void PowerCycle.detected() { // At this point, the duty cycling has been disabled temporary // and it will be this component's job to turn the radio back off // Wait long enough to see if we actually receive a packet, which is // just a little longer in case there is more than one lpl transmitter on // the channel. startOffTimer(); } /***************** SubControl Events ***************/ event void SubControl.startDone(error_t error) { if(!error) { call RadioPowerState.forceState(S_ON); if(call SendState.getState() == S_LPL_FIRST_MESSAGE || call SendState.getState() == S_LPL_SENDING) { initializeSend(); } } } event void SubControl.stopDone(error_t error) { if(!error) { if(call SendState.getState() == S_LPL_FIRST_MESSAGE || call SendState.getState() == S_LPL_SENDING) { // We're in the middle of sending a message; start the radio back up post startRadio(); } else { call OffTimer.stop(); call SendDoneTimer.stop(); } } } /***************** SubSend Events ***************/ event void SubSend.sendDone(message_t* msg, error_t error) { switch(call SendState.getState()) { case S_LPL_SENDING: if(call SendDoneTimer.isRunning()) { if(!call PacketAcknowledgements.wasAcked(msg)) { post resend(); return; } } break; case S_LPL_CLEAN_UP: /** * We include this state so upper layers can't send a different message * before the last message gets done sending */ break; default: break; } call SendState.toIdle(); call SendDoneTimer.stop(); startOffTimer(); signal Send.sendDone(msg, error); } /***************** SubReceive Events ***************/ /** * If the received message is new, we signal the receive event and * start the off timer. If the last message we received had the same * DSN as this message, then the chances are pretty good * that this message should be ignored, especially if the destination address * as the broadcast address */ event message_t *SubReceive.receive(message_t* msg, void* payload, uint8_t len) { startOffTimer(); return signal Receive.receive(msg, payload, len); } /***************** Timer Events ****************/ event void OffTimer.fired() { /* * Only stop the radio if the radio is supposed to be off permanently * or if the duty cycle is on and our sleep interval is not 0 */ if(call SplitControlState.getState() == S_OFF || (call PowerCycle.getSleepInterval() > 0 && call SplitControlState.getState() != S_OFF && call SendState.getState() == S_LPL_NOT_SENDING)) { post stopRadio(); } } /** * When this timer is running, that means we're sending repeating messages * to a node that is receive check duty cycling. */ event void SendDoneTimer.fired() { if(call SendState.getState() == S_LPL_SENDING) { // The next time SubSend.sendDone is signaled, send is complete. call SendState.forceState(S_LPL_CLEAN_UP); } } /***************** Resend Events ****************/ /** * Signal that a message has been sent * * @param p_msg message to send. * @param error notifaction of how the operation went. */ async event void Resend.sendDone( message_t* p_msg, error_t error ) { // This is actually caught by SubSend.sendDone } /***************** Tasks ***************/ task void send() { if(call SubSend.send(currentSendMsg, currentSendLen) != SUCCESS) { post send(); } } task void resend() { if(call Resend.resend(TRUE) != SUCCESS) { post resend(); } } task void startRadio() { if(call SubControl.start() != SUCCESS) { post startRadio(); } } task void stopRadio() { if(call SendState.getState() == S_LPL_NOT_SENDING) { if(call SubControl.stop() != SUCCESS) { post stopRadio(); } } } /***************** Functions ***************/ void initializeSend() { if(call LowPowerListening.getRxSleepInterval(currentSendMsg) > ONE_MESSAGE) { if(call AMPacket.destination(currentSendMsg) == AM_BROADCAST_ADDR) { call PacketAcknowledgements.noAck(currentSendMsg); } else { // Send it repetitively within our transmit window call PacketAcknowledgements.requestAck(currentSendMsg); } call SendDoneTimer.startOneShot( call LowPowerListening.getRxSleepInterval(currentSendMsg) + 20); } post send(); } void startOffTimer() { call OffTimer.startOneShot(DELAY_AFTER_RECEIVE); } /** * Check the bounds on a given duty cycle * We're never over 100%, and we're never at 0% */ uint16_t getActualDutyCycle(uint16_t dutyCycle) { if(dutyCycle > 10000) { return 10000; } else if(dutyCycle == 0) { return 1; } return dutyCycle; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -