diff --git a/Utilities.h b/Utilities.h index 79546cd..eaf71db 100644 --- a/Utilities.h +++ b/Utilities.h @@ -1263,54 +1263,104 @@ int getTxPower() { return (int)txp; } +#if HAS_LORA_PA + const int tx_gain[PA_GAIN_POINTS] = {PA_GAIN_VALUES}; +#endif + +int map_target_power_to_modem_output(int target_tx_power) { + #if HAS_LORA_PA + int modem_output_dbm = -9; + for (int i = 0; i < PA_GAIN_POINTS; i++) { + int gain = tx_gain[i]; + int effective_output_dbm = i + gain; + printf("At %d dBm modem output, gain is %d dBm, effective output is %d\n", i, gain, effective_output_dbm); + if (effective_output_dbm > target_tx_power) { + int diff = effective_output_dbm - target_tx_power; + modem_output_dbm = -1*diff; + break; + } else if (effective_output_dbm == target_tx_power) { + modem_output_dbm = i; break; + } else if (i == PA_GAIN_POINTS-1) { + int diff = target_tx_power - effective_output_dbm; + modem_output_dbm = i+diff; break; + } + } + #else + int modem_output_dbm = target_tx_power; + #endif + + return modem_output_dbm; +} + +int map_modem_output_to_target_power(int modem_output_dbm) { + #if HAS_LORA_PA + if (modem_output_dbm < 0) { modem_output_dbm = 0; } + if (modem_output_dbm >= PA_GAIN_POINTS) { modem_output_dbm = PA_GAIN_POINTS-1; } + int gain = tx_gain[modem_output_dbm]; + int target_tx_power = modem_output_dbm+gain; + #else + int target_tx_power = modem_output_dbm; + #endif + + return target_tx_power; +} + void setTXPower() { if (radio_online) { - if (model == MODEL_11) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); - if (model == MODEL_12) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); + int mapped_lora_txp = map_target_power_to_modem_output(lora_txp); + + #if HAS_LORA_PA + int real_lora_txp = map_modem_output_to_target_power(mapped_lora_txp); + lora_txp = real_lora_txp; + #endif - if (model == MODEL_C6) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); - if (model == MODEL_C7) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); + if (model == MODEL_11) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); + if (model == MODEL_12) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); - if (model == MODEL_A1) 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_A4) LoRa->setTxPower(lora_txp, PA_OUTPUT_RFO_PIN); - if (model == MODEL_A5) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_A6) 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_A9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_AA) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_AC) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_C6) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); + if (model == MODEL_C7) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); - if (model == MODEL_BA) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_BB) 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_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_A1) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_A2) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_A3) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); + if (model == MODEL_A4) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); + if (model == MODEL_A5) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_A6) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_A7) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_A8) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_A9) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_AA) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_AC) LoRa->setTxPower(mapped_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_C5) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_CA) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_BA) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_BB) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_B3) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_B4) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_B8) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_B9) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_D4) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_D9) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_C4) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_C9) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_C5) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_CA) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_C8) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_DB) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_DC) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_D4) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_D9) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_DD) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_DE) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_DB) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_DC) LoRa->setTxPower(mapped_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_E3) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); - if (model == MODEL_E8) LoRa->setTxPower(lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_DD) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_DE) LoRa->setTxPower(mapped_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_E4) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_E9) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_E3) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_E8) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + + if (model == MODEL_FE) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_PA_BOOST_PIN); + if (model == MODEL_FF) LoRa->setTxPower(mapped_lora_txp, PA_OUTPUT_RFO_PIN); } } @@ -1507,7 +1557,7 @@ bool eeprom_product_valid() { #if PLATFORM == PLATFORM_AVR if (rval == PRODUCT_RNODE || rval == PRODUCT_HMBRW) { #elif PLATFORM == PLATFORM_ESP32 - if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_10 || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2 || rval == PRODUCT_H32_V3 || rval == PRODUCT_TDECK_V1 || rval == PRODUCT_TBEAM_S_V1 || rval == PRODUCT_XIAO_S3) { + if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_10 || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2 || rval == PRODUCT_H32_V3 || rval == PRODUCT_H32_V4 || rval == PRODUCT_TDECK_V1 || rval == PRODUCT_TBEAM_S_V1 || rval == PRODUCT_XIAO_S3) { #elif PLATFORM == PLATFORM_NRF52 if (rval == PRODUCT_RAK4631 || rval == PRODUCT_HELTEC_T114 || rval == PRODUCT_TECHO || rval == PRODUCT_HMBRW) { #else diff --git a/sx126x.cpp b/sx126x.cpp index 18ae7e2..c1e7c20 100644 --- a/sx126x.cpp +++ b/sx126x.cpp @@ -342,12 +342,43 @@ int sx126x::begin(long frequency) { setModulationParams(_sf, _bw, _cr, _ldro); setPacketParams(_preambleLength, _implicitHeaderMode, _payloadLength, _crcMode); + #if HAS_LORA_PA + #if LORA_PA_GC1109 + // Enable Vfem_ctl for supply to + // PA power net. + pinMode(LORA_PA_PWR_EN, OUTPUT); + digitalWrite(LORA_PA_PWR_EN, HIGH); + + // Enable PA LNA and TX standby + pinMode(LORA_PA_CSD, OUTPUT); + digitalWrite(LORA_PA_CSD, HIGH); + + // Keep PA CPS low until actual + // transmit. Does it save power? + // Who knows? Will have to measure. + pinMode(LORA_PA_CPS, OUTPUT); + digitalWrite(LORA_PA_CPS, LOW); + + // On Heltec V4, the PA CTX pin + // is driven by the SX1262 DIO2 + // pin directly, so we do not + // need to manually raise this. + #endif + #endif + return 1; } void sx126x::end() { sleep(); SPI.end(); _preinit_done = false; } int sx126x::beginPacket(int implicitHeader) { + #if HAS_LORA_PA + #if LORA_PA_GC1109 + // Enable PA CPS for transmit + digitalWrite(LORA_PA_CPS, HIGH); + #endif + #endif + standby(); if (implicitHeader) { implicitHeaderMode(); } else { explicitHeaderMode(); } @@ -432,6 +463,9 @@ int ISR_VECT sx126x::currentRssi() { uint8_t byte = 0; executeOpcodeRead(OP_CURRENT_RSSI_6X, &byte, 1); int rssi = -(int(byte)) / 2; + #if HAS_LORA_LNA + rssi -= LORA_LNA_GAIN; + #endif return rssi; } @@ -446,6 +480,9 @@ int ISR_VECT sx126x::packetRssi() { uint8_t buf[3] = {0}; executeOpcodeRead(OP_PACKET_STATUS_6X, buf, 3); int pkt_rssi = -buf[0] / 2; + #if HAS_LORA_LNA + pkt_rssi -= LORA_LNA_GAIN; + #endif return pkt_rssi; } @@ -550,6 +587,13 @@ void sx126x::onReceive(void(*callback)(int)){ } void sx126x::receive(int size) { + #if HAS_LORA_PA + #if LORA_PA_GC1109 + // Disable PA CPS for receive + digitalWrite(LORA_PA_CPS, LOW); + #endif + #endif + if (size > 0) { implicitHeaderMode(); _payloadLength = size; @@ -584,6 +628,8 @@ void sx126x::enableTCXO() { uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; #elif BOARD_MODEL == BOARD_TECHO uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; + #elif BOARD_MODEL == BOARD_HELTEC32_V4 + uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; #endif executeOpcode(OP_DIO3_TCXO_CTRL_6X, buf, 4); #endif