mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-21 02:35:57 +10:00
Merge branch 'develop' into pioarduino
This commit is contained in:
@@ -75,7 +75,7 @@ bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkOTACapability(esp_app_desc_t *app_desc, uint8_t method)
|
||||
bool checkOTACapability(const esp_app_desc_t *app_desc, uint8_t method)
|
||||
{
|
||||
// Combined loader supports all (both) transports, BLE and WiFi
|
||||
if (strcmp(app_desc->project_name, combinedAppProjectName) == 0) {
|
||||
|
||||
@@ -16,7 +16,7 @@ void initialize();
|
||||
bool isUpdated();
|
||||
const esp_partition_t *getAppPartition();
|
||||
bool getAppDesc(const esp_partition_t *part, esp_app_desc_t *app_desc);
|
||||
bool checkOTACapability(esp_app_desc_t *app_desc, uint8_t method);
|
||||
bool checkOTACapability(const esp_app_desc_t *app_desc, uint8_t method);
|
||||
void recoverConfig(meshtastic_Config_NetworkConfig *network);
|
||||
void saveConfig(meshtastic_Config_NetworkConfig *network, meshtastic_OTAMode method, uint8_t *ota_hash);
|
||||
bool trySwitchToOTA();
|
||||
|
||||
@@ -33,9 +33,6 @@
|
||||
#ifndef HAS_RADIO
|
||||
#define HAS_RADIO 1
|
||||
#endif
|
||||
#ifndef HAS_RTC
|
||||
#define HAS_RTC 1
|
||||
#endif
|
||||
#ifndef HAS_CPU_SHUTDOWN
|
||||
#define HAS_CPU_SHUTDOWN 1
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
// Weak empty variant shutdown prep function.
|
||||
// May be redefined by variant files.
|
||||
void variant_shutdown() __attribute__((weak));
|
||||
void variant_shutdown() {}
|
||||
|
||||
#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
void setBluetoothEnable(bool enable)
|
||||
{
|
||||
@@ -250,6 +255,7 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
|
||||
#endif // #end ESP32S3_WAKE_TYPE
|
||||
#endif
|
||||
variant_shutdown();
|
||||
|
||||
#if SOC_PM_SUPPORT_RTC_PERIPH_PD
|
||||
// We want RTC peripherals to stay on
|
||||
|
||||
@@ -5,7 +5,7 @@ This directory tree is designed to solve two problems.
|
||||
- The ESP32 arduino/platformio project doesn't support the nice "if initVariant() is found, call that after init" behavior of the nrf52 builds (they use initVariant() internally).
|
||||
- Over the years a lot of 'board specific' init code has been added to init() in main.cpp. It would be great to have a general/clean mechanism to allow developers to specify board specific/unique code in a clean fashion without mucking in main.
|
||||
|
||||
So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define lateInitVariant() if your board needs it.
|
||||
So we are borrowing the initVariant() ideas here (by using weak gcc references). You can now define earlyInitVariant() and lateInitVariant() if your board needs them. earlyInitVariant() runs at the beginning of setup() directly after waitUntilPowerLevelSafe(); while lateInitVariant() runs after the LoRa radio is initialized.
|
||||
|
||||
If you'd like a board specific variant to be run, add the variant.cpp file to an appropriately named
|
||||
subdirectory and check for \_VARIANT_boardname in the cpp file (so that your code is only built for your board).
|
||||
|
||||
@@ -36,6 +36,13 @@ bool AsyncUDP::writeTo(const uint8_t *data, size_t len, IPAddress ip, uint16_t p
|
||||
return udp.endPacket();
|
||||
}
|
||||
|
||||
void AsyncUDP::close()
|
||||
{
|
||||
udp.stop();
|
||||
localPort = 0;
|
||||
_onPacket = nullptr;
|
||||
}
|
||||
|
||||
// AsyncUDPPacket
|
||||
AsyncUDPPacket::AsyncUDPPacket(EthernetUDP &source) : _udp(source), _remoteIP(source.remoteIP()), _remotePort(source.remotePort())
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ class AsyncUDP : public Print, private concurrency::OSThread
|
||||
|
||||
bool listenMulticast(IPAddress multicastIP, uint16_t port, uint8_t ttl = 64);
|
||||
bool writeTo(const uint8_t *data, size_t len, IPAddress ip, uint16_t port);
|
||||
void close();
|
||||
|
||||
size_t write(uint8_t b) override;
|
||||
size_t write(const uint8_t *data, size_t len) override;
|
||||
@@ -37,7 +38,7 @@ class AsyncUDP : public Print, private concurrency::OSThread
|
||||
class AsyncUDPPacket
|
||||
{
|
||||
public:
|
||||
AsyncUDPPacket(EthernetUDP &source);
|
||||
explicit AsyncUDPPacket(EthernetUDP &source);
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t length();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file BLEDfu.cpp
|
||||
@file BLEDfuSecure.cpp
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
@@ -1,6 +1,6 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file BLEDfu.h
|
||||
@file BLEDfuSecure.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
@@ -32,6 +32,7 @@ static uint8_t toRadioBytes[meshtastic_ToRadio_size];
|
||||
static uint8_t lastToRadio[MAX_TO_FROM_RADIO_SIZE];
|
||||
|
||||
static uint16_t connectionHandle;
|
||||
static bool passkeyShowing;
|
||||
|
||||
class BluetoothPhoneAPI : public PhoneAPI
|
||||
{
|
||||
@@ -86,6 +87,16 @@ void onDisconnect(uint16_t conn_handle, uint8_t reason)
|
||||
// Notify UI (or any other interested firmware components)
|
||||
meshtastic::BluetoothStatus newStatus(meshtastic::BluetoothStatus::ConnectionState::DISCONNECTED);
|
||||
bluetoothStatus->updateStatus(&newStatus);
|
||||
|
||||
#if HAS_SCREEN
|
||||
// If a pairing prompt is active, make sure we dismiss it on disconnect/cancel/failure paths.
|
||||
if (passkeyShowing) {
|
||||
passkeyShowing = false;
|
||||
if (screen) {
|
||||
screen->endAlert();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void onCccd(uint16_t conn_hdl, BLECharacteristic *chr, uint16_t cccd_value)
|
||||
{
|
||||
@@ -119,7 +130,7 @@ void startAdv(void)
|
||||
Bluefruit.Advertising.addService(meshBleService);
|
||||
/* Start Advertising
|
||||
* - Enable auto advertising if disconnected
|
||||
* - Interval: fast mode = 20 ms, slow mode = 152.5 ms
|
||||
* - Interval: fast mode = 20 ms, slow mode = 417,5 ms
|
||||
* - Timeout for fast mode is 30 seconds
|
||||
* - Start(timeout) with timeout = 0 will advertise forever (until connected)
|
||||
*
|
||||
@@ -127,7 +138,7 @@ void startAdv(void)
|
||||
* https://developer.apple.com/library/content/qa/qa1931/_index.html
|
||||
*/
|
||||
Bluefruit.Advertising.restartOnDisconnect(true);
|
||||
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
|
||||
Bluefruit.Advertising.setInterval(32, 668); // in unit of 0.625 ms
|
||||
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
||||
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds. FIXME, we should stop advertising after X
|
||||
}
|
||||
@@ -243,10 +254,8 @@ int NRF52Bluetooth::getRssi()
|
||||
|
||||
// Valid BLE TX power levels as per nRF52840 Product Specification are: "-20 to +8 dBm TX power, configurable in 4 dB steps".
|
||||
// See https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html
|
||||
#define VALID_BLE_TX_POWER(x) \
|
||||
((x) == -20 || (x) == -16 || (x) == -12 || \
|
||||
(x) == -8 || (x) == -4 || (x) == 0 || \
|
||||
(x) == 4 || (x) == 8)
|
||||
#define VALID_BLE_TX_POWER(x) \
|
||||
((x) == -20 || (x) == -16 || (x) == -12 || (x) == -8 || (x) == -4 || (x) == 0 || (x) == 4 || (x) == 8)
|
||||
|
||||
void NRF52Bluetooth::setup()
|
||||
{
|
||||
@@ -283,6 +292,29 @@ void NRF52Bluetooth::setup()
|
||||
// Set the connect/disconnect callback handlers
|
||||
Bluefruit.Periph.setConnectCallback(onConnect);
|
||||
Bluefruit.Periph.setDisconnectCallback(onDisconnect);
|
||||
|
||||
// Do not change Slave Latency to value other than 0 !!!
|
||||
// There is probably a bug in SoftDevice + certain Apple iOS versions being
|
||||
// brain damaged causing connectivity problems.
|
||||
|
||||
// On one side it seems SoftDevice is using SlaveLatency value even
|
||||
// if connection parameter negotation failed and phone sees it as connectivity errors.
|
||||
|
||||
// On the other hand Apple can randomly refuse any parameter negotiation and shutdown connection
|
||||
// even if you meet Apple Developer Guidelines for BLE devices. Because f* you, that's why.
|
||||
|
||||
// While this API call sets preferred connection parameters (PPCP) - many phones ignore it (yeah) and it seems SoftDevice
|
||||
// will try to renegotiate connection parameters based on those values after phone connection.
|
||||
// So those are relatively safe values so Apple braindead firmware won't get angry and at least we may try
|
||||
// to negotiate some longer connection interval to save battery.
|
||||
|
||||
// See https://github.com/meshtastic/firmware/pull/8858 for measurements. We are dealing with microamp savings anyway so not
|
||||
// worth dying on a hill here.
|
||||
|
||||
Bluefruit.Periph.setConnSlaveLatency(0);
|
||||
// 1.25 ms units - so min, max is 15, 100 ms range.
|
||||
Bluefruit.Periph.setConnInterval(12, 80);
|
||||
|
||||
#ifndef BLE_DFU_SECURE
|
||||
bledfu.setPermission(SECMODE_ENC_WITH_MITM, SECMODE_ENC_WITH_MITM);
|
||||
bledfu.begin(); // Install the DFU helper
|
||||
@@ -311,7 +343,7 @@ void NRF52Bluetooth::setup()
|
||||
void NRF52Bluetooth::resumeAdvertising()
|
||||
{
|
||||
Bluefruit.Advertising.restartOnDisconnect(true);
|
||||
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
|
||||
Bluefruit.Advertising.setInterval(32, 668); // in unit of 0.625 ms
|
||||
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
|
||||
Bluefruit.Advertising.start(0);
|
||||
}
|
||||
@@ -379,6 +411,8 @@ bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passke
|
||||
});
|
||||
}
|
||||
#endif
|
||||
passkeyShowing = true;
|
||||
|
||||
if (match_request) {
|
||||
uint32_t start_time = millis();
|
||||
while (millis() < start_time + 30000) {
|
||||
@@ -430,6 +464,7 @@ void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_statu
|
||||
}
|
||||
|
||||
// Todo: migrate this display code back into Screen class, and observe bluetoothStatus
|
||||
passkeyShowing = false;
|
||||
if (screen) {
|
||||
screen->endAlert();
|
||||
}
|
||||
@@ -443,4 +478,4 @@ void NRF52Bluetooth::sendLog(const uint8_t *logMessage, size_t length)
|
||||
logRadio.indicate(logMessage, (uint16_t)length);
|
||||
else
|
||||
logRadio.notify(logMessage, (uint16_t)length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,25 @@
|
||||
//
|
||||
// defaults for NRF52 architecture
|
||||
//
|
||||
|
||||
/*
|
||||
* Internal Reference is +/-0.6V, with an adjustable gain of 1/6, 1/5, 1/4,
|
||||
* 1/3, 1/2 or 1, meaning 3.6, 3.0, 2.4, 1.8, 1.2 or 0.6V for the ADC levels.
|
||||
*
|
||||
* External Reference is VDD/4, with an adjustable gain of 1, 2 or 4, meaning
|
||||
* VDD/4, VDD/2 or VDD for the ADC levels.
|
||||
*
|
||||
* Default settings are internal reference with 1/6 gain (GND..3.6V ADC range)
|
||||
* Some variants overwrite it.
|
||||
*/
|
||||
#ifndef AREF_VOLTAGE
|
||||
#define AREF_VOLTAGE 3.6
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_SENSE_RESOLUTION_BITS
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 10
|
||||
#endif
|
||||
|
||||
#ifndef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 1
|
||||
#endif
|
||||
@@ -139,7 +158,7 @@
|
||||
#endif
|
||||
|
||||
#ifdef PIN_LED1
|
||||
#define LED_PIN PIN_LED1 // LED1 on nrf52840-DK
|
||||
#define LED_POWER PIN_LED1 // LED1 on nrf52840-DK
|
||||
#endif
|
||||
|
||||
#ifdef PIN_BUTTON1
|
||||
|
||||
+121
-101
@@ -9,12 +9,12 @@
|
||||
#define NRFX_WDT_ENABLED 1
|
||||
#define NRFX_WDT0_ENABLED 1
|
||||
#define NRFX_WDT_CONFIG_NO_IRQ 1
|
||||
#include <nrfx_wdt.c>
|
||||
#include <nrfx_wdt.h>
|
||||
|
||||
#include "nrfx_power.h"
|
||||
#include <assert.h>
|
||||
#include <ble_gap.h>
|
||||
#include <memory.h>
|
||||
#include <nrfx_wdt.c>
|
||||
#include <nrfx_wdt.h>
|
||||
#include <stdio.h>
|
||||
// #include <Adafruit_USBD_Device.h>
|
||||
#include "NodeDB.h"
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "main.h"
|
||||
#include "meshUtils.h"
|
||||
#include "power.h"
|
||||
#include <power/PowerHAL.h>
|
||||
|
||||
#include <hal/nrf_lpcomp.h>
|
||||
|
||||
@@ -30,7 +31,22 @@
|
||||
#include "BQ25713.h"
|
||||
#endif
|
||||
|
||||
// Weak empty variant initialization function.
|
||||
// WARNING! THRESHOLD + HYSTERESIS should be less than regulated VDD voltage - which depends on board
|
||||
// and is 3.0 or 3.3V. Also VDD likes to read values like 2.9999 so make sure you account for that
|
||||
// otherwise board will not boot at all. Before you modify this part - please triple read NRF52840 power design
|
||||
// section in datasheet and you understand how REG0 and REG1 regulators work together.
|
||||
#ifndef SAFE_VDD_VOLTAGE_THRESHOLD
|
||||
#define SAFE_VDD_VOLTAGE_THRESHOLD 2.7
|
||||
#endif
|
||||
|
||||
// hysteresis value
|
||||
#ifndef SAFE_VDD_VOLTAGE_THRESHOLD_HYST
|
||||
#define SAFE_VDD_VOLTAGE_THRESHOLD_HYST 0.2
|
||||
#endif
|
||||
|
||||
uint16_t getVDDVoltage();
|
||||
|
||||
// Weak empty variant shutdown prep function.
|
||||
// May be redefined by variant files.
|
||||
void variant_shutdown() __attribute__((weak));
|
||||
void variant_shutdown() {}
|
||||
@@ -38,12 +54,95 @@ void variant_shutdown() {}
|
||||
static nrfx_wdt_t nrfx_wdt = NRFX_WDT_INSTANCE(0);
|
||||
static nrfx_wdt_channel_id nrfx_wdt_channel_id_nrf52_main;
|
||||
|
||||
// This is a public global so that the debugger can set it to false automatically from our gdbinit
|
||||
// @phaseloop comment: most part of codebase, including filesystem flash driver depend on softdevice
|
||||
// methods so disabling it may actually crash thing. Proceed with caution.
|
||||
|
||||
bool useSoftDevice = true; // Set to false for easier debugging
|
||||
|
||||
static inline void debugger_break(void)
|
||||
{
|
||||
__asm volatile("bkpt #0x01\n\t"
|
||||
"mov pc, lr\n\t");
|
||||
}
|
||||
|
||||
// PowerHAL NRF52 specific function implementations
|
||||
bool powerHAL_isVBUSConnected()
|
||||
{
|
||||
return NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk;
|
||||
}
|
||||
|
||||
bool powerHAL_isPowerLevelSafe()
|
||||
{
|
||||
|
||||
static bool powerLevelSafe = true;
|
||||
|
||||
uint16_t threshold = SAFE_VDD_VOLTAGE_THRESHOLD * 1000; // convert V to mV
|
||||
uint16_t hysteresis = SAFE_VDD_VOLTAGE_THRESHOLD_HYST * 1000;
|
||||
|
||||
if (powerLevelSafe) {
|
||||
if (getVDDVoltage() < threshold) {
|
||||
powerLevelSafe = false;
|
||||
}
|
||||
} else {
|
||||
// power level is only safe again when it raises above threshold + hysteresis
|
||||
if (getVDDVoltage() >= (threshold + hysteresis)) {
|
||||
powerLevelSafe = true;
|
||||
}
|
||||
}
|
||||
|
||||
return powerLevelSafe;
|
||||
}
|
||||
|
||||
void powerHAL_platformInit()
|
||||
{
|
||||
|
||||
// Enable POF power failure comparator. It will prevent writing to NVMC flash when supply voltage is too low.
|
||||
// Set to some low value as last resort - powerHAL_isPowerLevelSafe uses different method and should manage proper node
|
||||
// behaviour on its own.
|
||||
|
||||
// POFWARN is pretty useless for node power management because it triggers only once and clearing this event will not
|
||||
// re-trigger it again until voltage rises to safe level and drops again. So we will use SAADC routed to VDD to read safely
|
||||
// voltage.
|
||||
|
||||
// @phaseloop: I disable POFCON for now because it seems to be unreliable or buggy. Even when set at 2.0V it
|
||||
// triggers below 2.8V and corrupts data when pairing bluetooth - because it prevents filesystem writes and
|
||||
// adafruit BLE library triggers lfs_assert which reboots node and formats filesystem.
|
||||
// I did experiments with bench power supply and no matter what is set to POFCON, it always triggers right below
|
||||
// 2.8V. I compared raw registry values with datasheet.
|
||||
|
||||
NRF_POWER->POFCON =
|
||||
((POWER_POFCON_THRESHOLD_V22 << POWER_POFCON_THRESHOLD_Pos) | (POWER_POFCON_POF_Enabled << POWER_POFCON_POF_Pos));
|
||||
|
||||
// remember to always match VBAT_AR_INTERNAL with AREF_VALUE in variant definition file
|
||||
#ifdef VBAT_AR_INTERNAL
|
||||
analogReference(VBAT_AR_INTERNAL);
|
||||
#else
|
||||
analogReference(AR_INTERNAL); // 3.6V
|
||||
#endif
|
||||
}
|
||||
|
||||
// get VDD voltage (in millivolts)
|
||||
uint16_t getVDDVoltage()
|
||||
{
|
||||
// we use the same values as regular battery read so there is no conflict on SAADC
|
||||
analogReadResolution(BATTERY_SENSE_RESOLUTION_BITS);
|
||||
|
||||
// VDD range on NRF52840 is 1.8-3.3V so we need to remap analog reference to 3.6V
|
||||
// let's hope battery reading runs in same task and we don't have race condition
|
||||
analogReference(AR_INTERNAL);
|
||||
|
||||
uint16_t vddADCRead = analogReadVDD();
|
||||
float voltage = ((1000 * 3.6) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * vddADCRead;
|
||||
|
||||
// restore default battery reading reference
|
||||
#ifdef VBAT_AR_INTERNAL
|
||||
analogReference(VBAT_AR_INTERNAL);
|
||||
#endif
|
||||
|
||||
return voltage;
|
||||
}
|
||||
|
||||
bool loopCanSleep()
|
||||
{
|
||||
// turn off sleep only while connected via USB
|
||||
@@ -72,22 +171,6 @@ void getMacAddr(uint8_t *dmac)
|
||||
dmac[0] = src[5] | 0xc0; // MSB high two bits get set elsewhere in the bluetooth stack
|
||||
}
|
||||
|
||||
static void initBrownout()
|
||||
{
|
||||
auto vccthresh = POWER_POFCON_THRESHOLD_V24;
|
||||
|
||||
auto err_code = sd_power_pof_enable(POWER_POFCON_POF_Enabled);
|
||||
assert(err_code == NRF_SUCCESS);
|
||||
|
||||
err_code = sd_power_pof_threshold_set(vccthresh);
|
||||
assert(err_code == NRF_SUCCESS);
|
||||
|
||||
// We don't bother with setting up brownout if soft device is disabled - because during production we always use softdevice
|
||||
}
|
||||
|
||||
// This is a public global so that the debugger can set it to false automatically from our gdbinit
|
||||
bool useSoftDevice = true; // Set to false for easier debugging
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||
void setBluetoothEnable(bool enable)
|
||||
{
|
||||
@@ -106,7 +189,6 @@ void setBluetoothEnable(bool enable)
|
||||
if (!initialized) {
|
||||
nrf52Bluetooth = new NRF52Bluetooth();
|
||||
nrf52Bluetooth->startDisabled();
|
||||
initBrownout();
|
||||
initialized = true;
|
||||
}
|
||||
return;
|
||||
@@ -120,9 +202,6 @@ void setBluetoothEnable(bool enable)
|
||||
LOG_DEBUG("Init NRF52 Bluetooth");
|
||||
nrf52Bluetooth = new NRF52Bluetooth();
|
||||
nrf52Bluetooth->setup();
|
||||
|
||||
// We delay brownout init until after BLE because BLE starts soft device
|
||||
initBrownout();
|
||||
}
|
||||
// Already setup, apparently
|
||||
else
|
||||
@@ -192,9 +271,24 @@ extern "C" void lfs_assert(const char *reason)
|
||||
delay(500); // Give the serial port a bit of time to output that last message.
|
||||
// Try setting GPREGRET with the SoftDevice first. If that fails (perhaps because the SD hasn't been initialize yet) then set
|
||||
// NRF_POWER->GPREGRET directly.
|
||||
if (!(sd_power_gpregret_clr(0, 0xFF) == NRF_SUCCESS && sd_power_gpregret_set(0, NRF52_MAGIC_LFS_IS_CORRUPT) == NRF_SUCCESS)) {
|
||||
NRF_POWER->GPREGRET = NRF52_MAGIC_LFS_IS_CORRUPT;
|
||||
|
||||
// TODO: this will/can crash CPU if bluetooth stack is not compiled in or bluetooth is not initialized
|
||||
// (regardless if enabled or disabled) - as there is no live SoftDevice stack
|
||||
// implement "safe" functions detecting softdevice stack state and using proper method to set registers
|
||||
|
||||
// do not set GPREGRET if POFWARN is triggered because it means lfs_assert reports flash undervoltage protection
|
||||
// and not data corruption. Reboot is fine as boot procedure will wait until power level is safe again
|
||||
|
||||
if (!NRF_POWER->EVENTS_POFWARN) {
|
||||
if (!(sd_power_gpregret_clr(0, 0xFF) == NRF_SUCCESS &&
|
||||
sd_power_gpregret_set(0, NRF52_MAGIC_LFS_IS_CORRUPT) == NRF_SUCCESS)) {
|
||||
NRF_POWER->GPREGRET = NRF52_MAGIC_LFS_IS_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: this should not be done when SoftDevice is enabled as device will not boot back on soft reset
|
||||
// as some data is retained in RAM which will prevent re-enabling bluetooth stack
|
||||
// Google what Nordic has to say about NVIC_* + SoftDevice
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
@@ -336,15 +430,6 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
Serial1.end();
|
||||
#endif
|
||||
|
||||
#ifdef TTGO_T_ECHO
|
||||
// To power off the T-Echo, the display must be set
|
||||
// as an input pin; otherwise, there will be leakage current.
|
||||
pinMode(PIN_EINK_CS, INPUT);
|
||||
pinMode(PIN_EINK_DC, INPUT);
|
||||
pinMode(PIN_EINK_RES, INPUT);
|
||||
pinMode(PIN_EINK_BUSY, INPUT);
|
||||
#endif
|
||||
|
||||
setBluetoothEnable(false);
|
||||
|
||||
#ifdef RAK4630
|
||||
@@ -355,57 +440,8 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
// RAK-12039 set pin for Air quality sensor
|
||||
digitalWrite(AQ_SET_PIN, LOW);
|
||||
#endif
|
||||
#ifdef RAK14014
|
||||
// GPIO restores input status, otherwise there will be leakage current
|
||||
nrf_gpio_cfg_default(TFT_BL);
|
||||
nrf_gpio_cfg_default(TFT_DC);
|
||||
nrf_gpio_cfg_default(TFT_CS);
|
||||
nrf_gpio_cfg_default(TFT_SCLK);
|
||||
nrf_gpio_cfg_default(TFT_MOSI);
|
||||
nrf_gpio_cfg_default(TFT_MISO);
|
||||
nrf_gpio_cfg_default(SCREEN_TOUCH_INT);
|
||||
nrf_gpio_cfg_default(WB_I2C1_SCL);
|
||||
nrf_gpio_cfg_default(WB_I2C1_SDA);
|
||||
|
||||
// nrf_gpio_cfg_default(WB_I2C2_SCL);
|
||||
// nrf_gpio_cfg_default(WB_I2C2_SDA);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef MESHLINK
|
||||
#ifdef PIN_WD_EN
|
||||
digitalWrite(PIN_WD_EN, LOW);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_MESH_SOLAR)
|
||||
nrf_gpio_cfg_default(PIN_GPS_PPS);
|
||||
detachInterrupt(PIN_GPS_PPS);
|
||||
detachInterrupt(PIN_BUTTON1);
|
||||
#endif
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
for (int pin = 0; pin < 48; pin++) {
|
||||
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
|
||||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
|
||||
continue;
|
||||
}
|
||||
pinMode(pin, OUTPUT);
|
||||
}
|
||||
for (int pin = 0; pin < 48; pin++) {
|
||||
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
|
||||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
|
||||
continue;
|
||||
}
|
||||
digitalWrite(pin, LOW);
|
||||
}
|
||||
for (int pin = 0; pin < 48; pin++) {
|
||||
if (pin == 17 || pin == 19 || pin == 20 || pin == 22 || pin == 23 || pin == 24 || pin == 25 || pin == 9 || pin == 10 ||
|
||||
pin == PIN_BUTTON1 || pin == PIN_BUTTON2) {
|
||||
continue;
|
||||
}
|
||||
NRF_GPIO->DIRCLR = (1 << pin);
|
||||
}
|
||||
#endif
|
||||
// Run shutdown code if specified in variant.cpp
|
||||
variant_shutdown();
|
||||
|
||||
// Sleepy trackers or sensors can low power "sleep"
|
||||
@@ -428,22 +464,6 @@ void cpuDeepSleep(uint32_t msecToWake)
|
||||
// FIXME, use non-init RAM per
|
||||
// https://devzone.nordicsemi.com/f/nordic-q-a/48919/ram-retention-settings-with-softdevice-enabled
|
||||
|
||||
#ifdef ELECROW_ThinkNode_M1
|
||||
nrf_gpio_cfg_input(PIN_BUTTON1, NRF_GPIO_PIN_PULLUP); // Configure the pin to be woken up as an input
|
||||
nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW;
|
||||
nrf_gpio_cfg_sense_set(PIN_BUTTON1, sense);
|
||||
|
||||
nrf_gpio_cfg_input(PIN_BUTTON2, NRF_GPIO_PIN_PULLUP);
|
||||
nrf_gpio_pin_sense_t sense1 = NRF_GPIO_PIN_SENSE_LOW;
|
||||
nrf_gpio_cfg_sense_set(PIN_BUTTON2, sense1);
|
||||
#endif
|
||||
|
||||
#ifdef PROMICRO_DIY_TCXO
|
||||
nrf_gpio_cfg_input(BUTTON_PIN, NRF_GPIO_PIN_PULLUP); // Enable internal pull-up on the button pin
|
||||
nrf_gpio_pin_sense_t sense = NRF_GPIO_PIN_SENSE_LOW; // Configure SENSE signal on low edge
|
||||
nrf_gpio_cfg_sense_set(BUTTON_PIN, sense); // Apply SENSE to wake up the device from the deep sleep
|
||||
#endif
|
||||
|
||||
#ifdef BATTERY_LPCOMP_INPUT
|
||||
// Wake up if power rises again
|
||||
nrf_lpcomp_config_t c;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "platform/portduino/USBHal.h"
|
||||
|
||||
portduino_config_struct portduino_config;
|
||||
portduino_status_struct portduino_status;
|
||||
std::ofstream traceFile;
|
||||
std::ofstream JSONFile;
|
||||
Ch341Hal *ch341Hal = nullptr;
|
||||
@@ -400,6 +402,11 @@ void portduinoSetup()
|
||||
if (found_hat) {
|
||||
product_config =
|
||||
cleanupNameForAutoconf("lora-hat-" + std::string(hat_vendor) + "-" + autoconf_product + ".yaml");
|
||||
if (strncmp(hat_vendor, "RAK", strlen("RAK")) == 0 &&
|
||||
strncmp(autoconf_product, "6421 Pi Hat", strlen("6421 Pi Hat")) == 0) {
|
||||
std::cout << "autoconf: Setting hardwareModel to RAK6421" << std::endl;
|
||||
portduino_status.hardwareModel = meshtastic_HardwareModel_RAK6421;
|
||||
}
|
||||
} else if (found_ch341) {
|
||||
product_config = cleanupNameForAutoconf("lora-usb-" + std::string(autoconf_product) + ".yaml");
|
||||
// look for more data after the null terminator
|
||||
@@ -408,6 +415,10 @@ void portduinoSetup()
|
||||
memcpy(portduino_config.device_id, autoconf_product + len + 1, 16);
|
||||
if (!memfll(portduino_config.device_id, '\0', 16) && !memfll(portduino_config.device_id, 0xff, 16)) {
|
||||
portduino_config.has_device_id = true;
|
||||
if (strncmp(autoconf_product, "MESHSTICK 1262", strlen("MESHSTICK 1262")) == 0) {
|
||||
std::cout << "autoconf: Setting hardwareModel to Meshstick 1262" << std::endl;
|
||||
portduino_status.hardwareModel = meshtastic_HardwareModel_MESHSTICK_1262;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -485,7 +496,7 @@ void portduinoSetup()
|
||||
randomSeed(time(NULL));
|
||||
|
||||
std::string defaultGpioChipName = gpioChipName + std::to_string(portduino_config.lora_default_gpiochip);
|
||||
for (auto i : portduino_config.all_pins) {
|
||||
for (const auto *i : portduino_config.all_pins) {
|
||||
if (i->enabled && i->pin > max_GPIO)
|
||||
max_GPIO = i->pin;
|
||||
}
|
||||
@@ -499,7 +510,7 @@ void portduinoSetup()
|
||||
|
||||
// Need to bind all the configured GPIO pins so they're not simulated
|
||||
// TODO: If one of these fails, we should log and terminate
|
||||
for (auto i : portduino_config.all_pins) {
|
||||
for (const auto *i : portduino_config.all_pins) {
|
||||
// In the case of a ch341 Lora device, we don't want to touch the system GPIO lines for Lora
|
||||
// Those GPIO are handled in our usermode driver instead.
|
||||
if (i->config_section == "Lora" && portduino_config.lora_spi_dev == "ch341") {
|
||||
@@ -526,6 +537,27 @@ void portduinoSetup()
|
||||
}
|
||||
}
|
||||
|
||||
// In one test, this dance seemed necessary to trigger the pin to detect properly.
|
||||
if (portduino_config.lora_pa_detect_pin.enabled) {
|
||||
pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT_PULLDOWN);
|
||||
sleep(1);
|
||||
if (digitalRead(portduino_config.lora_pa_detect_pin.pin) == LOW) {
|
||||
std::cout << "Pin " << portduino_config.lora_pa_detect_pin.pin << " PULLDOWN is LOW" << std::endl;
|
||||
}
|
||||
pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT_PULLUP);
|
||||
sleep(1);
|
||||
if (digitalRead(portduino_config.lora_pa_detect_pin.pin) == HIGH) {
|
||||
std::cout << "Pin " << portduino_config.lora_pa_detect_pin.pin << " PULLUP is HIGH, dropping PA curve" << std::endl;
|
||||
portduino_config.num_pa_points = 1;
|
||||
portduino_config.tx_gain_lora[0] = 0;
|
||||
} else {
|
||||
std::cout << "Pin " << portduino_config.lora_pa_detect_pin.pin << " PULLUP is LOW, using PA curve" << std::endl;
|
||||
}
|
||||
|
||||
// disable bias once finished
|
||||
pinMode(portduino_config.lora_pa_detect_pin.pin, INPUT);
|
||||
}
|
||||
|
||||
// Only initialize the radio pins when dealing with real, kernel controlled SPI hardware
|
||||
if (portduino_config.lora_spi_dev != "" && portduino_config.lora_spi_dev != "ch341") {
|
||||
SPI.begin(portduino_config.lora_spi_dev.c_str());
|
||||
@@ -561,7 +593,7 @@ void portduinoSetup()
|
||||
return;
|
||||
}
|
||||
|
||||
int initGPIOPin(int pinNum, const std::string gpioChipName, int line)
|
||||
int initGPIOPin(int pinNum, const std::string &gpioChipName, int line)
|
||||
{
|
||||
#ifdef PORTDUINO_LINUX_HARDWARE
|
||||
std::string gpio_name = "GPIO" + std::to_string(pinNum);
|
||||
@@ -632,7 +664,7 @@ bool loadConfig(const char *configPath)
|
||||
if (yamlConfig["Lora"]) {
|
||||
|
||||
if (yamlConfig["Lora"]["Module"]) {
|
||||
for (auto &loraModule : portduino_config.loraModules) {
|
||||
for (const auto &loraModule : portduino_config.loraModules) {
|
||||
if (yamlConfig["Lora"]["Module"].as<std::string>("") == loraModule.second) {
|
||||
portduino_config.lora_module = loraModule.first;
|
||||
break;
|
||||
@@ -766,7 +798,7 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
if (yamlConfig["Display"]) {
|
||||
|
||||
for (auto &screen_name : portduino_config.screen_names) {
|
||||
for (const auto &screen_name : portduino_config.screen_names) {
|
||||
if (yamlConfig["Display"]["Panel"].as<std::string>("") == screen_name.second)
|
||||
portduino_config.displayPanel = screen_name.first;
|
||||
}
|
||||
@@ -861,6 +893,7 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
|
||||
if (yamlConfig["Config"]) {
|
||||
portduino_config.has_config_overrides = true;
|
||||
if (yamlConfig["Config"]["DisplayMode"]) {
|
||||
portduino_config.has_configDisplayMode = true;
|
||||
if ((yamlConfig["Config"]["DisplayMode"]).as<std::string>("") == "TWOCOLOR") {
|
||||
@@ -873,6 +906,13 @@ bool loadConfig(const char *configPath)
|
||||
portduino_config.configDisplayMode = meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT;
|
||||
}
|
||||
}
|
||||
if (yamlConfig["Config"]["StatusMessage"]) {
|
||||
portduino_config.has_statusMessage = true;
|
||||
portduino_config.statusMessage = (yamlConfig["Config"]["StatusMessage"]).as<std::string>("");
|
||||
}
|
||||
if ((yamlConfig["Config"]["EnableUDP"]).as<bool>(false)) {
|
||||
portduino_config.enable_UDP = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (yamlConfig["General"]) {
|
||||
@@ -888,7 +928,7 @@ bool loadConfig(const char *configPath)
|
||||
}
|
||||
if (checkConfigPort) {
|
||||
portduino_config.api_port = (yamlConfig["General"]["APIPort"]).as<int>(-1);
|
||||
if (portduino_config.api_port != -1 && portduino_config.api_port > 1023 && portduino_config.api_port < 65536) {
|
||||
if (portduino_config.api_port > 1023 && portduino_config.api_port < 65536) {
|
||||
TCPPort = (portduino_config.api_port);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "LR11x0Interface.h"
|
||||
#include "Module.h"
|
||||
#include "mesh/generated/meshtastic/mesh.pb.h"
|
||||
#include "platform/portduino/USBHal.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
extern struct portduino_status_struct {
|
||||
bool LoRa_in_error = false;
|
||||
_meshtastic_HardwareModel hardwareModel = meshtastic_HardwareModel_PORTDUINO;
|
||||
} portduino_status;
|
||||
|
||||
#include "platform/portduino/USBHal.h"
|
||||
|
||||
// Product strings for auto-configuration
|
||||
// {"PRODUCT_STRING", "CONFIG.YAML"}
|
||||
// YAML paths are relative to `meshtastic/available.d`
|
||||
@@ -51,7 +58,7 @@ extern std::ofstream traceFile;
|
||||
extern std::ofstream JSONFile;
|
||||
|
||||
extern Ch341Hal *ch341Hal;
|
||||
int initGPIOPin(int pinNum, std::string gpioChipname, int line);
|
||||
int initGPIOPin(int pinNum, const std::string &gpioChipname, int line);
|
||||
bool loadConfig(const char *configPath);
|
||||
static bool ends_with(std::string_view str, std::string_view suffix);
|
||||
void getMacAddr(uint8_t *dmac);
|
||||
@@ -100,6 +107,7 @@ extern struct portduino_config_struct {
|
||||
pinMapping lora_txen_pin = {"Lora", "TXen"};
|
||||
pinMapping lora_rxen_pin = {"Lora", "RXen"};
|
||||
pinMapping lora_sx126x_ant_sw_pin = {"Lora", "SX126X_ANT_SW"};
|
||||
pinMapping lora_pa_detect_pin = {"Lora", "GPIO_DETECT_PA"};
|
||||
std::vector<pinMapping> extra_pins = {};
|
||||
|
||||
// GPS
|
||||
@@ -170,8 +178,12 @@ extern struct portduino_config_struct {
|
||||
int hostMetrics_channel = 0;
|
||||
|
||||
// config
|
||||
bool has_config_overrides = false;
|
||||
int configDisplayMode = 0;
|
||||
bool has_configDisplayMode = false;
|
||||
std::string statusMessage = "";
|
||||
bool has_statusMessage = false;
|
||||
bool enable_UDP = false;
|
||||
|
||||
// General
|
||||
std::string mac_address = "";
|
||||
@@ -183,13 +195,14 @@ extern struct portduino_config_struct {
|
||||
int maxtophone = 100;
|
||||
int MaxNodes = 200;
|
||||
|
||||
pinMapping *all_pins[20] = {&lora_cs_pin,
|
||||
pinMapping *all_pins[21] = {&lora_cs_pin,
|
||||
&lora_irq_pin,
|
||||
&lora_busy_pin,
|
||||
&lora_reset_pin,
|
||||
&lora_txen_pin,
|
||||
&lora_rxen_pin,
|
||||
&lora_sx126x_ant_sw_pin,
|
||||
&lora_pa_detect_pin,
|
||||
&displayDC,
|
||||
&displayCS,
|
||||
&displayBacklight,
|
||||
@@ -213,7 +226,7 @@ extern struct portduino_config_struct {
|
||||
out << YAML::Key << "Lora" << YAML::Value << YAML::BeginMap;
|
||||
out << YAML::Key << "Module" << YAML::Value << loraModules[lora_module];
|
||||
|
||||
for (auto lora_pin : all_pins) {
|
||||
for (const 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;
|
||||
@@ -244,18 +257,23 @@ extern struct portduino_config_struct {
|
||||
out << YAML::Key << "TX_GAIN_LORA" << YAML::Value << tx_gain_lora[0];
|
||||
}
|
||||
|
||||
out << YAML::Key << "DIO2_AS_RF_SWITCH" << YAML::Value << dio2_as_rf_switch;
|
||||
if (dio2_as_rf_switch)
|
||||
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 << YAML::Precision(3) << (float)dio3_tcxo_voltage / 1000;
|
||||
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 != "")
|
||||
if (lora_spi_dev != "" && !(lora_spi_dev == "/dev/spidev0.0" && lora_module == use_autoconf)) {
|
||||
if (lora_spi_dev.find("/dev/") != std::string::npos)
|
||||
lora_spi_dev = lora_spi_dev.substr(5);
|
||||
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 (spiSpeed != 2000000)
|
||||
out << YAML::Key << "spiSpeed" << YAML::Value << spiSpeed;
|
||||
if (rfswitch_dio_pins[0] != RADIOLIB_NC) {
|
||||
out << YAML::Key << "rfswitch_table" << YAML::Value << YAML::BeginMap;
|
||||
|
||||
@@ -339,11 +357,11 @@ extern struct portduino_config_struct {
|
||||
// Display
|
||||
if (displayPanel != no_screen) {
|
||||
out << YAML::Key << "Display" << YAML::Value << YAML::BeginMap;
|
||||
for (auto &screen_name : screen_names) {
|
||||
for (const 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) {
|
||||
for (const 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;
|
||||
@@ -391,7 +409,7 @@ extern struct portduino_config_struct {
|
||||
case ft5x06:
|
||||
out << YAML::Key << "Module" << YAML::Value << "FT5x06";
|
||||
}
|
||||
for (auto touchscreen_pin : all_pins) {
|
||||
for (const 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;
|
||||
@@ -414,7 +432,7 @@ extern struct portduino_config_struct {
|
||||
if (pointerDevice != "")
|
||||
out << YAML::Key << "PointerDevice" << YAML::Value << pointerDevice;
|
||||
|
||||
for (auto input_pin : all_pins) {
|
||||
for (const 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;
|
||||
@@ -498,21 +516,30 @@ extern struct portduino_config_struct {
|
||||
}
|
||||
|
||||
// config
|
||||
if (has_configDisplayMode) {
|
||||
if (has_config_overrides) {
|
||||
out << YAML::Key << "Config" << YAML::Value << YAML::BeginMap;
|
||||
switch (configDisplayMode) {
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
||||
break;
|
||||
if (has_configDisplayMode) {
|
||||
|
||||
switch (configDisplayMode) {
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_TWOCOLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "TWOCOLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_INVERTED:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "INVERTED";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_COLOR:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "COLOR";
|
||||
break;
|
||||
case meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT:
|
||||
out << YAML::Key << "DisplayMode" << YAML::Value << "DEFAULT";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_statusMessage) {
|
||||
out << YAML::Key << "StatusMessage" << YAML::Value << statusMessage;
|
||||
}
|
||||
if (enable_UDP) {
|
||||
out << YAML::Key << "EnableUDP" << YAML::Value << true;
|
||||
}
|
||||
|
||||
out << YAML::EndMap; // Config
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <libpinedio-usb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern uint32_t rebootAtMsec;
|
||||
|
||||
// include the library for Raspberry GPIO pins
|
||||
|
||||
#define PI_RISING (PINEDIO_INT_MODE_RISING)
|
||||
@@ -27,7 +29,7 @@ class Ch341Hal : public RadioLibHal
|
||||
{
|
||||
public:
|
||||
// default constructor - initializes the base HAL and any needed private members
|
||||
explicit Ch341Hal(uint8_t spiChannel, std::string serial = "", uint32_t vid = 0x1A86, uint32_t pid = 0x5512,
|
||||
explicit Ch341Hal(uint8_t spiChannel, const std::string &serial = "", uint32_t vid = 0x1A86, uint32_t pid = 0x5512,
|
||||
uint32_t spiSpeed = 2000000, uint8_t spiDevice = 0, uint8_t gpioDevice = 0)
|
||||
: RadioLibHal(PI_INPUT, PI_OUTPUT, PI_LOW, PI_HIGH, PI_RISING, PI_FALLING)
|
||||
{
|
||||
@@ -45,7 +47,7 @@ class Ch341Hal : public RadioLibHal
|
||||
int32_t ret = pinedio_init(&pinedio, NULL);
|
||||
if (ret != 0) {
|
||||
std::string s = "Could not open SPI: ";
|
||||
throw(s + std::to_string(ret));
|
||||
throw std::runtime_error(s + std::to_string(ret));
|
||||
}
|
||||
|
||||
pinedio_set_option(&pinedio, PINEDIO_OPTION_AUTO_CS, 0);
|
||||
@@ -74,30 +76,55 @@ class Ch341Hal : public RadioLibHal
|
||||
// RADIOLIB_NC as an alias for non-connected pins
|
||||
void pinMode(uint32_t pin, uint32_t mode) override
|
||||
{
|
||||
if (checkError()) {
|
||||
return;
|
||||
}
|
||||
if (pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
pinedio_set_pin_mode(&pinedio, pin, mode);
|
||||
auto res = pinedio_set_pin_mode(&pinedio, pin, mode);
|
||||
if (res < 0 && rebootAtMsec == 0) {
|
||||
LOG_ERROR("USBHal pinMode: Could not set pin %u mode to %u: %d", pin, mode, res);
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(uint32_t pin, uint32_t value) override
|
||||
{
|
||||
if (checkError()) {
|
||||
return;
|
||||
}
|
||||
if (pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
pinedio_digital_write(&pinedio, pin, value);
|
||||
auto res = pinedio_digital_write(&pinedio, pin, value);
|
||||
if (res < 0 && rebootAtMsec == 0) {
|
||||
LOG_ERROR("USBHal digitalWrite: Could not write pin %u: %d", pin, res);
|
||||
portduino_status.LoRa_in_error = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t digitalRead(uint32_t pin) override
|
||||
{
|
||||
if (checkError()) {
|
||||
return 0;
|
||||
}
|
||||
if (pin == RADIOLIB_NC) {
|
||||
return 0;
|
||||
}
|
||||
return pinedio_digital_read(&pinedio, pin);
|
||||
auto res = pinedio_digital_read(&pinedio, pin);
|
||||
if (res < 0 && rebootAtMsec == 0) {
|
||||
LOG_ERROR("USBHal digitalRead: Could not read pin %u: %d", pin, res);
|
||||
portduino_status.LoRa_in_error = true;
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override
|
||||
{
|
||||
if (checkError()) {
|
||||
return;
|
||||
}
|
||||
if (interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
@@ -107,6 +134,9 @@ class Ch341Hal : public RadioLibHal
|
||||
|
||||
void detachInterrupt(uint32_t interruptNum) override
|
||||
{
|
||||
if (checkError()) {
|
||||
return;
|
||||
}
|
||||
if (interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
@@ -152,6 +182,9 @@ class Ch341Hal : public RadioLibHal
|
||||
|
||||
void spiTransfer(uint8_t *out, size_t len, uint8_t *in)
|
||||
{
|
||||
if (checkError()) {
|
||||
return;
|
||||
}
|
||||
int32_t ret = pinedio_transceive(&this->pinedio, out, in, len);
|
||||
if (ret < 0) {
|
||||
std::cerr << "Could not perform SPI transfer: " << ret << std::endl;
|
||||
@@ -160,9 +193,22 @@ class Ch341Hal : public RadioLibHal
|
||||
|
||||
void spiEndTransaction() {}
|
||||
void spiEnd() {}
|
||||
bool checkError()
|
||||
{
|
||||
if (pinedio.in_error) {
|
||||
if (!has_warned)
|
||||
LOG_ERROR("USBHal: libch341 in_error detected");
|
||||
portduino_status.LoRa_in_error = true;
|
||||
has_warned = true;
|
||||
return true;
|
||||
}
|
||||
has_warned = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
pinedio_inst pinedio = {0};
|
||||
bool has_warned = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
// set HW_VENDOR
|
||||
//
|
||||
|
||||
#define HW_VENDOR meshtastic_HardwareModel_PORTDUINO
|
||||
#define HW_VENDOR portduino_status.hardwareModel
|
||||
|
||||
#ifndef HAS_BUTTON
|
||||
#define HAS_BUTTON 1
|
||||
@@ -17,9 +17,6 @@
|
||||
#ifndef HAS_RADIO
|
||||
#define HAS_RADIO 1
|
||||
#endif
|
||||
#ifndef HAS_RTC
|
||||
#define HAS_RTC 1
|
||||
#endif
|
||||
#ifndef HAS_TELEMETRY
|
||||
#define HAS_TELEMETRY 1
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user