mirror of
				https://github.com/liberatedsystems/RNode_Firmware_CE.git
				synced 2024-07-02 14:34:13 +02:00 
			
		
		
		
	Merge branch 'master' of github.com:markqvist/RNode_Firmware
This commit is contained in:
		
						commit
						35515bc7fa
					
				
							
								
								
									
										13
									
								
								Config.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Config.h
									
									
									
									
									
								
							@ -315,9 +315,8 @@
 | 
				
			|||||||
            #define HAS_NP false
 | 
					            #define HAS_NP false
 | 
				
			||||||
            #define HAS_SD false
 | 
					            #define HAS_SD false
 | 
				
			||||||
            #define HAS_TCXO true
 | 
					            #define HAS_TCXO true
 | 
				
			||||||
            #define HAS_RXEN_BUSY true
 | 
					            #define HAS_RF_SWITCH_RX_TX true
 | 
				
			||||||
            #define MODEM SX1262 
 | 
					            #define HAS_BUSY true
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            #define CONFIG_UART_BUFFER_SIZE 6144
 | 
					            #define CONFIG_UART_BUFFER_SIZE 6144
 | 
				
			||||||
            #define CONFIG_QUEUE_SIZE 6144
 | 
					            #define CONFIG_QUEUE_SIZE 6144
 | 
				
			||||||
            #define CONFIG_QUEUE_MAX_LENGTH 200
 | 
					            #define CONFIG_QUEUE_MAX_LENGTH 200
 | 
				
			||||||
@ -351,12 +350,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	#define eeprom_addr(a) (a+EEPROM_OFFSET)
 | 
						#define eeprom_addr(a) (a+EEPROM_OFFSET)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #ifndef HAS_RXEN_BUSY
 | 
					    #ifndef HAS_RF_SWITCH_RX_TX
 | 
				
			||||||
        const int pin_rxen = -1;
 | 
					        const int pin_rxen = -1;
 | 
				
			||||||
 | 
					        const int pin_txen = -1;
 | 
				
			||||||
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #ifndef HAS_BUSY
 | 
				
			||||||
        const int pin_busy = -1;
 | 
					        const int pin_busy = -1;
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if MODEM == SX1262 && defined(NRF52840_XXAA)
 | 
					    #if (MODEM == SX1262 || MODEM == SX1280) && defined(NRF52840_XXAA)
 | 
				
			||||||
        SPIClass spiModem(NRF_SPIM2, pin_miso, pin_sclk, pin_mosi);
 | 
					        SPIClass spiModem(NRF_SPIM2, pin_miso, pin_sclk, pin_mosi);
 | 
				
			||||||
    #endif
 | 
					    #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								Modem.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Modem.h
									
									
									
									
									
								
							@ -1,3 +1,4 @@
 | 
				
			|||||||
#define SX1276 0x01
 | 
					#define SX1276 0x01
 | 
				
			||||||
#define SX1278 0x02
 | 
					#define SX1278 0x02
 | 
				
			||||||
#define SX1262 0x03
 | 
					#define SX1262 0x03
 | 
				
			||||||
 | 
					#define SX1280 0x04
 | 
				
			||||||
 | 
				
			|||||||
@ -93,16 +93,22 @@ void setup() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Set chip select, reset and interrupt
 | 
					  // Set chip select, reset and interrupt
 | 
				
			||||||
  // pins for the LoRa module
 | 
					  // pins for the LoRa module
 | 
				
			||||||
  LoRa.setPins(pin_cs, pin_reset, pin_dio, pin_rxen, pin_busy);
 | 
					  #if MODEM == SX1276 || MODEM == SX1278
 | 
				
			||||||
 | 
					  LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy);
 | 
				
			||||||
 | 
					  #elif MODEM == SX1262
 | 
				
			||||||
 | 
					  LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy, pin_rxen);
 | 
				
			||||||
 | 
					  #elif MODEM == SX1280
 | 
				
			||||||
 | 
					  LoRa->setPins(pin_cs, pin_reset, pin_dio, pin_busy, pin_rxen, pin_txen);
 | 
				
			||||||
 | 
					  #endif
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  #if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
 | 
					  #if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
 | 
				
			||||||
    init_channel_stats();
 | 
					    init_channel_stats();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check installed transceiver chip and
 | 
					    // Check installed transceiver chip and
 | 
				
			||||||
    // probe boot parameters.
 | 
					    // probe boot parameters.
 | 
				
			||||||
    if (LoRa.preInit()) {
 | 
					    if (LoRa->preInit()) {
 | 
				
			||||||
      modem_installed = true;
 | 
					      modem_installed = true;
 | 
				
			||||||
      uint32_t lfr = LoRa.getFrequency();
 | 
					      uint32_t lfr = LoRa->getFrequency();
 | 
				
			||||||
      if (lfr == 0) {
 | 
					      if (lfr == 0) {
 | 
				
			||||||
        // Normal boot
 | 
					        // Normal boot
 | 
				
			||||||
      } else if (lfr == M_FRQ_R) {
 | 
					      } else if (lfr == M_FRQ_R) {
 | 
				
			||||||
@ -115,7 +121,7 @@ void setup() {
 | 
				
			|||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // Unknown boot
 | 
					        // Unknown boot
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      LoRa.setFrequency(M_FRQ_S);
 | 
					      LoRa->setFrequency(M_FRQ_S);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      modem_installed = false;
 | 
					      modem_installed = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -158,14 +164,14 @@ void setup() {
 | 
				
			|||||||
  // Validate board health, EEPROM and config
 | 
					  // Validate board health, EEPROM and config
 | 
				
			||||||
  validate_status();
 | 
					  validate_status();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (op_mode != MODE_TNC) LoRa.setFrequency(0);
 | 
					  if (op_mode != MODE_TNC) LoRa->setFrequency(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lora_receive() {
 | 
					void lora_receive() {
 | 
				
			||||||
  if (!implicit) {
 | 
					  if (!implicit) {
 | 
				
			||||||
    LoRa.receive();
 | 
					    LoRa->receive();
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    LoRa.receive(implicit_l);
 | 
					    LoRa->receive(implicit_l);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -187,7 +193,7 @@ inline void kiss_write_packet() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
inline void getPacketData(uint16_t len) {
 | 
					inline void getPacketData(uint16_t len) {
 | 
				
			||||||
  while (len-- && read_len < MTU) {
 | 
					  while (len-- && read_len < MTU) {
 | 
				
			||||||
    pbuf[read_len++] = LoRa.read();
 | 
					    pbuf[read_len++] = LoRa->read();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -198,7 +204,7 @@ void ISR_VECT receive_callback(int packet_size) {
 | 
				
			|||||||
    // by combining two raw LoRa packets.
 | 
					    // by combining two raw LoRa packets.
 | 
				
			||||||
    // We read the 1-byte header and extract
 | 
					    // We read the 1-byte header and extract
 | 
				
			||||||
    // packet sequence number and split flags
 | 
					    // packet sequence number and split flags
 | 
				
			||||||
    uint8_t header   = LoRa.read(); packet_size--;
 | 
					    uint8_t header   = LoRa->read(); packet_size--;
 | 
				
			||||||
    uint8_t sequence = packetSequence(header);
 | 
					    uint8_t sequence = packetSequence(header);
 | 
				
			||||||
    bool    ready    = false;
 | 
					    bool    ready    = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -210,8 +216,8 @@ void ISR_VECT receive_callback(int packet_size) {
 | 
				
			|||||||
      seq = sequence;
 | 
					      seq = sequence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
					      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
				
			||||||
        last_rssi = LoRa.packetRssi();
 | 
					        last_rssi = LoRa->packetRssi();
 | 
				
			||||||
        last_snr_raw = LoRa.packetSnrRaw();
 | 
					        last_snr_raw = LoRa->packetSnrRaw();
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      getPacketData(packet_size);
 | 
					      getPacketData(packet_size);
 | 
				
			||||||
@ -223,8 +229,8 @@ void ISR_VECT receive_callback(int packet_size) {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
					      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
				
			||||||
        last_rssi = (last_rssi+LoRa.packetRssi())/2;
 | 
					        last_rssi = (last_rssi+LoRa->packetRssi())/2;
 | 
				
			||||||
        last_snr_raw = (last_snr_raw+LoRa.packetSnrRaw())/2;
 | 
					        last_snr_raw = (last_snr_raw+LoRa->packetSnrRaw())/2;
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      getPacketData(packet_size);
 | 
					      getPacketData(packet_size);
 | 
				
			||||||
@ -241,8 +247,8 @@ void ISR_VECT receive_callback(int packet_size) {
 | 
				
			|||||||
      seq = sequence;
 | 
					      seq = sequence;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
					      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
				
			||||||
        last_rssi = LoRa.packetRssi();
 | 
					        last_rssi = LoRa->packetRssi();
 | 
				
			||||||
        last_snr_raw = LoRa.packetSnrRaw();
 | 
					        last_snr_raw = LoRa->packetSnrRaw();
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      getPacketData(packet_size);
 | 
					      getPacketData(packet_size);
 | 
				
			||||||
@ -260,8 +266,8 @@ void ISR_VECT receive_callback(int packet_size) {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
					      #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
				
			||||||
        last_rssi = LoRa.packetRssi();
 | 
					        last_rssi = LoRa->packetRssi();
 | 
				
			||||||
        last_snr_raw = LoRa.packetSnrRaw();
 | 
					        last_snr_raw = LoRa->packetSnrRaw();
 | 
				
			||||||
      #endif
 | 
					      #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      getPacketData(packet_size);
 | 
					      getPacketData(packet_size);
 | 
				
			||||||
@ -287,8 +293,8 @@ void ISR_VECT receive_callback(int packet_size) {
 | 
				
			|||||||
    read_len = 0;
 | 
					    read_len = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
					    #if MCU_VARIANT != MCU_ESP32 && MCU_VARIANT != MCU_NRF52
 | 
				
			||||||
      last_rssi = LoRa.packetRssi();
 | 
					      last_rssi = LoRa->packetRssi();
 | 
				
			||||||
      last_snr_raw = LoRa.packetSnrRaw();
 | 
					      last_snr_raw = LoRa->packetSnrRaw();
 | 
				
			||||||
      getPacketData(packet_size);
 | 
					      getPacketData(packet_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // We first signal the RSSI of the
 | 
					      // We first signal the RSSI of the
 | 
				
			||||||
@ -310,7 +316,7 @@ bool startRadio() {
 | 
				
			|||||||
  update_radio_lock();
 | 
					  update_radio_lock();
 | 
				
			||||||
  if (!radio_online && !console_active) {
 | 
					  if (!radio_online && !console_active) {
 | 
				
			||||||
    if (!radio_locked && hw_ready) {
 | 
					    if (!radio_locked && hw_ready) {
 | 
				
			||||||
      if (!LoRa.begin(lora_freq)) {
 | 
					      if (!LoRa->begin(lora_freq)) {
 | 
				
			||||||
        // The radio could not be started.
 | 
					        // The radio could not be started.
 | 
				
			||||||
        // Indicate this failure over both the
 | 
					        // Indicate this failure over both the
 | 
				
			||||||
        // serial port and with the onboard LEDs
 | 
					        // serial port and with the onboard LEDs
 | 
				
			||||||
@ -329,9 +335,9 @@ bool startRadio() {
 | 
				
			|||||||
        setCodingRate();
 | 
					        setCodingRate();
 | 
				
			||||||
        getFrequency();
 | 
					        getFrequency();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LoRa.enableCrc();
 | 
					        LoRa->enableCrc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        LoRa.onReceive(receive_callback);
 | 
					        LoRa->onReceive(receive_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        lora_receive();
 | 
					        lora_receive();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -360,7 +366,7 @@ bool startRadio() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void stopRadio() {
 | 
					void stopRadio() {
 | 
				
			||||||
  LoRa.end();
 | 
					  LoRa->end();
 | 
				
			||||||
  radio_online = false;
 | 
					  radio_online = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -469,23 +475,23 @@ void transmit(uint16_t size) {
 | 
				
			|||||||
        header = header | FLAG_SPLIT;
 | 
					        header = header | FLAG_SPLIT;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      LoRa.beginPacket();
 | 
					      LoRa->beginPacket();
 | 
				
			||||||
      LoRa.write(header); written++;
 | 
					      LoRa->write(header); written++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (uint16_t i=0; i < size; i++) {
 | 
					      for (uint16_t i=0; i < size; i++) {
 | 
				
			||||||
        LoRa.write(tbuf[i]);
 | 
					        LoRa->write(tbuf[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        written++;
 | 
					        written++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (written == 255) {
 | 
					        if (written == 255) {
 | 
				
			||||||
          LoRa.endPacket(); add_airtime(written);
 | 
					          LoRa->endPacket(); add_airtime(written);
 | 
				
			||||||
          LoRa.beginPacket();
 | 
					          LoRa->beginPacket();
 | 
				
			||||||
          LoRa.write(header);
 | 
					          LoRa->write(header);
 | 
				
			||||||
          written = 1;
 | 
					          written = 1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      LoRa.endPacket(); add_airtime(written);
 | 
					      LoRa->endPacket(); add_airtime(written);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      // In promiscuous mode, we only send out
 | 
					      // In promiscuous mode, we only send out
 | 
				
			||||||
      // plain raw LoRa packets with a maximum
 | 
					      // plain raw LoRa packets with a maximum
 | 
				
			||||||
@ -501,17 +507,17 @@ void transmit(uint16_t size) {
 | 
				
			|||||||
      // If implicit header mode has been set,
 | 
					      // If implicit header mode has been set,
 | 
				
			||||||
      // set packet length to payload data length
 | 
					      // set packet length to payload data length
 | 
				
			||||||
      if (!implicit) {
 | 
					      if (!implicit) {
 | 
				
			||||||
        LoRa.beginPacket();
 | 
					        LoRa->beginPacket();
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        LoRa.beginPacket(size);
 | 
					        LoRa->beginPacket(size);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      for (uint16_t i=0; i < size; i++) {
 | 
					      for (uint16_t i=0; i < size; i++) {
 | 
				
			||||||
        LoRa.write(tbuf[i]);
 | 
					        LoRa->write(tbuf[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        written++;
 | 
					        written++;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      LoRa.endPacket(); add_airtime(written);
 | 
					      LoRa->endPacket(); add_airtime(written);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    kiss_indicate_error(ERROR_TXFAILED);
 | 
					    kiss_indicate_error(ERROR_TXFAILED);
 | 
				
			||||||
@ -631,7 +637,7 @@ void serialCallback(uint8_t sbyte) {
 | 
				
			|||||||
        kiss_indicate_spreadingfactor();
 | 
					        kiss_indicate_spreadingfactor();
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        int sf = sbyte;
 | 
					        int sf = sbyte;
 | 
				
			||||||
        if (sf < 6) sf = 6;
 | 
					        if (sf < 5) sf = 5;
 | 
				
			||||||
        if (sf > 12) sf = 12;
 | 
					        if (sf > 12) sf = 12;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        lora_sf = sf;
 | 
					        lora_sf = sf;
 | 
				
			||||||
@ -938,8 +944,8 @@ void updateModemStatus() {
 | 
				
			|||||||
    portENTER_CRITICAL();
 | 
					    portENTER_CRITICAL();
 | 
				
			||||||
  #endif
 | 
					  #endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint8_t status = LoRa.modemStatus();
 | 
					  uint8_t status = LoRa->modemStatus();
 | 
				
			||||||
  current_rssi = LoRa.currentRssi();
 | 
					  current_rssi = LoRa->currentRssi();
 | 
				
			||||||
  last_status_update = millis();
 | 
					  last_status_update = millis();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if MCU_VARIANT == MCU_ESP32
 | 
					  #if MCU_VARIANT == MCU_ESP32
 | 
				
			||||||
@ -1158,8 +1164,8 @@ void loop() {
 | 
				
			|||||||
    #if MCU_VARIANT == MCU_ESP32
 | 
					    #if MCU_VARIANT == MCU_ESP32
 | 
				
			||||||
      if (packet_ready) {
 | 
					      if (packet_ready) {
 | 
				
			||||||
        portENTER_CRITICAL(&update_lock);
 | 
					        portENTER_CRITICAL(&update_lock);
 | 
				
			||||||
        last_rssi = LoRa.packetRssi();
 | 
					        last_rssi = LoRa->packetRssi();
 | 
				
			||||||
        last_snr_raw = LoRa.packetSnrRaw();
 | 
					        last_snr_raw = LoRa->packetSnrRaw();
 | 
				
			||||||
        portEXIT_CRITICAL(&update_lock);
 | 
					        portEXIT_CRITICAL(&update_lock);
 | 
				
			||||||
        kiss_indicate_stat_rssi();
 | 
					        kiss_indicate_stat_rssi();
 | 
				
			||||||
        kiss_indicate_stat_snr();
 | 
					        kiss_indicate_stat_snr();
 | 
				
			||||||
@ -1173,8 +1179,8 @@ void loop() {
 | 
				
			|||||||
    #elif MCU_VARIANT == MCU_NRF52
 | 
					    #elif MCU_VARIANT == MCU_NRF52
 | 
				
			||||||
      if (packet_ready) {
 | 
					      if (packet_ready) {
 | 
				
			||||||
        portENTER_CRITICAL();
 | 
					        portENTER_CRITICAL();
 | 
				
			||||||
        last_rssi = LoRa.packetRssi();
 | 
					        last_rssi = LoRa->packetRssi();
 | 
				
			||||||
        last_snr_raw = LoRa.packetSnrRaw();
 | 
					        last_snr_raw = LoRa->packetSnrRaw();
 | 
				
			||||||
        portEXIT_CRITICAL();
 | 
					        portEXIT_CRITICAL();
 | 
				
			||||||
        kiss_indicate_stat_rssi();
 | 
					        kiss_indicate_stat_rssi();
 | 
				
			||||||
        kiss_indicate_stat_snr();
 | 
					        kiss_indicate_stat_snr();
 | 
				
			||||||
@ -1199,7 +1205,7 @@ void loop() {
 | 
				
			|||||||
              }
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (!dcd) {
 | 
					              if (!dcd) {
 | 
				
			||||||
                uint8_t csma_r = (uint8_t)random(256);
 | 
					                uint8_t csma_r = (uint8_t)random(20); // updated to increase bitrate: todo check
 | 
				
			||||||
                if (csma_p >= csma_r) {
 | 
					                if (csma_p >= csma_r) {
 | 
				
			||||||
                  flushQueue();
 | 
					                  flushQueue();
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										67
									
								
								Utilities.h
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								Utilities.h
									
									
									
									
									
								
							@ -22,7 +22,18 @@
 | 
				
			|||||||
    int written_bytes = 0;
 | 
					    int written_bytes = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
#include "LoRa.h"
 | 
					
 | 
				
			||||||
 | 
					#if MODEM == SX1262
 | 
				
			||||||
 | 
					#include "sx126x.h"
 | 
				
			||||||
 | 
					sx126x *LoRa = &sx126x_modem;
 | 
				
			||||||
 | 
					#elif MODEM == SX1276 || MODEM == SX1278
 | 
				
			||||||
 | 
					#include "sx127x.h"
 | 
				
			||||||
 | 
					sx127x *LoRa = &sx127x_modem;
 | 
				
			||||||
 | 
					#elif MODEM == SX1280
 | 
				
			||||||
 | 
					#include "sx128x.h"
 | 
				
			||||||
 | 
					sx128x *LoRa = &sx128x_modem;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ROM.h"
 | 
					#include "ROM.h"
 | 
				
			||||||
#include "Framing.h"
 | 
					#include "Framing.h"
 | 
				
			||||||
#include "MD5.h"
 | 
					#include "MD5.h"
 | 
				
			||||||
@ -657,11 +668,7 @@ void kiss_indicate_stat_tx() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void kiss_indicate_stat_rssi() {
 | 
					void kiss_indicate_stat_rssi() {
 | 
				
			||||||
    #if MODEM == SX1276 || MODEM == SX1278
 | 
					 | 
				
			||||||
    uint8_t packet_rssi_val = (uint8_t)(last_rssi+rssi_offset);
 | 
					    uint8_t packet_rssi_val = (uint8_t)(last_rssi+rssi_offset);
 | 
				
			||||||
    #elif MODEM == SX1262
 | 
					 | 
				
			||||||
        int8_t packet_rssi_val = (int8_t)(last_rssi+rssi_offset);
 | 
					 | 
				
			||||||
    #endif
 | 
					 | 
				
			||||||
	serial_write(FEND);
 | 
						serial_write(FEND);
 | 
				
			||||||
	serial_write(CMD_STAT_RSSI);
 | 
						serial_write(CMD_STAT_RSSI);
 | 
				
			||||||
	escaped_serial_write(packet_rssi_val);
 | 
						escaped_serial_write(packet_rssi_val);
 | 
				
			||||||
@ -975,7 +982,7 @@ inline uint8_t packetSequence(uint8_t header) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setPreamble() {
 | 
					void setPreamble() {
 | 
				
			||||||
	if (radio_online) LoRa.setPreambleLength(lora_preamble_symbols);
 | 
						if (radio_online) LoRa->setPreambleLength(lora_preamble_symbols);
 | 
				
			||||||
	kiss_indicate_phy_stats();
 | 
						kiss_indicate_phy_stats();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1002,12 +1009,12 @@ void updateBitrate() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setSpreadingFactor() {
 | 
					void setSpreadingFactor() {
 | 
				
			||||||
	if (radio_online) LoRa.setSpreadingFactor(lora_sf);
 | 
						if (radio_online) LoRa->setSpreadingFactor(lora_sf);
 | 
				
			||||||
	updateBitrate();
 | 
						updateBitrate();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setCodingRate() {
 | 
					void setCodingRate() {
 | 
				
			||||||
	if (radio_online) LoRa.setCodingRate4(lora_cr);
 | 
						if (radio_online) LoRa->setCodingRate4(lora_cr);
 | 
				
			||||||
	updateBitrate();
 | 
						updateBitrate();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1021,66 +1028,66 @@ void set_implicit_length(uint8_t len) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int getTxPower() {
 | 
					int getTxPower() {
 | 
				
			||||||
	uint8_t txp = LoRa.getTxPower();
 | 
						uint8_t txp = LoRa->getTxPower();
 | 
				
			||||||
	return (int)txp;
 | 
						return (int)txp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setTXPower() {
 | 
					void setTXPower() {
 | 
				
			||||||
	if (radio_online) {
 | 
						if (radio_online) {
 | 
				
			||||||
		if (model == MODEL_A2) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_A2) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_A3) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
 | 
							if (model == MODEL_A3) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
 | 
				
			||||||
		if (model == MODEL_A4) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
 | 
							if (model == MODEL_A4) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
 | 
				
			||||||
		if (model == MODEL_A7) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_A7) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_A8) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_A8) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_A9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_A9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (model == MODEL_B3) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_B3) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_B4) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_B4) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_B8) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_B8) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_B9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_B9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (model == MODEL_C4) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_C4) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_C9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_C9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (model == MODEL_E4) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_E4) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_E9) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_E9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (model == MODEL_FE) LoRa.setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
							if (model == MODEL_FE) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
		if (model == MODEL_FF) LoRa.setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
 | 
							if (model == MODEL_FF) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void getBandwidth() {
 | 
					void getBandwidth() {
 | 
				
			||||||
	if (radio_online) {
 | 
						if (radio_online) {
 | 
				
			||||||
			lora_bw = LoRa.getSignalBandwidth();
 | 
								lora_bw = LoRa->getSignalBandwidth();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	updateBitrate();
 | 
						updateBitrate();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setBandwidth() {
 | 
					void setBandwidth() {
 | 
				
			||||||
	if (radio_online) {
 | 
						if (radio_online) {
 | 
				
			||||||
		LoRa.setSignalBandwidth(lora_bw);
 | 
							LoRa->setSignalBandwidth(lora_bw);
 | 
				
			||||||
		getBandwidth();
 | 
							getBandwidth();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void getFrequency() {
 | 
					void getFrequency() {
 | 
				
			||||||
	if (radio_online) {
 | 
						if (radio_online) {
 | 
				
			||||||
		lora_freq = LoRa.getFrequency();
 | 
							lora_freq = LoRa->getFrequency();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void setFrequency() {
 | 
					void setFrequency() {
 | 
				
			||||||
	if (radio_online) {
 | 
						if (radio_online) {
 | 
				
			||||||
		LoRa.setFrequency(lora_freq);
 | 
							LoRa->setFrequency(lora_freq);
 | 
				
			||||||
		getFrequency();
 | 
							getFrequency();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t getRandom() {
 | 
					uint8_t getRandom() {
 | 
				
			||||||
	if (radio_online) {
 | 
						if (radio_online) {
 | 
				
			||||||
		return LoRa.random();
 | 
							return LoRa->random();
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return 0x00;
 | 
							return 0x00;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										915
									
								
								sx126x.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										915
									
								
								sx126x.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,915 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Modifications and additions copyright 2023 by Mark Qvist
 | 
				
			||||||
 | 
					// Obviously still under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sx126x.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MCU_1284P 0x91
 | 
				
			||||||
 | 
					#define MCU_2560  0x92
 | 
				
			||||||
 | 
					#define MCU_ESP32 0x81
 | 
				
			||||||
 | 
					#define MCU_NRF52 0x71
 | 
				
			||||||
 | 
					#if defined(__AVR_ATmega1284P__)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_AVR
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_1284P
 | 
				
			||||||
 | 
					#elif defined(__AVR_ATmega2560__)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_AVR
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_2560
 | 
				
			||||||
 | 
					#elif defined(ESP32)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_ESP32
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_ESP32
 | 
				
			||||||
 | 
					#elif defined(NRF52840_XXAA)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_NRF52
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_NRF52
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MCU_VARIANT
 | 
				
			||||||
 | 
					  #error No MCU variant defined, cannot compile
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if MCU_VARIANT == MCU_ESP32
 | 
				
			||||||
 | 
					  #include "soc/rtc_wdt.h"
 | 
				
			||||||
 | 
					  #define ISR_VECT IRAM_ATTR
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  #define ISR_VECT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OP_RF_FREQ_6X               0x86
 | 
				
			||||||
 | 
					#define OP_SLEEP_6X                 0x84
 | 
				
			||||||
 | 
					#define OP_STANDBY_6X               0x80
 | 
				
			||||||
 | 
					#define OP_TX_6X                    0x83
 | 
				
			||||||
 | 
					#define OP_RX_6X                    0x82
 | 
				
			||||||
 | 
					#define OP_PA_CONFIG_6X             0x95
 | 
				
			||||||
 | 
					#define OP_SET_IRQ_FLAGS_6X         0x08 // also provides info such as
 | 
				
			||||||
 | 
					                                      // preamble detection, etc for
 | 
				
			||||||
 | 
					                                      // knowing when it's safe to switch
 | 
				
			||||||
 | 
					                                      // antenna modes
 | 
				
			||||||
 | 
					#define OP_CLEAR_IRQ_STATUS_6X      0x02
 | 
				
			||||||
 | 
					#define OP_GET_IRQ_STATUS_6X        0x12
 | 
				
			||||||
 | 
					#define OP_RX_BUFFER_STATUS_6X      0x13
 | 
				
			||||||
 | 
					#define OP_PACKET_STATUS_6X         0x14 // get snr & rssi of last packet
 | 
				
			||||||
 | 
					#define OP_CURRENT_RSSI_6X          0x15
 | 
				
			||||||
 | 
					#define OP_MODULATION_PARAMS_6X     0x8B // bw, sf, cr, etc.
 | 
				
			||||||
 | 
					#define OP_PACKET_PARAMS_6X         0x8C // crc, preamble, payload length, etc.
 | 
				
			||||||
 | 
					#define OP_STATUS_6X                0xC0
 | 
				
			||||||
 | 
					#define OP_TX_PARAMS_6X             0x8E // set dbm, etc
 | 
				
			||||||
 | 
					#define OP_PACKET_TYPE_6X           0x8A
 | 
				
			||||||
 | 
					#define OP_BUFFER_BASE_ADDR_6X      0x8F
 | 
				
			||||||
 | 
					#define OP_READ_REGISTER_6X         0x1D
 | 
				
			||||||
 | 
					#define OP_WRITE_REGISTER_6X        0x0D
 | 
				
			||||||
 | 
					#define OP_DIO3_TCXO_CTRL_6X        0x97
 | 
				
			||||||
 | 
					#define OP_DIO2_RF_CTRL_6X          0x9D
 | 
				
			||||||
 | 
					#define OP_CALIBRATE_6X             0x89
 | 
				
			||||||
 | 
					#define IRQ_TX_DONE_MASK_6X         0x01
 | 
				
			||||||
 | 
					#define IRQ_RX_DONE_MASK_6X         0x02
 | 
				
			||||||
 | 
					#define IRQ_HEADER_DET_MASK_6X      0x10
 | 
				
			||||||
 | 
					#define IRQ_PAYLOAD_CRC_ERROR_MASK_6X 0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MODE_LONG_RANGE_MODE_6X     0x01
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OP_FIFO_WRITE_6X            0x0E
 | 
				
			||||||
 | 
					#define OP_FIFO_READ_6X             0x1E
 | 
				
			||||||
 | 
					#define REG_OCP_6X                0x08E7
 | 
				
			||||||
 | 
					#define REG_LNA_6X                0x08AC // no agc in sx1262
 | 
				
			||||||
 | 
					#define REG_SYNC_WORD_MSB_6X      0x0740
 | 
				
			||||||
 | 
					#define REG_SYNC_WORD_LSB_6X      0x0741
 | 
				
			||||||
 | 
					#define REG_PAYLOAD_LENGTH_6X     0x0702 // https://github.com/beegee-tokyo/SX126x-Arduino/blob/master/src/radio/sx126x/sx126x.h#L98
 | 
				
			||||||
 | 
					#define REG_RANDOM_GEN_6X         0x0819
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MODE_TCXO_3_3V_6X           0x07
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define IRQ_PREAMBLE_DET_MASK_6X    0x04
 | 
				
			||||||
 | 
					#define XTAL_FREQ_6X (double)32000000
 | 
				
			||||||
 | 
					#define FREQ_DIV_6X (double)pow(2.0, 25.0)
 | 
				
			||||||
 | 
					#define FREQ_STEP_6X (double)(XTAL_FREQ_6X / FREQ_DIV_6X)
 | 
				
			||||||
 | 
					extern SPIClass spiModem;
 | 
				
			||||||
 | 
					#define SPI spiModem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern SPIClass SPI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_PKT_LENGTH           255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sx126x::sx126x() :
 | 
				
			||||||
 | 
					  _spiSettings(8E6, MSBFIRST, SPI_MODE0),
 | 
				
			||||||
 | 
					  _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), _busy(LORA_DEFAULT_BUSY_PIN), _rxen(LORA_DEFAULT_RXEN_PIN),
 | 
				
			||||||
 | 
					  _frequency(0),
 | 
				
			||||||
 | 
					  _txp(0),
 | 
				
			||||||
 | 
					  _sf(0x07),
 | 
				
			||||||
 | 
					  _bw(0x04),
 | 
				
			||||||
 | 
					  _cr(0x01),
 | 
				
			||||||
 | 
					  _ldro(0x00),
 | 
				
			||||||
 | 
					  _packetIndex(0),
 | 
				
			||||||
 | 
					  _preambleLength(18),
 | 
				
			||||||
 | 
					  _implicitHeaderMode(0),
 | 
				
			||||||
 | 
					  _payloadLength(255),
 | 
				
			||||||
 | 
					  _crcMode(1),
 | 
				
			||||||
 | 
					  _fifo_tx_addr_ptr(0),
 | 
				
			||||||
 | 
					  _fifo_rx_addr_ptr(0),
 | 
				
			||||||
 | 
					  _packet({0}),
 | 
				
			||||||
 | 
					  _preinit_done(false),
 | 
				
			||||||
 | 
					  _onReceive(NULL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // overide Stream timeout value
 | 
				
			||||||
 | 
					  setTimeout(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sx126x::preInit() {
 | 
				
			||||||
 | 
					  // setup pins
 | 
				
			||||||
 | 
					  pinMode(_ss, OUTPUT);
 | 
				
			||||||
 | 
					  // set SS high
 | 
				
			||||||
 | 
					  digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  SPI.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check version (retry for up to 2 seconds)
 | 
				
			||||||
 | 
					  long start = millis();
 | 
				
			||||||
 | 
					  uint8_t syncmsb;
 | 
				
			||||||
 | 
					  uint8_t synclsb;
 | 
				
			||||||
 | 
					  while (((millis() - start) < 2000) && (millis() >= start)) {
 | 
				
			||||||
 | 
					      syncmsb = readRegister(REG_SYNC_WORD_MSB_6X);
 | 
				
			||||||
 | 
					      synclsb = readRegister(REG_SYNC_WORD_LSB_6X);
 | 
				
			||||||
 | 
					      if ( uint16_t(syncmsb << 8 | synclsb) == 0x1424 || uint16_t(syncmsb << 8 | synclsb) == 0x4434) {
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      delay(100);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if ( uint16_t(syncmsb << 8 | synclsb) != 0x1424 && uint16_t(syncmsb << 8 | synclsb) != 0x4434) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _preinit_done = true;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx126x::readRegister(uint16_t address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return singleTransfer(OP_READ_REGISTER_6X, address, 0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::writeRegister(uint16_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    singleTransfer(OP_WRITE_REGISTER_6X, address, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx126x::singleTransfer(uint8_t opcode, uint16_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(opcode);
 | 
				
			||||||
 | 
					    SPI.transfer((address & 0xFF00) >> 8);
 | 
				
			||||||
 | 
					    SPI.transfer(address & 0x00FF);
 | 
				
			||||||
 | 
					    if (opcode == OP_READ_REGISTER_6X) {
 | 
				
			||||||
 | 
					        SPI.transfer(0x00);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    response = SPI.transfer(value);
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return response;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::rxAntEnable()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        uint8_t byte = 0x01;
 | 
				
			||||||
 | 
					        // enable dio2 rf switch
 | 
				
			||||||
 | 
					        executeOpcode(OP_DIO2_RF_CTRL_6X, &byte, 1); 
 | 
				
			||||||
 | 
					        digitalWrite(_rxen, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::loraMode() {
 | 
				
			||||||
 | 
					    // enable lora mode on the SX1262 chip
 | 
				
			||||||
 | 
					    uint8_t mode = MODE_LONG_RANGE_MODE_6X;
 | 
				
			||||||
 | 
					    executeOpcode(OP_PACKET_TYPE_6X, &mode, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::waitOnBusy() {
 | 
				
			||||||
 | 
					    unsigned long time = millis();
 | 
				
			||||||
 | 
					    if (_busy != -1) {
 | 
				
			||||||
 | 
					        while (digitalRead(_busy) == HIGH)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (millis() >= (time + 100)) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // do nothing
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(opcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.transfer(buffer[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(opcode);
 | 
				
			||||||
 | 
					    SPI.transfer(0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        buffer[i] = SPI.transfer(0x00);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::writeBuffer(const uint8_t* buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(OP_FIFO_WRITE_6X);
 | 
				
			||||||
 | 
					    SPI.transfer(_fifo_tx_addr_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.transfer(buffer[i]);
 | 
				
			||||||
 | 
					        _fifo_tx_addr_ptr++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::readBuffer(uint8_t* buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(OP_FIFO_READ_6X);
 | 
				
			||||||
 | 
					    SPI.transfer(_fifo_rx_addr_ptr);
 | 
				
			||||||
 | 
					    SPI.transfer(0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        buffer[i] = SPI.transfer(0x00);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro) {
 | 
				
			||||||
 | 
					  // because there is no access to these registers on the sx1262, we have
 | 
				
			||||||
 | 
					  // to set all these parameters at once or not at all.
 | 
				
			||||||
 | 
					  uint8_t buf[8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = sf;
 | 
				
			||||||
 | 
					  buf[1] = bw;
 | 
				
			||||||
 | 
					  buf[2] = cr; 
 | 
				
			||||||
 | 
					  // low data rate toggle
 | 
				
			||||||
 | 
					  buf[3] = ldro;
 | 
				
			||||||
 | 
					  // unused params in LoRa mode
 | 
				
			||||||
 | 
					  buf[4] = 0x00; 
 | 
				
			||||||
 | 
					  buf[5] = 0x00;
 | 
				
			||||||
 | 
					  buf[6] = 0x00;
 | 
				
			||||||
 | 
					  buf[7] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  executeOpcode(OP_MODULATION_PARAMS_6X, buf, 8);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setPacketParams(long preamble, uint8_t headermode, uint8_t length, uint8_t crc) {
 | 
				
			||||||
 | 
					  // because there is no access to these registers on the sx1262, we have
 | 
				
			||||||
 | 
					  // to set all these parameters at once or not at all.
 | 
				
			||||||
 | 
					  uint8_t buf[9];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = uint8_t((preamble & 0xFF00) >> 8);
 | 
				
			||||||
 | 
					  buf[1] = uint8_t((preamble & 0x00FF));
 | 
				
			||||||
 | 
					  buf[2] = headermode;
 | 
				
			||||||
 | 
					  buf[3] = length;
 | 
				
			||||||
 | 
					  buf[4] = crc;
 | 
				
			||||||
 | 
					  // standard IQ setting (no inversion)
 | 
				
			||||||
 | 
					  buf[5] = 0x00; 
 | 
				
			||||||
 | 
					  // unused params
 | 
				
			||||||
 | 
					  buf[6] = 0x00; 
 | 
				
			||||||
 | 
					  buf[7] = 0x00; 
 | 
				
			||||||
 | 
					  buf[8] = 0x00; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  executeOpcode(OP_PACKET_PARAMS_6X, buf, 9);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx126x::begin(long frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (_reset != -1) {
 | 
				
			||||||
 | 
					    pinMode(_reset, OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // perform reset
 | 
				
			||||||
 | 
					    digitalWrite(_reset, LOW);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					    digitalWrite(_reset, HIGH);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (_busy != -1) {
 | 
				
			||||||
 | 
					      pinMode(_busy, INPUT);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!_preinit_done) {
 | 
				
			||||||
 | 
					    if (!preInit()) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      //#if HAS_TCXO
 | 
				
			||||||
 | 
					          // turn TCXO on
 | 
				
			||||||
 | 
					          enableTCXO();
 | 
				
			||||||
 | 
					      //#endif
 | 
				
			||||||
 | 
					      loraMode();
 | 
				
			||||||
 | 
					      idle();
 | 
				
			||||||
 | 
					      // cannot access registers in sleep mode on sx1262, set to idle instead
 | 
				
			||||||
 | 
					      if (_rxen != -1) {
 | 
				
			||||||
 | 
					          pinMode(_rxen, OUTPUT);
 | 
				
			||||||
 | 
					          rxAntEnable();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // calibrate RC64k, RC13M, PLL, ADC and image
 | 
				
			||||||
 | 
					      uint8_t calibrate = 0x7F; 
 | 
				
			||||||
 | 
					      executeOpcode(OP_CALIBRATE_6X, &calibrate, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setFrequency(frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set output power to 2 dBm
 | 
				
			||||||
 | 
					      setTxPower(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set LNA boost
 | 
				
			||||||
 | 
					      writeRegister(REG_LNA_6X, 0x96);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set base addresses
 | 
				
			||||||
 | 
					      uint8_t basebuf[2] = {0};
 | 
				
			||||||
 | 
					      executeOpcode(OP_BUFFER_BASE_ADDR_6X, basebuf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setModulationParams(_sf, _bw, _cr, _ldro);
 | 
				
			||||||
 | 
					      setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::end()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in sleep mode
 | 
				
			||||||
 | 
					  sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // stop SPI
 | 
				
			||||||
 | 
					  SPI.end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _preinit_done = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx126x::beginPacket(int implicitHeader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in standby mode
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (implicitHeader) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      _payloadLength = 0;
 | 
				
			||||||
 | 
					      _fifo_tx_addr_ptr = 0;
 | 
				
			||||||
 | 
					      setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx126x::endPacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					      setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // put in single TX mode
 | 
				
			||||||
 | 
					      uint8_t timeout[3] = {0};
 | 
				
			||||||
 | 
					      executeOpcode(OP_TX_6X, timeout, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      uint8_t buf[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      buf[0] = 0x00;
 | 
				
			||||||
 | 
					      buf[1] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // wait for TX done
 | 
				
			||||||
 | 
					      while ((buf[1] & IRQ_TX_DONE_MASK_6X) == 0) {
 | 
				
			||||||
 | 
					        buf[0] = 0x00;
 | 
				
			||||||
 | 
					        buf[1] = 0x00;
 | 
				
			||||||
 | 
					        executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
 | 
				
			||||||
 | 
					        yield();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // clear IRQ's
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      uint8_t mask[2];
 | 
				
			||||||
 | 
					      mask[0] = 0x00;
 | 
				
			||||||
 | 
					      mask[1] = IRQ_TX_DONE_MASK_6X;
 | 
				
			||||||
 | 
					      executeOpcode(OP_CLEAR_IRQ_STATUS_6X, mask, 2);
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx126x::modemStatus() {
 | 
				
			||||||
 | 
					    // imitate the register status from the sx1276 / 78
 | 
				
			||||||
 | 
					    uint8_t buf[2] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t clearbuf[2] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t byte = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (buf[1] & IRQ_PREAMBLE_DET_MASK_6X != 0) {
 | 
				
			||||||
 | 
					        byte = byte | 0x01 | 0x04;
 | 
				
			||||||
 | 
					        // clear register after reading
 | 
				
			||||||
 | 
					        clearbuf[1] = IRQ_PREAMBLE_DET_MASK_6X; 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (buf[1] & IRQ_HEADER_DET_MASK_6X != 0) {
 | 
				
			||||||
 | 
					        byte = byte | 0x02 | 0x04;
 | 
				
			||||||
 | 
					        // clear register after reading
 | 
				
			||||||
 | 
					        clearbuf[1] = clearbuf[1] | IRQ_HEADER_DET_MASK_6X; 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_CLEAR_IRQ_STATUS_6X, clearbuf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return byte; 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx126x::currentRssiRaw() {
 | 
				
			||||||
 | 
					    uint8_t byte = 0;
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1);
 | 
				
			||||||
 | 
					    return byte;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx126x::currentRssi() {
 | 
				
			||||||
 | 
					    uint8_t byte = 0;
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1);
 | 
				
			||||||
 | 
					    int rssi = -(int(byte)) / 2;
 | 
				
			||||||
 | 
					    return rssi - RSSI_OFFSET;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx126x::packetRssiRaw() {
 | 
				
			||||||
 | 
					    uint8_t buf[3] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3);
 | 
				
			||||||
 | 
					    return buf[2];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx126x::packetRssi() {
 | 
				
			||||||
 | 
					    // may need more calculations here
 | 
				
			||||||
 | 
					    uint8_t buf[3] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3);
 | 
				
			||||||
 | 
					    int pkt_rssi = -buf[0] / 2;
 | 
				
			||||||
 | 
					    return pkt_rssi - RSSI_OFFSET;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx126x::packetSnrRaw() {
 | 
				
			||||||
 | 
					    uint8_t buf[3] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3);
 | 
				
			||||||
 | 
					    return buf[1];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ISR_VECT sx126x::packetSnr() {
 | 
				
			||||||
 | 
					    uint8_t buf[3] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3);
 | 
				
			||||||
 | 
					    return float(buf[1]) * 0.25;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long sx126x::packetFrequencyError()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // todo: implement this, no idea how to check it on the sx1262
 | 
				
			||||||
 | 
					    const float fError = 0.0;
 | 
				
			||||||
 | 
					    return static_cast<long>(fError);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sx126x::write(uint8_t byte)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return write(&byte, sizeof(byte));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sx126x::write(const uint8_t *buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if ((_payloadLength + size) > MAX_PKT_LENGTH) {
 | 
				
			||||||
 | 
					        size = MAX_PKT_LENGTH - _payloadLength;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // write data
 | 
				
			||||||
 | 
					    writeBuffer(buffer, size);
 | 
				
			||||||
 | 
					    _payloadLength = _payloadLength + size;
 | 
				
			||||||
 | 
					    return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx126x::available()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t buf[2] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, buf, 2);
 | 
				
			||||||
 | 
					    return buf[0] - _packetIndex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx126x::read()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // if received new packet
 | 
				
			||||||
 | 
					  if (_packetIndex == 0) {
 | 
				
			||||||
 | 
					      uint8_t rxbuf[2] = {0};
 | 
				
			||||||
 | 
					      executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2);
 | 
				
			||||||
 | 
					      int size = rxbuf[0];
 | 
				
			||||||
 | 
					      _fifo_rx_addr_ptr = rxbuf[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      readBuffer(_packet, size);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t byte = _packet[_packetIndex];
 | 
				
			||||||
 | 
					  _packetIndex++;
 | 
				
			||||||
 | 
					  return byte;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx126x::peek()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // if received new packet
 | 
				
			||||||
 | 
					  if (_packetIndex == 0) {
 | 
				
			||||||
 | 
					      uint8_t rxbuf[2] = {0};
 | 
				
			||||||
 | 
					      executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2);
 | 
				
			||||||
 | 
					      int size = rxbuf[0];
 | 
				
			||||||
 | 
					      _fifo_rx_addr_ptr = rxbuf[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      readBuffer(_packet, size);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t b = _packet[_packetIndex];
 | 
				
			||||||
 | 
					  return b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::flush()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::onReceive(void(*callback)(int))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _onReceive = callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (callback) {
 | 
				
			||||||
 | 
					    pinMode(_dio0, INPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set preamble and header detection irqs, plus dio0 mask
 | 
				
			||||||
 | 
					    uint8_t buf[8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set irq masks, enable all
 | 
				
			||||||
 | 
					    buf[0] = 0xFF; 
 | 
				
			||||||
 | 
					    buf[1] = 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set dio0 masks
 | 
				
			||||||
 | 
					    buf[2] = 0x00;
 | 
				
			||||||
 | 
					    buf[3] = IRQ_RX_DONE_MASK_6X; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set dio1 masks
 | 
				
			||||||
 | 
					    buf[4] = 0x00; 
 | 
				
			||||||
 | 
					    buf[5] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set dio2 masks
 | 
				
			||||||
 | 
					    buf[6] = 0x00; 
 | 
				
			||||||
 | 
					    buf[7] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_SET_IRQ_FLAGS_6X, buf, 8);
 | 
				
			||||||
 | 
					#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					    SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    attachInterrupt(digitalPinToInterrupt(_dio0), sx126x::onDio0Rise, RISING);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    detachInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					    SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::receive(int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (size > 0) {
 | 
				
			||||||
 | 
					        implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // tell radio payload length
 | 
				
			||||||
 | 
					        _payloadLength = size;
 | 
				
			||||||
 | 
					        setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        explicitHeaderMode();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_rxen != -1) {
 | 
				
			||||||
 | 
					        rxAntEnable();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    uint8_t mode[3] = {0xFF, 0xFF, 0xFF}; // continuous mode
 | 
				
			||||||
 | 
					    executeOpcode(OP_RX_6X, mode, 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::idle()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					      //#if HAS_TCXO
 | 
				
			||||||
 | 
					          // STDBY_XOSC
 | 
				
			||||||
 | 
					          uint8_t byte = 0x01;
 | 
				
			||||||
 | 
					      //#else
 | 
				
			||||||
 | 
					      //    // STDBY_RC
 | 
				
			||||||
 | 
					      //    uint8_t byte = 0x00;
 | 
				
			||||||
 | 
					      //#endif
 | 
				
			||||||
 | 
					      executeOpcode(OP_STANDBY_6X, &byte, 1); 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::sleep()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t byte = 0x00;
 | 
				
			||||||
 | 
					    executeOpcode(OP_SLEEP_6X, &byte, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::enableTCXO() {
 | 
				
			||||||
 | 
					    // only tested for RAK4630, voltage may be different on other platforms
 | 
				
			||||||
 | 
					    uint8_t buf[4] = {MODE_TCXO_3_3V_6X, 0x00, 0x00, 0xFF};
 | 
				
			||||||
 | 
					    executeOpcode(OP_DIO3_TCXO_CTRL_6X, buf, 4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::disableTCXO() {
 | 
				
			||||||
 | 
					    // currently cannot disable on SX1262?
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setTxPower(int level, int outputPin) {
 | 
				
			||||||
 | 
					    // currently no low power mode for SX1262 implemented, assuming PA boost
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // WORKAROUND - Better Resistance of the SX1262 Tx to Antenna Mismatch, see DS_SX1261-2_V1.2 datasheet chapter 15.2
 | 
				
			||||||
 | 
					    // RegTxClampConfig = @address 0x08D8
 | 
				
			||||||
 | 
					    writeRegister(0x08D8, readRegister(0x08D8) | (0x0F << 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t pa_buf[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_buf[0] = 0x04;
 | 
				
			||||||
 | 
					    pa_buf[1] = 0x07;
 | 
				
			||||||
 | 
					    pa_buf[2] = 0x00;
 | 
				
			||||||
 | 
					    pa_buf[3] = 0x01;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_PA_CONFIG_6X, pa_buf, 4); // set pa_config for high power
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (level > 22) {
 | 
				
			||||||
 | 
					        level = 22;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (level < -9) {
 | 
				
			||||||
 | 
					        level = -9;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_OCP_6X, 0x38); // 160mA limit, overcurrent protection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t tx_buf[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tx_buf[0] = level;
 | 
				
			||||||
 | 
					    tx_buf[1] = 0x02; // ramping time - 40 microseconds
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    executeOpcode(OP_TX_PARAMS_6X, tx_buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _txp = level;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx126x::getTxPower() {
 | 
				
			||||||
 | 
					    return _txp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setFrequency(long frequency) {
 | 
				
			||||||
 | 
					  _frequency = frequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t buf[4];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t freq = (uint32_t)((double)frequency / (double)FREQ_STEP_6X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = ((freq >> 24) & 0xFF);
 | 
				
			||||||
 | 
					  buf[1] = ((freq >> 16) & 0xFF);
 | 
				
			||||||
 | 
					  buf[2] = ((freq >> 8) & 0xFF);
 | 
				
			||||||
 | 
					  buf[3] = (freq & 0xFF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  executeOpcode(OP_RF_FREQ_6X, buf, 4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t sx126x::getFrequency() {
 | 
				
			||||||
 | 
					    // we can't read the frequency on the sx1262 / 80
 | 
				
			||||||
 | 
					    uint32_t frequency = _frequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return frequency;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setSpreadingFactor(int sf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (sf < 5) {
 | 
				
			||||||
 | 
					      sf = 5;
 | 
				
			||||||
 | 
					  } else if (sf > 12) {
 | 
				
			||||||
 | 
					    sf = 12;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _sf = sf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setModulationParams(sf, _bw, _cr, _ldro);
 | 
				
			||||||
 | 
					  handleLowDataRate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long sx126x::getSignalBandwidth()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int bw = _bw;
 | 
				
			||||||
 | 
					    switch (bw) {
 | 
				
			||||||
 | 
					        case 0x00: return 7.8E3;
 | 
				
			||||||
 | 
					        case 0x01: return 15.6E3;
 | 
				
			||||||
 | 
					        case 0x02: return 31.25E3;
 | 
				
			||||||
 | 
					        case 0x03: return 62.5E3;
 | 
				
			||||||
 | 
					        case 0x04: return 125E3;
 | 
				
			||||||
 | 
					        case 0x05: return 250E3;
 | 
				
			||||||
 | 
					        case 0x06: return 500E3;
 | 
				
			||||||
 | 
					        case 0x08: return 10.4E3;
 | 
				
			||||||
 | 
					        case 0x09: return 20.8E3;
 | 
				
			||||||
 | 
					        case 0x0A: return 41.7E3;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::handleLowDataRate(){
 | 
				
			||||||
 | 
					    _ldro = 1;
 | 
				
			||||||
 | 
					    setModulationParams(_sf, _bw, _cr, _ldro);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::optimizeModemSensitivity(){
 | 
				
			||||||
 | 
					    // todo: check if there's anything the sx1262 can do here
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setSignalBandwidth(long sbw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (sbw <= 7.8E3) {
 | 
				
			||||||
 | 
					        _bw = 0x00;
 | 
				
			||||||
 | 
					    } else if (sbw <= 10.4E3) {
 | 
				
			||||||
 | 
					        _bw = 0x08;
 | 
				
			||||||
 | 
					    } else if (sbw <= 15.6E3) {
 | 
				
			||||||
 | 
					        _bw = 0x01;
 | 
				
			||||||
 | 
					    } else if (sbw <= 20.8E3) {
 | 
				
			||||||
 | 
					        _bw = 0x09;
 | 
				
			||||||
 | 
					    } else if (sbw <= 31.25E3) {
 | 
				
			||||||
 | 
					        _bw = 0x02;
 | 
				
			||||||
 | 
					    } else if (sbw <= 41.7E3) {
 | 
				
			||||||
 | 
					        _bw = 0x0A;
 | 
				
			||||||
 | 
					    } else if (sbw <= 62.5E3) {
 | 
				
			||||||
 | 
					        _bw = 0x03;
 | 
				
			||||||
 | 
					    } else if (sbw <= 125E3) {
 | 
				
			||||||
 | 
					        _bw = 0x04;
 | 
				
			||||||
 | 
					    } else if (sbw <= 250E3) {
 | 
				
			||||||
 | 
					        _bw = 0x05;
 | 
				
			||||||
 | 
					    } else /*if (sbw <= 250E3)*/ {
 | 
				
			||||||
 | 
					        _bw = 0x06;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setModulationParams(_sf, _bw, _cr, _ldro);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    handleLowDataRate();
 | 
				
			||||||
 | 
					  optimizeModemSensitivity();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setCodingRate4(int denominator)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (denominator < 5) {
 | 
				
			||||||
 | 
					    denominator = 5;
 | 
				
			||||||
 | 
					  } else if (denominator > 8) {
 | 
				
			||||||
 | 
					    denominator = 8;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int cr = denominator - 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _cr = cr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setModulationParams(_sf, _bw, cr, _ldro);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setPreambleLength(long length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setSyncWord(int sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    writeRegister(REG_SYNC_WORD_MSB_6X, sw & 0xFF00);
 | 
				
			||||||
 | 
					    writeRegister(REG_SYNC_WORD_LSB_6X, sw & 0x00FF);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::enableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _crcMode = 1;
 | 
				
			||||||
 | 
					    setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::disableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _crcMode = 0;
 | 
				
			||||||
 | 
					    setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte sx126x::random()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return readRegister(REG_RANDOM_GEN_6X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setPins(int ss, int reset, int dio0, int busy, int rxen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _ss = ss;
 | 
				
			||||||
 | 
					  _reset = reset;
 | 
				
			||||||
 | 
					  _dio0 = dio0;
 | 
				
			||||||
 | 
					  _busy = busy;
 | 
				
			||||||
 | 
					  _rxen = rxen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::setSPIFrequency(uint32_t frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::dumpRegisters(Stream& out)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (int i = 0; i < 128; i++) {
 | 
				
			||||||
 | 
					    out.print("0x");
 | 
				
			||||||
 | 
					    out.print(i, HEX);
 | 
				
			||||||
 | 
					    out.print(": 0x");
 | 
				
			||||||
 | 
					    out.println(readRegister(i), HEX);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::explicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 0;
 | 
				
			||||||
 | 
					  setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx126x::implicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 1;
 | 
				
			||||||
 | 
					  setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ISR_VECT sx126x::handleDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t buf[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    buf[0] = 0x00;
 | 
				
			||||||
 | 
					    buf[1] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_GET_IRQ_STATUS_6X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_CLEAR_IRQ_STATUS_6X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_6X) == 0) {
 | 
				
			||||||
 | 
					        // received a packet
 | 
				
			||||||
 | 
					        _packetIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // read packet length
 | 
				
			||||||
 | 
					        uint8_t rxbuf[2] = {0};
 | 
				
			||||||
 | 
					        executeOpcodeRead(OP_RX_BUFFER_STATUS_6X, rxbuf, 2);
 | 
				
			||||||
 | 
					        int packetLength = rxbuf[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (_onReceive) {
 | 
				
			||||||
 | 
					            _onReceive(packetLength);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ISR_VECT sx126x::onDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    sx126x_modem.handleDio0Rise();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sx126x sx126x_modem;
 | 
				
			||||||
@ -4,8 +4,8 @@
 | 
				
			|||||||
// Modifications and additions copyright 2023 by Mark Qvist
 | 
					// Modifications and additions copyright 2023 by Mark Qvist
 | 
				
			||||||
// Obviously still under the MIT license.
 | 
					// Obviously still under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef LORA_H
 | 
					#ifndef SX126X_H
 | 
				
			||||||
#define LORA_H
 | 
					#define SX126X_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <Arduino.h>
 | 
					#include <Arduino.h>
 | 
				
			||||||
#include <SPI.h>
 | 
					#include <SPI.h>
 | 
				
			||||||
@ -15,6 +15,7 @@
 | 
				
			|||||||
#define LORA_DEFAULT_RESET_PIN 9
 | 
					#define LORA_DEFAULT_RESET_PIN 9
 | 
				
			||||||
#define LORA_DEFAULT_DIO0_PIN  2
 | 
					#define LORA_DEFAULT_DIO0_PIN  2
 | 
				
			||||||
#define LORA_DEFAULT_RXEN_PIN  -1
 | 
					#define LORA_DEFAULT_RXEN_PIN  -1
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_TXEN_PIN  -1
 | 
				
			||||||
#define LORA_DEFAULT_BUSY_PIN  -1
 | 
					#define LORA_DEFAULT_BUSY_PIN  -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PA_OUTPUT_RFO_PIN      0
 | 
					#define PA_OUTPUT_RFO_PIN      0
 | 
				
			||||||
@ -22,9 +23,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define RSSI_OFFSET 157
 | 
					#define RSSI_OFFSET 157
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LoRaClass : public Stream {
 | 
					class sx126x : public Stream {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  LoRaClass();
 | 
					  sx126x();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int begin(long frequency);
 | 
					  int begin(long frequency);
 | 
				
			||||||
  void end();
 | 
					  void end();
 | 
				
			||||||
@ -74,18 +75,16 @@ public:
 | 
				
			|||||||
  void enableTCXO();
 | 
					  void enableTCXO();
 | 
				
			||||||
  void disableTCXO();
 | 
					  void disableTCXO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if MODEM == SX1262
 | 
					  void rxAntEnable();
 | 
				
			||||||
      void enableAntenna();
 | 
					 | 
				
			||||||
      void disableAntenna();
 | 
					 | 
				
			||||||
  void loraMode();
 | 
					  void loraMode();
 | 
				
			||||||
  void waitOnBusy();
 | 
					  void waitOnBusy();
 | 
				
			||||||
  void executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size);
 | 
					  void executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size);
 | 
				
			||||||
  void executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size);
 | 
					  void executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size);
 | 
				
			||||||
  void writeBuffer(const uint8_t* buffer, size_t size);
 | 
					  void writeBuffer(const uint8_t* buffer, size_t size);
 | 
				
			||||||
  void readBuffer(uint8_t* buffer, size_t size);
 | 
					  void readBuffer(uint8_t* buffer, size_t size);
 | 
				
			||||||
      void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro);
 | 
					 | 
				
			||||||
  void setPacketParams(long preamble, uint8_t headermode, uint8_t length, uint8_t crc);
 | 
					  void setPacketParams(long preamble, uint8_t headermode, uint8_t length, uint8_t crc);
 | 
				
			||||||
  #endif
 | 
					
 | 
				
			||||||
 | 
					  void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // deprecated
 | 
					  // deprecated
 | 
				
			||||||
  void crc() { enableCrc(); }
 | 
					  void crc() { enableCrc(); }
 | 
				
			||||||
@ -93,7 +92,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  byte random();
 | 
					  byte random();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN, int rxen = LORA_DEFAULT_RXEN_PIN, int busy = LORA_DEFAULT_BUSY_PIN);
 | 
					  void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN, int busy = LORA_DEFAULT_BUSY_PIN, int rxen = LORA_DEFAULT_RXEN_PIN);
 | 
				
			||||||
  void setSPIFrequency(uint32_t frequency);
 | 
					  void setSPIFrequency(uint32_t frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void dumpRegisters(Stream& out);
 | 
					  void dumpRegisters(Stream& out);
 | 
				
			||||||
@ -104,15 +103,9 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void handleDio0Rise();
 | 
					  void handleDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #if MODEM == SX1276 || MODEM == SX1278
 | 
					 | 
				
			||||||
      uint8_t readRegister(uint8_t address);
 | 
					 | 
				
			||||||
      void writeRegister(uint8_t address, uint8_t value);
 | 
					 | 
				
			||||||
      uint8_t singleTransfer(uint8_t address, uint8_t value);
 | 
					 | 
				
			||||||
  #elif MODEM == SX1262
 | 
					 | 
				
			||||||
  uint8_t readRegister(uint16_t address);
 | 
					  uint8_t readRegister(uint16_t address);
 | 
				
			||||||
  void writeRegister(uint16_t address, uint8_t value);
 | 
					  void writeRegister(uint16_t address, uint8_t value);
 | 
				
			||||||
  uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value);
 | 
					  uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value);
 | 
				
			||||||
  #endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static void onDio0Rise();
 | 
					  static void onDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -137,9 +130,13 @@ private:
 | 
				
			|||||||
  int _implicitHeaderMode;
 | 
					  int _implicitHeaderMode;
 | 
				
			||||||
  int _payloadLength;
 | 
					  int _payloadLength;
 | 
				
			||||||
  int _crcMode;
 | 
					  int _crcMode;
 | 
				
			||||||
 | 
					  int _fifo_tx_addr_ptr;
 | 
				
			||||||
 | 
					  int _fifo_rx_addr_ptr;
 | 
				
			||||||
 | 
					  uint8_t _packet[255];
 | 
				
			||||||
 | 
					  bool _preinit_done;
 | 
				
			||||||
  void (*_onReceive)(int);
 | 
					  void (*_onReceive)(int);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern LoRaClass LoRa;
 | 
					extern sx126x sx126x_modem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										691
									
								
								sx127x.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										691
									
								
								sx127x.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,691 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Modifications and additions copyright 2023 by Mark Qvist
 | 
				
			||||||
 | 
					// Obviously still under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sx127x.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MCU_1284P 0x91
 | 
				
			||||||
 | 
					#define MCU_2560  0x92
 | 
				
			||||||
 | 
					#define MCU_ESP32 0x81
 | 
				
			||||||
 | 
					#define MCU_NRF52 0x71
 | 
				
			||||||
 | 
					#if defined(__AVR_ATmega1284P__)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_AVR
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_1284P
 | 
				
			||||||
 | 
					#elif defined(__AVR_ATmega2560__)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_AVR
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_2560
 | 
				
			||||||
 | 
					#elif defined(ESP32)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_ESP32
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_ESP32
 | 
				
			||||||
 | 
					#elif defined(NRF52840_XXAA)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_NRF52
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_NRF52
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MCU_VARIANT
 | 
				
			||||||
 | 
					  #error No MCU variant defined, cannot compile
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if MCU_VARIANT == MCU_ESP32
 | 
				
			||||||
 | 
					  #include "soc/rtc_wdt.h"
 | 
				
			||||||
 | 
					  #define ISR_VECT IRAM_ATTR
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  #define ISR_VECT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Registers
 | 
				
			||||||
 | 
					#define REG_FIFO_7X                 0x00
 | 
				
			||||||
 | 
					#define REG_OP_MODE_7X              0x01
 | 
				
			||||||
 | 
					#define REG_FRF_MSB_7X              0x06
 | 
				
			||||||
 | 
					#define REG_FRF_MID_7X              0x07
 | 
				
			||||||
 | 
					#define REG_FRF_LSB_7X              0x08
 | 
				
			||||||
 | 
					#define REG_PA_CONFIG_7X            0x09
 | 
				
			||||||
 | 
					#define REG_OCP_7X                  0x0b
 | 
				
			||||||
 | 
					#define REG_LNA_7X                  0x0c
 | 
				
			||||||
 | 
					#define REG_FIFO_ADDR_PTR_7X        0x0d
 | 
				
			||||||
 | 
					#define REG_FIFO_TX_BASE_ADDR_7X    0x0e
 | 
				
			||||||
 | 
					#define REG_FIFO_RX_BASE_ADDR_7X    0x0f
 | 
				
			||||||
 | 
					#define REG_FIFO_RX_CURRENT_ADDR_7X 0x10
 | 
				
			||||||
 | 
					#define REG_IRQ_FLAGS_7X            0x12
 | 
				
			||||||
 | 
					#define REG_RX_NB_BYTES_7X          0x13
 | 
				
			||||||
 | 
					#define REG_MODEM_STAT_7X           0x18
 | 
				
			||||||
 | 
					#define REG_PKT_SNR_VALUE_7X        0x19
 | 
				
			||||||
 | 
					#define REG_PKT_RSSI_VALUE_7X       0x1a
 | 
				
			||||||
 | 
					#define REG_RSSI_VALUE_7X           0x1b
 | 
				
			||||||
 | 
					#define REG_MODEM_CONFIG_1_7X       0x1d
 | 
				
			||||||
 | 
					#define REG_MODEM_CONFIG_2_7X       0x1e
 | 
				
			||||||
 | 
					#define REG_PREAMBLE_MSB_7X         0x20
 | 
				
			||||||
 | 
					#define REG_PREAMBLE_LSB_7X         0x21
 | 
				
			||||||
 | 
					#define REG_PAYLOAD_LENGTH_7X       0x22
 | 
				
			||||||
 | 
					#define REG_MODEM_CONFIG_3_7X       0x26
 | 
				
			||||||
 | 
					#define REG_FREQ_ERROR_MSB_7X       0x28
 | 
				
			||||||
 | 
					#define REG_FREQ_ERROR_MID_7X       0x29
 | 
				
			||||||
 | 
					#define REG_FREQ_ERROR_LSB_7X       0x2a
 | 
				
			||||||
 | 
					#define REG_RSSI_WIDEBAND_7X        0x2c
 | 
				
			||||||
 | 
					#define REG_DETECTION_OPTIMIZE_7X   0x31
 | 
				
			||||||
 | 
					#define REG_HIGH_BW_OPTIMIZE_1_7X   0x36
 | 
				
			||||||
 | 
					#define REG_DETECTION_THRESHOLD_7X  0x37
 | 
				
			||||||
 | 
					#define REG_SYNC_WORD_7X            0x39
 | 
				
			||||||
 | 
					#define REG_HIGH_BW_OPTIMIZE_2_7X   0x3a
 | 
				
			||||||
 | 
					#define REG_DIO_MAPPING_1_7X        0x40
 | 
				
			||||||
 | 
					#define REG_VERSION_7X              0x42
 | 
				
			||||||
 | 
					#define REG_TCXO_7X                 0x4b
 | 
				
			||||||
 | 
					#define REG_PA_DAC_7X               0x4d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Modes
 | 
				
			||||||
 | 
					#define MODE_LONG_RANGE_MODE_7X     0x80
 | 
				
			||||||
 | 
					#define MODE_SLEEP_7X               0x00
 | 
				
			||||||
 | 
					#define MODE_STDBY_7X               0x01
 | 
				
			||||||
 | 
					#define MODE_TX_7X                  0x03
 | 
				
			||||||
 | 
					#define MODE_RX_CONTINUOUS_7X       0x05
 | 
				
			||||||
 | 
					#define MODE_RX_SINGLE_7X           0x06
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PA config
 | 
				
			||||||
 | 
					#define PA_BOOST_7X                 0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IRQ masks
 | 
				
			||||||
 | 
					#define IRQ_TX_DONE_MASK_7X         0x08
 | 
				
			||||||
 | 
					#define IRQ_PAYLOAD_CRC_ERROR_MASK_7X 0x20
 | 
				
			||||||
 | 
					#define IRQ_RX_DONE_MASK_7X         0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern SPIClass SPI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_PKT_LENGTH           255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sx127x::sx127x() :
 | 
				
			||||||
 | 
					  _spiSettings(8E6, MSBFIRST, SPI_MODE0),
 | 
				
			||||||
 | 
					  _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN),
 | 
				
			||||||
 | 
					  _frequency(0),
 | 
				
			||||||
 | 
					  _packetIndex(0),
 | 
				
			||||||
 | 
					  _preinit_done(false),
 | 
				
			||||||
 | 
					  _onReceive(NULL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // overide Stream timeout value
 | 
				
			||||||
 | 
					  setTimeout(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sx127x::preInit() {
 | 
				
			||||||
 | 
					  // setup pins
 | 
				
			||||||
 | 
					  pinMode(_ss, OUTPUT);
 | 
				
			||||||
 | 
					  // set SS high
 | 
				
			||||||
 | 
					  digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  SPI.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check version (retry for up to 2 seconds)
 | 
				
			||||||
 | 
					  uint8_t version;
 | 
				
			||||||
 | 
					  long start = millis();
 | 
				
			||||||
 | 
					  while (((millis() - start) < 2000) && (millis() >= start)) {
 | 
				
			||||||
 | 
					      version = readRegister(REG_VERSION_7X);
 | 
				
			||||||
 | 
					      if (version == 0x12) {
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      delay(100);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (version != 0x12) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _preinit_done = true;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx127x::readRegister(uint8_t address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return singleTransfer(address & 0x7f, 0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::writeRegister(uint8_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  singleTransfer(address | 0x80, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx127x::singleTransfer(uint8_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint8_t response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					  SPI.transfer(address);
 | 
				
			||||||
 | 
					  response = SPI.transfer(value);
 | 
				
			||||||
 | 
					  SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return response;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx127x::begin(long frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (_reset != -1) {
 | 
				
			||||||
 | 
					    pinMode(_reset, OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // perform reset
 | 
				
			||||||
 | 
					    digitalWrite(_reset, LOW);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					    digitalWrite(_reset, HIGH);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (_busy != -1) {
 | 
				
			||||||
 | 
					      pinMode(_busy, INPUT);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!_preinit_done) {
 | 
				
			||||||
 | 
					    if (!preInit()) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // put in sleep mode
 | 
				
			||||||
 | 
					  sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set frequency
 | 
				
			||||||
 | 
					  setFrequency(frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set base addresses
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_TX_BASE_ADDR_7X, 0);
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_RX_BASE_ADDR_7X, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set LNA boost
 | 
				
			||||||
 | 
					  writeRegister(REG_LNA_7X, readRegister(REG_LNA_7X) | 0x03);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set auto AGC
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_3_7X, 0x04);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set output power to 2 dBm
 | 
				
			||||||
 | 
					  setTxPower(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // put in standby mode
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::end()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in sleep mode
 | 
				
			||||||
 | 
					  sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // stop SPI
 | 
				
			||||||
 | 
					  SPI.end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _preinit_done = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx127x::beginPacket(int implicitHeader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in standby mode
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (implicitHeader) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // reset FIFO address and payload length
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_ADDR_PTR_7X, 0);
 | 
				
			||||||
 | 
					  writeRegister(REG_PAYLOAD_LENGTH_7X, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx127x::endPacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in TX mode
 | 
				
			||||||
 | 
					  writeRegister(REG_OP_MODE_7X, MODE_LONG_RANGE_MODE_7X | MODE_TX_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // wait for TX done
 | 
				
			||||||
 | 
					  while ((readRegister(REG_IRQ_FLAGS_7X) & IRQ_TX_DONE_MASK_7X) == 0) {
 | 
				
			||||||
 | 
					    yield();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // clear IRQ's
 | 
				
			||||||
 | 
					  writeRegister(REG_IRQ_FLAGS_7X, IRQ_TX_DONE_MASK_7X);
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx127x::modemStatus() {
 | 
				
			||||||
 | 
					    return readRegister(REG_MODEM_STAT_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx127x::currentRssiRaw() {
 | 
				
			||||||
 | 
					    uint8_t rssi = readRegister(REG_RSSI_VALUE_7X);
 | 
				
			||||||
 | 
					    return rssi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx127x::currentRssi() {
 | 
				
			||||||
 | 
					    int rssi = (int)readRegister(REG_RSSI_VALUE_7X) - RSSI_OFFSET;
 | 
				
			||||||
 | 
					    if (_frequency < 820E6) rssi -= 7;
 | 
				
			||||||
 | 
					    return rssi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx127x::packetRssiRaw() {
 | 
				
			||||||
 | 
					    uint8_t pkt_rssi_value = readRegister(REG_PKT_RSSI_VALUE_7X);
 | 
				
			||||||
 | 
					    return pkt_rssi_value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx127x::packetRssi() {
 | 
				
			||||||
 | 
					    int pkt_rssi = (int)readRegister(REG_PKT_RSSI_VALUE_7X) - RSSI_OFFSET;
 | 
				
			||||||
 | 
					    int pkt_snr = packetSnr();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_frequency < 820E6) pkt_rssi -= 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (pkt_snr < 0) {
 | 
				
			||||||
 | 
					        pkt_rssi += pkt_snr;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // Slope correction is (16/15)*pkt_rssi,
 | 
				
			||||||
 | 
					        // this estimation looses one floating point
 | 
				
			||||||
 | 
					        // operation, and should be precise enough.
 | 
				
			||||||
 | 
					        pkt_rssi = (int)(1.066 * pkt_rssi);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return pkt_rssi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx127x::packetSnrRaw() {
 | 
				
			||||||
 | 
					    return readRegister(REG_PKT_SNR_VALUE_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ISR_VECT sx127x::packetSnr() {
 | 
				
			||||||
 | 
					    return ((int8_t)readRegister(REG_PKT_SNR_VALUE_7X)) * 0.25;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long sx127x::packetFrequencyError()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t freqError = 0;
 | 
				
			||||||
 | 
					  freqError = static_cast<int32_t>(readRegister(REG_FREQ_ERROR_MSB_7X) & B111);
 | 
				
			||||||
 | 
					  freqError <<= 8L;
 | 
				
			||||||
 | 
					  freqError += static_cast<int32_t>(readRegister(REG_FREQ_ERROR_MID_7X));
 | 
				
			||||||
 | 
					  freqError <<= 8L;
 | 
				
			||||||
 | 
					  freqError += static_cast<int32_t>(readRegister(REG_FREQ_ERROR_LSB_7X));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (readRegister(REG_FREQ_ERROR_MSB_7X) & B1000) { // Sign bit is on
 | 
				
			||||||
 | 
					      freqError -= 524288; // B1000'0000'0000'0000'0000
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const float fXtal = 32E6; // FXOSC: crystal oscillator (XTAL) frequency (2.5. Chip Specification, p. 14)
 | 
				
			||||||
 | 
					  const float fError = ((static_cast<float>(freqError) * (1L << 24)) / fXtal) * (getSignalBandwidth() / 500000.0f); // p. 37
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return static_cast<long>(fError);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sx127x::write(uint8_t byte)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return write(&byte, sizeof(byte));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sx127x::write(const uint8_t *buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int currentLength = readRegister(REG_PAYLOAD_LENGTH_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check size
 | 
				
			||||||
 | 
					    if ((currentLength + size) > MAX_PKT_LENGTH) {
 | 
				
			||||||
 | 
					        size = MAX_PKT_LENGTH - currentLength;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // write data
 | 
				
			||||||
 | 
					    for (size_t i = 0; i < size; i++) {
 | 
				
			||||||
 | 
					        writeRegister(REG_FIFO_7X, buffer[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // update length
 | 
				
			||||||
 | 
					    writeRegister(REG_PAYLOAD_LENGTH_7X, currentLength + size);
 | 
				
			||||||
 | 
					    return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx127x::available()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return (readRegister(REG_RX_NB_BYTES_7X) - _packetIndex);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx127x::read()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _packetIndex++;
 | 
				
			||||||
 | 
					  return readRegister(REG_FIFO_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx127x::peek()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // store current FIFO address
 | 
				
			||||||
 | 
					  int currentAddress = readRegister(REG_FIFO_ADDR_PTR_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // read
 | 
				
			||||||
 | 
					  uint8_t b = readRegister(REG_FIFO_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // restore FIFO address
 | 
				
			||||||
 | 
					  writeRegister(REG_FIFO_ADDR_PTR_7X, currentAddress);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::flush()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::onReceive(void(*callback)(int))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _onReceive = callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (callback) {
 | 
				
			||||||
 | 
					    pinMode(_dio0, INPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_DIO_MAPPING_1_7X, 0x00);
 | 
				
			||||||
 | 
					#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					    SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    attachInterrupt(digitalPinToInterrupt(_dio0), sx127x::onDio0Rise, RISING);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    detachInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					    SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::receive(int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (size > 0) {
 | 
				
			||||||
 | 
					        implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        writeRegister(REG_PAYLOAD_LENGTH_7X, size & 0xff);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        explicitHeaderMode();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_OP_MODE_7X, MODE_LONG_RANGE_MODE_7X | MODE_RX_CONTINUOUS_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::idle()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    writeRegister(REG_OP_MODE_7X, MODE_LONG_RANGE_MODE_7X | MODE_STDBY_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::sleep()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    writeRegister(REG_OP_MODE_7X, MODE_LONG_RANGE_MODE_7X | MODE_SLEEP_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::enableTCXO() {
 | 
				
			||||||
 | 
					    uint8_t tcxo_reg = readRegister(REG_TCXO_7X);
 | 
				
			||||||
 | 
					    writeRegister(REG_TCXO_7X, tcxo_reg | 0x10);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::disableTCXO() {
 | 
				
			||||||
 | 
					      uint8_t tcxo_reg = readRegister(REG_TCXO_7X);
 | 
				
			||||||
 | 
					      writeRegister(REG_TCXO_7X, tcxo_reg & 0xEF);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setTxPower(int level, int outputPin) {
 | 
				
			||||||
 | 
					    if (PA_OUTPUT_RFO_PIN == outputPin) {
 | 
				
			||||||
 | 
					        // RFO
 | 
				
			||||||
 | 
					        if (level < 0) {
 | 
				
			||||||
 | 
					            level = 0;
 | 
				
			||||||
 | 
					        } else if (level > 14) {
 | 
				
			||||||
 | 
					            level = 14;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        writeRegister(REG_PA_DAC_7X, 0x84);
 | 
				
			||||||
 | 
					        writeRegister(REG_PA_CONFIG_7X, 0x70 | level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // PA BOOST
 | 
				
			||||||
 | 
					        if (level < 2) {
 | 
				
			||||||
 | 
					            level = 2;
 | 
				
			||||||
 | 
					        } else if (level > 17) {
 | 
				
			||||||
 | 
					            level = 17;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        writeRegister(REG_PA_DAC_7X, 0x84);
 | 
				
			||||||
 | 
					        writeRegister(REG_PA_CONFIG_7X, PA_BOOST_7X | (level - 2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx127x::getTxPower() {
 | 
				
			||||||
 | 
					    byte txp = readRegister(REG_PA_CONFIG_7X);
 | 
				
			||||||
 | 
					    return txp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setFrequency(unsigned long frequency) {
 | 
				
			||||||
 | 
					  _frequency = frequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t frf = ((uint64_t)frequency << 19) / 32000000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_FRF_MSB_7X, (uint8_t)(frf >> 16));
 | 
				
			||||||
 | 
					  writeRegister(REG_FRF_MID_7X, (uint8_t)(frf >> 8));
 | 
				
			||||||
 | 
					  writeRegister(REG_FRF_LSB_7X, (uint8_t)(frf >> 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  optimizeModemSensitivity();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t sx127x::getFrequency() {
 | 
				
			||||||
 | 
					    uint8_t msb = readRegister(REG_FRF_MSB_7X);
 | 
				
			||||||
 | 
					    uint8_t mid = readRegister(REG_FRF_MID_7X);
 | 
				
			||||||
 | 
					    uint8_t lsb = readRegister(REG_FRF_LSB_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t frf = ((uint32_t)msb << 16) | ((uint32_t)mid << 8) | (uint32_t)lsb;
 | 
				
			||||||
 | 
					    uint64_t frm = (uint64_t)frf*32000000;
 | 
				
			||||||
 | 
					    uint32_t frequency = (frm >> 19);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return frequency;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setSpreadingFactor(int sf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (sf < 6) {
 | 
				
			||||||
 | 
					    sf = 6;
 | 
				
			||||||
 | 
					  } else if (sf > 12) {
 | 
				
			||||||
 | 
					    sf = 12;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (sf == 6) {
 | 
				
			||||||
 | 
					      writeRegister(REG_DETECTION_OPTIMIZE_7X, 0xc5);
 | 
				
			||||||
 | 
					      writeRegister(REG_DETECTION_THRESHOLD_7X, 0x0c);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					      writeRegister(REG_DETECTION_OPTIMIZE_7X, 0xc3);
 | 
				
			||||||
 | 
					      writeRegister(REG_DETECTION_THRESHOLD_7X, 0x0a);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_2_7X, (readRegister(REG_MODEM_CONFIG_2_7X) & 0x0f) | ((sf << 4) & 0xf0));
 | 
				
			||||||
 | 
					  handleLowDataRate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long sx127x::getSignalBandwidth()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					      byte bw = (readRegister(REG_MODEM_CONFIG_1_7X) >> 4);
 | 
				
			||||||
 | 
					      switch (bw) {
 | 
				
			||||||
 | 
					        case 0: return 7.8E3;
 | 
				
			||||||
 | 
					        case 1: return 10.4E3;
 | 
				
			||||||
 | 
					        case 2: return 15.6E3;
 | 
				
			||||||
 | 
					        case 3: return 20.8E3;
 | 
				
			||||||
 | 
					        case 4: return 31.25E3;
 | 
				
			||||||
 | 
					        case 5: return 41.7E3;
 | 
				
			||||||
 | 
					        case 6: return 62.5E3;
 | 
				
			||||||
 | 
					        case 7: return 125E3;
 | 
				
			||||||
 | 
					        case 8: return 250E3;
 | 
				
			||||||
 | 
					        case 9: return 500E3;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::handleLowDataRate(){
 | 
				
			||||||
 | 
					    int sf = (readRegister(REG_MODEM_CONFIG_2_7X) >> 4);
 | 
				
			||||||
 | 
					    if ( long( (1<<sf) / (getSignalBandwidth()/1000)) > 16) {
 | 
				
			||||||
 | 
					        // set auto AGC and LowDataRateOptimize
 | 
				
			||||||
 | 
					        writeRegister(REG_MODEM_CONFIG_3_7X, (1<<3)|(1<<2));
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        // set auto AGC
 | 
				
			||||||
 | 
					        writeRegister(REG_MODEM_CONFIG_3_7X, (1<<2));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::optimizeModemSensitivity(){
 | 
				
			||||||
 | 
					    byte bw = (readRegister(REG_MODEM_CONFIG_1_7X) >> 4);
 | 
				
			||||||
 | 
					    uint32_t freq = getFrequency();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bw == 9 && (410E6 <= freq) && (freq <= 525E6)) {
 | 
				
			||||||
 | 
					        writeRegister(REG_HIGH_BW_OPTIMIZE_1_7X, 0x02);
 | 
				
			||||||
 | 
					        writeRegister(REG_HIGH_BW_OPTIMIZE_2_7X, 0x7f);
 | 
				
			||||||
 | 
					    } else if (bw == 9 && (820E6 <= freq) && (freq <= 1020E6)) {
 | 
				
			||||||
 | 
					        writeRegister(REG_HIGH_BW_OPTIMIZE_1_7X, 0x02);
 | 
				
			||||||
 | 
					        writeRegister(REG_HIGH_BW_OPTIMIZE_2_7X, 0x64);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        writeRegister(REG_HIGH_BW_OPTIMIZE_1_7X, 0x03);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setSignalBandwidth(long sbw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int bw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sbw <= 7.8E3) {
 | 
				
			||||||
 | 
					        bw = 0;
 | 
				
			||||||
 | 
					    } else if (sbw <= 10.4E3) {
 | 
				
			||||||
 | 
					        bw = 1;
 | 
				
			||||||
 | 
					    } else if (sbw <= 15.6E3) {
 | 
				
			||||||
 | 
					        bw = 2;
 | 
				
			||||||
 | 
					    } else if (sbw <= 20.8E3) {
 | 
				
			||||||
 | 
					        bw = 3;
 | 
				
			||||||
 | 
					    } else if (sbw <= 31.25E3) {
 | 
				
			||||||
 | 
					        bw = 4;
 | 
				
			||||||
 | 
					    } else if (sbw <= 41.7E3) {
 | 
				
			||||||
 | 
					        bw = 5;
 | 
				
			||||||
 | 
					    } else if (sbw <= 62.5E3) {
 | 
				
			||||||
 | 
					        bw = 6;
 | 
				
			||||||
 | 
					    } else if (sbw <= 125E3) {
 | 
				
			||||||
 | 
					        bw = 7;
 | 
				
			||||||
 | 
					    } else if (sbw <= 250E3) {
 | 
				
			||||||
 | 
					        bw = 8;
 | 
				
			||||||
 | 
					    } else /*if (sbw <= 250E3)*/ {
 | 
				
			||||||
 | 
					        bw = 9;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeRegister(REG_MODEM_CONFIG_1_7X, (readRegister(REG_MODEM_CONFIG_1_7X) & 0x0f) | (bw << 4));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleLowDataRate();
 | 
				
			||||||
 | 
					  optimizeModemSensitivity();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setCodingRate4(int denominator)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (denominator < 5) {
 | 
				
			||||||
 | 
					    denominator = 5;
 | 
				
			||||||
 | 
					  } else if (denominator > 8) {
 | 
				
			||||||
 | 
					    denominator = 8;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int cr = denominator - 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1_7X, (readRegister(REG_MODEM_CONFIG_1_7X) & 0xf1) | (cr << 1));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setPreambleLength(long length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  writeRegister(REG_PREAMBLE_MSB_7X, (uint8_t)(length >> 8));
 | 
				
			||||||
 | 
					  writeRegister(REG_PREAMBLE_LSB_7X, (uint8_t)(length >> 0));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setSyncWord(int sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    writeRegister(REG_SYNC_WORD_7X, sw);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::enableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    writeRegister(REG_MODEM_CONFIG_2_7X, readRegister(REG_MODEM_CONFIG_2_7X) | 0x04);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::disableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    writeRegister(REG_MODEM_CONFIG_2_7X, readRegister(REG_MODEM_CONFIG_2_7X) & 0xfb);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte sx127x::random()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return readRegister(REG_RSSI_WIDEBAND_7X);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setPins(int ss, int reset, int dio0, int busy)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _ss = ss;
 | 
				
			||||||
 | 
					  _reset = reset;
 | 
				
			||||||
 | 
					  _dio0 = dio0;
 | 
				
			||||||
 | 
					  _busy = busy;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::setSPIFrequency(uint32_t frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::dumpRegisters(Stream& out)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (int i = 0; i < 128; i++) {
 | 
				
			||||||
 | 
					    out.print("0x");
 | 
				
			||||||
 | 
					    out.print(i, HEX);
 | 
				
			||||||
 | 
					    out.print(": 0x");
 | 
				
			||||||
 | 
					    out.println(readRegister(i), HEX);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::explicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1_7X, readRegister(REG_MODEM_CONFIG_1_7X) & 0xfe);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx127x::implicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  writeRegister(REG_MODEM_CONFIG_1_7X, readRegister(REG_MODEM_CONFIG_1_7X) | 0x01);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ISR_VECT sx127x::handleDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int irqFlags = readRegister(REG_IRQ_FLAGS_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // clear IRQ's
 | 
				
			||||||
 | 
					    writeRegister(REG_IRQ_FLAGS_7X, irqFlags);
 | 
				
			||||||
 | 
					    if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK_7X) == 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // received a packet
 | 
				
			||||||
 | 
					        _packetIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // read packet length
 | 
				
			||||||
 | 
					        int packetLength = _implicitHeaderMode ? readRegister(REG_PAYLOAD_LENGTH_7X) : readRegister(REG_RX_NB_BYTES_7X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // set FIFO address to current RX address
 | 
				
			||||||
 | 
					        writeRegister(REG_FIFO_ADDR_PTR_7X, readRegister(REG_FIFO_RX_CURRENT_ADDR_7X));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (_onReceive) {
 | 
				
			||||||
 | 
					            _onReceive(packetLength);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // reset FIFO address
 | 
				
			||||||
 | 
					        writeRegister(REG_FIFO_ADDR_PTR_7X, 0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ISR_VECT sx127x::onDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  sx127x_modem.handleDio0Rise();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sx127x sx127x_modem;
 | 
				
			||||||
							
								
								
									
										117
									
								
								sx127x.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								sx127x.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Modifications and additions copyright 2023 by Mark Qvist
 | 
				
			||||||
 | 
					// Obviously still under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SX1276_H
 | 
				
			||||||
 | 
					#define SX1276_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <SPI.h>
 | 
				
			||||||
 | 
					#include "Modem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_SS_PIN    10
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_RESET_PIN 9
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_DIO0_PIN  2
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_BUSY_PIN  -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PA_OUTPUT_RFO_PIN      0
 | 
				
			||||||
 | 
					#define PA_OUTPUT_PA_BOOST_PIN 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RSSI_OFFSET 157
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class sx127x : public Stream {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  sx127x();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int begin(long frequency);
 | 
				
			||||||
 | 
					  void end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int beginPacket(int implicitHeader = false);
 | 
				
			||||||
 | 
					  int endPacket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int parsePacket(int size = 0);
 | 
				
			||||||
 | 
					  int packetRssi();
 | 
				
			||||||
 | 
					  int currentRssi();
 | 
				
			||||||
 | 
					  uint8_t packetRssiRaw();
 | 
				
			||||||
 | 
					  uint8_t currentRssiRaw();
 | 
				
			||||||
 | 
					  uint8_t packetSnrRaw();
 | 
				
			||||||
 | 
					  float packetSnr();
 | 
				
			||||||
 | 
					  long packetFrequencyError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // from Print
 | 
				
			||||||
 | 
					  virtual size_t write(uint8_t byte);
 | 
				
			||||||
 | 
					  virtual size_t write(const uint8_t *buffer, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // from Stream
 | 
				
			||||||
 | 
					  virtual int available();
 | 
				
			||||||
 | 
					  virtual int read();
 | 
				
			||||||
 | 
					  virtual int peek();
 | 
				
			||||||
 | 
					  virtual void flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void onReceive(void(*callback)(int));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void receive(int size = 0);
 | 
				
			||||||
 | 
					  void idle();
 | 
				
			||||||
 | 
					  void sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool preInit();
 | 
				
			||||||
 | 
					  uint8_t getTxPower();
 | 
				
			||||||
 | 
					  void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					  uint32_t getFrequency();
 | 
				
			||||||
 | 
					  void setFrequency(unsigned long frequency);
 | 
				
			||||||
 | 
					  void setSpreadingFactor(int sf);
 | 
				
			||||||
 | 
					  long getSignalBandwidth();
 | 
				
			||||||
 | 
					  void setSignalBandwidth(long sbw);
 | 
				
			||||||
 | 
					  void setCodingRate4(int denominator);
 | 
				
			||||||
 | 
					  void setPreambleLength(long length);
 | 
				
			||||||
 | 
					  void setSyncWord(int sw);
 | 
				
			||||||
 | 
					  uint8_t modemStatus();
 | 
				
			||||||
 | 
					  void enableCrc();
 | 
				
			||||||
 | 
					  void disableCrc();
 | 
				
			||||||
 | 
					  void enableTCXO();
 | 
				
			||||||
 | 
					  void disableTCXO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // deprecated
 | 
				
			||||||
 | 
					  void crc() { enableCrc(); }
 | 
				
			||||||
 | 
					  void noCrc() { disableCrc(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte random();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN, int busy = LORA_DEFAULT_BUSY_PIN);
 | 
				
			||||||
 | 
					  void setSPIFrequency(uint32_t frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void dumpRegisters(Stream& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  void explicitHeaderMode();
 | 
				
			||||||
 | 
					  void implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void handleDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t readRegister(uint8_t address);
 | 
				
			||||||
 | 
					  void writeRegister(uint8_t address, uint8_t value);
 | 
				
			||||||
 | 
					  uint8_t singleTransfer(uint8_t address, uint8_t value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static void onDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void handleLowDataRate();
 | 
				
			||||||
 | 
					  void optimizeModemSensitivity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  SPISettings _spiSettings;
 | 
				
			||||||
 | 
					  int _ss;
 | 
				
			||||||
 | 
					  int _reset;
 | 
				
			||||||
 | 
					  int _dio0;
 | 
				
			||||||
 | 
					  int _busy;
 | 
				
			||||||
 | 
					  long _frequency;
 | 
				
			||||||
 | 
					  int _packetIndex;
 | 
				
			||||||
 | 
					  int _implicitHeaderMode;
 | 
				
			||||||
 | 
					  bool _preinit_done;
 | 
				
			||||||
 | 
					  void (*_onReceive)(int);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern sx127x sx127x_modem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										876
									
								
								sx128x.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										876
									
								
								sx128x.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,876 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Modifications and additions copyright 2023 by Mark Qvist
 | 
				
			||||||
 | 
					// Obviously still under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "sx128x.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MCU_1284P 0x91
 | 
				
			||||||
 | 
					#define MCU_2560  0x92
 | 
				
			||||||
 | 
					#define MCU_ESP32 0x81
 | 
				
			||||||
 | 
					#define MCU_NRF52 0x71
 | 
				
			||||||
 | 
					#if defined(__AVR_ATmega1284P__)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_AVR
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_1284P
 | 
				
			||||||
 | 
					#elif defined(__AVR_ATmega2560__)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_AVR
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_2560
 | 
				
			||||||
 | 
					#elif defined(ESP32)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_ESP32
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_ESP32
 | 
				
			||||||
 | 
					#elif defined(NRF52840_XXAA)
 | 
				
			||||||
 | 
					  #define PLATFORM PLATFORM_NRF52
 | 
				
			||||||
 | 
					  #define MCU_VARIANT MCU_NRF52
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef MCU_VARIANT
 | 
				
			||||||
 | 
					  #error No MCU variant defined, cannot compile
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if MCU_VARIANT == MCU_ESP32
 | 
				
			||||||
 | 
					  #include "soc/rtc_wdt.h"
 | 
				
			||||||
 | 
					  #define ISR_VECT IRAM_ATTR
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					  #define ISR_VECT
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OP_RF_FREQ_8X               0x86
 | 
				
			||||||
 | 
					#define OP_SLEEP_8X                 0x84
 | 
				
			||||||
 | 
					#define OP_STANDBY_8X               0x80
 | 
				
			||||||
 | 
					#define OP_TX_8X                    0x83
 | 
				
			||||||
 | 
					#define OP_RX_8X                    0x82
 | 
				
			||||||
 | 
					#define OP_SET_IRQ_FLAGS_8X         0x8D // also provides info such as
 | 
				
			||||||
 | 
					                                         // preamble detection, etc for
 | 
				
			||||||
 | 
					                                         // knowing when it's safe to switch
 | 
				
			||||||
 | 
					                                         // antenna modes
 | 
				
			||||||
 | 
					#define OP_CLEAR_IRQ_STATUS_8X      0x97
 | 
				
			||||||
 | 
					#define OP_GET_IRQ_STATUS_8X        0x15
 | 
				
			||||||
 | 
					#define OP_RX_BUFFER_STATUS_8X      0x17
 | 
				
			||||||
 | 
					#define OP_PACKET_STATUS_8X         0x1D // get snr & rssi of last packet
 | 
				
			||||||
 | 
					#define OP_CURRENT_RSSI_8X          0x1F
 | 
				
			||||||
 | 
					#define OP_MODULATION_PARAMS_8X     0x8B // bw, sf, cr, etc.
 | 
				
			||||||
 | 
					#define OP_PACKET_PARAMS_8X         0x8C // crc, preamble, payload length, etc.
 | 
				
			||||||
 | 
					#define OP_STATUS_8X                0xC0
 | 
				
			||||||
 | 
					#define OP_TX_PARAMS_8X             0x8E // set dbm, etc
 | 
				
			||||||
 | 
					#define OP_PACKET_TYPE_8X           0x8A
 | 
				
			||||||
 | 
					#define OP_BUFFER_BASE_ADDR_8X      0x8F
 | 
				
			||||||
 | 
					#define OP_READ_REGISTER_8X         0x19
 | 
				
			||||||
 | 
					#define OP_WRITE_REGISTER_8X        0x18
 | 
				
			||||||
 | 
					#define IRQ_TX_DONE_MASK_8X         0x01
 | 
				
			||||||
 | 
					#define IRQ_RX_DONE_MASK_8X         0x02
 | 
				
			||||||
 | 
					#define IRQ_HEADER_DET_MASK_8X      0x10
 | 
				
			||||||
 | 
					#define IRQ_HEADER_ERROR_MASK_8X    0x20
 | 
				
			||||||
 | 
					#define IRQ_PAYLOAD_CRC_ERROR_MASK_8X 0x40
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MODE_LONG_RANGE_MODE_8X     0x01
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OP_FIFO_WRITE_8X            0x1A
 | 
				
			||||||
 | 
					#define OP_FIFO_READ_8X             0x1B
 | 
				
			||||||
 | 
					#define IRQ_PREAMBLE_DET_MASK_8X    0x80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define REG_PACKET_SIZE            0x901
 | 
				
			||||||
 | 
					#define REG_FIRM_VER_MSB           0x154
 | 
				
			||||||
 | 
					#define REG_FIRM_VER_LSB           0x153
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define XTAL_FREQ_8X (double)52000000
 | 
				
			||||||
 | 
					#define FREQ_DIV_8X (double)pow(2.0, 18.0)
 | 
				
			||||||
 | 
					#define FREQ_STEP_8X (double)(XTAL_FREQ_8X / FREQ_DIV_8X)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern SPIClass spiModem;
 | 
				
			||||||
 | 
					#define SPI spiModem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern SPIClass SPI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_PKT_LENGTH           255
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sx128x::sx128x() :
 | 
				
			||||||
 | 
					  _spiSettings(8E6, MSBFIRST, SPI_MODE0),
 | 
				
			||||||
 | 
					  _ss(LORA_DEFAULT_SS_PIN), _reset(LORA_DEFAULT_RESET_PIN), _dio0(LORA_DEFAULT_DIO0_PIN), _rxen(LORA_DEFAULT_RXEN_PIN), _busy(LORA_DEFAULT_BUSY_PIN),
 | 
				
			||||||
 | 
					  _frequency(0),
 | 
				
			||||||
 | 
					  _txp(0),
 | 
				
			||||||
 | 
					  _sf(0x50),
 | 
				
			||||||
 | 
					  _bw(0x34),
 | 
				
			||||||
 | 
					  _cr(0x01),
 | 
				
			||||||
 | 
					  _packetIndex(0),
 | 
				
			||||||
 | 
					  _preambleLength(18),
 | 
				
			||||||
 | 
					  _implicitHeaderMode(0),
 | 
				
			||||||
 | 
					  _payloadLength(255),
 | 
				
			||||||
 | 
					  _crcMode(0),
 | 
				
			||||||
 | 
					  _fifo_tx_addr_ptr(0),
 | 
				
			||||||
 | 
					  _fifo_rx_addr_ptr(0),
 | 
				
			||||||
 | 
					  _packet({0}),
 | 
				
			||||||
 | 
					  _rxPacketLength(0),
 | 
				
			||||||
 | 
					  _preinit_done(false),
 | 
				
			||||||
 | 
					  _onReceive(NULL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // overide Stream timeout value
 | 
				
			||||||
 | 
					  setTimeout(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool sx128x::preInit() {
 | 
				
			||||||
 | 
					  // setup pins
 | 
				
			||||||
 | 
					  pinMode(_ss, OUTPUT);
 | 
				
			||||||
 | 
					  // set SS high
 | 
				
			||||||
 | 
					  digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  SPI.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check version (retry for up to 2 seconds)
 | 
				
			||||||
 | 
					  long start = millis();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t version_msb;
 | 
				
			||||||
 | 
					  uint8_t version_lsb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (((millis() - start) < 2000) && (millis() >= start)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      version_msb = readRegister(REG_FIRM_VER_MSB);
 | 
				
			||||||
 | 
					      version_lsb = readRegister(REG_FIRM_VER_LSB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if ((version_msb == 0xB7 && version_lsb == 0xA9) || (version_msb == 0xB5 && version_lsb == 0xA9)) {
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      delay(100);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if ((version_msb != 0xB7 || version_lsb != 0xA9) && (version_msb != 0xB5 || version_lsb != 0xA9)) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _preinit_done = true;
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx128x::readRegister(uint16_t address)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return singleTransfer(OP_READ_REGISTER_8X, address, 0x00);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::writeRegister(uint16_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    singleTransfer(OP_WRITE_REGISTER_8X, address, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx128x::singleTransfer(uint8_t opcode, uint16_t address, uint8_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t response;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(opcode);
 | 
				
			||||||
 | 
					    SPI.transfer((address & 0xFF00) >> 8);
 | 
				
			||||||
 | 
					    SPI.transfer(address & 0x00FF);
 | 
				
			||||||
 | 
					    if (opcode == OP_READ_REGISTER_8X) {
 | 
				
			||||||
 | 
					        SPI.transfer(0x00);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    response = SPI.transfer(value);
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return response;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::rxAntEnable()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (_txen != -1) {
 | 
				
			||||||
 | 
					        digitalWrite(_txen, LOW);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (_rxen != -1) {
 | 
				
			||||||
 | 
					        digitalWrite(_rxen, HIGH);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::txAntEnable()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (_txen != -1) {
 | 
				
			||||||
 | 
					        digitalWrite(_txen, HIGH);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (_rxen != -1) {
 | 
				
			||||||
 | 
					        digitalWrite(_rxen, LOW);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::loraMode() {
 | 
				
			||||||
 | 
					    // enable lora mode on the SX1262 chip
 | 
				
			||||||
 | 
					    uint8_t mode = MODE_LONG_RANGE_MODE_8X;
 | 
				
			||||||
 | 
					    executeOpcode(OP_PACKET_TYPE_8X, &mode, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::waitOnBusy() {
 | 
				
			||||||
 | 
					    unsigned long time = millis();
 | 
				
			||||||
 | 
					    if (_busy != -1) {
 | 
				
			||||||
 | 
					        while (digitalRead(_busy) == HIGH)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (millis() >= (time + 100)) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            // do nothing
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(opcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.transfer(buffer[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(opcode);
 | 
				
			||||||
 | 
					    SPI.transfer(0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        buffer[i] = SPI.transfer(0x00);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::writeBuffer(const uint8_t* buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(OP_FIFO_WRITE_8X);
 | 
				
			||||||
 | 
					    SPI.transfer(_fifo_tx_addr_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        SPI.transfer(buffer[i]);
 | 
				
			||||||
 | 
					        _fifo_tx_addr_ptr++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::readBuffer(uint8_t* buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    waitOnBusy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, LOW);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.beginTransaction(_spiSettings);
 | 
				
			||||||
 | 
					    SPI.transfer(OP_FIFO_READ_8X);
 | 
				
			||||||
 | 
					    SPI.transfer(_fifo_rx_addr_ptr);
 | 
				
			||||||
 | 
					    SPI.transfer(0x00);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < size; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        buffer[i] = SPI.transfer(0x00);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SPI.endTransaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    digitalWrite(_ss, HIGH);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr) {
 | 
				
			||||||
 | 
					  // because there is no access to these registers on the sx1280, we have
 | 
				
			||||||
 | 
					  // to set all these parameters at once or not at all.
 | 
				
			||||||
 | 
					  uint8_t buf[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = sf;
 | 
				
			||||||
 | 
					  buf[1] = bw;
 | 
				
			||||||
 | 
					  buf[2] = cr; 
 | 
				
			||||||
 | 
					  executeOpcode(OP_MODULATION_PARAMS_8X, buf, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (sf <= 6) {
 | 
				
			||||||
 | 
					      writeRegister(0x925, 0x1E);
 | 
				
			||||||
 | 
					  } else if (sf <= 8) {
 | 
				
			||||||
 | 
					      writeRegister(0x925, 0x37);
 | 
				
			||||||
 | 
					  } else if (sf >= 9) {
 | 
				
			||||||
 | 
					      writeRegister(0x925, 0x32);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  writeRegister(0x093C, 0x1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setPacketParams(uint32_t preamble, uint8_t headermode, uint8_t length, uint8_t crc) {
 | 
				
			||||||
 | 
					  // because there is no access to these registers on the sx1280, we have
 | 
				
			||||||
 | 
					  // to set all these parameters at once or not at all.
 | 
				
			||||||
 | 
					  uint8_t buf[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // calculate exponent and mantissa values for modem
 | 
				
			||||||
 | 
					  uint8_t e = 1;
 | 
				
			||||||
 | 
					  uint8_t m = 1;
 | 
				
			||||||
 | 
					  uint32_t preamblelen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (e <= 15; e++;) {
 | 
				
			||||||
 | 
					      for (m <= 15; m++;) {
 | 
				
			||||||
 | 
					          preamblelen = m * (uint32_t(1) << e);
 | 
				
			||||||
 | 
					          if (preamblelen >= preamble) break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (preamblelen >= preamble) break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = (e << 4) | m;
 | 
				
			||||||
 | 
					  buf[1] = headermode;
 | 
				
			||||||
 | 
					  buf[2] = length;
 | 
				
			||||||
 | 
					  buf[3] = crc;
 | 
				
			||||||
 | 
					  // standard IQ setting (no inversion)
 | 
				
			||||||
 | 
					  buf[4] = 0x40; 
 | 
				
			||||||
 | 
					  // unused params
 | 
				
			||||||
 | 
					  buf[5] = 0x00; 
 | 
				
			||||||
 | 
					  buf[6] = 0x00; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  executeOpcode(OP_PACKET_PARAMS_8X, buf, 7);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx128x::begin(unsigned long frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (_reset != -1) {
 | 
				
			||||||
 | 
					    pinMode(_reset, OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // perform reset
 | 
				
			||||||
 | 
					    digitalWrite(_reset, LOW);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					    digitalWrite(_reset, HIGH);
 | 
				
			||||||
 | 
					    delay(10);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (_busy != -1) {
 | 
				
			||||||
 | 
					      pinMode(_busy, INPUT);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!_preinit_done) {
 | 
				
			||||||
 | 
					    if (!preInit()) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					  loraMode();
 | 
				
			||||||
 | 
					  rxAntEnable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setFrequency(frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set LNA boost
 | 
				
			||||||
 | 
					  // todo: implement this
 | 
				
			||||||
 | 
					  //writeRegister(REG_LNA, 0x96);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setModulationParams(_sf, _bw, _cr);
 | 
				
			||||||
 | 
					  setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set output power to 2 dBm
 | 
				
			||||||
 | 
					  setTxPower(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // set base addresses
 | 
				
			||||||
 | 
					  uint8_t basebuf[2] = {0};
 | 
				
			||||||
 | 
					  executeOpcode(OP_BUFFER_BASE_ADDR_8X, basebuf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::end()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in sleep mode
 | 
				
			||||||
 | 
					  sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // stop SPI
 | 
				
			||||||
 | 
					  SPI.end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _preinit_done = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx128x::beginPacket(int implicitHeader)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  // put in standby mode
 | 
				
			||||||
 | 
					  idle();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (implicitHeader) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _payloadLength = 0;
 | 
				
			||||||
 | 
					  _fifo_tx_addr_ptr = 0;
 | 
				
			||||||
 | 
					  setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx128x::endPacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  txAntEnable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // put in single TX mode
 | 
				
			||||||
 | 
					  uint8_t timeout[3] = {0};
 | 
				
			||||||
 | 
					  executeOpcode(OP_TX_8X, timeout, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t buf[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = 0x00;
 | 
				
			||||||
 | 
					  buf[1] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // wait for TX done
 | 
				
			||||||
 | 
					  while ((buf[1] & IRQ_TX_DONE_MASK_8X) == 0) {
 | 
				
			||||||
 | 
					    buf[0] = 0x00;
 | 
				
			||||||
 | 
					    buf[1] = 0x00;
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
 | 
				
			||||||
 | 
					    yield();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // clear IRQ's
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t mask[2];
 | 
				
			||||||
 | 
					  mask[0] = 0x00;
 | 
				
			||||||
 | 
					  mask[1] = IRQ_TX_DONE_MASK_8X;
 | 
				
			||||||
 | 
					  executeOpcode(OP_CLEAR_IRQ_STATUS_8X, mask, 2);
 | 
				
			||||||
 | 
					  return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx128x::modemStatus() {
 | 
				
			||||||
 | 
					    // imitate the register status from the sx1276 / 78
 | 
				
			||||||
 | 
					    uint8_t buf[2] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t clearbuf[2] = {0};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t byte = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (buf[0] & IRQ_PREAMBLE_DET_MASK_8X != 0) {
 | 
				
			||||||
 | 
					        byte = byte | 0x01 | 0x04;
 | 
				
			||||||
 | 
					        // clear register after reading
 | 
				
			||||||
 | 
					        clearbuf[0] = 0xFF;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (buf[1] & IRQ_HEADER_DET_MASK_8X != 0) {
 | 
				
			||||||
 | 
					        byte = byte | 0x02 | 0x04;
 | 
				
			||||||
 | 
					        // clear register after reading
 | 
				
			||||||
 | 
					        clearbuf[1] = 0xFF;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_CLEAR_IRQ_STATUS_8X, clearbuf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return byte;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx128x::currentRssiRaw() {
 | 
				
			||||||
 | 
					    uint8_t byte = 0;
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_CURRENT_RSSI_8X, &byte, 1);
 | 
				
			||||||
 | 
					    return byte;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx128x::currentRssi() {
 | 
				
			||||||
 | 
					    uint8_t byte = 0;
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_CURRENT_RSSI_8X, &byte, 1);
 | 
				
			||||||
 | 
					    int rssi = -byte / 2;
 | 
				
			||||||
 | 
					    return rssi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx128x::packetRssiRaw() {
 | 
				
			||||||
 | 
					    uint8_t buf[5] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
 | 
				
			||||||
 | 
					    return buf[0];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx128x::packetRssi() {
 | 
				
			||||||
 | 
					    // may need more calculations here
 | 
				
			||||||
 | 
					    uint8_t buf[5] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
 | 
				
			||||||
 | 
					    int pkt_rssi = -buf[0] / 2;
 | 
				
			||||||
 | 
					    return pkt_rssi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t ISR_VECT sx128x::packetSnrRaw() {
 | 
				
			||||||
 | 
					    uint8_t buf[5] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 5);
 | 
				
			||||||
 | 
					    return buf[1];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ISR_VECT sx128x::packetSnr() {
 | 
				
			||||||
 | 
					    uint8_t buf[5] = {0};
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_PACKET_STATUS_8X, buf, 3);
 | 
				
			||||||
 | 
					    return float(buf[1]) * 0.25;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long sx128x::packetFrequencyError()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int32_t freqError = 0;
 | 
				
			||||||
 | 
					  // todo: implement this, page 120 of sx1280 datasheet
 | 
				
			||||||
 | 
					  const float fError = 0.0;
 | 
				
			||||||
 | 
					  return static_cast<long>(fError);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sx128x::write(uint8_t byte)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  return write(&byte, sizeof(byte));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t sx128x::write(const uint8_t *buffer, size_t size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if ((_payloadLength + size) > MAX_PKT_LENGTH) {
 | 
				
			||||||
 | 
					      size = MAX_PKT_LENGTH - _payloadLength;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // write data
 | 
				
			||||||
 | 
					  writeBuffer(buffer, size);
 | 
				
			||||||
 | 
					  _payloadLength = _payloadLength + size;
 | 
				
			||||||
 | 
					  return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx128x::available()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return _rxPacketLength - _packetIndex;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int ISR_VECT sx128x::read()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t byte = _packet[_packetIndex];
 | 
				
			||||||
 | 
					  _packetIndex++;
 | 
				
			||||||
 | 
					  return byte;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int sx128x::peek()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (!available()) {
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t b = _packet[_packetIndex];
 | 
				
			||||||
 | 
					  return b;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::flush()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::onReceive(void(*callback)(int))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _onReceive = callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (callback) {
 | 
				
			||||||
 | 
					    pinMode(_dio0, INPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set preamble and header detection irqs, plus dio0 mask
 | 
				
			||||||
 | 
					      uint8_t buf[8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set irq masks, enable all
 | 
				
			||||||
 | 
					      buf[0] = 0xFF; 
 | 
				
			||||||
 | 
					      buf[1] = 0xFF;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set dio0 masks
 | 
				
			||||||
 | 
					      buf[2] = 0x00;
 | 
				
			||||||
 | 
					      buf[3] = IRQ_RX_DONE_MASK_8X; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set dio1 masks
 | 
				
			||||||
 | 
					      buf[4] = 0x00; 
 | 
				
			||||||
 | 
					      buf[5] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // set dio2 masks
 | 
				
			||||||
 | 
					      buf[6] = 0x00; 
 | 
				
			||||||
 | 
					      buf[7] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      executeOpcode(OP_SET_IRQ_FLAGS_8X, buf, 8);
 | 
				
			||||||
 | 
					//#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					//    SPI.usingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					//#endif
 | 
				
			||||||
 | 
					    attachInterrupt(digitalPinToInterrupt(_dio0), sx128x::onDio0Rise, RISING);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    detachInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					//#ifdef SPI_HAS_NOTUSINGINTERRUPT
 | 
				
			||||||
 | 
					//    SPI.notUsingInterrupt(digitalPinToInterrupt(_dio0));
 | 
				
			||||||
 | 
					//#endif
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::receive(int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (size > 0) {
 | 
				
			||||||
 | 
					    implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // tell radio payload length
 | 
				
			||||||
 | 
					    _rxPacketLength = size;
 | 
				
			||||||
 | 
					    //_payloadLength = size;
 | 
				
			||||||
 | 
					    //setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    explicitHeaderMode();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rxAntEnable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t mode[3] = {0xFF, 0xFF, 0xFF}; // continuous mode
 | 
				
			||||||
 | 
					    executeOpcode(OP_RX_8X, mode, 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::idle()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					      #if HAS_TCXO
 | 
				
			||||||
 | 
					          // STDBY_XOSC
 | 
				
			||||||
 | 
					          uint8_t byte = 0x01;
 | 
				
			||||||
 | 
					      #else
 | 
				
			||||||
 | 
					          // STDBY_RC
 | 
				
			||||||
 | 
					          uint8_t byte = 0x00;
 | 
				
			||||||
 | 
					      #endif
 | 
				
			||||||
 | 
					      executeOpcode(OP_STANDBY_8X, &byte, 1); 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::sleep()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t byte = 0x00;
 | 
				
			||||||
 | 
					    executeOpcode(OP_SLEEP_8X, &byte, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::enableTCXO() {
 | 
				
			||||||
 | 
					    // todo: need to check how to implement on sx1280
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::disableTCXO() {
 | 
				
			||||||
 | 
					    // todo: need to check how to implement on sx1280
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setTxPower(int level, int outputPin) {
 | 
				
			||||||
 | 
					    if (level > 13) {
 | 
				
			||||||
 | 
					        level = 13;
 | 
				
			||||||
 | 
					    } else if (level < -18) {
 | 
				
			||||||
 | 
					        level = -18;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _txp = level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    level = level + 18;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t tx_buf[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tx_buf[0] = level;
 | 
				
			||||||
 | 
					    tx_buf[1] = 0xE0; // ramping time - 20 microseconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_TX_PARAMS_8X, tx_buf, 2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t sx128x::getTxPower() {
 | 
				
			||||||
 | 
					      return _txp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setFrequency(unsigned long frequency) {
 | 
				
			||||||
 | 
					  _frequency = frequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t buf[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32_t freq = (uint32_t)((double)frequency / (double)FREQ_STEP_8X);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  buf[0] = ((freq >> 16) & 0xFF);
 | 
				
			||||||
 | 
					  buf[1] = ((freq >> 8) & 0xFF);
 | 
				
			||||||
 | 
					  buf[2] = (freq & 0xFF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  executeOpcode(OP_RF_FREQ_8X, buf, 3);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t sx128x::getFrequency() {
 | 
				
			||||||
 | 
					  // we can't read the frequency on the sx1280
 | 
				
			||||||
 | 
					  uint32_t frequency = _frequency;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return frequency;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setSpreadingFactor(int sf)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (sf < 5) {
 | 
				
			||||||
 | 
					      sf = 5;
 | 
				
			||||||
 | 
					  } else if (sf > 12) {
 | 
				
			||||||
 | 
					    sf = 12;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _sf = sf << 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setModulationParams(sf << 4, _bw, _cr);
 | 
				
			||||||
 | 
					  handleLowDataRate();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					long sx128x::getSignalBandwidth()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int bw = _bw;
 | 
				
			||||||
 | 
					  switch (bw) {
 | 
				
			||||||
 | 
					      case 0x34: return 203.125E3;
 | 
				
			||||||
 | 
					      case 0x26: return 406.25E3;
 | 
				
			||||||
 | 
					      case 0x18: return 812.5E3;
 | 
				
			||||||
 | 
					      case 0x0A: return 1625E3;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::handleLowDataRate(){
 | 
				
			||||||
 | 
					    // todo: do i need this??
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::optimizeModemSensitivity(){
 | 
				
			||||||
 | 
					    // todo: check if there's anything the sx1280 can do here
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setSignalBandwidth(long sbw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					      if (sbw <= 203.125E3) {
 | 
				
			||||||
 | 
					          _bw = 0x34;
 | 
				
			||||||
 | 
					      } else if (sbw <= 406.25E3) {
 | 
				
			||||||
 | 
					          _bw = 0x26;
 | 
				
			||||||
 | 
					      } else if (sbw <= 812.5E3) {
 | 
				
			||||||
 | 
					          _bw = 0x18;
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					          _bw = 0x0A;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setModulationParams(_sf, _bw, _cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleLowDataRate();
 | 
				
			||||||
 | 
					  optimizeModemSensitivity();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setCodingRate4(int denominator)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  if (denominator < 5) {
 | 
				
			||||||
 | 
					    denominator = 5;
 | 
				
			||||||
 | 
					  } else if (denominator > 8) {
 | 
				
			||||||
 | 
					    denominator = 8;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  _cr = denominator - 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // todo: add support for new interleaving scheme, see page 117 of sx1280
 | 
				
			||||||
 | 
					  // datasheet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // update cr values for sx1280's use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setModulationParams(_sf, _bw, _cr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setPreambleLength(long length)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _preambleLength = length;
 | 
				
			||||||
 | 
					  setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setSyncWord(int sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // not implemented
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::enableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					      _crcMode = 0x20;
 | 
				
			||||||
 | 
					      setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::disableCrc()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _crcMode = 0;
 | 
				
			||||||
 | 
					    setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					byte sx128x::random()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // todo: implement
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setPins(int ss, int reset, int dio0, int busy, int rxen, int txen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _ss = ss;
 | 
				
			||||||
 | 
					  _reset = reset;
 | 
				
			||||||
 | 
					  _dio0 = dio0;
 | 
				
			||||||
 | 
					  _busy = busy;
 | 
				
			||||||
 | 
					  _rxen = rxen;
 | 
				
			||||||
 | 
					  _txen = txen;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::setSPIFrequency(uint32_t frequency)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::dumpRegisters(Stream& out)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (int i = 0; i < 128; i++) {
 | 
				
			||||||
 | 
					    out.print("0x");
 | 
				
			||||||
 | 
					    out.print(i, HEX);
 | 
				
			||||||
 | 
					    out.print(": 0x");
 | 
				
			||||||
 | 
					    out.println(readRegister(i), HEX);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::explicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  _implicitHeaderMode = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void sx128x::implicitHeaderMode()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _implicitHeaderMode = 0x80;
 | 
				
			||||||
 | 
					    setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ISR_VECT sx128x::handleDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint8_t buf[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    buf[0] = 0x00;
 | 
				
			||||||
 | 
					    buf[1] = 0x00;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcodeRead(OP_GET_IRQ_STATUS_8X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    executeOpcode(OP_CLEAR_IRQ_STATUS_8X, buf, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((buf[1] & IRQ_PAYLOAD_CRC_ERROR_MASK_8X) == 0) {
 | 
				
			||||||
 | 
					        // received a packet
 | 
				
			||||||
 | 
					        _packetIndex = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint8_t rxbuf[2] = {0};
 | 
				
			||||||
 | 
					        executeOpcodeRead(OP_RX_BUFFER_STATUS_8X, rxbuf, 2);
 | 
				
			||||||
 | 
					        _rxPacketLength = rxbuf[0];
 | 
				
			||||||
 | 
					        _fifo_rx_addr_ptr = rxbuf[1];
 | 
				
			||||||
 | 
					        readBuffer(_packet, _rxPacketLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (_onReceive) {
 | 
				
			||||||
 | 
					            _onReceive(_rxPacketLength);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ISR_VECT sx128x::onDio0Rise()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  sx128x_modem.handleDio0Rise();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sx128x sx128x_modem;
 | 
				
			||||||
							
								
								
									
										144
									
								
								sx128x.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								sx128x.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					// Copyright (c) Sandeep Mistry. All rights reserved.
 | 
				
			||||||
 | 
					// Licensed under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Modifications and additions copyright 2023 by Mark Qvist
 | 
				
			||||||
 | 
					// Obviously still under the MIT license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SX128X_H
 | 
				
			||||||
 | 
					#define SX128X_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <Arduino.h>
 | 
				
			||||||
 | 
					#include <SPI.h>
 | 
				
			||||||
 | 
					#include "Modem.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_SS_PIN    10
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_RESET_PIN 9
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_DIO0_PIN  2
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_RXEN_PIN  -1
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_TXEN_PIN  -1
 | 
				
			||||||
 | 
					#define LORA_DEFAULT_BUSY_PIN  -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PA_OUTPUT_RFO_PIN      0
 | 
				
			||||||
 | 
					#define PA_OUTPUT_PA_BOOST_PIN 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RSSI_OFFSET 157
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class sx128x : public Stream {
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					  sx128x();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int begin(unsigned long frequency);
 | 
				
			||||||
 | 
					  void end();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int beginPacket(int implicitHeader = false);
 | 
				
			||||||
 | 
					  int endPacket();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int parsePacket(int size = 0);
 | 
				
			||||||
 | 
					  int packetRssi();
 | 
				
			||||||
 | 
					  int currentRssi();
 | 
				
			||||||
 | 
					  uint8_t packetRssiRaw();
 | 
				
			||||||
 | 
					  uint8_t currentRssiRaw();
 | 
				
			||||||
 | 
					  uint8_t packetSnrRaw();
 | 
				
			||||||
 | 
					  float packetSnr();
 | 
				
			||||||
 | 
					  long packetFrequencyError();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // from Print
 | 
				
			||||||
 | 
					  virtual size_t write(uint8_t byte);
 | 
				
			||||||
 | 
					  virtual size_t write(const uint8_t *buffer, size_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // from Stream
 | 
				
			||||||
 | 
					  virtual int available();
 | 
				
			||||||
 | 
					  virtual int read();
 | 
				
			||||||
 | 
					  virtual int peek();
 | 
				
			||||||
 | 
					  virtual void flush();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void onReceive(void(*callback)(int));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void receive(int size = 0);
 | 
				
			||||||
 | 
					  void idle();
 | 
				
			||||||
 | 
					  void sleep();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool preInit();
 | 
				
			||||||
 | 
					  uint8_t getTxPower();
 | 
				
			||||||
 | 
					  void setTxPower(int level, int outputPin = PA_OUTPUT_PA_BOOST_PIN);
 | 
				
			||||||
 | 
					  uint32_t getFrequency();
 | 
				
			||||||
 | 
					  void setFrequency(unsigned long frequency);
 | 
				
			||||||
 | 
					  void setSpreadingFactor(int sf);
 | 
				
			||||||
 | 
					  long getSignalBandwidth();
 | 
				
			||||||
 | 
					  void setSignalBandwidth(long sbw);
 | 
				
			||||||
 | 
					  void setCodingRate4(int denominator);
 | 
				
			||||||
 | 
					  void setPreambleLength(long length);
 | 
				
			||||||
 | 
					  void setSyncWord(int sw);
 | 
				
			||||||
 | 
					  uint8_t modemStatus();
 | 
				
			||||||
 | 
					  void enableCrc();
 | 
				
			||||||
 | 
					  void disableCrc();
 | 
				
			||||||
 | 
					  void enableTCXO();
 | 
				
			||||||
 | 
					  void disableTCXO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void txAntEnable();
 | 
				
			||||||
 | 
					  void rxAntEnable();
 | 
				
			||||||
 | 
					  void loraMode();
 | 
				
			||||||
 | 
					  void waitOnBusy();
 | 
				
			||||||
 | 
					  void executeOpcode(uint8_t opcode, uint8_t *buffer, uint8_t size);
 | 
				
			||||||
 | 
					  void executeOpcodeRead(uint8_t opcode, uint8_t *buffer, uint8_t size);
 | 
				
			||||||
 | 
					  void writeBuffer(const uint8_t* buffer, size_t size);
 | 
				
			||||||
 | 
					  void readBuffer(uint8_t* buffer, size_t size);
 | 
				
			||||||
 | 
					  void setPacketParams(uint32_t preamble, uint8_t headermode, uint8_t length, uint8_t crc);
 | 
				
			||||||
 | 
					  void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // deprecated
 | 
				
			||||||
 | 
					  void crc() { enableCrc(); }
 | 
				
			||||||
 | 
					  void noCrc() { disableCrc(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  byte random();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setPins(int ss = LORA_DEFAULT_SS_PIN, int reset = LORA_DEFAULT_RESET_PIN, int dio0 = LORA_DEFAULT_DIO0_PIN, int busy = LORA_DEFAULT_BUSY_PIN, int rxen = LORA_DEFAULT_RXEN_PIN, int txen = LORA_DEFAULT_TXEN_PIN);
 | 
				
			||||||
 | 
					  void setSPIFrequency(uint32_t frequency);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void dumpRegisters(Stream& out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  void explicitHeaderMode();
 | 
				
			||||||
 | 
					  void implicitHeaderMode();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void handleDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t readRegister(uint16_t address);
 | 
				
			||||||
 | 
					  void writeRegister(uint16_t address, uint8_t value);
 | 
				
			||||||
 | 
					  uint8_t singleTransfer(uint8_t opcode, uint16_t address, uint8_t value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static void onDio0Rise();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void handleLowDataRate();
 | 
				
			||||||
 | 
					  void optimizeModemSensitivity();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					  SPISettings _spiSettings;
 | 
				
			||||||
 | 
					  int _ss;
 | 
				
			||||||
 | 
					  int _reset;
 | 
				
			||||||
 | 
					  int _dio0;
 | 
				
			||||||
 | 
					  int _rxen;
 | 
				
			||||||
 | 
					  int _txen;
 | 
				
			||||||
 | 
					  int _busy;
 | 
				
			||||||
 | 
					  int _modem;
 | 
				
			||||||
 | 
					  unsigned long _frequency;
 | 
				
			||||||
 | 
					  int _txp;
 | 
				
			||||||
 | 
					  uint8_t _sf;
 | 
				
			||||||
 | 
					  uint8_t _bw;
 | 
				
			||||||
 | 
					  uint8_t _cr;
 | 
				
			||||||
 | 
					  int _packetIndex;
 | 
				
			||||||
 | 
					  uint32_t _preambleLength;
 | 
				
			||||||
 | 
					  int _implicitHeaderMode;
 | 
				
			||||||
 | 
					  int _payloadLength;
 | 
				
			||||||
 | 
					  int _crcMode;
 | 
				
			||||||
 | 
					  int _fifo_tx_addr_ptr;
 | 
				
			||||||
 | 
					  int _fifo_rx_addr_ptr;
 | 
				
			||||||
 | 
					  uint8_t _packet[256];
 | 
				
			||||||
 | 
					  bool _preinit_done;
 | 
				
			||||||
 | 
					  int _rxPacketLength;
 | 
				
			||||||
 | 
					  void (*_onReceive)(int);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern sx128x sx128x_modem;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user