Merge remote-tracking branch 'upstream/develop' into fix/tlora-pager-rotary-amplifier
This commit is contained in:
@@ -10,7 +10,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
check-label:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check for PR labels
|
||||
uses: actions/github-script@v8
|
||||
|
||||
+4
-4
@@ -9,14 +9,14 @@ plugins:
|
||||
lint:
|
||||
enabled:
|
||||
- checkov@3.2.471
|
||||
- renovate@41.115.6
|
||||
- renovate@41.118.1
|
||||
- prettier@3.6.2
|
||||
- trufflehog@3.90.6
|
||||
- trufflehog@3.90.8
|
||||
- yamllint@1.37.1
|
||||
- bandit@1.8.6
|
||||
- trivy@0.66.0
|
||||
- taplo@0.10.0
|
||||
- ruff@0.13.0
|
||||
- ruff@0.13.1
|
||||
- isort@6.0.1
|
||||
- markdownlint@0.45.0
|
||||
- oxipng@9.1.5
|
||||
@@ -26,7 +26,7 @@ lint:
|
||||
- hadolint@2.13.1
|
||||
- shfmt@3.6.0
|
||||
- shellcheck@0.11.0
|
||||
- black@25.1.0
|
||||
- black@25.9.0
|
||||
- git-diff-check
|
||||
- gitleaks@8.28.0
|
||||
- clang-format@16.0.3
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
[portduino_base]
|
||||
platform =
|
||||
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
|
||||
https://github.com/meshtastic/platform-native/archive/c490bcd019e0658404088a61b96e653c9da22c45.zip
|
||||
https://github.com/meshtastic/platform-native/archive/d3f6e339534233c7217818867368767590ce549e.zip
|
||||
framework = arduino
|
||||
|
||||
build_src_filter =
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ lib_deps =
|
||||
[radiolib_base]
|
||||
lib_deps =
|
||||
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
|
||||
jgromes/RadioLib@7.2.1
|
||||
jgromes/RadioLib@7.3.0
|
||||
|
||||
[device-ui_base]
|
||||
lib_deps =
|
||||
|
||||
@@ -83,6 +83,11 @@ extern uint16_t TFT_MESH;
|
||||
#include "platform/portduino/PortduinoGlue.h"
|
||||
#endif
|
||||
|
||||
#if defined(T_LORA_PAGER)
|
||||
// KB backlight control
|
||||
#include "input/cardKbI2cImpl.h"
|
||||
#endif
|
||||
|
||||
using namespace meshtastic; /** @todo remove */
|
||||
|
||||
namespace graphics
|
||||
@@ -655,6 +660,19 @@ void Screen::setup()
|
||||
MeshModule::observeUIEvents(&uiFrameEventObserver);
|
||||
}
|
||||
|
||||
void Screen::setOn(bool on, FrameCallback einkScreensaver)
|
||||
{
|
||||
#if defined(T_LORA_PAGER)
|
||||
if (cardKbI2cImpl)
|
||||
cardKbI2cImpl->toggleBacklight(on);
|
||||
#endif
|
||||
if (!on)
|
||||
// We handle off commands immediately, because they might be called because the CPU is shutting down
|
||||
handleSetOn(false, einkScreensaver);
|
||||
else
|
||||
enqueueCmd(ScreenCmd{.cmd = Cmd::SET_ON});
|
||||
}
|
||||
|
||||
void Screen::forceDisplay(bool forceUiUpdate)
|
||||
{
|
||||
// Nasty hack to force epaper updates for 'key' frames. FIXME, cleanup.
|
||||
|
||||
@@ -259,15 +259,7 @@ class Screen : public concurrency::OSThread
|
||||
void setup();
|
||||
|
||||
/// Turns the screen on/off. Optionally, pass a custom screensaver frame for E-Ink
|
||||
void setOn(bool on, FrameCallback einkScreensaver = NULL)
|
||||
{
|
||||
if (!on)
|
||||
// We handle off commands immediately, because they might be called because the CPU is shutting down
|
||||
handleSetOn(false, einkScreensaver);
|
||||
else
|
||||
enqueueCmd(ScreenCmd{.cmd = Cmd::SET_ON});
|
||||
}
|
||||
|
||||
void setOn(bool on, FrameCallback einkScreensaver = NULL);
|
||||
/**
|
||||
* Prepare the display for the unit going to the lowest power mode possible. Most screens will just
|
||||
* poweroff, but eink screens will show a "I'm sleeping" graphic, possibly with a QR code
|
||||
|
||||
@@ -31,19 +31,21 @@ uint8_t test_count = 0;
|
||||
|
||||
void menuHandler::loraMenu()
|
||||
{
|
||||
static const char *optionsArray[] = {"Back", "Region Picker", "Device Role"};
|
||||
enum optionsNumbers { Back = 0, lora_picker = 1, device_role_picker = 2 };
|
||||
static const char *optionsArray[] = {"Back", "Device Role", "Radio Preset", "LoRa Region"};
|
||||
enum optionsNumbers { Back = 0, device_role_picker = 1, radio_preset_picker = 2, lora_picker = 3 };
|
||||
BannerOverlayOptions bannerOptions;
|
||||
bannerOptions.message = "LoRa Actions";
|
||||
bannerOptions.optionsArrayPtr = optionsArray;
|
||||
bannerOptions.optionsCount = 3;
|
||||
bannerOptions.optionsCount = 4;
|
||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||
if (selected == Back) {
|
||||
// No action
|
||||
} else if (selected == lora_picker) {
|
||||
menuHandler::menuQueue = menuHandler::lora_picker;
|
||||
} else if (selected == device_role_picker) {
|
||||
menuHandler::menuQueue = menuHandler::device_role_picker;
|
||||
} else if (selected == radio_preset_picker) {
|
||||
menuHandler::menuQueue = menuHandler::radio_preset_picker;
|
||||
} else if (selected == lora_picker) {
|
||||
menuHandler::menuQueue = menuHandler::lora_picker;
|
||||
}
|
||||
};
|
||||
screen->showOverlayBanner(bannerOptions);
|
||||
@@ -180,6 +182,53 @@ void menuHandler::DeviceRolePicker()
|
||||
screen->showOverlayBanner(bannerOptions);
|
||||
}
|
||||
|
||||
void menuHandler::RadioPresetPicker()
|
||||
{
|
||||
static const char *optionsArray[] = {"Back", "LongSlow", "LongModerate", "LongFast", "MediumSlow",
|
||||
"MediumFast", "ShortSlow", "ShortFast", "ShortTurbo"};
|
||||
enum optionsNumbers {
|
||||
Back = 0,
|
||||
radiopreset_LongSlow = 1,
|
||||
radiopreset_LongModerate = 2,
|
||||
radiopreset_LongFast = 3,
|
||||
radiopreset_MediumSlow = 4,
|
||||
radiopreset_MediumFast = 5,
|
||||
radiopreset_ShortSlow = 6,
|
||||
radiopreset_ShortFast = 7,
|
||||
radiopreset_ShortTurbo = 8
|
||||
};
|
||||
BannerOverlayOptions bannerOptions;
|
||||
bannerOptions.message = "Radio Preset";
|
||||
bannerOptions.optionsArrayPtr = optionsArray;
|
||||
bannerOptions.optionsCount = 9;
|
||||
bannerOptions.bannerCallback = [](int selected) -> void {
|
||||
if (selected == Back) {
|
||||
menuHandler::menuQueue = menuHandler::lora_Menu;
|
||||
screen->runNow();
|
||||
return;
|
||||
} else if (selected == radiopreset_LongSlow) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_SLOW;
|
||||
} else if (selected == radiopreset_LongModerate) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE;
|
||||
} else if (selected == radiopreset_LongFast) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_LONG_FAST;
|
||||
} else if (selected == radiopreset_MediumSlow) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_SLOW;
|
||||
} else if (selected == radiopreset_MediumFast) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_MEDIUM_FAST;
|
||||
} else if (selected == radiopreset_ShortSlow) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW;
|
||||
} else if (selected == radiopreset_ShortFast) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST;
|
||||
} else if (selected == radiopreset_ShortTurbo) {
|
||||
config.lora.modem_preset = meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO;
|
||||
}
|
||||
service->reloadConfig(SEGMENT_CONFIG);
|
||||
rebootAtMsec = (millis() + DEFAULT_REBOOT_SECONDS * 1000);
|
||||
};
|
||||
screen->showOverlayBanner(bannerOptions);
|
||||
}
|
||||
|
||||
void menuHandler::TwelveHourPicker()
|
||||
{
|
||||
static const char *optionsArray[] = {"Back", "12-hour", "24-hour"};
|
||||
@@ -1478,6 +1527,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display)
|
||||
case device_role_picker:
|
||||
DeviceRolePicker();
|
||||
break;
|
||||
case radio_preset_picker:
|
||||
RadioPresetPicker();
|
||||
break;
|
||||
case no_timeout_lora_picker:
|
||||
LoraRegionPicker(0);
|
||||
break;
|
||||
|
||||
@@ -12,6 +12,7 @@ class menuHandler
|
||||
lora_Menu,
|
||||
lora_picker,
|
||||
device_role_picker,
|
||||
radio_preset_picker,
|
||||
no_timeout_lora_picker,
|
||||
TZ_picker,
|
||||
twelve_hour_picker,
|
||||
@@ -50,6 +51,7 @@ class menuHandler
|
||||
static void LoraRegionPicker(uint32_t duration = 30000);
|
||||
static void loraMenu();
|
||||
static void DeviceRolePicker();
|
||||
static void RadioPresetPicker();
|
||||
static void handleMenuSwitch(OLEDDisplay *display);
|
||||
static void showConfirmationBanner(const char *message, std::function<void()> onConfirm);
|
||||
static void clockMenu();
|
||||
|
||||
@@ -200,6 +200,11 @@ uint8_t TCA8418KeyboardBase::flush()
|
||||
return count;
|
||||
}
|
||||
|
||||
void TCA8418KeyboardBase::clearInt()
|
||||
{
|
||||
writeRegister(TCA8418_REG_INT_STAT, 3);
|
||||
}
|
||||
|
||||
uint8_t TCA8418KeyboardBase::digitalRead(uint8_t pinnum) const
|
||||
{
|
||||
if (pinnum > TCA8418_COL9)
|
||||
|
||||
@@ -37,6 +37,8 @@ class TCA8418KeyboardBase
|
||||
virtual void begin(i2c_com_fptr_t r, i2c_com_fptr_t w, uint8_t addr = TCA8418_KB_ADDR);
|
||||
|
||||
virtual void reset(void);
|
||||
void clearInt(void);
|
||||
|
||||
virtual void trigger(void);
|
||||
|
||||
virtual void setBacklight(bool on);
|
||||
|
||||
@@ -105,7 +105,14 @@ void TLoraPagerKeyboard::trigger()
|
||||
|
||||
void TLoraPagerKeyboard::setBacklight(bool on)
|
||||
{
|
||||
toggleBacklight(!on);
|
||||
uint32_t _brightness = 0;
|
||||
if (on)
|
||||
_brightness = brightness;
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ledcWrite(KB_BL_PIN, _brightness);
|
||||
#else
|
||||
ledcWrite(LEDC_BACKLIGHT_CHANNEL, _brightness);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TLoraPagerKeyboard::pressed(uint8_t key)
|
||||
@@ -192,7 +199,6 @@ void TLoraPagerKeyboard::hapticFeedback()
|
||||
// toggle brightness of the backlight in three steps
|
||||
void TLoraPagerKeyboard::toggleBacklight(bool off)
|
||||
{
|
||||
static uint32_t brightness = 0;
|
||||
if (off) {
|
||||
brightness = 0;
|
||||
} else {
|
||||
@@ -206,11 +212,7 @@ void TLoraPagerKeyboard::toggleBacklight(bool off)
|
||||
}
|
||||
LOG_DEBUG("Toggle backlight: %d", brightness);
|
||||
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
|
||||
ledcWrite(KB_BL_PIN, brightness);
|
||||
#else
|
||||
ledcWrite(LEDC_BACKLIGHT_CHANNEL, brightness);
|
||||
#endif
|
||||
setBacklight(true);
|
||||
}
|
||||
|
||||
void TLoraPagerKeyboard::updateModifierFlag(uint8_t key)
|
||||
|
||||
@@ -26,4 +26,5 @@ class TLoraPagerKeyboard : public TCA8418KeyboardBase
|
||||
uint32_t last_tap;
|
||||
uint8_t char_idx;
|
||||
int32_t tap_interval;
|
||||
uint32_t brightness = 0;
|
||||
};
|
||||
|
||||
@@ -333,6 +333,7 @@ int32_t KbI2cBase::runOnce()
|
||||
}
|
||||
TCAKeyboard.trigger();
|
||||
}
|
||||
TCAKeyboard.clearInt();
|
||||
break;
|
||||
}
|
||||
case 0x02: {
|
||||
@@ -519,4 +520,11 @@ int32_t KbI2cBase::runOnce()
|
||||
LOG_WARN("Unknown kb_model 0x%02x", kb_model);
|
||||
}
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
||||
void KbI2cBase::toggleBacklight(bool on)
|
||||
{
|
||||
#if defined(T_LORA_PAGER)
|
||||
TCAKeyboard.setBacklight(on);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class KbI2cBase : public Observable<const InputEvent *>, public concurrency::OST
|
||||
{
|
||||
public:
|
||||
explicit KbI2cBase(const char *name);
|
||||
void toggleBacklight(bool on);
|
||||
|
||||
protected:
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
@@ -369,6 +369,7 @@ void setup()
|
||||
digitalWrite(SDCARD_CS, HIGH);
|
||||
pinMode(TFT_CS, OUTPUT);
|
||||
digitalWrite(TFT_CS, HIGH);
|
||||
pinMode(KB_INT, INPUT_PULLUP);
|
||||
// io expander
|
||||
io.begin(Wire, XL9555_SLAVE_ADDRESS0, SDA, SCL);
|
||||
io.pinMode(EXPANDS_DRV_EN, OUTPUT);
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ NodeDB::NodeDB()
|
||||
|
||||
int saveWhat = 0;
|
||||
// Get device unique id
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32C6)
|
||||
uint32_t unique_id[4];
|
||||
// ESP32 factory burns a unique id in efuse for S2+ series and evidently C3+ series
|
||||
// This is used for HMACs in the esp-rainmaker AIOT platform and seems to be a good choice for us
|
||||
|
||||
@@ -250,6 +250,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
if (config_nonce == SPECIAL_NONCE_ONLY_NODES) {
|
||||
// If client only wants node info, jump directly to sending nodes
|
||||
state = STATE_SEND_OTHER_NODEINFOS;
|
||||
onNowHasData(0);
|
||||
} else {
|
||||
state = STATE_SEND_METADATA;
|
||||
}
|
||||
@@ -423,6 +424,7 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf)
|
||||
state = STATE_SEND_FILEMANIFEST;
|
||||
} else {
|
||||
state = STATE_SEND_OTHER_NODEINFOS;
|
||||
onNowHasData(0);
|
||||
}
|
||||
config_state = 0;
|
||||
}
|
||||
@@ -588,6 +590,7 @@ bool PhoneAPI::available()
|
||||
nodeInfoForPhone.snr = isUs ? 0 : nodeInfoForPhone.snr;
|
||||
nodeInfoForPhone.via_mqtt = isUs ? false : nodeInfoForPhone.via_mqtt;
|
||||
nodeInfoForPhone.is_favorite = nodeInfoForPhone.is_favorite || isUs; // Our node is always a favorite
|
||||
onNowHasData(0);
|
||||
}
|
||||
}
|
||||
return true; // Always say we have something, because we might need to advance our state machine
|
||||
|
||||
@@ -293,9 +293,7 @@ void setupModules()
|
||||
#endif
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION
|
||||
if (moduleConfig.has_external_notification && moduleConfig.external_notification.enabled) {
|
||||
externalNotificationModule = new ExternalNotificationModule();
|
||||
}
|
||||
externalNotificationModule = new ExternalNotificationModule();
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_RANGETEST && !MESHTASTIC_EXCLUDE_GPS
|
||||
if (moduleConfig.has_range_test && moduleConfig.range_test.enabled)
|
||||
|
||||
@@ -174,11 +174,11 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
|
||||
|
||||
#if !defined(M5STACK_UNITC6L)
|
||||
display->setFont(FONT_SMALL);
|
||||
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM - 4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
|
||||
display->drawString(x_offset + x, y_offset + y, "Enter this code");
|
||||
|
||||
#endif
|
||||
display->setFont(FONT_LARGE);
|
||||
char pin[8];
|
||||
snprintf(pin, sizeof(pin), "%.3s %.3s", btPIN, btPIN + 3);
|
||||
|
||||
+13
-4
@@ -411,12 +411,16 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
// assert(uart_set_wakeup_threshold(UART_NUM_0, 3) == ESP_OK);
|
||||
// assert(esp_sleep_enable_uart_wakeup(0) == ESP_OK);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN
|
||||
#ifdef ROTARY_PRESS
|
||||
// The enableLoraInterrupt() method is using ext0_wakeup, so we are forced to use GPIO wakeup
|
||||
gpio_wakeup_enable((gpio_num_t)ROTARY_PRESS, GPIO_INTR_LOW_LEVEL);
|
||||
#endif
|
||||
#ifdef KB_INT
|
||||
gpio_wakeup_enable((gpio_num_t)KB_INT, GPIO_INTR_LOW_LEVEL);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN
|
||||
gpio_num_t pin = (gpio_num_t)(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
|
||||
|
||||
gpio_wakeup_enable(pin, GPIO_INTR_LOW_LEVEL);
|
||||
esp_sleep_enable_gpio_wakeup();
|
||||
#endif
|
||||
#ifdef INPUTDRIVER_ENCODER_BTN
|
||||
gpio_wakeup_enable((gpio_num_t)INPUTDRIVER_ENCODER_BTN, GPIO_INTR_LOW_LEVEL);
|
||||
@@ -450,7 +454,12 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r
|
||||
// commented out because it's not that crucial;
|
||||
// if it sporadically happens the node will go into light sleep during the next round
|
||||
// assert(res == ESP_OK);
|
||||
|
||||
#ifdef ROTARY_PRESS
|
||||
gpio_wakeup_disable((gpio_num_t)ROTARY_PRESS);
|
||||
#endif
|
||||
#ifdef KB_INT
|
||||
gpio_wakeup_disable((gpio_num_t)KB_INT);
|
||||
#endif
|
||||
#ifdef BUTTON_PIN
|
||||
// Disable wake-on-button interrupt. Re-attach normal button-interrupts
|
||||
gpio_wakeup_disable(pin);
|
||||
|
||||
Reference in New Issue
Block a user