]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/chips/rf230/RF230LayerP.nc
Proper MSP_BSL_FLAGS for telosa and telosb based platforms using TMI modular tos...
[tinyos-2.x.git] / tos / chips / rf230 / RF230LayerP.nc
index ef4c52f69f1b5613cfa54db6558d54360c069983..4ba79fca8bf74f60d948f3f78c71a38f29e0186e 100644 (file)
@@ -25,6 +25,7 @@
 #include <HplRF230.h>
 #include <Tasklet.h>
 #include <RadioAssert.h>
+#include <TimeSyncMessage.h>
 
 module RF230LayerP
 {
@@ -54,14 +55,21 @@ module RF230LayerP
 
                interface BusyWait<TMicro, uint16_t>;
 
+               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 PacketTimeStamp<TRF230, uint32_t>;
+               interface LocalTime<TRF230>;
+
                interface RF230Config;
                interface Tasklet;
+               interface RadioAlarm;
 
 #ifdef RF230_DEBUG
                interface DiagMsg;
 #endif
-
-               interface RadioAlarm;
        }
 }
 
@@ -142,19 +150,17 @@ implementation
 
        enum
        {
-               SLEEP_WAKEUP_TIME = (uint16_t)(880 * RF230_ALARM_MICROSEC),
-               CCA_REQUEST_TIME = (uint16_t)(140 * RF230_ALARM_MICROSEC),
+               SLEEP_WAKEUP_TIME = (uint16_t)(880 * RF230_ALARM_SEC / 1000000UL),
+               CCA_REQUEST_TIME = (uint16_t)(140 * RF230_ALARM_SEC / 1000000UL),
 
-               TX_SFD_DELAY = (uint16_t)(176 * RF230_ALARM_MICROSEC),
-               RX_SFD_DELAY = (uint16_t)(8 * RF230_ALARM_MICROSEC),
+               TX_SFD_DELAY = (uint16_t)(176 * RF230_ALARM_SEC / 1000000UL),
+               RX_SFD_DELAY = (uint16_t)(8 * RF230_ALARM_SEC / 1000000UL),
        };
 
        tasklet_async event void RadioAlarm.fired()
        {
                if( state == STATE_SLEEP_2_TRX_OFF )
-               {
                        state = STATE_TRX_OFF;
-               }
                else if( cmd == CMD_CCA )
                {
                        uint8_t cca;
@@ -215,7 +221,7 @@ implementation
 
                call BusyWait.wait(510);
 
-               writeRegister(RF230_IRQ_MASK, RF230_IRQ_TRX_UR | RF230_IRQ_PLL_UNLOCK | RF230_IRQ_PLL_LOCK | RF230_IRQ_TRX_END | RF230_IRQ_RX_START);
+               writeRegister(RF230_IRQ_MASK, RF230_IRQ_TRX_UR | RF230_IRQ_PLL_LOCK | RF230_IRQ_TRX_END | RF230_IRQ_RX_START);
                writeRegister(RF230_CCA_THRES, RF230_CCA_THRES_VALUE);
                writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | RF230_TX_PWR_DEFAULT);
 
@@ -231,7 +237,7 @@ implementation
 
        event void SpiResource.granted()
        {
-               // TODO: this should not be here, see my comment in HplRF230C.nc
+               call SELN.makeOutput();
                call SELN.set();
 
                if( state == STATE_P_ON )
@@ -250,7 +256,7 @@ implementation
 
                if( call SpiResource.immediateRequest() == SUCCESS )
                {
-                       // TODO: this should not be here, see my comment in HplRF230C.nc
+                       call SELN.makeOutput();
                        call SELN.set();
 
                        return TRUE;
@@ -308,15 +314,22 @@ implementation
                }
                else if( cmd == CMD_TURNON && state == STATE_TRX_OFF && isSpiAcquired() )
                {
+                       ASSERT( ! radioIrq );
+
+                       readRegister(RF230_IRQ_STATUS); // clear the interrupt register
                        call IRQ.captureRisingEdge();
+
                        writeRegister(RF230_TRX_STATE, RF230_RX_ON);
                        state = STATE_TRX_OFF_2_RX_ON;
                }
                else if( (cmd == CMD_TURNOFF || cmd == CMD_STANDBY) 
                        && state == STATE_RX_ON && isSpiAcquired() )
                {
-                       call IRQ.disable();
                        writeRegister(RF230_TRX_STATE, RF230_FORCE_TRX_OFF);
+
+                       call IRQ.disable();
+                       radioIrq = FALSE;
+
                        state = STATE_TRX_OFF;
                }
 
@@ -378,24 +391,32 @@ implementation
                uint16_t time;
                uint8_t length;
                uint8_t* data;
+               uint8_t header;
+               uint32_t time32;
+               void* timesync;
 
                if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || radioIrq )
                        return EBUSY;
 
-               if( call RF230Config.requiresRssiCca(msg) 
-                               && readRegister(RF230_PHY_RSSI) > ((rssiClear + rssiBusy) >> 3) )
-                       return EBUSY;
+               length = (call PacketTransmitPower.isSet(msg) ?
+                       call PacketTransmitPower.get(msg) : RF230_DEF_RFPOWER) & RF230_TX_PWR_MASK;
 
-               writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
-
-               // do something useful, just to wait a little
-               length = call RF230Config.getTransmitPower(msg) & RF230_TX_PWR_MASK;
                if( length != txPower )
                {
                        txPower = length;
                        writeRegister(RF230_PHY_TX_PWR, RF230_TX_AUTO_CRC_ON | txPower);
                }
 
+               if( call RF230Config.requiresRssiCca(msg) 
+                               && (readRegister(RF230_PHY_RSSI) & RF230_RSSI_MASK) > ((rssiClear + rssiBusy) >> 3) )
+                       return EBUSY;
+
+               writeRegister(RF230_TRX_STATE, RF230_PLL_ON);
+
+               // do something useful, just to wait a little
+               time32 = call LocalTime.get();
+               timesync = call PacketTimeSyncOffset.isSet(msg) ? msg->data + 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 )
                {
@@ -408,7 +429,7 @@ implementation
                atomic
                {
                        call SLP_TR.set();
-                       time = call RadioAlarm.getNow();
+                       time = call RadioAlarm.getNow() + TX_SFD_DELAY;
                }
                call SLP_TR.clr();
 
@@ -423,9 +444,26 @@ implementation
                // length | data[0] ... data[length-3] | automatically generated FCS
                call HplRF230.spiSplitReadWrite(length);
 
-               // the FCS is atomatically generated
+               // the FCS is atomatically generated (2 bytes)
                length -= 2;
 
+               header = call RF230Config.getHeaderLength();
+               if( header > length )
+                       header = length;
+
+               length -= header;
+
+               // first upload the header to gain some time
+               do {
+                       call HplRF230.spiSplitReadWrite(*(data++));
+               }
+               while( --header != 0 );
+
+               time32 += (int16_t)(time) - (int16_t)(time32);
+
+               if( timesync != 0 )
+                       *(timesync_relative_t*)timesync = (*(timesync_absolute_t*)timesync) - time32;
+
                do {
                        call HplRF230.spiSplitReadWrite(*(data++));
                }
@@ -435,37 +473,38 @@ implementation
                call HplRF230.spiSplitRead();
                call SELN.set();
 
-               length = readRegister(RF230_TRX_STATUS); 
-
-               // go back to RX_ON state when finished
-               writeRegister(RF230_TRX_STATE, RF230_RX_ON);
-
                /*
                 * There is a very small window (~1 microsecond) when the RF230 went 
                 * into PLL_ON state but was somehow not properly initialized because 
-                * of an incoming message and could not go into BUSY_TX. 
+                * of an incoming message and could not go into BUSY_TX. I think the
+                * radio can even receive a message, and generate a TRX_UR interrupt
+                * because of concurrent access, but that message probably cannot be
+                * recovered.
+                *
+                * TODO: this needs to be verified, and make sure that the chip is 
+                * not locked up in this case.
                 */
-               if( (length & RF230_TRX_STATUS_MASK) != RF230_BUSY_TX )
+
+               // go back to RX_ON state when finished
+               writeRegister(RF230_TRX_STATE, RF230_RX_ON);
+
+#ifdef RF230_DEBUG_MESSAGES
+               if( call DiagMsg.record() )
                {
-#ifdef RF230_DEBUG
-                       if( call DiagMsg.record() )
-                       {
-                               call DiagMsg.str("assert tx");
-                               call DiagMsg.uint16(call RadioAlarm.getNow());
-                               call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
-                               call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
-                               call DiagMsg.hex8(radioIrq);
-                               call DiagMsg.uint8(state);
-                               call DiagMsg.uint8(cmd);
-                               call DiagMsg.send();
-                       }
-#endif
-                       ASSERT( (length & RF230_TRX_STATUS_MASK) == RF230_PLL_ON );
-                       return FAIL;
+                       length = call RF230Config.getLength(msg);
+
+                       call DiagMsg.str("tx");
+                       call DiagMsg.uint16(time);
+                       call DiagMsg.uint8(length);
+                       call DiagMsg.hex8s(data, length - 2);
+                       call DiagMsg.send();
                }
+#endif
 
-               time += TX_SFD_DELAY;
-               call RF230Config.setTimestamp(msg, time);
+               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;
@@ -475,6 +514,7 @@ implementation
        }
 
        default tasklet_async event void RadioSend.sendDone(error_t error) { }
+       default tasklet_async event void RadioSend.ready() { }
 
 /*----------------- CCA -----------------*/
 
@@ -531,8 +571,10 @@ implementation
 
                        length -= read;
 
-                       while( read-- != 0 )
+                       do {
                                crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0));
+                       }
+                       while( --read != 0  );
 
                        if( signal RadioReceive.header(rxMsg) )
                        {
@@ -542,7 +584,7 @@ implementation
                                crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
                                crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0));
 
-                               call RF230Config.setLinkQuality(rxMsg, call HplRF230.spiSplitRead());
+                               call PacketLinkQuality.set(rxMsg, call HplRF230.spiSplitRead());
                        }
                        else
                                crc = 1;
@@ -552,6 +594,22 @@ implementation
 
                call SELN.set();
                state = STATE_RX_ON;
+
+#ifdef RF230_DEBUG_MESSAGES
+               if( call DiagMsg.record() )
+               {
+                       length = call RF230Config.getLength(rxMsg);
+
+                       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 RF230Config.getPayload(rxMsg), length - 2);
+                       call DiagMsg.send();
+               }
+#endif
+               
                cmd = CMD_NONE;
 
                // signal only if it has passed the CRC check
@@ -579,7 +637,9 @@ implementation
                if( isSpiAcquired() )
                {
                        uint16_t time;
+                       uint32_t time32;
                        uint8_t irq;
+                       uint8_t temp;
                        
                        atomic time = capturedTime;
                        radioIrq = FALSE;
@@ -587,7 +647,6 @@ implementation
 
 #ifdef RF230_DEBUG
                        // TODO: handle this interrupt
-//                     ASSERT( ! (irq & RF230_IRQ_TRX_UR) );
                        if( irq & RF230_IRQ_TRX_UR )
                        {
                                if( call DiagMsg.record() )
@@ -604,9 +663,6 @@ implementation
                        }
 #endif
 
-                       // TODO: handle this interrupt
-                       ASSERT( ! (irq & RF230_IRQ_PLL_UNLOCK) );
-
                        if( irq & RF230_IRQ_PLL_LOCK )
                        {
                                if( cmd == CMD_TURNON || cmd == CMD_CHANNEL )
@@ -636,8 +692,19 @@ implementation
                                {
                                        ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
 
-                                       // the most likely place for busy channel
-                                       rssiBusy += readRegister(RF230_PHY_RSSI) - (rssiBusy >> 2);
+                                       // the most likely place for busy channel, with no TRX_END interrupt
+                                       if( irq == RF230_IRQ_RX_START )
+                                       {
+                                               temp = readRegister(RF230_PHY_RSSI) & RF230_RSSI_MASK;
+                                               rssiBusy += temp - (rssiBusy >> 2);
+#ifndef RF230_RSSI_ENERGY
+                                               call PacketRSSI.set(rxMsg, temp);
+                                       }
+                                       else
+                                       {
+                                               call PacketRSSI.clear(rxMsg);
+#endif
+                                       }
 
                                        /*
                                         * The timestamp corresponds to the first event which could not
@@ -647,25 +714,19 @@ implementation
                                         * we could not be after a transmission, because then cmd = 
                                         * CMD_TRANSMIT.
                                         */
-                                       call RF230Config.setTimestamp(rxMsg, time - RX_SFD_DELAY);
-                                       cmd = CMD_RECEIVE;
-                               }
-                               else
-                               {
-#ifdef RF230_DEBUG
-                                       if( call DiagMsg.record() )
+                                       if( irq == RF230_IRQ_RX_START ) // just to be cautious
                                        {
-                                               call DiagMsg.str("assert irq");
-                                               call DiagMsg.uint16(call RadioAlarm.getNow());
-                                               call DiagMsg.hex8(readRegister(RF230_TRX_STATUS));
-                                               call DiagMsg.hex8(readRegister(RF230_TRX_STATE));
-                                               call DiagMsg.hex8(irq);
-                                               call DiagMsg.uint8(state);
-                                               call DiagMsg.uint8(cmd);
-                                               call DiagMsg.send();
+                                               time32 = call LocalTime.get();
+                                               time32 += (int16_t)(time - RX_SFD_DELAY) - (int16_t)(time32);
+                                               call PacketTimeStamp.set(rxMsg, time32);
                                        }
-#endif
+                                       else
+                                               call PacketTimeStamp.clear(rxMsg);
+
+                                       cmd = CMD_RECEIVE;
                                }
+                               else
+                                       ASSERT( cmd == CMD_TURNOFF );
                        }
 
                        if( irq & RF230_IRQ_TRX_END )
@@ -684,7 +745,12 @@ implementation
                                else if( cmd == CMD_RECEIVE )
                                {
                                        ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON );
-
+#ifdef RF230_RSSI_ENERGY
+                                       if( irq == RF230_IRQ_TRX_END )
+                                               call PacketRSSI.set(rxMsg, readRegister(RF230_PHY_ED_LEVEL));
+                                       else
+                                               call PacketRSSI.clear(rxMsg);
+#endif
                                        if( state == STATE_PLL_ON_2_RX_ON )
                                        {
                                                ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_PLL_ON );
@@ -695,7 +761,7 @@ implementation
                                        else
                                        {
                                                // the most likely place for clear channel (hope to avoid acks)
-                                               rssiClear += readRegister(RF230_PHY_RSSI) - (rssiClear >> 2);
+                                               rssiClear += (readRegister(RF230_PHY_RSSI) & RF230_RSSI_MASK) - (rssiClear >> 2);
                                        }
 
                                        cmd = CMD_DOWNLOAD;
@@ -727,7 +793,7 @@ implementation
                {
                        if( cmd == CMD_DOWNLOAD )
                                downloadMessage();
-                       else if( cmd <= CMD_TURNON && CMD_TURNOFF <= cmd )
+                       else if( CMD_TURNOFF <= cmd && cmd <= CMD_TURNON )
                                changeState();
                        else if( cmd == CMD_CHANNEL )
                                changeChannel();