Hardware Abstraction Layer, permitting any LoRa application to use any LoRa radio chip
Dependents: alarm_slave alarm_master lora_p2p lorawan1v1 ... more
radio_lr1110.cpp
00001 #include "radio.h" 00002 #ifdef SX1265_H 00003 #include "SPIu.h" 00004 00005 #ifdef TARGET_FF_ARDUINO 00006 SPI spi(D11, D12, D13); // mosi, miso, sclk 00007 //spi, nss, busy, dio9, nreset 00008 SX1265 Radio::radio(spi, D7, D3, D5, A0); 00009 00010 static void initRfSwDIO() 00011 { 00012 /*stat_t stat;*/ 00013 uint8_t dioBuf[8]; 00014 /* antenna truth table 00015 * V1 V2 port 00016 * 0 0 shutdown 00017 * 1 0 J2 rx RFI 00018 * 0 1 J1 HP tx RFO 00019 * 1 1 J3 LP tx RFO 00020 * DIO5 DIO6 00021 */ 00022 dioBuf[ DIO_en_IDX] = DIO5_BIT | DIO6_BIT; 00023 dioBuf[DIO_stby_IDX] = 0; 00024 dioBuf[ DIO_rx_IDX] = DIO5_BIT; 00025 dioBuf[ DIO_tx_IDX] = DIO5_BIT | DIO6_BIT; 00026 dioBuf[DIO_txhp_IDX] = DIO6_BIT; 00027 dioBuf[DIO_gnss_IDX] = 0; 00028 dioBuf[DIO_wifi_IDX] = 0; 00029 /*stat.word =*/ Radio::radio.xfer(OPCODE_SET_DIO_AS_RFSWITCH, 8, 0, dioBuf); 00030 } 00031 #else 00032 /* declare pins for form-factor */ 00033 #error non-ardiuno-form-factor 00034 #endif /* TARGET_FF_ARDUINO */ 00035 00036 uint8_t gfsk_pp_buf[9]; 00037 uint8_t gfsk_mp_buf[10]; 00038 uint8_t lora_pp_buf[6]; 00039 uint8_t lora_mp_buf[4]; 00040 00041 const RadioEvents_t* RadioEvents; 00042 LowPowerTimer Radio::lpt; 00043 volatile us_timestamp_t Radio::irqAt; 00044 uint8_t Radio::loraTimeoutSymbols; 00045 00046 void Radio::LoRaPacketConfig(unsigned preambleLen, bool fixLen, bool crcOn, bool invIQ) 00047 { 00048 /*stat_t stat;*/ 00049 if (radio.getPacketType() != PACKET_TYPE_LORA) 00050 radio.setPacketType(PACKET_TYPE_LORA); 00051 00052 radio.to_big_endian16(preambleLen, lora_pp_buf); 00053 lora_pp_buf[2] = fixLen; 00054 /* lora_pp_buf[3] = set when txing, initialized to zero in Init */ 00055 lora_pp_buf[4] = crcOn; 00056 lora_pp_buf[5] = invIQ; 00057 /*stat.word =*/ radio.xfer(OPCODE_SET_PACKET_PARAM, 6, 0, lora_pp_buf); 00058 } 00059 00060 void Radio::set_tx_dbm(int8_t dbm) 00061 { 00062 /*stat_t stat;*/ 00063 uint8_t buf[4]; 00064 int8_t txpower; 00065 unsigned PaSel, RegPaSupply, PaDutyCycle, PaHPSel; 00066 00067 if (dbm > 20) { 00068 txpower = 22; 00069 PaSel = 1; 00070 RegPaSupply = 1; 00071 PaDutyCycle = 4; 00072 PaHPSel = 7; 00073 } else if (dbm > 17) { 00074 txpower = 22; 00075 PaSel = 1; 00076 RegPaSupply = 1; 00077 PaDutyCycle = 2; 00078 PaHPSel = 7; 00079 } else if (dbm > 15) { 00080 txpower = 22; 00081 PaSel = 1; 00082 RegPaSupply = 1; 00083 PaDutyCycle = 4; 00084 PaHPSel = 3; 00085 } else { 00086 txpower = 14; 00087 PaSel = 0; 00088 RegPaSupply = 0; 00089 if (dbm > 14) 00090 PaDutyCycle = 7; 00091 else if (dbm > 10) 00092 PaDutyCycle = 4; 00093 else 00094 PaDutyCycle = 0; 00095 PaHPSel = 0; 00096 } 00097 00098 buf[0] = PaSel; 00099 buf[1] = RegPaSupply; 00100 buf[2] = PaDutyCycle; 00101 buf[3] = PaHPSel; 00102 /*stat.word =*/ radio.xfer(OPCODE_SET_PA_CONFIG, 4, 0, buf); 00103 00104 buf[0] = txpower; 00105 buf[1] = 4; 00106 /*stat.word =*/ radio.xfer(OPCODE_SET_TXPARAMS, 2, 0, buf); 00107 } 00108 00109 void Radio::SetChannel(unsigned hz) 00110 { 00111 /*stat_t stat;*/ 00112 uint8_t buf[4]; 00113 radio.to_big_endian32(hz, buf); 00114 /*stat.word =*/ radio.xfer(OPCODE_SET_RF_FREQ_HZ, 4, 0, buf); 00115 } 00116 00117 void Radio::Standby() 00118 { 00119 /*stat_t stat;*/ 00120 uint8_t buf = 0; // 0=rc, 1=xosc 00121 /*stat.word =*/ radio.xfer(OPCODE_SET_STANDBY, 1, 0, &buf); 00122 } 00123 00124 void Radio::LoRaModemConfig(unsigned bwKHz, uint8_t sf, uint8_t cr) 00125 { 00126 /*stat_t stat;*/ 00127 uint8_t buf[4]; 00128 uint8_t ldro = 0; 00129 00130 if (radio.getPacketType() != PACKET_TYPE_LORA) 00131 radio.setPacketType(PACKET_TYPE_LORA); 00132 00133 if (bwKHz > 500) 00134 buf[1] = LORA_BW_1000KHz; 00135 else if (bwKHz > 250) 00136 buf[1] = LORA_BW_500KHz; 00137 else if (bwKHz > 125) { 00138 buf[1] = LORA_BW_250KHz; 00139 } else if (bwKHz > 80) { 00140 buf[1] = LORA_BW_125KHz; 00141 if (sf > 11) 00142 ldro = 1; 00143 } else if (bwKHz > 16) { 00144 buf[1] = LORA_BW_31_25KHz; 00145 if (sf > 10) 00146 ldro = 1; 00147 } else if (bwKHz > 8) { 00148 buf[1] = LORA_BW_15_6KHz; 00149 if (sf > 9) 00150 ldro = 1; 00151 } else { 00152 buf[1] = LORA_BW_7_8KHz; 00153 if (sf > 8) 00154 ldro = 1; 00155 } 00156 00157 buf[0] = sf; 00158 buf[2] = cr; 00159 buf[3] = ldro; 00160 /*stat.word =*/ radio.xfer(OPCODE_SET_MODULATION, 4, 0, buf); 00161 } 00162 00163 int Radio::Send(uint8_t size, timestamp_t maxListenTime, timestamp_t channelFreeTime, int rssiThresh) 00164 { 00165 /*stat_t stat;*/ 00166 uint8_t pktType; 00167 00168 pktType = radio.getPacketType(); 00169 if (pktType == PACKET_TYPE_LORA) { 00170 lora_pp_buf[3] = size; 00171 /*stat.word =*/ radio.xfer(OPCODE_SET_PACKET_PARAM, 6, 0, lora_pp_buf); 00172 } else if (pktType == PACKET_TYPE_GFSK) { 00173 gfsk_pp_buf[6] = size; 00174 /*stat.word =*/ radio.xfer(OPCODE_SET_PACKET_PARAM, 9, 0, gfsk_pp_buf); 00175 } 00176 00177 /* TODO: LBT */ 00178 00179 radio.start_tx(size); 00180 return 0; 00181 } 00182 00183 void Radio::service() 00184 { 00185 irq_t irq; 00186 irq.dword = radio.service(); 00187 if (irq.dword != 0) { 00188 } 00189 } 00190 00191 bool Radio::init_irq; 00192 void Radio::my_irq_handler() 00193 { 00194 /* radio irq immediately after hardware reset: hf_xosc start due to TCXO */ 00195 init_irq = true; 00196 } 00197 00198 void Radio::dio9_top_half() 00199 { 00200 irqAt = lpt.read_us(); 00201 00202 if (RadioEvents->DioPin_top_half) 00203 RadioEvents->DioPin_top_half(); 00204 00205 if (radio.chipMode == CHIPMODE_TX) { 00206 /* TxDone handling requires low latency */ 00207 if (RadioEvents->TxDone_topHalf) { 00208 RadioEvents->TxDone_topHalf(); 00209 } 00210 } else { 00211 #ifdef RX_INDICATION 00212 RX_INDICATION = 0; 00213 #endif 00214 } 00215 } 00216 00217 void Radio::timeout_callback(bool tx) 00218 { 00219 if (!tx) { 00220 if (RadioEvents->RxTimeout) 00221 RadioEvents->RxTimeout(); 00222 } // else TODO tx timeout 00223 } 00224 00225 void Radio::rx_done(uint8_t size, float rssi, float snr) 00226 { 00227 RadioEvents->RxDone(size, rssi, snr); 00228 } 00229 00230 void Radio::txDoneBottom() 00231 { 00232 if (RadioEvents->TxDone_botHalf) 00233 RadioEvents->TxDone_botHalf(); 00234 } 00235 00236 void Radio::Init(const RadioEvents_t* e, unsigned spi_hz) 00237 { 00238 uint64_t a, b; 00239 /* initialize payload length to zero in packet params */ 00240 lora_pp_buf[3] = 0; 00241 gfsk_pp_buf[6] = 0; 00242 00243 radio.txDone = txDoneBottom; 00244 radio.rxDone = rx_done; 00245 radio.timeout = timeout_callback; 00246 //radio.chipModeChange = chipModeChange; 00247 00248 RadioEvents = e; 00249 lpt.start(); 00250 00251 spi.frequency(spi_hz); 00252 00253 radio.dio9_topHalf = my_irq_handler; 00254 init_irq = false; 00255 radio.hw_reset(); 00256 a = Kernel::get_ms_count(); 00257 do { 00258 b = Kernel::get_ms_count(); 00259 /* wait for radio interrupt at hardware reset, failure to start hf_xosc */ 00260 if (init_irq) { 00261 radio.service(); 00262 break; 00263 } 00264 } while ((b - a) < 30); 00265 00266 radio.dio9_topHalf = dio9_top_half; 00267 00268 initRfSwDIO(); 00269 } 00270 00271 void Radio::SetLoRaSymbolTimeout(uint16_t symbs) 00272 { 00273 /*stat_t stat;*/ 00274 if (radio.getPacketType() != PACKET_TYPE_LORA) 00275 radio.setPacketType(PACKET_TYPE_LORA); 00276 00277 loraTimeoutSymbols = symbs; 00278 /*stat.word =*/ radio.xfer(OPCODE_SET_LORA_SYNC_TIMEOUT, 1, 0, &loraTimeoutSymbols); 00279 } 00280 00281 void Radio::Rx(unsigned timeout) 00282 { 00283 /*stat_t stat;*/ 00284 uint8_t buf[3]; 00285 unsigned rx_timeout; 00286 00287 if (radio.getPacketType() == PACKET_TYPE_LORA) { 00288 /*stat.word =*/ radio.xfer(OPCODE_SET_LORA_SYNC_TIMEOUT, 1, 0, &loraTimeoutSymbols); 00289 } 00290 00291 if (timeout == 0) 00292 rx_timeout = 0xffffff; // receive until instructed otherwise 00293 else 00294 rx_timeout = timeout; 00295 00296 radio.to_big_endian24(rx_timeout, buf); 00297 /*stat.word =*/ radio.xfer(OPCODE_SET_RX, 3, 0, buf); 00298 00299 } 00300 00301 #endif /* ..SX126x_H */
Generated on Wed Jul 13 2022 17:56:01 by 1.7.2