diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index e68b01ba3c..c8f181308d 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -23,6 +23,47 @@ Lora: # Busy: 20 # Reset: 18 +### The Radxa Zero 3E/W employs multiple gpio chips. +### Each gpio pin must be unique, but can be assigned to a specific gpio chip and line. +### In case solely a no. is given, the default gpio chip and pin == line will be employed. +### +# Module: sx1262 # Radxa Zero 3E/W + Ebyte E22-900M30S +# DIO2_AS_RF_SWITCH: true +# DIO3_TCXO_VOLTAGE: 1.8 +# CS: # NSS PIN_24 -> chip 4, line 22 +# pin: 24 +# gpiochip: 4 +# line: 22 +# SCK: # SCK PIN_23 -> chip 4, line 18 +# pin: 23 +# gpiochip: 4 +# line: 18 +# Busy: # BUSY PIN_29 -> chip 3!, line 11 +# pin: 29 +# gpiochip: 3 +# line: 11 +# MOSI: # MOSI PIN_19 -> chip 4, line 19 +# pin: 19 +# gpiochip: 4 +# line: 19 +# MISO: # MISO PIN_21 -> chip 4, line 21 +# pin: 21 +# gpiochip: 4 +# line: 21 +# Reset: # NRST PIN_27 -> chip 4, line 10 +# pin: 27 +# gpiochip: 4 +# line: 10 +# IRQ: # DIO1 PIN_28 -> chip 4, line 11 +# pin: 28 +# gpiochip: 4 +# line: 11 +# RXen: # RXEN PIN_22 -> chip 3!, line 17 +# pin: 22 +# gpiochip: 3 +# line: 17 +# TXen: RADIOLIB_NC # TXEN no PIN, no line, fallback to default gpio chip + # Module: sx1268 # SX1268-based modules, tested with Ebyte E22 400M33S # CS: 21 # IRQ: 16 @@ -39,7 +80,7 @@ Lora: # spiSpeed: 2000000 -### Set gpio chip to use in /dev/. Defaults to 0. +### Set default/fallback gpio chip to use in /dev/. Defaults to 0. ### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4 # gpiochip: 4 @@ -147,4 +188,4 @@ General: MaxMessageQueue: 100 ConfigDirectory: /etc/meshtasticd/config.d/ # MACAddress: AA:BB:CC:DD:EE:FF -# MACAddressSource: eth0 \ No newline at end of file +# MACAddressSource: eth0 diff --git a/src/main.cpp b/src/main.cpp index 4a642ef6d8..338fca5c10 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -826,116 +826,61 @@ void setup() #endif #ifdef ARCH_PORTDUINO - if (settingsMap[use_sx1262]) { - if (!rIf) { - LOG_DEBUG("Activate sx1262 radio on SPI port %s", settingsStrings[spidev].c_str()); + const struct { configNames cfgName; + std::string strName; + } loraModules[] = { + { use_rf95, "RF95" }, + { use_sx1262, "sx1262" }, + { use_sx1268, "sx1268" }, + { use_sx1280, "sx1280" }, + { use_lr1110, "lr1110" }, + { use_lr1120, "lr1120" }, + { use_lr1121, "lr1121" }, + { use_llcc68, "LLCC68" } + }; + // as one can't use a function pointer to the class constructor: + auto loraModuleInterface = [](configNames cfgName, LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) { + switch (cfgName) { + case use_rf95: + return (RadioInterface*)new RF95Interface(hal, cs, irq, rst, busy); + case use_sx1262: + return (RadioInterface*)new SX1262Interface(hal, cs, irq, rst, busy); + case use_sx1268: + return (RadioInterface*)new SX1268Interface(hal, cs, irq, rst, busy); + case use_sx1280: + return (RadioInterface*)new SX1280Interface(hal, cs, irq, rst, busy); + case use_lr1110: + return (RadioInterface*)new LR1110Interface(hal, cs, irq, rst, busy); + case use_lr1120: + return (RadioInterface*)new LR1120Interface(hal, cs, irq, rst, busy); + case use_lr1121: + return (RadioInterface*)new LR1121Interface(hal, cs, irq, rst, busy); + case use_llcc68: + return (RadioInterface*)new LLCC68Interface(hal, cs, irq, rst, busy); + default: + assert(0); // shouldn't happen + return (RadioInterface*)nullptr; + } + }; + for (auto& loraModule : loraModules) { + if (settingsMap[loraModule.cfgName] && !rIf) { + LOG_DEBUG("Activate %s radio on SPI port %s", loraModule.strName.c_str(), settingsStrings[spidev].c_str()); if (settingsStrings[spidev] == "ch341") { RadioLibHAL = ch341Hal; } else { RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); } - rIf = new SX1262Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); + rIf = loraModuleInterface(loraModule.cfgName, (LockingArduinoHal *)RadioLibHAL, settingsMap[cs_pin], settingsMap[irq_pin], settingsMap[reset_pin], settingsMap[busy_pin]); if (!rIf->init()) { - LOG_WARN("No SX1262 radio"); - delete rIf; - exit(EXIT_FAILURE); - } else { - LOG_INFO("SX1262 init success"); - } - } - } else if (settingsMap[use_rf95]) { - if (!rIf) { - LOG_DEBUG("Activate rf95 radio on SPI port %s", settingsStrings[spidev].c_str()); - RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); - rIf = new RF95Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); - if (!rIf->init()) { - LOG_WARN("No RF95 radio"); - delete rIf; - rIf = NULL; - exit(EXIT_FAILURE); - } else { - LOG_INFO("RF95 init success"); - } - } - } else if (settingsMap[use_sx1280]) { - if (!rIf) { - LOG_DEBUG("Activate sx1280 radio on SPI port %s", settingsStrings[spidev].c_str()); - RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); - rIf = new SX1280Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); - if (!rIf->init()) { - LOG_WARN("No SX1280 radio"); + LOG_WARN("No %s radio", loraModule.strName.c_str()); delete rIf; rIf = NULL; exit(EXIT_FAILURE); } else { - LOG_INFO("SX1280 init success"); - } - } - } else if (settingsMap[use_lr1110]) { - if (!rIf) { - LOG_DEBUG("Activate lr1110 radio on SPI port %s", settingsStrings[spidev].c_str()); - LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); - rIf = new LR1110Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); - if (!rIf->init()) { - LOG_WARN("No LR1110 radio"); - delete rIf; - rIf = NULL; - exit(EXIT_FAILURE); - } else { - LOG_INFO("LR1110 init success"); - } - } - } else if (settingsMap[use_lr1120]) { - if (!rIf) { - LOG_DEBUG("Activate lr1120 radio on SPI port %s", settingsStrings[spidev].c_str()); - LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); - rIf = new LR1120Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); - if (!rIf->init()) { - LOG_WARN("No LR1120 radio"); - delete rIf; - rIf = NULL; - exit(EXIT_FAILURE); - } else { - LOG_INFO("LR1120 init success"); - } - } - } else if (settingsMap[use_lr1121]) { - if (!rIf) { - LOG_DEBUG("Activate lr1121 radio on SPI port %s", settingsStrings[spidev].c_str()); - LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); - rIf = new LR1121Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); - if (!rIf->init()) { - LOG_WARN("No LR1121 radio"); - delete rIf; - rIf = NULL; - exit(EXIT_FAILURE); - } else { - LOG_INFO("LR1121 init success"); - } - } - } else if (settingsMap[use_sx1268]) { - if (!rIf) { - LOG_DEBUG("Activate sx1268 radio on SPI port %s", settingsStrings[spidev].c_str()); - RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); - rIf = new SX1268Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], - settingsMap[busy]); - if (!rIf->init()) { - LOG_WARN("No SX1268 radio"); - delete rIf; - rIf = NULL; - exit(EXIT_FAILURE); - } else { - LOG_INFO("SX1268 init success"); + LOG_INFO("%s init success", loraModule.strName.c_str()); } } } - #elif defined(HW_SPI1_DEVICE) LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings); #else // HW_SPI1_DEVICE @@ -1280,4 +1225,4 @@ void loop() mainDelay.delay(delayMsec); } } -#endif \ No newline at end of file +#endif diff --git a/src/mesh/RF95Interface.cpp b/src/mesh/RF95Interface.cpp index 9ef0450997..d4d9ad23c6 100644 --- a/src/mesh/RF95Interface.cpp +++ b/src/mesh/RF95Interface.cpp @@ -91,16 +91,16 @@ void RF95Interface::setTransmitEnable(bool txon) #ifdef RF95_TXEN digitalWrite(RF95_TXEN, txon ? 1 : 0); #elif ARCH_PORTDUINO - if (settingsMap[txen] != RADIOLIB_NC) { - digitalWrite(settingsMap[txen], txon ? 1 : 0); + if (settingsMap[txen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[txen_pin], txon ? 1 : 0); } #endif #ifdef RF95_RXEN digitalWrite(RF95_RXEN, txon ? 0 : 1); #elif ARCH_PORTDUINO - if (settingsMap[rxen] != RADIOLIB_NC) { - digitalWrite(settingsMap[rxen], txon ? 0 : 1); + if (settingsMap[rxen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[rxen_pin], txon ? 0 : 1); } #endif } @@ -164,13 +164,13 @@ bool RF95Interface::init() digitalWrite(RF95_RXEN, 1); #endif #if ARCH_PORTDUINO - if (settingsMap[txen] != RADIOLIB_NC) { - pinMode(settingsMap[txen], OUTPUT); - digitalWrite(settingsMap[txen], 0); + if (settingsMap[txen_pin] != RADIOLIB_NC) { + pinMode(settingsMap[txen_pin], OUTPUT); + digitalWrite(settingsMap[txen_pin], 0); } - if (settingsMap[rxen] != RADIOLIB_NC) { - pinMode(settingsMap[rxen], OUTPUT); - digitalWrite(settingsMap[rxen], 0); + if (settingsMap[rxen_pin] != RADIOLIB_NC) { + pinMode(settingsMap[rxen_pin], OUTPUT); + digitalWrite(settingsMap[rxen_pin], 0); } #endif setTransmitEnable(false); @@ -337,4 +337,4 @@ bool RF95Interface::sleep() return true; } -#endif \ No newline at end of file +#endif diff --git a/src/mesh/SX126xInterface.cpp b/src/mesh/SX126xInterface.cpp index ed0267c5b9..b13bb6fafa 100644 --- a/src/mesh/SX126xInterface.cpp +++ b/src/mesh/SX126xInterface.cpp @@ -51,9 +51,9 @@ template bool SX126xInterface::init() #if ARCH_PORTDUINO float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; - if (settingsMap[sx126x_ant_sw] != RADIOLIB_NC) { - digitalWrite(settingsMap[sx126x_ant_sw], HIGH); - pinMode(settingsMap[sx126x_ant_sw], OUTPUT); + if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[sx126x_ant_sw_pin], HIGH); + pinMode(settingsMap[sx126x_ant_sw_pin], OUTPUT); } // FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE #elif !defined(SX126X_DIO3_TCXO_VOLTAGE) @@ -121,8 +121,8 @@ template bool SX126xInterface::init() // no effect #if ARCH_PORTDUINO if (res == RADIOLIB_ERR_NONE) { - LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen], settingsMap[txen]); - lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]); + LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen_pin], settingsMap[txen_pin]); + lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]); } #else #ifndef SX126X_RXEN @@ -341,4 +341,4 @@ template bool SX126xInterface::sleep() return true; } -#endif \ No newline at end of file +#endif diff --git a/src/mesh/SX128xInterface.cpp b/src/mesh/SX128xInterface.cpp index 013164bca6..ee34084569 100644 --- a/src/mesh/SX128xInterface.cpp +++ b/src/mesh/SX128xInterface.cpp @@ -38,13 +38,13 @@ template bool SX128xInterface::init() #endif #if ARCH_PORTDUINO - if (settingsMap[rxen] != RADIOLIB_NC) { - pinMode(settingsMap[rxen], OUTPUT); - digitalWrite(settingsMap[rxen], LOW); // Set low before becoming an output + if (settingsMap[rxen_pin] != RADIOLIB_NC) { + pinMode(settingsMap[rxen_pin], OUTPUT); + digitalWrite(settingsMap[rxen_pin], LOW); // Set low before becoming an output } - if (settingsMap[txen] != RADIOLIB_NC) { - pinMode(settingsMap[txen], OUTPUT); - digitalWrite(settingsMap[txen], LOW); // Set low before becoming an output + if (settingsMap[txen_pin] != RADIOLIB_NC) { + pinMode(settingsMap[txen_pin], OUTPUT); + digitalWrite(settingsMap[txen_pin], LOW); // Set low before becoming an output } #else #if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode @@ -93,8 +93,8 @@ template bool SX128xInterface::init() lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN); } #elif ARCH_PORTDUINO - if (res == RADIOLIB_ERR_NONE && settingsMap[rxen] != RADIOLIB_NC && settingsMap[txen] != RADIOLIB_NC) { - lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]); + if (res == RADIOLIB_ERR_NONE && settingsMap[rxen_pin] != RADIOLIB_NC && settingsMap[txen_pin] != RADIOLIB_NC) { + lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]); } #endif @@ -174,11 +174,11 @@ template void SX128xInterface::setStandby() LOG_ERROR("SX128x standby %s%d", radioLibErr, err); assert(err == RADIOLIB_ERR_NONE); #if ARCH_PORTDUINO - if (settingsMap[rxen] != RADIOLIB_NC) { - digitalWrite(settingsMap[rxen], LOW); + if (settingsMap[rxen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[rxen_pin], LOW); } - if (settingsMap[txen] != RADIOLIB_NC) { - digitalWrite(settingsMap[txen], LOW); + if (settingsMap[txen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[txen_pin], LOW); } #else #if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power @@ -210,11 +210,11 @@ template void SX128xInterface::addReceiveMetadata(meshtastic_Mes template void SX128xInterface::configHardwareForSend() { #if ARCH_PORTDUINO - if (settingsMap[txen] != RADIOLIB_NC) { - digitalWrite(settingsMap[txen], HIGH); + if (settingsMap[txen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[txen_pin], HIGH); } - if (settingsMap[rxen] != RADIOLIB_NC) { - digitalWrite(settingsMap[rxen], LOW); + if (settingsMap[rxen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[rxen_pin], LOW); } #else @@ -241,11 +241,11 @@ template void SX128xInterface::startReceive() setStandby(); #if ARCH_PORTDUINO - if (settingsMap[rxen] != RADIOLIB_NC) { - digitalWrite(settingsMap[rxen], HIGH); + if (settingsMap[rxen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[rxen_pin], HIGH); } - if (settingsMap[txen] != RADIOLIB_NC) { - digitalWrite(settingsMap[txen], LOW); + if (settingsMap[txen_pin] != RADIOLIB_NC) { + digitalWrite(settingsMap[txen_pin], LOW); } #else @@ -315,4 +315,4 @@ template bool SX128xInterface::sleep() return true; } -#endif \ No newline at end of file +#endif diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index b042510f50..e751122350 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -134,13 +134,13 @@ void portduinoSetup() { printf("Set up Meshtastic on Portduino...\n"); int max_GPIO = 0; - const configNames GPIO_lines[] = {cs, - irq, - busy, - reset, - sx126x_ant_sw, - txen, - rxen, + const configNames GPIO_lines[] = {cs_pin, + irq_pin, + busy_pin, + reset_pin, + sx126x_ant_sw_pin, + txen_pin, + rxen_pin, displayDC, displayCS, displayBacklight, @@ -247,7 +247,7 @@ void portduinoSetup() // Rather important to set this, if not running simulated. randomSeed(time(NULL)); - gpioChipName += std::to_string(settingsMap[gpiochip]); + std::string defaultGpioChipName = gpioChipName + std::to_string(settingsMap[default_gpiochip]); for (configNames i : GPIO_lines) { if (settingsMap.count(i) && settingsMap[i] > max_GPIO) @@ -260,62 +260,46 @@ void portduinoSetup() // TODO: Can we do this in the for loop above? // TODO: If one of these fails, we should log and terminate if (settingsMap.count(user) > 0 && settingsMap[user] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[user], gpioChipName) != ERRNO_OK) { + if (initGPIOPin(settingsMap[user], defaultGpioChipName, settingsMap[user]) != ERRNO_OK) { settingsMap[user] = RADIOLIB_NC; } } if (settingsMap[displayPanel] != no_screen) { if (settingsMap[displayCS] > 0) - initGPIOPin(settingsMap[displayCS], gpioChipName); + initGPIOPin(settingsMap[displayCS], defaultGpioChipName, settingsMap[displayCS]); if (settingsMap[displayDC] > 0) - initGPIOPin(settingsMap[displayDC], gpioChipName); + initGPIOPin(settingsMap[displayDC], defaultGpioChipName, settingsMap[displayDC]); if (settingsMap[displayBacklight] > 0) - initGPIOPin(settingsMap[displayBacklight], gpioChipName); + initGPIOPin(settingsMap[displayBacklight], defaultGpioChipName, settingsMap[displayBacklight]); if (settingsMap[displayReset] > 0) - initGPIOPin(settingsMap[displayReset], gpioChipName); + initGPIOPin(settingsMap[displayReset], defaultGpioChipName, settingsMap[displayReset]); } if (settingsMap[touchscreenModule] != no_touchscreen) { if (settingsMap[touchscreenCS] > 0) - initGPIOPin(settingsMap[touchscreenCS], gpioChipName); + initGPIOPin(settingsMap[touchscreenCS], defaultGpioChipName, settingsMap[touchscreenCS]); if (settingsMap[touchscreenIRQ] > 0) - initGPIOPin(settingsMap[touchscreenIRQ], gpioChipName); + initGPIOPin(settingsMap[touchscreenIRQ], defaultGpioChipName, settingsMap[touchscreenIRQ]); } // Only initialize the radio pins when dealing with real, kernel controlled SPI hardware if (settingsStrings[spidev] != "" && settingsStrings[spidev] != "ch341") { - if (settingsMap.count(cs) > 0 && settingsMap[cs] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[cs], gpioChipName) != ERRNO_OK) { - settingsMap[cs] = RADIOLIB_NC; - } - } - if (settingsMap.count(irq) > 0 && settingsMap[irq] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[irq], gpioChipName) != ERRNO_OK) { - settingsMap[irq] = RADIOLIB_NC; - } - } - if (settingsMap.count(busy) > 0 && settingsMap[busy] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[busy], gpioChipName) != ERRNO_OK) { - settingsMap[busy] = RADIOLIB_NC; - } - } - if (settingsMap.count(reset) > 0 && settingsMap[reset] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[reset], gpioChipName) != ERRNO_OK) { - settingsMap[reset] = RADIOLIB_NC; - } - } - if (settingsMap.count(sx126x_ant_sw) > 0 && settingsMap[sx126x_ant_sw] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[sx126x_ant_sw], gpioChipName) != ERRNO_OK) { - settingsMap[sx126x_ant_sw] = RADIOLIB_NC; - } - } - if (settingsMap.count(rxen) > 0 && settingsMap[rxen] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[rxen], gpioChipName) != ERRNO_OK) { - settingsMap[rxen] = RADIOLIB_NC; - } - } - if (settingsMap.count(txen) > 0 && settingsMap[txen] != RADIOLIB_NC) { - if (initGPIOPin(settingsMap[txen], gpioChipName) != ERRNO_OK) { - settingsMap[txen] = RADIOLIB_NC; + const struct { configNames pin; configNames gpiochip; configNames line; } pinMappings[] = { + { cs_pin, cs_gpiochip, cs_line }, + { irq_pin, irq_gpiochip, irq_line }, + { busy_pin, busy_gpiochip, busy_line }, + { reset_pin, reset_gpiochip, reset_line }, + { rxen_pin, rxen_gpiochip, rxen_line }, + { txen_pin, txen_gpiochip, txen_line }, + { sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line } + }; + for (auto& pinMap : pinMappings) { + auto setMapIter = settingsMap.find(pinMap.pin); + if (setMapIter != settingsMap.end() && setMapIter->second != RADIOLIB_NC) { + if (initGPIOPin(setMapIter->second, gpioChipName + std::to_string(settingsMap[pinMap.gpiochip]), settingsMap[pinMap.line] ) != ERRNO_OK) { + settingsMap[pinMap.pin] = RADIOLIB_NC; + settingsMap[pinMap.gpiochip] = RADIOLIB_NC; + settingsMap[pinMap.line] = RADIOLIB_NC; + } } } SPI.begin(settingsStrings[spidev].c_str()); @@ -332,13 +316,13 @@ void portduinoSetup() return; } -int initGPIOPin(int pinNum, const std::string gpioChipName) +int initGPIOPin(int pinNum, const std::string gpioChipName, int line) { #ifdef PORTDUINO_LINUX_HARDWARE std::string gpio_name = "GPIO" + std::to_string(pinNum); try { GPIOPin *csPin; - csPin = new LinuxGPIOPin(pinNum, gpioChipName.c_str(), pinNum, gpio_name.c_str()); + csPin = new LinuxGPIOPin(pinNum, gpioChipName.c_str(), line, gpio_name.c_str()); csPin->setSilent(); gpioBind(csPin); return ERRNO_OK; @@ -376,42 +360,65 @@ bool loadConfig(const char *configPath) } } if (yamlConfig["Lora"]) { - settingsMap[use_sx1262] = false; - settingsMap[use_rf95] = false; - settingsMap[use_sx1280] = false; - settingsMap[use_lr1110] = false; - settingsMap[use_lr1120] = false; - settingsMap[use_lr1121] = false; - settingsMap[use_sx1268] = false; - - if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1262") { - settingsMap[use_sx1262] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "RF95") { - settingsMap[use_rf95] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1280") { - settingsMap[use_sx1280] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "lr1110") { - settingsMap[use_lr1110] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "lr1120") { - settingsMap[use_lr1120] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "lr1121") { - settingsMap[use_lr1121] = true; - } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1268") { - settingsMap[use_sx1268] = true; + const struct { configNames cfgName; std::string strName; } loraModules[] = { + { use_rf95, "RF95" }, + { use_sx1262, "sx1262" }, + { use_sx1268, "sx1268" }, + { use_sx1280, "sx1280" }, + { use_lr1110, "lr1110" }, + { use_lr1120, "lr1120" }, + { use_lr1121, "lr1121" }, + { use_llcc68, "LLCC68" } + }; + for (auto& loraModule : loraModules) { + settingsMap[loraModule.cfgName] = false; + } + if (yamlConfig["Lora"]["Module"]) { + for (auto& loraModule : loraModules) { + if (yamlConfig["Lora"]["Module"].as("") == loraModule.strName) { + settingsMap[loraModule.cfgName] = true; + break; + } + } } + settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as(false); settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(0) * 1000; if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as(false)) { settingsMap[dio3_tcxo_voltage] = 1800; // default millivolts for "true" } - settingsMap[cs] = yamlConfig["Lora"]["CS"].as(RADIOLIB_NC); - settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as(RADIOLIB_NC); - settingsMap[busy] = yamlConfig["Lora"]["Busy"].as(RADIOLIB_NC); - settingsMap[reset] = yamlConfig["Lora"]["Reset"].as(RADIOLIB_NC); - settingsMap[txen] = yamlConfig["Lora"]["TXen"].as(RADIOLIB_NC); - settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as(RADIOLIB_NC); - settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as(RADIOLIB_NC); - settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as(0); + + // backwards API compatibility and to globally set gpiochip once + int defaultGpioChip = settingsMap[default_gpiochip] = yamlConfig["Lora"]["gpiochip"].as(0); + + const struct { configNames pin; + configNames gpiochip; + configNames line; + std::string strName; } pinMappings[] = { + { cs_pin, cs_gpiochip, cs_line, "CS" }, + { irq_pin, irq_gpiochip, irq_line, "IRQ" }, + { busy_pin, busy_gpiochip, busy_line, "Busy" }, + { reset_pin, reset_gpiochip, reset_line, "Reset" }, + { txen_pin, txen_gpiochip, txen_line, "TXen" }, + { rxen_pin, rxen_gpiochip, rxen_line, "RXen" }, + { sx126x_ant_sw_pin, sx126x_ant_sw_gpiochip, sx126x_ant_sw_line, "SX126X_ANT_SW" }, + }; + for (auto& pinMap : pinMappings) { + if (yamlConfig["Lora"][pinMap.strName].IsMap() + && (yamlConfig["Lora"][pinMap.strName]["pin"] + || yamlConfig["Lora"][pinMap.strName]["line"] + || yamlConfig["Lora"][pinMap.strName]["gpiochip"])) { + settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName]["pin"].as(RADIOLIB_NC); + settingsMap[pinMap.line] = yamlConfig["Lora"][pinMap.strName]["line"].as(settingsMap[pinMap.pin]); + settingsMap[pinMap.gpiochip] = yamlConfig["Lora"][pinMap.strName]["gpiochip"].as(defaultGpioChip); + } + else { // backwards API compatibility + settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName].as(RADIOLIB_NC); + settingsMap[pinMap.line] = settingsMap[pinMap.pin]; + settingsMap[pinMap.gpiochip] = defaultGpioChip; + } + } + settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as(2000000); settingsStrings[lora_usb_serial_num] = yamlConfig["Lora"]["USB_Serialnum"].as(""); settingsMap[lora_usb_pid] = yamlConfig["Lora"]["USB_PID"].as(0x5512); diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 5bc07df6ad..d1e91956d0 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -5,27 +5,42 @@ #include "platform/portduino/USBHal.h" enum configNames { - use_sx1262, - cs, - irq, - busy, - reset, - sx126x_ant_sw, - txen, - rxen, + default_gpiochip, + cs_pin, + cs_line, + cs_gpiochip, + irq_pin, + irq_line, + irq_gpiochip, + busy_pin, + busy_line, + busy_gpiochip, + reset_pin, + reset_line, + reset_gpiochip, + txen_pin, + txen_line, + txen_gpiochip, + rxen_pin, + rxen_line, + rxen_gpiochip, + sx126x_ant_sw_pin, + sx126x_ant_sw_line, + sx126x_ant_sw_gpiochip, dio2_as_rf_switch, dio3_tcxo_voltage, use_rf95, + use_sx1262, + use_sx1268, use_sx1280, use_lr1110, use_lr1120, use_lr1121, - use_sx1268, + use_llcc68, lora_usb_serial_num, lora_usb_pid, lora_usb_vid, user, - gpiochip, spidev, spiSpeed, i2cdev, @@ -75,7 +90,7 @@ extern std::map settingsMap; extern std::map settingsStrings; extern std::ofstream traceFile; extern Ch341Hal *ch341Hal; -int initGPIOPin(int pinNum, std::string gpioChipname); +int initGPIOPin(int pinNum, std::string gpioChipname, int line); bool loadConfig(const char *configPath); static bool ends_with(std::string_view str, std::string_view suffix); void getMacAddr(uint8_t *dmac);