* Author: Miklos Maroti
*/
-#include <RF230.h>
+#include <RF230DriverLayer.h>
#include <Tasklet.h>
#include <RadioAssert.h>
-#include <GenericTimeSyncMessage.h>
+#include <TimeSyncMessageLayer.h>
#include <RadioConfig.h>
module RF230DriverLayerP
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 RF230DriverConfig as Config;
+
+ interface PacketFlag as TransmitPowerFlag;
+ interface PacketFlag as RSSIFlag;
+ interface PacketFlag as TimeSyncFlag;
interface PacketTimeStamp<TRadio, uint32_t>;
- interface LocalTime<TRadio>;
- interface RF230DriverConfig;
interface Tasklet;
interface RadioAlarm;
implementation
{
+ rf230_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);
+ }
+
+ rf230_metadata_t* getMeta(message_t* msg)
+ {
+ return ((void*)msg) + sizeof(message_t) - call RadioPacket.metadataLength(msg);
+ }
+
/*----------------- STATE -----------------*/
tasklet_norace uint8_t state;
writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | txPower);
}
- if( call RF230DriverConfig.requiresRssiCca(msg)
+ if( call Config.requiresRssiCca(msg)
&& (readRegister(RF230_PHY_RSSI) & RF230_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(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) != RF230_PLL_ON )
call SELN.clr();
call FastSpiByte.splitWrite(RF230_CMD_FRAME_WRITE);
- length = call RF230DriverConfig.getLength(msg);
- data = call RF230DriverConfig.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 RF230DriverConfig.getHeaderLength();
+ header = call Config.headerPreloadLength();
if( header > length )
header = length;
if( timesync != 0 )
*(timesync_relative_t*)timesync = (*(timesync_absolute_t*)timesync) - time32;
- do {
+ while( length-- != 0 )
call FastSpiByte.splitReadWrite(*(data++));
- }
- while( --length != 0 );
// wait for the SPI transfer to finish
call FastSpiByte.splitRead();
// go back to RX_ON state when finished
writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+ if( timesync != 0 )
+ *(timesync_absolute_t*)timesync = (*(timesync_relative_t*)timesync) + time32;
+
+ call PacketTimeStamp.set(msg, time32);
+
#ifdef RADIO_DEBUG_MESSAGES
if( call DiagMsg.record() )
{
- length = call RF230DriverConfig.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.str("t");
+ call DiagMsg.uint32(call PacketTimeStamp.isValid(rxMsg) ? call PacketTimeStamp.timestamp(rxMsg) : 0);
+ call DiagMsg.uint16(call RadioAlarm.getNow());
+ call DiagMsg.int8(length);
+ call DiagMsg.hex8s(getPayload(msg), length - 2);
call DiagMsg.send();
}
#endif
- if( timesync != 0 )
- *(timesync_absolute_t*)timesync = (*(timesync_relative_t*)timesync) + time32;
-
- call PacketTimeStamp.set(msg, time32);
-
// wait for the TRX_END interrupt
state = STATE_BUSY_TX_2_RX_ON;
cmd = CMD_TRANSMIT;
length = call FastSpiByte.write(0);
// if correct length
- if( length >= 3 && length <= call RF230DriverConfig.getMaxLength() )
+ if( length >= 3 && length <= call RadioPacket.maxPayloadLength() + 2 )
{
uint8_t read;
uint8_t* data;
// initiate the reading
call FastSpiByte.splitWrite(0);
- call RF230DriverConfig.setLength(rxMsg, length);
- data = call RF230DriverConfig.getPayload(rxMsg);
+ data = getPayload(rxMsg);
+ getHeader(rxMsg)->length = length;
crc = 0;
// we do not store the CRC field
length -= 2;
- read = call RF230DriverConfig.getHeaderLength();
+ read = call Config.headerPreloadLength();
if( length < read )
read = length;
#ifdef RADIO_DEBUG_MESSAGES
if( call DiagMsg.record() )
{
- length = call RF230DriverConfig.getLength(rxMsg);
+ length = getHeader(rxMsg)->length;
- call DiagMsg.str("rx");
+ call DiagMsg.str("r");
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 RF230DriverConfig.getPayload(rxMsg), length - 2);
+ call DiagMsg.int8(crc == 0 ? length : -length);
+ 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(rf230_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(rf230_header_t);
+ }
+
+ async command uint8_t RadioPacket.metadataLength(message_t* msg)
+ {
+ return call Config.metadataLength(msg) + sizeof(rf230_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)
+ {
+ 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;
+ }
}