X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=tos%2Fchips%2Frf230%2FRF230LayerP.nc;h=0099fab001562d70aa70aaaeb21a01f3377bad13;hb=813ccd9a39dd0810febb285f17bcd72ba451f536;hp=d9d06d5e0fd2de04b0bdd1280437ad8fe5a2a1db;hpb=b3b5a0c4051c2ef8e6c27ac0750f5a1742a38452;p=tinyos-2.x.git diff --git a/tos/chips/rf230/RF230LayerP.nc b/tos/chips/rf230/RF230LayerP.nc index d9d06d5e..0099fab0 100644 --- a/tos/chips/rf230/RF230LayerP.nc +++ b/tos/chips/rf230/RF230LayerP.nc @@ -25,6 +25,7 @@ #include #include #include +#include module RF230LayerP { @@ -44,7 +45,7 @@ module RF230LayerP interface GeneralIO as SELN; interface Resource as SpiResource; - interface SpiByte; + interface FastSpiByte; interface HplRF230; interface GeneralIO as SLP_TR; @@ -54,15 +55,18 @@ module RF230LayerP interface BusyWait; - interface RF230Config; interface PacketField as PacketLinkQuality; interface PacketField as PacketTransmitPower; - interface PacketTimeStamp; + interface PacketField as PacketRSSI; + interface PacketField as PacketTimeSyncOffset; + + interface PacketTimeStamp; + interface LocalTime; + + interface RF230Config; interface Tasklet; interface RadioAlarm; - async event void lastTouch(message_t* msg); - #ifdef RF230_DEBUG interface DiagMsg; #endif @@ -122,9 +126,9 @@ implementation ASSERT( reg == (reg & RF230_CMD_REGISTER_MASK) ); call SELN.clr(); - call HplRF230.spiSplitWrite(RF230_CMD_REGISTER_WRITE | reg); - call HplRF230.spiSplitReadWrite(value); - call HplRF230.spiSplitRead(); + call FastSpiByte.splitWrite(RF230_CMD_REGISTER_WRITE | reg); + call FastSpiByte.splitReadWrite(value); + call FastSpiByte.splitRead(); call SELN.set(); } @@ -134,9 +138,9 @@ implementation ASSERT( reg == (reg & RF230_CMD_REGISTER_MASK) ); call SELN.clr(); - call HplRF230.spiSplitWrite(RF230_CMD_REGISTER_READ | reg); - call HplRF230.spiSplitReadWrite(0); - reg = call HplRF230.spiSplitRead(); + call FastSpiByte.splitWrite(RF230_CMD_REGISTER_READ | reg); + call FastSpiByte.splitReadWrite(0); + reg = call FastSpiByte.splitRead(); call SELN.set(); return reg; @@ -146,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; @@ -235,7 +237,6 @@ implementation event void SpiResource.granted() { - // TODO: this should not be here, see my comment in HplRF230C.nc call SELN.makeOutput(); call SELN.set(); @@ -255,7 +256,6 @@ implementation if( call SpiResource.immediateRequest() == SUCCESS ) { - // TODO: this should not be here, see my comment in HplRF230C.nc call SELN.makeOutput(); call SELN.set(); @@ -268,6 +268,11 @@ implementation /*----------------- CHANNEL -----------------*/ + tasklet_async command uint8_t RadioState.getChannel() + { + return channel; + } + tasklet_async command error_t RadioState.setChannel(uint8_t c) { c &= RF230_CHANNEL_MASK; @@ -314,15 +319,25 @@ implementation } else if( cmd == CMD_TURNON && state == STATE_TRX_OFF && isSpiAcquired() ) { + ASSERT( ! radioIrq ); + + readRegister(RF230_IRQ_STATUS); // clear the interrupt register call IRQ.captureRisingEdge(); + + // setChannel was ignored in SLEEP because the SPI was not working, so do it here + writeRegister(RF230_PHY_CC_CCA, RF230_CCA_MODE_VALUE | channel); + 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; } @@ -385,17 +400,12 @@ implementation 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; - - writeRegister(RF230_TRX_STATE, RF230_PLL_ON); - - // do something useful, just to wait a little length = (call PacketTransmitPower.isSet(msg) ? call PacketTransmitPower.get(msg) : RF230_DEF_RFPOWER) & RF230_TX_PWR_MASK; @@ -405,6 +415,16 @@ implementation 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 ) { @@ -424,13 +444,13 @@ implementation ASSERT( ! radioIrq ); call SELN.clr(); - call HplRF230.spiSplitWrite(RF230_CMD_FRAME_WRITE); + call FastSpiByte.splitWrite(RF230_CMD_FRAME_WRITE); length = call RF230Config.getLength(msg); data = call RF230Config.getPayload(msg); // length | data[0] ... data[length-3] | automatically generated FCS - call HplRF230.spiSplitReadWrite(length); + call FastSpiByte.splitReadWrite(length); // the FCS is atomatically generated (2 bytes) length -= 2; @@ -441,29 +461,26 @@ implementation length -= header; - // first upload the header + // first upload the header to gain some time do { - call HplRF230.spiSplitReadWrite(*(data++)); + call FastSpiByte.splitReadWrite(*(data++)); } while( --header != 0 ); - call PacketTimeStamp.set(msg, time); - signal lastTouch(msg); + time32 += (int16_t)(time) - (int16_t)(time32); + + if( timesync != 0 ) + *(timesync_relative_t*)timesync = (*(timesync_absolute_t*)timesync) - time32; do { - call HplRF230.spiSplitReadWrite(*(data++)); + call FastSpiByte.splitReadWrite(*(data++)); } while( --length != 0 ); // wait for the SPI transfer to finish - call HplRF230.spiSplitRead(); + call FastSpiByte.splitRead(); 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 @@ -471,27 +488,31 @@ implementation * 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 - call PacketTimeStamp.set(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; @@ -501,6 +522,7 @@ implementation } default tasklet_async event void RadioSend.sendDone(error_t error) { } + default tasklet_async event void RadioSend.ready() { } /*----------------- CCA -----------------*/ @@ -530,10 +552,10 @@ implementation uint16_t crc; call SELN.clr(); - call HplRF230.spiWrite(RF230_CMD_FRAME_READ); + call FastSpiByte.write(RF230_CMD_FRAME_READ); // read the length byte - length = call HplRF230.spiWrite(0); + length = call FastSpiByte.write(0); // if correct length if( length >= 3 && length <= call RF230Config.getMaxLength() ) @@ -542,7 +564,7 @@ implementation uint8_t* data; // initiate the reading - call HplRF230.spiSplitWrite(0); + call FastSpiByte.splitWrite(0); call RF230Config.setLength(rxMsg, length); data = call RF230Config.getPayload(rxMsg); @@ -558,19 +580,19 @@ implementation length -= read; do { - crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0)); + crc = call HplRF230.crcByte(crc, *(data++) = call FastSpiByte.splitReadWrite(0)); } while( --read != 0 ); if( signal RadioReceive.header(rxMsg) ) { while( length-- != 0 ) - crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(0)); + crc = call HplRF230.crcByte(crc, *(data++) = call FastSpiByte.splitReadWrite(0)); - crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0)); - crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0)); + crc = call HplRF230.crcByte(crc, call FastSpiByte.splitReadWrite(0)); + crc = call HplRF230.crcByte(crc, call FastSpiByte.splitReadWrite(0)); - call PacketLinkQuality.set(rxMsg, call HplRF230.spiSplitRead()); + call PacketLinkQuality.set(rxMsg, call FastSpiByte.splitRead()); } else crc = 1; @@ -580,6 +602,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 @@ -607,7 +645,9 @@ implementation if( isSpiAcquired() ) { uint16_t time; + uint32_t time32; uint8_t irq; + uint8_t temp; atomic time = capturedTime; radioIrq = FALSE; @@ -615,7 +655,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() ) @@ -661,8 +700,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 @@ -673,28 +723,18 @@ implementation * CMD_TRANSMIT. */ if( irq == RF230_IRQ_RX_START ) // just to be cautious - call PacketTimeStamp.set(rxMsg, time - RX_SFD_DELAY); + { + time32 = call LocalTime.get(); + time32 += (int16_t)(time - RX_SFD_DELAY) - (int16_t)(time32); + call PacketTimeStamp.set(rxMsg, time32); + } else call PacketTimeStamp.clear(rxMsg); cmd = CMD_RECEIVE; } else - { -#ifdef RF230_DEBUG - if( call DiagMsg.record() ) - { - 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(); - } -#endif - } + ASSERT( cmd == CMD_TURNOFF ); } if( irq & RF230_IRQ_TRX_END ) @@ -713,7 +753,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 ); @@ -724,7 +769,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; @@ -756,7 +801,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();