📄 rf230layerp.nc
字号:
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 ) { ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_BUSY_RX ); state = STATE_PLL_ON_2_RX_ON; return EBUSY; } atomic { call SLP_TR.set(); time = call RadioAlarm.getNow() + TX_SFD_DELAY; } call SLP_TR.clr(); ASSERT( ! radioIrq ); call SELN.clr(); call HplRF230.spiSplitWrite(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); // 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++)); } while( --length != 0 ); // wait for the SPI transfer to finish call HplRF230.spiSplitRead(); call SELN.set(); /* * 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. 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. */ // go back to RX_ON state when finished writeRegister(RF230_TRX_STATE, RF230_RX_ON);#ifdef RF230_DEBUG_MESSAGES if( call DiagMsg.record() ) { 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 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; return SUCCESS; } default tasklet_async event void RadioSend.sendDone(error_t error) { } default tasklet_async event void RadioSend.ready() { }/*----------------- CCA -----------------*/ tasklet_async command error_t RadioCCA.request() { if( cmd != CMD_NONE || state != STATE_RX_ON || ! isSpiAcquired() || ! call RadioAlarm.isFree() ) return EBUSY; // see Errata B7 of the datasheet // writeRegister(RF230_TRX_STATE, RF230_PLL_ON); // writeRegister(RF230_TRX_STATE, RF230_RX_ON); writeRegister(RF230_PHY_CC_CCA, RF230_CCA_REQUEST | RF230_CCA_MODE_VALUE | channel); call RadioAlarm.wait(CCA_REQUEST_TIME); cmd = CMD_CCA; return SUCCESS; } default tasklet_async event void RadioCCA.done(error_t error) { }/*----------------- RECEIVE -----------------*/ inline void downloadMessage() { uint8_t length; uint16_t crc; call SELN.clr(); call HplRF230.spiWrite(RF230_CMD_FRAME_READ); // read the length byte length = call HplRF230.spiWrite(0); // if correct length if( length >= 3 && length <= call RF230Config.getMaxLength() ) { uint8_t read; uint8_t* data; // initiate the reading call HplRF230.spiSplitWrite(0); call RF230Config.setLength(rxMsg, length); data = call RF230Config.getPayload(rxMsg); crc = 0; // we do not store the CRC field length -= 2; read = call RF230Config.getHeaderLength(); if( length < read ) read = length; length -= read; do { crc = call HplRF230.crcByte(crc, *(data++) = call HplRF230.spiSplitReadWrite(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, call HplRF230.spiSplitReadWrite(0)); crc = call HplRF230.crcByte(crc, call HplRF230.spiSplitReadWrite(0)); call PacketLinkQuality.set(rxMsg, call HplRF230.spiSplitRead()); } else crc = 1; } else crc = 1; 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 if( crc == 0 ) rxMsg = signal RadioReceive.receive(rxMsg); }/*----------------- IRQ -----------------*/ async event void IRQ.captured(uint16_t time) { ASSERT( ! radioIrq ); atomic { capturedTime = time; radioIrq = TRUE; } call Tasklet.schedule(); } void serviceRadio() { if( isSpiAcquired() ) { uint16_t time; uint32_t time32; uint8_t irq; uint8_t temp; atomic time = capturedTime; radioIrq = FALSE; irq = readRegister(RF230_IRQ_STATUS);#ifdef RF230_DEBUG // TODO: handle this interrupt if( irq & RF230_IRQ_TRX_UR ) { if( call DiagMsg.record() ) { call DiagMsg.str("assert ur"); 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 if( irq & RF230_IRQ_PLL_LOCK ) { if( cmd == CMD_TURNON || cmd == CMD_CHANNEL ) { ASSERT( state == STATE_TRX_OFF_2_RX_ON ); state = STATE_RX_ON; cmd = CMD_SIGNAL_DONE; } else if( cmd == CMD_TRANSMIT ) { ASSERT( state == STATE_BUSY_TX_2_RX_ON ); } else ASSERT(FALSE); } if( irq & RF230_IRQ_RX_START ) { if( cmd == CMD_CCA ) { signal RadioCCA.done(FAIL); cmd = CMD_NONE; } if( cmd == CMD_NONE ) { ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON ); // 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);#ifdef RF230_RSSI_ENERGY temp = readRegister(RF230_PHY_ED_LEVEL);#endif call PacketRSSI.set(rxMsg, temp); } else call PacketRSSI.clear(rxMsg); /* * The timestamp corresponds to the first event which could not * have been a PLL_LOCK because then cmd != CMD_NONE, so we must * have received a message (and could also have received the * TRX_END interrupt in the mean time, but that is fine. Also, * we could not be after a transmission, because then cmd = * CMD_TRANSMIT. */ if( irq == RF230_IRQ_RX_START ) // just to be cautious { 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 ASSERT( cmd == CMD_TURNOFF ); } if( irq & RF230_IRQ_TRX_END ) { if( cmd == CMD_TRANSMIT ) { ASSERT( state == STATE_BUSY_TX_2_RX_ON ); state = STATE_RX_ON; cmd = CMD_NONE; signal RadioSend.sendDone(SUCCESS); // TODO: we could have missed a received message ASSERT( ! (irq & RF230_IRQ_RX_START) ); } else if( cmd == CMD_RECEIVE ) { ASSERT( state == STATE_RX_ON || state == STATE_PLL_ON_2_RX_ON ); if( state == STATE_PLL_ON_2_RX_ON ) { ASSERT( (readRegister(RF230_TRX_STATUS) & RF230_TRX_STATUS_MASK) == RF230_PLL_ON ); writeRegister(RF230_TRX_STATE, RF230_RX_ON); state = STATE_RX_ON; } else { // the most likely place for clear channel (hope to avoid acks) rssiClear += (readRegister(RF230_PHY_RSSI) & RF230_RSSI_MASK) - (rssiClear >> 2); } cmd = CMD_DOWNLOAD; } else ASSERT(FALSE); } } } default tasklet_async event bool RadioReceive.header(message_t* msg) { return TRUE; } default tasklet_async event message_t* RadioReceive.receive(message_t* msg) { return msg; }/*----------------- TASKLET -----------------*/ tasklet_async event void Tasklet.run() { if( radioIrq ) serviceRadio(); if( cmd != CMD_NONE ) { if( cmd == CMD_DOWNLOAD ) downloadMessage(); else if( CMD_TURNOFF <= cmd && cmd <= CMD_TURNON ) changeState(); else if( cmd == CMD_CHANNEL ) changeChannel(); if( cmd == CMD_SIGNAL_DONE ) { cmd = CMD_NONE; signal RadioState.done(); } } if( cmd == CMD_NONE && state == STATE_RX_ON && ! radioIrq ) signal RadioSend.ready(); if( cmd == CMD_NONE ) call SpiResource.release(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -