cervin sx1265 operating with transceiver firmware
Dependents: lr1110_wifi_geolocation_device lr1110_wifi_geolocation_gateway
lr1110.cpp
00001 #include "sx12xx.h" 00002 00003 Callback<void()> SX1265::dio9_topHalf; // low latency ISR context 00004 00005 void SX1265::dio9isr() 00006 { 00007 if (dio9_topHalf) 00008 dio9_topHalf.call(); 00009 } 00010 00011 SX1265::SX1265(SPI& _spi, PinName _nss, PinName _busy, PinName _dio9, PinName _nrst, uint32_t di, unsigned tto, uint8_t tv) 00012 : spi(_spi), nss(_nss), busy(_busy), dio9(_dio9), nrst(_nrst), default_irqs(di), tcxoStartDelay(tto), tcxoVolts(tv) 00013 { 00014 nss = 1; 00015 dio9.mode(PullDown); // dio9 floats if no interrupts enabled 00016 00017 t.start(); 00018 00019 if (busy) { 00020 hw_reset(); 00021 } 00022 00023 dio9.rise(dio9isr); 00024 txTimeout = 0; // default tx-timeout off 00025 } 00026 00027 00028 void SX1265::hw_reset(void) 00029 { 00030 nrst.output(); 00031 nrst.write(0); 00032 ThisThread::sleep_for(2); 00033 nrst.write(1); 00034 nrst.input(); 00035 /* measured 211ms to startup (busy-hi during chip startup) */ 00036 ThisThread::sleep_for(200); 00037 while (busy) 00038 ThisThread::sleep_for(2); 00039 00040 enable_default_irqs_(); 00041 } 00042 00043 const char *SX1265::cmdStatus_toString(uint8_t s) 00044 { 00045 switch (s) { 00046 case CMD_FAIL: return "CMD_FAIL"; 00047 case CMD_PERR: return "CMD_PERR"; 00048 case CMD_OK: return "CMD_OK"; 00049 case CMD_DAT: return "CMD_DAT"; 00050 default: return NULL; 00051 } 00052 } 00053 00054 uint32_t SX1265::service(void) 00055 { 00056 uint32_t ret = 0; 00057 uint8_t buf[4]; 00058 uint8_t irqbuf[4]; 00059 00060 inService = true; 00061 if (dio9) { 00062 bool try_rx = false; 00063 irq_t irq; 00064 stat_t stat; 00065 stat.word = xfer(OPCODE_GET_STATUS, 4, 4, irqbuf); 00066 if (stat.bits.rfu) { 00067 inService = false; 00068 return -1; 00069 } 00070 irq.dword = from_big_endian32(irqbuf); 00071 ret = irq.dword; 00072 if (stat.bits.rfu) { 00073 ret = -1; 00074 goto done; 00075 } 00076 if (irq.bits.TxDone) { 00077 chipMode = CHIPMODE_NONE; 00078 if (chipModeChange) 00079 chipModeChange.call(); // might change to Rx 00080 if (txDone) 00081 txDone.call(); 00082 } 00083 if (irq.bits.RxDone) { 00084 uint8_t len, offset; 00085 float rssi, snr; 00086 int8_t s; 00087 00088 stat.word = xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 0, NULL); 00089 stat.word = xfer(0x0000, 0, 2, buf); 00090 rx_buf_offset = buf[1]; 00091 len = buf[0]; 00092 offset = buf[1]; 00093 00094 buf[0] = offset; 00095 buf[1] = len; 00096 stat.word = xfer(OPCODE_READ_BUFFER8, 2, 0, buf); 00097 stat.word = xfer(0x0000, 0, len, rx_buf); 00098 stat.word = xfer(OPCODE_GET_PKT_STATUS, 0, 0, NULL); 00099 stat.word = xfer(0x0000, 0, 3, buf); 00100 rssi = buf[0] / -2.0; 00101 s = buf[1]; 00102 snr = s / 4.0; 00103 00104 rxDone(len, rssi, snr); 00105 stat.word = xfer(OPCODE_CLEAR_RX_BUFFER, 0, 0, NULL); // yyy 00106 } 00107 if (irq.bits.CadDone) { 00108 if (cadDone) 00109 cadDone(irq.bits.CadDetected); 00110 } 00111 if (irq.bits.CmdErr) { 00112 err_opcode = prev_opcode; // culprit opcode 00113 } 00114 if (irq.bits.Error) { 00115 stat.word = xfer(OPCODE_GET_ERRORS, 0, 0, NULL); 00116 stat.word = xfer(0x0000, 0, 2, buf); 00117 if (stat.bits.cmdStatus == CMD_DAT) { 00118 errorStat.word = buf[0]; 00119 errorStat.word <<= 8; 00120 errorStat.word |= buf[1]; 00121 if (errorStat.bits.hf_xosc_start_) { 00122 buf[0] = tcxoVolts; 00123 to_big_endian32(tcxoStartDelay, buf+1); 00124 xfer(OPCODE_SET_TCXO_MODE, 5, 0, buf); 00125 buf[0] = 0; 00126 xfer(OPCODE_CALIBRATE, 1, 0, buf); 00127 00128 if (chipMode == CHIPMODE_RX) { 00129 /* RX start failed due to HF xosc being a tcxo */ 00130 try_rx = true; 00131 } 00132 } 00133 /* ? OPCODE_CLEAR_ERRORS ? */ 00134 } 00135 } 00136 if (irq.bits.Timeout) { 00137 if (chipMode != CHIPMODE_NONE) { 00138 if (timeout) 00139 timeout(chipMode == CHIPMODE_TX); 00140 } 00141 chipMode = CHIPMODE_NONE; 00142 if (chipModeChange) 00143 chipModeChange.call(); 00144 } 00145 00146 stat.word = xfer(OPCODE_CLEAR_IRQ, 4, 0, irqbuf); 00147 00148 if (try_rx) { 00149 /* RX wasnt started because xosc wasnt started */ 00150 xfer(OPCODE_SET_RX, 3, 0, rxArgs); 00151 } 00152 } // ..if (dio9) 00153 00154 done: 00155 inService = false; 00156 return ret; 00157 } 00158 00159 uint16_t SX1265::xfer(uint16_t opcode, uint16_t wlen, uint16_t rlen, uint8_t* ptr) 00160 { 00161 const uint8_t* stopPtr; 00162 const uint8_t* wstop; 00163 const uint8_t* rstop; 00164 const uint8_t nop = 0; 00165 uint16_t oc; 00166 stat_t ret; 00167 unsigned f; 00168 00169 if (opcode == OPCODE_SET_RX) { 00170 const uint8_t* _ptr = ptr; 00171 rxArgs[0] = *_ptr++; 00172 rxArgs[1] = *_ptr++; 00173 rxArgs[2] = *_ptr++; 00174 } 00175 00176 if (sleeping) { 00177 nss = 0; 00178 while (busy) 00179 ; 00180 sleeping = false; 00181 } else { 00182 if (busy) { 00183 int startAt = t.read_ms(); 00184 while (busy) { 00185 if (t.read_ms() - startAt > 50) { 00186 ret.bits.rfu = 15; 00187 return ret.word; 00188 } 00189 } 00190 } 00191 nss = 0; 00192 } 00193 00194 prev_opcode = this_opcode; 00195 this_opcode = opcode; 00196 00197 oc = opcode; 00198 f = oc >> 8; 00199 ret.word = spi.write(f); 00200 ret.word <<= 8; 00201 if (opcode != 0) { 00202 /* two byte command sent */ 00203 ret.word |= spi.write(oc & 0xff); 00204 } /* else: response */ 00205 else 00206 ret.word |= 0xff; // put impossible value for stat2, indicating only stat1 returned 00207 00208 wstop = ptr + wlen; 00209 rstop = ptr + rlen; 00210 if (rlen > wlen) 00211 stopPtr = rstop; 00212 else 00213 stopPtr = wstop; 00214 00215 for (; ptr < stopPtr; ptr++) { 00216 if (ptr < wstop && ptr < rstop) 00217 *ptr = spi.write(*ptr); 00218 else if (ptr < wstop) 00219 spi.write(*ptr); 00220 else 00221 *ptr = spi.write(nop); // n >= write length: send NOP 00222 } 00223 00224 nss = 1; 00225 00226 if (opcode == OPCODE_SET_SLEEP || 00227 opcode == OPCODE_SET_TX || 00228 opcode == OPCODE_SET_RX || 00229 opcode == OPCODE_SET_STANDBY || 00230 opcode == OPCODE_SET_FS) 00231 { 00232 if (opcode == OPCODE_SET_TX) 00233 chipMode = CHIPMODE_TX; 00234 else if (opcode == OPCODE_SET_RX) 00235 chipMode = CHIPMODE_RX; 00236 else if (opcode == OPCODE_SET_SLEEP || opcode == OPCODE_SET_STANDBY || opcode == OPCODE_SET_FS) { 00237 if (opcode == OPCODE_SET_SLEEP) 00238 sleeping = true; 00239 chipMode = CHIPMODE_NONE; 00240 } 00241 00242 if (chipModeChange) 00243 chipModeChange.call(); 00244 } 00245 00246 if (!inService && ret.bits.intActive) 00247 service(); 00248 00249 return ret.word; 00250 } 00251 00252 uint32_t SX1265::from_big_endian32(const uint8_t *in) 00253 { 00254 uint32_t ret; 00255 ret = *in++; 00256 ret <<= 8; 00257 ret |= *in++; 00258 ret <<= 8; 00259 ret |= *in++; 00260 ret <<= 8; 00261 ret |= *in; 00262 return ret; 00263 } 00264 00265 void SX1265::to_big_endian16(uint16_t in, uint8_t *out) 00266 { 00267 out[1] = in & 0xff; 00268 in >>= 8; 00269 out[0] = in & 0xff; 00270 } 00271 00272 void SX1265::to_big_endian24(uint32_t in, uint8_t *out) 00273 { 00274 out[2] = in & 0xff; 00275 in >>= 8; 00276 out[1] = in & 0xff; 00277 in >>= 8; 00278 out[0] = in & 0xff; 00279 } 00280 00281 void SX1265::to_big_endian32(uint32_t in, uint8_t *out) 00282 { 00283 out[3] = in & 0xff; 00284 in >>= 8; 00285 out[2] = in & 0xff; 00286 in >>= 8; 00287 out[1] = in & 0xff; 00288 in >>= 8; 00289 out[0] = in & 0xff; 00290 } 00291 00292 int SX1265::memRegRead(uint32_t addr, uint16_t len_dwords, uint32_t *dest) 00293 { 00294 uint8_t buf[5]; 00295 stat_t stat; 00296 while (len_dwords > 0) { 00297 unsigned this_len_dwords = len_dwords; 00298 if (this_len_dwords > 64) 00299 this_len_dwords = 64; 00300 buf[4] = this_len_dwords; 00301 to_big_endian32(addr, buf); 00302 stat.word = xfer(OPCODE_READREGMEM32, 5, 5, buf); 00303 if (stat.bits.rfu) { 00304 hw_reset(); 00305 return -1; 00306 } 00307 unsigned n, len_bytes = this_len_dwords * 4; 00308 stat.word = xfer(0x0000, 0, len_bytes, (uint8_t*)dest); 00309 if (stat.bits.rfu) { 00310 hw_reset(); 00311 return -1; 00312 } else { 00313 if (stat.bits.cmdStatus != CMD_DAT) { 00314 return -1; 00315 } 00316 for (n = 0; n < this_len_dwords; n++) { 00317 *dest = from_big_endian32((uint8_t*)dest); 00318 dest++; 00319 } 00320 } 00321 00322 addr += len_bytes; 00323 len_dwords -= this_len_dwords; 00324 } // ..while (len_dwords > 0) 00325 00326 return 0; 00327 } // ..memRegRead() 00328 00329 void SX1265::enable_default_irqs_() 00330 { 00331 /* DIO9 is hi-z when no irqs enabled (floats high) */ 00332 uint8_t buf[4]; 00333 to_big_endian32(default_irqs, buf); 00334 xfer(OPCODE_SET_DIOIRQPARAMS, 4, 4, buf); 00335 } 00336 00337 float SX1265::getMHz() 00338 { 00339 uint32_t frf; 00340 memRegRead(REG_ADDR_RFFREQ, 1, &frf); 00341 return frf / 1048576.0; 00342 } 00343 00344 uint8_t SX1265::setMHz(float MHz) 00345 { 00346 uint8_t buf[4]; 00347 to_big_endian32(MHz * 1000000, buf); 00348 xfer(OPCODE_SET_RF_FREQ_HZ, 4, 0, buf); 00349 return 0; 00350 } 00351 00352 void SX1265::setPacketType(uint8_t pt) 00353 { 00354 xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &pt); 00355 } 00356 00357 uint8_t SX1265::getPacketType() 00358 { 00359 uint8_t buf; 00360 stat_t stat; 00361 xfer(OPCODE_GET_PACKET_TYPE, 0, 0, NULL); 00362 stat.word = xfer(0x0000, 0, 1, &buf); 00363 if (stat.bits.cmdStatus == CMD_DAT) 00364 return buf; 00365 else 00366 return 0; 00367 } 00368 00369 void SX1265::start_tx(uint8_t pktLen) 00370 { 00371 uint8_t buf[3]; 00372 xfer(OPCODE_WRITE_BUFFER8, pktLen, 0, tx_buf); 00373 to_big_endian24(txTimeout, buf); 00374 xfer(OPCODE_SET_TX, 3, 0, buf); 00375 } 00376 00377 void SX1265::GetPaConfig(uint8_t *out) 00378 { 00379 txParamsA_t tpa; 00380 txParamsB_t tpb; 00381 /* PaSel also in 0x00f30088 */ 00382 memRegRead(REG_ADDR_TX_PARAMS_A, 1, &tpa.dword); 00383 memRegRead(REG_ADDR_TX_PARAMS_B, 1, &tpb.dword); 00384 out[0] = tpb.bits.PaSel; 00385 out[1] = tpa.bits.RegPASupply; 00386 out[2] = tpb.bits.PaDutyCycle; 00387 out[3] = tpb.bits.PaHPSel; 00388 } 00389 00390 void SX1265::GetLoRaModulationParameters(uint8_t *out) 00391 { 00392 loraConfig0_t cfg0; 00393 memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword); 00394 00395 out[0] = cfg0.bits.modem_sf; 00396 out[1] = cfg0.bits.modem_bw; 00397 out[2] = cfg0.bits.coding_rate; 00398 out[3] = cfg0.bits.ppm_offset; 00399 } 00400 00401 void SX1265::GetGfskModulationParameters(uint8_t *out) 00402 { 00403 uint32_t u32; 00404 gfskBW_t bw_reg; 00405 gfskConfig0_t cfg0; 00406 uint8_t bwf; 00407 unsigned hz; 00408 00409 memRegRead(REG_ADDR_GFSK_BITRATE, 1, &u32); 00410 hz = GFSK_BITRATE_NUMERATOR / u32; 00411 to_big_endian32(hz, out); 00412 00413 memRegRead(REG_ADDR_GFSK_CFG0, 1, &cfg0.dword); 00414 switch (cfg0.bits.bt) { 00415 case 0: /* off */ out[4] = GFSK_BT_OFF; break; 00416 case 1: /* 0.3 */ out[4] = GFSK_BT_0_3; break; 00417 case 2: /* 0.5 */ out[4] = GFSK_BT_0_5; break; 00418 case 3: /* 0.7 */ out[4] = GFSK_BT_0_7; break; 00419 case 4: /* 1.0 */ out[4] = GFSK_BT_1_0; break; 00420 } 00421 00422 memRegRead(REG_ADDR_GFSK_BWF, 1, &bw_reg.dword); 00423 bwf = bw_reg.bits.bwf_hi; 00424 bwf <<= 3; 00425 bwf |= bw_reg.bits.bwf_lo; 00426 out[5] = bwf; 00427 00428 memRegRead(REG_ADDR_GFSK_FDEV, 1, &u32); 00429 hz = (unsigned) ((u32 * FREQ_STEP) - 0.5); 00430 to_big_endian32(hz, out+6); 00431 } 00432 00433 void SX1265::GetLoRaPacketParameters(uint8_t *out) 00434 { 00435 loraConfig0_t cfg0; 00436 loraConfigA_t cfgA; 00437 loraConfigC_t cfgc; 00438 unsigned pl; 00439 00440 memRegRead(REG_ADDR_LORA_CONFIGC, 1, &cfgc.dword); 00441 pl = cfgc.bits.preamble_length; 00442 out[1] = pl & 0xff; 00443 pl >>= 8; 00444 out[0] = pl; 00445 00446 memRegRead(REG_ADDR_LORA_CONFIG0, 1, &cfg0.dword); 00447 out[2] = cfg0.bits.implicit_header; 00448 out[3] = cfg0.bits.payload_length; 00449 out[4] = cfg0.bits.crc_on; 00450 00451 memRegRead(REG_ADDR_LORA_CONFIGA, 1, &cfgA.dword); 00452 out[5] = cfgA.bits.invertIQ; 00453 } 00454 00455 void SX1265::GetGfskPacketParameters(uint8_t *out) 00456 { 00457 gfskConfig1_t cfg1; 00458 gfskConfig2_t cfg2; 00459 gfskConfig3_t cfg3; 00460 gfskConfig4_t cfg4; 00461 gfskConfig5_t cfg5; 00462 uint32_t u32; 00463 00464 memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword); 00465 00466 u32 = cfg1.bits.preamble_length; 00467 out[1] = u32; 00468 u32 >>= 8; 00469 out[0] = u32; 00470 00471 memRegRead(REG_ADDR_GFSK_CFG1, 1, &cfg1.dword); 00472 if (cfg1.bits.preamble_det_enable) 00473 out[2] = cfg1.bits.preamble_det_len; 00474 else 00475 out[2] = 0; 00476 00477 memRegRead(REG_ADDR_GFSK_CFG2, 1, &cfg2.dword); 00478 out[3] = cfg2.bits.sync_word_length; 00479 00480 memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_B, 1, &cfg4.dword); 00481 out[4] = cfg4.bits.addr_comp; 00482 00483 memRegRead(REG_ADDR_GFSK_CFG3, 1, &cfg3.dword); 00484 out[5] = cfg3.bits.variable_length; 00485 00486 memRegRead(REG_ADDR_GFSK_PAYLOAD_LENGTH_A, 1, &u32); 00487 out[6] = u32 & 0xff; 00488 00489 memRegRead(REG_ADDR_GFSK_CFG5, 1, &cfg5.dword); 00490 00491 if (cfg5.bits.crc_off) 00492 out[7] |= 1; 00493 else 00494 out[7] &= ~1; 00495 00496 if (cfg5.bits.crc_size) 00497 out[7] |= 2; 00498 else 00499 out[7] &= ~2; 00500 00501 if (cfg5.bits.crc_invert) 00502 out[7] |= 4; 00503 else 00504 out[7] &= ~4; 00505 00506 out[8] = cfg5.bits.whitening_enable; 00507 } 00508
Generated on Tue Jul 19 2022 12:22:24 by 1.7.2