]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
low power listening: better state machine
authormmaroti <mmaroti>
Tue, 22 Apr 2008 10:55:20 +0000 (10:55 +0000)
committermmaroti <mmaroti>
Tue, 22 Apr 2008 10:55:20 +0000 (10:55 +0000)
tos/chips/rf230/DefaultMacC.nc
tos/chips/rf230/DummyLayerC.nc
tos/chips/rf230/LowPowerListeningLayerC.nc
tos/chips/rf230/LowPowerListeningLayerP.nc

index 382b8b89069b636f1cb9c521251f7a30d7fa443e..cb9e3b11ad78c8ed9a6779a6efcd4aa7fe5fe20f 100644 (file)
@@ -94,6 +94,9 @@ implementation
        LowPowerListeningLayerC.SubControl -> MessageBufferLayerC;
        LowPowerListeningLayerC.SubSend -> MessageBufferLayerC;
        LowPowerListeningLayerC.SubReceive -> MessageBufferLayerC;
+       LowPowerListeningLayerC.PacketSleepInterval -> DefaultPacketC;
+       LowPowerListeningLayerC.IEEE154Packet -> IEEE154PacketC;
+       LowPowerListeningLayerC.PacketAcknowledgements -> DefaultPacketC;
 
        MessageBufferLayerC.Packet -> DefaultPacketC;
        MessageBufferLayerC.RadioSend -> TrafficMonitorLayerC;
@@ -116,8 +119,8 @@ implementation
        SoftwareAckLayerC.SubReceive -> RF230LayerC;
 
        CsmaLayerC.Config -> DefaultMacP;
-       CsmaLayerC.SubSend -> RF230LayerC;
-       CsmaLayerC.SubCCA -> RF230LayerC;
+       CsmaLayerC -> RF230LayerC.RadioSend;
+       CsmaLayerC -> RF230LayerC.RadioCCA;
 
        RF230LayerC.RF230Config -> DefaultMacP;
        RF230LayerC.PacketLinkQuality -> DefaultPacketC.PacketLinkQuality;
index 5aebc90d92f71b7aa46ddec361c58716b25eacf3..f1f6f699792f858351d7bd9e123fe616248de9dc 100644 (file)
@@ -25,30 +25,55 @@ generic configuration DummyLayerC()
 {
        provides
        {
+               interface SplitControl;
+               interface Send;
+               interface Receive;
+               interface LowPowerListening;
+
                interface RadioState;
                interface RadioSend;
                interface RadioReceive;
                interface RadioCCA;
 
                interface DummyConfig as UnconnectedConfig;
+               interface PacketField<uint16_t> as UnconnectedPacketSleepInterval;
+               interface IEEE154Packet as UnconnectedIEEE154Packet;
+               interface PacketAcknowledgements as UnconnectedPacketAcknowledgments;
        }
 
        uses 
        {
                interface RadioState as SubState;
-               interface RadioSend as SubSend;
-               interface RadioReceive as SubReceive;
-               interface RadioCCA as SubCCA;
+               interface RadioSend as SubRadioSend;
+               interface RadioReceive as SubRadioReceive;
+               interface RadioCCA as SubRadioCCA;
+               interface SplitControl as SubControl;
+               interface Send as SubSend;
+               interface Receive as SubReceive;
 
                interface DummyConfig as Config;
+               interface PacketField<uint16_t> as PacketSleepInterval;
+               interface IEEE154Packet;
+               interface PacketAcknowledgements;
+
+               interface LowPowerListening as UnconnectedLowPowerListening;
        }
 }
 
 implementation
 {
        RadioState = SubState;
-       RadioSend = SubSend;
-       RadioReceive = SubReceive;
-       RadioCCA = SubCCA;
+       RadioSend = SubRadioSend;
+       RadioReceive = SubRadioReceive;
+       RadioCCA = SubRadioCCA;
+
+       SplitControl = SubControl;
+       Send = SubSend;
+       Receive = SubReceive;
+
        Config = UnconnectedConfig;
+       PacketSleepInterval = UnconnectedPacketSleepInterval;
+       IEEE154Packet = UnconnectedIEEE154Packet;
+       PacketAcknowledgements = UnconnectedPacketAcknowledgments;
+       LowPowerListening = UnconnectedLowPowerListening;
 }
index f86055856cc49cd7381249e497505c57ca9d277c..a60ff739df61208d264dc5c2678b2fd13bd8be70 100644 (file)
@@ -38,6 +38,8 @@ configuration LowPowerListeningLayerC
                interface Receive as SubReceive;
 
                interface PacketField<uint16_t> as PacketSleepInterval;
+               interface IEEE154Packet;
+               interface PacketAcknowledgements;
        }
 }
 
@@ -45,14 +47,17 @@ implementation
 {
        components LowPowerListeningLayerP, new TimerMilliC();
 
-       LowPowerListening = LowPowerListeningLayerP;
-       PacketSleepInterval = LowPowerListeningLayerP;
        SplitControl = LowPowerListeningLayerP;
-       SubControl = LowPowerListeningLayerP;
        Send = LowPowerListeningLayerP;
-       SubSend = LowPowerListeningLayerP;
        Receive = LowPowerListeningLayerP;
+       LowPowerListening = LowPowerListeningLayerP;
+
+       SubControl = LowPowerListeningLayerP;
+       SubSend = LowPowerListeningLayerP;
        SubReceive = LowPowerListeningLayerP;
+       PacketSleepInterval = LowPowerListeningLayerP;
+       IEEE154Packet = LowPowerListeningLayerP;
+       PacketAcknowledgements = LowPowerListeningLayerP;
        
        LowPowerListeningLayerP.Timer -> TimerMilliC;
 }
index 532528437ad03121d7469aa8e76305d9ca691dc5..8b4876daf702a66d2553c9431a5d070f077fc9cd 100644 (file)
@@ -41,6 +41,8 @@ module LowPowerListeningLayerP
                interface Receive as SubReceive;
 
                interface PacketField<uint16_t> as PacketSleepInterval;
+               interface IEEE154Packet;
+               interface PacketAcknowledgements;
                interface Timer<TMilli>;
        }
 }
@@ -63,96 +65,139 @@ implementation
                MIN_DUTY = 2,           // the minimum duty cycle
        };
 
-       uint16_t rxSleepInterval;
+       uint16_t sleepInterval;
+
+       message_t* txMsg;
+       uint8_t txLen;
+       error_t txError;
 
 /*----------------- state machine -----------------*/
 
        enum
        {
-               STATE_OFF = 0,          // timer off, radio off
-               STATE_SLEEP = 1,        // timer on, radio off
-               STATE_LISTEN = 2,       // timer on/off, radio on
-               STATE_SEND = 3,         // timer on/off, radio on
-
-               STATE_OFF_TO_LISTEN = 10,
-               STATE_SLEEP_TO_LISTEN = 11,
-               STATE_SLEEP_TO_SEND = 12,
-               STATE_SLEEP_TO_OFF = 13,
-               STATE_LISTEN_TO_SLEEP_1 = 14,   // we go back to listen if a message arrives in this state
-               STATE_LISTEN_TO_SLEEP_2 = 15,
-               STATE_LISTEN_TO_OFF = 16,
-               STATE_SEND_DONE = 17,
+               OFF = 0,                                        
+               OFF_SUBSTOP = 1,                        // must have consecutive indices
+               OFF_SUBSTOP_DONE = 2,           // must have consecutive indices
+               OFF_STOP_END = 3,                       // must have consecutive indices
+               OFF_START_END = 4,
+
+               LISTEN_SUBSTART = 5,            // must have consecutive indices
+               LISTEN_SUBSTART_DONE = 6,       // must have consecutive indices
+               LISTEN_TIMER = 7,                       // must have consecutive indices
+               LISTEN = 8,                                     // must have consecutive indices
+
+               SLEEP_SUBSTOP = 9,                      // must have consecutive indices
+               SLEEP_SUBSTOP_DONE = 10,        // must have consecutive indices
+               SLEEP_TIMER = 11,                       // must have consecutive indices
+               SLEEP = 12,                                     // must have consecutive indices
+
+               SEND_SUBSTART = 13,                     // must have consecutive indices
+               SEND_SUBSTART_DONE = 14,        // must have consecutive indices
+               SEND_TIMER = 15,                        // must have consecutive indices
+               SEND_SUBSEND= 16,
+               SEND_SUBSEND_DONE = 17,
+               SEND_SUBSEND_DONE_LAST = 18,
+               SEND_DONE = 19,
        };
 
        uint8_t state;
 
-       message_t* txMsg;
-       uint8_t txLen;
-
        task void transition()
        {
                error_t error;
+               uint16_t transmitInterval;
 
-               if( state == STATE_OFF_TO_LISTEN || state == STATE_SLEEP_TO_LISTEN || state == STATE_SLEEP_TO_SEND )
+               if( state == LISTEN_SUBSTART || state == SEND_SUBSTART )
                {
                        error = call SubControl.start();
                        ASSERT( error == SUCCESS || error == EBUSY );
 
-                       if( error != SUCCESS )
+                       if( error == SUCCESS )
+                               ++state;
+                       else
                                post transition();
                }
-               else if( state == STATE_LISTEN_TO_OFF || state == STATE_LISTEN_TO_SLEEP_1 )
+               else if( state == SLEEP_SUBSTOP || state == OFF_SUBSTOP )
                {
                        error = call SubControl.stop();
                        ASSERT( error == SUCCESS || error == EBUSY );
 
-                       if( error != SUCCESS )
+                       if( error == SUCCESS )
+                               ++state;
+                       else
                                post transition();
-                       else if( state == STATE_LISTEN_TO_SLEEP_1 )
-                               state = STATE_LISTEN_TO_SLEEP_2;
                }
-               else if( state == STATE_SLEEP_TO_OFF )
+               else if( state == OFF_START_END )
+               {
+                       state = LISTEN_SUBSTART;
+                       post transition();
+
+                       signal SplitControl.startDone(SUCCESS);
+               }
+               else if( state == OFF_STOP_END )
                {
-                       state = STATE_OFF;
+                       state = OFF;
                        signal SplitControl.stopDone(SUCCESS);
                }
-               else if( state == STATE_SEND )
+               else if( state == LISTEN_TIMER )
                {
-                       error = call SubSend.send(txMsg, txLen);
-                       if( error == SUCCESS )
-                               state = STATE_SEND_DONE;
+                       state = LISTEN;
+                       if( sleepInterval > 0 )
+                               call Timer.startOneShot(LISTEN_WAKEUP);
+               }
+               else if( state == SLEEP_TIMER )
+               {
+                       if( sleepInterval > 0 )
+                       {
+                               state = SLEEP;
+                               call Timer.startOneShot(sleepInterval);
+                       }
                        else
                        {
-                               state = STATE_LISTEN;
-                               if( rxSleepInterval > 0 )
-                                       call Timer.startOneShot(AFTER_TRANSMIT);
-
-                               signal Send.sendDone(txMsg, error);
+                               state = LISTEN_SUBSTART;
+                               post transition();
                        }
                }
-               else if( state == STATE_LISTEN )
+               else if( state == SEND_TIMER )
                {
-                       if( rxSleepInterval > 0 )
-                               call Timer.startOneShot(LISTEN_WAKEUP);
+                       transmitInterval = call LowPowerListening.getRxSleepInterval(txMsg);
+
+                       if( transmitInterval > 0 )
+                               call Timer.startOneShot(transmitInterval);
+
+                       state = SEND_SUBSEND;
+                       post transition();
                }
-               else if( state == STATE_SLEEP )
+               else if( state == SEND_SUBSEND)
                {
-                       if( rxSleepInterval > 0 )
-                               call Timer.startOneShot(rxSleepInterval);
+                       txError = call SubSend.send(txMsg, txLen);
+
+                       if( txError == SUCCESS )
+                               state = SEND_SUBSEND_DONE;
                        else
                        {
-                               state = STATE_SLEEP_TO_LISTEN;
+                               state = SEND_DONE;
                                post transition();
                        }
                }
+               else if( state == SEND_DONE )
+               {
+                       state = LISTEN;
+                       if( sleepInterval > 0 )
+                               call Timer.startOneShot(AFTER_TRANSMIT);
+
+                       signal Send.sendDone(txMsg, txError);
+               }
        }
 
        command error_t SplitControl.start()
        {
-               if( state != STATE_OFF )
+               if( state == OFF_START_END )
+                       return EBUSY;
+               else if( state != OFF )
                        return EALREADY;
 
-               state = STATE_OFF_TO_LISTEN;
+               state = OFF_START_END;
                post transition();
 
                return SUCCESS;
@@ -161,35 +206,34 @@ implementation
        event void SubControl.startDone(error_t error)
        {
                ASSERT( error == SUCCESS || error == EBUSY );
-               ASSERT( state == STATE_OFF_TO_LISTEN || state == STATE_SLEEP_TO_LISTEN || state == STATE_SLEEP_TO_SEND );
+               ASSERT( state == LISTEN_SUBSTART_DONE || state == SEND_SUBSTART_DONE );
 
                if( error == SUCCESS )
-               {
-                       if( state == STATE_OFF_TO_LISTEN )
-                               signal SplitControl.startDone(SUCCESS);
-                       else if( state == STATE_SLEEP_TO_SEND )
-                               state = STATE_SEND;
-                       else
-                               state = STATE_LISTEN;
-               }
+                       ++state;
+               else
+                       --state;
 
                post transition();
        }
 
        command error_t SplitControl.stop()
        {
-               if( state == STATE_OFF )
-                       return EALREADY;
-               else if( state != STATE_LISTEN || state != STATE_SLEEP )
-                       return EBUSY;
+               if( state == SLEEP || state == LISTEN )
+               {
+                       call Timer.stop();
+                       post transition();
+               }
 
-               call Timer.stop();
-               if( state == STATE_SLEEP )
-                       state = STATE_SLEEP_TO_OFF;
+               if( state == LISTEN_TIMER || state == LISTEN || state == SLEEP_SUBSTOP )
+                       state = OFF_SUBSTOP;
+               else if( state == SLEEP_SUBSTOP_DONE )
+                       state = OFF_SUBSTOP_DONE;
+               else if( state == LISTEN_SUBSTART || state == SLEEP_TIMER || state == SLEEP )
+                       state = OFF_STOP_END;
+               else if( state == OFF )
+                       return EALREADY;
                else
-                       state = STATE_LISTEN_TO_OFF;
-
-               post transition();
+                       return EBUSY;
 
                return SUCCESS;
        }
@@ -197,49 +241,48 @@ implementation
        event void SubControl.stopDone(error_t error)
        {
                ASSERT( error == SUCCESS || error == EBUSY );
-               ASSERT( state == STATE_LISTEN_TO_SLEEP_2 || state == STATE_LISTEN_TO_OFF );
+               ASSERT( state == SLEEP_SUBSTOP_DONE || state == OFF_SUBSTOP_DONE );
 
                if( error == SUCCESS )
-               {
-                       if( state == STATE_LISTEN_TO_OFF )
-                               state = STATE_SLEEP_TO_OFF;
-                       else
-                               state = STATE_SLEEP;
-               }
+                       ++state;
+               else
+                       --state;
 
                post transition();
        }
 
        event void Timer.fired()
        {
-               ASSERT( state == STATE_LISTEN || state == STATE_SLEEP );
+               ASSERT( state == LISTEN || state == SLEEP || state == SEND_SUBSEND|| state == SEND_SUBSEND_DONE );
 
-               if( state == STATE_LISTEN )
-                       state = STATE_LISTEN_TO_SLEEP_1;
-               else
-                       state = STATE_SLEEP_TO_LISTEN;
+               if( state == LISTEN )
+                       state = SLEEP_SUBSTOP;
+               else if( state == SLEEP )
+                       state = LISTEN_SUBSTART;
+               else if( state == SEND_SUBSEND_DONE )
+                       state = SEND_SUBSEND_DONE_LAST;
+               else if( state == SEND_SUBSEND)
+                       state = SEND_DONE;
 
                post transition();
        }
 
-       void rxSleepIntervalChanged()
+       void sleepIntervalChanged()
        {
-               if( rxSleepInterval == 0 )
+               if( (state == LISTEN && sleepInterval == 0) || state == SLEEP )
                {
                        call Timer.stop();
-                       if( state == STATE_SLEEP )
-                               state = STATE_SLEEP_TO_LISTEN;
+                       --state;
+                       post transition();
                }
-
-               post transition();
        }
 
        event message_t* SubReceive.receive(message_t* msg, void* payload, uint8_t len)
        {
-               if( state == STATE_LISTEN_TO_SLEEP_1 )
-                       state = STATE_LISTEN;
+               if( state == SLEEP_SUBSTOP )
+                       state = LISTEN;
 
-               if( state == STATE_LISTEN && rxSleepInterval > 0 )
+               if( state == LISTEN && sleepInterval > 0 )
                        call Timer.startOneShot(AFTER_RECEIVE);
 
                return signal Receive.receive(msg, payload, len);
@@ -247,42 +290,61 @@ implementation
 
        command error_t Send.send(message_t* msg, uint8_t len)
        {
-               if( state == STATE_LISTEN || state == STATE_SLEEP )
-                       call Timer.stop();
-
-               if( state == STATE_LISTEN || state == STATE_LISTEN_TO_SLEEP_1 )
+               if( state == LISTEN || state == SLEEP )
                {
-                       state = STATE_SEND;
-                       post transition();
-               }
-               else if( state == STATE_SLEEP )
-               {
-                       state = STATE_SLEEP_TO_SEND;
+                       call Timer.stop();
                        post transition();
                }
-               else if( state == STATE_SLEEP_TO_LISTEN )
-                       state = STATE_SLEEP_TO_SEND;
+
+               if( state == LISTEN_SUBSTART || state == SLEEP_TIMER || state == LISTEN )
+                       state = SEND_SUBSTART;
+               else if( state == LISTEN_SUBSTART_DONE )
+                       state = SEND_SUBSTART_DONE;
+               else if( state == LISTEN_TIMER || state == SLEEP_SUBSTOP|| state == LISTEN )
+                       state = SEND_TIMER;
                else
                        return EBUSY;
 
                txMsg = msg;
                txLen = len;
+               txError = FAIL;
        }
 
        command error_t Send.cancel(message_t* msg)
        {
-               return call SubSend.cancel(msg);
+               if( state == SEND_SUBSEND )
+               {
+                       call Timer.stop();
+                       state = LISTEN_TIMER;
+                       post transition();
+
+                       // TODO: ask if sendDone should be called after a succesfull cancel
+                       return SUCCESS;
+               }
+               else
+                       return FAIL;
        }
 
        event void SubSend.sendDone(message_t* msg, error_t error)
        {
-               ASSERT( state == STATE_SEND_DONE );
+               ASSERT( state == SEND_SUBSEND_DONE || state == SEND_SUBSEND_DONE_LAST );
+               ASSERT( msg == txMsg );
 
-               state = STATE_LISTEN;
-               if( rxSleepInterval > 0 )
-                       call Timer.startOneShot(AFTER_TRANSMIT);
+               txError = error;
 
-               signal Send.sendDone(msg, error);
+               // TODO: extend the PacketAcknowledgements interface with getAckRequired
+               if( error != SUCCESS
+                       || call LowPowerListening.getRxSleepInterval(msg) == 0
+                       || state == SEND_SUBSEND_DONE_LAST
+                       || (call IEEE154Packet.getAckRequired(msg) && call PacketAcknowledgements.wasAcked(msg)) )
+               {
+                       call Timer.stop();
+                       state = SEND_DONE;
+               }
+               else
+                       state = SEND_SUBSEND;
+
+               post transition();
        }
 
        command uint8_t Send.maxPayloadLength()
@@ -307,30 +369,30 @@ implementation
                return ((10000 * LISTEN_WAKEUP) / dutyCycle) - LISTEN_WAKEUP;
        }
 
-       command uint16_t LowPowerListening.sleepIntervalToDutyCycle(uint16_t sleepInterval)
+       command uint16_t LowPowerListening.sleepIntervalToDutyCycle(uint16_t interval)
        {
-               if( sleepInterval < MIN_SLEEP )
+               if( interval < MIN_SLEEP )
                        return 10000;
-               else if( sleepInterval >= MAX_SLEEP )
+               else if( interval >= MAX_SLEEP )
                        return MIN_DUTY;
 
-               return (10000 * LISTEN_WAKEUP) / (LISTEN_WAKEUP + sleepInterval);
+               return (10000 * LISTEN_WAKEUP) / (LISTEN_WAKEUP + interval);
        }
 
-       command void LowPowerListening.setLocalSleepInterval(uint16_t sleepInterval)
+       command void LowPowerListening.setLocalSleepInterval(uint16_t interval)
     {
-               if( sleepInterval < MIN_SLEEP )
-                       sleepInterval = 0;
-               else if( sleepInterval > MAX_SLEEP )
-                       sleepInterval = MAX_SLEEP;
+               if( interval < MIN_SLEEP )
+                       interval = 0;
+               else if( interval > MAX_SLEEP )
+                       interval = MAX_SLEEP;
 
-               rxSleepInterval = sleepInterval;
-               rxSleepIntervalChanged();
+               sleepInterval = interval;
+               sleepIntervalChanged();
        }
 
        command uint16_t LowPowerListening.getLocalSleepInterval()
     {  
-               return rxSleepInterval;
+               return sleepInterval;
        }
 
        command void LowPowerListening.setLocalDutyCycle(uint16_t dutyCycle)
@@ -341,17 +403,17 @@ implementation
 
        command uint16_t LowPowerListening.getLocalDutyCycle()
        {
-               return call LowPowerListening.sleepIntervalToDutyCycle(rxSleepInterval);
+               return call LowPowerListening.sleepIntervalToDutyCycle(sleepInterval);
        }
 
-       command void LowPowerListening.setRxSleepInterval(message_t *msg, uint16_t sleepInterval)
+       command void LowPowerListening.setRxSleepInterval(message_t *msg, uint16_t interval)
        {
-               if( sleepInterval < MIN_SLEEP )
-                       sleepInterval = 0;
-               else if( sleepInterval > MAX_SLEEP )
-                       sleepInterval = MAX_SLEEP;
+               if( interval < MIN_SLEEP )
+                       interval = 0;
+               else if( interval > MAX_SLEEP )
+                       interval = MAX_SLEEP;
 
-               call PacketSleepInterval.set(msg, sleepInterval);
+               call PacketSleepInterval.set(msg, interval);
        }
 
        command uint16_t LowPowerListening.getRxSleepInterval(message_t *msg)