Accurate preamble and airtime calculations on SX1280. Fix airtime calculation on SX1262 when LDRO is enabled.

master
Mark Qvist 2 months ago
parent b667e825f8
commit c39164e272
  1. 36
      RNode_Firmware.ino
  2. 20
      Utilities.h
  3. 24
      sx126x.cpp
  4. 4
      sx126x.h
  5. 6
      sx127x.cpp
  6. 2
      sx127x.h
  7. 60
      sx128x.cpp
  8. 4
      sx128x.h

@ -557,18 +557,44 @@ void flushQueue(void) {
#endif
}
#define PHY_HEADER_LORA_SYMBOLS 8
#define PHY_HEADER_LORA_SYMBOLS 20
#define PHY_CRC_LORA_BITS 16
void add_airtime(uint16_t written) {
#if MCU_VARIANT == MCU_ESP32 || MCU_VARIANT == MCU_NRF52
float lora_symbols = 0;
float packet_cost_ms = 0.0;
float payload_cost_ms = ((float)written * lora_us_per_byte)/1000.0;
packet_cost_ms += payload_cost_ms;
packet_cost_ms += (lora_preamble_symbols+4.25)*lora_symbol_time_ms;
packet_cost_ms += PHY_HEADER_LORA_SYMBOLS * lora_symbol_time_ms;
int ldr_opt = 0; if (lora_low_datarate) ldr_opt = 1;
#if MODEM == SX1276 || MODEM == SX1278
lora_symbols += (8*written + PHY_CRC_LORA_BITS - 4*lora_sf + 8 + PHY_HEADER_LORA_SYMBOLS);
lora_symbols /= 4*(lora_sf-2*ldr_opt);
lora_symbols *= lora_cr;
lora_symbols += lora_preamble_symbols + 0.25 + 8;
packet_cost_ms += lora_symbols * lora_symbol_time_ms;
#elif MODEM == SX1262 || MODEM == SX1280
if (lora_sf < 7) {
lora_symbols += (8*written + PHY_CRC_LORA_BITS - 4*lora_sf + PHY_HEADER_LORA_SYMBOLS);
lora_symbols /= 4*lora_sf;
lora_symbols *= lora_cr;
lora_symbols += lora_preamble_symbols + 2.25 + 8;
packet_cost_ms += lora_symbols * lora_symbol_time_ms;
} else {
lora_symbols += (8*written + PHY_CRC_LORA_BITS - 4*lora_sf + 8 + PHY_HEADER_LORA_SYMBOLS);
lora_symbols /= 4*(lora_sf-2*ldr_opt);
lora_symbols *= lora_cr;
lora_symbols += lora_preamble_symbols + 0.25 + 8;
packet_cost_ms += lora_symbols * lora_symbol_time_ms;
}
#endif
uint16_t cb = current_airtime_bin();
uint16_t nb = cb+1; if (nb == AIRTIME_BINS) { nb = 0; }
airtime_bins[cb] += packet_cost_ms;
airtime_bins[nb] = 0;
#endif
}

@ -863,8 +863,8 @@ void kiss_indicate_phy_stats() {
#if MCU_VARIANT == MCU_ESP32
uint16_t lst = (uint16_t)(lora_symbol_time_ms*1000);
uint16_t lsr = (uint16_t)(lora_symbol_rate);
uint16_t prs = (uint16_t)(lora_preamble_symbols+4);
uint16_t prt = (uint16_t)((lora_preamble_symbols+4)*lora_symbol_time_ms);
uint16_t prs = (uint16_t)(lora_preamble_symbols);
uint16_t prt = (uint16_t)((lora_preamble_symbols)*lora_symbol_time_ms);
uint16_t cst = (uint16_t)(csma_slot_ms);
serial_write(FEND);
serial_write(CMD_STAT_PHYPRM);
@ -1091,20 +1091,14 @@ void updateBitrate() {
lora_symbol_time_ms = (1.0/lora_symbol_rate)*1000.0;
lora_bitrate = (uint32_t)(lora_sf * ( (4.0/(float)lora_cr) / ((float)(pow(2, lora_sf))/((float)lora_bw/1000.0)) ) * 1000.0);
lora_us_per_byte = 1000000.0/((float)lora_bitrate/8.0);
csma_slot_ms = lora_symbol_time_ms*12;
csma_slot_ms = lora_symbol_time_ms*CSMA_SLOT_SYMBOLS;
if (csma_slot_ms > CSMA_SLOT_MAX_MS) { csma_slot_ms = CSMA_SLOT_MAX_MS; }
if (csma_slot_ms < CSMA_SLOT_MIN_MS) { csma_slot_ms = CSMA_SLOT_MIN_MS; }
float target_preamble_symbols = (LORA_PREAMBLE_TARGET_MS/lora_symbol_time_ms)-LORA_PREAMBLE_SYMBOLS_HW;
#if MODEM == SX1280
target_preamble_symbols = 12;
#else
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) {
target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN;
} else {
target_preamble_symbols = ceil(target_preamble_symbols);
}
#endif
float target_preamble_symbols = LORA_PREAMBLE_TARGET_MS/lora_symbol_time_ms;
if (target_preamble_symbols < LORA_PREAMBLE_SYMBOLS_MIN) { target_preamble_symbols = LORA_PREAMBLE_SYMBOLS_MIN; }
else { target_preamble_symbols = (ceil)(target_preamble_symbols); }
lora_preamble_symbols = (long)target_preamble_symbols;
setPreamble();

@ -252,14 +252,14 @@ void sx126x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro) {
executeOpcode(OP_MODULATION_PARAMS_6X, buf, 8);
}
void sx126x::setPacketParams(long preamble, uint8_t headermode, uint8_t length, uint8_t crc) {
void sx126x::setPacketParams(long preamble_symbols, uint8_t headermode, uint8_t payload_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[0] = uint8_t((preamble_symbols & 0xFF00) >> 8);
buf[1] = uint8_t((preamble_symbols & 0x00FF));
buf[2] = headermode;
buf[3] = length;
buf[3] = payload_length;
buf[4] = crc;
buf[5] = 0x00; // standard IQ setting (no inversion)
buf[6] = 0x00; // unused params
@ -642,12 +642,14 @@ long sx126x::getSignalBandwidth() {
return 0;
}
void sx126x::handleLowDataRate(){
if ( long( (1<<_sf) / (getSignalBandwidth()/1000)) > 16) { _ldro = 0x01; }
else { _ldro = 0x00; }
extern bool lora_low_datarate;
void sx126x::handleLowDataRate() {
if ( long( (1<<_sf) / (getSignalBandwidth()/1000)) > 16)
{ _ldro = 0x01; lora_low_datarate = true; }
else { _ldro = 0x00; lora_low_datarate = false; }
}
// TODO: check if there's anything the sx1262 can do here
// TODO: Check if there's anything the sx1262 can do here
void sx126x::optimizeModemSensitivity(){ }
void sx126x::setSignalBandwidth(long sbw) {
@ -675,9 +677,9 @@ void sx126x::setCodingRate4(int denominator) {
setModulationParams(_sf, _bw, cr, _ldro);
}
void sx126x::setPreambleLength(long length) {
_preambleLength = length;
setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode);
void sx126x::setPreambleLength(long preamble_symbols) {
_preambleLength = preamble_symbols;
setPacketParams(preamble_symbols, _implicitHeaderMode, _payloadLength, _crcMode);
}
void sx126x::setSyncWord(uint16_t sw) {

@ -66,7 +66,7 @@ public:
long getSignalBandwidth();
void setSignalBandwidth(long sbw);
void setCodingRate4(int denominator);
void setPreambleLength(long length);
void setPreambleLength(long preamble_symbols);
void setSyncWord(uint16_t sw);
uint8_t modemStatus();
void enableCrc();
@ -81,7 +81,7 @@ public:
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(long preamble, uint8_t headermode, uint8_t length, uint8_t crc);
void setPacketParams(long preamble_symbols, uint8_t headermode, uint8_t payload_length, uint8_t crc);
void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr, int ldro);

@ -440,19 +440,23 @@ void sx127x::setCodingRate4(int denominator) {
writeRegister(REG_MODEM_CONFIG_1_7X, (readRegister(REG_MODEM_CONFIG_1_7X) & 0xf1) | (cr << 1));
}
void sx127x::setPreambleLength(long length) {
void sx127x::setPreambleLength(long preamble_symbols) {
long length = preamble_symbols - 4;
writeRegister(REG_PREAMBLE_MSB_7X, (uint8_t)(length >> 8));
writeRegister(REG_PREAMBLE_LSB_7X, (uint8_t)(length >> 0));
}
extern bool lora_low_datarate;
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));
lora_low_datarate = true;
} else {
// Only set auto AGC
writeRegister(REG_MODEM_CONFIG_3_7X, (1<<2));
lora_low_datarate = false;
}
}

@ -63,7 +63,7 @@ public:
long getSignalBandwidth();
void setSignalBandwidth(long sbw);
void setCodingRate4(int denominator);
void setPreambleLength(long length);
void setPreambleLength(long preamble_symbols);
void setSyncWord(uint8_t sw);
uint8_t modemStatus();
void enableCrc();

@ -269,32 +269,43 @@ void sx128x::setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr) {
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;
while (e <= 15) {
uint8_t preamble_e = 0;
uint8_t preamble_m = 0;
uint32_t last_me_result_target = 0;
extern long lora_preamble_symbols;
void sx128x::setPacketParams(uint32_t target_preamble_symbols, uint8_t headermode, uint8_t payload_length, uint8_t crc) {
if (last_me_result_target != target_preamble_symbols) {
// Calculate exponent and mantissa values for modem
if (target_preamble_symbols >= 0xF000) target_preamble_symbols = 0xF000;
uint32_t calculated_preamble_symbols;
uint8_t e = 1;
uint8_t m = 1;
while (e <= 15) {
while (m <= 15) {
preamblelen = m * (pow(2,e));
if (preamblelen >= preamble) break;
m++;
calculated_preamble_symbols = m * (pow(2,e));
if (calculated_preamble_symbols >= target_preamble_symbols-4) break;
m++;
}
if (preamblelen >= preamble) break;
m = 0;
e++;
if (calculated_preamble_symbols >= target_preamble_symbols-4) break;
m = 1; e++;
}
last_me_result_target = target_preamble_symbols;
lora_preamble_symbols = calculated_preamble_symbols+4;
_preambleLength = lora_preamble_symbols;
preamble_e = e;
preamble_m = m;
}
buf[0] = (e << 4) | m;
uint8_t buf[7];
buf[0] = (preamble_e << 4) | preamble_m;
buf[1] = headermode;
buf[2] = length;
buf[2] = payload_length;
buf[3] = crc;
buf[4] = 0x40; // standard IQ setting (no inversion)
buf[5] = 0x00; // unused params
buf[4] = 0x40; // Standard IQ setting (no inversion)
buf[5] = 0x00; // Unused params
buf[6] = 0x00;
executeOpcode(OP_PACKET_PARAMS_8X, buf, 7);
@ -847,10 +858,15 @@ void sx128x::setCodingRate4(int denominator) {
setModulationParams(_sf, _bw, _cr);
}
void sx128x::handleLowDataRate() { } // TODO: Is this needed for SX1280?
extern bool lora_low_datarate;
void sx128x::handleLowDataRate() {
if (_sf > 10) { lora_low_datarate = true; }
else { lora_low_datarate = false; }
}
void sx128x::optimizeModemSensitivity() { } // TODO: Check if there's anything the sx1280 can do here
uint8_t sx128x::getCodingRate4() { return _cr + 4; }
void sx128x::setPreambleLength(long length) { _preambleLength = length; setPacketParams(length, _implicitHeaderMode, _payloadLength, _crcMode); }
void sx128x::setPreambleLength(long preamble_symbols) { setPacketParams(preamble_symbols, _implicitHeaderMode, _payloadLength, _crcMode); }
void sx128x::setSyncWord(int sw) { } // TODO: Implement
void sx128x::enableTCXO() { } // TODO: Need to check how to implement on sx1280
void sx128x::disableTCXO() { } // TODO: Need to check how to implement on sx1280

@ -67,7 +67,7 @@ public:
void setSignalBandwidth(uint32_t sbw);
void setCodingRate4(int denominator);
uint8_t getCodingRate4();
void setPreambleLength(long length);
void setPreambleLength(long preamble_symbols);
void setSyncWord(int sw);
uint8_t modemStatus();
void clearIRQStatus();
@ -84,7 +84,7 @@ public:
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 setPacketParams(uint32_t target_preamble_symbols, uint8_t headermode, uint8_t payload_length, uint8_t crc);
void setModulationParams(uint8_t sf, uint8_t bw, uint8_t cr);
void crc() { enableCrc(); }

Loading…
Cancel
Save