Portduino work (#3049)

* Move to Portduino's getMacAddr()

* Add ST7735/S screen support

* Push Raspbian support into native target

* Remove latent pigpio references.

* CardKB defensive programming

* Adds configurable spidev

* Fixes to build on Fedora 40

* ENUMs are not #defines. Pull latest portduino

* Add more configuration options for SPI displays

* Add config.yaml option to set DIO3_TCXO_VOLTAGE

* change tft clear() to fillScreen()
Maintains compatability with ESPI driver.

* Adds TXen and RXen pins to portduino

* Add -c --config options to specify config file

* Fail when a specified config file is unavailable

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
Jonathan Bennett 2024-01-12 02:00:31 -06:00 committed by GitHub
parent 7e53a96ee5
commit 4a867c81c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 279 additions and 250 deletions

View File

@ -1,6 +1,6 @@
; The Portduino based sim environment on top of any host OS, all hardware will be simulated ; The Portduino based sim environment on top of any host OS, all hardware will be simulated
[portduino_base] [portduino_base]
platform = https://github.com/meshtastic/platform-native.git#8a66ef82cf38a4135d85cbb5043d0e8ebbb8ba17 platform = https://github.com/meshtastic/platform-native.git#04435d06e39916a6c019d511518d8e95c659dfbd
framework = arduino framework = arduino
build_src_filter = build_src_filter =
@ -29,3 +29,7 @@ build_flags =
-fPIC -fPIC
-Isrc/platform/portduino -Isrc/platform/portduino
-DRADIOLIB_EEPROM_UNSUPPORTED -DRADIOLIB_EEPROM_UNSUPPORTED
-DPORTDUINO_LINUX_HARDWARE
-lbluetooth
-lgpiod
-lyaml-cpp

View File

@ -14,6 +14,12 @@ Lora:
# IRQ: 17 # IRQ: 17
# Reset: 22 # Reset: 22
# Module: sx1262 # pinedio
# CS: 0
# IRQ: 10
# Busy: 11
# spidev: spidev0.1
# Module: RF95 # Adafruit RFM9x # Module: RF95 # Adafruit RFM9x
# Reset: 25 # Reset: 25
# CS: 7 # CS: 7
@ -31,10 +37,19 @@ Lora:
# Busy: 20 # Busy: 20
# Reset: 18 # Reset: 18
# DIO3_TCXO_VOLTAGE: true # the Waveshare Core1262 and others are known to need this setting
# TXen: x # TX and RX enable pins
# RXen: x
### Set gpio chip to use in /dev/. Defaults to 0. ### Set gpio chip to use in /dev/. Defaults to 0.
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4 ### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
# gpiochip: 4 # gpiochip: 4
### Specify the SPI device to use in /dev/. Defaults to spidev0.0
### Some devices, like the pinedio, may require spidev0.1 as a workaround.
# spidev: spidev0.0
### Define GPIO buttons here: ### Define GPIO buttons here:
GPIO: GPIO:
@ -58,6 +73,18 @@ Display:
# Height: 320 # Height: 320
# Reset: 27 # Reset: 27
# Rotate: true # Rotate: true
# Invert: true
### Waveshare 1.44inch LCD HAT
# Panel: ST7735S
# CS: 8 #Chip Select
# DC: 25 # Data/Command pin
# Backlight: 24
# Width: 128
# Height: 128
# Reset: 27
# OffsetX: 0
# OffsetY: 0
Touchscreen: Touchscreen:
# Module: XPT2046 # Module: XPT2046

View File

@ -38,7 +38,7 @@ class ButtonThread : public concurrency::OSThread
#ifdef BUTTON_PIN_TOUCH #ifdef BUTTON_PIN_TOUCH
OneButton userButtonTouch; OneButton userButtonTouch;
#endif #endif
#if defined(ARCH_RASPBERRY_PI) #if defined(ARCH_PORTDUINO)
OneButton userButton; OneButton userButton;
#endif #endif
static bool shutdown_on_long_stop; static bool shutdown_on_long_stop;
@ -49,8 +49,8 @@ class ButtonThread : public concurrency::OSThread
// callback returns the period for the next callback invocation (or 0 if we should no longer be called) // callback returns the period for the next callback invocation (or 0 if we should no longer be called)
ButtonThread() : OSThread("Button") ButtonThread() : OSThread("Button")
{ {
#if defined(ARCH_RASPBERRY_PI) || defined(BUTTON_PIN) #if defined(ARCH_PORTDUINO) || defined(BUTTON_PIN)
#if defined(ARCH_RASPBERRY_PI) #if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
userButton = OneButton(settingsMap[user], true, true); userButton = OneButton(settingsMap[user], true, true);
#elif defined(BUTTON_PIN) #elif defined(BUTTON_PIN)
@ -68,7 +68,7 @@ class ButtonThread : public concurrency::OSThread
userButton.attachMultiClick(userButtonMultiPressed); userButton.attachMultiClick(userButtonMultiPressed);
userButton.attachLongPressStart(userButtonPressedLongStart); userButton.attachLongPressStart(userButtonPressedLongStart);
userButton.attachLongPressStop(userButtonPressedLongStop); userButton.attachLongPressStop(userButtonPressedLongStop);
#if defined(ARCH_RASPBERRY_PI) #if defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
wakeOnIrq(settingsMap[user], FALLING); wakeOnIrq(settingsMap[user], FALLING);
#else #else
@ -105,7 +105,7 @@ class ButtonThread : public concurrency::OSThread
#if defined(BUTTON_PIN) #if defined(BUTTON_PIN)
userButton.tick(); userButton.tick();
canSleep &= userButton.isIdle(); canSleep &= userButton.isIdle();
#elif defined(ARCH_RASPBERRY_PI) #elif defined(ARCH_PORTDUINO)
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) { if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
userButton.tick(); userButton.tick();
canSleep &= userButton.isIdle(); canSleep &= userButton.isIdle();
@ -143,7 +143,7 @@ class ButtonThread : public concurrency::OSThread
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
#endif #endif
#if defined(ARCH_RASPBERRY_PI) #if defined(ARCH_PORTDUINO)
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) && if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) || (settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) { !moduleConfig.canned_message.enabled) {

View File

@ -100,9 +100,9 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); r += ::printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
} else } else
r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000); r += ::printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
auto thread = concurrency::OSThread::currentThread; auto thread = concurrency::OSThread::currentThread;
if (thread) { if (thread) {

View File

@ -2,7 +2,7 @@
#include "concurrency/LockGuard.h" #include "concurrency/LockGuard.h"
#include "configuration.h" #include "configuration.h"
#if defined(ARCH_RASPBERRY_PI) #if defined(ARCH_PORTDUINO)
#include "linux/LinuxHardwareI2C.h" #include "linux/LinuxHardwareI2C.h"
#endif #endif
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) #if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)

View File

@ -16,7 +16,7 @@
#define GPS_RESET_MODE HIGH #define GPS_RESET_MODE HIGH
#endif #endif
#if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_RASPBERRY_PI) #if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(aLinuxInputImpl)
HardwareSerial *GPS::_serial_gps = &Serial1; HardwareSerial *GPS::_serial_gps = &Serial1;
#else #else
HardwareSerial *GPS::_serial_gps = NULL; HardwareSerial *GPS::_serial_gps = NULL;
@ -924,7 +924,7 @@ GPS *GPS::createGps()
if (!_en_gpio) if (!_en_gpio)
_en_gpio = PIN_GPS_EN; _en_gpio = PIN_GPS_EN;
#endif #endif
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
if (!settingsMap[has_gps]) if (!settingsMap[has_gps])
return nullptr; return nullptr;
#endif #endif

View File

@ -43,7 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "sleep.h" #include "sleep.h"
#include "target_specific.h" #include "target_specific.h"
#if HAS_WIFI && !defined(ARCH_RASPBERRY_PI) #if HAS_WIFI && !defined(ARCH_PORTDUINO)
#include "mesh/wifi/WiFiAPClient.h" #include "mesh/wifi/WiFiAPClient.h"
#endif #endif
@ -52,7 +52,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "modules/esp32/StoreForwardModule.h" #include "modules/esp32/StoreForwardModule.h"
#endif #endif
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h" #include "platform/portduino/PortduinoGlue.h"
#endif #endif
@ -930,8 +930,8 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
#elif defined(USE_ST7567) #elif defined(USE_ST7567)
dispdev = new ST7567Wire(address.address, -1, -1, geometry, dispdev = new ST7567Wire(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);
#elif ARCH_RASPBERRY_PI #elif ARCH_PORTDUINO
if (settingsMap[displayPanel] == st7789) { if (settingsMap[displayPanel] != no_screen) {
LOG_DEBUG("Making TFTDisplay!\n"); LOG_DEBUG("Making TFTDisplay!\n");
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);
@ -976,7 +976,7 @@ void Screen::handleSetOn(bool on)
#ifdef T_WATCH_S3 #ifdef T_WATCH_S3
PMU->enablePowerOutput(XPOWERS_ALDO2); PMU->enablePowerOutput(XPOWERS_ALDO2);
#endif #endif
#if !ARCH_RASPBERRY_PI #if !ARCH_PORTDUINO
dispdev->displayOn(); dispdev->displayOn();
#endif #endif
dispdev->displayOn(); dispdev->displayOn();
@ -1060,7 +1060,7 @@ void Screen::setup()
uint8_t dmac[6]; uint8_t dmac[6];
getMacAddr(dmac); getMacAddr(dmac);
snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]); snprintf(ourId, sizeof(ourId), "%02x%02x", dmac[4], dmac[5]);
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
handleSetOn(false); // force clean init handleSetOn(false); // force clean init
#endif #endif
@ -1075,7 +1075,7 @@ void Screen::setup()
#endif #endif
serialSinceMsec = millis(); serialSinceMsec = millis();
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
if (settingsMap[touchscreenModule]) { if (settingsMap[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);
@ -1344,7 +1344,7 @@ void Screen::setFrames()
// call a method on debugInfoScreen object (for more details) // call a method on debugInfoScreen object (for more details)
normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline; normalFrames[numframes++] = &Screen::drawDebugInfoSettingsTrampoline;
#if HAS_WIFI && !defined(ARCH_RASPBERRY_PI) #if HAS_WIFI && !defined(ARCH_PORTDUINO)
if (isWifiAvailable()) { if (isWifiAvailable()) {
// call a method on debugInfoScreen object (for more details) // call a method on debugInfoScreen object (for more details)
normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline; normalFrames[numframes++] = &Screen::drawDebugInfoWiFiTrampoline;
@ -1588,7 +1588,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#endif #endif
} else { } else {
// TODO: Raspberry Pi supports more than just the one screen size // TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_RASPBERRY_PI) && \ #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS) !defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1); imgInfoL1);
@ -1615,7 +1615,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
// Jm // Jm
void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
#if HAS_WIFI && !defined(ARCH_RASPBERRY_PI) #if HAS_WIFI && !defined(ARCH_PORTDUINO)
const char *wifiName = config.network.wifi_ssid; const char *wifiName = config.network.wifi_ssid;
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);

View File

@ -1,6 +1,6 @@
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h" #include "platform/portduino/PortduinoGlue.h"
#endif #endif
@ -331,7 +331,7 @@ static LGFX *tft = nullptr;
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip #include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip
static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h static TFT_eSPI *tft = nullptr; // Invoke library, pins defined in User_Setup.h
#elif ARCH_RASPBERRY_PI #elif ARCH_PORTDUINO
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip #include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
class LGFX : public lgfx::LGFX_Device class LGFX : public lgfx::LGFX_Device
@ -344,8 +344,12 @@ class LGFX : public lgfx::LGFX_Device
public: public:
LGFX(void) LGFX(void)
{ {
if (settingsMap[displayPanel] == st7789)
_panel_instance = new lgfx::Panel_ST7789; _panel_instance = new lgfx::Panel_ST7789;
else if (settingsMap[displayPanel] == st7735)
_panel_instance = new lgfx::Panel_ST7735;
else if (settingsMap[displayPanel] == st7735s)
_panel_instance = new lgfx::Panel_ST7735S;
auto buscfg = _bus_instance.config(); auto buscfg = _bus_instance.config();
buscfg.spi_mode = 0; buscfg.spi_mode = 0;
@ -356,19 +360,14 @@ class LGFX : public lgfx::LGFX_Device
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("Height: %d, Width: %d \n", settingsMap[displayHeight], settingsMap[displayWidth]); LOG_DEBUG("Height: %d, Width: %d \n", settingsMap[displayHeight], settingsMap[displayWidth]);
cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable) cfg.pin_cs = settingsMap[displayCS]; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = settingsMap[displayReset];
cfg.panel_width = settingsMap[displayWidth]; // actual displayable width cfg.panel_width = settingsMap[displayWidth]; // actual displayable width
cfg.panel_height = settingsMap[displayHeight]; // actual displayable height cfg.panel_height = settingsMap[displayHeight]; // actual displayable height
cfg.offset_x = 0; // Panel offset amount in X direction cfg.offset_x = settingsMap[displayOffsetX]; // Panel offset amount in X direction
cfg.offset_y = 0; // Panel offset amount in Y direction cfg.offset_y = settingsMap[displayOffsetY]; // Panel offset amount in Y direction
cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored) cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout cfg.invert = settingsMap[displayInvert]; // Set to true if the light/darkness of the panel is reversed
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit = false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
_panel_instance->config(cfg); _panel_instance->config(cfg);
@ -399,7 +398,7 @@ class LGFX : public lgfx::LGFX_Device
static LGFX *tft = nullptr; static LGFX *tft = nullptr;
#endif #endif
#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_RASPBERRY_PI #if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || ARCH_PORTDUINO
#include "SPILock.h" #include "SPILock.h"
#include "TFTDisplay.h" #include "TFTDisplay.h"
#include <SPI.h> #include <SPI.h>
@ -407,7 +406,7 @@ static LGFX *tft = nullptr;
TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus) TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus)
{ {
LOG_DEBUG("TFTDisplay!\n"); LOG_DEBUG("TFTDisplay!\n");
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
if (settingsMap[displayRotate]) { if (settingsMap[displayRotate]) {
setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]); setGeometry(GEOMETRY_RAWMODE, settingsMap[configNames::displayHeight], settingsMap[configNames::displayWidth]);
} else { } else {
@ -460,7 +459,7 @@ void TFTDisplay::sendCommand(uint8_t com)
// handle display on/off directly // handle display on/off directly
switch (com) { switch (com) {
case DISPLAYON: { case DISPLAYON: {
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
display(true); display(true);
if (settingsMap[displayBacklight] > 0) if (settingsMap[displayBacklight] > 0)
digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON); digitalWrite(settingsMap[displayBacklight], TFT_BACKLIGHT_ON);
@ -492,7 +491,7 @@ void TFTDisplay::sendCommand(uint8_t com)
break; break;
} }
case DISPLAYOFF: { case DISPLAYOFF: {
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
tft->clear(); tft->clear();
if (settingsMap[displayBacklight] > 0) if (settingsMap[displayBacklight] > 0)
digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON); digitalWrite(settingsMap[displayBacklight], !TFT_BACKLIGHT_ON);

View File

@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF}; const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF}; const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_RASPBERRY_PI) && \ #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS) !defined(DISPLAY_FORCE_SMALL_FONTS)
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff}; const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f}; const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};

View File

@ -1,7 +1,6 @@
#if ARCH_RASPBERRY_PI
#include "LinuxInput.h"
#include "configuration.h" #include "configuration.h"
#if ARCH_PORTDUINO
#include "LinuxInput.h"
#include "platform/portduino/PortduinoGlue.h" #include "platform/portduino/PortduinoGlue.h"
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
#include "InputBroker.h" #include "InputBroker.h"
#include "concurrency/OSThread.h" #include "concurrency/OSThread.h"
#include <assert.h> #include <assert.h>

View File

@ -1,6 +1,7 @@
#if ARCH_RASPBERRY_PI #include "configuration.h"
#include "LinuxInputImpl.h" #if ARCH_PORTDUINO
#include "InputBroker.h" #include "InputBroker.h"
#include "LinuxInputImpl.h"
LinuxInputImpl *aLinuxInputImpl; LinuxInputImpl *aLinuxInputImpl;

View File

@ -1,4 +1,4 @@
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
#pragma once #pragma once
#include "LinuxInput.h" #include "LinuxInput.h"
#include "main.h" #include "main.h"

View File

@ -4,7 +4,7 @@
#include "configuration.h" #include "configuration.h"
#include "modules/ExternalNotificationModule.h" #include "modules/ExternalNotificationModule.h"
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h" #include "platform/portduino/PortduinoGlue.h"
#endif #endif
@ -17,7 +17,7 @@ TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTo
void TouchScreenImpl1::init() void TouchScreenImpl1::init()
{ {
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
if (settingsMap[touchscreenModule]) { if (settingsMap[touchscreenModule]) {
TouchScreenBase::init(true); TouchScreenBase::init(true);
inputBroker->registerSource(this); inputBroker->registerSource(this);

View File

@ -187,7 +187,7 @@ int32_t KbI2cBase::runOnce()
i2cBus->requestFrom((int)cardkb_found.address, 1); i2cBus->requestFrom((int)cardkb_found.address, 1);
while (i2cBus->available()) { if (i2cBus->available()) {
char c = i2cBus->read(); char c = i2cBus->read();
InputEvent e; InputEvent e;
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
@ -222,7 +222,11 @@ int32_t KbI2cBase::runOnce()
case 0x00: // nopress case 0x00: // nopress
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE; e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break; break;
default: // all other keys default: // all other keys
if (c > 127) { // bogus key value
e.inputEvent = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
break;
}
e.inputEvent = ANYKEY; e.inputEvent = ANYKEY;
e.kbchar = c; e.kbchar = c;
break; break;

View File

@ -66,7 +66,7 @@ NRF52Bluetooth *nrf52Bluetooth;
#include "platform/portduino/SimRadio.h" #include "platform/portduino/SimRadio.h"
#endif #endif
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
#include "linux/LinuxHardwareI2C.h" #include "linux/LinuxHardwareI2C.h"
#include "platform/portduino/PortduinoGlue.h" #include "platform/portduino/PortduinoGlue.h"
#include <fstream> #include <fstream>
@ -74,7 +74,7 @@ NRF52Bluetooth *nrf52Bluetooth;
#include <string> #include <string>
#endif #endif
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI) #if HAS_BUTTON || defined(ARCH_PORTDUINO)
#include "ButtonThread.h" #include "ButtonThread.h"
#endif #endif
#include "PowerFSMThread.h" #include "PowerFSMThread.h"
@ -141,32 +141,12 @@ std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySenso
Router *router = NULL; // Users of router don't care what sort of subclass implements that API Router *router = NULL; // Users of router don't care what sort of subclass implements that API
#ifdef ARCH_RASPBERRY_PI
void getPiMacAddr(uint8_t *dmac)
{
std::fstream macIdentity;
macIdentity.open("/sys/kernel/debug/bluetooth/hci0/identity", std::ios::in);
std::string macLine;
getline(macIdentity, macLine);
macIdentity.close();
dmac[0] = strtol(macLine.substr(0, 2).c_str(), NULL, 16);
dmac[1] = strtol(macLine.substr(3, 2).c_str(), NULL, 16);
dmac[2] = strtol(macLine.substr(6, 2).c_str(), NULL, 16);
dmac[3] = strtol(macLine.substr(9, 2).c_str(), NULL, 16);
dmac[4] = strtol(macLine.substr(12, 2).c_str(), NULL, 16);
dmac[5] = strtol(macLine.substr(15, 2).c_str(), NULL, 16);
}
#endif
const char *getDeviceName() const char *getDeviceName()
{ {
uint8_t dmac[6]; uint8_t dmac[6];
#ifdef ARCH_RASPBERRY_PI
getPiMacAddr(dmac);
#else
getMacAddr(dmac); getMacAddr(dmac);
#endif
// Meshtastic_ab3c or Shortname_abcd // Meshtastic_ab3c or Shortname_abcd
static char name[20]; static char name[20];
snprintf(name, sizeof(name), "%02x%02x", dmac[4], dmac[5]); snprintf(name, sizeof(name), "%02x%02x", dmac[4], dmac[5]);
@ -211,13 +191,13 @@ static int32_t ledBlinker()
uint32_t timeLastPowered = 0; uint32_t timeLastPowered = 0;
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI) #if HAS_BUTTON || defined(ARCH_PORTDUINO)
bool ButtonThread::shutdown_on_long_stop = false; bool ButtonThread::shutdown_on_long_stop = false;
#endif #endif
static Periodic *ledPeriodic; static Periodic *ledPeriodic;
static OSThread *powerFSMthread; static OSThread *powerFSMthread;
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI) #if HAS_BUTTON || defined(ARCH_PORTDUINO)
static OSThread *buttonThread; static OSThread *buttonThread;
uint32_t ButtonThread::longPressTime = 0; uint32_t ButtonThread::longPressTime = 0;
#endif #endif
@ -613,7 +593,7 @@ void setup()
} else } else
router = new ReliableRouter(); router = new ReliableRouter();
#if HAS_BUTTON || defined(ARCH_RASPBERRY_PI) #if HAS_BUTTON || defined(ARCH_PORTDUINO)
// Buttons. Moved here cause we need NodeDB to be initialized // Buttons. Moved here cause we need NodeDB to be initialized
buttonThread = new ButtonThread(); buttonThread = new ButtonThread();
#endif #endif
@ -664,12 +644,14 @@ void setup()
pinMode(LORA_CS, OUTPUT); pinMode(LORA_CS, OUTPUT);
digitalWrite(LORA_CS, HIGH); digitalWrite(LORA_CS, HIGH);
SPI1.begin(false); SPI1.begin(false);
#else // HW_SPI1_DEVICE #else // HW_SPI1_DEVICE
SPI.setSCK(LORA_SCK); SPI.setSCK(LORA_SCK);
SPI.setTX(LORA_MOSI); SPI.setTX(LORA_MOSI);
SPI.setRX(LORA_MISO); SPI.setRX(LORA_MISO);
SPI.begin(false); SPI.begin(false);
#endif // HW_SPI1_DEVICE #endif // HW_SPI1_DEVICE
#elif ARCH_PORTDUINO
SPI.begin(settingsStrings[spidev].c_str());
#elif !defined(ARCH_ESP32) // ARCH_RP2040 #elif !defined(ARCH_ESP32) // ARCH_RP2040
SPI.begin(); SPI.begin();
#else #else
@ -715,7 +697,7 @@ void setup()
// the current region name) // the current region name)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) #if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
screen->setup(); screen->setup();
#elif ARCH_RASPBERRY_PI #elif defined(ARCH_PORTDUINO)
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) { if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
screen->setup(); screen->setup();
} }
@ -732,7 +714,7 @@ void setup()
digitalWrite(SX126X_ANT_SW, 1); digitalWrite(SX126X_ANT_SW, 1);
#endif #endif
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
if (settingsMap[use_sx1262]) { if (settingsMap[use_sx1262]) {
if (!rIf) { if (!rIf) {
LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings);
@ -822,7 +804,7 @@ void setup()
} }
#endif #endif
#if defined(USE_SX1262) && !defined(ARCH_RASPBERRY_PI) #if defined(USE_SX1262) && !defined(ARCH_PORTDUINO)
if (!rIf) { if (!rIf) {
rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY); rIf = new SX1262Interface(RadioLibHAL, SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY);
if (!rIf->init()) { if (!rIf->init()) {

View File

@ -62,7 +62,6 @@ extern graphics::Screen *screen;
// Return a human readable string of the form "Meshtastic_ab13" // Return a human readable string of the form "Meshtastic_ab13"
const char *getDeviceName(); const char *getDeviceName();
void getPiMacAddr(uint8_t *dmac);
extern uint32_t timeLastPowered; extern uint32_t timeLastPowered;

View File

@ -27,7 +27,7 @@
#include <nvs_flash.h> #include <nvs_flash.h>
#endif #endif
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
#include "platform/portduino/PortduinoGlue.h" #include "platform/portduino/PortduinoGlue.h"
#endif #endif
@ -195,7 +195,7 @@ void NodeDB::installDefaultConfig()
config.bluetooth.fixed_pin = defaultBLEPin; config.bluetooth.fixed_pin = defaultBLEPin;
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) #if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
bool hasScreen = true; bool hasScreen = true;
#elif ARCH_RASPBERRY_PI #elif ARCH_PORTDUINO
bool hasScreen = false; bool hasScreen = false;
if (settingsMap[displayPanel]) if (settingsMap[displayPanel])
hasScreen = true; hasScreen = true;
@ -464,11 +464,8 @@ void NodeDB::init()
*/ */
void NodeDB::pickNewNodeNum() void NodeDB::pickNewNodeNum()
{ {
#ifdef ARCH_RASPBERRY_PI
getPiMacAddr(ourMacAddr); // Make sure ourMacAddr is set
#else
getMacAddr(ourMacAddr); // Make sure ourMacAddr is set getMacAddr(ourMacAddr); // Make sure ourMacAddr is set
#endif
// Pick an initial nodenum based on the macaddr // Pick an initial nodenum based on the macaddr
NodeNum nodeNum = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5]; NodeNum nodeNum = (ourMacAddr[2] << 24) | (ourMacAddr[3] << 16) | (ourMacAddr[4] << 8) | ourMacAddr[5];

View File

@ -4,6 +4,10 @@
#include "configuration.h" #include "configuration.h"
#include "error.h" #include "error.h"
#if ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
#define MAX_POWER 20 #define MAX_POWER 20
// if we use 20 we are limited to 1% duty cycle or hw might overheat. For continuous operation set a limit of 17 // if we use 20 we are limited to 1% duty cycle or hw might overheat. For continuous operation set a limit of 17
// In theory up to 27 dBm is possible, but the modules installed in most radios can cope with a max of 20. So BIG WARNING // In theory up to 27 dBm is possible, but the modules installed in most radios can cope with a max of 20. So BIG WARNING
@ -23,10 +27,18 @@ 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
if (settingsMap[txen] != RADIOLIB_NC) {
digitalWrite(settingsMap[txen], 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
if (settingsMap[rxen] != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen], txon ? 0 : 1);
}
#endif #endif
} }
@ -62,6 +74,16 @@ bool RF95Interface::init()
#ifdef RF95_RXEN #ifdef RF95_RXEN
pinMode(RF95_RXEN, OUTPUT); pinMode(RF95_RXEN, OUTPUT);
digitalWrite(RF95_RXEN, 1); digitalWrite(RF95_RXEN, 1);
#endif
#if ARCH_PORTDUINO
if (settingsMap[txen] != RADIOLIB_NC) {
pinMode(settingsMap[txen], OUTPUT);
digitalWrite(settingsMap[txen], 0);
}
if (settingsMap[rxen] != RADIOLIB_NC) {
pinMode(settingsMap[rxen], OUTPUT);
digitalWrite(settingsMap[rxen], 0);
}
#endif #endif
setTransmitEnable(false); setTransmitEnable(false);

View File

@ -2,7 +2,7 @@
#include "configuration.h" #include "configuration.h"
#include "error.h" #include "error.h"
#include "mesh/NodeDB.h" #include "mesh/NodeDB.h"
#ifdef ARCH_RASPBERRY_PI #ifdef ARCH_PORTDUINO
#include "PortduinoGlue.h" #include "PortduinoGlue.h"
#endif #endif
@ -30,18 +30,25 @@ template <typename T> bool SX126xInterface<T>::init()
digitalWrite(SX126X_POWER_EN, HIGH); digitalWrite(SX126X_POWER_EN, HIGH);
#endif #endif
#if ARCH_PORTDUINO
float tcxoVoltage = 0;
if (settingsMap[dio3_tcxo_voltage])
tcxoVoltage = 1.8;
// FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE // FIXME: correct logic to default to not using TCXO if no voltage is specified for SX126X_DIO3_TCXO_VOLTAGE
#if !defined(SX126X_DIO3_TCXO_VOLTAGE) #elif !defined(SX126X_DIO3_TCXO_VOLTAGE)
float tcxoVoltage = float tcxoVoltage =
0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per 0; // "TCXO reference voltage to be set on DIO3. Defaults to 1.6 V, set to 0 to skip." per
// https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.h#L471C26-L471C104 // https://github.com/jgromes/RadioLib/blob/690a050ebb46e6097c5d00c371e961c1caa3b52e/src/modules/SX126x/SX126x.h#L471C26-L471C104
// (DIO3 is free to be used as an IRQ) // (DIO3 is free to be used as an IRQ)
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage\n");
#else #else
float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE; float tcxoVoltage = SX126X_DIO3_TCXO_VOLTAGE;
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V\n", SX126X_DIO3_TCXO_VOLTAGE);
// (DIO3 is not free to be used as an IRQ) // (DIO3 is not free to be used as an IRQ)
#endif #endif
if (tcxoVoltage == 0)
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE not defined, not using DIO3 as TCXO reference voltage\n");
else
LOG_DEBUG("SX126X_DIO3_TCXO_VOLTAGE defined, using DIO3 as TCXO reference voltage at %f V\n", tcxoVoltage);
// FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option // FIXME: May want to set depending on a definition, currently all SX126x variant files use the DC-DC regulator option
bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC? bool useRegulatorLDO = false; // Seems to depend on the connection to pin 9/DCC_SW - if an inductor DCDC?
@ -77,7 +84,7 @@ template <typename T> bool SX126xInterface<T>::init()
#ifdef SX126X_DIO2_AS_RF_SWITCH #ifdef SX126X_DIO2_AS_RF_SWITCH
LOG_DEBUG("Setting DIO2 as RF switch\n"); LOG_DEBUG("Setting DIO2 as RF switch\n");
bool dio2AsRfSwitch = true; bool dio2AsRfSwitch = true;
#elif defined(ARCH_RASPBERRY_PI) #elif defined(ARCH_PORTDUINO)
bool dio2AsRfSwitch = false; bool dio2AsRfSwitch = false;
if (settingsMap[dio2_as_rf_switch]) { if (settingsMap[dio2_as_rf_switch]) {
LOG_DEBUG("Setting DIO2 as RF switch\n"); LOG_DEBUG("Setting DIO2 as RF switch\n");
@ -93,6 +100,12 @@ template <typename T> bool SX126xInterface<T>::init()
// If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has // If a pin isn't defined, we set it to RADIOLIB_NC, it is safe to always do external RF switching with RADIOLIB_NC as it has
// no effect // no effect
#if ARCH_PORTDUINO
if (res == RADIOLIB_ERR_NONE) {
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching\n", settingsMap[rxen], settingsMap[txen]);
lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]);
}
#else
#ifndef SX126X_RXEN #ifndef SX126X_RXEN
#define SX126X_RXEN RADIOLIB_NC #define SX126X_RXEN RADIOLIB_NC
LOG_DEBUG("SX126X_RXEN not defined, defaulting to RADIOLIB_NC\n"); LOG_DEBUG("SX126X_RXEN not defined, defaulting to RADIOLIB_NC\n");
@ -105,7 +118,7 @@ template <typename T> bool SX126xInterface<T>::init()
LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching\n", SX126X_RXEN, SX126X_TXEN); LOG_DEBUG("Using MCU pin %i as RXEN and pin %i as TXEN to control RF switching\n", SX126X_RXEN, SX126X_TXEN);
lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); lora.setRfSwitchPins(SX126X_RXEN, SX126X_TXEN);
} }
#endif
if (config.lora.sx126x_rx_boosted_gain) { if (config.lora.sx126x_rx_boosted_gain) {
uint16_t result = lora.setRxBoostedGainMode(true); uint16_t result = lora.setRxBoostedGainMode(true);
LOG_INFO("Set RX gain to boosted mode; result: %d\n", result); LOG_INFO("Set RX gain to boosted mode; result: %d\n", result);

View File

@ -3,6 +3,10 @@
#include "error.h" #include "error.h"
#include "mesh/NodeDB.h" #include "mesh/NodeDB.h"
#if ARCH_PORTDUINO
#include "PortduinoGlue.h"
#endif
// 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
#ifndef SX128X_MAX_POWER #ifndef SX128X_MAX_POWER
#define SX128X_MAX_POWER 13 #define SX128X_MAX_POWER 13
@ -31,6 +35,16 @@ template <typename T> bool SX128xInterface<T>::init()
digitalWrite(RF95_FAN_EN, 1); digitalWrite(RF95_FAN_EN, 1);
#endif #endif
#if ARCH_PORTDUINO
if (settingsMap[rxen] != RADIOLIB_NC) {
pinMode(settingsMap[rxen], OUTPUT);
digitalWrite(settingsMap[rxen], LOW); // Set low before becoming an output
}
if (settingsMap[txen] != RADIOLIB_NC) {
pinMode(settingsMap[txen], OUTPUT);
digitalWrite(settingsMap[txen], LOW); // Set low before becoming an output
}
#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
pinMode(SX128X_RXEN, OUTPUT); pinMode(SX128X_RXEN, OUTPUT);
digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output digitalWrite(SX128X_RXEN, LOW); // Set low before becoming an output
@ -38,6 +52,7 @@ template <typename T> bool SX128xInterface<T>::init()
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) #if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
pinMode(SX128X_TXEN, OUTPUT); pinMode(SX128X_TXEN, OUTPUT);
digitalWrite(SX128X_TXEN, LOW); digitalWrite(SX128X_TXEN, LOW);
#endif
#endif #endif
RadioLibInterface::init(); RadioLibInterface::init();
@ -75,6 +90,10 @@ template <typename T> bool SX128xInterface<T>::init()
if (res == RADIOLIB_ERR_NONE) { if (res == RADIOLIB_ERR_NONE) {
lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN); lora.setRfSwitchPins(SX128X_RXEN, SX128X_TXEN);
} }
#elif ARCH_PORTDUINO
if (res == RADIOLIB_ERR_NONE && settingsMap[rxen] != RADIOLIB_NC && settingsMap[txen] != RADIOLIB_NC) {
lora.setRfSwitchPins(settingsMap[rxen], settingsMap[txen]);
}
#endif #endif
if (res == RADIOLIB_ERR_NONE) if (res == RADIOLIB_ERR_NONE)
@ -148,14 +167,21 @@ template <typename T> void SX128xInterface<T>::setStandby()
} }
assert(err == RADIOLIB_ERR_NONE); assert(err == RADIOLIB_ERR_NONE);
#if ARCH_PORTDUINO
if (settingsMap[rxen] != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen], LOW);
}
if (settingsMap[txen] != RADIOLIB_NC) {
digitalWrite(settingsMap[txen], LOW);
}
#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
digitalWrite(SX128X_RXEN, LOW); digitalWrite(SX128X_RXEN, LOW);
#endif #endif
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) #if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
digitalWrite(SX128X_TXEN, LOW); digitalWrite(SX128X_TXEN, LOW);
#endif #endif
#endif
isReceiving = false; // If we were receiving, not any more isReceiving = false; // If we were receiving, not any more
activeReceiveStart = 0; activeReceiveStart = 0;
disableInterrupt(); disableInterrupt();
@ -176,11 +202,21 @@ 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 (settingsMap[txen] != RADIOLIB_NC) {
digitalWrite(settingsMap[txen], HIGH);
}
if (settingsMap[rxen] != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen], LOW);
}
#else
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on TX power / off RX power #if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on TX power / off RX power
digitalWrite(SX128X_TXEN, HIGH); digitalWrite(SX128X_TXEN, HIGH);
#endif #endif
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) #if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC)
digitalWrite(SX128X_RXEN, LOW); digitalWrite(SX128X_RXEN, LOW);
#endif
#endif #endif
RadioLibInterface::configHardwareForSend(); RadioLibInterface::configHardwareForSend();
@ -197,11 +233,21 @@ template <typename T> void SX128xInterface<T>::startReceive()
setStandby(); setStandby();
#if ARCH_PORTDUINO
if (settingsMap[rxen] != RADIOLIB_NC) {
digitalWrite(settingsMap[rxen], HIGH);
}
if (settingsMap[txen] != RADIOLIB_NC) {
digitalWrite(settingsMap[txen], LOW);
}
#else
#if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on RX power / off TX power #if defined(SX128X_RXEN) && (SX128X_RXEN != RADIOLIB_NC) // we have RXEN/TXEN control - turn on RX power / off TX power
digitalWrite(SX128X_RXEN, HIGH); digitalWrite(SX128X_RXEN, HIGH);
#endif #endif
#if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC) #if defined(SX128X_TXEN) && (SX128X_TXEN != RADIOLIB_NC)
digitalWrite(SX128X_TXEN, LOW); digitalWrite(SX128X_TXEN, LOW);
#endif
#endif #endif
// We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving // We use the PREAMBLE_DETECTED and HEADER_VALID IRQ flag to detect whether we are actively receiving

View File

@ -8,5 +8,6 @@ template <class T> constexpr const T &clamp(const T &v, const T &lo, const T &hi
#if (defined(ARCH_PORTDUINO) && !defined(STRNSTR)) #if (defined(ARCH_PORTDUINO) && !defined(STRNSTR))
#define STRNSTR #define STRNSTR
#include <string.h>
char *strnstr(const char *s, const char *find, size_t slen); char *strnstr(const char *s, const char *find, size_t slen);
#endif #endif

View File

@ -1,5 +1,5 @@
#include "configuration.h" #include "configuration.h"
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
#include "PortduinoGlue.h" #include "PortduinoGlue.h"
#endif #endif
#if HAS_SCREEN #if HAS_SCREEN

View File

@ -17,7 +17,7 @@
#include "modules/TextMessageModule.h" #include "modules/TextMessageModule.h"
#include "modules/TraceRouteModule.h" #include "modules/TraceRouteModule.h"
#include "modules/WaypointModule.h" #include "modules/WaypointModule.h"
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
#include "input/LinuxInputImpl.h" #include "input/LinuxInputImpl.h"
#endif #endif
#if HAS_TELEMETRY #if HAS_TELEMETRY
@ -50,7 +50,7 @@
void setupModules() void setupModules()
{ {
if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) {
#if HAS_BUTTON || ARCH_RASPBERRY_PI #if HAS_BUTTON || ARCH_PORTDUINO
inputBroker = new InputBroker(); inputBroker = new InputBroker();
#endif #endif
adminModule = new AdminModule(); adminModule = new AdminModule();
@ -67,7 +67,7 @@ void setupModules()
new RemoteHardwareModule(); new RemoteHardwareModule();
new ReplyModule(); new ReplyModule();
#if HAS_BUTTON || ARCH_RASPBERRY_PI #if HAS_BUTTON || ARCH_PORTDUINO
rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1(); rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1();
if (!rotaryEncoderInterruptImpl1->init()) { if (!rotaryEncoderInterruptImpl1->init()) {
delete rotaryEncoderInterruptImpl1; delete rotaryEncoderInterruptImpl1;
@ -85,7 +85,7 @@ void setupModules()
kbMatrixImpl->init(); kbMatrixImpl->init();
#endif // INPUTBROKER_MATRIX_TYPE #endif // INPUTBROKER_MATRIX_TYPE
#endif // HAS_BUTTON #endif // HAS_BUTTON
#if ARCH_RASPBERRY_PI #if ARCH_PORTDUINO
aLinuxInputImpl = new LinuxInputImpl(); aLinuxInputImpl = new LinuxInputImpl();
aLinuxInputImpl->init(); aLinuxInputImpl->init();
#endif #endif

View File

@ -8,10 +8,8 @@
#include <Utility.h> #include <Utility.h>
#include <assert.h> #include <assert.h>
#ifdef ARCH_RASPBERRY_PI
#include "PortduinoGlue.h" #include "PortduinoGlue.h"
#include "linux/gpio/LinuxGPIOPin.h" #include "linux/gpio/LinuxGPIOPin.h"
#include "pigpio.h"
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
#include <iostream> #include <iostream>
#include <map> #include <map>
@ -19,10 +17,7 @@
std::map<configNames, int> settingsMap; std::map<configNames, int> settingsMap;
std::map<configNames, std::string> settingsStrings; std::map<configNames, std::string> settingsStrings;
char *configPath = nullptr;
#else
#include <linux/gpio/LinuxGPIOPin.h>
#endif
// FIXME - move setBluetoothEnable into a HALPlatform class // FIXME - move setBluetoothEnable into a HALPlatform class
void setBluetoothEnable(bool on) void setBluetoothEnable(bool on)
@ -36,34 +31,7 @@ void cpuDeepSleep(uint32_t msecs)
} }
void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel");
#ifndef ARCH_RASPBERRY_PI
/** a simulated pin for busted IRQ hardware
* Porduino helper class to do this i2c based polling:
*/
class PolledIrqPin : public GPIOPin
{
public:
PolledIrqPin() : GPIOPin(LORA_DIO1, "loraIRQ") {}
/// Read the low level hardware for this pin
virtual PinStatus readPinHardware()
{
if (isrPinStatus < 0)
return LOW; // No interrupt handler attached, don't bother polling i2c right now
else {
extern RadioInterface *rIf; // FIXME, temporary hack until we know if we need to keep this
assert(rIf);
RadioLibInterface *rIf95 = static_cast<RadioLibInterface *>(rIf);
bool p = rIf95->isIRQPending();
log(SysGPIO, LogDebug, "PolledIrqPin::readPinHardware(%s, %d, %d)", getName(), getPinNum(), p);
return p ? HIGH : LOW;
}
}
};
static GPIOPin *loraIrq;
#endif
int TCPPort = 4403; int TCPPort = 4403;
static error_t parse_opt(int key, char *arg, struct argp_state *state) static error_t parse_opt(int key, char *arg, struct argp_state *state)
@ -73,7 +41,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
if (sscanf(arg, "%d", &TCPPort) < 1) if (sscanf(arg, "%d", &TCPPort) < 1)
return ARGP_ERR_UNKNOWN; return ARGP_ERR_UNKNOWN;
else else
printf("Using TCP port %d\n", TCPPort); printf("Using config file %d\n", TCPPort);
break;
case 'c':
configPath = arg;
break; break;
case ARGP_KEY_ARG: case ARGP_KEY_ARG:
return 0; return 0;
@ -85,7 +56,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
void portduinoCustomInit() void portduinoCustomInit()
{ {
static struct argp_option options[] = {{"port", 'p', "PORT", 0, "The TCP port to use."}, {0}}; static struct argp_option options[] = {{"port", 'p', "PORT", 0, "The TCP port to use."},
{"config", 'c', "CONFIG_PATH", 0, "Full path of the .yaml config file to use."},
{0}};
static void *childArguments; static void *childArguments;
static char doc[] = "Meshtastic native build."; static char doc[] = "Meshtastic native build.";
static char args_doc[] = "..."; static char args_doc[] = "...";
@ -101,14 +74,20 @@ void portduinoCustomInit()
void portduinoSetup() void portduinoSetup()
{ {
printf("Setting up Meshtastic on Portduino...\n"); printf("Setting up Meshtastic on Portduino...\n");
#ifdef ARCH_RASPBERRY_PI
gpioInit(); gpioInit();
std::string gpioChipName = "gpiochip"; std::string gpioChipName = "gpiochip";
YAML::Node yamlConfig; YAML::Node yamlConfig;
if (access("config.yaml", R_OK) == 0) { if (configPath != nullptr) {
try {
yamlConfig = YAML::LoadFile(configPath);
} catch (YAML::Exception e) {
std::cout << "Could not open " << configPath << " because of error: " << e.what() << std::endl;
exit(EXIT_FAILURE);
}
} else if (access("config.yaml", R_OK) == 0) {
try { try {
yamlConfig = YAML::LoadFile("config.yaml"); yamlConfig = YAML::LoadFile("config.yaml");
} catch (YAML::Exception e) { } catch (YAML::Exception e) {
@ -123,8 +102,24 @@ void portduinoSetup()
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else { } else {
std::cout << "No 'config.yaml' found, exiting." << std::endl; std::cout << "No 'config.yaml' found, running simulated." << std::endl;
exit(EXIT_FAILURE); // Set the random seed equal to TCPPort to have a different seed per instance
randomSeed(TCPPort);
/* Aren't all pins defaulted to simulated?
auto fakeBusy = new SimGPIOPin(SX126X_BUSY, "fakeBusy");
fakeBusy->writePin(LOW);
fakeBusy->setSilent(true);
gpioBind(fakeBusy);
auto cs = new SimGPIOPin(SX126X_CS, "fakeLoraCS");
cs->setSilent(true);
gpioBind(cs);
gpioBind(new SimGPIOPin(SX126X_RESET, "fakeLoraReset"));
gpioBind(new SimGPIOPin(LORA_DIO1, "fakeLoraIrq"));
*/
return;
} }
try { try {
@ -141,12 +136,17 @@ void portduinoSetup()
settingsMap[use_sx1280] = true; settingsMap[use_sx1280] = true;
} }
settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false); settingsMap[dio2_as_rf_switch] = yamlConfig["Lora"]["DIO2_AS_RF_SWITCH"].as<bool>(false);
settingsMap[dio3_tcxo_voltage] = yamlConfig["Lora"]["DIO3_TCXO_VOLTAGE"].as<bool>(false);
settingsMap[cs] = yamlConfig["Lora"]["CS"].as<int>(RADIOLIB_NC); settingsMap[cs] = yamlConfig["Lora"]["CS"].as<int>(RADIOLIB_NC);
settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as<int>(RADIOLIB_NC); settingsMap[irq] = yamlConfig["Lora"]["IRQ"].as<int>(RADIOLIB_NC);
settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC); settingsMap[busy] = yamlConfig["Lora"]["Busy"].as<int>(RADIOLIB_NC);
settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC); settingsMap[reset] = yamlConfig["Lora"]["Reset"].as<int>(RADIOLIB_NC);
settingsMap[txen] = yamlConfig["Lora"]["TXen"].as<int>(RADIOLIB_NC);
settingsMap[rxen] = yamlConfig["Lora"]["RXen"].as<int>(RADIOLIB_NC);
settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0); settingsMap[gpiochip] = yamlConfig["Lora"]["gpiochip"].as<int>(0);
gpioChipName += std::to_string(settingsMap[gpiochip]); gpioChipName += std::to_string(settingsMap[gpiochip]);
settingsStrings[spidev] = "/dev/" + yamlConfig["Lora"]["spidev"].as<std::string>("spidev0.0");
} }
if (yamlConfig["GPIO"]) { if (yamlConfig["GPIO"]) {
settingsMap[user] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC); settingsMap[user] = yamlConfig["GPIO"]["User"].as<int>(RADIOLIB_NC);
@ -162,13 +162,20 @@ void portduinoSetup()
if (yamlConfig["Display"]) { if (yamlConfig["Display"]) {
if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789") if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7789")
settingsMap[displayPanel] = st7789; settingsMap[displayPanel] = st7789;
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735")
settingsMap[displayPanel] = st7735;
else if (yamlConfig["Display"]["Panel"].as<std::string>("") == "ST7735S")
settingsMap[displayPanel] = st7735s;
settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0); settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as<int>(0);
settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0); settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as<int>(0);
settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1); settingsMap[displayDC] = yamlConfig["Display"]["DC"].as<int>(-1);
settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1); settingsMap[displayCS] = yamlConfig["Display"]["CS"].as<int>(-1);
settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1); settingsMap[displayBacklight] = yamlConfig["Display"]["Backlight"].as<int>(-1);
settingsMap[displayReset] = yamlConfig["Display"]["Reset"].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[displayRotate] = yamlConfig["Display"]["Rotate"].as<bool>(false);
settingsMap[displayInvert] = yamlConfig["Display"]["Invert"].as<bool>(false);
} }
settingsMap[touchscreenModule] = no_touchscreen; settingsMap[touchscreenModule] = no_touchscreen;
if (yamlConfig["Touchscreen"]) { if (yamlConfig["Touchscreen"]) {
@ -185,10 +192,6 @@ void portduinoSetup()
std::cout << "*** Exception " << e.what() << std::endl; std::cout << "*** Exception " << e.what() << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (access("/sys/kernel/debug/bluetooth/hci0/identity", R_OK) != 0) {
std::cout << "Cannot read Bluetooth MAC Address. Please run as root" << std::endl;
exit(EXIT_FAILURE);
}
// 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
if (settingsMap.count(cs) > 0 && settingsMap[cs] != RADIOLIB_NC) { if (settingsMap.count(cs) > 0 && settingsMap[cs] != RADIOLIB_NC) {
@ -216,6 +219,16 @@ void portduinoSetup()
settingsMap[user] = RADIOLIB_NC; settingsMap[user] = RADIOLIB_NC;
} }
} }
if (settingsMap.count(rxen) > 0 && settingsMap[rxen] != RADIOLIB_NC) {
if (initGPIOPin(settingsMap[rxen], gpioChipName) != ERRNO_OK) {
settingsMap[rxen] = RADIOLIB_NC;
}
}
if (settingsMap.count(txen) > 0 && settingsMap[txen] != RADIOLIB_NC) {
if (initGPIOPin(settingsMap[txen], gpioChipName) != ERRNO_OK) {
settingsMap[txen] = RADIOLIB_NC;
}
}
if (settingsMap[displayPanel] != no_screen) { if (settingsMap[displayPanel] != no_screen) {
if (settingsMap[displayCS] > 0) if (settingsMap[displayCS] > 0)
@ -235,55 +248,8 @@ void portduinoSetup()
} }
return; return;
#endif
#ifdef defined(PORTDUINO_LINUX_HARDWARE)
SPI.begin(); // We need to create SPI
bool usePineLora = !spiChip->isSimulated();
if (usePineLora) {
printf("Connecting to PineLora board...\n");
// FIXME: remove this hack once interrupts are confirmed to work on new pine64 board
// loraIrq = new PolledIrqPin();
loraIrq = new LinuxGPIOPin(LORA_DIO1, "ch341", "int", "loraIrq"); // or "err"?
loraIrq->setSilent();
gpioBind(loraIrq);
// BUSY hw was busted on current board - just use the simulated pin (which will read low)
auto busy = new LinuxGPIOPin(SX126X_BUSY, "ch341", "slct", "loraBusy");
busy->setSilent();
gpioBind(busy);
gpioBind(new LinuxGPIOPin(SX126X_RESET, "ch341", "ini", "loraReset"));
auto loraCs = new LinuxGPIOPin(SX126X_CS, "ch341", "cs0", "loraCs");
loraCs->setSilent();
gpioBind(loraCs);
} else
#endif
#ifndef ARCH_RASPBERRY_PI
{
// Set the random seed equal to TCPPort to have a different seed per instance
randomSeed(TCPPort);
auto fakeBusy = new SimGPIOPin(SX126X_BUSY, "fakeBusy");
fakeBusy->writePin(LOW);
fakeBusy->setSilent(true);
gpioBind(fakeBusy);
auto cs = new SimGPIOPin(SX126X_CS, "fakeLoraCS");
cs->setSilent(true);
gpioBind(cs);
gpioBind(new SimGPIOPin(SX126X_RESET, "fakeLoraReset"));
gpioBind(new SimGPIOPin(LORA_DIO1, "fakeLoraIrq"));
}
// gpioBind((new SimGPIOPin(LORA_RESET, "LORA_RESET")));
// gpioBind((new SimGPIOPin(LORA_CS, "LORA_CS"))->setSilent());
#endif
} }
#ifdef ARCH_RASPBERRY_PI
int initGPIOPin(int pinNum, std::string gpioChipName) int initGPIOPin(int pinNum, std::string gpioChipName)
{ {
std::string gpio_name = "GPIO" + std::to_string(pinNum); std::string gpio_name = "GPIO" + std::to_string(pinNum);
@ -299,4 +265,3 @@ int initGPIOPin(int pinNum, std::string gpioChipName)
return ERRNO_DISABLED; return ERRNO_DISABLED;
} }
} }
#endif

View File

@ -1,5 +1,4 @@
#pragma once #pragma once
#ifdef ARCH_RASPBERRY_PI
#include <map> #include <map>
enum configNames { enum configNames {
@ -8,11 +7,15 @@ enum configNames {
irq, irq,
busy, busy,
reset, reset,
txen,
rxen,
dio2_as_rf_switch, dio2_as_rf_switch,
dio3_tcxo_voltage,
use_rf95, use_rf95,
use_sx1280, use_sx1280,
user, user,
gpiochip, gpiochip,
spidev,
has_gps, has_gps,
touchscreenModule, touchscreenModule,
touchscreenCS, touchscreenCS,
@ -25,13 +28,14 @@ enum configNames {
displayBacklight, displayBacklight,
displayReset, displayReset,
displayRotate, displayRotate,
displayOffsetX,
displayOffsetY,
displayInvert,
keyboardDevice keyboardDevice
}; };
enum { no_screen, st7789 }; enum { no_screen, st7789, st7735, st7735s };
enum { no_touchscreen, xpt2046 }; enum { no_touchscreen, xpt2046 };
extern std::map<configNames, int> settingsMap; extern std::map<configNames, int> settingsMap;
extern std::map<configNames, std::string> settingsStrings; extern std::map<configNames, std::string> settingsStrings;
int initGPIOPin(int pinNum, std::string gpioChipname); int initGPIOPin(int pinNum, std::string gpioChipname);
#endif

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#define ARCH_PORTDUINO #define ARCH_PORTDUINO 1
// //
// set HW_VENDOR // set HW_VENDOR

View File

@ -3,7 +3,7 @@
#include "graphics/Screen.h" #include "graphics/Screen.h"
#include "main.h" #include "main.h"
#include "power.h" #include "power.h"
#if ARCH_RASPBERRY_PI #if defined(ARCH_PORTDUINO)
#include "api/WiFiServerAPI.h" #include "api/WiFiServerAPI.h"
#include "input/LinuxInputImpl.h" #include "input/LinuxInputImpl.h"
@ -19,7 +19,7 @@ void powerCommandsCheck()
NVIC_SystemReset(); NVIC_SystemReset();
#elif defined(ARCH_RP2040) #elif defined(ARCH_RP2040)
rp2040.reboot(); rp2040.reboot();
#elif defined(ARCH_RASPBERRY_PI) #elif defined(ARCH_PORTDUINO)
deInitApiServer(); deInitApiServer();
if (aLinuxInputImpl) if (aLinuxInputImpl)
aLinuxInputImpl->deInit(); aLinuxInputImpl->deInit();
@ -27,11 +27,6 @@ void powerCommandsCheck()
Wire.end(); Wire.end();
Serial1.end(); Serial1.end();
reboot(); reboot();
#elif defined(ARCH_PORTDUINO)
deInitApiServer();
SPI.end();
Wire.end();
reboot();
#else #else
rebootAtMsec = -1; rebootAtMsec = -1;
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied.\n"); LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied.\n");
@ -49,7 +44,7 @@ void powerCommandsCheck()
#if defined(ARCH_NRF52) || defined(ARCH_ESP32) #if defined(ARCH_NRF52) || defined(ARCH_ESP32)
playShutdownMelody(); playShutdownMelody();
power->shutdown(); power->shutdown();
#elif ARCH_RASPBERRY_PI #elif defined(ARCH_PORTDUINO)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
#else #else
LOG_WARN("FIXME implement shutdown for this platform"); LOG_WARN("FIXME implement shutdown for this platform");

View File

@ -3,6 +3,7 @@ extends = portduino_base
build_flags = ${portduino_base.build_flags} -O0 -I variants/portduino build_flags = ${portduino_base.build_flags} -O0 -I variants/portduino
board = cross_platform board = cross_platform
lib_deps = ${portduino_base.lib_deps} lib_deps = ${portduino_base.lib_deps}
lovyan03/LovyanGFX@^1.1.12
build_src_filter = ${portduino_base.build_src_filter} build_src_filter = ${portduino_base.build_src_filter}
; The Portduino based sim environment on top of a linux OS and touching linux hardware devices ; The Portduino based sim environment on top of a linux OS and touching linux hardware devices
@ -16,7 +17,7 @@ build_src_filter = ${portduino_base.build_src_filter}
; The Raspberry Pi actually has accessible SPI and GPIO, so we can support real hardware there. ; The Raspberry Pi actually has accessible SPI and GPIO, so we can support real hardware there.
[env:raspbian] [env:raspbian]
extends = portduino_base extends = portduino_base
build_flags = ${portduino_base.build_flags} -O0 -lgpiod -I variants/portduino -DARCH_RASPBERRY_PI -lpigpio -lyaml-cpp build_flags = ${portduino_base.build_flags} -O0 -lgpiod -I variants/portduino -DARCH_RASPBERRY_PI -lyaml-cpp
board = linux_arm board = linux_arm
lib_deps = ${portduino_base.lib_deps} lib_deps = ${portduino_base.lib_deps}
https://github.com/jp-bennett/LovyanGFX.git#jp-bennett-patch-1 ; lovyan03/LovyanGFX@^1.1.9 https://github.com/jp-bennett/LovyanGFX.git#jp-bennett-patch-1 ; lovyan03/LovyanGFX@^1.1.9

View File

@ -1,33 +1,3 @@
#if defined(ARCH_RASPBERRY_PI)
#define HAS_WIRE 1 #define HAS_WIRE 1
#define HAS_SCREEN 1 #define HAS_SCREEN 1
#define CANNED_MESSAGE_MODULE_ENABLE 1 #define CANNED_MESSAGE_MODULE_ENABLE 1
#else // Pine64 mode.
// Pine64 uses a common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if
// not found then probe for SX1262. Currently the RF95 code is disabled because I think the RF95 module won't need to ship.
// #define USE_RF95
#define USE_SX1262
// Fake SPI device selections
#define LORA_SCK 5
#define LORA_MISO 19
#define LORA_MOSI 27
#define LORA_CS RADIOLIB_NC // the ch341f spi controller does CS for us
#define LORA_DIO0 26 // a No connect on the SX1262 module
#define LORA_RESET 14
#define LORA_DIO1 33 // SX1262 IRQ, called DIO0 on pinelora schematic, pin 7 on ch341f "ack" - FIXME, enable hwints in linux
#define LORA_DIO2 32 // SX1262 BUSY, actually connected to "DIO5" on pinelora schematic, pin 8 on ch341f "slct"
#define LORA_DIO3 RADIOLIB_NC // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
#ifdef USE_SX1262
#define SX126X_CS 20 // CS0 on pinelora schematic, hooked to gpio D0 on ch341f
#define SX126X_DIO1 LORA_DIO1
#define SX126X_BUSY LORA_DIO2
#define SX126X_RESET LORA_RESET
#define SX126X_DIO2_AS_RF_SWITCH
#endif
#endif