diff --git a/platformio.ini b/platformio.ini index 377635873..7de2d16ef 100644 --- a/platformio.ini +++ b/platformio.ini @@ -26,6 +26,7 @@ build_flags = -Wno-missing-field-initializers -DUSE_THREAD_NAMES -DTINYGPS_OPTION_NO_CUSTOM_FIELDS -DPB_ENABLE_MALLOC=1 + -DRADIOLIB_LOW_LEVEL=1 -DRADIOLIB_EXCLUDE_CC1101=1 -DRADIOLIB_EXCLUDE_NRF24=1 -DRADIOLIB_EXCLUDE_RF69=1 diff --git a/src/main.cpp b/src/main.cpp index bf4b0c2f2..9e074f8cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -185,6 +185,8 @@ bool pauseBluetoothLogging = false; bool pmu_found; +uint8_t pa_fan_percentage = 50; + #if !MESHTASTIC_EXCLUDE_I2C // Array map of sensor types with i2c address and wire as we'll find in the i2c scan std::pair nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1] = {}; @@ -1218,16 +1220,36 @@ void setup() mqttInit(); #endif -#ifdef RF95_FAN_EN - // Ability to disable FAN if PIN has been set with RF95_FAN_EN. +#ifdef RADIO_FAN_EN + // Ability to disable FAN if PIN has been set with RADIO_FAN_EN. // Make sure LoRa has been started before disabling FAN. - if (config.lora.pa_fan_disabled) - digitalWrite(RF95_FAN_EN, LOW ^ 0); +#ifdef RADIO_FAN_PWM +#if defined(ARCH_ESP32) + // Set up PWM at Channel 1 at 25KHz, using 8-bit resolution + // Turn ON/OFF fan to the specified value if enabled by config. + // code by https://github.com/gjelsoe/ + if (ledcSetup(1, 25000, 8)) { + ledcAttachPin(RADIO_FAN_EN, 1); + LOG_INFO("PWM init C1 P%d\n", RADIO_FAN_EN); + // Set PWM duty cycle based on fan disabled state + ledcWrite(1, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55)); + } else { + LOG_WARN("PWM init fail P%d\n", RADIO_FAN_EN); + } +#elif defined(ARCH_NRF52) + pinMode(RADIO_FAN_EN, OUTPUT); + analogWrite(RADIO_FAN_EN, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55)); +#endif +#else + // Set up as ON/OFF switch of fan + pinMode(RADIO_FAN_EN, OUTPUT); + digitalWrite(RADIO_FAN_EN, LOW ^ 0); +#endif #endif #ifndef ARCH_PORTDUINO - // Initialize Wifi + // Initialize Wifi #if HAS_WIFI initWifi(); #endif diff --git a/src/main.h b/src/main.h index 3b71cfeea..a7835a3d6 100644 --- a/src/main.h +++ b/src/main.h @@ -77,6 +77,8 @@ extern uint32_t shutdownAtMsec; extern uint32_t serialSinceMsec; +extern uint8_t pa_fan_percentage; + // If a thread does something that might need for it to be rescheduled ASAP it can set this flag // This will suppress the current delay and instead try to run ASAP. extern bool runASAP; diff --git a/src/mesh/LR11x0Interface.cpp b/src/mesh/LR11x0Interface.cpp index 2b060ad38..32faab194 100644 --- a/src/mesh/LR11x0Interface.cpp +++ b/src/mesh/LR11x0Interface.cpp @@ -3,6 +3,7 @@ #include "Throttle.h" #include "configuration.h" #include "error.h" +#include "main.h" #include "mesh/NodeDB.h" #ifdef LR11X0_DIO_AS_RF_SWITCH #include "rfswitch.h" @@ -54,6 +55,8 @@ template bool LR11x0Interface::init() digitalWrite(LR11X0_POWER_EN, HIGH); #endif + enableFan(); + #if ARCH_PORTDUINO float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; // FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 1dfc72708..a488d30e7 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -157,10 +157,7 @@ bool RF95Interface::init() digitalWrite(RF95_TXEN, 0); #endif -#ifdef RF95_FAN_EN - pinMode(RF95_FAN_EN, OUTPUT); - digitalWrite(RF95_FAN_EN, 1); -#endif + enableFan(); #ifdef RF95_RXEN pinMode(RF95_RXEN, OUTPUT); @@ -333,10 +330,7 @@ bool RF95Interface::sleep() // put chipset into sleep mode setStandby(); // First cancel any active receiving/sending lora->sleep(); - -#ifdef RF95_FAN_EN - digitalWrite(RF95_FAN_EN, 0); -#endif + disableFan(); return true; } diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index a6faebff4..bdcf38d29 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -523,4 +523,37 @@ bool RadioLibInterface::startSend(meshtastic_MeshPacket *txp) return res == RADIOLIB_ERR_NONE; } +} + +void RadioLibInterface::enableFan() +{ +#ifdef RADIO_FAN_EN + +#ifdef RADIO_FAN_PWM +#if defined(ARCH_ESP32) + ledcWrite(1, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55)); +#elif defined(ARCH_NRF52) + analogWrite(RADIO_FAN_EN, config.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55)); +#endif +#else + pinMode(RADIO_FAN_EN, OUTPUT); + digitalWrite(RADIO_FAN_EN, 1); +#endif +#endif +} + +void RadioLibInterface::disableFan() +{ +#ifdef RADIO_FAN_EN +#ifdef RADIO_FAN_PWM +#if defined(ARCH_ESP32) + ledcWrite(1, 0); +#elif defined(ARCH_NRF52) + analogWrite(RADIO_FAN_EN, 0); +#endif +#else + pinMode(RADIO_FAN_EN, OUTPUT); + digitalWrite(RADIO_FAN_EN, 0); +#endif +#endif } \ No newline at end of file diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index b24879eaf..d78031469 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -138,6 +138,9 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified /** Attempt to find a packet in the TxQueue. Returns true if the packet was found. */ virtual bool findInTxQueue(NodeNum from, PacketId id) override; + void enableFan(); + void disableFan(); + private: /** if we have something waiting to send, start a short (random) timer so we can come check for collision before actually * doing the transmit */ diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index 6a4be023b..9e4726a99 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -52,6 +52,8 @@ template bool SX126xInterface::init() pinMode(SX126X_POWER_EN, OUTPUT); #endif + enableFan(); + #if ARCH_PORTDUINO tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) { diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index e06f274e7..c8c24113b 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -35,10 +35,7 @@ template bool SX128xInterface::init() digitalWrite(SX128X_POWER_EN, HIGH); #endif -#ifdef RF95_FAN_EN - pinMode(RF95_FAN_EN, OUTPUT); - digitalWrite(RF95_FAN_EN, 1); -#endif + enableFan(); #if ARCH_PORTDUINO if (settingsMap[rxen_pin] != RADIOLIB_NC) { diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 88109bc78..052aec66a 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -635,13 +635,21 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) requiresReboot = false; } -#ifdef RF95_FAN_EN +#ifdef RADIO_FAN_EN +#ifdef RADIO_FAN_PWM +#if defined(ARCH_ESP32) + ledcWrite(1, c.payload_variant.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55)); +#elif defined(ARCH_NFR52) + analogWrite(RADIO_FAN_EN, c.payload_variant.lora.pa_fan_disabled ? 0 : (pa_fan_percentage * 2.55)); +#endif +#else // Turn PA off if disabled by config if (c.payload_variant.lora.pa_fan_disabled) { - digitalWrite(RF95_FAN_EN, LOW ^ 0); + digitalWrite(RADIO_FAN_EN, LOW ^ 0); } else { - digitalWrite(RF95_FAN_EN, HIGH ^ 0); + digitalWrite(RADIO_FAN_EN, HIGH ^ 0); } +#endif #endif config.lora = c.payload_variant.lora; // If we're setting region for the first time, init the region diff --git a/variants/betafpv_2400_tx_micro/variant.h b/variants/betafpv_2400_tx_micro/variant.h index 67699e7c8..9e3503bd5 100644 --- a/variants/betafpv_2400_tx_micro/variant.h +++ b/variants/betafpv_2400_tx_micro/variant.h @@ -12,7 +12,7 @@ #define LORA_MISO 19 #define LORA_MOSI 23 #define LORA_CS 5 -#define RF95_FAN_EN 17 +#define RADIO_FAN_EN 17 // #define LED_PIN 16 // This is a LED_WS2812 not a standard LED #define HAS_NEOPIXEL // Enable the use of neopixels diff --git a/variants/radiomaster_900_bandit/variant.h b/variants/radiomaster_900_bandit/variant.h index 0c7417cac..a84a1ca4a 100644 --- a/variants/radiomaster_900_bandit/variant.h +++ b/variants/radiomaster_900_bandit/variant.h @@ -46,7 +46,8 @@ FAN is active at 250mW on it's ExpressLRS Firmware. This FAN has TACHO signal on Pin 27 for use with PWM. */ -#define RF95_FAN_EN 2 +#define RADIO_FAN_EN 2 +#define RADIO_FAN_PWM /* LED PIN setup and it has a NeoPixel LED. diff --git a/variants/radiomaster_900_bandit_nano/variant.h b/variants/radiomaster_900_bandit_nano/variant.h index 1b6bba126..d960dd9ef 100644 --- a/variants/radiomaster_900_bandit_nano/variant.h +++ b/variants/radiomaster_900_bandit_nano/variant.h @@ -32,7 +32,7 @@ This unit has a FAN built-in. FAN is active at 250mW on it's ExpressLRS Firmware. */ -#define RF95_FAN_EN 2 +#define RADIO_FAN_EN 2 /* LED PIN setup. diff --git a/variants/radiomaster_nomad_gemini/platformio.ini b/variants/radiomaster_nomad_gemini/platformio.ini new file mode 100644 index 000000000..96ea42e50 --- /dev/null +++ b/variants/radiomaster_nomad_gemini/platformio.ini @@ -0,0 +1,20 @@ +[env:radiomaster_nomad_gemini] +extends = esp32_base +board = esp32doit-devkit-v1 +build_flags = + ${esp32_base.build_flags} + -DRADIOMASTER_NOMAD_GEMINI + -DPRIVATE_HW + -DVTABLES_IN_FLASH=1 + -DCONFIG_DISABLE_HAL_LOCKS=1 + -O2 + -Ivariants/radiomaster_nomad_gemini + -DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR=1 + -DMESHTASTIC_EXCLUDE_I2C=1 + -DRADIOLIB_EXCLUDE_SX128X=1 + -DRADIOLIB_EXCLUDE_SX127X=1 + -DRADIOLIB_EXCLUDE_SX126X=1 +board_build.f_cpu = 240000000L +upload_protocol = esptool +lib_deps = + ${esp32_base.lib_deps} diff --git a/variants/radiomaster_nomad_gemini/rfswitch.h b/variants/radiomaster_nomad_gemini/rfswitch.h new file mode 100644 index 000000000..8c2a56a87 --- /dev/null +++ b/variants/radiomaster_nomad_gemini/rfswitch.h @@ -0,0 +1,56 @@ +#include "RadioLib.h" + +static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_LR11X0_DIO7, + RADIOLIB_LR11X0_DIO8, RADIOLIB_NC}; + +static const Module::RfSwitchMode_t rfswitch_table[] = { + // mode DIO5 DIO6 DIO7 DIO8 + {LR11x0::MODE_STBY, {LOW, LOW, LOW, LOW}}, {LR11x0::MODE_RX, {LOW, LOW, HIGH, LOW}}, + {LR11x0::MODE_TX, {LOW, LOW, LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, LOW, LOW, HIGH}}, + {LR11x0::MODE_TX_HF, {LOW, HIGH, LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW, LOW, LOW}}, + {LR11x0::MODE_WIFI, {HIGH, LOW, LOW, LOW}}, END_OF_MODE_TABLE, +}; + +/* + +DIO5: RXEN 2.4GHz +DIO6: TXEN 2.4GHz +DIO7: RXEN 900MHz +DIO8: TXEN 900MHz + + + "radio_dcdc": true, + "radio_rfo_hf": true, + + "power_apc2": 26, + "power_min": 0, + "power_high": 6, + "power_max": 6, + "power_default": 3, + "power_control": 3, POWER_OUTPUT_DACWRITE // use internal dacWrite function to set value on GPIO_PIN_RFamp_APC2 + [0, 1, 2, 3, 4, 5, 6 ] // 0-6 + "power_values": [120, 120, 120, 120, 120, 120, 95] // DAC Value + "power_values2": [-17, -16, -14, -11, -7, -3, 5 ] // 900M + "power_values_dual": [-18, -14, -8, -6, -2, 3, 5 ] // 2.4G + + // default value 0 means direct! +#define POWER_OUTPUT_DACWRITE (hardware_int(HARDWARE_power_control)==3) +#define POWER_OUTPUT_VALUES hardware_i16_array(HARDWARE_power_values) +#define POWER_OUTPUT_VALUES_COUNT hardware_int(HARDWARE_power_values_count) +#define POWER_OUTPUT_VALUES2 hardware_i16_array(HARDWARE_power_values2) +#define POWER_OUTPUT_VALUES_DUAL hardware_i16_array(HARDWARE_power_values_dual) +#define POWER_OUTPUT_VALUES_DUAL_COUNT hardware_int(HARDWARE_power_values_dual_count) + +#define GPIO_PIN_FAN_EN hardware_pin(HARDWARE_misc_fan_en) + + case PWR_10mW: return 10; + case PWR_25mW: return 14; + case PWR_50mW: return 17; + case PWR_100mW: return 20; + case PWR_250mW: return 24; + case PWR_500mW: return 27; + case PWR_1000mW: return 30; + + 95 -> +25dBm + 120 -> +24dBm +*/ \ No newline at end of file diff --git a/variants/radiomaster_nomad_gemini/variant.h b/variants/radiomaster_nomad_gemini/variant.h new file mode 100644 index 000000000..643b89759 --- /dev/null +++ b/variants/radiomaster_nomad_gemini/variant.h @@ -0,0 +1,60 @@ +#define HAS_SCREEN 0 +#define HAS_WIRE 0 +#define HAS_GPS 0 +#undef GPS_RX_PIN +#undef GPS_TX_PIN + +#define PIN_SPI_MISO 33 +#define PIN_SPI_MOSI 32 +#define PIN_SPI_SCK 25 +#define PIN_SPI_NSS 27 + +#define LORA_RESET 15 +#define LORA_DIO1 37 +#define LORA_DIO2 36 +#define LORA_SCK PIN_SPI_SCK +#define LORA_MISO PIN_SPI_MISO +#define LORA_MOSI PIN_SPI_MOSI +#define LORA_CS PIN_SPI_NSS + +// supported modules list +#define USE_LR1121 + +#define LR1121_IRQ_PIN LORA_DIO1 +#define LR1121_NRESET_PIN LORA_RESET +#define LR1121_BUSY_PIN LORA_DIO2 +#define LR1121_SPI_NSS_PIN LORA_CS +#define LR1121_SPI_SCK_PIN LORA_SCK +#define LR1121_SPI_MOSI_PIN LORA_MOSI +#define LR1121_SPI_MISO_PIN LORA_MISO + +// this is correct and sets the cap for the Sub-GHz part +#define LR1110_MAX_POWER 5 +// 2.4G Part +#define LR1120_MAX_POWER 5 + +#define POWER_SHIFT -20 + +// not yet implemented +#define JANUS_RADIO +#define LR1121_IRQ2_PIN 34 +#define LR1121_NRESET2_PIN 21 +#define LR1121_BUSY2_PIN 39 +#define LR1121_SPI_NSS2_PIN 13 + +// TODO: check if this is correct +// #define LR11X0_DIO3_TCXO_VOLTAGE 1.6 +#define LR11X0_DIO_AS_RF_SWITCH + +#define HAS_NEOPIXEL // Enable the use of neopixels +#define NEOPIXEL_COUNT 2 // How many neopixels are connected +#define NEOPIXEL_DATA 22 // GPIO pin used to send data to the neopixels +#define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // Type of neopixels in use +#define ENABLE_AMBIENTLIGHTING // Turn on Ambient Lighting + +#define BUTTON_PIN 34 +#define BUTTON_NEED_PULLUP + +#undef EXT_NOTIFY_OUT + +#define RADIO_FAN_EN 2