Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: LoRaWAN-SanJose_Bootcamp LoRaWAN-grove-cayenne LoRaWAN-classC-demo LoRaWAN-grove-cayenne ... more
Diff: radio/radio.cpp
- Revision:
- 0:6b3ac9c5a042
- Child:
- 4:e4bfe9183f94
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/radio/radio.cpp Wed Feb 28 10:48:11 2018 -0800 @@ -0,0 +1,384 @@ +#include "board.h" +#include "radio.h" + +LowPowerTimer Radio::lpt; + +void Radio::Sleep() +{ + radio.set_opmode(RF_OPMODE_SLEEP); +} + +void Radio::Standby() +{ + radio.set_opmode(RF_OPMODE_STANDBY); +} + +bool Radio::CheckRfFrequency(unsigned hz) +{ + return true; +} + +void Radio::SetChannel(unsigned hz) +{ + radio.set_frf_MHz(hz / 1000000.0); + MAC_PRINTF(" %uhz ", hz); +} + +LowPowerTimeout TxTimeoutEvent; + +void SX1272OnTimeoutIrq( void ) +{ + Radio::radio.set_opmode(RF_OPMODE_STANDBY); +} + +void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us) +{ + Radio::SetChannel(hz); + /* TODO: fsk enable, set regPacketConfig2.datamode */ + set_tx_dbm(dbm); + TxTimeoutEvent.attach_us(SX1272OnTimeoutIrq, timeout_us); + radio.set_opmode(RF_OPMODE_TRANSMITTER); +} + +#define LORA_MAC_PRIVATE_SYNCWORD 0x12 +#define LORA_MAC_PUBLIC_SYNCWORD 0x34 +void Radio::SetPublicNetwork(bool en) +{ + radio.write_reg(REG_LR_SYNC_BYTE, en ? LORA_MAC_PUBLIC_SYNCWORD : LORA_MAC_PRIVATE_SYNCWORD); +} + +uint32_t Radio::Random(void) +{ + uint32_t ret = 0; + unsigned i; + + radio.set_opmode(RF_OPMODE_RECEIVER); + for (i = 0; i < 32; i++) { + uint32_t r; + wait_us(3000); + r = radio.read_reg(REG_LR_WIDEBAND_RSSI); + r <<= ((i & 7) << 2); + ret ^= r; + } + + return ret; +} + +void Radio::LoRaConfig(uint32_t bandwidth, uint8_t datarate, uint8_t coderate, uint16_t preambleLen, bool fixLen, bool crcOn) +{ + float sp; + + if (!radio.RegOpMode.bits.LongRangeMode) { + lora.enable(); + } + radio.write_reg(REG_LR_IRQFLAGSMASK, 0); + + MAC_PRINTF("sf%u bw%u ", datarate, bandwidth); + lora.RegModemConfig2.sx1276bits.SpreadingFactor = datarate; + if (radio.type == SX1276) { + MAC_PRINTF("sx1276 "); + lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn = crcOn; + lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn = fixLen; + lora.RegModemConfig.sx1276bits.CodingRate = coderate; + lora.RegModemConfig.sx1276bits.Bw = bandwidth + 7; + lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3); + sp = lora.get_symbol_period(); + if (sp > 16) + lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; + else + lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; + radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet); + } else if (radio.type == SX1272) { + lora.RegModemConfig.sx1272bits.RxPayloadCrcOn = crcOn; + lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn = fixLen; + lora.RegModemConfig.sx1272bits.CodingRate = coderate; + lora.RegModemConfig.sx1272bits.Bw = bandwidth; + if (lora.get_symbol_period() > 16) + lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 1; + else + lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 0; + MAC_PRINTF("sx1272 "); + } else { + MAC_PRINTF("\e[31msx127?\e[0m "); + return; + } + + //printf(" {%02x %02x} ", lora.RegModemConfig.octet, lora.RegModemConfig2.octet); + radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet); + radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); + + lora.RegPreamble = preambleLen; + radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble); +} + +void Radio::SetRxConfig( + RadioModems_t modem, + uint32_t bandwidth, + uint32_t datarate, + uint8_t coderate, + uint32_t bandwidthAfc, + uint16_t preambleLen, + uint16_t symbTimeout, + bool fixLen, + uint8_t payloadLen, + bool crcOn, + bool iqInverted) +{ + if (modem == MODEM_FSK) { + if (radio.RegOpMode.bits.LongRangeMode) + fsk.enable(false); + /* TODO */ + //uint32_t bandwidthAfc, + } else if (modem == MODEM_LORA) { + uint16_t reg_u16; + + LoRaConfig(bandwidth, datarate, coderate, preambleLen, fixLen, crcOn); + + reg_u16 = radio.read_u16(REG_LR_MODEMCONFIG2); + reg_u16 &= 0xfc00; + reg_u16 |= symbTimeout; + radio.write_u16(REG_LR_MODEMCONFIG2, reg_u16); + //MAC_PRINTF("rxconf symbt %02x %02x mask:%02x\r\n", radio.read_reg(REG_LR_MODEMCONFIG2), radio.read_reg(REG_LR_MODEMCONFIG2+1), radio.read_reg(REG_LR_IRQFLAGSMASK)); + + lora.invert_rx(iqInverted); + } +} + +void Radio::SetTxConfig( + RadioModems_t modem, + int8_t dbm, + uint32_t fdev, + uint32_t bandwidth, + uint32_t datarate, + uint8_t coderate, + uint16_t preambleLen, + bool fixLen, + bool crcOn, + bool iqInverted) +{ + set_tx_dbm(dbm); + + if (modem == MODEM_FSK) { + if (radio.RegOpMode.bits.LongRangeMode) + fsk.enable(false); + /* TODO */ + } else if (modem == MODEM_LORA) { + LoRaConfig(bandwidth, datarate, coderate, preambleLen, fixLen, crcOn); + + lora.invert_tx(iqInverted); + } +} + +void Radio::SetRxMaxPayloadLength(RadioModems_t modem, uint8_t max) +{ + /* TODO fsk */ + radio.write_reg(REG_LR_RX_MAX_PAYLOADLENGTH, max); +} + +const RadioEvents_t* RadioEvents; + + +#if 0 +void dumpregs() +{ + unsigned i; + //MAC_PRINTF("%02x) %02x\r\n", i, radio.read_reg(i)); + for (i = 0; i < 0x70; i++) { + MAC_PRINTF("%02x) %02x\r\n", i, radio.read_reg(i)); + } +} +#endif /* if 0 */ + +//volatile bool fooEnable = false; + +void Radio::dio0callback() +{ + us_timestamp_t now = lpt.read_us(); + + lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); + + if (radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER || + radio.RegOpMode.bits.Mode == RF_OPMODE_RECEIVER_SINGLE) + { + lora.service(); + if (!lora.RegIrqFlags.bits.RxDone) { + MAC_PRINTF("not-rxdone\r\n"); + } else if (RadioEvents->RxDone) { + int8_t rssi; + float snr = lora.RegPktSnrValue / 4.0; + + rssi = lora.get_pkt_rssi(); + if (snr < 0) + rssi += snr; + //MAC_PRINTF("rxdone snr:%.2f, rssi:%d\r\n", snr, rssi); + //fooEnable = true; + RadioEvents->RxDone(radio.rx_buf, lora.RegRxNbBytes, rssi, snr, now); + } + } else if (radio.RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) { + if (!lora.RegIrqFlags.bits.TxDone) { + MAC_PRINTF("not-txdone\r\n"); + } else if (RadioEvents->TxDone) + RadioEvents->TxDone(now); + lora.service(); + } +} // ..dio0callback() + +void Radio::dio1callback() +{ + lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); + + MAC_PRINTF("\e[7mdio1:%02x\e[0m\r\n", lora.RegIrqFlags.octet); + if (!lora.RegIrqFlags.bits.RxTimeout) { + MAC_PRINTF("dio1-not-rxtimeout\r\n"); + } else if (RadioEvents->RxTimeout) + RadioEvents->RxTimeout(); +} + +void Radio::Init(const RadioEvents_t* e) +{ + dio0.rise(dio0callback); + dio1.rise(dio1callback); + + radio.rf_switch = rfsw_callback; + boardInit(); + + RadioEvents = e; + lpt.start(); +} + +void Radio::Send(uint8_t size) +{ + if (radio.RegOpMode.bits.Mode == RF_OPMODE_SLEEP) { + radio.set_opmode(RF_OPMODE_STANDBY); + wait_us(1000); + } + //MAC_PRINTF("Radio::Send() dio:%u:%u opmode:%02x ", radio.dio0.read(), radio.dio1.read(), radio.read_reg(REG_OPMODE)); + lora.RegPayloadLength = size; + radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); + lora.start_tx(size); +} + +/*volatile RadioState_t state; + +RadioState_t Radio::GetStatus() +{ + return state; +}*/ + +void Radio::Rx(unsigned timeout) +{ + if (timeout == 0) + lora.start_rx(RF_OPMODE_RECEIVER); + else + lora.start_rx(RF_OPMODE_RECEIVER_SINGLE); + + MAC_PRINTF("start_rx "); +} + + +void Radio::ocp(uint8_t ma) +{ + if (ma < 130) + radio.RegOcp.bits.OcpTrim = (ma - 45) / 5; + else + radio.RegOcp.bits.OcpTrim = (ma + 30) / 10; + radio.write_reg(REG_OCP, radio.RegOcp.octet); + + radio.RegOcp.octet = radio.read_reg(REG_OCP); + if (radio.RegOcp.bits.OcpTrim < 16) + ma = 45 + (5 * radio.RegOcp.bits.OcpTrim); + else if (radio.RegOcp.bits.OcpTrim < 28) + ma = (10 * radio.RegOcp.bits.OcpTrim) - 30; + else + ma = 240; + //MAC_PRINTF("Ocp: %dmA\r\n", ma); +} + + +void Radio::PrintStatus() +{ + MAC_PRINTF("dio:%u:%u opmode:%02x ", radio.dio0.read(), radio.dio1.read(), radio.read_reg(REG_OPMODE)); + lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); + MAC_PRINTF("irqFlags:%02x\r\n", lora.RegIrqFlags.octet); +} + +#ifdef DUTY_ENABLE +us_timestamp_t +Radio::TimeOnAir(RadioModems_t m, uint8_t pktLen) +{ + uint32_t airTime = 0; + + switch (m) + { + case MODEM_FSK: + { + /* TODO + airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen + + ( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) + + ( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) + + ( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) + + pktLen + + ( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) / + SX1272.Settings.Fsk.Datarate ) * 1e3 ); + */ + } + break; + case MODEM_LORA: + { + double bw = 0.0; + uint8_t fixLen, bandwidth, LowDatarateOptimize, coderate, crcOn ; + if (radio.type == SX1276) { + coderate = lora.RegModemConfig.sx1276bits.CodingRate; + LowDatarateOptimize = lora.RegModemConfig3.sx1276bits.LowDataRateOptimize; + fixLen = lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn; + bandwidth = lora.RegModemConfig.sx1276bits.Bw - 7; + crcOn = lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn; + } else if (radio.type == SX1272) { + coderate = lora.RegModemConfig.sx1272bits.CodingRate; + LowDatarateOptimize = lora.RegModemConfig.sx1272bits.LowDataRateOptimize; + fixLen = lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn; + bandwidth = lora.RegModemConfig.sx1272bits.Bw; + crcOn = lora.RegModemConfig.sx1272bits.RxPayloadCrcOn; + } else + return 0; + + switch( bandwidth ) + { + case 0: // 125 kHz + bw = 125;//ms: 125e3; + break; + case 1: // 250 kHz + bw = 250;//ms:250e3; + break; + case 2: // 500 kHz + bw = 500;//ms:500e3; + break; + } + + // Symbol rate : time for one symbol (secs) + double rs = bw / ( 1 << lora.RegModemConfig2.sx1276bits.SpreadingFactor ); + double ts = 1 / rs; + // time of preamble + double tPreamble; + tPreamble = (lora.RegPreamble + 4.25 ) * ts; + // Symbol length of payload and time + double tmp = ceil( ( 8 * pktLen - 4 * lora.RegModemConfig2.sx1276bits.SpreadingFactor + + 28 + 16 * crcOn - + ( fixLen ? 20 : 0 ) ) / + ( double )( 4 * ( lora.RegModemConfig2.sx1276bits.SpreadingFactor - + ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * + ( coderate + 4 ); + double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); + double tPayload = nPayload * ts; + // Time on air + double tOnAir = tPreamble + tPayload; + // return ms secs + airTime = floor( tOnAir * 1e3 + 0.999 ); + } + break; + } + return airTime; + +} +#endif /* DUTY_ENABLE */ +