Portduino config refactor (#7796)

* Start portduino_config refactor

* refactor GPIOs to new portduino_config

* More portduino_config work

* More conversion to portduino_config

* Finish portduino_config transition

* trunk

* yaml output work

* Simplify the GPIO config

* Trunk
This commit is contained in:
Jonathan Bennett
2025-09-19 08:24:35 -05:00
committed by Ben Meadors
co-authored by Ben Meadors
parent 6a92358b68
commit cc579dd0bd
25 changed files with 855 additions and 646 deletions
+2 -2
View File
@@ -76,7 +76,7 @@ bool loopCanSleep()
// Called just prior to starting Meshtastic. Allows for setting config values before startup. // Called just prior to starting Meshtastic. Allows for setting config values before startup.
void lateInitVariant() void lateInitVariant()
{ {
settingsMap[logoutputlevel] = level_error; portduino_config.logoutputlevel = level_error;
channelFile.channels[0] = meshtastic_Channel{ channelFile.channels[0] = meshtastic_Channel{
.has_settings = true, .has_settings = true,
.settings = .settings =
@@ -132,7 +132,7 @@ int portduino_main(int argc, char **argv); // Renamed "main" function from Mesht
// Start Meshtastic in a thread and wait till it has reached the ON state. // Start Meshtastic in a thread and wait till it has reached the ON state.
int LLVMFuzzerInitialize(int *argc, char ***argv) int LLVMFuzzerInitialize(int *argc, char ***argv)
{ {
settingsMap[maxtophone] = 5; portduino_config.maxtophone = 5;
meshtasticThread = std::thread([program = *argv[0]]() { meshtasticThread = std::thread([program = *argv[0]]() {
char nodeIdStr[12]; char nodeIdStr[12];
+1 -1
View File
@@ -146,7 +146,7 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
{ {
int result; int result;
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
bool utf = !settingsMap[ascii_logs]; bool utf = !portduino_config.ascii_logs;
#else #else
bool utf = true; bool utf = true;
#endif #endif
+7 -7
View File
@@ -58,7 +58,7 @@ size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_l
#endif #endif
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
bool color = !settingsMap[ascii_logs]; bool color = !portduino_config.ascii_logs;
#else #else
bool color = true; bool color = true;
#endif #endif
@@ -100,7 +100,7 @@ void RedirectablePrint::log_to_serial(const char *logLevel, const char *format,
size_t r = 0; size_t r = 0;
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
bool color = !settingsMap[ascii_logs]; bool color = !portduino_config.ascii_logs;
#else #else
bool color = true; bool color = true;
#endif #endif
@@ -299,7 +299,7 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
// level trace is special, two possible ways to handle it. // level trace is special, two possible ways to handle it.
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) { if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
if (settingsStrings[traceFilename] != "") { if (portduino_config.traceFilename != "") {
va_list arg; va_list arg;
va_start(arg, format); va_start(arg, format);
try { try {
@@ -308,18 +308,18 @@ void RedirectablePrint::log(const char *logLevel, const char *format, ...)
} }
va_end(arg); va_end(arg);
} }
if (settingsMap[logoutputlevel] < level_trace && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) { if (portduino_config.logoutputlevel < level_trace && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_TRACE) == 0) {
delete[] newFormat; delete[] newFormat;
return; return;
} }
} }
if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) { if (portduino_config.logoutputlevel < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
delete[] newFormat; delete[] newFormat;
return; return;
} else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) { } else if (portduino_config.logoutputlevel < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) {
delete[] newFormat; delete[] newFormat;
return; return;
} else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) { } else if (portduino_config.logoutputlevel < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) {
delete[] newFormat; delete[] newFormat;
return; return;
} }
+1 -1
View File
@@ -1440,7 +1440,7 @@ GPS *GPS::createGps()
_en_gpio = PIN_GPS_EN; _en_gpio = PIN_GPS_EN;
#endif #endif
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
if (!settingsMap[has_gps]) if (!portduino_config.has_gps)
return nullptr; return nullptr;
#endif #endif
if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all if (!_rx_gpio || !_serial_gps) // Configured to have no GPS at all
+2 -2
View File
@@ -340,7 +340,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
if (settingsMap[displayPanel] != no_screen) { if (portduino_config.displayPanel != no_screen) {
LOG_DEBUG("Make TFTDisplay!"); LOG_DEBUG("Make TFTDisplay!");
dispdev = new TFTDisplay(address.address, -1, -1, geometry, dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
@@ -588,7 +588,7 @@ void Screen::setup()
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
if (settingsMap[touchscreenModule]) { if (portduino_config.touchscreenModule) {
touchScreenImpl1 = touchScreenImpl1 =
new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch); new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast<TFTDisplay *>(dispdev)->getTouch);
touchScreenImpl1->init(); touchScreenImpl1->init();
+44 -44
View File
@@ -767,24 +767,24 @@ class LGFX : public lgfx::LGFX_Device
LGFX(void) LGFX(void)
{ {
if (settingsMap[displayPanel] == st7789) if (portduino_config.displayPanel == st7789)
_panel_instance = new lgfx::Panel_ST7789; _panel_instance = new lgfx::Panel_ST7789;
else if (settingsMap[displayPanel] == st7735) else if (portduino_config.displayPanel == st7735)
_panel_instance = new lgfx::Panel_ST7735; _panel_instance = new lgfx::Panel_ST7735;
else if (settingsMap[displayPanel] == st7735s) else if (portduino_config.displayPanel == st7735s)
_panel_instance = new lgfx::Panel_ST7735S; _panel_instance = new lgfx::Panel_ST7735S;
else if (settingsMap[displayPanel] == st7796) else if (portduino_config.displayPanel == st7796)
_panel_instance = new lgfx::Panel_ST7796; _panel_instance = new lgfx::Panel_ST7796;
else if (settingsMap[displayPanel] == ili9341) else if (portduino_config.displayPanel == ili9341)
_panel_instance = new lgfx::Panel_ILI9341; _panel_instance = new lgfx::Panel_ILI9341;
else if (settingsMap[displayPanel] == ili9342) else if (portduino_config.displayPanel == ili9342)
_panel_instance = new lgfx::Panel_ILI9342; _panel_instance = new lgfx::Panel_ILI9342;
else if (settingsMap[displayPanel] == ili9488) else if (portduino_config.displayPanel == ili9488)
_panel_instance = new lgfx::Panel_ILI9488; _panel_instance = new lgfx::Panel_ILI9488;
else if (settingsMap[displayPanel] == hx8357d) else if (portduino_config.displayPanel == hx8357d)
_panel_instance = new lgfx::Panel_HX8357D; _panel_instance = new lgfx::Panel_HX8357D;
#if defined(LGFX_SDL) #if defined(LGFX_SDL)
else if (settingsMap[displayPanel] == x11) { else if (portduino_config.displayPanel == x11) {
_panel_instance = new lgfx::Panel_sdl; _panel_instance = new lgfx::Panel_sdl;
} }
#endif #endif
@@ -795,61 +795,61 @@ class LGFX : public lgfx::LGFX_Device
auto buscfg = _bus_instance.config(); auto buscfg = _bus_instance.config();
buscfg.spi_mode = 0; buscfg.spi_mode = 0;
buscfg.spi_host = settingsMap[displayspidev]; buscfg.spi_host = portduino_config.display_spi_dev_int;
buscfg.pin_dc = settingsMap[displayDC]; // Set SPI DC pin number (-1 = disable) buscfg.pin_dc = portduino_config.displayDC.pin; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(buscfg); // applies the set value to the bus. _bus_instance.config(buscfg); // applies the set value to the bus.
_panel_instance->setBus(&_bus_instance); // set the bus on the panel. _panel_instance->setBus(&_bus_instance); // set the bus on the panel.
auto cfg = _panel_instance->config(); // Gets a structure for display panel settings. auto cfg = _panel_instance->config(); // Gets a structure for display panel settings.
LOG_DEBUG("Width: %d, Height: %d", settingsMap[displayWidth], settingsMap[displayHeight]); LOG_DEBUG("Width: %d, Height: %d", portduino_config.displayWidth, portduino_config.displayHeight);
cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable) cfg.pin_cs = portduino_config.displayCS.pin; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = settingsMap[displayReset]; cfg.pin_rst = portduino_config.displayReset.pin;
if (settingsMap[displayRotate]) { if (portduino_config.displayRotate) {
cfg.panel_width = settingsMap[displayHeight]; // actual displayable width cfg.panel_width = portduino_config.displayHeight; // actual displayable width
cfg.panel_height = settingsMap[displayWidth]; // actual displayable height cfg.panel_height = portduino_config.displayWidth; // actual displayable height
} else { } else {
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width cfg.panel_width = portduino_config.displayWidth; // actual displayable width
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height cfg.panel_height = portduino_config.displayHeight; // actual displayable height
} }
cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction cfg.offset_x = portduino_config.displayOffsetX; // Panel offset amount in X direction
cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction cfg.offset_y = portduino_config.displayOffsetY; // Panel offset amount in Y direction
cfg.offset_rotation = settingsMap[displayOffsetRotate]; // Rotation direction value offset 0~7 (4~7 is mirrored) cfg.offset_rotation = portduino_config.displayOffsetRotate; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed cfg.invert = portduino_config.displayInvert; // Set to true if the light/darkness of the panel is reversed
_panel_instance->config(cfg); _panel_instance->config(cfg);
// Configure settings for touch control. // Configure settings for touch control.
if (settingsMap[touchscreenModule]) { if (portduino_config.touchscreenModule) {
if (settingsMap[touchscreenModule] == xpt2046) { if (portduino_config.touchscreenModule == xpt2046) {
_touch_instance = new lgfx::Touch_XPT2046; _touch_instance = new lgfx::Touch_XPT2046;
} else if (settingsMap[touchscreenModule] == stmpe610) { } else if (portduino_config.touchscreenModule == stmpe610) {
_touch_instance = new lgfx::Touch_STMPE610; _touch_instance = new lgfx::Touch_STMPE610;
} else if (settingsMap[touchscreenModule] == ft5x06) { } else if (portduino_config.touchscreenModule == ft5x06) {
_touch_instance = new lgfx::Touch_FT5x06; _touch_instance = new lgfx::Touch_FT5x06;
} }
auto touch_cfg = _touch_instance->config(); auto touch_cfg = _touch_instance->config();
touch_cfg.pin_cs = settingsMap[touchscreenCS]; touch_cfg.pin_cs = portduino_config.touchscreenCS.pin;
touch_cfg.x_min = 0; touch_cfg.x_min = 0;
touch_cfg.x_max = settingsMap[displayHeight] - 1; touch_cfg.x_max = portduino_config.displayHeight - 1;
touch_cfg.y_min = 0; touch_cfg.y_min = 0;
touch_cfg.y_max = settingsMap[displayWidth] - 1; touch_cfg.y_max = portduino_config.displayWidth - 1;
touch_cfg.pin_int = settingsMap[touchscreenIRQ]; touch_cfg.pin_int = portduino_config.touchscreenIRQ.pin;
touch_cfg.bus_shared = true; touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = settingsMap[touchscreenRotate]; touch_cfg.offset_rotation = portduino_config.touchscreenRotate;
if (settingsMap[touchscreenI2CAddr] != -1) { if (portduino_config.touchscreenI2CAddr != -1) {
touch_cfg.i2c_addr = settingsMap[touchscreenI2CAddr]; touch_cfg.i2c_addr = portduino_config.touchscreenI2CAddr;
} else { } else {
touch_cfg.spi_host = settingsMap[touchscreenspidev]; touch_cfg.spi_host = portduino_config.touchscreen_spi_dev_int;
} }
_touch_instance->config(touch_cfg); _touch_instance->config(touch_cfg);
_panel_instance->setTouch(_touch_instance); _panel_instance->setTouch(_touch_instance);
} }
#if defined(LGFX_SDL) #if defined(LGFX_SDL)
if (settingsMap[displayPanel] == x11) { if (portduino_config.displayPanel == x11) {
lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)_panel_instance; lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)_panel_instance;
sdl_panel_->setup(); sdl_panel_->setup();
sdl_panel_->addKeyCodeMapping(SDLK_RETURN, SDL_SCANCODE_KP_ENTER); sdl_panel_->addKeyCodeMapping(SDLK_RETURN, SDL_SCANCODE_KP_ENTER);
@@ -1115,10 +1115,10 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY g
backlightEnable = p; backlightEnable = p;
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[displayRotate]) { if (portduino_config.displayRotate) {
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayWidth], settingsMap[configNames::displayHeight]); setGeometry(GEOMETRY_RAWMODE, portduino_config.displayWidth, portduino_config.displayWidth);
} else { } else {
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]); setGeometry(GEOMETRY_RAWMODE, portduino_config.displayHeight, portduino_config.displayHeight);
} }
#elif defined(SCREEN_ROTATE) #elif defined(SCREEN_ROTATE)
@@ -1240,7 +1240,7 @@ void TFTDisplay::sdlLoop()
#if defined(LGFX_SDL) #if defined(LGFX_SDL)
static int lastPressed = 0; static int lastPressed = 0;
static int shuttingDown = false; static int shuttingDown = false;
if (settingsMap[displayPanel] == x11) { if (portduino_config.displayPanel == x11) {
lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)tft->_panel_instance; lgfx::Panel_sdl *sdl_panel_ = (lgfx::Panel_sdl *)tft->_panel_instance;
if (sdl_panel_->loop() && !shuttingDown) { if (sdl_panel_->loop() && !shuttingDown) {
LOG_WARN("Window Closed!"); LOG_WARN("Window Closed!");
@@ -1288,8 +1288,8 @@ void TFTDisplay::sendCommand(uint8_t com)
backlightEnable->set(true); backlightEnable->set(true);
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
display(true); display(true);
if (settingsMap[displayBacklight] > 0) if (portduino_config.displayBacklight.pin > 0)
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON); digitalWrite(portduino_config.displayBacklight.pin, TFT_BACKLIGHT_ON);
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) #elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
tft->wakeup(); tft->wakeup();
tft->powerSaveOff(); tft->powerSaveOff();
@@ -1312,8 +1312,8 @@ void TFTDisplay::sendCommand(uint8_t com)
backlightEnable->set(false); backlightEnable->set(false);
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
tft->clear(); tft->clear();
if (settingsMap[displayBacklight] > 0) if (portduino_config.displayBacklight.pin > 0)
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON); digitalWrite(portduino_config.displayBacklight.pin, !TFT_BACKLIGHT_ON);
#elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE) #elif !defined(RAK14014) && !defined(M5STACK) && !defined(UNPHONE)
tft->sleep(); tft->sleep();
tft->powerSaveOn(); tft->powerSaveOn();
+48 -48
View File
@@ -41,78 +41,78 @@ void tftSetup(void)
PacketAPI::create(PacketServer::init()); PacketAPI::create(PacketServer::init());
deviceScreen->init(new PacketClient); deviceScreen->init(new PacketClient);
#else #else
if (settingsMap[displayPanel] != no_screen) { if (portduino_config.displayPanel != no_screen) {
DisplayDriverConfig displayConfig; DisplayDriverConfig displayConfig;
static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S", static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S",
"ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"}; "ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"};
static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"}; static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"};
#if defined(USE_X11) #if defined(USE_X11)
if (settingsMap[displayPanel] == x11) { if (portduino_config.displayPanel == x11) {
if (settingsMap[displayWidth] && settingsMap[displayHeight]) if (portduino_config.displayWidth && portduino_config.displayHeight)
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth], displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)portduino_config.displayWidth,
(uint16_t)settingsMap[displayHeight]); (uint16_t)portduino_config.displayHeight);
else else
displayConfig.device(DisplayDriverConfig::device_t::X11); displayConfig.device(DisplayDriverConfig::device_t::X11);
} else } else
#elif defined(USE_FRAMEBUFFER) #elif defined(USE_FRAMEBUFFER)
if (settingsMap[displayPanel] == fb) { if (portduino_config.displayPanel == fb) {
if (settingsMap[displayWidth] && settingsMap[displayHeight]) if (portduino_config.displayWidth && portduino_config.displayHeight)
displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)settingsMap[displayWidth], displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)portduino_config.displayWidth,
(uint16_t)settingsMap[displayHeight]); (uint16_t)portduino_config.displayHeight);
else else
displayConfig.device(DisplayDriverConfig::device_t::FB); displayConfig.device(DisplayDriverConfig::device_t::FB);
} else } else
#endif #endif
{ {
displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT) displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT)
.panel(DisplayDriverConfig::panel_config_t{.type = panels[settingsMap[displayPanel]], .panel(DisplayDriverConfig::panel_config_t{.type = panels[portduino_config.displayPanel],
.panel_width = (uint16_t)settingsMap[displayWidth], .panel_width = (uint16_t)portduino_config.displayWidth,
.panel_height = (uint16_t)settingsMap[displayHeight], .panel_height = (uint16_t)portduino_config.displayHeight,
.rotation = (bool)settingsMap[displayRotate], .rotation = (bool)portduino_config.displayRotate,
.pin_cs = (int16_t)settingsMap[displayCS], .pin_cs = (int16_t)portduino_config.displayCS.pin,
.pin_rst = (int16_t)settingsMap[displayReset], .pin_rst = (int16_t)portduino_config.displayReset.pin,
.offset_x = (uint16_t)settingsMap[displayOffsetX], .offset_x = (uint16_t)portduino_config.displayOffsetX,
.offset_y = (uint16_t)settingsMap[displayOffsetY], .offset_y = (uint16_t)portduino_config.displayOffsetY,
.offset_rotation = (uint8_t)settingsMap[displayOffsetRotate], .offset_rotation = (uint8_t)portduino_config.displayOffsetRotate,
.invert = settingsMap[displayInvert] ? true : false, .invert = portduino_config.displayInvert ? true : false,
.rgb_order = (bool)settingsMap[displayRGBOrder], .rgb_order = (bool)portduino_config.displayRGBOrder,
.dlen_16bit = settingsMap[displayPanel] == ili9486 || .dlen_16bit = portduino_config.displayPanel == ili9486 ||
settingsMap[displayPanel] == ili9488}) portduino_config.displayPanel == ili9488})
.bus(DisplayDriverConfig::bus_config_t{.freq_write = (uint32_t)settingsMap[displayBusFrequency], .bus(DisplayDriverConfig::bus_config_t{.freq_write = (uint32_t)portduino_config.displayBusFrequency,
.freq_read = 16000000, .freq_read = 16000000,
.spi{.pin_dc = (int8_t)settingsMap[displayDC], .spi{.pin_dc = (int8_t)portduino_config.displayDC.pin,
.use_lock = true, .use_lock = true,
.spi_host = (uint16_t)settingsMap[displayspidev]}}) .spi_host = (uint16_t)portduino_config.display_spi_dev_int}})
.input(DisplayDriverConfig::input_config_t{.keyboardDevice = settingsStrings[keyboardDevice], .input(DisplayDriverConfig::input_config_t{.keyboardDevice = portduino_config.keyboardDevice,
.pointerDevice = settingsStrings[pointerDevice]}) .pointerDevice = portduino_config.pointerDevice})
.light(DisplayDriverConfig::light_config_t{.pin_bl = (int16_t)settingsMap[displayBacklight], .light(DisplayDriverConfig::light_config_t{.pin_bl = (int16_t)portduino_config.displayBacklight.pin,
.pwm_channel = (int8_t)settingsMap[displayBacklightPWMChannel], .pwm_channel = (int8_t)portduino_config.displayBacklightPWMChannel.pin,
.invert = (bool)settingsMap[displayBacklightInvert]}); .invert = (bool)portduino_config.displayBacklightInvert});
if (settingsMap[touchscreenI2CAddr] == -1) { if (portduino_config.touchscreenI2CAddr == -1) {
displayConfig.touch( displayConfig.touch(
DisplayDriverConfig::touch_config_t{.type = touch[settingsMap[touchscreenModule]], DisplayDriverConfig::touch_config_t{.type = touch[portduino_config.touchscreenModule],
.freq = (uint32_t)settingsMap[touchscreenBusFrequency], .freq = (uint32_t)portduino_config.touchscreenBusFrequency,
.pin_int = (int16_t)settingsMap[touchscreenIRQ], .pin_int = (int16_t)portduino_config.touchscreenIRQ.pin,
.offset_rotation = (uint8_t)settingsMap[touchscreenRotate], .offset_rotation = (uint8_t)portduino_config.touchscreenRotate,
.spi{ .spi{
.spi_host = (int8_t)settingsMap[touchscreenspidev], .spi_host = (int8_t)portduino_config.touchscreen_spi_dev_int,
}, },
.pin_cs = (int16_t)settingsMap[touchscreenCS]}); .pin_cs = (int16_t)portduino_config.touchscreenCS.pin});
} else { } else {
displayConfig.touch(DisplayDriverConfig::touch_config_t{ displayConfig.touch(DisplayDriverConfig::touch_config_t{
.type = touch[settingsMap[touchscreenModule]], .type = touch[portduino_config.touchscreenModule],
.freq = (uint32_t)settingsMap[touchscreenBusFrequency], .freq = (uint32_t)portduino_config.touchscreenBusFrequency,
.x_min = 0, .x_min = 0,
.x_max = .x_max = (int16_t)((portduino_config.touchscreenRotate & 1 ? portduino_config.displayWidth
(int16_t)((settingsMap[touchscreenRotate] & 1 ? settingsMap[displayWidth] : settingsMap[displayHeight]) - : portduino_config.displayHeight) -
1), 1),
.y_min = 0, .y_min = 0,
.y_max = .y_max = (int16_t)((portduino_config.touchscreenRotate & 1 ? portduino_config.displayHeight
(int16_t)((settingsMap[touchscreenRotate] & 1 ? settingsMap[displayHeight] : settingsMap[displayWidth]) - : portduino_config.displayWidth) -
1), 1),
.pin_int = (int16_t)settingsMap[touchscreenIRQ], .pin_int = (int16_t)portduino_config.touchscreenIRQ.pin,
.offset_rotation = (uint8_t)settingsMap[touchscreenRotate], .offset_rotation = (uint8_t)portduino_config.touchscreenRotate,
.i2c{.i2c_addr = (uint8_t)settingsMap[touchscreenI2CAddr]}}); .i2c{.i2c_addr = (uint8_t)portduino_config.touchscreenI2CAddr}});
} }
} }
deviceScreen = &DeviceScreen::create(&displayConfig); deviceScreen = &DeviceScreen::create(&displayConfig);
+2 -2
View File
@@ -33,9 +33,9 @@ int32_t LinuxInput::runOnce()
{ {
if (firstTime) { if (firstTime) {
if (settingsStrings[keyboardDevice] == "") if (portduino_config.keyboardDevice == "")
return disable(); return disable();
fd = open(settingsStrings[keyboardDevice].c_str(), O_RDWR); fd = open(portduino_config.keyboardDevice.c_str(), O_RDWR);
if (fd < 0) if (fd < 0)
return disable(); return disable();
ret = ioctl(fd, EVIOCGRAB, (void *)1); ret = ioctl(fd, EVIOCGRAB, (void *)1);
+1 -1
View File
@@ -18,7 +18,7 @@ TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTo
void TouchScreenImpl1::init() void TouchScreenImpl1::init()
{ {
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[touchscreenModule]) { if (portduino_config.touchscreenModule) {
TouchScreenBase::init(true); TouchScreenBase::init(true);
inputBroker->registerSource(this); inputBroker->registerSource(this);
} else { } else {
+1 -1
View File
@@ -6,7 +6,7 @@
#ifndef TB_DIRECTION #ifndef TB_DIRECTION
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
#include "PortduinoGlue.h" #include "PortduinoGlue.h"
#define TB_DIRECTION (PinStatus) settingsMap[tbDirection] #define TB_DIRECTION (PinStatus) portduino_config.lora_usb_vid
#else #else
#define TB_DIRECTION RISING #define TB_DIRECTION RISING
#endif #endif
+37 -53
View File
@@ -387,7 +387,7 @@ void setup()
#endif #endif
concurrency::hasBeenSetup = true; concurrency::hasBeenSetup = true;
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
SPISettings spiSettings(settingsMap[spiSpeed], MSBFIRST, SPI_MODE0); SPISettings spiSettings(portduino_config.spiSpeed, MSBFIRST, SPI_MODE0);
#else #else
SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0);
#endif #endif
@@ -532,9 +532,9 @@ void setup()
#elif defined(I2C_SDA) && !defined(ARCH_RP2040) #elif defined(I2C_SDA) && !defined(ARCH_RP2040)
Wire.begin(I2C_SDA, I2C_SCL); Wire.begin(I2C_SDA, I2C_SCL);
#elif defined(ARCH_PORTDUINO) #elif defined(ARCH_PORTDUINO)
if (settingsStrings[i2cdev] != "") { if (portduino_config.i2cdev != "") {
LOG_INFO("Use %s as I2C device", settingsStrings[i2cdev].c_str()); LOG_INFO("Use %s as I2C device", portduino_config.i2cdev.c_str());
Wire.begin(settingsStrings[i2cdev].c_str()); Wire.begin(portduino_config.i2cdev.c_str());
} else { } else {
LOG_INFO("No I2C device configured, Skip"); LOG_INFO("No I2C device configured, Skip");
} }
@@ -586,7 +586,7 @@ void setup()
#if defined(I2C_SDA) #if defined(I2C_SDA)
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE); i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
#elif defined(ARCH_PORTDUINO) #elif defined(ARCH_PORTDUINO)
if (settingsStrings[i2cdev] != "") { if (portduino_config.i2cdev != "") {
LOG_INFO("Scan for i2c devices"); LOG_INFO("Scan for i2c devices");
i2cScanner->scanPort(ScanI2C::I2CPort::WIRE); i2cScanner->scanPort(ScanI2C::I2CPort::WIRE);
} }
@@ -859,7 +859,7 @@ void setup()
SPI.begin(false); SPI.begin(false);
#endif // HW_SPI1_DEVICE #endif // HW_SPI1_DEVICE
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (settingsStrings[spidev] != "ch341") { if (portduino_config.lora_spi_dev != "ch341") {
SPI.begin(); SPI.begin();
} }
#elif !defined(ARCH_ESP32) // ARCH_RP2040 #elif !defined(ARCH_ESP32) // ARCH_RP2040
@@ -886,7 +886,7 @@ void setup()
defined(USE_SPISSD1306) defined(USE_SPISSD1306)
screen = new graphics::Screen(screen_found, screen_model, screen_geometry); screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
#elif defined(ARCH_PORTDUINO) #elif defined(ARCH_PORTDUINO)
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) && if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) &&
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
screen = new graphics::Screen(screen_found, screen_model, screen_geometry); screen = new graphics::Screen(screen_found, screen_model, screen_geometry);
} }
@@ -987,13 +987,13 @@ void setup()
#endif #endif
#if defined(ARCH_PORTDUINO) #if defined(ARCH_PORTDUINO)
if (settingsMap.count(userButtonPin) != 0 && settingsMap[userButtonPin] != RADIOLIB_NC) { if (portduino_config.userButtonPin.enabled) {
LOG_DEBUG("Use GPIO%02d for button", settingsMap[userButtonPin]); LOG_DEBUG("Use GPIO%02d for button", portduino_config.userButtonPin.pin);
UserButtonThread = new ButtonThread("UserButton"); UserButtonThread = new ButtonThread("UserButton");
if (screen) { if (screen) {
ButtonConfig config; ButtonConfig config;
config.pinNumber = (uint8_t)settingsMap[userButtonPin]; config.pinNumber = (uint8_t)portduino_config.userButtonPin.pin;
config.activeLow = true; config.activeLow = true;
config.activePullup = true; config.activePullup = true;
config.pullupSense = INPUT_PULLUP; config.pullupSense = INPUT_PULLUP;
@@ -1151,7 +1151,7 @@ void setup()
if (screen) if (screen)
screen->setup(); screen->setup();
#elif defined(ARCH_PORTDUINO) #elif defined(ARCH_PORTDUINO)
if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) && if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) &&
config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) {
screen->setup(); screen->setup();
} }
@@ -1167,15 +1167,10 @@ void setup()
#endif #endif
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
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: // 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, auto loraModuleInterface = [](LockingArduinoHal *hal, RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst,
RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy) { RADIOLIB_PIN_TYPE busy) {
switch (cfgName) { switch (portduino_config.lora_module) {
case use_rf95: case use_rf95:
return (RadioInterface *)new RF95Interface(hal, cs, irq, rst, busy); return (RadioInterface *)new RF95Interface(hal, cs, irq, rst, busy);
case use_sx1262: case use_sx1262:
@@ -1192,31 +1187,34 @@ void setup()
return (RadioInterface *)new LR1121Interface(hal, cs, irq, rst, busy); return (RadioInterface *)new LR1121Interface(hal, cs, irq, rst, busy);
case use_llcc68: case use_llcc68:
return (RadioInterface *)new LLCC68Interface(hal, cs, irq, rst, busy); return (RadioInterface *)new LLCC68Interface(hal, cs, irq, rst, busy);
case use_simradio:
return (RadioInterface *)new SimRadio;
default: default:
assert(0); // shouldn't happen assert(0); // shouldn't happen
return (RadioInterface *)nullptr; return (RadioInterface *)nullptr;
} }
}; };
for (auto &loraModule : loraModules) {
if (settingsMap[loraModule.cfgName] && !rIf) { LOG_DEBUG("Activate %s radio on SPI port %s", portduino_config.loraModules[portduino_config.lora_module].c_str(),
LOG_DEBUG("Activate %s radio on SPI port %s", loraModule.strName.c_str(), settingsStrings[spidev].c_str()); portduino_config.lora_spi_dev.c_str());
if (settingsStrings[spidev] == "ch341") { if (portduino_config.lora_spi_dev == "ch341") {
RadioLibHAL = ch341Hal; RadioLibHAL = ch341Hal;
} else { } else {
RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
}
rIf = loraModuleInterface(loraModule.cfgName, (LockingArduinoHal *)RadioLibHAL, settingsMap[cs_pin],
settingsMap[irq_pin], settingsMap[reset_pin], settingsMap[busy_pin]);
if (!rIf->init()) {
LOG_WARN("No %s radio", loraModule.strName.c_str());
delete rIf;
rIf = NULL;
exit(EXIT_FAILURE);
} else {
LOG_INFO("%s init success", loraModule.strName.c_str());
}
}
} }
rIf =
loraModuleInterface((LockingArduinoHal *)RadioLibHAL, portduino_config.lora_cs_pin.pin, portduino_config.lora_irq_pin.pin,
portduino_config.lora_reset_pin.pin, portduino_config.lora_busy_pin.pin);
if (!rIf->init()) {
LOG_WARN("No %s radio", portduino_config.loraModules[portduino_config.lora_module].c_str());
delete rIf;
rIf = NULL;
exit(EXIT_FAILURE);
} else {
LOG_INFO("%s init success", portduino_config.loraModules[portduino_config.lora_module].c_str());
}
#elif defined(HW_SPI1_DEVICE) #elif defined(HW_SPI1_DEVICE)
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings); LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI1, spiSettings);
#else // HW_SPI1_DEVICE #else // HW_SPI1_DEVICE
@@ -1238,20 +1236,6 @@ void setup()
} }
#endif #endif
#if defined(ARCH_PORTDUINO)
if (!rIf) {
rIf = new SimRadio;
if (!rIf->init()) {
LOG_WARN("No simulated radio");
delete rIf;
rIf = NULL;
} else {
LOG_INFO("Use SIMULATED radio!");
radioType = SIM_RADIO;
}
}
#endif
#if defined(RF95_IRQ) && RADIOLIB_EXCLUDE_SX127X != 1 #if defined(RF95_IRQ) && RADIOLIB_EXCLUDE_SX127X != 1
if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) { if ((!rIf) && (config.lora.region != meshtastic_Config_LoRaConfig_RegionCode_LORA_24)) {
rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1); rIf = new RF95Interface(RadioLibHAL, LORA_CS, RF95_IRQ, RF95_RESET, RF95_DIO1);
@@ -1462,7 +1446,7 @@ void setup()
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
#if __has_include(<ulfius.h>) #if __has_include(<ulfius.h>)
if (settingsMap[webserverport] != -1) { if (portduino_config.webserverport != -1) {
piwebServerThread = new PiWebServerThread(); piwebServerThread = new PiWebServerThread();
std::atexit([] { delete piwebServerThread; }); std::atexit([] { delete piwebServerThread; });
} }
+3 -3
View File
@@ -21,7 +21,7 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not // Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and LR11x0 power config forgotten) // specified (may be dangerous if using external PA and LR11x0 power config forgotten)
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
#define LR1110_MAX_POWER settingsMap[lr1110_max_power] #define LR1110_MAX_POWER portduino_config.lr1110_max_power
#endif #endif
#ifndef LR1110_MAX_POWER #ifndef LR1110_MAX_POWER
#define LR1110_MAX_POWER 22 #define LR1110_MAX_POWER 22
@@ -30,7 +30,7 @@ static const Module::RfSwitchMode_t rfswitch_table[] = {
// the 2.4G part maxes at 13dBm // the 2.4G part maxes at 13dBm
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
#define LR1120_MAX_POWER settingsMap[lr1120_max_power] #define LR1120_MAX_POWER portduino_config.lr1120_max_power
#endif #endif
#ifndef LR1120_MAX_POWER #ifndef LR1120_MAX_POWER
#define LR1120_MAX_POWER 13 #define LR1120_MAX_POWER 13
@@ -55,7 +55,7 @@ template <typename T> bool LR11x0Interface<T>::init()
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
float tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; float tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000;
// FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE // FIXME: correct logic to default to not using TCXO if no voltage is specified for LR11x0_DIO3_TCXO_VOLTAGE
#elif !defined(LR11X0_DIO3_TCXO_VOLTAGE) #elif !defined(LR11X0_DIO3_TCXO_VOLTAGE)
float tcxoVoltage = float tcxoVoltage =
+3 -3
View File
@@ -673,7 +673,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
#endif #endif
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
bool hasScreen = false; bool hasScreen = false;
if (settingsMap[displayPanel]) if (portduino_config.displayPanel)
hasScreen = true; hasScreen = true;
else else
hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C; hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C;
@@ -1334,8 +1334,8 @@ void NodeDB::loadFromDisk()
} }
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
// set any config overrides // set any config overrides
if (settingsMap[has_configDisplayMode]) { if (portduino_config.has_configDisplayMode) {
config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)settingsMap[configDisplayMode]; config.display.displaymode = (_meshtastic_Config_DisplayConfig_DisplayMode)portduino_config.configDisplayMode;
} }
#endif #endif
+11 -11
View File
@@ -10,7 +10,7 @@
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
#define RF95_MAX_POWER settingsMap[rf95_max_power] #define RF95_MAX_POWER portduino_config.rf95_max_power
#endif #endif
#ifndef RF95_MAX_POWER #ifndef RF95_MAX_POWER
#define RF95_MAX_POWER 20 #define RF95_MAX_POWER 20
@@ -94,16 +94,16 @@ void RF95Interface::setTransmitEnable(bool txon)
#ifdef RF95_TXEN #ifdef RF95_TXEN
digitalWrite(RF95_TXEN, txon ? 1 : 0); digitalWrite(RF95_TXEN, txon ? 1 : 0);
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (settingsMap[txen_pin] != RADIOLIB_NC) { if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[txen_pin], txon ? 1 : 0); digitalWrite(portduino_config.lora_txen_pin.pin, txon ? 1 : 0);
} }
#endif #endif
#ifdef RF95_RXEN #ifdef RF95_RXEN
digitalWrite(RF95_RXEN, txon ? 0 : 1); digitalWrite(RF95_RXEN, txon ? 0 : 1);
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen_pin], txon ? 0 : 1); digitalWrite(portduino_config.lora_rxen_pin.pin, txon ? 0 : 1);
} }
#endif #endif
} }
@@ -164,13 +164,13 @@ bool RF95Interface::init()
digitalWrite(RF95_RXEN, 1); digitalWrite(RF95_RXEN, 1);
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[txen_pin] != RADIOLIB_NC) { if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
pinMode(settingsMap[txen_pin], OUTPUT); pinMode(portduino_config.lora_txen_pin.pin, OUTPUT);
digitalWrite(settingsMap[txen_pin], 0); digitalWrite(portduino_config.lora_txen_pin.pin, 0);
} }
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
pinMode(settingsMap[rxen_pin], OUTPUT); pinMode(portduino_config.lora_rxen_pin.pin, OUTPUT);
digitalWrite(settingsMap[rxen_pin], 0); digitalWrite(portduino_config.lora_rxen_pin.pin, 0);
} }
#endif #endif
setTransmitEnable(false); setTransmitEnable(false);
+1 -1
View File
@@ -417,7 +417,7 @@ void RadioLibInterface::handleReceiveInterrupt()
int state = iface->readData((uint8_t *)&radioBuffer, length); int state = iface->readData((uint8_t *)&radioBuffer, length);
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[logoutputlevel] == level_trace) { if (portduino_config.logoutputlevel == level_trace) {
printBytes("Raw incoming packet: ", (uint8_t *)&radioBuffer, length); printBytes("Raw incoming packet: ", (uint8_t *)&radioBuffer, length);
} }
#endif #endif
+2 -2
View File
@@ -490,7 +490,7 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p)
#if ENABLE_JSON_LOGGING #if ENABLE_JSON_LOGGING
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str()); LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (settingsStrings[traceFilename] != "" || settingsMap[logoutputlevel] == level_trace) { if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) {
LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str()); LOG_TRACE("%s", MeshPacketSerializer::JsonSerialize(p, false).c_str());
} }
#endif #endif
@@ -730,7 +730,7 @@ void Router::perhapsHandleReceived(meshtastic_MeshPacket *p)
LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str()); LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str());
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
// Even ignored packets get logged in the trace // Even ignored packets get logged in the trace
if (settingsStrings[traceFilename] != "" || settingsMap[logoutputlevel] == level_trace) { if (portduino_config.traceFilename != "" || portduino_config.logoutputlevel == level_trace) {
p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone p->rx_time = getValidTime(RTCQualityFromNet); // store the arrival timestamp for the phone
LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str()); LOG_TRACE("%s", MeshPacketSerializer::JsonSerializeEncrypted(p).c_str());
} }
+9 -9
View File
@@ -12,7 +12,7 @@
// Particular boards might define a different max power based on what their hardware can do, default to max power output if not // Particular boards might define a different max power based on what their hardware can do, default to max power output if not
// specified (may be dangerous if using external PA and SX126x power config forgotten) // specified (may be dangerous if using external PA and SX126x power config forgotten)
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
#define SX126X_MAX_POWER settingsMap[sx126x_max_power] #define SX126X_MAX_POWER portduino_config.sx126x_max_power
#endif #endif
#ifndef SX126X_MAX_POWER #ifndef SX126X_MAX_POWER
#define SX126X_MAX_POWER 22 #define SX126X_MAX_POWER 22
@@ -53,10 +53,10 @@ template <typename T> bool SX126xInterface<T>::init()
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
tcxoVoltage = (float)settingsMap[dio3_tcxo_voltage] / 1000; tcxoVoltage = (float)portduino_config.dio3_tcxo_voltage / 1000;
if (settingsMap[sx126x_ant_sw_pin] != RADIOLIB_NC) { if (portduino_config.lora_sx126x_ant_sw_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[sx126x_ant_sw_pin], HIGH); digitalWrite(portduino_config.lora_sx126x_ant_sw_pin.pin, HIGH);
pinMode(settingsMap[sx126x_ant_sw_pin], OUTPUT); pinMode(portduino_config.lora_sx126x_ant_sw_pin.pin, OUTPUT);
} }
#endif #endif
if (tcxoVoltage == 0.0) if (tcxoVoltage == 0.0)
@@ -98,7 +98,7 @@ template <typename T> bool SX126xInterface<T>::init()
bool dio2AsRfSwitch = true; bool dio2AsRfSwitch = true;
#elif defined(ARCH_PORTDUINO) #elif defined(ARCH_PORTDUINO)
bool dio2AsRfSwitch = false; bool dio2AsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) { if (portduino_config.dio2_as_rf_switch) {
dio2AsRfSwitch = true; dio2AsRfSwitch = true;
} }
#else #else
@@ -112,9 +112,9 @@ template <typename T> bool SX126xInterface<T>::init()
// no effect // no effect
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (res == RADIOLIB_ERR_NONE) { if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", settingsMap[rxen_pin], LOG_DEBUG("Use MCU pin %i as RXEN and pin %i as TXEN to control RF switching", portduino_config.lora_rxen_pin.pin,
settingsMap[txen_pin]); portduino_config.lora_txen_pin.pin);
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]); lora.setRfSwitchPins(portduino_config.lora_rxen_pin.pin, portduino_config.lora_txen_pin.pin);
} }
#else #else
#ifndef SX126X_RXEN #ifndef SX126X_RXEN
+22 -21
View File
@@ -11,7 +11,7 @@
// Particular boards might define a different max power based on what their hardware can do // Particular boards might define a different max power based on what their hardware can do
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
#define SX128X_MAX_POWER settingsMap[sx128x_max_power] #define SX128X_MAX_POWER portduino_config.sx128x_max_power
#endif #endif
#ifndef SX128X_MAX_POWER #ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 13 #define SX128X_MAX_POWER 13
@@ -41,13 +41,13 @@ template <typename T> bool SX128xInterface<T>::init()
#endif #endif
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
pinMode(settingsMap[rxen_pin], OUTPUT); pinMode(portduino_config.lora_rxen_pin.pin, OUTPUT);
digitalWrite(settingsMap[rxen_pin], LOW); // Set low before becoming an output digitalWrite(portduino_config.lora_rxen_pin.pin, LOW); // Set low before becoming an output
} }
if (settingsMap[txen_pin] != RADIOLIB_NC) { if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
pinMode(settingsMap[txen_pin], OUTPUT); pinMode(portduino_config.lora_txen_pin.pin, OUTPUT);
digitalWrite(settingsMap[txen_pin], LOW); // Set low before becoming an output digitalWrite(portduino_config.lora_txen_pin.pin, LOW); // Set low before becoming an output
} }
#else #else
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode #if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // set not rx or tx mode
@@ -93,8 +93,9 @@ template <typename T> bool SX128xInterface<T>::init()
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN); lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
} }
#elif ARCH_PORTDUINO #elif ARCH_PORTDUINO
if (res == RADIOLIB_ERR_NONE && settingsMap[rxen_pin] != RADIOLIB_NC && settingsMap[txen_pin] != RADIOLIB_NC) { if (res == RADIOLIB_ERR_NONE && portduino_config.lora_rxen_pin.pin != RADIOLIB_NC &&
lora.setRfSwitchPins(settingsMap[rxen_pin], settingsMap[txen_pin]); portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
lora.setRfSwitchPins(portduino_config.lora_rxen_pin.pin, portduino_config.lora_txen_pin.pin);
} }
#endif #endif
@@ -174,11 +175,11 @@ template <typename T> void SX128xInterface<T>::setStandby()
LOG_ERROR("SX128x standby %s%d", radioLibErr, err); LOG_ERROR("SX128x standby %s%d", radioLibErr, err);
assert(err == RADIOLIB_ERR_NONE); assert(err == RADIOLIB_ERR_NONE);
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen_pin], LOW); digitalWrite(portduino_config.lora_rxen_pin.pin, LOW);
} }
if (settingsMap[txen_pin] != RADIOLIB_NC) { if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[txen_pin], LOW); digitalWrite(portduino_config.lora_txen_pin.pin, LOW);
} }
#else #else
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power #if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn off RX and TX power
@@ -210,11 +211,11 @@ template <typename T> void SX128xInterface<T>::addReceiveMetadata(meshtastic_Mes
template <typename T> void SX128xInterface<T>::configHardwareForSend() template <typename T> void SX128xInterface<T>::configHardwareForSend()
{ {
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[txen_pin] != RADIOLIB_NC) { if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[txen_pin], HIGH); digitalWrite(portduino_config.lora_txen_pin.pin, HIGH);
} }
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen_pin], LOW); digitalWrite(portduino_config.lora_rxen_pin.pin, LOW);
} }
#else #else
@@ -241,11 +242,11 @@ template <typename T> void SX128xInterface<T>::startReceive()
setStandby(); setStandby();
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[rxen_pin] != RADIOLIB_NC) { if (portduino_config.lora_rxen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen_pin], HIGH); digitalWrite(portduino_config.lora_rxen_pin.pin, HIGH);
} }
if (settingsMap[txen_pin] != RADIOLIB_NC) { if (portduino_config.lora_txen_pin.pin != RADIOLIB_NC) {
digitalWrite(settingsMap[txen_pin], LOW); digitalWrite(portduino_config.lora_txen_pin.pin, LOW);
} }
#else #else
+5 -5
View File
@@ -65,8 +65,8 @@ mail: marchammermann@googlemail.com
#define DEFAULT_REALM "default_realm" #define DEFAULT_REALM "default_realm"
#define PREFIX "" #define PREFIX ""
#define KEY_PATH settingsStrings[websslkeypath].c_str() #define KEY_PATH portduino_config.webserver_ssl_key_path.c_str()
#define CERT_PATH settingsStrings[websslcertpath].c_str() #define CERT_PATH portduino_config.webserver_ssl_cert_path.c_str()
struct _file_config configWeb; struct _file_config configWeb;
@@ -458,8 +458,8 @@ PiWebServerThread::PiWebServerThread()
} }
} }
if (settingsMap[webserverport] != 0) { if (portduino_config.webserverport != 0) {
webservport = settingsMap[webserverport]; webservport = portduino_config.webserverport;
LOG_INFO("Use webserver port from yaml config %i ", webservport); LOG_INFO("Use webserver port from yaml config %i ", webservport);
} else { } else {
LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 9443"); LOG_INFO("Webserver port in yaml config set to 0, defaulting to port 9443");
@@ -490,7 +490,7 @@ PiWebServerThread::PiWebServerThread()
u_map_put(&configWeb.mime_types, ".ico", "image/x-icon"); u_map_put(&configWeb.mime_types, ".ico", "image/x-icon");
u_map_put(&configWeb.mime_types, ".svg", "image/svg+xml"); u_map_put(&configWeb.mime_types, ".svg", "image/svg+xml");
webrootpath = settingsStrings[webserverrootpath]; webrootpath = portduino_config.webserver_root_path;
configWeb.files_path = (char *)webrootpath.c_str(); configWeb.files_path = (char *)webrootpath.c_str();
configWeb.url_prefix = ""; configWeb.url_prefix = "";
+5 -5
View File
@@ -9,11 +9,11 @@
int32_t HostMetricsModule::runOnce() int32_t HostMetricsModule::runOnce()
{ {
#if ARCH_PORTDUINO #if ARCH_PORTDUINO
if (settingsMap[hostMetrics_interval] == 0) { if (portduino_config.hostMetrics_interval == 0) {
return disable(); return disable();
} else { } else {
sendMetrics(); sendMetrics();
return 60 * 1000 * settingsMap[hostMetrics_interval]; return 60 * 1000 * portduino_config.hostMetrics_interval;
} }
#else #else
return disable(); return disable();
@@ -110,8 +110,8 @@ meshtastic_Telemetry HostMetricsModule::getHostMetrics()
proc_loadavg.close(); proc_loadavg.close();
} }
} }
if (settingsStrings[hostMetrics_user_command] != "") { if (portduino_config.hostMetrics_user_command != "") {
std::string userCommandResult = exec(settingsStrings[hostMetrics_user_command].c_str()); std::string userCommandResult = exec(portduino_config.hostMetrics_user_command.c_str());
if (userCommandResult.length() > 1) { if (userCommandResult.length() > 1) {
strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), sizeof(t.variant.host_metrics.user_string)); strncpy(t.variant.host_metrics.user_string, userCommandResult.c_str(), sizeof(t.variant.host_metrics.user_string));
t.variant.host_metrics.user_string[sizeof(t.variant.host_metrics.user_string) - 1] = '\0'; t.variant.host_metrics.user_string[sizeof(t.variant.host_metrics.user_string) - 1] = '\0';
@@ -135,7 +135,7 @@ bool HostMetricsModule::sendMetrics()
p->to = NODENUM_BROADCAST; p->to = NODENUM_BROADCAST;
p->decoded.want_response = false; p->decoded.want_response = false;
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND; p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
p->channel = settingsMap[hostMetrics_channel]; p->channel = portduino_config.hostMetrics_channel;
LOG_INFO("Send packet to mesh"); LOG_INFO("Send packet to mesh");
service->sendToMesh(p, RX_SRC_LOCAL, true); service->sendToMesh(p, RX_SRC_LOCAL, true);
return true; return true;
+214 -320
View File
@@ -9,7 +9,6 @@
#include "api/ServerAPI.h" #include "api/ServerAPI.h"
#include "linux/gpio/LinuxGPIOPin.h" #include "linux/gpio/LinuxGPIOPin.h"
#include "meshUtils.h" #include "meshUtils.h"
#include "yaml-cpp/yaml.h"
#include <ErriezCRC32.h> #include <ErriezCRC32.h>
#include <Utility.h> #include <Utility.h>
#include <assert.h> #include <assert.h>
@@ -28,14 +27,13 @@
#include "platform/portduino/USBHal.h" #include "platform/portduino/USBHal.h"
std::map<configNames, int> settingsMap;
std::map<configNames, std::string> settingsStrings;
portduino_config_struct portduino_config; portduino_config_struct portduino_config;
std::ofstream traceFile; std::ofstream traceFile;
Ch341Hal *ch341Hal = nullptr; Ch341Hal *ch341Hal = nullptr;
char *configPath = nullptr; char *configPath = nullptr;
char *optionMac = nullptr; char *optionMac = nullptr;
bool verboseEnabled = false; bool verboseEnabled = false;
bool yamlOnly = false;
const char *argp_program_version = optstr(APP_VERSION); const char *argp_program_version = optstr(APP_VERSION);
@@ -75,6 +73,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 'v': case 'v':
verboseEnabled = true; verboseEnabled = true;
break; break;
case 'y':
yamlOnly = true;
break;
case ARGP_KEY_ARG: case ARGP_KEY_ARG:
return 0; return 0;
default: default:
@@ -90,6 +91,7 @@ void portduinoCustomInit()
{"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"}, {"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"},
{"sim", 's', 0, 0, "Run in Simulated radio mode"}, {"sim", 's', 0, 0, "Run in Simulated radio mode"},
{"verbose", 'v', 0, 0, "Set log level to full debug"}, {"verbose", 'v', 0, 0, "Set log level to full debug"},
{"output-yaml", 'y', 0, 0, "Output config yaml and exit"},
{0}}; {0}};
static void *childArguments; static void *childArguments;
static char doc[] = "Meshtastic native build."; static char doc[] = "Meshtastic native build.";
@@ -115,8 +117,8 @@ void getMacAddr(uint8_t *dmac)
dmac[4] = hwId >> 8; dmac[4] = hwId >> 8;
dmac[5] = hwId & 0xff; dmac[5] = hwId & 0xff;
} }
} else if (settingsStrings[mac_address].length() > 11) { } else if (portduino_config.mac_address.length() > 11) {
MAC_from_string(settingsStrings[mac_address], dmac); MAC_from_string(portduino_config.mac_address, dmac);
exit; exit;
} else { } else {
@@ -148,89 +150,46 @@ void getMacAddr(uint8_t *dmac)
*/ */
void portduinoSetup() void portduinoSetup()
{ {
printf("Set up Meshtastic on Portduino...\n");
int max_GPIO = 0; int max_GPIO = 0;
const configNames GPIO_lines[] = {cs_pin,
irq_pin,
busy_pin,
reset_pin,
sx126x_ant_sw_pin,
txen_pin,
rxen_pin,
displayDC,
displayCS,
displayBacklight,
displayBacklightPWMChannel,
displayReset,
touchscreenCS,
touchscreenIRQ,
userButtonPin,
tbUpPin,
tbDownPin,
tbLeftPin,
tbRightPin,
tbPressPin};
std::string gpioChipName = "gpiochip"; std::string gpioChipName = "gpiochip";
settingsStrings[i2cdev] = ""; portduino_config.displayPanel = no_screen;
settingsStrings[keyboardDevice] = "";
settingsStrings[pointerDevice] = "";
settingsStrings[webserverrootpath] = "";
settingsStrings[spidev] = "";
settingsStrings[displayspidev] = "";
settingsMap[spiSpeed] = 2000000;
settingsMap[ascii_logs] = !isatty(1);
settingsMap[displayPanel] = no_screen;
settingsMap[touchscreenModule] = no_touchscreen;
settingsMap[tbUpPin] = RADIOLIB_NC;
settingsMap[tbDownPin] = RADIOLIB_NC;
settingsMap[tbLeftPin] = RADIOLIB_NC;
settingsMap[tbRightPin] = RADIOLIB_NC;
settingsMap[tbPressPin] = RADIOLIB_NC;
YAML::Node yamlConfig;
if (portduino_config.force_simradio == true) { if (portduino_config.force_simradio == true) {
settingsMap[use_simradio] = true; portduino_config.lora_module = use_simradio;
} else if (configPath != nullptr) { } else if (configPath != nullptr) {
if (loadConfig(configPath)) { if (loadConfig(configPath)) {
std::cout << "Using " << configPath << " as config file" << std::endl; if (!yamlOnly)
std::cout << "Using " << configPath << " as config file" << std::endl;
} else { } else {
std::cout << "Unable to use " << configPath << " as config file" << std::endl; std::cout << "Unable to use " << configPath << " as config file" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else if (access("config.yaml", R_OK) == 0) { } else if (access("config.yaml", R_OK) == 0) {
if (loadConfig("config.yaml")) { if (loadConfig("config.yaml")) {
std::cout << "Using local config.yaml as config file" << std::endl; if (!yamlOnly)
std::cout << "Using local config.yaml as config file" << std::endl;
} else { } else {
std::cout << "Unable to use local config.yaml as config file" << std::endl; std::cout << "Unable to use local config.yaml as config file" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) { } else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) {
if (loadConfig("/etc/meshtasticd/config.yaml")) { if (loadConfig("/etc/meshtasticd/config.yaml")) {
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl; if (!yamlOnly)
std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl;
} else { } else {
std::cout << "Unable to use /etc/meshtasticd/config.yaml as config file" << std::endl; std::cout << "Unable to use /etc/meshtasticd/config.yaml as config file" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else { } else {
std::cout << "No 'config.yaml' found..." << std::endl; if (!yamlOnly)
settingsMap[use_simradio] = true; std::cout << "No 'config.yaml' found..." << std::endl;
portduino_config.lora_module = use_simradio;
} }
if (settingsMap[use_simradio] == true) { if (portduino_config.config_directory != "") {
std::cout << "Running in simulated mode." << std::endl;
settingsMap[maxnodes] = 200; // Default to 200 nodes
settingsMap[logoutputlevel] = level_debug; // Default to debug
// Set the random seed equal to TCPPort to have a different seed per instance
randomSeed(TCPPort);
return;
}
if (settingsStrings[config_directory] != "") {
std::string filetype = ".yaml"; std::string filetype = ".yaml";
for (const std::filesystem::directory_entry &entry : for (const std::filesystem::directory_entry &entry :
std::filesystem::directory_iterator{settingsStrings[config_directory]}) { std::filesystem::directory_iterator{portduino_config.config_directory}) {
if (ends_with(entry.path().string(), ".yaml")) { if (ends_with(entry.path().string(), ".yaml")) {
std::cout << "Also using " << entry << " as additional config file" << std::endl; std::cout << "Also using " << entry << " as additional config file" << std::endl;
loadConfig(entry.path().c_str()); loadConfig(entry.path().c_str());
@@ -238,15 +197,28 @@ void portduinoSetup()
} }
} }
if (yamlOnly) {
std::cout << portduino_config.emit_yaml() << std::endl;
exit(EXIT_SUCCESS);
}
if (portduino_config.lora_module == use_simradio) {
std::cout << "Running in simulated mode." << std::endl;
portduino_config.MaxNodes = 200; // Default to 200 nodes
// Set the random seed equal to TCPPort to have a different seed per instance
randomSeed(TCPPort);
return;
}
// If LoRa `Module: auto` (default in config.yaml), // If LoRa `Module: auto` (default in config.yaml),
// attempt to auto config based on Product Strings // attempt to auto config based on Product Strings
if (settingsMap[use_autoconf] == true) { if (portduino_config.lora_module == use_autoconf) {
char autoconf_product[96] = {0}; char autoconf_product[96] = {0};
// Try CH341 // Try CH341
try { try {
std::cout << "autoconf: Looking for CH341 device..." << std::endl; std::cout << "autoconf: Looking for CH341 device..." << std::endl;
ch341Hal = ch341Hal = new Ch341Hal(0, portduino_config.lora_usb_serial_num, portduino_config.lora_usb_vid,
new Ch341Hal(0, settingsStrings[lora_usb_serial_num], settingsMap[lora_usb_vid], settingsMap[lora_usb_pid]); portduino_config.lora_usb_pid);
ch341Hal->getProductString(autoconf_product, 95); ch341Hal->getProductString(autoconf_product, 95);
delete ch341Hal; delete ch341Hal;
std::cout << "autoconf: Found CH341 device " << autoconf_product << std::endl; std::cout << "autoconf: Found CH341 device " << autoconf_product << std::endl;
@@ -323,7 +295,7 @@ void portduinoSetup()
if (mac_start != nullptr) { if (mac_start != nullptr) {
std::cout << "autoconf: Found mac data " << mac_start << std::endl; std::cout << "autoconf: Found mac data " << mac_start << std::endl;
if (strlen(mac_start) == 12) if (strlen(mac_start) == 12)
settingsStrings[mac_address] = std::string(mac_start); portduino_config.mac_address = std::string(mac_start);
} }
if (devID_start != nullptr) { if (devID_start != nullptr) {
std::cout << "autoconf: Found deviceid data " << devID_start << std::endl; std::cout << "autoconf: Found deviceid data " << devID_start << std::endl;
@@ -354,7 +326,7 @@ void portduinoSetup()
std::cerr << "autoconf: Unable to find config for " << autoconf_product << std::endl; std::cerr << "autoconf: Unable to find config for " << autoconf_product << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (loadConfig((settingsStrings[available_directory] + product_config).c_str())) { if (loadConfig((portduino_config.available_directory + product_config).c_str())) {
std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl; std::cout << "autoconf: Using " << product_config << " as config file for " << autoconf_product << std::endl;
} else { } else {
std::cerr << "autoconf: Unable to use " << product_config << " as config file for " << autoconf_product std::cerr << "autoconf: Unable to use " << product_config << " as config file for " << autoconf_product
@@ -363,15 +335,16 @@ void portduinoSetup()
} }
} else { } else {
std::cerr << "autoconf: Could not locate any devices" << std::endl; std::cerr << "autoconf: Could not locate any devices" << std::endl;
exit(EXIT_FAILURE);
} }
} }
// if we're using a usermode driver, we need to initialize it here, to get a serial number back for mac address // if we're using a usermode driver, we need to initialize it here, to get a serial number back for mac address
uint8_t dmac[6] = {0}; uint8_t dmac[6] = {0};
if (settingsStrings[spidev] == "ch341") { if (portduino_config.lora_spi_dev == "ch341") {
try { try {
ch341Hal = ch341Hal = new Ch341Hal(0, portduino_config.lora_usb_serial_num, portduino_config.lora_usb_vid,
new Ch341Hal(0, settingsStrings[lora_usb_serial_num], settingsMap[lora_usb_vid], settingsMap[lora_usb_pid]); portduino_config.lora_usb_pid);
} catch (std::exception &e) { } catch (std::exception &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
std::cerr << "Could not initialize CH341 device!" << std::endl; std::cerr << "Could not initialize CH341 device!" << std::endl;
@@ -383,7 +356,7 @@ void portduinoSetup()
char product_string[96] = {0}; char product_string[96] = {0};
ch341Hal->getProductString(product_string, 95); ch341Hal->getProductString(product_string, 95);
std::cout << "CH341 Product " << product_string << std::endl; std::cout << "CH341 Product " << product_string << std::endl;
if (strlen(serial) == 8 && settingsStrings[mac_address].length() < 12) { if (strlen(serial) == 8 && portduino_config.mac_address.length() < 12) {
uint8_t hash[32] = {0}; uint8_t hash[32] = {0};
memcpy(hash, serial, 8); memcpy(hash, serial, 8);
crypto->hash(hash, 8); crypto->hash(hash, 8);
@@ -395,7 +368,7 @@ void portduinoSetup()
dmac[5] = hash[5]; dmac[5] = hash[5];
char macBuf[13] = {0}; char macBuf[13] = {0};
sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); sprintf(macBuf, "%02X%02X%02X%02X%02X%02X", dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]);
settingsStrings[mac_address] = macBuf; portduino_config.mac_address = macBuf;
} }
} }
@@ -409,100 +382,38 @@ void portduinoSetup()
// Rather important to set this, if not running simulated. // Rather important to set this, if not running simulated.
randomSeed(time(NULL)); randomSeed(time(NULL));
std::string defaultGpioChipName = gpioChipName + std::to_string(settingsMap[default_gpiochip]); std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip);
for (auto i : portduino_config.all_pins) {
for (configNames i : GPIO_lines) { if (i->enabled && i->pin > max_GPIO)
if (settingsMap.count(i) && settingsMap[i] > max_GPIO) max_GPIO = i->pin;
max_GPIO = settingsMap[i];
} }
gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need. gpioInit(max_GPIO + 1); // Done here so we can inform Portduino how many GPIOs we need.
// Need to bind all the configured GPIO pins so they're not simulated // Need to bind all the configured GPIO pins so they're not simulated
// TODO: If one of these fails, we should log and terminate // TODO: If one of these fails, we should log and terminate
if (settingsMap.count(userButtonPin) > 0 && settingsMap[userButtonPin] != RADIOLIB_NC) { for (auto i : portduino_config.all_pins) {
if (initGPIOPin(settingsMap[userButtonPin], defaultGpioChipName, settingsMap[userButtonPin]) != ERRNO_OK) { if (i->enabled)
settingsMap[userButtonPin] = RADIOLIB_NC; if (initGPIOPin(i->pin, gpioChipName + std::to_string(i->gpiochip), i->line) != ERRNO_OK) {
} printf("Error setting pin number %d. It may not exist, or may already be in use.\n", i->line);
} exit(EXIT_FAILURE);
if (settingsMap.count(tbUpPin) > 0 && settingsMap[tbUpPin] != RADIOLIB_NC) { }
if (initGPIOPin(settingsMap[tbUpPin], defaultGpioChipName, settingsMap[tbUpPin]) != ERRNO_OK) {
settingsMap[tbUpPin] = RADIOLIB_NC;
}
}
if (settingsMap.count(tbDownPin) > 0 && settingsMap[tbDownPin] != RADIOLIB_NC) {
if (initGPIOPin(settingsMap[tbDownPin], defaultGpioChipName, settingsMap[tbDownPin]) != ERRNO_OK) {
settingsMap[tbDownPin] = RADIOLIB_NC;
}
}
if (settingsMap.count(tbLeftPin) > 0 && settingsMap[tbLeftPin] != RADIOLIB_NC) {
if (initGPIOPin(settingsMap[tbLeftPin], defaultGpioChipName, settingsMap[tbLeftPin]) != ERRNO_OK) {
settingsMap[tbLeftPin] = RADIOLIB_NC;
}
}
if (settingsMap.count(tbRightPin) > 0 && settingsMap[tbRightPin] != RADIOLIB_NC) {
if (initGPIOPin(settingsMap[tbRightPin], defaultGpioChipName, settingsMap[tbRightPin]) != ERRNO_OK) {
settingsMap[tbRightPin] = RADIOLIB_NC;
}
}
if (settingsMap.count(tbPressPin) > 0 && settingsMap[tbPressPin] != RADIOLIB_NC) {
if (initGPIOPin(settingsMap[tbPressPin], defaultGpioChipName, settingsMap[tbPressPin]) != ERRNO_OK) {
settingsMap[tbPressPin] = RADIOLIB_NC;
}
}
if (settingsMap[displayPanel] != no_screen) {
if (settingsMap[displayCS] > 0)
initGPIOPin(settingsMap[displayCS], defaultGpioChipName, settingsMap[displayCS]);
if (settingsMap[displayDC] > 0)
initGPIOPin(settingsMap[displayDC], defaultGpioChipName, settingsMap[displayDC]);
if (settingsMap[displayBacklight] > 0)
initGPIOPin(settingsMap[displayBacklight], defaultGpioChipName, settingsMap[displayBacklight]);
if (settingsMap[displayReset] > 0)
initGPIOPin(settingsMap[displayReset], defaultGpioChipName, settingsMap[displayReset]);
}
if (settingsMap[touchscreenModule] != no_touchscreen) {
if (settingsMap[touchscreenCS] > 0)
initGPIOPin(settingsMap[touchscreenCS], defaultGpioChipName, settingsMap[touchscreenCS]);
if (settingsMap[touchscreenIRQ] > 0)
initGPIOPin(settingsMap[touchscreenIRQ], defaultGpioChipName, settingsMap[touchscreenIRQ]);
} }
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware // Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
if (settingsStrings[spidev] != "" && settingsStrings[spidev] != "ch341") { if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
const struct { SPI.begin(portduino_config.lora_spi_dev.c_str());
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) {
printf("Error setting pin number %d. It may not exist, or may already be in use.\n",
settingsMap[pinMap.line]);
exit(EXIT_FAILURE);
}
}
}
SPI.begin(settingsStrings[spidev].c_str());
} }
if (settingsStrings[traceFilename] != "") { if (portduino_config.traceFilename != "") {
try { try {
traceFile.open(settingsStrings[traceFilename], std::ios::out | std::ios::app); traceFile.open(portduino_config.traceFilename, std::ios::out | std::ios::app);
} catch (std::ofstream::failure &e) { } catch (std::ofstream::failure &e) {
std::cout << "*** traceFile Exception " << e.what() << std::endl; std::cout << "*** traceFile Exception " << e.what() << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
if (verboseEnabled && settingsMap[logoutputlevel] != level_trace) { if (verboseEnabled && portduino_config.logoutputlevel != level_trace) {
settingsMap[logoutputlevel] = level_debug; portduino_config.logoutputlevel = level_debug;
} }
return; return;
@@ -537,99 +448,78 @@ bool loadConfig(const char *configPath)
yamlConfig = YAML::LoadFile(configPath); yamlConfig = YAML::LoadFile(configPath);
if (yamlConfig["Logging"]) { if (yamlConfig["Logging"]) {
if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "trace") { if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "trace") {
settingsMap[logoutputlevel] = level_trace; portduino_config.logoutputlevel = level_trace;
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") { } else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "debug") {
settingsMap[logoutputlevel] = level_debug; portduino_config.logoutputlevel = level_debug;
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") { } else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "info") {
settingsMap[logoutputlevel] = level_info; portduino_config.logoutputlevel = level_info;
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") { } else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "warn") {
settingsMap[logoutputlevel] = level_warn; portduino_config.logoutputlevel = level_warn;
} else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") { } else if (yamlConfig["Logging"]["LogLevel"].as<std::string>("info") == "error") {
settingsMap[logoutputlevel] = level_error; portduino_config.logoutputlevel = level_error;
} }
settingsStrings[traceFilename] = yamlConfig["Logging"]["TraceFile"].as<std::string>(""); portduino_config.traceFilename = yamlConfig["Logging"]["TraceFile"].as<std::string>("");
if (yamlConfig["Logging"]["AsciiLogs"]) { if (yamlConfig["Logging"]["AsciiLogs"]) {
// Default is !isatty(1) but can be set explicitly in config.yaml // Default is !isatty(1) but can be set explicitly in config.yaml
settingsMap[ascii_logs] = yamlConfig["Logging"]["AsciiLogs"].as<bool>(); portduino_config.ascii_logs = yamlConfig["Logging"]["AsciiLogs"].as<bool>();
portduino_config.ascii_logs_explicit = true;
} }
} }
if (yamlConfig["Lora"]) { if (yamlConfig["Lora"]) {
const struct {
configNames cfgName;
std::string strName;
} loraModules[] = {{use_simradio, "sim"}, {use_autoconf, "auto"}, {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"]) { if (yamlConfig["Lora"]["Module"]) {
for (auto &loraModule : loraModules) { for (auto &loraModule : portduino_config.loraModules) {
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.strName) { if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.second) {
settingsMap[loraModule.cfgName] = true; portduino_config.lora_module = loraModule.first;
break; break;
} }
} }
} }
if (yamlConfig["Lora"]["SX126X_MAX_POWER"])
portduino_config.sx126x_max_power = yamlConfig["Lora"]["SX126X_MAX_POWER"].as<int>(22);
if (yamlConfig["Lora"]["SX128X_MAX_POWER"])
portduino_config.sx128x_max_power = yamlConfig["Lora"]["SX128X_MAX_POWER"].as<int>(13);
if (yamlConfig["Lora"]["LR1110_MAX_POWER"])
portduino_config.lr1110_max_power = yamlConfig["Lora"]["LR1110_MAX_POWER"].as<int>(22);
if (yamlConfig["Lora"]["LR1120_MAX_POWER"])
portduino_config.lr1120_max_power = yamlConfig["Lora"]["LR1120_MAX_POWER"].as<int>(13);
if (yamlConfig["Lora"]["RF95_MAX_POWER"])
portduino_config.rf95_max_power = yamlConfig["Lora"]["RF95_MAX_POWER"].as<int>(20);
settingsMap[sx126x_max_power] = yamlConfig["Lora"]["SX126X_MAX_POWER"].as<int>(22); if (portduino_config.lora_module != use_autoconf && portduino_config.lora_module != use_simradio &&
settingsMap[sx128x_max_power] = yamlConfig["Lora"]["SX128X_MAX_POWER"].as<int>(13); !portduino_config.force_simradio) {
settingsMap[lr1110_max_power] = yamlConfig["Lora"]["LR1110_MAX_POWER"].as<int>(22); portduino_config.dio2_as_rf_switch = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
settingsMap[lr1120_max_power] = yamlConfig["Lora"]["LR1120_MAX_POWER"].as<int>(13); portduino_config.dio3_tcxo_voltage = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000;
settingsMap[rf95_max_power] = yamlConfig["Lora"]["RF95_MAX_POWER"].as<int>(20); if (portduino_config.dio3_tcxo_voltage == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) {
portduino_config.dio3_tcxo_voltage = 1800; // default millivolts for "true"
}
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false); // backwards API compatibility and to globally set gpiochip once
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<float>(0) * 1000; portduino_config.lora_default_gpiochip = yamlConfig["Lora"]["gpiochip"].as<int>(0);
if (settingsMap[dio3_tcxo_voltage] == 0 && yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false)) { for (auto this_pin : portduino_config.all_pins) {
settingsMap[dio3_tcxo_voltage] = 1800; // default millivolts for "true" if (this_pin->config_section == "Lora") {
} readGPIOFromYaml(yamlConfig["Lora"][this_pin->config_name], *this_pin);
}
// 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()) {
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); portduino_config.spiSpeed = yamlConfig["Lora"]["spiSpeed"].as<int>(2000000);
settingsStrings[lora_usb_serial_num] = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>(""); portduino_config.lora_usb_serial_num = yamlConfig["Lora"]["USB_Serialnum"].as<std::string>("");
settingsMap[lora_usb_pid] = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512); portduino_config.lora_usb_pid = yamlConfig["Lora"]["USB_PID"].as<int>(0x5512);
settingsMap[lora_usb_vid] = yamlConfig["Lora"]["USB_VID"].as<int>(0x1A86); portduino_config.lora_usb_vid = yamlConfig["Lora"]["USB_VID"].as<int>(0x1A86);
settingsStrings[spidev] = yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0"); portduino_config.lora_spi_dev = yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
if (settingsStrings[spidev] != "ch341") { if (portduino_config.lora_spi_dev != "ch341") {
settingsStrings[spidev] = "/dev/" + settingsStrings[spidev]; portduino_config.lora_spi_dev = "/dev/" + portduino_config.lora_spi_dev;
if (settingsStrings[spidev].length() == 14) { if (portduino_config.lora_spi_dev.length() == 14) {
int x = settingsStrings[spidev].at(11) - '0'; int x = portduino_config.lora_spi_dev.at(11) - '0';
int y = settingsStrings[spidev].at(13) - '0'; int y = portduino_config.lora_spi_dev.at(13) - '0';
// Pretty sure this is always true // Pretty sure this is always true
if (x >= 0 && x < 10 && y >= 0 && y < 10) { if (x >= 0 && x < 10 && y >= 0 && y < 10) {
// I believe this bit of weirdness is specifically for the new GUI // I believe this bit of weirdness is specifically for the new GUI
settingsMap[spidev] = x + y << 4; portduino_config.lora_spi_dev_int = x + y << 4;
settingsMap[displayspidev] = settingsMap[spidev]; portduino_config.display_spi_dev_int = portduino_config.lora_spi_dev_int;
settingsMap[touchscreenspidev] = settingsMap[spidev]; portduino_config.touchscreen_spi_dev_int = portduino_config.lora_spi_dev_int;
} }
} }
} }
@@ -676,163 +566,152 @@ bool loadConfig(const char *configPath)
} }
} }
} }
if (yamlConfig["GPIO"]) { readGPIOFromYaml(yamlConfig["GPIO"]["User"], portduino_config.userButtonPin);
settingsMap[userButtonPin] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
}
if (yamlConfig["GPS"]) { if (yamlConfig["GPS"]) {
std::string serialPath = yamlConfig["GPS"]["SerialPath"].as<std::string>(""); std::string serialPath = yamlConfig["GPS"]["SerialPath"].as<std::string>("");
if (serialPath != "") { if (serialPath != "") {
Serial1.setPath(serialPath); Serial1.setPath(serialPath);
settingsMap[has_gps] = 1; portduino_config.has_gps = 1;
} }
} }
if (yamlConfig["I2C"]) { if (yamlConfig["I2C"]) {
settingsStrings[i2cdev] = yamlConfig["I2C"]["I2CDevice"].as<std::string>(""); portduino_config.i2cdev = yamlConfig["I2C"]["I2CDevice"].as<std::string>("");
} }
if (yamlConfig["Display"]) { if (yamlConfig["Display"]) {
if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789")
settingsMap[displayPanel] = st7789; for (auto &screen_name : portduino_config.screen_names) {
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735") if (yamlConfig["Display"]["Panel"].as<std::string>("") == screen_name.second)
settingsMap[displayPanel] = st7735; portduino_config.displayPanel = screen_name.first;
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S") }
settingsMap[displayPanel] = st7735s; portduino_config.displayHeight = yamlConfig["Display"]["Height"].as<int>(0);
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7796") portduino_config.displayWidth = yamlConfig["Display"]["Width"].as<int>(0);
settingsMap[displayPanel] = st7796;
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9341") readGPIOFromYaml(yamlConfig["Display"]["DC"], portduino_config.displayDC, -1);
settingsMap[displayPanel] = ili9341; readGPIOFromYaml(yamlConfig["Display"]["CS"], portduino_config.displayCS, -1);
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9342") readGPIOFromYaml(yamlConfig["Display"]["Backlight"], portduino_config.displayBacklight, -1);
settingsMap[displayPanel] = ili9342; readGPIOFromYaml(yamlConfig["Display"]["BacklightPWMChannel"], portduino_config.displayBacklightPWMChannel, -1);
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9486") readGPIOFromYaml(yamlConfig["Display"]["Reset"], portduino_config.displayReset, -1);
settingsMap[displayPanel] = ili9486;
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ILI9488") portduino_config.displayBacklightInvert = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
settingsMap[displayPanel] = ili9488; portduino_config.displayRGBOrder = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "HX8357D") portduino_config.displayOffsetX = yamlConfig["Display"]["OffsetX"].as<int>(0);
settingsMap[displayPanel] = hx8357d; portduino_config.displayOffsetY = yamlConfig["Display"]["OffsetY"].as<int>(0);
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "X11") portduino_config.displayRotate = yamlConfig["Display"]["Rotate"].as<bool>(false);
settingsMap[displayPanel] = x11; portduino_config.displayOffsetRotate = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "FB") portduino_config.displayInvert = yamlConfig["Display"]["Invert"].as<bool>(false);
settingsMap[displayPanel] = fb; portduino_config.displayBusFrequency = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1);
settingsMap[displayRGBOrder] = yamlConfig["Display"]["RGBOrder"].as<bool>(false);
settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1);
settingsMap[displayBacklightInvert] = yamlConfig["Display"]["BacklightInvert"].as<bool>(false);
settingsMap[displayBacklightPWMChannel] = yamlConfig["Display"]["BacklightPWMChannel"].as<int>(-1);
settingsMap[displayReset] = yamlConfig["Display"]["Reset"].as<int>(-1);
settingsMap[displayOffsetX] = yamlConfig["Display"]["OffsetX"].as<int>(0);
settingsMap[displayOffsetY] = yamlConfig["Display"]["OffsetY"].as<int>(0);
settingsMap[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
settingsMap[displayOffsetRotate] = yamlConfig["Display"]["OffsetRotate"].as<int>(1);
settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
settingsMap[displayBusFrequency] = yamlConfig["Display"]["BusFrequency"].as<int>(40000000);
if (yamlConfig["Display"]["spidev"]) { if (yamlConfig["Display"]["spidev"]) {
settingsStrings[displayspidev] = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1"); portduino_config.display_spi_dev = "/dev/" + yamlConfig["Display"]["spidev"].as<std::string>("spidev0.1");
if (settingsStrings[displayspidev].length() == 14) { if (portduino_config.display_spi_dev.length() == 14) {
int x = settingsStrings[displayspidev].at(11) - '0'; int x = portduino_config.display_spi_dev.at(11) - '0';
int y = settingsStrings[displayspidev].at(13) - '0'; int y = portduino_config.display_spi_dev.at(13) - '0';
if (x >= 0 && x < 10 && y >= 0 && y < 10) { if (x >= 0 && x < 10 && y >= 0 && y < 10) {
settingsMap[displayspidev] = x + y << 4; portduino_config.display_spi_dev_int = x + y << 4;
settingsMap[touchscreenspidev] = settingsMap[displayspidev]; portduino_config.touchscreen_spi_dev_int = portduino_config.display_spi_dev_int;
} }
} }
} }
} }
if (yamlConfig["Touchscreen"]) { if (yamlConfig["Touchscreen"]) {
if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046") if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "XPT2046")
settingsMap[touchscreenModule] = xpt2046; portduino_config.touchscreenModule = xpt2046;
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610") else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "STMPE610")
settingsMap[touchscreenModule] = stmpe610; portduino_config.touchscreenModule = stmpe610;
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911") else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "GT911")
settingsMap[touchscreenModule] = gt911; portduino_config.touchscreenModule = gt911;
else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06") else if (yamlConfig["Touchscreen"]["Module"].as<std::string>("") == "FT5x06")
settingsMap[touchscreenModule] = ft5x06; portduino_config.touchscreenModule = ft5x06;
settingsMap[touchscreenCS] = yamlConfig["Touchscreen"]["CS"].as<int>(-1);
settingsMap[touchscreenIRQ] = yamlConfig["Touchscreen"]["IRQ"].as<int>(-1); readGPIOFromYaml(yamlConfig["Touchscreen"]["CS"], portduino_config.touchscreenCS, -1);
settingsMap[touchscreenBusFrequency] = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000); readGPIOFromYaml(yamlConfig["Touchscreen"]["IRQ"], portduino_config.touchscreenIRQ, -1);
settingsMap[touchscreenRotate] = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
settingsMap[touchscreenI2CAddr] = yamlConfig["Touchscreen"]["I2CAddr"].as<int>(-1); portduino_config.touchscreenBusFrequency = yamlConfig["Touchscreen"]["BusFrequency"].as<int>(1000000);
portduino_config.touchscreenRotate = yamlConfig["Touchscreen"]["Rotate"].as<int>(-1);
portduino_config.touchscreenI2CAddr = yamlConfig["Touchscreen"]["I2CAddr"].as<int>(-1);
if (yamlConfig["Touchscreen"]["spidev"]) { if (yamlConfig["Touchscreen"]["spidev"]) {
settingsStrings[touchscreenspidev] = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>(""); portduino_config.touchscreen_spi_dev = "/dev/" + yamlConfig["Touchscreen"]["spidev"].as<std::string>("");
if (settingsStrings[touchscreenspidev].length() == 14) { if (portduino_config.touchscreen_spi_dev.length() == 14) {
int x = settingsStrings[touchscreenspidev].at(11) - '0'; int x = portduino_config.touchscreen_spi_dev.at(11) - '0';
int y = settingsStrings[touchscreenspidev].at(13) - '0'; int y = portduino_config.touchscreen_spi_dev.at(13) - '0';
if (x >= 0 && x < 10 && y >= 0 && y < 10) { if (x >= 0 && x < 10 && y >= 0 && y < 10) {
settingsMap[touchscreenspidev] = x + y << 4; portduino_config.touchscreen_spi_dev_int = x + y << 4;
} }
} }
} }
} }
if (yamlConfig["Input"]) { if (yamlConfig["Input"]) {
settingsStrings[keyboardDevice] = (yamlConfig["Input"]["KeyboardDevice"]).as<std::string>(""); portduino_config.keyboardDevice = (yamlConfig["Input"]["KeyboardDevice"]).as<std::string>("");
settingsStrings[pointerDevice] = (yamlConfig["Input"]["PointerDevice"]).as<std::string>(""); portduino_config.pointerDevice = (yamlConfig["Input"]["PointerDevice"]).as<std::string>("");
settingsMap[userButtonPin] = yamlConfig["Input"]["User"].as<int>(RADIOLIB_NC);
settingsMap[tbUpPin] = yamlConfig["Input"]["TrackballUp"].as<int>(RADIOLIB_NC); readGPIOFromYaml(yamlConfig["Input"]["User"], portduino_config.userButtonPin);
settingsMap[tbDownPin] = yamlConfig["Input"]["TrackballDown"].as<int>(RADIOLIB_NC); readGPIOFromYaml(yamlConfig["Input"]["TrackballUp"], portduino_config.tbUpPin);
settingsMap[tbLeftPin] = yamlConfig["Input"]["TrackballLeft"].as<int>(RADIOLIB_NC); readGPIOFromYaml(yamlConfig["Input"]["TrackballDown"], portduino_config.tbDownPin);
settingsMap[tbRightPin] = yamlConfig["Input"]["TrackballRight"].as<int>(RADIOLIB_NC); readGPIOFromYaml(yamlConfig["Input"]["TrackballLeft"], portduino_config.tbLeftPin);
settingsMap[tbPressPin] = yamlConfig["Input"]["TrackballPress"].as<int>(RADIOLIB_NC); readGPIOFromYaml(yamlConfig["Input"]["TrackballRight"], portduino_config.tbRightPin);
readGPIOFromYaml(yamlConfig["Input"]["TrackballPress"], portduino_config.tbPressPin);
if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "RISING") { if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "RISING") {
settingsMap[tbDirection] = 4; portduino_config.tbDirection = 4;
} else if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "FALLING") { } else if (yamlConfig["Input"]["TrackballDirection"].as<std::string>("RISING") == "FALLING") {
settingsMap[tbDirection] = 3; portduino_config.tbDirection = 3;
} }
} }
if (yamlConfig["Webserver"]) { if (yamlConfig["Webserver"]) {
settingsMap[webserverport] = (yamlConfig["Webserver"]["Port"]).as<int>(-1); portduino_config.webserverport = (yamlConfig["Webserver"]["Port"]).as<int>(-1);
settingsStrings[webserverrootpath] = portduino_config.webserver_root_path =
(yamlConfig["Webserver"]["RootPath"]).as<std::string>("/usr/share/meshtasticd/web"); (yamlConfig["Webserver"]["RootPath"]).as<std::string>("/usr/share/meshtasticd/web");
settingsStrings[websslkeypath] = portduino_config.webserver_ssl_key_path =
(yamlConfig["Webserver"]["SSLKey"]).as<std::string>("/etc/meshtasticd/ssl/private_key.pem"); (yamlConfig["Webserver"]["SSLKey"]).as<std::string>("/etc/meshtasticd/ssl/private_key.pem");
settingsStrings[websslcertpath] = portduino_config.webserver_ssl_cert_path =
(yamlConfig["Webserver"]["SSLCert"]).as<std::string>("/etc/meshtasticd/ssl/certificate.pem"); (yamlConfig["Webserver"]["SSLCert"]).as<std::string>("/etc/meshtasticd/ssl/certificate.pem");
} }
if (yamlConfig["HostMetrics"]) { if (yamlConfig["HostMetrics"]) {
settingsMap[hostMetrics_channel] = (yamlConfig["HostMetrics"]["Channel"]).as<int>(0); portduino_config.hostMetrics_channel = (yamlConfig["HostMetrics"]["Channel"]).as<int>(0);
settingsMap[hostMetrics_interval] = (yamlConfig["HostMetrics"]["ReportInterval"]).as<int>(0); portduino_config.hostMetrics_interval = (yamlConfig["HostMetrics"]["ReportInterval"]).as<int>(0);
settingsStrings[hostMetrics_user_command] = (yamlConfig["HostMetrics"]["UserStringCommand"]).as<std::string>(""); portduino_config.hostMetrics_user_command = (yamlConfig["HostMetrics"]["UserStringCommand"]).as<std::string>("");
} }
if (yamlConfig["Config"]) { if (yamlConfig["Config"]) {
if (yamlConfig["Config"]["DisplayMode"]) { if (yamlConfig["Config"]["DisplayMode"]) {
settingsMap[has_configDisplayMode] = true; portduino_config.has_configDisplayMode = true;
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") { if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR; portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR;
} else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "INVERTED") { } else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "INVERTED") {
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_INVERTED; portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_INVERTED;
} else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "COLOR") { } else if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "COLOR") {
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_COLOR; portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_COLOR;
} else { } else {
settingsMap[configDisplayMode] = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT; portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
} }
} }
} }
if (yamlConfig["General"]) { if (yamlConfig["General"]) {
settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as<int>(200); portduino_config.MaxNodes = (yamlConfig["General"]["MaxNodes"]).as<int>(200);
settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100); portduino_config.maxtophone = (yamlConfig["General"]["MaxMessageQueue"]).as<int>(100);
settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as<std::string>(""); portduino_config.config_directory = (yamlConfig["General"]["ConfigDirectory"]).as<std::string>("");
settingsStrings[available_directory] = portduino_config.available_directory =
(yamlConfig["General"]["AvailableDirectory"]).as<std::string>("/etc/meshtasticd/available.d/"); (yamlConfig["General"]["AvailableDirectory"]).as<std::string>("/etc/meshtasticd/available.d/");
if ((yamlConfig["General"]["MACAddress"]).as<std::string>("") != "" && if ((yamlConfig["General"]["MACAddress"]).as<std::string>("") != "" &&
(yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") { (yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl; std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
settingsStrings[mac_address] = (yamlConfig["General"]["MACAddress"]).as<std::string>(""); portduino_config.mac_address = (yamlConfig["General"]["MACAddress"]).as<std::string>("");
if ((yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") { if (portduino_config.mac_address != "") {
std::ifstream infile("/sys/class/net/" + (yamlConfig["General"]["MACAddressSource"]).as<std::string>("") + portduino_config.mac_address_explicit = true;
"/address"); } else if ((yamlConfig["General"]["MACAddressSource"]).as<std::string>("") != "") {
std::getline(infile, settingsStrings[mac_address]); portduino_config.mac_address_source = (yamlConfig["General"]["MACAddressSource"]).as<std::string>("");
std::ifstream infile("/sys/class/net/" + portduino_config.mac_address_source + "/address");
std::getline(infile, portduino_config.mac_address);
} }
// https://stackoverflow.com/a/20326454 // https://stackoverflow.com/a/20326454
settingsStrings[mac_address].erase( portduino_config.mac_address.erase(
std::remove(settingsStrings[mac_address].begin(), settingsStrings[mac_address].end(), ':'), std::remove(portduino_config.mac_address.begin(), portduino_config.mac_address.end(), ':'),
settingsStrings[mac_address].end()); portduino_config.mac_address.end());
} }
} catch (YAML::Exception &e) { } catch (YAML::Exception &e) {
std::cout << "*** Exception " << e.what() << std::endl; std::cout << "*** Exception " << e.what() << std::endl;
@@ -851,12 +730,12 @@ bool MAC_from_string(std::string mac_str, uint8_t *dmac)
{ {
mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end()); mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end());
if (mac_str.length() == 12) { if (mac_str.length() == 12) {
dmac[0] = std::stoi(settingsStrings[mac_address].substr(0, 2), nullptr, 16); dmac[0] = std::stoi(portduino_config.mac_address.substr(0, 2), nullptr, 16);
dmac[1] = std::stoi(settingsStrings[mac_address].substr(2, 2), nullptr, 16); dmac[1] = std::stoi(portduino_config.mac_address.substr(2, 2), nullptr, 16);
dmac[2] = std::stoi(settingsStrings[mac_address].substr(4, 2), nullptr, 16); dmac[2] = std::stoi(portduino_config.mac_address.substr(4, 2), nullptr, 16);
dmac[3] = std::stoi(settingsStrings[mac_address].substr(6, 2), nullptr, 16); dmac[3] = std::stoi(portduino_config.mac_address.substr(6, 2), nullptr, 16);
dmac[4] = std::stoi(settingsStrings[mac_address].substr(8, 2), nullptr, 16); dmac[4] = std::stoi(portduino_config.mac_address.substr(8, 2), nullptr, 16);
dmac[5] = std::stoi(settingsStrings[mac_address].substr(10, 2), nullptr, 16); dmac[5] = std::stoi(portduino_config.mac_address.substr(10, 2), nullptr, 16);
return true; return true;
} else { } else {
return false; return false;
@@ -875,4 +754,19 @@ std::string exec(const char *cmd)
result += buffer.data(); result += buffer.data();
} }
return result; return result;
}
void readGPIOFromYaml(YAML::Node sourceNode, pinMapping &destPin, int pinDefault)
{
if (sourceNode.IsMap()) {
destPin.enabled = true;
destPin.pin = sourceNode["pin"].as<int>(pinDefault);
destPin.line = sourceNode["line"].as<int>(destPin.pin);
destPin.gpiochip = sourceNode["gpiochip"].as<int>(portduino_config.lora_default_gpiochip);
} else if (sourceNode) { // backwards API compatibility
destPin.enabled = true;
destPin.pin = sourceNode.as<int>(pinDefault);
destPin.line = destPin.pin;
destPin.gpiochip = portduino_config.lora_default_gpiochip;
}
} }
+424 -94
View File
@@ -6,6 +6,7 @@
#include "LR11x0Interface.h" #include "LR11x0Interface.h"
#include "Module.h" #include "Module.h"
#include "platform/portduino/USBHal.h" #include "platform/portduino/USBHal.h"
#include "yaml-cpp/yaml.h"
// Product strings for auto-configuration // Product strings for auto-configuration
// {"PRODUCT_STRING", "CONFIG.YAML"} // {"PRODUCT_STRING", "CONFIG.YAML"}
@@ -19,36 +20,10 @@ inline const std::unordered_map<std::string, std::string> configProducts = {
{"RAK6421-13300-S1", "lora-RAK6421-13300-slot1.yaml"}, {"RAK6421-13300-S1", "lora-RAK6421-13300-slot1.yaml"},
{"RAK6421-13300-S2", "lora-RAK6421-13300-slot2.yaml"}}; {"RAK6421-13300-S2", "lora-RAK6421-13300-slot2.yaml"}};
enum configNames { enum screen_modules { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d };
default_gpiochip, enum touchscreen_modules { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
cs_pin, enum portduino_log_level { level_error, level_warn, level_info, level_debug, level_trace };
cs_line, enum lora_module_enum {
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,
sx126x_max_power,
sx128x_max_power,
lr1110_max_power,
lr1120_max_power,
rf95_max_power,
dio2_as_rf_switch,
dio3_tcxo_voltage,
use_simradio, use_simradio,
use_autoconf, use_autoconf,
use_rf95, use_rf95,
@@ -58,72 +33,18 @@ enum configNames {
use_lr1110, use_lr1110,
use_lr1120, use_lr1120,
use_lr1121, use_lr1121,
use_llcc68, use_llcc68
lora_usb_serial_num, };
lora_usb_pid,
lora_usb_vid, struct pinMapping {
userButtonPin, std::string config_section;
tbUpPin, std::string config_name;
tbDownPin, int pin = RADIOLIB_NC;
tbLeftPin, int gpiochip;
tbRightPin, int line;
tbPressPin, bool enabled = false;
tbDirection,
spidev,
spiSpeed,
i2cdev,
has_gps,
touchscreenModule,
touchscreenCS,
touchscreenIRQ,
touchscreenI2CAddr,
touchscreenBusFrequency,
touchscreenRotate,
touchscreenspidev,
displayspidev,
displayBusFrequency,
displayPanel,
displayWidth,
displayHeight,
displayCS,
displayDC,
displayRGBOrder,
displayBacklight,
displayBacklightPWMChannel,
displayBacklightInvert,
displayReset,
displayRotate,
displayOffsetRotate,
displayOffsetX,
displayOffsetY,
displayInvert,
keyboardDevice,
pointerDevice,
logoutputlevel,
traceFilename,
webserver,
webserverport,
webserverrootpath,
websslkeypath,
websslcertpath,
maxtophone,
maxnodes,
ascii_logs,
config_directory,
available_directory,
mac_address,
hostMetrics_interval,
hostMetrics_channel,
hostMetrics_user_command,
configDisplayMode,
has_configDisplayMode
}; };
enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d };
enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 };
enum { level_error, level_warn, level_info, level_debug, level_trace };
extern std::map<configNames, int> settingsMap;
extern std::map<configNames, std::string> settingsStrings;
extern std::ofstream traceFile; extern std::ofstream traceFile;
extern Ch341Hal *ch341Hal; extern Ch341Hal *ch341Hal;
int initGPIOPin(int pinNum, std::string gpioChipname, int line); int initGPIOPin(int pinNum, std::string gpioChipname, int line);
@@ -131,13 +52,422 @@ bool loadConfig(const char *configPath);
static bool ends_with(std::string_view str, std::string_view suffix); static bool ends_with(std::string_view str, std::string_view suffix);
void getMacAddr(uint8_t *dmac); void getMacAddr(uint8_t *dmac);
bool MAC_from_string(std::string mac_str, uint8_t *dmac); bool MAC_from_string(std::string mac_str, uint8_t *dmac);
void readGPIOFromYaml(YAML::Node sourceNode, pinMapping &destPin, int pinDefault = RADIOLIB_NC);
std::string exec(const char *cmd); std::string exec(const char *cmd);
extern struct portduino_config_struct { extern struct portduino_config_struct {
// Lora
std::map<lora_module_enum, std::string> loraModules = {
{use_simradio, "sim"}, {use_autoconf, "auto"}, {use_rf95, "RF95"}, {use_sx1262, "sx1262"}, {use_sx1268, "sx1268"},
{use_sx1280, "sx1280"}, {use_lr1110, "lr1110"}, {use_lr1120, "lr1120"}, {use_lr1121, "lr1121"}, {use_llcc68, "LLCC68"}};
std::map<screen_modules, std::string> screen_names = {{x11, "X11"}, {fb, "FB"}, {st7789, "ST7789"},
{st7735, "ST7735"}, {st7735s, "ST7735S"}, {st7796, "ST7796"},
{ili9341, "ILI9341"}, {ili9342, "ILI9342"}, {ili9486, "ILI9486"},
{ili9488, "ILI9488"}, {hx8357d, "HX8357D"}};
lora_module_enum lora_module;
bool has_rfswitch_table = false; bool has_rfswitch_table = false;
uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; uint32_t rfswitch_dio_pins[5] = {RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
Module::RfSwitchMode_t rfswitch_table[8]; Module::RfSwitchMode_t rfswitch_table[8];
bool force_simradio = false; bool force_simradio = false;
bool has_device_id = false; bool has_device_id = false;
uint8_t device_id[16] = {0}; uint8_t device_id[16] = {0};
std::string lora_spi_dev = "";
std::string lora_usb_serial_num = "";
int lora_spi_dev_int = 0;
int lora_default_gpiochip = 0;
int sx126x_max_power = 22;
int sx128x_max_power = 13;
int lr1110_max_power = 22;
int lr1120_max_power = 13;
int rf95_max_power = 20;
bool dio2_as_rf_switch = false;
int dio3_tcxo_voltage = 0;
int lora_usb_pid = 0x5512;
int lora_usb_vid = 0x1A86;
int spiSpeed = 2000000;
pinMapping lora_cs_pin = {"Lora", "CS"};
pinMapping lora_irq_pin = {"Lora", "IRQ"};
pinMapping lora_busy_pin = {"Lora", "Busy"};
pinMapping lora_reset_pin = {"Lora", "Reset"};
pinMapping lora_txen_pin = {"Lora", "TXen"};
pinMapping lora_rxen_pin = {"Lora", "RXen"};
pinMapping lora_sx126x_ant_sw_pin = {"Lora", "SX126X_ANT_SW"};
// GPS
bool has_gps = false;
// I2C
std::string i2cdev = "";
// Display
std::string display_spi_dev = "";
int display_spi_dev_int = 0;
int displayBusFrequency = 40000000;
screen_modules displayPanel = no_screen;
int displayWidth = 0;
int displayHeight = 0;
bool displayRGBOrder = false;
bool displayBacklightInvert = false;
bool displayRotate = false;
int displayOffsetRotate = 1;
bool displayInvert = false;
int displayOffsetX = 0;
int displayOffsetY = 0;
pinMapping displayDC = {"Display", "DC"};
pinMapping displayCS = {"Display", "CS"};
pinMapping displayBacklight = {"Display", "Backlight"};
pinMapping displayBacklightPWMChannel = {"Display", "BacklightPWMChannel"};
pinMapping displayReset = {"Display", "Reset"};
// Touchscreen
std::string touchscreen_spi_dev = "";
int touchscreen_spi_dev_int = 0;
touchscreen_modules touchscreenModule = no_touchscreen;
int touchscreenI2CAddr = -1;
int touchscreenBusFrequency = 1000000;
int touchscreenRotate = -1;
pinMapping touchscreenCS = {"Touchscreen", "CS"};
pinMapping touchscreenIRQ = {"Touchscreen", "IRQ"};
// Input
std::string keyboardDevice = "";
std::string pointerDevice = "";
int tbDirection;
pinMapping userButtonPin = {"Input", "User"};
pinMapping tbUpPin = {"Input", "TrackballUp"};
pinMapping tbDownPin = {"Input", "TrackballDown"};
pinMapping tbLeftPin = {"Input", "TrackballLwft"};
pinMapping tbRightPin = {"Input", "TrackballRight"};
pinMapping tbPressPin = {"Input", "TrackballPress"};
// Logging
portduino_log_level logoutputlevel = level_debug;
std::string traceFilename;
bool ascii_logs = !isatty(1);
bool ascii_logs_explicit = false;
// Webserver
std::string webserver_root_path = "";
std::string webserver_ssl_key_path = "/etc/meshtasticd/ssl/private_key.pem";
std::string webserver_ssl_cert_path = "/etc/meshtasticd/ssl/certificate.pem";
int webserverport = -1;
// HostMetrics
std::string hostMetrics_user_command = "";
int hostMetrics_interval = 0;
int hostMetrics_channel = 0;
// config
int configDisplayMode = 0;
bool has_configDisplayMode = false;
// General
std::string mac_address = "";
bool mac_address_explicit = false;
std::string mac_address_source = "";
std::string config_directory = "";
std::string available_directory = "/etc/meshtasticd/available.d/";
int maxtophone = 100;
int MaxNodes = 200;
pinMapping *all_pins[20] = {&lora_cs_pin,
&lora_irq_pin,
&lora_busy_pin,
&lora_reset_pin,
&lora_txen_pin,
&lora_rxen_pin,
&lora_sx126x_ant_sw_pin,
&displayDC,
&displayCS,
&displayBacklight,
&displayBacklightPWMChannel,
&displayReset,
&touchscreenCS,
&touchscreenIRQ,
&userButtonPin,
&tbUpPin,
&tbDownPin,
&tbLeftPin,
&tbRightPin,
&tbPressPin};
std::string emit_yaml()
{
YAML::Emitter out;
out << YAML::BeginMap;
// Lora
out << YAML::Key << "Lora" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "Module" << YAML::Value << loraModules[lora_module];
for (auto lora_pin : all_pins) {
if (lora_pin->config_section == "Lora" && lora_pin->enabled) {
out << YAML::Key << lora_pin->config_name << YAML::Value << YAML::BeginMap;
out << YAML::Key << "pin" << YAML::Value << lora_pin->pin;
out << YAML::Key << "line" << YAML::Value << lora_pin->line;
out << YAML::Key << "gpiochip" << YAML::Value << lora_pin->gpiochip;
out << YAML::EndMap; // User
}
}
if (sx126x_max_power != 22)
out << YAML::Key << "SX126X_MAX_POWER" << YAML::Value << sx126x_max_power;
if (sx128x_max_power != 13)
out << YAML::Key << "SX128X_MAX_POWER" << YAML::Value << sx128x_max_power;
if (lr1110_max_power != 22)
out << YAML::Key << "LR1110_MAX_POWER" << YAML::Value << lr1110_max_power;
if (lr1120_max_power != 13)
out << YAML::Key << "LR1120_MAX_POWER" << YAML::Value << lr1120_max_power;
if (rf95_max_power != 20)
out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power;
out << YAML::Key << "DIO2_AS_RF_SWITCH" << YAML::Value << dio2_as_rf_switch;
if (dio3_tcxo_voltage != 0)
out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << dio3_tcxo_voltage;
if (lora_usb_pid != 0x5512)
out << YAML::Key << "USB_PID" << YAML::Value << YAML::Hex << lora_usb_pid;
if (lora_usb_vid != 0x1A86)
out << YAML::Key << "USB_VID" << YAML::Value << YAML::Hex << lora_usb_vid;
if (lora_spi_dev != "")
out << YAML::Key << "spidev" << YAML::Value << lora_spi_dev;
if (lora_usb_serial_num != "")
out << YAML::Key << "USB_Serialnum" << YAML::Value << lora_usb_serial_num;
out << YAML::Key << "spiSpeed" << YAML::Value << spiSpeed;
if (rfswitch_dio_pins[0] != RADIOLIB_NC) {
out << YAML::Key << "rfswitch_table" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "pins";
out << YAML::Value << YAML::Flow << YAML::BeginSeq;
for (int i = 0; i < 5; i++) {
// set up the pin array first
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO5)
out << "DIO5";
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO6)
out << "DIO6";
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO7)
out << "DIO7";
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO8)
out << "DIO8";
if (rfswitch_dio_pins[i] == RADIOLIB_LR11X0_DIO10)
out << "DIO10";
}
out << YAML::EndSeq;
for (int i = 0; i < 7; i++) {
switch (i) {
case 0:
out << YAML::Key << "MODE_STBY";
break;
case 1:
out << YAML::Key << "MODE_RX";
break;
case 2:
out << YAML::Key << "MODE_TX";
break;
case 3:
out << YAML::Key << "MODE_TX_HP";
break;
case 4:
out << YAML::Key << "MODE_TX_HF";
break;
case 5:
out << YAML::Key << "MODE_GNSS";
break;
case 6:
out << YAML::Key << "MODE_WIFI";
break;
}
out << YAML::Value << YAML::Flow << YAML::BeginSeq;
for (int j = 0; j < 5; j++) {
if (rfswitch_table[i].values[j] == HIGH) {
out << "HIGH";
} else {
out << "LOW";
}
}
out << YAML::EndSeq;
}
out << YAML::EndMap; // rfswitch_table
}
out << YAML::EndMap; // Lora
if (i2cdev != "") {
out << YAML::Key << "I2C" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "I2CDevice" << YAML::Value << i2cdev;
out << YAML::EndMap; // I2C
}
// Display
if (displayPanel != no_screen) {
out << YAML::Key << "Display" << YAML::Value << YAML::BeginMap;
for (auto &screen_name : screen_names) {
if (displayPanel == screen_name.first)
out << YAML::Key << "Module" << YAML::Value << screen_name.second;
}
for (auto display_pin : all_pins) {
if (display_pin->config_section == "Display" && display_pin->enabled) {
out << YAML::Key << display_pin->config_name << YAML::Value << YAML::BeginMap;
out << YAML::Key << "pin" << YAML::Value << display_pin->pin;
out << YAML::Key << "line" << YAML::Value << display_pin->line;
out << YAML::Key << "gpiochip" << YAML::Value << display_pin->gpiochip;
out << YAML::EndMap;
}
}
out << YAML::Key << "spidev" << YAML::Value << display_spi_dev;
out << YAML::Key << "BusFrequency" << YAML::Value << displayBusFrequency;
if (displayWidth)
out << YAML::Key << "Width" << YAML::Value << displayWidth;
if (displayHeight)
out << YAML::Key << "Height" << YAML::Value << displayHeight;
if (displayRGBOrder)
out << YAML::Key << "RGBOrder" << YAML::Value << true;
if (displayBacklightInvert)
out << YAML::Key << "BacklightInvert" << YAML::Value << true;
if (displayRotate)
out << YAML::Key << "Rotate" << YAML::Value << true;
if (displayInvert)
out << YAML::Key << "Invert" << YAML::Value << true;
if (displayOffsetX)
out << YAML::Key << "OffsetX" << YAML::Value << displayOffsetX;
if (displayOffsetY)
out << YAML::Key << "OffsetY" << YAML::Value << displayOffsetY;
out << YAML::Key << "OffsetRotate" << YAML::Value << displayOffsetRotate;
out << YAML::EndMap; // Display
}
// Touchscreen
if (touchscreen_spi_dev != "") {
out << YAML::Key << "Touchscreen" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "spidev" << YAML::Value << touchscreen_spi_dev;
out << YAML::Key << "BusFrequency" << YAML::Value << touchscreenBusFrequency;
switch (touchscreenModule) {
case xpt2046:
out << YAML::Key << "Module" << YAML::Value << "XPT2046";
case stmpe610:
out << YAML::Key << "Module" << YAML::Value << "STMPE610";
case gt911:
out << YAML::Key << "Module" << YAML::Value << "GT911";
case ft5x06:
out << YAML::Key << "Module" << YAML::Value << "FT5x06";
}
for (auto touchscreen_pin : all_pins) {
if (touchscreen_pin->config_section == "Touchscreen" && touchscreen_pin->enabled) {
out << YAML::Key << touchscreen_pin->config_name << YAML::Value << YAML::BeginMap;
out << YAML::Key << "pin" << YAML::Value << touchscreen_pin->pin;
out << YAML::Key << "line" << YAML::Value << touchscreen_pin->line;
out << YAML::Key << "gpiochip" << YAML::Value << touchscreen_pin->gpiochip;
out << YAML::EndMap;
}
}
if (touchscreenRotate != -1)
out << YAML::Key << "Rotate" << YAML::Value << touchscreenRotate;
if (touchscreenI2CAddr != -1)
out << YAML::Key << "I2CAddr" << YAML::Value << touchscreenI2CAddr;
out << YAML::EndMap; // Touchscreen
}
// Input
out << YAML::Key << "Input" << YAML::Value << YAML::BeginMap;
if (keyboardDevice != "")
out << YAML::Key << "KeyboardDevice" << YAML::Value << keyboardDevice;
if (pointerDevice != "")
out << YAML::Key << "PointerDevice" << YAML::Value << pointerDevice;
for (auto input_pin : all_pins) {
if (input_pin->config_section == "Input" && input_pin->enabled) {
out << YAML::Key << input_pin->config_name << YAML::Value << YAML::BeginMap;
out << YAML::Key << "pin" << YAML::Value << input_pin->pin;
out << YAML::Key << "line" << YAML::Value << input_pin->line;
out << YAML::Key << "gpiochip" << YAML::Value << input_pin->gpiochip;
out << YAML::EndMap;
}
}
if (tbDirection == 3)
out << YAML::Key << "TrackballDirection" << YAML::Value << "FALLING";
out << YAML::EndMap; // Input
out << YAML::Key << "Logging" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "LogLevel" << YAML::Value;
switch (logoutputlevel) {
case level_error:
out << "error";
break;
case level_warn:
out << "warn";
break;
case level_info:
out << "info";
break;
case level_debug:
out << "debug";
break;
case level_trace:
out << "trace";
break;
}
if (traceFilename != "")
out << YAML::Key << "TraceFile" << YAML::Value << traceFilename;
if (ascii_logs_explicit) {
out << YAML::Key << "AsciiLogs" << YAML::Value << ascii_logs;
}
out << YAML::EndMap; // Logging
// Webserver
if (webserver_root_path != "") {
out << YAML::Key << "Webserver" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "RootPath" << YAML::Value << webserver_root_path;
out << YAML::Key << "SSLKey" << YAML::Value << webserver_ssl_key_path;
out << YAML::Key << "SSLCert" << YAML::Value << webserver_ssl_cert_path;
out << YAML::Key << "Port" << YAML::Value << webserverport;
out << YAML::EndMap; // Webserver
}
// HostMetrics
if (hostMetrics_user_command != "") {
out << YAML::Key << "HostMetrics" << YAML::Value << YAML::BeginMap;
out << YAML::Key << "UserStringCommand" << YAML::Value << hostMetrics_user_command;
out << YAML::Key << "ReportInterval" << YAML::Value << hostMetrics_interval;
out << YAML::Key << "Channel" << YAML::Value << hostMetrics_channel;
out << YAML::EndMap; // HostMetrics
}
// config
if (has_configDisplayMode) {
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
switch (configDisplayMode) {
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
}
out << YAML::EndMap; // Config
}
// General
out << YAML::Key << "General" << YAML::Value << YAML::BeginMap;
if (config_directory != "")
out << YAML::Key << "ConfigDirectory" << YAML::Value << config_directory;
if (mac_address_explicit)
out << YAML::Key << "MACAddress" << YAML::Value << mac_address;
if (mac_address_source != "")
out << YAML::Key << "MACAddressSource" << YAML::Value << mac_address_source;
if (available_directory != "")
out << YAML::Key << "AvailableDirectory" << YAML::Value << available_directory;
out << YAML::Key << "MaxMessageQueue" << YAML::Value << maxtophone;
out << YAML::Key << "MaxNodes" << YAML::Value << MaxNodes;
out << YAML::EndMap; // General
return out.c_str();
}
} portduino_config; } portduino_config;
+5 -5
View File
@@ -28,9 +28,9 @@
#endif #endif
#ifndef HAS_TRACKBALL #ifndef HAS_TRACKBALL
#define HAS_TRACKBALL 1 #define HAS_TRACKBALL 1
#define TB_DOWN (uint8_t) settingsMap[tbDownPin] #define TB_DOWN (uint8_t) portduino_config.tbDownPin.pin
#define TB_UP (uint8_t) settingsMap[tbUpPin] #define TB_UP (uint8_t) portduino_config.tbUpPin.pin
#define TB_LEFT (uint8_t) settingsMap[tbLeftPin] #define TB_LEFT (uint8_t) portduino_config.tbLeftPin.pin
#define TB_RIGHT (uint8_t) settingsMap[tbRightPin] #define TB_RIGHT (uint8_t) portduino_config.tbRightPin.pin
#define TB_PRESS (uint8_t) settingsMap[tbPressPin] #define TB_PRESS (uint8_t) portduino_config.tbPressPin.pin
#endif #endif
@@ -1,5 +1,5 @@
#define HAS_SCREEN 1 #define HAS_SCREEN 1
#define CANNED_MESSAGE_MODULE_ENABLE 1 #define CANNED_MESSAGE_MODULE_ENABLE 1
#define HAS_GPS 1 #define HAS_GPS 1
#define MAX_RX_TOPHONE settingsMap[maxtophone] #define MAX_RX_TOPHONE portduino_config.maxtophone
#define MAX_NUM_NODES settingsMap[maxnodes] #define MAX_NUM_NODES portduino_config.MaxNodes
+3 -3
View File
@@ -3,8 +3,8 @@
#endif #endif
#define CANNED_MESSAGE_MODULE_ENABLE 1 #define CANNED_MESSAGE_MODULE_ENABLE 1
#define HAS_GPS 1 #define HAS_GPS 1
#define MAX_RX_TOPHONE settingsMap[maxtophone] #define MAX_RX_TOPHONE portduino_config.maxtophone
#define MAX_NUM_NODES settingsMap[maxnodes] #define MAX_NUM_NODES portduino_config.MaxNodes
// RAK12002 RTC Module // RAK12002 RTC Module
#define RV3028_RTC (uint8_t)0b1010010 #define RV3028_RTC (uint8_t)0b1010010