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
radio/radio_sx127x.cpp@8:5a5ea7cc946f, 2018-05-23 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Wed May 23 10:20:07 2018 -0700
- Revision:
- 8:5a5ea7cc946f
permit either sx127x or sx126x radio chips to be used
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wayne Roberts |
8:5a5ea7cc946f | 1 | #include "radio.h" |
Wayne Roberts |
8:5a5ea7cc946f | 2 | #ifdef SX127x_H |
Wayne Roberts |
8:5a5ea7cc946f | 3 | #include "board.h" |
Wayne Roberts |
8:5a5ea7cc946f | 4 | |
Wayne Roberts |
8:5a5ea7cc946f | 5 | LowPowerTimer Radio::lpt; |
Wayne Roberts |
8:5a5ea7cc946f | 6 | |
Wayne Roberts |
8:5a5ea7cc946f | 7 | void Radio::Sleep() |
Wayne Roberts |
8:5a5ea7cc946f | 8 | { |
Wayne Roberts |
8:5a5ea7cc946f | 9 | radio.set_opmode(RF_OPMODE_SLEEP); |
Wayne Roberts |
8:5a5ea7cc946f | 10 | } |
Wayne Roberts |
8:5a5ea7cc946f | 11 | |
Wayne Roberts |
8:5a5ea7cc946f | 12 | void Radio::Standby() |
Wayne Roberts |
8:5a5ea7cc946f | 13 | { |
Wayne Roberts |
8:5a5ea7cc946f | 14 | radio.set_opmode(RF_OPMODE_STANDBY); |
Wayne Roberts |
8:5a5ea7cc946f | 15 | } |
Wayne Roberts |
8:5a5ea7cc946f | 16 | |
Wayne Roberts |
8:5a5ea7cc946f | 17 | bool Radio::CheckRfFrequency(unsigned hz) |
Wayne Roberts |
8:5a5ea7cc946f | 18 | { |
Wayne Roberts |
8:5a5ea7cc946f | 19 | return true; |
Wayne Roberts |
8:5a5ea7cc946f | 20 | } |
Wayne Roberts |
8:5a5ea7cc946f | 21 | |
Wayne Roberts |
8:5a5ea7cc946f | 22 | void Radio::SetChannel(unsigned hz) |
Wayne Roberts |
8:5a5ea7cc946f | 23 | { |
Wayne Roberts |
8:5a5ea7cc946f | 24 | radio.set_frf_MHz(hz / 1000000.0); |
Wayne Roberts |
8:5a5ea7cc946f | 25 | MAC_PRINTF(" %uhz ", hz); |
Wayne Roberts |
8:5a5ea7cc946f | 26 | } |
Wayne Roberts |
8:5a5ea7cc946f | 27 | |
Wayne Roberts |
8:5a5ea7cc946f | 28 | LowPowerTimeout TxTimeoutEvent; |
Wayne Roberts |
8:5a5ea7cc946f | 29 | |
Wayne Roberts |
8:5a5ea7cc946f | 30 | void SX1272OnTimeoutIrq( void ) |
Wayne Roberts |
8:5a5ea7cc946f | 31 | { |
Wayne Roberts |
8:5a5ea7cc946f | 32 | Radio::radio.set_opmode(RF_OPMODE_STANDBY); |
Wayne Roberts |
8:5a5ea7cc946f | 33 | } |
Wayne Roberts |
8:5a5ea7cc946f | 34 | |
Wayne Roberts |
8:5a5ea7cc946f | 35 | void Radio::SetTxContinuousWave(unsigned hz, int8_t dbm, unsigned timeout_us) |
Wayne Roberts |
8:5a5ea7cc946f | 36 | { |
Wayne Roberts |
8:5a5ea7cc946f | 37 | Radio::SetChannel(hz); |
Wayne Roberts |
8:5a5ea7cc946f | 38 | /* TODO: fsk enable, set regPacketConfig2.datamode */ |
Wayne Roberts |
8:5a5ea7cc946f | 39 | set_tx_dbm(dbm); |
Wayne Roberts |
8:5a5ea7cc946f | 40 | TxTimeoutEvent.attach_us(SX1272OnTimeoutIrq, timeout_us); |
Wayne Roberts |
8:5a5ea7cc946f | 41 | radio.set_opmode(RF_OPMODE_TRANSMITTER); |
Wayne Roberts |
8:5a5ea7cc946f | 42 | } |
Wayne Roberts |
8:5a5ea7cc946f | 43 | |
Wayne Roberts |
8:5a5ea7cc946f | 44 | #define LORA_MAC_PRIVATE_SYNCWORD 0x12 |
Wayne Roberts |
8:5a5ea7cc946f | 45 | #define LORA_MAC_PUBLIC_SYNCWORD 0x34 |
Wayne Roberts |
8:5a5ea7cc946f | 46 | void Radio::SetPublicNetwork(bool en) |
Wayne Roberts |
8:5a5ea7cc946f | 47 | { |
Wayne Roberts |
8:5a5ea7cc946f | 48 | radio.write_reg(REG_LR_SYNC_BYTE, en ? LORA_MAC_PUBLIC_SYNCWORD : LORA_MAC_PRIVATE_SYNCWORD); |
Wayne Roberts |
8:5a5ea7cc946f | 49 | } |
Wayne Roberts |
8:5a5ea7cc946f | 50 | |
Wayne Roberts |
8:5a5ea7cc946f | 51 | uint32_t Radio::Random(void) |
Wayne Roberts |
8:5a5ea7cc946f | 52 | { |
Wayne Roberts |
8:5a5ea7cc946f | 53 | uint32_t ret = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 54 | unsigned i; |
Wayne Roberts |
8:5a5ea7cc946f | 55 | |
Wayne Roberts |
8:5a5ea7cc946f | 56 | radio.set_opmode(RF_OPMODE_RECEIVER); |
Wayne Roberts |
8:5a5ea7cc946f | 57 | for (i = 0; i < 32; i++) { |
Wayne Roberts |
8:5a5ea7cc946f | 58 | uint32_t r; |
Wayne Roberts |
8:5a5ea7cc946f | 59 | wait_us(3000); |
Wayne Roberts |
8:5a5ea7cc946f | 60 | r = radio.read_reg(REG_LR_WIDEBAND_RSSI); |
Wayne Roberts |
8:5a5ea7cc946f | 61 | r <<= ((i & 7) << 2); |
Wayne Roberts |
8:5a5ea7cc946f | 62 | ret ^= r; |
Wayne Roberts |
8:5a5ea7cc946f | 63 | } |
Wayne Roberts |
8:5a5ea7cc946f | 64 | |
Wayne Roberts |
8:5a5ea7cc946f | 65 | return ret; |
Wayne Roberts |
8:5a5ea7cc946f | 66 | } |
Wayne Roberts |
8:5a5ea7cc946f | 67 | |
Wayne Roberts |
8:5a5ea7cc946f | 68 | void Radio::LoRaConfig(uint32_t bandwidth, uint8_t datarate, uint8_t coderate, uint16_t preambleLen, bool fixLen, bool crcOn) |
Wayne Roberts |
8:5a5ea7cc946f | 69 | { |
Wayne Roberts |
8:5a5ea7cc946f | 70 | float sp; |
Wayne Roberts |
8:5a5ea7cc946f | 71 | |
Wayne Roberts |
8:5a5ea7cc946f | 72 | if (!radio.RegOpMode.bits.LongRangeMode) { |
Wayne Roberts |
8:5a5ea7cc946f | 73 | lora.enable(); |
Wayne Roberts |
8:5a5ea7cc946f | 74 | } |
Wayne Roberts |
8:5a5ea7cc946f | 75 | radio.write_reg(REG_LR_IRQFLAGSMASK, 0); |
Wayne Roberts |
8:5a5ea7cc946f | 76 | |
Wayne Roberts |
8:5a5ea7cc946f | 77 | MAC_PRINTF("sf%u bw%u ", datarate, bandwidth); |
Wayne Roberts |
8:5a5ea7cc946f | 78 | lora.RegModemConfig2.sx1276bits.SpreadingFactor = datarate; |
Wayne Roberts |
8:5a5ea7cc946f | 79 | if (radio.type == SX1276) { |
Wayne Roberts |
8:5a5ea7cc946f | 80 | MAC_PRINTF("sx1276 "); |
Wayne Roberts |
8:5a5ea7cc946f | 81 | lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn = crcOn; |
Wayne Roberts |
8:5a5ea7cc946f | 82 | lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn = fixLen; |
Wayne Roberts |
8:5a5ea7cc946f | 83 | lora.RegModemConfig.sx1276bits.CodingRate = coderate; |
Wayne Roberts |
8:5a5ea7cc946f | 84 | lora.RegModemConfig.sx1276bits.Bw = bandwidth + 7; |
Wayne Roberts |
8:5a5ea7cc946f | 85 | lora.RegModemConfig3.octet = radio.read_reg(REG_LR_MODEMCONFIG3); |
Wayne Roberts |
8:5a5ea7cc946f | 86 | sp = lora.get_symbol_period(); |
Wayne Roberts |
8:5a5ea7cc946f | 87 | if (sp > 16) |
Wayne Roberts |
8:5a5ea7cc946f | 88 | lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 1; |
Wayne Roberts |
8:5a5ea7cc946f | 89 | else |
Wayne Roberts |
8:5a5ea7cc946f | 90 | lora.RegModemConfig3.sx1276bits.LowDataRateOptimize = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 91 | radio.write_reg(REG_LR_MODEMCONFIG3, lora.RegModemConfig3.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 92 | } else if (radio.type == SX1272) { |
Wayne Roberts |
8:5a5ea7cc946f | 93 | lora.RegModemConfig.sx1272bits.RxPayloadCrcOn = crcOn; |
Wayne Roberts |
8:5a5ea7cc946f | 94 | lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn = fixLen; |
Wayne Roberts |
8:5a5ea7cc946f | 95 | lora.RegModemConfig.sx1272bits.CodingRate = coderate; |
Wayne Roberts |
8:5a5ea7cc946f | 96 | lora.RegModemConfig.sx1272bits.Bw = bandwidth; |
Wayne Roberts |
8:5a5ea7cc946f | 97 | if (lora.get_symbol_period() > 16) |
Wayne Roberts |
8:5a5ea7cc946f | 98 | lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 1; |
Wayne Roberts |
8:5a5ea7cc946f | 99 | else |
Wayne Roberts |
8:5a5ea7cc946f | 100 | lora.RegModemConfig.sx1272bits.LowDataRateOptimize = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 101 | MAC_PRINTF("sx1272 "); |
Wayne Roberts |
8:5a5ea7cc946f | 102 | } else { |
Wayne Roberts |
8:5a5ea7cc946f | 103 | MAC_PRINTF("\e[31msx127?\e[0m "); |
Wayne Roberts |
8:5a5ea7cc946f | 104 | return; |
Wayne Roberts |
8:5a5ea7cc946f | 105 | } |
Wayne Roberts |
8:5a5ea7cc946f | 106 | |
Wayne Roberts |
8:5a5ea7cc946f | 107 | //printf(" {%02x %02x} ", lora.RegModemConfig.octet, lora.RegModemConfig2.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 108 | radio.write_reg(REG_LR_MODEMCONFIG, lora.RegModemConfig.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 109 | radio.write_reg(REG_LR_MODEMCONFIG2, lora.RegModemConfig2.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 110 | |
Wayne Roberts |
8:5a5ea7cc946f | 111 | lora.RegPreamble = preambleLen; |
Wayne Roberts |
8:5a5ea7cc946f | 112 | radio.write_u16(REG_LR_PREAMBLEMSB, lora.RegPreamble); |
Wayne Roberts |
8:5a5ea7cc946f | 113 | } |
Wayne Roberts |
8:5a5ea7cc946f | 114 | |
Wayne Roberts |
8:5a5ea7cc946f | 115 | void Radio::SetRxConfig( |
Wayne Roberts |
8:5a5ea7cc946f | 116 | RadioModems_t modem, |
Wayne Roberts |
8:5a5ea7cc946f | 117 | uint32_t bandwidth, |
Wayne Roberts |
8:5a5ea7cc946f | 118 | uint32_t datarate, |
Wayne Roberts |
8:5a5ea7cc946f | 119 | uint8_t coderate, |
Wayne Roberts |
8:5a5ea7cc946f | 120 | uint32_t bandwidthAfc, |
Wayne Roberts |
8:5a5ea7cc946f | 121 | uint16_t preambleLen, |
Wayne Roberts |
8:5a5ea7cc946f | 122 | uint16_t symbTimeout, |
Wayne Roberts |
8:5a5ea7cc946f | 123 | bool fixLen, |
Wayne Roberts |
8:5a5ea7cc946f | 124 | uint8_t payloadLen, |
Wayne Roberts |
8:5a5ea7cc946f | 125 | bool crcOn, |
Wayne Roberts |
8:5a5ea7cc946f | 126 | bool iqInverted) |
Wayne Roberts |
8:5a5ea7cc946f | 127 | { |
Wayne Roberts |
8:5a5ea7cc946f | 128 | if (modem == MODEM_FSK) { |
Wayne Roberts |
8:5a5ea7cc946f | 129 | if (radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
8:5a5ea7cc946f | 130 | fsk.enable(false); |
Wayne Roberts |
8:5a5ea7cc946f | 131 | /* TODO */ |
Wayne Roberts |
8:5a5ea7cc946f | 132 | //uint32_t bandwidthAfc, |
Wayne Roberts |
8:5a5ea7cc946f | 133 | } else if (modem == MODEM_LORA) { |
Wayne Roberts |
8:5a5ea7cc946f | 134 | uint16_t reg_u16; |
Wayne Roberts |
8:5a5ea7cc946f | 135 | |
Wayne Roberts |
8:5a5ea7cc946f | 136 | LoRaConfig(bandwidth, datarate, coderate, preambleLen, fixLen, crcOn); |
Wayne Roberts |
8:5a5ea7cc946f | 137 | |
Wayne Roberts |
8:5a5ea7cc946f | 138 | reg_u16 = radio.read_u16(REG_LR_MODEMCONFIG2); |
Wayne Roberts |
8:5a5ea7cc946f | 139 | reg_u16 &= 0xfc00; |
Wayne Roberts |
8:5a5ea7cc946f | 140 | reg_u16 |= symbTimeout; |
Wayne Roberts |
8:5a5ea7cc946f | 141 | radio.write_u16(REG_LR_MODEMCONFIG2, reg_u16); |
Wayne Roberts |
8:5a5ea7cc946f | 142 | //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)); |
Wayne Roberts |
8:5a5ea7cc946f | 143 | |
Wayne Roberts |
8:5a5ea7cc946f | 144 | lora.invert_rx(iqInverted); |
Wayne Roberts |
8:5a5ea7cc946f | 145 | } |
Wayne Roberts |
8:5a5ea7cc946f | 146 | } |
Wayne Roberts |
8:5a5ea7cc946f | 147 | |
Wayne Roberts |
8:5a5ea7cc946f | 148 | void Radio::SetTxConfig( |
Wayne Roberts |
8:5a5ea7cc946f | 149 | RadioModems_t modem, |
Wayne Roberts |
8:5a5ea7cc946f | 150 | int8_t dbm, |
Wayne Roberts |
8:5a5ea7cc946f | 151 | uint32_t fdev, |
Wayne Roberts |
8:5a5ea7cc946f | 152 | uint32_t bandwidth, |
Wayne Roberts |
8:5a5ea7cc946f | 153 | uint32_t datarate, |
Wayne Roberts |
8:5a5ea7cc946f | 154 | uint8_t coderate, |
Wayne Roberts |
8:5a5ea7cc946f | 155 | uint16_t preambleLen, |
Wayne Roberts |
8:5a5ea7cc946f | 156 | bool fixLen, |
Wayne Roberts |
8:5a5ea7cc946f | 157 | bool crcOn, |
Wayne Roberts |
8:5a5ea7cc946f | 158 | bool iqInverted) |
Wayne Roberts |
8:5a5ea7cc946f | 159 | { |
Wayne Roberts |
8:5a5ea7cc946f | 160 | set_tx_dbm(dbm); |
Wayne Roberts |
8:5a5ea7cc946f | 161 | |
Wayne Roberts |
8:5a5ea7cc946f | 162 | if (modem == MODEM_FSK) { |
Wayne Roberts |
8:5a5ea7cc946f | 163 | if (radio.RegOpMode.bits.LongRangeMode) |
Wayne Roberts |
8:5a5ea7cc946f | 164 | fsk.enable(false); |
Wayne Roberts |
8:5a5ea7cc946f | 165 | /* TODO */ |
Wayne Roberts |
8:5a5ea7cc946f | 166 | } else if (modem == MODEM_LORA) { |
Wayne Roberts |
8:5a5ea7cc946f | 167 | LoRaConfig(bandwidth, datarate, coderate, preambleLen, fixLen, crcOn); |
Wayne Roberts |
8:5a5ea7cc946f | 168 | |
Wayne Roberts |
8:5a5ea7cc946f | 169 | lora.invert_tx(iqInverted); |
Wayne Roberts |
8:5a5ea7cc946f | 170 | } |
Wayne Roberts |
8:5a5ea7cc946f | 171 | } |
Wayne Roberts |
8:5a5ea7cc946f | 172 | |
Wayne Roberts |
8:5a5ea7cc946f | 173 | void Radio::SetRxMaxPayloadLength(RadioModems_t modem, uint8_t max) |
Wayne Roberts |
8:5a5ea7cc946f | 174 | { |
Wayne Roberts |
8:5a5ea7cc946f | 175 | /* TODO fsk */ |
Wayne Roberts |
8:5a5ea7cc946f | 176 | radio.write_reg(REG_LR_RX_MAX_PAYLOADLENGTH, max); |
Wayne Roberts |
8:5a5ea7cc946f | 177 | } |
Wayne Roberts |
8:5a5ea7cc946f | 178 | |
Wayne Roberts |
8:5a5ea7cc946f | 179 | const RadioEvents_t* RadioEvents; |
Wayne Roberts |
8:5a5ea7cc946f | 180 | |
Wayne Roberts |
8:5a5ea7cc946f | 181 | |
Wayne Roberts |
8:5a5ea7cc946f | 182 | #if 0 |
Wayne Roberts |
8:5a5ea7cc946f | 183 | void dumpregs() |
Wayne Roberts |
8:5a5ea7cc946f | 184 | { |
Wayne Roberts |
8:5a5ea7cc946f | 185 | unsigned i; |
Wayne Roberts |
8:5a5ea7cc946f | 186 | //MAC_PRINTF("%02x) %02x\r\n", i, radio.read_reg(i)); |
Wayne Roberts |
8:5a5ea7cc946f | 187 | for (i = 0; i < 0x70; i++) { |
Wayne Roberts |
8:5a5ea7cc946f | 188 | MAC_PRINTF("%02x) %02x\r\n", i, radio.read_reg(i)); |
Wayne Roberts |
8:5a5ea7cc946f | 189 | } |
Wayne Roberts |
8:5a5ea7cc946f | 190 | } |
Wayne Roberts |
8:5a5ea7cc946f | 191 | #endif /* if 0 */ |
Wayne Roberts |
8:5a5ea7cc946f | 192 | |
Wayne Roberts |
8:5a5ea7cc946f | 193 | volatile struct pe { |
Wayne Roberts |
8:5a5ea7cc946f | 194 | uint8_t dio0 : 1; |
Wayne Roberts |
8:5a5ea7cc946f | 195 | uint8_t dio1 : 1; |
Wayne Roberts |
8:5a5ea7cc946f | 196 | uint8_t txing : 1; |
Wayne Roberts |
8:5a5ea7cc946f | 197 | } pinEvent; |
Wayne Roberts |
8:5a5ea7cc946f | 198 | volatile us_timestamp_t dio0at; |
Wayne Roberts |
8:5a5ea7cc946f | 199 | |
Wayne Roberts |
8:5a5ea7cc946f | 200 | void |
Wayne Roberts |
8:5a5ea7cc946f | 201 | Radio::dio0UserContext() |
Wayne Roberts |
8:5a5ea7cc946f | 202 | { |
Wayne Roberts |
8:5a5ea7cc946f | 203 | if (!pinEvent.txing) { |
Wayne Roberts |
8:5a5ea7cc946f | 204 | lora.service(); |
Wayne Roberts |
8:5a5ea7cc946f | 205 | if (!lora.RegIrqFlags.bits.RxDone) { |
Wayne Roberts |
8:5a5ea7cc946f | 206 | MAC_PRINTF("not-rxdone\r\n"); |
Wayne Roberts |
8:5a5ea7cc946f | 207 | } else if (RadioEvents->RxDone) { |
Wayne Roberts |
8:5a5ea7cc946f | 208 | int8_t rssi; |
Wayne Roberts |
8:5a5ea7cc946f | 209 | float snr = lora.RegPktSnrValue / 4.0; |
Wayne Roberts |
8:5a5ea7cc946f | 210 | |
Wayne Roberts |
8:5a5ea7cc946f | 211 | rssi = lora.get_pkt_rssi(); |
Wayne Roberts |
8:5a5ea7cc946f | 212 | if (snr < 0) |
Wayne Roberts |
8:5a5ea7cc946f | 213 | rssi += snr; |
Wayne Roberts |
8:5a5ea7cc946f | 214 | //MAC_PRINTF("rxdone snr:%.2f, rssi:%d\r\n", snr, rssi); |
Wayne Roberts |
8:5a5ea7cc946f | 215 | RadioEvents->RxDone(radio.rx_buf, lora.RegRxNbBytes, rssi, snr, dio0at); |
Wayne Roberts |
8:5a5ea7cc946f | 216 | } |
Wayne Roberts |
8:5a5ea7cc946f | 217 | } |
Wayne Roberts |
8:5a5ea7cc946f | 218 | } |
Wayne Roberts |
8:5a5ea7cc946f | 219 | |
Wayne Roberts |
8:5a5ea7cc946f | 220 | void Radio::dio0isr() |
Wayne Roberts |
8:5a5ea7cc946f | 221 | { |
Wayne Roberts |
8:5a5ea7cc946f | 222 | dio0at = lpt.read_us(); |
Wayne Roberts |
8:5a5ea7cc946f | 223 | |
Wayne Roberts |
8:5a5ea7cc946f | 224 | if (pinEvent.txing) { |
Wayne Roberts |
8:5a5ea7cc946f | 225 | /* TxDone handling requires low latency */ |
Wayne Roberts |
8:5a5ea7cc946f | 226 | if (RadioEvents->TxDone) |
Wayne Roberts |
8:5a5ea7cc946f | 227 | RadioEvents->TxDone(dio0at); |
Wayne Roberts |
8:5a5ea7cc946f | 228 | |
Wayne Roberts |
8:5a5ea7cc946f | 229 | lora.service(); |
Wayne Roberts |
8:5a5ea7cc946f | 230 | pinEvent.txing = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 231 | } else |
Wayne Roberts |
8:5a5ea7cc946f | 232 | pinEvent.dio0 = 1; |
Wayne Roberts |
8:5a5ea7cc946f | 233 | } |
Wayne Roberts |
8:5a5ea7cc946f | 234 | |
Wayne Roberts |
8:5a5ea7cc946f | 235 | void Radio::dio1UserContext() |
Wayne Roberts |
8:5a5ea7cc946f | 236 | { |
Wayne Roberts |
8:5a5ea7cc946f | 237 | lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); |
Wayne Roberts |
8:5a5ea7cc946f | 238 | |
Wayne Roberts |
8:5a5ea7cc946f | 239 | MAC_PRINTF("\e[7mdio1:%02x\e[0m\r\n", lora.RegIrqFlags.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 240 | |
Wayne Roberts |
8:5a5ea7cc946f | 241 | if (RadioEvents->RxTimeout) |
Wayne Roberts |
8:5a5ea7cc946f | 242 | RadioEvents->RxTimeout(); |
Wayne Roberts |
8:5a5ea7cc946f | 243 | |
Wayne Roberts |
8:5a5ea7cc946f | 244 | radio.write_reg(REG_LR_IRQFLAGS, 0x80); // ensure RxTimeout is cleared |
Wayne Roberts |
8:5a5ea7cc946f | 245 | } |
Wayne Roberts |
8:5a5ea7cc946f | 246 | |
Wayne Roberts |
8:5a5ea7cc946f | 247 | void Radio::dio1isr() |
Wayne Roberts |
8:5a5ea7cc946f | 248 | { |
Wayne Roberts |
8:5a5ea7cc946f | 249 | pinEvent.dio1 = 1; |
Wayne Roberts |
8:5a5ea7cc946f | 250 | } |
Wayne Roberts |
8:5a5ea7cc946f | 251 | |
Wayne Roberts |
8:5a5ea7cc946f | 252 | void Radio::Init(const RadioEvents_t* e) |
Wayne Roberts |
8:5a5ea7cc946f | 253 | { |
Wayne Roberts |
8:5a5ea7cc946f | 254 | dio0.rise(dio0isr); |
Wayne Roberts |
8:5a5ea7cc946f | 255 | dio1.rise(dio1isr); |
Wayne Roberts |
8:5a5ea7cc946f | 256 | |
Wayne Roberts |
8:5a5ea7cc946f | 257 | radio.rf_switch = rfsw_callback; |
Wayne Roberts |
8:5a5ea7cc946f | 258 | boardInit(); |
Wayne Roberts |
8:5a5ea7cc946f | 259 | |
Wayne Roberts |
8:5a5ea7cc946f | 260 | RadioEvents = e; |
Wayne Roberts |
8:5a5ea7cc946f | 261 | lpt.start(); |
Wayne Roberts |
8:5a5ea7cc946f | 262 | } |
Wayne Roberts |
8:5a5ea7cc946f | 263 | |
Wayne Roberts |
8:5a5ea7cc946f | 264 | int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh) |
Wayne Roberts |
8:5a5ea7cc946f | 265 | { |
Wayne Roberts |
8:5a5ea7cc946f | 266 | if (radio.RegOpMode.bits.Mode == RF_OPMODE_SLEEP) { |
Wayne Roberts |
8:5a5ea7cc946f | 267 | radio.set_opmode(RF_OPMODE_STANDBY); |
Wayne Roberts |
8:5a5ea7cc946f | 268 | wait_us(1000); |
Wayne Roberts |
8:5a5ea7cc946f | 269 | } |
Wayne Roberts |
8:5a5ea7cc946f | 270 | radio.write_reg(REG_LR_IRQFLAGS, 0x08); // ensure TxDone is cleared |
Wayne Roberts |
8:5a5ea7cc946f | 271 | MAC_PRINTF("Radio::Send() dio:%u:%u opmode:%02x ", radio.dio0.read(), radio.dio1.read(), radio.read_reg(REG_OPMODE)); |
Wayne Roberts |
8:5a5ea7cc946f | 272 | lora.RegPayloadLength = size; |
Wayne Roberts |
8:5a5ea7cc946f | 273 | radio.write_reg(REG_LR_PAYLOADLENGTH, lora.RegPayloadLength); |
Wayne Roberts |
8:5a5ea7cc946f | 274 | |
Wayne Roberts |
8:5a5ea7cc946f | 275 | if (maxListenTime > 0) { |
Wayne Roberts |
8:5a5ea7cc946f | 276 | int rssi; |
Wayne Roberts |
8:5a5ea7cc946f | 277 | us_timestamp_t startAt, chFreeAt, now; |
Wayne Roberts |
8:5a5ea7cc946f | 278 | lora.start_rx(RF_OPMODE_RECEIVER); |
Wayne Roberts |
8:5a5ea7cc946f | 279 | startAt = lpt.read_us(); |
Wayne Roberts |
8:5a5ea7cc946f | 280 | Lstart: |
Wayne Roberts |
8:5a5ea7cc946f | 281 | do { |
Wayne Roberts |
8:5a5ea7cc946f | 282 | now = lpt.read_us(); |
Wayne Roberts |
8:5a5ea7cc946f | 283 | if ((now - startAt) > maxListenTime) { |
Wayne Roberts |
8:5a5ea7cc946f | 284 | return -1; |
Wayne Roberts |
8:5a5ea7cc946f | 285 | } |
Wayne Roberts |
8:5a5ea7cc946f | 286 | rssi = lora.get_current_rssi(); |
Wayne Roberts |
8:5a5ea7cc946f | 287 | } while (rssi > rssiThresh); |
Wayne Roberts |
8:5a5ea7cc946f | 288 | chFreeAt = lpt.read_us(); |
Wayne Roberts |
8:5a5ea7cc946f | 289 | do { |
Wayne Roberts |
8:5a5ea7cc946f | 290 | now = lpt.read_us(); |
Wayne Roberts |
8:5a5ea7cc946f | 291 | rssi = lora.get_current_rssi(); |
Wayne Roberts |
8:5a5ea7cc946f | 292 | if (rssi > rssiThresh) { |
Wayne Roberts |
8:5a5ea7cc946f | 293 | goto Lstart; |
Wayne Roberts |
8:5a5ea7cc946f | 294 | } |
Wayne Roberts |
8:5a5ea7cc946f | 295 | } while ((now - chFreeAt) < channelFreeTime); |
Wayne Roberts |
8:5a5ea7cc946f | 296 | } |
Wayne Roberts |
8:5a5ea7cc946f | 297 | |
Wayne Roberts |
8:5a5ea7cc946f | 298 | lora.start_tx(size); |
Wayne Roberts |
8:5a5ea7cc946f | 299 | pinEvent.txing = 1; |
Wayne Roberts |
8:5a5ea7cc946f | 300 | |
Wayne Roberts |
8:5a5ea7cc946f | 301 | return 0; |
Wayne Roberts |
8:5a5ea7cc946f | 302 | } |
Wayne Roberts |
8:5a5ea7cc946f | 303 | |
Wayne Roberts |
8:5a5ea7cc946f | 304 | void Radio::Rx(unsigned timeout) |
Wayne Roberts |
8:5a5ea7cc946f | 305 | { |
Wayne Roberts |
8:5a5ea7cc946f | 306 | if (timeout == 0) { |
Wayne Roberts |
8:5a5ea7cc946f | 307 | lora.start_rx(RF_OPMODE_RECEIVER); |
Wayne Roberts |
8:5a5ea7cc946f | 308 | MAC_PRINTF("startRxC "); |
Wayne Roberts |
8:5a5ea7cc946f | 309 | } else { |
Wayne Roberts |
8:5a5ea7cc946f | 310 | lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); // yyy tmp remove |
Wayne Roberts |
8:5a5ea7cc946f | 311 | lora.start_rx(RF_OPMODE_RECEIVER_SINGLE); |
Wayne Roberts |
8:5a5ea7cc946f | 312 | MAC_PRINTF("startRxS:%02x ", lora.RegIrqFlags.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 313 | } |
Wayne Roberts |
8:5a5ea7cc946f | 314 | |
Wayne Roberts |
8:5a5ea7cc946f | 315 | pinEvent.txing = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 316 | |
Wayne Roberts |
8:5a5ea7cc946f | 317 | } |
Wayne Roberts |
8:5a5ea7cc946f | 318 | |
Wayne Roberts |
8:5a5ea7cc946f | 319 | |
Wayne Roberts |
8:5a5ea7cc946f | 320 | void Radio::ocp(uint8_t ma) |
Wayne Roberts |
8:5a5ea7cc946f | 321 | { |
Wayne Roberts |
8:5a5ea7cc946f | 322 | if (ma < 130) |
Wayne Roberts |
8:5a5ea7cc946f | 323 | radio.RegOcp.bits.OcpTrim = (ma - 45) / 5; |
Wayne Roberts |
8:5a5ea7cc946f | 324 | else |
Wayne Roberts |
8:5a5ea7cc946f | 325 | radio.RegOcp.bits.OcpTrim = (ma + 30) / 10; |
Wayne Roberts |
8:5a5ea7cc946f | 326 | radio.write_reg(REG_OCP, radio.RegOcp.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 327 | |
Wayne Roberts |
8:5a5ea7cc946f | 328 | radio.RegOcp.octet = radio.read_reg(REG_OCP); |
Wayne Roberts |
8:5a5ea7cc946f | 329 | if (radio.RegOcp.bits.OcpTrim < 16) |
Wayne Roberts |
8:5a5ea7cc946f | 330 | ma = 45 + (5 * radio.RegOcp.bits.OcpTrim); |
Wayne Roberts |
8:5a5ea7cc946f | 331 | else if (radio.RegOcp.bits.OcpTrim < 28) |
Wayne Roberts |
8:5a5ea7cc946f | 332 | ma = (10 * radio.RegOcp.bits.OcpTrim) - 30; |
Wayne Roberts |
8:5a5ea7cc946f | 333 | else |
Wayne Roberts |
8:5a5ea7cc946f | 334 | ma = 240; |
Wayne Roberts |
8:5a5ea7cc946f | 335 | //MAC_PRINTF("Ocp: %dmA\r\n", ma); |
Wayne Roberts |
8:5a5ea7cc946f | 336 | } |
Wayne Roberts |
8:5a5ea7cc946f | 337 | |
Wayne Roberts |
8:5a5ea7cc946f | 338 | |
Wayne Roberts |
8:5a5ea7cc946f | 339 | void Radio::PrintStatus() |
Wayne Roberts |
8:5a5ea7cc946f | 340 | { |
Wayne Roberts |
8:5a5ea7cc946f | 341 | #ifdef MAC_DEBUG |
Wayne Roberts |
8:5a5ea7cc946f | 342 | radio.RegOpMode.octet = radio.read_reg(REG_OPMODE); |
Wayne Roberts |
8:5a5ea7cc946f | 343 | switch (radio.RegOpMode.bits.Mode) { |
Wayne Roberts |
8:5a5ea7cc946f | 344 | case RF_OPMODE_SLEEP: MAC_PRINTF("SLEEP "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 345 | case RF_OPMODE_STANDBY: MAC_PRINTF("STBY "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 346 | case RF_OPMODE_SYNTHESIZER_TX: MAC_PRINTF("FSTX "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 347 | case RF_OPMODE_TRANSMITTER: MAC_PRINTF("TX "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 348 | case RF_OPMODE_SYNTHESIZER_RX: MAC_PRINTF("FSRX "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 349 | case RF_OPMODE_RECEIVER: MAC_PRINTF("RXC "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 350 | case RF_OPMODE_RECEIVER_SINGLE: MAC_PRINTF("RXS "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 351 | case RF_OPMODE_CAD: MAC_PRINTF("CAD "); break; |
Wayne Roberts |
8:5a5ea7cc946f | 352 | } |
Wayne Roberts |
8:5a5ea7cc946f | 353 | |
Wayne Roberts |
8:5a5ea7cc946f | 354 | MAC_PRINTF("dio:%u:%u opmode:%02x %.2fMHz sf%ubw%u ", radio.dio0.read(), radio.dio1.read(), radio.RegOpMode.octet, radio.get_frf_MHz(), lora.getSf(), lora.getBw()); |
Wayne Roberts |
8:5a5ea7cc946f | 355 | lora.RegIrqFlags.octet = radio.read_reg(REG_LR_IRQFLAGS); |
Wayne Roberts |
8:5a5ea7cc946f | 356 | MAC_PRINTF("irqFlags:%02x\r\n", lora.RegIrqFlags.octet); |
Wayne Roberts |
8:5a5ea7cc946f | 357 | #endif /* MAC_DEBUG */ |
Wayne Roberts |
8:5a5ea7cc946f | 358 | } |
Wayne Roberts |
8:5a5ea7cc946f | 359 | |
Wayne Roberts |
8:5a5ea7cc946f | 360 | #ifdef DUTY_ENABLE |
Wayne Roberts |
8:5a5ea7cc946f | 361 | us_timestamp_t |
Wayne Roberts |
8:5a5ea7cc946f | 362 | Radio::TimeOnAir(RadioModems_t m, uint8_t pktLen) |
Wayne Roberts |
8:5a5ea7cc946f | 363 | { |
Wayne Roberts |
8:5a5ea7cc946f | 364 | uint32_t airTime = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 365 | |
Wayne Roberts |
8:5a5ea7cc946f | 366 | switch (m) |
Wayne Roberts |
8:5a5ea7cc946f | 367 | { |
Wayne Roberts |
8:5a5ea7cc946f | 368 | case MODEM_FSK: |
Wayne Roberts |
8:5a5ea7cc946f | 369 | { |
Wayne Roberts |
8:5a5ea7cc946f | 370 | /* TODO |
Wayne Roberts |
8:5a5ea7cc946f | 371 | airTime = round( ( 8 * ( SX1272.Settings.Fsk.PreambleLen + |
Wayne Roberts |
8:5a5ea7cc946f | 372 | ( ( SX1272Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) + |
Wayne Roberts |
8:5a5ea7cc946f | 373 | ( ( SX1272.Settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) + |
Wayne Roberts |
8:5a5ea7cc946f | 374 | ( ( ( SX1272Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) + |
Wayne Roberts |
8:5a5ea7cc946f | 375 | pktLen + |
Wayne Roberts |
8:5a5ea7cc946f | 376 | ( ( SX1272.Settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) / |
Wayne Roberts |
8:5a5ea7cc946f | 377 | SX1272.Settings.Fsk.Datarate ) * 1e3 ); |
Wayne Roberts |
8:5a5ea7cc946f | 378 | */ |
Wayne Roberts |
8:5a5ea7cc946f | 379 | } |
Wayne Roberts |
8:5a5ea7cc946f | 380 | break; |
Wayne Roberts |
8:5a5ea7cc946f | 381 | case MODEM_LORA: |
Wayne Roberts |
8:5a5ea7cc946f | 382 | { |
Wayne Roberts |
8:5a5ea7cc946f | 383 | double bw = 0.0; |
Wayne Roberts |
8:5a5ea7cc946f | 384 | uint8_t fixLen, bandwidth, LowDatarateOptimize, coderate, crcOn ; |
Wayne Roberts |
8:5a5ea7cc946f | 385 | if (radio.type == SX1276) { |
Wayne Roberts |
8:5a5ea7cc946f | 386 | coderate = lora.RegModemConfig.sx1276bits.CodingRate; |
Wayne Roberts |
8:5a5ea7cc946f | 387 | LowDatarateOptimize = lora.RegModemConfig3.sx1276bits.LowDataRateOptimize; |
Wayne Roberts |
8:5a5ea7cc946f | 388 | fixLen = lora.RegModemConfig.sx1276bits.ImplicitHeaderModeOn; |
Wayne Roberts |
8:5a5ea7cc946f | 389 | bandwidth = lora.RegModemConfig.sx1276bits.Bw - 7; |
Wayne Roberts |
8:5a5ea7cc946f | 390 | crcOn = lora.RegModemConfig2.sx1276bits.RxPayloadCrcOn; |
Wayne Roberts |
8:5a5ea7cc946f | 391 | } else if (radio.type == SX1272) { |
Wayne Roberts |
8:5a5ea7cc946f | 392 | coderate = lora.RegModemConfig.sx1272bits.CodingRate; |
Wayne Roberts |
8:5a5ea7cc946f | 393 | LowDatarateOptimize = lora.RegModemConfig.sx1272bits.LowDataRateOptimize; |
Wayne Roberts |
8:5a5ea7cc946f | 394 | fixLen = lora.RegModemConfig.sx1272bits.ImplicitHeaderModeOn; |
Wayne Roberts |
8:5a5ea7cc946f | 395 | bandwidth = lora.RegModemConfig.sx1272bits.Bw; |
Wayne Roberts |
8:5a5ea7cc946f | 396 | crcOn = lora.RegModemConfig.sx1272bits.RxPayloadCrcOn; |
Wayne Roberts |
8:5a5ea7cc946f | 397 | } else |
Wayne Roberts |
8:5a5ea7cc946f | 398 | return 0; |
Wayne Roberts |
8:5a5ea7cc946f | 399 | |
Wayne Roberts |
8:5a5ea7cc946f | 400 | switch( bandwidth ) |
Wayne Roberts |
8:5a5ea7cc946f | 401 | { |
Wayne Roberts |
8:5a5ea7cc946f | 402 | case 0: // 125 kHz |
Wayne Roberts |
8:5a5ea7cc946f | 403 | bw = 125;//ms: 125e3; |
Wayne Roberts |
8:5a5ea7cc946f | 404 | break; |
Wayne Roberts |
8:5a5ea7cc946f | 405 | case 1: // 250 kHz |
Wayne Roberts |
8:5a5ea7cc946f | 406 | bw = 250;//ms:250e3; |
Wayne Roberts |
8:5a5ea7cc946f | 407 | break; |
Wayne Roberts |
8:5a5ea7cc946f | 408 | case 2: // 500 kHz |
Wayne Roberts |
8:5a5ea7cc946f | 409 | bw = 500;//ms:500e3; |
Wayne Roberts |
8:5a5ea7cc946f | 410 | break; |
Wayne Roberts |
8:5a5ea7cc946f | 411 | } |
Wayne Roberts |
8:5a5ea7cc946f | 412 | |
Wayne Roberts |
8:5a5ea7cc946f | 413 | // Symbol rate : time for one symbol (secs) |
Wayne Roberts |
8:5a5ea7cc946f | 414 | double rs = bw / ( 1 << lora.RegModemConfig2.sx1276bits.SpreadingFactor ); |
Wayne Roberts |
8:5a5ea7cc946f | 415 | double ts = 1 / rs; |
Wayne Roberts |
8:5a5ea7cc946f | 416 | // time of preamble |
Wayne Roberts |
8:5a5ea7cc946f | 417 | double tPreamble; |
Wayne Roberts |
8:5a5ea7cc946f | 418 | tPreamble = (lora.RegPreamble + 4.25 ) * ts; |
Wayne Roberts |
8:5a5ea7cc946f | 419 | // Symbol length of payload and time |
Wayne Roberts |
8:5a5ea7cc946f | 420 | double tmp = ceil( ( 8 * pktLen - 4 * lora.RegModemConfig2.sx1276bits.SpreadingFactor + |
Wayne Roberts |
8:5a5ea7cc946f | 421 | 28 + 16 * crcOn - |
Wayne Roberts |
8:5a5ea7cc946f | 422 | ( fixLen ? 20 : 0 ) ) / |
Wayne Roberts |
8:5a5ea7cc946f | 423 | ( double )( 4 * ( lora.RegModemConfig2.sx1276bits.SpreadingFactor - |
Wayne Roberts |
8:5a5ea7cc946f | 424 | ( ( LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * |
Wayne Roberts |
8:5a5ea7cc946f | 425 | ( coderate + 4 ); |
Wayne Roberts |
8:5a5ea7cc946f | 426 | double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); |
Wayne Roberts |
8:5a5ea7cc946f | 427 | double tPayload = nPayload * ts; |
Wayne Roberts |
8:5a5ea7cc946f | 428 | // Time on air |
Wayne Roberts |
8:5a5ea7cc946f | 429 | double tOnAir = tPreamble + tPayload; |
Wayne Roberts |
8:5a5ea7cc946f | 430 | // return ms secs |
Wayne Roberts |
8:5a5ea7cc946f | 431 | airTime = floor( tOnAir * 1e3 + 0.999 ); |
Wayne Roberts |
8:5a5ea7cc946f | 432 | } |
Wayne Roberts |
8:5a5ea7cc946f | 433 | break; |
Wayne Roberts |
8:5a5ea7cc946f | 434 | } |
Wayne Roberts |
8:5a5ea7cc946f | 435 | return airTime; |
Wayne Roberts |
8:5a5ea7cc946f | 436 | |
Wayne Roberts |
8:5a5ea7cc946f | 437 | } |
Wayne Roberts |
8:5a5ea7cc946f | 438 | #endif /* DUTY_ENABLE */ |
Wayne Roberts |
8:5a5ea7cc946f | 439 | |
Wayne Roberts |
8:5a5ea7cc946f | 440 | void Radio::UserContext() |
Wayne Roberts |
8:5a5ea7cc946f | 441 | { |
Wayne Roberts |
8:5a5ea7cc946f | 442 | if (pinEvent.dio0) { |
Wayne Roberts |
8:5a5ea7cc946f | 443 | dio0UserContext(); |
Wayne Roberts |
8:5a5ea7cc946f | 444 | pinEvent.dio0 = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 445 | } |
Wayne Roberts |
8:5a5ea7cc946f | 446 | |
Wayne Roberts |
8:5a5ea7cc946f | 447 | if (pinEvent.dio1) { |
Wayne Roberts |
8:5a5ea7cc946f | 448 | dio1UserContext(); |
Wayne Roberts |
8:5a5ea7cc946f | 449 | pinEvent.dio1 = 0; |
Wayne Roberts |
8:5a5ea7cc946f | 450 | } |
Wayne Roberts |
8:5a5ea7cc946f | 451 | } |
Wayne Roberts |
8:5a5ea7cc946f | 452 | #endif /* ..SX127x_H */ |
Wayne Roberts |
8:5a5ea7cc946f | 453 |