*/
#include <RadioAssert.h>
+#include <LowPowerListeningLayer.h>
module LowPowerListeningLayerP
{
provides
{
interface SplitControl;
- interface Send;
- interface Receive;
+ interface BareSend as Send;
+ interface BareReceive as Receive;
+ interface RadioPacket;
interface LowPowerListening;
}
uses
{
interface SplitControl as SubControl;
- interface Send as SubSend;
- interface Receive as SubReceive;
+ interface BareSend as SubSend;
+ interface BareReceive as SubReceive;
+ interface RadioPacket as SubPacket;
- interface PacketField<uint16_t> as PacketSleepInterval;
- interface IEEE154Packet;
interface PacketAcknowledgements;
+ interface LowPowerListeningConfig as Config;
interface Timer<TMilli>;
+ interface SystemLowPowerListening;
}
}
implementation
{
+#ifndef LPL_DEF_LOCAL_WAKEUP
+#define LPL_DEF_LOCAL_WAKEUP 0
+#endif
+
enum
{
// minimum wakeup time to catch a transmission in milliseconds
LISTEN_WAKEUP = 6U, // use xxxL if LISTEN_WAKEUP * 10000 > 65535
- // extra wakeup time after receiving a message in milliseconds
- AFTER_RECEIVE = 10U,
-
- // extra wakeup time after transmitting a message in milliseconds
- AFTER_TRANSMIT = 10U,
-
MIN_SLEEP = 2, // the minimum sleep interval in milliseconds
- MAX_SLEEP = 30000, // the maximum sleep interval in milliseconds
- MIN_DUTY = 2, // the minimum duty cycle
};
- uint16_t sleepInterval;
+ uint16_t sleepInterval = LPL_DEF_LOCAL_WAKEUP;
message_t* txMsg;
- uint8_t txLen;
error_t txError;
/*----------------- state machine -----------------*/
{
OFF = 0,
OFF_SUBSTOP = 1, // must have consecutive indices
- OFF_SUBSTOP_DONE = 2, // 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_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
+ LISTEN = 8, // must have consecutive indices
SLEEP_SUBSTOP = 9, // must have consecutive indices
- SLEEP_SUBSTOP_DONE = 10, // 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
+ SLEEP = 12, // must have consecutive indices
SEND_SUBSTART = 13, // must have consecutive indices
- SEND_SUBSTART_DONE = 14, // 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,
}
else if( state == SEND_TIMER )
{
- transmitInterval = call LowPowerListening.getRxSleepInterval(txMsg);
+ transmitInterval = call LowPowerListening.getRemoteWakeupInterval(txMsg);
if( transmitInterval > 0 )
call Timer.startOneShot(transmitInterval);
}
else if( state == SEND_SUBSEND)
{
- txError = call SubSend.send(txMsg, txLen);
+ txError = call SubSend.send(txMsg);
if( txError == SUCCESS )
state = SEND_SUBSEND_DONE;
{
state = LISTEN;
if( sleepInterval > 0 )
- call Timer.startOneShot(AFTER_TRANSMIT);
+ call Timer.startOneShot(call SystemLowPowerListening.getDelayAfterReceive());
signal Send.sendDone(txMsg, txError);
}
post transition();
}
- event message_t* SubReceive.receive(message_t* msg, void* payload, uint8_t len)
+ event message_t* SubReceive.receive(message_t* msg)
{
if( state == SLEEP_SUBSTOP )
state = LISTEN;
if( state == LISTEN && sleepInterval > 0 )
- call Timer.startOneShot(AFTER_RECEIVE);
+ call Timer.startOneShot(call SystemLowPowerListening.getDelayAfterReceive());
- return signal Receive.receive(msg, payload, len);
+ return signal Receive.receive(msg);
}
- command error_t Send.send(message_t* msg, uint8_t len)
+ command error_t Send.send(message_t* msg)
{
if( state == LISTEN || state == SLEEP )
{
return EBUSY;
txMsg = msg;
- txLen = len;
txError = FAIL;
return SUCCESS;
// TODO: extend the PacketAcknowledgements interface with getAckRequired
if( error != SUCCESS
- || call LowPowerListening.getRxSleepInterval(msg) == 0
+ || call LowPowerListening.getRemoteWakeupInterval(msg) == 0
|| state == SEND_SUBSEND_DONE_LAST
- || (call IEEE154Packet.getAckRequired(msg) && call PacketAcknowledgements.wasAcked(msg)) )
+ || (call Config.getAckRequired(msg) && call PacketAcknowledgements.wasAcked(msg)) )
{
call Timer.stop();
state = SEND_DONE;
post transition();
}
- 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);
- }
-
/*----------------- LowPowerListening -----------------*/
- command uint16_t LowPowerListening.dutyCycleToSleepInterval(uint16_t dutyCycle)
+ lpl_metadata_t* getMeta(message_t* msg)
{
- if( dutyCycle >= 10000 )
- return 0;
- else if( dutyCycle <= MIN_DUTY )
- return MAX_SLEEP;
-
- return ((10000U * LISTEN_WAKEUP) / dutyCycle) - LISTEN_WAKEUP;
+ return ((void*)msg) + sizeof(message_t) - call RadioPacket.metadataLength(msg);
}
- command uint16_t LowPowerListening.sleepIntervalToDutyCycle(uint16_t interval)
+ command void LowPowerListening.setLocalWakeupInterval(uint16_t interval)
{
- if( interval < MIN_SLEEP )
- return 10000;
- else if( interval >= MAX_SLEEP )
- return MIN_DUTY;
-
- return (10000U * LISTEN_WAKEUP) / (LISTEN_WAKEUP + interval);
- }
-
- command void LowPowerListening.setLocalSleepInterval(uint16_t interval)
- {
if( interval < MIN_SLEEP )
interval = 0;
- else if( interval > MAX_SLEEP )
- interval = MAX_SLEEP;
sleepInterval = interval;
}
}
- command uint16_t LowPowerListening.getLocalSleepInterval()
- {
+ command uint16_t LowPowerListening.getLocalWakeupInterval()
+ {
return sleepInterval;
}
- command void LowPowerListening.setLocalDutyCycle(uint16_t dutyCycle)
+ command void LowPowerListening.setRemoteWakeupInterval(message_t *msg, uint16_t interval)
{
- call LowPowerListening.setLocalSleepInterval(
- call LowPowerListening.dutyCycleToSleepInterval(dutyCycle));
+ if( interval < MIN_SLEEP )
+ interval = 0;
+
+ getMeta(msg)->sleepint = interval;
}
- command uint16_t LowPowerListening.getLocalDutyCycle()
+ command uint16_t LowPowerListening.getRemoteWakeupInterval(message_t *msg)
{
- return call LowPowerListening.sleepIntervalToDutyCycle(sleepInterval);
+ return getMeta(msg)->sleepint;
}
- command void LowPowerListening.setRxSleepInterval(message_t *msg, uint16_t interval)
+/*----------------- RadioPacket -----------------*/
+
+ async command uint8_t RadioPacket.headerLength(message_t* msg)
{
- if( interval < MIN_SLEEP )
- interval = 0;
- else if( interval > MAX_SLEEP )
- interval = MAX_SLEEP;
+ return call SubPacket.headerLength(msg);
+ }
- call PacketSleepInterval.set(msg, interval);
+ async command uint8_t RadioPacket.payloadLength(message_t* msg)
+ {
+ return call SubPacket.payloadLength(msg);
}
- command uint16_t LowPowerListening.getRxSleepInterval(message_t *msg)
- {
- if( ! call PacketSleepInterval.isSet(msg) )
- return sleepInterval;
+ async command void RadioPacket.setPayloadLength(message_t* msg, uint8_t length)
+ {
+ call SubPacket.setPayloadLength(msg, length);
+ }
- return call PacketSleepInterval.get(msg);
+ async command uint8_t RadioPacket.maxPayloadLength()
+ {
+ return call SubPacket.maxPayloadLength();
}
- command void LowPowerListening.setRxDutyCycle(message_t *msg, uint16_t dutyCycle)
- {
- call LowPowerListening.setRxSleepInterval(msg,
- call LowPowerListening.dutyCycleToSleepInterval(dutyCycle));
+ async command uint8_t RadioPacket.metadataLength(message_t* msg)
+ {
+ return call SubPacket.metadataLength(msg) + sizeof(lpl_metadata_t);
}
- command uint16_t LowPowerListening.getRxDutyCycle(message_t *msg)
- {
- return call LowPowerListening.sleepIntervalToDutyCycle(
- call LowPowerListening.getRxSleepInterval(msg));
+ async command void RadioPacket.clear(message_t* msg)
+ {
+ getMeta(msg)->sleepint = 0;
+ call SubPacket.clear(msg);
}
}