Multi gpiochip support for native environment (#5743)

* For each GPIO PIN, allow to specify gpiochip and line

* Added support for LLCC68 in native env.

* Removed one if by employing &&

* Fix for log, as std::string and not const char*

* Remove CH341 flag, enabling it for all LoRa chips

* Provide a default example

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
This commit is contained in:
Patrick Siegl 2025-01-12 20:40:25 +01:00 committed by GitHub
parent 0cf4a2951a
commit 70296b47bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 237 additions and 229 deletions

View File

@ -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
# MACAddressSource: eth0

View File

@ -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");
LOG_WARN("No %s radio", loraModule.strName.c_str());
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");
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
#endif

View File

@ -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
#endif

View File

@ -51,9 +51,9 @@ template <typename T> bool SX126xInterface<T>::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 <typename T> bool SX126xInterface<T>::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 <typename T> bool SX126xInterface<T>::sleep()
return true;
}
#endif
#endif

View File

@ -38,13 +38,13 @@ template <typename T> bool SX128xInterface<T>::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 <typename T> bool SX128xInterface<T>::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 <typename T> void SX128xInterface<T>::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 <typename T> void SX128xInterface<T>::addReceiveMetadata(meshtastic_Mes
template <typename T> void SX128xInterface<T>::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 <typename T> void SX128xInterface<T>::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 <typename T> bool SX128xInterface<T>::sleep()
return true;
}
#endif
#endif

View File

@ -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<std::string>("") == "sx1262") {
settingsMap[use_sx1262] = true;
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "RF95") {
settingsMap[use_rf95] = true;
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "sx1280") {
settingsMap[use_sx1280] = true;
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1110") {
settingsMap[use_lr1110] = true;
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1120") {
settingsMap[use_lr1120] = true;
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "lr1121") {
settingsMap[use_lr1121] = true;
} else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as<std::string>("") == "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<std::string>("") == loraModule.strName) {
settingsMap[loraModule.cfgName] = true;
break;
}
}
}
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000;
if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) {
settingsMap[dio3_tcxo_voltage] = 1800; // default millivolts for "true"
}
settingsMap[cs] = yamlConfig["Lora"]["CS"].as<int>(RADIOLIB_NC);
settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as<int>(RADIOLIB_NC);
settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC);
settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC);
settingsMap[txen] = yamlConfig["Lora"]["TXen"].as<int>(RADIOLIB_NC);
settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC);
settingsMap[sx126x_ant_sw] = yamlConfig["Lora"]["SX126X_ANT_SW"].as<int>(RADIOLIB_NC);
settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
// backwards API compatibility and to globally set gpiochip once
int defaultGpioChip = settingsMap[default_gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(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<int>(RADIOLIB_NC);
settingsMap[pinMap.line] = yamlConfig["Lora"][pinMap.strName]["line"].as<int>(settingsMap[pinMap.pin]);
settingsMap[pinMap.gpiochip] = yamlConfig["Lora"][pinMap.strName]["gpiochip"].as<int>(defaultGpioChip);
}
else { // backwards API compatibility
settingsMap[pinMap.pin] = yamlConfig["Lora"][pinMap.strName].as<int>(RADIOLIB_NC);
settingsMap[pinMap.line] = settingsMap[pinMap.pin];
settingsMap[pinMap.gpiochip] = defaultGpioChip;
}
}
settingsMap[spiSpeed] = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
settingsStrings[lora_usb_serial_num] = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>("");
settingsMap[lora_usb_pid] = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512);

View File

@ -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<configNames, int> settingsMap;
extern std::map<configNames, std::string> 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);