cervin sx1265 operating with transceiver firmware
Dependents: lr1110_wifi_geolocation_device lr1110_wifi_geolocation_gateway
To use this driver, your LR1110 must be programmed as transceiver (not modem, which is LoRaWAN only).
Visit https://github.com/Lora-net/lr1110_updater_tool to update your LR1110, or change it from modem to transceiver if necessary.
lr1110.cpp@1:29294cae9f9a, 2021-02-05 (annotated)
- Committer:
- Wayne Roberts
- Date:
- Fri Feb 05 16:33:27 2021 -0800
- Revision:
- 1:29294cae9f9a
- Parent:
- 0:987d9022c152
remove busy check from service
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Wayne Roberts |
0:987d9022c152 | 1 | #include "sx12xx.h" |
Wayne Roberts |
0:987d9022c152 | 2 | |
Wayne Roberts |
0:987d9022c152 | 3 | Callback<void()> SX1265::dio9_topHalf; // low latency ISR context |
Wayne Roberts |
0:987d9022c152 | 4 | |
Wayne Roberts |
0:987d9022c152 | 5 | void SX1265::dio9isr() |
Wayne Roberts |
0:987d9022c152 | 6 | { |
Wayne Roberts |
0:987d9022c152 | 7 | if (dio9_topHalf) |
Wayne Roberts |
0:987d9022c152 | 8 | dio9_topHalf.call(); |
Wayne Roberts |
0:987d9022c152 | 9 | } |
Wayne Roberts |
0:987d9022c152 | 10 | |
Wayne Roberts |
0:987d9022c152 | 11 | SX1265::SX1265(SPI& _spi, PinName _nss, PinName _busy, PinName _dio9, PinName _nrst, uint32_t di, unsigned tto, uint8_t tv) |
Wayne Roberts |
0:987d9022c152 | 12 | : spi(_spi), nss(_nss), busy(_busy), dio9(_dio9), nrst(_nrst), default_irqs(di), tcxoStartDelay(tto), tcxoVolts(tv) |
Wayne Roberts |
0:987d9022c152 | 13 | { |
Wayne Roberts |
0:987d9022c152 | 14 | nss = 1; |
Wayne Roberts |
0:987d9022c152 | 15 | dio9.mode(PullDown); // dio9 floats if no interrupts enabled |
Wayne Roberts |
0:987d9022c152 | 16 | |
Wayne Roberts |
0:987d9022c152 | 17 | t.start(); |
Wayne Roberts |
0:987d9022c152 | 18 | |
Wayne Roberts |
0:987d9022c152 | 19 | if (busy) { |
Wayne Roberts |
0:987d9022c152 | 20 | hw_reset(); |
Wayne Roberts |
0:987d9022c152 | 21 | } |
Wayne Roberts |
0:987d9022c152 | 22 | |
Wayne Roberts |
0:987d9022c152 | 23 | dio9.rise(dio9isr); |
Wayne Roberts |
0:987d9022c152 | 24 | txTimeout = 0; // default tx-timeout off |
Wayne Roberts |
0:987d9022c152 | 25 | } |
Wayne Roberts |
0:987d9022c152 | 26 | |
Wayne Roberts |
0:987d9022c152 | 27 | |
Wayne Roberts |
0:987d9022c152 | 28 | void SX1265::hw_reset(void) |
Wayne Roberts |
0:987d9022c152 | 29 | { |
Wayne Roberts |
0:987d9022c152 | 30 | nrst.output(); |
Wayne Roberts |
0:987d9022c152 | 31 | nrst.write(0); |
Wayne Roberts |
0:987d9022c152 | 32 | ThisThread::sleep_for(2); |
Wayne Roberts |
0:987d9022c152 | 33 | nrst.write(1); |
Wayne Roberts |
0:987d9022c152 | 34 | nrst.input(); |
Wayne Roberts |
0:987d9022c152 | 35 | /* measured 211ms to startup (busy-hi during chip startup) */ |
Wayne Roberts |
0:987d9022c152 | 36 | ThisThread::sleep_for(200); |
Wayne Roberts |
0:987d9022c152 | 37 | while (busy) |
Wayne Roberts |
0:987d9022c152 | 38 | ThisThread::sleep_for(2); |
Wayne Roberts |
0:987d9022c152 | 39 | |
Wayne Roberts |
0:987d9022c152 | 40 | enable_default_irqs_(); |
Wayne Roberts |
0:987d9022c152 | 41 | } |
Wayne Roberts |
0:987d9022c152 | 42 | |
Wayne Roberts |
0:987d9022c152 | 43 | const char *SX1265::cmdStatus_toString(uint8_t s) |
Wayne Roberts |
0:987d9022c152 | 44 | { |
Wayne Roberts |
0:987d9022c152 | 45 | switch (s) { |
Wayne Roberts |
0:987d9022c152 | 46 | case CMD_FAIL: return "CMD_FAIL"; |
Wayne Roberts |
0:987d9022c152 | 47 | case CMD_PERR: return "CMD_PERR"; |
Wayne Roberts |
0:987d9022c152 | 48 | case CMD_OK: return "CMD_OK"; |
Wayne Roberts |
0:987d9022c152 | 49 | case CMD_DAT: return "CMD_DAT"; |
Wayne Roberts |
0:987d9022c152 | 50 | default: return NULL; |
Wayne Roberts |
0:987d9022c152 | 51 | } |
Wayne Roberts |
0:987d9022c152 | 52 | } |
Wayne Roberts |
0:987d9022c152 | 53 | |
Wayne Roberts |
0:987d9022c152 | 54 | uint32_t SX1265::service(void) |
Wayne Roberts |
0:987d9022c152 | 55 | { |
Wayne Roberts |
0:987d9022c152 | 56 | uint32_t ret = 0; |
Wayne Roberts |
0:987d9022c152 | 57 | uint8_t buf[4]; |
Wayne Roberts |
0:987d9022c152 | 58 | uint8_t irqbuf[4]; |
Wayne Roberts |
0:987d9022c152 | 59 | |
Wayne Roberts |
0:987d9022c152 | 60 | inService = true; |
Wayne Roberts |
1:29294cae9f9a | 61 | if (dio9) { |
Wayne Roberts |
0:987d9022c152 | 62 | bool try_rx = false; |
Wayne Roberts |
0:987d9022c152 | 63 | irq_t irq; |
Wayne Roberts |
0:987d9022c152 | 64 | stat_t stat; |
Wayne Roberts |
0:987d9022c152 | 65 | stat.word = xfer(OPCODE_GET_STATUS, 4, 4, irqbuf); |
Wayne Roberts |
0:987d9022c152 | 66 | if (stat.bits.rfu) { |
Wayne Roberts |
0:987d9022c152 | 67 | inService = false; |
Wayne Roberts |
0:987d9022c152 | 68 | return -1; |
Wayne Roberts |
0:987d9022c152 | 69 | } |
Wayne Roberts |
0:987d9022c152 | 70 | irq.dword = from_big_endian32(irqbuf); |
Wayne Roberts |
0:987d9022c152 | 71 | ret = irq.dword; |
Wayne Roberts |
0:987d9022c152 | 72 | if (stat.bits.rfu) { |
Wayne Roberts |
0:987d9022c152 | 73 | ret = -1; |
Wayne Roberts |
0:987d9022c152 | 74 | goto done; |
Wayne Roberts |
0:987d9022c152 | 75 | } |
Wayne Roberts |
0:987d9022c152 | 76 | if (irq.bits.TxDone) { |
Wayne Roberts |
0:987d9022c152 | 77 | chipMode = CHIPMODE_NONE; |
Wayne Roberts |
0:987d9022c152 | 78 | if (chipModeChange) |
Wayne Roberts |
0:987d9022c152 | 79 | chipModeChange.call(); // might change to Rx |
Wayne Roberts |
0:987d9022c152 | 80 | if (txDone) |
Wayne Roberts |
0:987d9022c152 | 81 | txDone.call(); |
Wayne Roberts |
0:987d9022c152 | 82 | } |
Wayne Roberts |
0:987d9022c152 | 83 | if (irq.bits.RxDone) { |
Wayne Roberts |
0:987d9022c152 | 84 | uint8_t len, offset; |
Wayne Roberts |
0:987d9022c152 | 85 | float rssi, snr; |
Wayne Roberts |
0:987d9022c152 | 86 | int8_t s; |
Wayne Roberts |
0:987d9022c152 | 87 | |
Wayne Roberts |
0:987d9022c152 | 88 | stat.word = xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 0, NULL); |
Wayne Roberts |
0:987d9022c152 | 89 | stat.word = xfer(0x0000, 0, 2, buf); |
Wayne Roberts |
0:987d9022c152 | 90 | rx_buf_offset = buf[1]; |
Wayne Roberts |
0:987d9022c152 | 91 | len = buf[0]; |
Wayne Roberts |
0:987d9022c152 | 92 | offset = buf[1]; |
Wayne Roberts |
0:987d9022c152 | 93 | |
Wayne Roberts |
0:987d9022c152 | 94 | buf[0] = offset; |
Wayne Roberts |
0:987d9022c152 | 95 | buf[1] = len; |
Wayne Roberts |
0:987d9022c152 | 96 | stat.word = xfer(OPCODE_READ_BUFFER8, 2, 0, buf); |
Wayne Roberts |
0:987d9022c152 | 97 | stat.word = xfer(0x0000, 0, len, rx_buf); |
Wayne Roberts |
0:987d9022c152 | 98 | stat.word = xfer(OPCODE_GET_PKT_STATUS, 0, 0, NULL); |
Wayne Roberts |
0:987d9022c152 | 99 | stat.word = xfer(0x0000, 0, 3, buf); |
Wayne Roberts |
0:987d9022c152 | 100 | rssi = buf[0] / -2.0; |
Wayne Roberts |
0:987d9022c152 | 101 | s = buf[1]; |
Wayne Roberts |
0:987d9022c152 | 102 | snr = s / 4.0; |
Wayne Roberts |
0:987d9022c152 | 103 | |
Wayne Roberts |
0:987d9022c152 | 104 | rxDone(len, rssi, snr); |
Wayne Roberts |
0:987d9022c152 | 105 | stat.word = xfer(OPCODE_CLEAR_RX_BUFFER, 0, 0, NULL); // yyy |
Wayne Roberts |
0:987d9022c152 | 106 | } |
Wayne Roberts |
0:987d9022c152 | 107 | if (irq.bits.CadDone) { |
Wayne Roberts |
0:987d9022c152 | 108 | if (cadDone) |
Wayne Roberts |
0:987d9022c152 | 109 | cadDone(irq.bits.CadDetected); |
Wayne Roberts |
0:987d9022c152 | 110 | } |
Wayne Roberts |
0:987d9022c152 | 111 | if (irq.bits.CmdErr) { |
Wayne Roberts |
0:987d9022c152 | 112 | err_opcode = prev_opcode; // culprit opcode |
Wayne Roberts |
0:987d9022c152 | 113 | } |
Wayne Roberts |
0:987d9022c152 | 114 | if (irq.bits.Error) { |
Wayne Roberts |
0:987d9022c152 | 115 | stat.word = xfer(OPCODE_GET_ERRORS, 0, 0, NULL); |
Wayne Roberts |
0:987d9022c152 | 116 | stat.word = xfer(0x0000, 0, 2, buf); |
Wayne Roberts |
0:987d9022c152 | 117 | if (stat.bits.cmdStatus == CMD_DAT) { |
Wayne Roberts |
0:987d9022c152 | 118 | errorStat.word = buf[0]; |
Wayne Roberts |
0:987d9022c152 | 119 | errorStat.word <<= 8; |
Wayne Roberts |
0:987d9022c152 | 120 | errorStat.word |= buf[1]; |
Wayne Roberts |
0:987d9022c152 | 121 | if (errorStat.bits.hf_xosc_start_) { |
Wayne Roberts |
0:987d9022c152 | 122 | buf[0] = tcxoVolts; |
Wayne Roberts |
0:987d9022c152 | 123 | to_big_endian32(tcxoStartDelay, buf+1); |
Wayne Roberts |
0:987d9022c152 | 124 | xfer(OPCODE_SET_TCXO_MODE, 5, 0, buf); |
Wayne Roberts |
0:987d9022c152 | 125 | buf[0] = 0; |
Wayne Roberts |
0:987d9022c152 | 126 | xfer(OPCODE_CALIBRATE, 1, 0, buf); |
Wayne Roberts |
0:987d9022c152 | 127 | |
Wayne Roberts |
0:987d9022c152 | 128 | if (chipMode == CHIPMODE_RX) { |
Wayne Roberts |
0:987d9022c152 | 129 | /* RX start failed due to HF xosc being a tcxo */ |
Wayne Roberts |
0:987d9022c152 | 130 | try_rx = true; |
Wayne Roberts |
0:987d9022c152 | 131 | } |
Wayne Roberts |
0:987d9022c152 | 132 | } |
Wayne Roberts |
0:987d9022c152 | 133 | /* ? OPCODE_CLEAR_ERRORS ? */ |
Wayne Roberts |
0:987d9022c152 | 134 | } |
Wayne Roberts |
0:987d9022c152 | 135 | } |
Wayne Roberts |
0:987d9022c152 | 136 | if (irq.bits.Timeout) { |
Wayne Roberts |
0:987d9022c152 | 137 | if (chipMode != CHIPMODE_NONE) { |
Wayne Roberts |
0:987d9022c152 | 138 | if (timeout) |
Wayne Roberts |
0:987d9022c152 | 139 | timeout(chipMode == CHIPMODE_TX); |
Wayne Roberts |
0:987d9022c152 | 140 | } |
Wayne Roberts |
0:987d9022c152 | 141 | chipMode = CHIPMODE_NONE; |
Wayne Roberts |
0:987d9022c152 | 142 | if (chipModeChange) |
Wayne Roberts |
0:987d9022c152 | 143 | chipModeChange.call(); |
Wayne Roberts |
0:987d9022c152 | 144 | } |
Wayne Roberts |
0:987d9022c152 | 145 | |
Wayne Roberts |
0:987d9022c152 | 146 | stat.word = xfer(OPCODE_CLEAR_IRQ, 4, 0, irqbuf); |
Wayne Roberts |
0:987d9022c152 | 147 | |
Wayne Roberts |
0:987d9022c152 | 148 | if (try_rx) { |
Wayne Roberts |
0:987d9022c152 | 149 | /* RX wasnt started because xosc wasnt started */ |
Wayne Roberts |
0:987d9022c152 | 150 | xfer(OPCODE_SET_RX, 3, 0, rxArgs); |
Wayne Roberts |
0:987d9022c152 | 151 | } |
Wayne Roberts |
1:29294cae9f9a | 152 | } // ..if (dio9) |
Wayne Roberts |
0:987d9022c152 | 153 | |
Wayne Roberts |
0:987d9022c152 | 154 | done: |
Wayne Roberts |
0:987d9022c152 | 155 | inService = false; |
Wayne Roberts |
0:987d9022c152 | 156 | return ret; |
Wayne Roberts |
0:987d9022c152 | 157 | } |
Wayne Roberts |
0:987d9022c152 | 158 | |
Wayne Roberts |
0:987d9022c152 | 159 | uint16_t SX1265::xfer(uint16_t opcode, uint16_t wlen, uint16_t rlen, uint8_t* ptr) |
Wayne Roberts |
0:987d9022c152 | 160 | { |
Wayne Roberts |
0:987d9022c152 | 161 | const uint8_t* stopPtr; |
Wayne Roberts |
0:987d9022c152 | 162 | const uint8_t* wstop; |
Wayne Roberts |
0:987d9022c152 | 163 | const uint8_t* rstop; |
Wayne Roberts |
0:987d9022c152 | 164 | const uint8_t nop = 0; |
Wayne Roberts |
0:987d9022c152 | 165 | uint16_t oc; |
Wayne Roberts |
0:987d9022c152 | 166 | stat_t ret; |
Wayne Roberts |
0:987d9022c152 | 167 | unsigned f; |
Wayne Roberts |
0:987d9022c152 | 168 | |
Wayne Roberts |
0:987d9022c152 | 169 | if (opcode == OPCODE_SET_RX) { |
Wayne Roberts |
0:987d9022c152 | 170 | const uint8_t* _ptr = ptr; |
Wayne Roberts |
0:987d9022c152 | 171 | rxArgs[0] = *_ptr++; |
Wayne Roberts |
0:987d9022c152 | 172 | rxArgs[1] = *_ptr++; |
Wayne Roberts |
0:987d9022c152 | 173 | rxArgs[2] = *_ptr++; |
Wayne Roberts |
0:987d9022c152 | 174 | } |
Wayne Roberts |
0:987d9022c152 | 175 | |
Wayne Roberts |
0:987d9022c152 | 176 | if (sleeping) { |
Wayne Roberts |
0:987d9022c152 | 177 | nss = 0; |
Wayne Roberts |
0:987d9022c152 | 178 | while (busy) |
Wayne Roberts |
0:987d9022c152 | 179 | ; |
Wayne Roberts |
0:987d9022c152 | 180 | sleeping = false; |
Wayne Roberts |
0:987d9022c152 | 181 | } else { |
Wayne Roberts |
0:987d9022c152 | 182 | if (busy) { |
Wayne Roberts |
0:987d9022c152 | 183 | int startAt = t.read_ms(); |
Wayne Roberts |
0:987d9022c152 | 184 | while (busy) { |
Wayne Roberts |
0:987d9022c152 | 185 | if (t.read_ms() - startAt > 50) { |
Wayne Roberts |
0:987d9022c152 | 186 | ret.bits.rfu = 15; |
Wayne Roberts |
0:987d9022c152 | 187 | return ret.word; |
Wayne Roberts |
0:987d9022c152 | 188 | } |
Wayne Roberts |
0:987d9022c152 | 189 | } |
Wayne Roberts |
0:987d9022c152 | 190 | } |
Wayne Roberts |
0:987d9022c152 | 191 | nss = 0; |
Wayne Roberts |
0:987d9022c152 | 192 | } |
Wayne Roberts |
0:987d9022c152 | 193 | |
Wayne Roberts |
0:987d9022c152 | 194 | prev_opcode = this_opcode; |
Wayne Roberts |
0:987d9022c152 | 195 | this_opcode = opcode; |
Wayne Roberts |
0:987d9022c152 | 196 | |
Wayne Roberts |
0:987d9022c152 | 197 | oc = opcode; |
Wayne Roberts |
0:987d9022c152 | 198 | f = oc >> 8; |
Wayne Roberts |
0:987d9022c152 | 199 | ret.word = spi.write(f); |
Wayne Roberts |
0:987d9022c152 | 200 | ret.word <<= 8; |
Wayne Roberts |
0:987d9022c152 | 201 | if (opcode != 0) { |
Wayne Roberts |
0:987d9022c152 | 202 | /* two byte command sent */ |
Wayne Roberts |
0:987d9022c152 | 203 | ret.word |= spi.write(oc & 0xff); |
Wayne Roberts |
0:987d9022c152 | 204 | } /* else: response */ |
Wayne Roberts |
0:987d9022c152 | 205 | else |
Wayne Roberts |
0:987d9022c152 | 206 | ret.word |= 0xff; // put impossible value for stat2, indicating only stat1 returned |
Wayne Roberts |
0:987d9022c152 | 207 | |
Wayne Roberts |
0:987d9022c152 | 208 | wstop = ptr + wlen; |
Wayne Roberts |
0:987d9022c152 | 209 | rstop = ptr + rlen; |
Wayne Roberts |
0:987d9022c152 | 210 | if (rlen > wlen) |
Wayne Roberts |
0:987d9022c152 | 211 | stopPtr = rstop; |
Wayne Roberts |
0:987d9022c152 | 212 | else |
Wayne Roberts |
0:987d9022c152 | 213 | stopPtr = wstop; |
Wayne Roberts |
0:987d9022c152 | 214 | |
Wayne Roberts |
0:987d9022c152 | 215 | for (; ptr < stopPtr; ptr++) { |
Wayne Roberts |
0:987d9022c152 | 216 | if (ptr < wstop && ptr < rstop) |
Wayne Roberts |
0:987d9022c152 | 217 | *ptr = spi.write(*ptr); |
Wayne Roberts |
0:987d9022c152 | 218 | else if (ptr < wstop) |
Wayne Roberts |
0:987d9022c152 | 219 | spi.write(*ptr); |
Wayne Roberts |
0:987d9022c152 | 220 | else |
Wayne Roberts |
0:987d9022c152 | 221 | *ptr = spi.write(nop); // n >= write length: send NOP |
Wayne Roberts |
0:987d9022c152 | 222 | } |
Wayne Roberts |
0:987d9022c152 | 223 | |
Wayne Roberts |
0:987d9022c152 | 224 | nss = 1; |
Wayne Roberts |
0:987d9022c152 | 225 | |
Wayne Roberts |
0:987d9022c152 | 226 | if (opcode == OPCODE_SET_SLEEP || |
Wayne Roberts |
0:987d9022c152 | 227 | opcode == OPCODE_SET_TX || |
Wayne Roberts |
0:987d9022c152 | 228 | opcode == OPCODE_SET_RX || |
Wayne Roberts |
0:987d9022c152 | 229 | opcode == OPCODE_SET_STANDBY || |
Wayne Roberts |
0:987d9022c152 | 230 | opcode == OPCODE_SET_FS) |
Wayne Roberts |
0:987d9022c152 | 231 | { |
Wayne Roberts |
0:987d9022c152 | 232 | if (opcode == OPCODE_SET_TX) |
Wayne Roberts |
0:987d9022c152 | 233 | chipMode = CHIPMODE_TX; |
Wayne Roberts |
0:987d9022c152 | 234 | else if (opcode == OPCODE_SET_RX) |
Wayne Roberts |
0:987d9022c152 | 235 | chipMode = CHIPMODE_RX; |
Wayne Roberts |
0:987d9022c152 | 236 | else if (opcode == OPCODE_SET_SLEEP || opcode == OPCODE_SET_STANDBY || opcode == OPCODE_SET_FS) { |
Wayne Roberts |
0:987d9022c152 | 237 | if (opcode == OPCODE_SET_SLEEP) |
Wayne Roberts |
0:987d9022c152 | 238 | sleeping = true; |
Wayne Roberts |
0:987d9022c152 | 239 | chipMode = CHIPMODE_NONE; |
Wayne Roberts |
0:987d9022c152 | 240 | } |
Wayne Roberts |
0:987d9022c152 | 241 | |
Wayne Roberts |
0:987d9022c152 | 242 | if (chipModeChange) |
Wayne Roberts |
0:987d9022c152 | 243 | chipModeChange.call(); |
Wayne Roberts |
0:987d9022c152 | 244 | } |
Wayne Roberts |
0:987d9022c152 | 245 | |
Wayne Roberts |
0:987d9022c152 | 246 | if (!inService && ret.bits.intActive) |
Wayne Roberts |
0:987d9022c152 | 247 | service(); |
Wayne Roberts |
0:987d9022c152 | 248 | |
Wayne Roberts |
0:987d9022c152 | 249 | return ret.word; |
Wayne Roberts |
0:987d9022c152 | 250 | } |
Wayne Roberts |
0:987d9022c152 | 251 | |
Wayne Roberts |
0:987d9022c152 | 252 | uint32_t SX1265::from_big_endian32(const uint8_t *in) |
Wayne Roberts |
0:987d9022c152 | 253 | { |
Wayne Roberts |
0:987d9022c152 | 254 | uint32_t ret; |
Wayne Roberts |
0:987d9022c152 | 255 | ret = *in++; |
Wayne Roberts |
0:987d9022c152 | 256 | ret <<= 8; |
Wayne Roberts |
0:987d9022c152 | 257 | ret |= *in++; |
Wayne Roberts |
0:987d9022c152 | 258 | ret <<= 8; |
Wayne Roberts |
0:987d9022c152 | 259 | ret |= *in++; |
Wayne Roberts |
0:987d9022c152 | 260 | ret <<= 8; |
Wayne Roberts |
0:987d9022c152 | 261 | ret |= *in; |
Wayne Roberts |
0:987d9022c152 | 262 | return ret; |
Wayne Roberts |
0:987d9022c152 | 263 | } |
Wayne Roberts |
0:987d9022c152 | 264 | |
Wayne Roberts |
0:987d9022c152 | 265 | void SX1265::to_big_endian16(uint16_t in, uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 266 | { |
Wayne Roberts |
0:987d9022c152 | 267 | out[1] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 268 | in >>= 8; |
Wayne Roberts |
0:987d9022c152 | 269 | out[0] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 270 | } |
Wayne Roberts |
0:987d9022c152 | 271 | |
Wayne Roberts |
0:987d9022c152 | 272 | void SX1265::to_big_endian24(uint32_t in, uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 273 | { |
Wayne Roberts |
0:987d9022c152 | 274 | out[2] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 275 | in >>= 8; |
Wayne Roberts |
0:987d9022c152 | 276 | out[1] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 277 | in >>= 8; |
Wayne Roberts |
0:987d9022c152 | 278 | out[0] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 279 | } |
Wayne Roberts |
0:987d9022c152 | 280 | |
Wayne Roberts |
0:987d9022c152 | 281 | void SX1265::to_big_endian32(uint32_t in, uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 282 | { |
Wayne Roberts |
0:987d9022c152 | 283 | out[3] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 284 | in >>= 8; |
Wayne Roberts |
0:987d9022c152 | 285 | out[2] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 286 | in >>= 8; |
Wayne Roberts |
0:987d9022c152 | 287 | out[1] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 288 | in >>= 8; |
Wayne Roberts |
0:987d9022c152 | 289 | out[0] = in & 0xff; |
Wayne Roberts |
0:987d9022c152 | 290 | } |
Wayne Roberts |
0:987d9022c152 | 291 | |
Wayne Roberts |
0:987d9022c152 | 292 | int SX1265::memRegRead(uint32_t addr, uint16_t len_dwords, uint32_t *dest) |
Wayne Roberts |
0:987d9022c152 | 293 | { |
Wayne Roberts |
0:987d9022c152 | 294 | uint8_t buf[5]; |
Wayne Roberts |
0:987d9022c152 | 295 | stat_t stat; |
Wayne Roberts |
0:987d9022c152 | 296 | while (len_dwords > 0) { |
Wayne Roberts |
0:987d9022c152 | 297 | unsigned this_len_dwords = len_dwords; |
Wayne Roberts |
0:987d9022c152 | 298 | if (this_len_dwords > 64) |
Wayne Roberts |
0:987d9022c152 | 299 | this_len_dwords = 64; |
Wayne Roberts |
0:987d9022c152 | 300 | buf[4] = this_len_dwords; |
Wayne Roberts |
0:987d9022c152 | 301 | to_big_endian32(addr, buf); |
Wayne Roberts |
0:987d9022c152 | 302 | stat.word = xfer(OPCODE_READREGMEM32, 5, 5, buf); |
Wayne Roberts |
0:987d9022c152 | 303 | if (stat.bits.rfu) { |
Wayne Roberts |
0:987d9022c152 | 304 | hw_reset(); |
Wayne Roberts |
0:987d9022c152 | 305 | return -1; |
Wayne Roberts |
0:987d9022c152 | 306 | } |
Wayne Roberts |
0:987d9022c152 | 307 | unsigned n, len_bytes = this_len_dwords * 4; |
Wayne Roberts |
0:987d9022c152 | 308 | stat.word = xfer(0x0000, 0, len_bytes, (uint8_t*)dest); |
Wayne Roberts |
0:987d9022c152 | 309 | if (stat.bits.rfu) { |
Wayne Roberts |
0:987d9022c152 | 310 | hw_reset(); |
Wayne Roberts |
0:987d9022c152 | 311 | return -1; |
Wayne Roberts |
0:987d9022c152 | 312 | } else { |
Wayne Roberts |
0:987d9022c152 | 313 | if (stat.bits.cmdStatus != CMD_DAT) { |
Wayne Roberts |
0:987d9022c152 | 314 | return -1; |
Wayne Roberts |
0:987d9022c152 | 315 | } |
Wayne Roberts |
0:987d9022c152 | 316 | for (n = 0; n < this_len_dwords; n++) { |
Wayne Roberts |
0:987d9022c152 | 317 | *dest = from_big_endian32((uint8_t*)dest); |
Wayne Roberts |
0:987d9022c152 | 318 | dest++; |
Wayne Roberts |
0:987d9022c152 | 319 | } |
Wayne Roberts |
0:987d9022c152 | 320 | } |
Wayne Roberts |
0:987d9022c152 | 321 | |
Wayne Roberts |
0:987d9022c152 | 322 | addr += len_bytes; |
Wayne Roberts |
0:987d9022c152 | 323 | len_dwords -= this_len_dwords; |
Wayne Roberts |
0:987d9022c152 | 324 | } // ..while (len_dwords > 0) |
Wayne Roberts |
0:987d9022c152 | 325 | |
Wayne Roberts |
0:987d9022c152 | 326 | return 0; |
Wayne Roberts |
0:987d9022c152 | 327 | } // ..memRegRead() |
Wayne Roberts |
0:987d9022c152 | 328 | |
Wayne Roberts |
0:987d9022c152 | 329 | void SX1265::enable_default_irqs_() |
Wayne Roberts |
0:987d9022c152 | 330 | { |
Wayne Roberts |
0:987d9022c152 | 331 | /* DIO9 is hi-z when no irqs enabled (floats high) */ |
Wayne Roberts |
0:987d9022c152 | 332 | uint8_t buf[4]; |
Wayne Roberts |
0:987d9022c152 | 333 | to_big_endian32(default_irqs, buf); |
Wayne Roberts |
0:987d9022c152 | 334 | xfer(OPCODE_SET_DIOIRQPARAMS, 4, 4, buf); |
Wayne Roberts |
0:987d9022c152 | 335 | } |
Wayne Roberts |
0:987d9022c152 | 336 | |
Wayne Roberts |
0:987d9022c152 | 337 | float SX1265::getMHz() |
Wayne Roberts |
0:987d9022c152 | 338 | { |
Wayne Roberts |
0:987d9022c152 | 339 | uint32_t frf; |
Wayne Roberts |
0:987d9022c152 | 340 | memRegRead(REG_ADDR_RFFREQ, 1, &frf); |
Wayne Roberts |
0:987d9022c152 | 341 | return frf / 1048576.0; |
Wayne Roberts |
0:987d9022c152 | 342 | } |
Wayne Roberts |
0:987d9022c152 | 343 | |
Wayne Roberts |
0:987d9022c152 | 344 | uint8_t SX1265::setMHz(float MHz) |
Wayne Roberts |
0:987d9022c152 | 345 | { |
Wayne Roberts |
0:987d9022c152 | 346 | uint8_t buf[4]; |
Wayne Roberts |
0:987d9022c152 | 347 | to_big_endian32(MHz * 1000000, buf); |
Wayne Roberts |
0:987d9022c152 | 348 | xfer(OPCODE_SET_RF_FREQ_HZ, 4, 0, buf); |
Wayne Roberts |
0:987d9022c152 | 349 | return 0; |
Wayne Roberts |
0:987d9022c152 | 350 | } |
Wayne Roberts |
0:987d9022c152 | 351 | |
Wayne Roberts |
0:987d9022c152 | 352 | void SX1265::setPacketType(uint8_t pt) |
Wayne Roberts |
0:987d9022c152 | 353 | { |
Wayne Roberts |
0:987d9022c152 | 354 | xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &pt); |
Wayne Roberts |
0:987d9022c152 | 355 | } |
Wayne Roberts |
0:987d9022c152 | 356 | |
Wayne Roberts |
0:987d9022c152 | 357 | uint8_t SX1265::getPacketType() |
Wayne Roberts |
0:987d9022c152 | 358 | { |
Wayne Roberts |
0:987d9022c152 | 359 | uint8_t buf; |
Wayne Roberts |
0:987d9022c152 | 360 | stat_t stat; |
Wayne Roberts |
0:987d9022c152 | 361 | xfer(OPCODE_GET_PACKET_TYPE, 0, 0, NULL); |
Wayne Roberts |
0:987d9022c152 | 362 | stat.word = xfer(0x0000, 0, 1, &buf); |
Wayne Roberts |
0:987d9022c152 | 363 | if (stat.bits.cmdStatus == CMD_DAT) |
Wayne Roberts |
0:987d9022c152 | 364 | return buf; |
Wayne Roberts |
0:987d9022c152 | 365 | else |
Wayne Roberts |
0:987d9022c152 | 366 | return 0; |
Wayne Roberts |
0:987d9022c152 | 367 | } |
Wayne Roberts |
0:987d9022c152 | 368 | |
Wayne Roberts |
0:987d9022c152 | 369 | void SX1265::start_tx(uint8_t pktLen) |
Wayne Roberts |
0:987d9022c152 | 370 | { |
Wayne Roberts |
0:987d9022c152 | 371 | uint8_t buf[3]; |
Wayne Roberts |
0:987d9022c152 | 372 | xfer(OPCODE_WRITE_BUFFER8, pktLen, 0, tx_buf); |
Wayne Roberts |
0:987d9022c152 | 373 | to_big_endian24(txTimeout, buf); |
Wayne Roberts |
0:987d9022c152 | 374 | xfer(OPCODE_SET_TX, 3, 0, buf); |
Wayne Roberts |
0:987d9022c152 | 375 | } |
Wayne Roberts |
0:987d9022c152 | 376 | |
Wayne Roberts |
0:987d9022c152 | 377 | void SX1265::GetPaConfig(uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 378 | { |
Wayne Roberts |
0:987d9022c152 | 379 | txParamsA_t tpa; |
Wayne Roberts |
0:987d9022c152 | 380 | txParamsB_t tpb; |
Wayne Roberts |
0:987d9022c152 | 381 | /* PaSel also in 0x00f30088 */ |
Wayne Roberts |
0:987d9022c152 | 382 | memRegRead(REG_ADDR_TX_PARAMS_A, 1, &tpa.dword); |
Wayne Roberts |
0:987d9022c152 | 383 | memRegRead(REG_ADDR_TX_PARAMS_B, 1, &tpb.dword); |
Wayne Roberts |
0:987d9022c152 | 384 | out[0] = tpb.bits.PaSel; |
Wayne Roberts |
0:987d9022c152 | 385 | out[1] = tpa.bits.RegPASupply; |
Wayne Roberts |
0:987d9022c152 | 386 | out[2] = tpb.bits.PaDutyCycle; |
Wayne Roberts |
0:987d9022c152 | 387 | out[3] = tpb.bits.PaHPSel; |
Wayne Roberts |
0:987d9022c152 | 388 | } |
Wayne Roberts |
0:987d9022c152 | 389 | |
Wayne Roberts |
0:987d9022c152 | 390 | void SX1265::GetLoRaModulationParameters(uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 391 | { |
Wayne Roberts |
0:987d9022c152 | 392 | loraConfig0_t cfg0; |
Wayne Roberts |
0:987d9022c152 | 393 | memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword); |
Wayne Roberts |
0:987d9022c152 | 394 | |
Wayne Roberts |
0:987d9022c152 | 395 | out[0] = cfg0.bits.modem_sf; |
Wayne Roberts |
0:987d9022c152 | 396 | out[1] = cfg0.bits.modem_bw; |
Wayne Roberts |
0:987d9022c152 | 397 | out[2] = cfg0.bits.coding_rate; |
Wayne Roberts |
0:987d9022c152 | 398 | out[3] = cfg0.bits.ppm_offset; |
Wayne Roberts |
0:987d9022c152 | 399 | } |
Wayne Roberts |
0:987d9022c152 | 400 | |
Wayne Roberts |
0:987d9022c152 | 401 | void SX1265::GetGfskModulationParameters(uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 402 | { |
Wayne Roberts |
0:987d9022c152 | 403 | uint32_t u32; |
Wayne Roberts |
0:987d9022c152 | 404 | gfskBW_t bw_reg; |
Wayne Roberts |
0:987d9022c152 | 405 | gfskConfig0_t cfg0; |
Wayne Roberts |
0:987d9022c152 | 406 | uint8_t bwf; |
Wayne Roberts |
0:987d9022c152 | 407 | unsigned hz; |
Wayne Roberts |
0:987d9022c152 | 408 | |
Wayne Roberts |
0:987d9022c152 | 409 | memRegRead(REG_ADDR_GFSK_BITRATE, 1, &u32); |
Wayne Roberts |
0:987d9022c152 | 410 | hz = GFSK_BITRATE_NUMERATOR / u32; |
Wayne Roberts |
0:987d9022c152 | 411 | to_big_endian32(hz, out); |
Wayne Roberts |
0:987d9022c152 | 412 | |
Wayne Roberts |
0:987d9022c152 | 413 | memRegRead(REG_ADDR_GFSK_CFG0, 1, &cfg0.dword); |
Wayne Roberts |
0:987d9022c152 | 414 | switch (cfg0.bits.bt) { |
Wayne Roberts |
0:987d9022c152 | 415 | case 0: /* off */ out[4] = GFSK_BT_OFF; break; |
Wayne Roberts |
0:987d9022c152 | 416 | case 1: /* 0.3 */ out[4] = GFSK_BT_0_3; break; |
Wayne Roberts |
0:987d9022c152 | 417 | case 2: /* 0.5 */ out[4] = GFSK_BT_0_5; break; |
Wayne Roberts |
0:987d9022c152 | 418 | case 3: /* 0.7 */ out[4] = GFSK_BT_0_7; break; |
Wayne Roberts |
0:987d9022c152 | 419 | case 4: /* 1.0 */ out[4] = GFSK_BT_1_0; break; |
Wayne Roberts |
0:987d9022c152 | 420 | } |
Wayne Roberts |
0:987d9022c152 | 421 | |
Wayne Roberts |
0:987d9022c152 | 422 | memRegRead(REG_ADDR_GFSK_BWF, 1, &bw_reg.dword); |
Wayne Roberts |
0:987d9022c152 | 423 | bwf = bw_reg.bits.bwf_hi; |
Wayne Roberts |
0:987d9022c152 | 424 | bwf <<= 3; |
Wayne Roberts |
0:987d9022c152 | 425 | bwf |= bw_reg.bits.bwf_lo; |
Wayne Roberts |
0:987d9022c152 | 426 | out[5] = bwf; |
Wayne Roberts |
0:987d9022c152 | 427 | |
Wayne Roberts |
0:987d9022c152 | 428 | memRegRead(REG_ADDR_GFSK_FDEV, 1, &u32); |
Wayne Roberts |
0:987d9022c152 | 429 | hz = (unsigned) ((u32 * FREQ_STEP) - 0.5); |
Wayne Roberts |
0:987d9022c152 | 430 | to_big_endian32(hz, out+6); |
Wayne Roberts |
0:987d9022c152 | 431 | } |
Wayne Roberts |
0:987d9022c152 | 432 | |
Wayne Roberts |
0:987d9022c152 | 433 | void SX1265::GetLoRaPacketParameters(uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 434 | { |
Wayne Roberts |
0:987d9022c152 | 435 | loraConfig0_t cfg0; |
Wayne Roberts |
0:987d9022c152 | 436 | loraConfigA_t cfgA; |
Wayne Roberts |
0:987d9022c152 | 437 | loraConfigC_t cfgc; |
Wayne Roberts |
0:987d9022c152 | 438 | unsigned pl; |
Wayne Roberts |
0:987d9022c152 | 439 | |
Wayne Roberts |
0:987d9022c152 | 440 | memRegRead(REG_ADDR_LORA_CONFIGC, 1, &cfgc.dword); |
Wayne Roberts |
0:987d9022c152 | 441 | pl = cfgc.bits.preamble_length; |
Wayne Roberts |
0:987d9022c152 | 442 | out[1] = pl & 0xff; |
Wayne Roberts |
0:987d9022c152 | 443 | pl >>= 8; |
Wayne Roberts |
0:987d9022c152 | 444 | out[0] = pl; |
Wayne Roberts |
0:987d9022c152 | 445 | |
Wayne Roberts |
0:987d9022c152 | 446 | memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword); |
Wayne Roberts |
0:987d9022c152 | 447 | out[2] = cfg0.bits.implicit_header; |
Wayne Roberts |
0:987d9022c152 | 448 | out[3] = cfg0.bits.payload_length; |
Wayne Roberts |
0:987d9022c152 | 449 | out[4] = cfg0.bits.crc_on; |
Wayne Roberts |
0:987d9022c152 | 450 | |
Wayne Roberts |
0:987d9022c152 | 451 | memRegRead(REG_ADDR_LORA_CONFIGA, 1, &cfgA.dword); |
Wayne Roberts |
0:987d9022c152 | 452 | out[5] = cfgA.bits.invertIQ; |
Wayne Roberts |
0:987d9022c152 | 453 | } |
Wayne Roberts |
0:987d9022c152 | 454 | |
Wayne Roberts |
0:987d9022c152 | 455 | void SX1265::GetGfskPacketParameters(uint8_t *out) |
Wayne Roberts |
0:987d9022c152 | 456 | { |
Wayne Roberts |
0:987d9022c152 | 457 | gfskConfig1_t cfg1; |
Wayne Roberts |
0:987d9022c152 | 458 | gfskConfig2_t cfg2; |
Wayne Roberts |
0:987d9022c152 | 459 | gfskConfig3_t cfg3; |
Wayne Roberts |
0:987d9022c152 | 460 | gfskConfig4_t cfg4; |
Wayne Roberts |
0:987d9022c152 | 461 | gfskConfig5_t cfg5; |
Wayne Roberts |
0:987d9022c152 | 462 | uint32_t u32; |
Wayne Roberts |
0:987d9022c152 | 463 | |
Wayne Roberts |
0:987d9022c152 | 464 | memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword); |
Wayne Roberts |
0:987d9022c152 | 465 | |
Wayne Roberts |
0:987d9022c152 | 466 | u32 = cfg1.bits.preamble_length; |
Wayne Roberts |
0:987d9022c152 | 467 | out[1] = u32; |
Wayne Roberts |
0:987d9022c152 | 468 | u32 >>= 8; |
Wayne Roberts |
0:987d9022c152 | 469 | out[0] = u32; |
Wayne Roberts |
0:987d9022c152 | 470 | |
Wayne Roberts |
0:987d9022c152 | 471 | memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword); |
Wayne Roberts |
0:987d9022c152 | 472 | if (cfg1.bits.preamble_det_enable) |
Wayne Roberts |
0:987d9022c152 | 473 | out[2] = cfg1.bits.preamble_det_len; |
Wayne Roberts |
0:987d9022c152 | 474 | else |
Wayne Roberts |
0:987d9022c152 | 475 | out[2] = 0; |
Wayne Roberts |
0:987d9022c152 | 476 | |
Wayne Roberts |
0:987d9022c152 | 477 | memRegRead(REG_ADDR_GFSK_CFG2, 1, &cfg2.dword); |
Wayne Roberts |
0:987d9022c152 | 478 | out[3] = cfg2.bits.sync_word_length; |
Wayne Roberts |
0:987d9022c152 | 479 | |
Wayne Roberts |
0:987d9022c152 | 480 | memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_B, 1, &cfg4.dword); |
Wayne Roberts |
0:987d9022c152 | 481 | out[4] = cfg4.bits.addr_comp; |
Wayne Roberts |
0:987d9022c152 | 482 | |
Wayne Roberts |
0:987d9022c152 | 483 | memRegRead(REG_ADDR_GFSK_CFG3, 1, &cfg3.dword); |
Wayne Roberts |
0:987d9022c152 | 484 | out[5] = cfg3.bits.variable_length; |
Wayne Roberts |
0:987d9022c152 | 485 | |
Wayne Roberts |
0:987d9022c152 | 486 | memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_A, 1, &u32); |
Wayne Roberts |
0:987d9022c152 | 487 | out[6] = u32 & 0xff; |
Wayne Roberts |
0:987d9022c152 | 488 | |
Wayne Roberts |
0:987d9022c152 | 489 | memRegRead(REG_ADDR_GFSK_CFG5, 1, &cfg5.dword); |
Wayne Roberts |
0:987d9022c152 | 490 | |
Wayne Roberts |
0:987d9022c152 | 491 | if (cfg5.bits.crc_off) |
Wayne Roberts |
0:987d9022c152 | 492 | out[7] |= 1; |
Wayne Roberts |
0:987d9022c152 | 493 | else |
Wayne Roberts |
0:987d9022c152 | 494 | out[7] &= ~1; |
Wayne Roberts |
0:987d9022c152 | 495 | |
Wayne Roberts |
0:987d9022c152 | 496 | if (cfg5.bits.crc_size) |
Wayne Roberts |
0:987d9022c152 | 497 | out[7] |= 2; |
Wayne Roberts |
0:987d9022c152 | 498 | else |
Wayne Roberts |
0:987d9022c152 | 499 | out[7] &= ~2; |
Wayne Roberts |
0:987d9022c152 | 500 | |
Wayne Roberts |
0:987d9022c152 | 501 | if (cfg5.bits.crc_invert) |
Wayne Roberts |
0:987d9022c152 | 502 | out[7] |= 4; |
Wayne Roberts |
0:987d9022c152 | 503 | else |
Wayne Roberts |
0:987d9022c152 | 504 | out[7] &= ~4; |
Wayne Roberts |
0:987d9022c152 | 505 | |
Wayne Roberts |
0:987d9022c152 | 506 | out[8] = cfg5.bits.whitening_enable; |
Wayne Roberts |
0:987d9022c152 | 507 | } |
Wayne Roberts |
0:987d9022c152 | 508 |