Hardware Abstraction Layer, permitting any LoRa application to use any LoRa radio chip

Dependents:   alarm_slave alarm_master lora_p2p lorawan1v1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers radio_lr1110.cpp Source File

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 */