* Author: Miklos Maroti
*/
-#include <RF212.h>
+#include <RF212DriverLayer.h>
#include <Tasklet.h>
#include <RadioAssert.h>
#include <GenericTimeSyncMessage.h>
interface RadioSend;
interface RadioReceive;
interface RadioCCA;
+ interface RadioPacket;
+
+ interface PacketField<uint8_t> as PacketTransmitPower;
+ interface PacketField<uint8_t> as PacketRSSI;
+ interface PacketField<uint8_t> as PacketTimeSyncOffset;
+ interface PacketField<uint8_t> as PacketLinkQuality;
}
uses
interface GpioCapture as IRQ;
interface BusyWait<TMicro, uint16_t>;
+ interface LocalTime<TRadio>;
- interface PacketField<uint8_t> as PacketLinkQuality;
- interface PacketField<uint8_t> as PacketTransmitPower;
- interface PacketField<uint8_t> as PacketRSSI;
- interface PacketField<uint8_t> as PacketTimeSyncOffset;
+ interface RF212DriverConfig as Config;
+
+ interface PacketFlag as TransmitPowerFlag;
+ interface PacketFlag as RSSIFlag;
+ interface PacketFlag as TimeSyncFlag;
interface PacketTimeStamp<TRadio, uint32_t>;
- interface LocalTime<TRadio>;
- interface RF212DriverConfig;
interface Tasklet;
interface RadioAlarm;
implementation
{
+ rf212_header_t* getHeader(message_t* msg)
+ {
+ return ((void*)msg) + call Config.headerLength(msg);
+ }
+
+ void* getPayload(message_t* msg)
+ {
+ return ((void*)msg) + call RadioPacket.headerLength(msg);
+ }
+
+ rf212_metadata_t* getMeta(message_t* msg)
+ {
+ return ((void*)msg) + sizeof(message_t) - call RadioPacket.metadataLength(msg);
+ }
+
/*----------------- STATE -----------------*/
tasklet_norace uint8_t state;
writeRegister(RF212_PHY_TX_PWR, txPower);
}
- if( call RF212DriverConfig.requiresRssiCca(msg)
+ if( call Config.requiresRssiCca(msg)
&& (readRegister(RF212_PHY_RSSI) & RF212_RSSI_MASK) > ((rssiClear + rssiBusy) >> 3) )
return EBUSY;
// do something useful, just to wait a little
time32 = call LocalTime.get();
- timesync = call PacketTimeSyncOffset.isSet(msg) ? msg->data + call PacketTimeSyncOffset.get(msg) : 0;
+ timesync = call PacketTimeSyncOffset.isSet(msg) ? ((void*)msg) + call PacketTimeSyncOffset.get(msg) : 0;
// we have missed an incoming message in this short amount of time
if( (readRegister(RF212_TRX_STATUS) & RF212_TRX_STATUS_MASK) != RF212_PLL_ON )
call SELN.clr();
call FastSpiByte.splitWrite(RF212_CMD_FRAME_WRITE);
- length = call RF212DriverConfig.getLength(msg);
- data = call RF212DriverConfig.getPayload(msg);
+ data = getPayload(msg);
+ length = getHeader(msg)->length;
// length | data[0] ... data[length-3] | automatically generated FCS
call FastSpiByte.splitReadWrite(length);
// the FCS is atomatically generated (2 bytes)
length -= 2;
- header = call RF212DriverConfig.getHeaderLength();
+ header = call Config.headerPreloadLength();
if( header > length )
header = length;
#ifdef RADIO_DEBUG_MESSAGES
if( call DiagMsg.record() )
{
- length = call RF212DriverConfig.getLength(msg);
+ length = getHeader(msg)->length;
call DiagMsg.str("tx");
call DiagMsg.uint16(time);
call DiagMsg.uint8(length);
- call DiagMsg.hex8s(data, length - 2);
+ call DiagMsg.hex8s(getPayload(msg), length - 2);
call DiagMsg.send();
}
#endif
inline void downloadMessage()
{
uint8_t length;
- uint8_t crc;
+ uint8_t crc = 0;
call SELN.clr();
call FastSpiByte.write(RF212_CMD_FRAME_READ);
length = call FastSpiByte.write(0);
// if correct length
- if( length >= 3 && length <= call RF212DriverConfig.getMaxLength() )
+ if( length >= 3 && length <= call RadioPacket.maxPayloadLength() + 2 )
{
uint8_t read;
uint8_t* data;
// initiate the reading
call FastSpiByte.splitWrite(0);
- call RF212DriverConfig.setLength(rxMsg, length);
- data = call RF212DriverConfig.getPayload(rxMsg);
+ data = getPayload(rxMsg);
+ getHeader(rxMsg)->length = length;
crc = 0;
// we do not store the CRC field
length -= 2;
- read = call RF212DriverConfig.getHeaderLength();
+ read = call Config.headerPreloadLength();
if( length < read )
read = length;
#ifdef RADIO_DEBUG_MESSAGES
if( call DiagMsg.record() )
{
- length = call RF212DriverConfig.getLength(rxMsg);
+ length = getHeader(rxMsg)->length;
call DiagMsg.str("rx");
call DiagMsg.uint32(call PacketTimeStamp.isValid(rxMsg) ? call PacketTimeStamp.timestamp(rxMsg) : 0);
call DiagMsg.uint16(call RadioAlarm.getNow());
call DiagMsg.uint8(crc != 0);
call DiagMsg.uint8(length);
- call DiagMsg.hex8s(call RF212DriverConfig.getPayload(rxMsg), length - 2);
+ call DiagMsg.hex8s(getPayload(rxMsg), length - 2);
call DiagMsg.send();
}
#endif
if( cmd == CMD_NONE )
call SpiResource.release();
}
+
+/*----------------- RadioPacket -----------------*/
+
+ async command uint8_t RadioPacket.headerLength(message_t* msg)
+ {
+ return call Config.headerLength(msg) + sizeof(rf212_header_t);
+ }
+
+ async command uint8_t RadioPacket.payloadLength(message_t* msg)
+ {
+ return getHeader(msg)->length - 2;
+ }
+
+ async command void RadioPacket.setPayloadLength(message_t* msg, uint8_t length)
+ {
+ ASSERT( 1 <= length && length <= 125 );
+ ASSERT( call RadioPacket.headerLength(msg) + length + call RadioPacket.metadataLength(msg) <= sizeof(message_t) );
+
+ // we add the length of the CRC, which is automatically generated
+ getHeader(msg)->length = length + 2;
+ }
+
+ async command uint8_t RadioPacket.maxPayloadLength()
+ {
+ ASSERT( call Config.maxPayloadLength() <= 125 );
+
+ return call Config.maxPayloadLength() - sizeof(rf212_header_t);
+ }
+
+ async command uint8_t RadioPacket.metadataLength(message_t* msg)
+ {
+ return call Config.metadataLength(msg) + sizeof(rf212_metadata_t);
+ }
+
+ async command void RadioPacket.clear(message_t* msg)
+ {
+ // all flags are automatically cleared
+ }
+
+/*----------------- PacketTransmitPower -----------------*/
+
+ async command bool PacketTransmitPower.isSet(message_t* msg)
+ {
+ return call TransmitPowerFlag.get(msg);
+ }
+
+ async command uint8_t PacketTransmitPower.get(message_t* msg)
+ {
+ return getMeta(msg)->power;
+ }
+
+ async command void PacketTransmitPower.clear(message_t* msg)
+ {
+ call TransmitPowerFlag.clear(msg);
+ }
+
+ async command void PacketTransmitPower.set(message_t* msg, uint8_t value)
+ {
+ call TransmitPowerFlag.set(msg);
+ getMeta(msg)->power = value;
+ }
+
+/*----------------- PacketRSSI -----------------*/
+
+ async command bool PacketRSSI.isSet(message_t* msg)
+ {
+ return call RSSIFlag.get(msg);
+ }
+
+ async command uint8_t PacketRSSI.get(message_t* msg)
+ {
+ return getMeta(msg)->rssi;
+ }
+
+ async command void PacketRSSI.clear(message_t* msg)
+ {
+ call RSSIFlag.clear(msg);
+ }
+
+ async command void PacketRSSI.set(message_t* msg, uint8_t value)
+ {
+ // just to be safe if the user fails to clear the packet
+ call TransmitPowerFlag.clear(msg);
+
+ call RSSIFlag.set(msg);
+ getMeta(msg)->rssi = value;
+ }
+
+/*----------------- PacketTimeSyncOffset -----------------*/
+
+ async command bool PacketTimeSyncOffset.isSet(message_t* msg)
+ {
+ return call TimeSyncFlag.get(msg);
+ }
+
+ async command uint8_t PacketTimeSyncOffset.get(message_t* msg)
+ {
+ return call RadioPacket.headerLength(msg) + call RadioPacket.payloadLength(msg) - sizeof(timesync_absolute_t);
+ }
+
+ async command void PacketTimeSyncOffset.clear(message_t* msg)
+ {
+ call TimeSyncFlag.clear(msg);
+ }
+
+ async command void PacketTimeSyncOffset.set(message_t* msg, uint8_t value)
+ {
+ // we do not store the value, the time sync field is always the last 4 bytes
+ ASSERT( call PacketTimeSyncOffset.get(msg) == value );
+
+ call TimeSyncFlag.set(msg);
+ }
+
+/*----------------- PacketLinkQuality -----------------*/
+
+ async command bool PacketLinkQuality.isSet(message_t* msg)
+ {
+ return TRUE;
+ }
+
+ async command uint8_t PacketLinkQuality.get(message_t* msg)
+ {
+ // we have some bug in BLIP, so fix it here
+ if( getMeta(msg)->lqi > 120 )
+ return 120;
+
+ return getMeta(msg)->lqi;
+ }
+
+ async command void PacketLinkQuality.clear(message_t* msg)
+ {
+ }
+
+ async command void PacketLinkQuality.set(message_t* msg, uint8_t value)
+ {
+ getMeta(msg)->lqi = value;
+ }
}