mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-23 11:10:52 +00:00
Merge branch 'master' into raspi-portduino
This commit is contained in:
4
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
4
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -37,7 +37,9 @@ body:
|
||||
- T-Lora v1
|
||||
- T-Lora v1.3
|
||||
- T-Lora v2 1.6
|
||||
- T-Deck
|
||||
- T-Echo
|
||||
- T-Watch
|
||||
- Rak4631
|
||||
- Rak11200
|
||||
- Rak11310
|
||||
@@ -45,6 +47,8 @@ body:
|
||||
- Heltec v2
|
||||
- Heltec v2.1
|
||||
- Heltec V3
|
||||
- Heltec Wireless Paper
|
||||
- Heltec Wireless Tracker
|
||||
- Raspberry Pi Pico (W)
|
||||
- Relay v1
|
||||
- Relay v2
|
||||
|
||||
16
.github/workflows/build_esp32.yml
vendored
16
.github/workflows/build_esp32.yml
vendored
@@ -17,11 +17,11 @@ jobs:
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||
with:
|
||||
repo: "meshtastic/web"
|
||||
file: "build.tar"
|
||||
target: "build.tar"
|
||||
repo: meshtastic/web
|
||||
file: build.tar
|
||||
target: build.tar
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
@@ -40,11 +40,11 @@ jobs:
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||
with:
|
||||
repo: "meshtastic/firmware-ota"
|
||||
file: "firmware.bin"
|
||||
target: "release/bleota.bin"
|
||||
repo: meshtastic/firmware-ota
|
||||
file: firmware.bin
|
||||
target: release/bleota.bin
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
|
||||
16
.github/workflows/build_esp32_s3.yml
vendored
16
.github/workflows/build_esp32_s3.yml
vendored
@@ -17,11 +17,11 @@ jobs:
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||
with:
|
||||
repo: "meshtastic/web"
|
||||
file: "build.tar"
|
||||
target: "build.tar"
|
||||
repo: meshtastic/web
|
||||
file: build.tar
|
||||
target: build.tar
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
@@ -38,11 +38,11 @@ jobs:
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
||||
with:
|
||||
repo: "meshtastic/firmware-ota"
|
||||
file: "firmware-s3.bin"
|
||||
target: "release/bleota-s3.bin"
|
||||
repo: meshtastic/firmware-ota
|
||||
file: firmware-s3.bin
|
||||
target: release/bleota-s3.bin
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
|
||||
7
.github/workflows/main_matrix.yml
vendored
7
.github/workflows/main_matrix.yml
vendored
@@ -1,4 +1,7 @@
|
||||
name: CI
|
||||
#concurrency:
|
||||
# group: ${{ github.ref }}
|
||||
# cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
|
||||
on:
|
||||
# # Triggers the workflow on push but only for the master branch
|
||||
push:
|
||||
@@ -46,7 +49,7 @@ jobs:
|
||||
|
||||
- name: Trunk Check
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
uses: trunk-io/trunk-action@v1
|
||||
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
||||
|
||||
- name: Check ${{ matrix.board }}
|
||||
run: bin/check-all.sh ${{ matrix.board }}
|
||||
@@ -108,6 +111,7 @@ jobs:
|
||||
- board: t-echo
|
||||
- board: pca10059_diy_eink
|
||||
- board: feather_diy
|
||||
- board: nano-g2-ultra
|
||||
uses: ./.github/workflows/build_nrf52.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
@@ -255,6 +259,7 @@ jobs:
|
||||
retention-days: 30
|
||||
|
||||
- name: Create request artifacts
|
||||
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||
uses: gavv/pull-request-artifacts@v1.1.0
|
||||
with:
|
||||
|
||||
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -14,6 +14,6 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Trunk Check
|
||||
uses: trunk-io/trunk-action@v1
|
||||
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
||||
with:
|
||||
trunk-token: ${{ secrets.TRUNK_TOKEN }}
|
||||
|
||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "trunk.io"
|
||||
"editor.defaultFormatter": "trunk.io",
|
||||
"trunk.enableWindows": true
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
|
||||
@REM Account for S3 board's different OTA partition
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% (
|
||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||
) else (
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||
|
||||
@@ -50,7 +50,7 @@ if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||
# Account for S3 board's different OTA partition
|
||||
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ]; then
|
||||
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ] && [ ! -z "${FILENAME##*"t-deck"*}" ] && [ ! -z "${FILENAME##*"wireless-paper"*}" ] && [ ! -z "${FILENAME##*"wireless-tracker"*}" ]; then
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||
else
|
||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
||||
|
||||
51
boards/nano-g2-ultra.json
Normal file
51
boards/nano-g2-ultra.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
["0x239A", "0x8029"],
|
||||
["0x239A", "0x0029"],
|
||||
["0x239A", "0x002A"],
|
||||
["0x239A", "0x802A"]
|
||||
],
|
||||
"usb_product": "BQ nRF52840",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "nano-g2-ultra",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "BQ nRF52840",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||
"use_1200bps_touch": true,
|
||||
"require_upload_port": true,
|
||||
"wait_for_upload_port": true
|
||||
},
|
||||
"url": "https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra",
|
||||
"vendor": "BQ Consulting"
|
||||
}
|
||||
Submodule protobufs updated: f17298c2b0...8e7500278f
@@ -101,23 +101,8 @@ class ButtonThread : public concurrency::OSThread
|
||||
#endif
|
||||
// if (!canSleep) LOG_DEBUG("Suppressing sleep!\n");
|
||||
// else LOG_DEBUG("sleep ok\n");
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
||||
int x, y = 0;
|
||||
screen->getTouch(&x, &y);
|
||||
if (x > 0 && y > 0) {
|
||||
#ifdef T_WATCH_S3
|
||||
drv.setWaveform(0, 75);
|
||||
drv.setWaveform(1, 0); // end waveform
|
||||
drv.go();
|
||||
#endif
|
||||
LOG_DEBUG("touch %d %d\n", x, y);
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
return 150; // Check for next touch every in 150ms
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 5;
|
||||
return 50;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -15,4 +15,6 @@ enum class Cmd {
|
||||
PRINT,
|
||||
START_SHUTDOWN_SCREEN,
|
||||
START_REBOOT_SCREEN,
|
||||
SHOW_PREV_FRAME,
|
||||
SHOW_NEXT_FRAME
|
||||
};
|
||||
@@ -98,8 +98,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// Define if screen should be mirrored left to right
|
||||
// #define SCREEN_MIRROR
|
||||
|
||||
// The m5stack I2C Keyboard (also RAK14004)
|
||||
// I2C Keyboards (M5Stack, RAK14004, T-Deck)
|
||||
#define CARDKB_ADDR 0x5F
|
||||
#define TDECK_KB_ADDR 0x55
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SENSOR
|
||||
@@ -173,6 +174,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef HAS_BUTTON
|
||||
#define HAS_BUTTON 0
|
||||
#endif
|
||||
#ifndef HAS_TRACKBALL
|
||||
#define HAS_TRACKBALL 0
|
||||
#endif
|
||||
#ifndef HAS_TOUCHSCREEN
|
||||
#define HAS_TOUCHSCREEN 0
|
||||
#endif
|
||||
#ifndef HAS_TELEMETRY
|
||||
#define HAS_TELEMETRY 0
|
||||
#endif
|
||||
|
||||
@@ -30,8 +30,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
|
||||
{
|
||||
ScanI2C::DeviceType types[] = {CARDKB, RAK14004};
|
||||
return firstOfOrNONE(2, types);
|
||||
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, RAK14004};
|
||||
return firstOfOrNONE(3, types);
|
||||
}
|
||||
|
||||
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
|
||||
|
||||
@@ -16,6 +16,7 @@ class ScanI2C
|
||||
RTC_RV3028,
|
||||
RTC_PCF8563,
|
||||
CARDKB,
|
||||
TDECKKB,
|
||||
RAK14004,
|
||||
PMU_AXP192_AXP2101,
|
||||
BME_680,
|
||||
|
||||
@@ -212,6 +212,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port)
|
||||
}
|
||||
break;
|
||||
|
||||
SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found\n");
|
||||
SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found\n");
|
||||
#ifdef HAS_NCP5623
|
||||
SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found\n");
|
||||
|
||||
@@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "gps/GeoCoord.h"
|
||||
#include "gps/RTC.h"
|
||||
#include "graphics/images.h"
|
||||
#include "input/TouchScreenImpl1.h"
|
||||
#include "main.h"
|
||||
#include "mesh-pb-constants.h"
|
||||
#include "mesh/Channels.h"
|
||||
@@ -835,7 +836,11 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
}
|
||||
|
||||
static char distStr[20];
|
||||
strncpy(distStr, "? km", sizeof(distStr)); // might not have location data
|
||||
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||
strncpy(distStr, "? mi", sizeof(distStr)); // might not have location data
|
||||
} else {
|
||||
strncpy(distStr, "? km", sizeof(distStr));
|
||||
}
|
||||
meshtastic_NodeInfoLite *ourNode = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
||||
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
||||
int16_t compassX = 0, compassY = 0;
|
||||
@@ -1040,12 +1045,18 @@ void Screen::setup()
|
||||
#endif
|
||||
serialSinceMsec = millis();
|
||||
|
||||
#if HAS_TOUCHSCREEN
|
||||
touchScreenImpl1 = new TouchScreenImpl1(dispdev.getWidth(), dispdev.getHeight(), dispdev.getTouch);
|
||||
touchScreenImpl1->init();
|
||||
#endif
|
||||
|
||||
// Subscribe to status updates
|
||||
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
||||
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
|
||||
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
|
||||
if (textMessageModule)
|
||||
textMessageObserver.observe(textMessageModule);
|
||||
inputObserver.observe(inputBroker);
|
||||
|
||||
// Modules can notify screen about refresh
|
||||
MeshModule::observeUIEvents(&uiFrameEventObserver);
|
||||
@@ -1123,6 +1134,12 @@ int32_t Screen::runOnce()
|
||||
handleOnPress();
|
||||
}
|
||||
break;
|
||||
case Cmd::SHOW_PREV_FRAME:
|
||||
handleShowPrevFrame();
|
||||
break;
|
||||
case Cmd::SHOW_NEXT_FRAME:
|
||||
handleShowNextFrame();
|
||||
break;
|
||||
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
||||
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
||||
break;
|
||||
@@ -1416,6 +1433,28 @@ void Screen::handleOnPress()
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::handleShowPrevFrame()
|
||||
{
|
||||
// If screen was off, just wake it, otherwise go back to previous frame
|
||||
// If we are in a transition, the press must have bounced, drop it.
|
||||
if (ui.getUiState()->frameState == FIXED) {
|
||||
ui.previousFrame();
|
||||
lastScreenTransition = millis();
|
||||
setFastFramerate();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::handleShowNextFrame()
|
||||
{
|
||||
// If screen was off, just wake it, otherwise advance to next frame
|
||||
// If we are in a transition, the press must have bounced, drop it.
|
||||
if (ui.getUiState()->frameState == FIXED) {
|
||||
ui.nextFrame();
|
||||
lastScreenTransition = millis();
|
||||
setFastFramerate();
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SCREEN_TRANSITION_FRAMERATE
|
||||
#define SCREEN_TRANSITION_FRAMERATE 30 // fps
|
||||
#endif
|
||||
@@ -1853,6 +1892,20 @@ int Screen::handleUIFrameEvent(const UIFrameEvent *event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Screen::handleInputEvent(const InputEvent *event)
|
||||
{
|
||||
if (showingNormalScreen && moduleFrames.size() == 0) {
|
||||
LOG_DEBUG("Screen::handleInputEvent from %s\n", event->source);
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||
showPrevFrame();
|
||||
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||
showNextFrame();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace graphics
|
||||
#else
|
||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||
|
||||
@@ -53,6 +53,7 @@ class Screen
|
||||
#include "commands.h"
|
||||
#include "concurrency/LockGuard.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "input/InputBroker.h"
|
||||
#include "mesh/MeshModule.h"
|
||||
#include "power.h"
|
||||
#include <string>
|
||||
@@ -118,6 +119,8 @@ class Screen : public concurrency::OSThread
|
||||
CallbackObserver<Screen, const meshtastic_MeshPacket *>(this, &Screen::handleTextMessage);
|
||||
CallbackObserver<Screen, const UIFrameEvent *> uiFrameEventObserver =
|
||||
CallbackObserver<Screen, const UIFrameEvent *>(this, &Screen::handleUIFrameEvent);
|
||||
CallbackObserver<Screen, const InputEvent *> inputObserver =
|
||||
CallbackObserver<Screen, const InputEvent *>(this, &Screen::handleInputEvent);
|
||||
|
||||
public:
|
||||
explicit Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY);
|
||||
@@ -152,8 +155,10 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
void blink();
|
||||
|
||||
/// Handles a button press.
|
||||
/// Handle button press, trackball or swipe action)
|
||||
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
||||
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
|
||||
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
|
||||
|
||||
// Implementation to Adjust Brightness
|
||||
void adjustBrightness();
|
||||
@@ -301,9 +306,11 @@ class Screen : public concurrency::OSThread
|
||||
// Use this handle to set things like battery status, user count, GPS status, etc.
|
||||
DebugInfo *debug_info() { return &debugInfo; }
|
||||
|
||||
// Handle observer events
|
||||
int handleStatusUpdate(const meshtastic::Status *arg);
|
||||
int handleTextMessage(const meshtastic_MeshPacket *arg);
|
||||
int handleUIFrameEvent(const UIFrameEvent *arg);
|
||||
int handleInputEvent(const InputEvent *arg);
|
||||
|
||||
/// Used to force (super slow) eink displays to draw critical frames
|
||||
void forceDisplay();
|
||||
@@ -313,13 +320,6 @@ class Screen : public concurrency::OSThread
|
||||
|
||||
void setWelcomeFrames();
|
||||
|
||||
void getTouch(int *x, int *y)
|
||||
{
|
||||
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
|
||||
dispdev.getTouch(x, y);
|
||||
#endif
|
||||
};
|
||||
|
||||
protected:
|
||||
/// Updates the UI.
|
||||
//
|
||||
@@ -350,6 +350,8 @@ class Screen : public concurrency::OSThread
|
||||
// Implementations of various commands, called from doTask().
|
||||
void handleSetOn(bool on);
|
||||
void handleOnPress();
|
||||
void handleShowNextFrame();
|
||||
void handleShowPrevFrame();
|
||||
void handleStartBluetoothPinScreen(uint32_t pin);
|
||||
void handlePrint(const char *text);
|
||||
void handleStartFirmwareUpdateScreen();
|
||||
|
||||
@@ -174,7 +174,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
|
||||
|
||||
cfg.pin_bl = ST7789_BL; // Pin number to which the backlight is connected
|
||||
cfg.invert = true; // true to invert the brightness of the backlight
|
||||
cfg.invert = false; // true to invert the brightness of the backlight
|
||||
// cfg.pwm_channel = 0;
|
||||
|
||||
_light_instance.config(cfg);
|
||||
@@ -196,7 +196,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
// cfg.freq = 2500000;
|
||||
|
||||
// I2C
|
||||
cfg.i2c_port = 1;
|
||||
cfg.i2c_port = TOUCH_I2C_PORT;
|
||||
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
|
||||
#ifdef SCREEN_TOUCH_USE_I2C1
|
||||
cfg.pin_sda = I2C_SDA1;
|
||||
@@ -205,7 +205,7 @@ class LGFX : public lgfx::LGFX_Device
|
||||
cfg.pin_sda = I2C_SDA;
|
||||
cfg.pin_scl = I2C_SCL;
|
||||
#endif
|
||||
cfg.freq = 400000;
|
||||
// cfg.freq = 400000;
|
||||
|
||||
_touch_instance.config(cfg);
|
||||
_panel_instance.setTouch(&_touch_instance);
|
||||
@@ -275,6 +275,9 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
#endif
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, LOW);
|
||||
#endif
|
||||
#ifndef M5STACK
|
||||
tft.setBrightness(128);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -284,6 +287,9 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
#endif
|
||||
#ifdef VTFT_CTRL
|
||||
digitalWrite(VTFT_CTRL, HIGH);
|
||||
#endif
|
||||
#ifndef M5STACK
|
||||
tft.setBrightness(0);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -294,6 +300,24 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
// Drop all other commands to device (we just update the buffer)
|
||||
}
|
||||
|
||||
bool TFTDisplay::hasTouch(void)
|
||||
{
|
||||
#ifndef M5STACK
|
||||
return tft.touch() != nullptr;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TFTDisplay::getTouch(int16_t *x, int16_t *y)
|
||||
{
|
||||
#ifndef M5STACK
|
||||
return tft.getTouch(x, y);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void TFTDisplay::setDetected(uint8_t detected)
|
||||
{
|
||||
(void)detected;
|
||||
@@ -322,12 +346,4 @@ bool TFTDisplay::connect()
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get touch coords from the display
|
||||
void TFTDisplay::getTouch(int *x, int *y)
|
||||
{
|
||||
#ifndef M5STACK
|
||||
tft.getTouch(x, y);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -22,14 +22,16 @@ class TFTDisplay : public OLEDDisplay
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void) override;
|
||||
|
||||
// Touch screen (static handlers)
|
||||
static bool hasTouch(void);
|
||||
static bool getTouch(int16_t *x, int16_t *y);
|
||||
|
||||
/**
|
||||
* shim to make the abstraction happy
|
||||
*
|
||||
*/
|
||||
void setDetected(uint8_t detected);
|
||||
|
||||
void getTouch(int *x, int *y);
|
||||
|
||||
protected:
|
||||
// the header size of the buffer used, e.g. for the SPI command header
|
||||
virtual int getBufferOffset(void) override { return 0; }
|
||||
|
||||
137
src/input/TouchScreenBase.cpp
Normal file
137
src/input/TouchScreenBase.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "TouchScreenBase.h"
|
||||
#include "main.h"
|
||||
|
||||
#ifndef TIME_LONG_PRESS
|
||||
#define TIME_LONG_PRESS 400
|
||||
#endif
|
||||
|
||||
// move a minimum distance over the screen to detect a "swipe"
|
||||
#ifndef TOUCH_THRESHOLD_X
|
||||
#define TOUCH_THRESHOLD_X 30
|
||||
#endif
|
||||
|
||||
#ifndef TOUCH_THRESHOLD_Y
|
||||
#define TOUCH_THRESHOLD_Y 20
|
||||
#endif
|
||||
|
||||
TouchScreenBase::TouchScreenBase(const char *name, uint16_t width, uint16_t height)
|
||||
: concurrency::OSThread(name), _display_width(width), _display_height(height), _first_x(0), _last_x(0), _first_y(0),
|
||||
_last_y(0), _start(0), _tapped(false), _originName(name)
|
||||
{
|
||||
}
|
||||
|
||||
void TouchScreenBase::init(bool hasTouch)
|
||||
{
|
||||
if (hasTouch) {
|
||||
LOG_INFO("TouchScreen initialized %d %d\n", TOUCH_THRESHOLD_X, TOUCH_THRESHOLD_Y);
|
||||
this->setInterval(100);
|
||||
} else {
|
||||
disable();
|
||||
this->setInterval(UINT_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t TouchScreenBase::runOnce()
|
||||
{
|
||||
TouchEvent e;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_NONE);
|
||||
|
||||
// process touch events
|
||||
int16_t x, y;
|
||||
bool touched = getTouch(x, y);
|
||||
if (touched) {
|
||||
hapticFeedback();
|
||||
this->setInterval(20);
|
||||
_last_x = x;
|
||||
_last_y = y;
|
||||
}
|
||||
if (touched != _touchedOld) {
|
||||
if (touched) {
|
||||
_state = TOUCH_EVENT_OCCURRED;
|
||||
_start = millis();
|
||||
_first_x = x;
|
||||
_first_y = y;
|
||||
} else {
|
||||
_state = TOUCH_EVENT_CLEARED;
|
||||
time_t duration = millis() - _start;
|
||||
x = _last_x;
|
||||
y = _last_y;
|
||||
this->setInterval(50);
|
||||
|
||||
// compute distance
|
||||
int16_t dx = x - _first_x;
|
||||
int16_t dy = y - _first_y;
|
||||
uint16_t adx = abs(dx);
|
||||
uint16_t ady = abs(dy);
|
||||
|
||||
// swipe horizontal
|
||||
if (adx > ady && adx > TOUCH_THRESHOLD_X) {
|
||||
if (0 > dx) { // swipe right to left
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_LEFT);
|
||||
LOG_DEBUG("action SWIPE: right to left\n");
|
||||
} else { // swipe left to right
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_RIGHT);
|
||||
LOG_DEBUG("action SWIPE: left to right\n");
|
||||
}
|
||||
}
|
||||
// swipe vertical
|
||||
else if (ady > adx && ady > TOUCH_THRESHOLD_Y) {
|
||||
if (0 > dy) { // swipe bottom to top
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_UP);
|
||||
LOG_DEBUG("action SWIPE: bottom to top\n");
|
||||
} else { // swipe top to bottom
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_DOWN);
|
||||
LOG_DEBUG("action SWIPE: top to bottom\n");
|
||||
}
|
||||
}
|
||||
// tap
|
||||
else {
|
||||
if (duration > 0 && duration < TIME_LONG_PRESS) {
|
||||
if (_tapped) {
|
||||
_tapped = false;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_DOUBLE_TAP);
|
||||
LOG_DEBUG("action DOUBLE TAP(%d/%d)\n", x, y);
|
||||
} else {
|
||||
_tapped = true;
|
||||
}
|
||||
} else {
|
||||
_tapped = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_touchedOld = touched;
|
||||
|
||||
// fire TAP event when no 2nd tap occured within time
|
||||
if (_tapped && (time_t(millis()) - _start) > TIME_LONG_PRESS - 50) {
|
||||
_tapped = false;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_TAP);
|
||||
LOG_DEBUG("action TAP(%d/%d)\n", _last_x, _last_y);
|
||||
}
|
||||
|
||||
// fire LONG_PRESS event without the need for release
|
||||
if (touched && (time_t(millis()) - _start) > TIME_LONG_PRESS) {
|
||||
// tricky: prevent reoccurring events and another touch event when releasing
|
||||
_start = millis() + 30000;
|
||||
e.touchEvent = static_cast<char>(TOUCH_ACTION_LONG_PRESS);
|
||||
LOG_DEBUG("action LONG PRESS(%d/%d)\n", _last_x, _last_y);
|
||||
}
|
||||
|
||||
if (e.touchEvent != TOUCH_ACTION_NONE) {
|
||||
e.source = this->_originName;
|
||||
e.x = _last_x;
|
||||
e.y = _last_y;
|
||||
onEvent(e);
|
||||
}
|
||||
|
||||
return interval;
|
||||
}
|
||||
|
||||
void TouchScreenBase::hapticFeedback()
|
||||
{
|
||||
#ifdef T_WATCH_S3
|
||||
drv.setWaveform(0, 75);
|
||||
drv.setWaveform(1, 0); // end waveform
|
||||
drv.go();
|
||||
#endif
|
||||
}
|
||||
55
src/input/TouchScreenBase.h
Normal file
55
src/input/TouchScreenBase.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "concurrency/OSThread.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
typedef struct _TouchEvent {
|
||||
const char *source;
|
||||
char touchEvent;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
} TouchEvent;
|
||||
|
||||
class TouchScreenBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit TouchScreenBase(const char *name, uint16_t width, uint16_t height);
|
||||
void init(bool hasTouch);
|
||||
|
||||
protected:
|
||||
enum TouchScreenBaseStateType { TOUCH_EVENT_OCCURRED, TOUCH_EVENT_CLEARED };
|
||||
|
||||
enum TouchScreenBaseEventType {
|
||||
TOUCH_ACTION_NONE,
|
||||
TOUCH_ACTION_UP,
|
||||
TOUCH_ACTION_DOWN,
|
||||
TOUCH_ACTION_LEFT,
|
||||
TOUCH_ACTION_RIGHT,
|
||||
TOUCH_ACTION_TAP,
|
||||
TOUCH_ACTION_DOUBLE_TAP,
|
||||
TOUCH_ACTION_LONG_PRESS
|
||||
};
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
virtual bool getTouch(int16_t &x, int16_t &y) = 0;
|
||||
virtual void onEvent(const TouchEvent &event) = 0;
|
||||
|
||||
volatile TouchScreenBaseStateType _state = TOUCH_EVENT_CLEARED;
|
||||
volatile TouchScreenBaseEventType _action = TOUCH_ACTION_NONE;
|
||||
void hapticFeedback();
|
||||
|
||||
protected:
|
||||
uint16_t _display_width;
|
||||
uint16_t _display_height;
|
||||
|
||||
private:
|
||||
bool _touchedOld = false; // previous touch state
|
||||
int16_t _first_x, _last_x; // horizontal swipe direction
|
||||
int16_t _first_y, _last_y; // vertical swipe direction
|
||||
time_t _start; // for LONG_PRESS
|
||||
bool _tapped; // for DOUBLE_TAP
|
||||
|
||||
const char *_originName;
|
||||
};
|
||||
68
src/input/TouchScreenImpl1.cpp
Normal file
68
src/input/TouchScreenImpl1.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include "TouchScreenImpl1.h"
|
||||
#include "InputBroker.h"
|
||||
#include "configuration.h"
|
||||
|
||||
TouchScreenImpl1 *touchScreenImpl1;
|
||||
|
||||
TouchScreenImpl1::TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *))
|
||||
: TouchScreenBase("touchscreen1", width, height), _getTouch(getTouch)
|
||||
{
|
||||
}
|
||||
|
||||
void TouchScreenImpl1::init()
|
||||
{
|
||||
#if !HAS_TOUCHSCREEN
|
||||
TouchScreenBase::init(false);
|
||||
return;
|
||||
#else
|
||||
TouchScreenBase::init(true);
|
||||
inputBroker->registerSource(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool TouchScreenImpl1::getTouch(int16_t &x, int16_t &y)
|
||||
{
|
||||
return _getTouch(&x, &y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief forward touchscreen event
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* The touchscreen events are translated to input events and reversed
|
||||
*/
|
||||
void TouchScreenImpl1::onEvent(const TouchEvent &event)
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = event.source;
|
||||
switch (event.touchEvent) {
|
||||
case TOUCH_ACTION_LEFT: {
|
||||
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);
|
||||
break;
|
||||
}
|
||||
case TOUCH_ACTION_RIGHT: {
|
||||
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT);
|
||||
break;
|
||||
}
|
||||
case TOUCH_ACTION_UP: {
|
||||
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP);
|
||||
break;
|
||||
}
|
||||
case TOUCH_ACTION_DOWN: {
|
||||
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
|
||||
break;
|
||||
}
|
||||
case TOUCH_ACTION_DOUBLE_TAP: {
|
||||
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
|
||||
break;
|
||||
}
|
||||
case TOUCH_ACTION_LONG_PRESS: {
|
||||
e.inputEvent = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_CANCEL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
17
src/input/TouchScreenImpl1.h
Normal file
17
src/input/TouchScreenImpl1.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "TouchScreenBase.h"
|
||||
|
||||
class TouchScreenImpl1 : public TouchScreenBase
|
||||
{
|
||||
public:
|
||||
TouchScreenImpl1(uint16_t width, uint16_t height, bool (*getTouch)(int16_t *, int16_t *));
|
||||
void init(void);
|
||||
|
||||
protected:
|
||||
virtual bool getTouch(int16_t &x, int16_t &y);
|
||||
virtual void onEvent(const TouchEvent &event);
|
||||
|
||||
bool (*_getTouch)(int16_t *, int16_t *);
|
||||
};
|
||||
|
||||
extern TouchScreenImpl1 *touchScreenImpl1;
|
||||
78
src/input/TrackballInterruptBase.cpp
Normal file
78
src/input/TrackballInterruptBase.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include "TrackballInterruptBase.h"
|
||||
#include "configuration.h"
|
||||
|
||||
TrackballInterruptBase::TrackballInterruptBase(const char *name)
|
||||
{
|
||||
this->_originName = name;
|
||||
}
|
||||
|
||||
void TrackballInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress,
|
||||
char eventDown, char eventUp, char eventLeft, char eventRight, char eventPressed,
|
||||
void (*onIntDown)(), void (*onIntUp)(), void (*onIntLeft)(), void (*onIntRight)(),
|
||||
void (*onIntPress)())
|
||||
{
|
||||
this->_pinDown = pinDown;
|
||||
this->_pinUp = pinUp;
|
||||
this->_pinLeft = pinLeft;
|
||||
this->_pinRight = pinRight;
|
||||
this->_eventDown = eventDown;
|
||||
this->_eventUp = eventUp;
|
||||
this->_eventLeft = eventLeft;
|
||||
this->_eventRight = eventRight;
|
||||
this->_eventPressed = eventPressed;
|
||||
|
||||
pinMode(pinPress, INPUT_PULLUP);
|
||||
pinMode(this->_pinDown, INPUT_PULLUP);
|
||||
pinMode(this->_pinUp, INPUT_PULLUP);
|
||||
pinMode(this->_pinLeft, INPUT_PULLUP);
|
||||
pinMode(this->_pinRight, INPUT_PULLUP);
|
||||
|
||||
attachInterrupt(pinPress, onIntPress, RISING);
|
||||
attachInterrupt(this->_pinDown, onIntDown, RISING);
|
||||
attachInterrupt(this->_pinUp, onIntUp, RISING);
|
||||
attachInterrupt(this->_pinLeft, onIntLeft, RISING);
|
||||
attachInterrupt(this->_pinRight, onIntRight, RISING);
|
||||
|
||||
LOG_DEBUG("Trackball GPIO initialized (%d, %d, %d, %d, %d)\n", this->_pinUp, this->_pinDown, this->_pinLeft, this->_pinRight,
|
||||
pinPress);
|
||||
}
|
||||
|
||||
void TrackballInterruptBase::intPressHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
e.inputEvent = this->_eventPressed;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
void TrackballInterruptBase::intDownHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
e.inputEvent = this->_eventDown;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
void TrackballInterruptBase::intUpHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
e.inputEvent = this->_eventUp;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
void TrackballInterruptBase::intLeftHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
e.inputEvent = this->_eventLeft;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
void TrackballInterruptBase::intRightHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
e.inputEvent = this->_eventRight;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
30
src/input/TrackballInterruptBase.h
Normal file
30
src/input/TrackballInterruptBase.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "InputBroker.h"
|
||||
#include "mesh/NodeDB.h"
|
||||
|
||||
class TrackballInterruptBase : public Observable<const InputEvent *>
|
||||
{
|
||||
public:
|
||||
explicit TrackballInterruptBase(const char *name);
|
||||
void init(uint8_t pinDown, uint8_t pinUp, uint8_t pinLeft, uint8_t pinRight, uint8_t pinPress, char eventDown, char eventUp,
|
||||
char eventLeft, char eventRight, char eventPressed, void (*onIntDown)(), void (*onIntUp)(), void (*onIntLeft)(),
|
||||
void (*onIntRight)(), void (*onIntPress)());
|
||||
void intPressHandler();
|
||||
void intDownHandler();
|
||||
void intUpHandler();
|
||||
void intLeftHandler();
|
||||
void intRightHandler();
|
||||
|
||||
private:
|
||||
uint8_t _pinDown = 0;
|
||||
uint8_t _pinUp = 0;
|
||||
uint8_t _pinLeft = 0;
|
||||
uint8_t _pinRight = 0;
|
||||
char _eventDown = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
char _eventUp = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
char _eventLeft = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
char _eventRight = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
char _eventPressed = meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE;
|
||||
const char *_originName;
|
||||
};
|
||||
54
src/input/TrackballInterruptImpl1.cpp
Normal file
54
src/input/TrackballInterruptImpl1.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "TrackballInterruptImpl1.h"
|
||||
#include "InputBroker.h"
|
||||
#include "configuration.h"
|
||||
|
||||
TrackballInterruptImpl1 *trackballInterruptImpl1;
|
||||
|
||||
TrackballInterruptImpl1::TrackballInterruptImpl1() : TrackballInterruptBase("trackball1") {}
|
||||
|
||||
void TrackballInterruptImpl1::init()
|
||||
{
|
||||
#if !HAS_TRACKBALL
|
||||
// Input device is disabled.
|
||||
return;
|
||||
#else
|
||||
uint8_t pinUp = TB_UP;
|
||||
uint8_t pinDown = TB_DOWN;
|
||||
uint8_t pinLeft = TB_LEFT;
|
||||
uint8_t pinRight = TB_RIGHT;
|
||||
uint8_t pinPress = TB_PRESS;
|
||||
|
||||
char eventDown = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_DOWN);
|
||||
char eventUp = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_UP);
|
||||
char eventLeft = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT);
|
||||
char eventRight = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT);
|
||||
char eventPressed = static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT);
|
||||
|
||||
TrackballInterruptBase::init(pinDown, pinUp, pinLeft, pinRight, pinPress, eventDown, eventUp, eventLeft, eventRight,
|
||||
eventPressed, TrackballInterruptImpl1::handleIntDown, TrackballInterruptImpl1::handleIntUp,
|
||||
TrackballInterruptImpl1::handleIntLeft, TrackballInterruptImpl1::handleIntRight,
|
||||
TrackballInterruptImpl1::handleIntPressed);
|
||||
inputBroker->registerSource(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TrackballInterruptImpl1::handleIntDown()
|
||||
{
|
||||
trackballInterruptImpl1->intDownHandler();
|
||||
}
|
||||
void TrackballInterruptImpl1::handleIntUp()
|
||||
{
|
||||
trackballInterruptImpl1->intUpHandler();
|
||||
}
|
||||
void TrackballInterruptImpl1::handleIntLeft()
|
||||
{
|
||||
trackballInterruptImpl1->intLeftHandler();
|
||||
}
|
||||
void TrackballInterruptImpl1::handleIntRight()
|
||||
{
|
||||
trackballInterruptImpl1->intRightHandler();
|
||||
}
|
||||
void TrackballInterruptImpl1::handleIntPressed()
|
||||
{
|
||||
trackballInterruptImpl1->intPressHandler();
|
||||
}
|
||||
16
src/input/TrackballInterruptImpl1.h
Normal file
16
src/input/TrackballInterruptImpl1.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "TrackballInterruptBase.h"
|
||||
|
||||
class TrackballInterruptImpl1 : public TrackballInterruptBase
|
||||
{
|
||||
public:
|
||||
TrackballInterruptImpl1();
|
||||
void init();
|
||||
static void handleIntDown();
|
||||
static void handleIntUp();
|
||||
static void handleIntLeft();
|
||||
static void handleIntRight();
|
||||
static void handleIntPressed();
|
||||
};
|
||||
|
||||
extern TrackballInterruptImpl1 *trackballInterruptImpl1;
|
||||
@@ -23,7 +23,7 @@ void UpDownInterruptBase::init(uint8_t pinDown, uint8_t pinUp, uint8_t pinPress,
|
||||
attachInterrupt(this->_pinDown, onIntDown, RISING);
|
||||
attachInterrupt(this->_pinUp, onIntUp, RISING);
|
||||
|
||||
LOG_DEBUG("GPIO initialized (%d, %d, %d)\n", this->_pinDown, this->_pinUp, pinPress);
|
||||
LOG_DEBUG("Up/down/press GPIO initialized (%d, %d, %d)\n", this->_pinUp, this->_pinDown, pinPress);
|
||||
}
|
||||
|
||||
void UpDownInterruptBase::intPressHandler()
|
||||
|
||||
@@ -7,7 +7,7 @@ CardKbI2cImpl::CardKbI2cImpl() : KbI2cBase("cardKB") {}
|
||||
|
||||
void CardKbI2cImpl::init()
|
||||
{
|
||||
if (cardkb_found.address != CARDKB_ADDR) {
|
||||
if (cardkb_found.address != CARDKB_ADDR && cardkb_found.address != TDECK_KB_ADDR) {
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void write_to_14004(const TwoWire * i2cBus, uint8_t reg, uint8_t data)
|
||||
|
||||
int32_t KbI2cBase::runOnce()
|
||||
{
|
||||
if (cardkb_found.address != CARDKB_ADDR) {
|
||||
if (cardkb_found.address != CARDKB_ADDR && cardkb_found.address != TDECK_KB_ADDR) {
|
||||
// Input device is not detected.
|
||||
return INT32_MAX;
|
||||
}
|
||||
@@ -85,9 +85,9 @@ int32_t KbI2cBase::runOnce()
|
||||
e.kbchar = PrintDataBuf;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
} else {
|
||||
// m5 cardkb
|
||||
i2cBus->requestFrom(CARDKB_ADDR, 1);
|
||||
} else if (kb_model == 0x00 || kb_model == 0x10) {
|
||||
// m5 cardkb and T-Deck
|
||||
i2cBus->requestFrom(kb_model == 0x00 ? CARDKB_ADDR : TDECK_KB_ADDR, 1);
|
||||
|
||||
while (i2cBus->available()) {
|
||||
char c = i2cBus->read();
|
||||
@@ -132,6 +132,8 @@ int32_t KbI2cBase::runOnce()
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("Unknown kb_model 0x%02x\n", kb_model);
|
||||
}
|
||||
return 500;
|
||||
return 300;
|
||||
}
|
||||
|
||||
23
src/main.cpp
23
src/main.cpp
@@ -96,7 +96,7 @@ ScanI2C::DeviceAddress screen_found = ScanI2C::ADDRESS_NONE;
|
||||
|
||||
// The I2C address of the cardkb or RAK14004 (if found)
|
||||
ScanI2C::DeviceAddress cardkb_found = ScanI2C::ADDRESS_NONE;
|
||||
// 0x02 for RAK14004 and 0x00 for cardkb
|
||||
// 0x02 for RAK14004, 0x00 for cardkb, 0x10 for T-Deck
|
||||
uint8_t kb_model;
|
||||
|
||||
// The I2C address of the RTC Module (if found)
|
||||
@@ -300,6 +300,15 @@ void setup()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef T_DECK
|
||||
// enable keyboard
|
||||
pinMode(KB_POWERON, OUTPUT);
|
||||
digitalWrite(KB_POWERON, HIGH);
|
||||
// There needs to be a delay after power on, give LILYGO-KEYBOARD some startup time
|
||||
// otherwise keyboard and touch screen will not work
|
||||
delay(800);
|
||||
#endif
|
||||
|
||||
// Currently only the tbeam has a PMU
|
||||
// PMU initialization needs to be placed before i2c scanning
|
||||
power = new Power();
|
||||
@@ -372,8 +381,15 @@ void setup()
|
||||
kb_model = 0x02;
|
||||
break;
|
||||
case ScanI2C::DeviceType::CARDKB:
|
||||
kb_model = 0x00;
|
||||
break;
|
||||
case ScanI2C::DeviceType::TDECKKB:
|
||||
// assign an arbitrary value to distinguish from other models
|
||||
kb_model = 0x10;
|
||||
break;
|
||||
default:
|
||||
// use this as default since it's also just zero
|
||||
LOG_WARN("kb_info.type is unknown(0x%02x), setting kb_model=0x00\n", kb_info.type);
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
@@ -458,6 +474,11 @@ void setup()
|
||||
#ifdef ARCH_NRF52
|
||||
nrf52Setup();
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_RP2040
|
||||
rp2040Setup();
|
||||
#endif
|
||||
|
||||
// We do this as early as possible because this loads preferences from flash
|
||||
// but we need to do this after main cpu iniot (esp32setup), because we need the random seed set
|
||||
nodeDB.init();
|
||||
|
||||
@@ -68,7 +68,7 @@ extern uint32_t serialSinceMsec;
|
||||
// This will suppress the current delay and instead try to run ASAP.
|
||||
extern bool runASAP;
|
||||
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), clearBonds();
|
||||
void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds();
|
||||
|
||||
meshtastic_DeviceMetadata getDeviceMetadata();
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ void NodeDB::installDefaultConfig()
|
||||
config.has_bluetooth = true;
|
||||
config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL;
|
||||
|
||||
config.lora.sx126x_rx_boosted_gain = false;
|
||||
config.lora.sx126x_rx_boosted_gain = true;
|
||||
config.lora.tx_enabled =
|
||||
true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
||||
config.lora.override_duty_cycle = false;
|
||||
|
||||
@@ -53,7 +53,9 @@ typedef enum _meshtastic_AdminMessage_ModuleConfigType {
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_AdminMessage_ModuleConfigType_AUDIO_CONFIG = 7,
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG = 8
|
||||
meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG = 8,
|
||||
/* TODO: REPLACE */
|
||||
meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG = 10
|
||||
} meshtastic_AdminMessage_ModuleConfigType;
|
||||
|
||||
/* Struct definitions */
|
||||
@@ -172,8 +174,8 @@ extern "C" {
|
||||
#define _meshtastic_AdminMessage_ConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ConfigType)(meshtastic_AdminMessage_ConfigType_BLUETOOTH_CONFIG+1))
|
||||
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_MIN meshtastic_AdminMessage_ModuleConfigType_MQTT_CONFIG
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_REMOTEHARDWARE_CONFIG+1))
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_MAX meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG
|
||||
#define _meshtastic_AdminMessage_ModuleConfigType_ARRAYSIZE ((meshtastic_AdminMessage_ModuleConfigType)(meshtastic_AdminMessage_ModuleConfigType_AMBIENTLIGHTING_CONFIG+1))
|
||||
|
||||
#define meshtastic_AdminMessage_payload_variant_get_config_request_ENUMTYPE meshtastic_AdminMessage_ConfigType
|
||||
#define meshtastic_AdminMessage_payload_variant_get_module_config_request_ENUMTYPE meshtastic_AdminMessage_ModuleConfigType
|
||||
|
||||
@@ -59,6 +59,8 @@ typedef enum _meshtastic_HardwareModel {
|
||||
meshtastic_HardwareModel_TLORA_T3_S3 = 16,
|
||||
/* B&Q Consulting Nano G1 Explorer: https://wiki.uniteng.com/en/meshtastic/nano-g1-explorer */
|
||||
meshtastic_HardwareModel_NANO_G1_EXPLORER = 17,
|
||||
/* B&Q Consulting Nano G2 Ultra: https://wiki.uniteng.com/en/meshtastic/nano-g2-ultra */
|
||||
meshtastic_HardwareModel_NANO_G2_ULTRA = 18,
|
||||
/* B&Q Consulting Station Edition G1: https://uniteng.com/wiki/doku.php?id=meshtastic:station */
|
||||
meshtastic_HardwareModel_STATION_G1 = 25,
|
||||
/* RAK11310 (RP2040 + SX1262) */
|
||||
@@ -228,9 +230,9 @@ typedef enum _meshtastic_Routing_Error {
|
||||
to make sure that critical packets are sent ASAP.
|
||||
In the case of meshtastic that means we want to send protocol acks as soon as possible
|
||||
(to prevent unneeded retransmissions), we want routing messages to be sent next,
|
||||
then messages marked as reliable and finally ‘background’ packets like periodic position updates.
|
||||
then messages marked as reliable and finally 'background' packets like periodic position updates.
|
||||
So I bit the bullet and implemented a new (internal - not sent over the air)
|
||||
field in MeshPacket called ‘priority’.
|
||||
field in MeshPacket called 'priority'.
|
||||
And the transmission queue in the router object is now a priority queue. */
|
||||
typedef enum _meshtastic_MeshPacket_Priority {
|
||||
/* Treated as Priority.DEFAULT */
|
||||
|
||||
@@ -54,8 +54,6 @@ typedef enum _meshtastic_PortNum {
|
||||
/* Audio Payloads.
|
||||
Encapsulated codec2 packets. On 2.4 GHZ Bandwidths only for now */
|
||||
meshtastic_PortNum_AUDIO_APP = 9,
|
||||
/* Payloads for clients with a network connection proxying MQTT pub/sub to the device */
|
||||
meshtastic_PortNum_MQTT_CLIENT_PROXY_APP = 10,
|
||||
/* Provides a 'ping' service that replies to any packet it receives.
|
||||
Also serves as a small example module. */
|
||||
meshtastic_PortNum_REPLY_APP = 32,
|
||||
|
||||
@@ -164,12 +164,21 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) ||
|
||||
(event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT))) {
|
||||
LOG_DEBUG("Canned message event (%x)\n", event->kbchar);
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
// tweak for left/right events generated via trackball/touch with empty kbchar
|
||||
if (!event->kbchar) {
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||
this->payload = 0xb4;
|
||||
this->destSelect = true;
|
||||
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||
this->payload = 0xb7;
|
||||
this->destSelect = true;
|
||||
}
|
||||
} else {
|
||||
// pass the pressed key
|
||||
this->payload = event->kbchar;
|
||||
this->lastTouchMillis = millis();
|
||||
validEvent = true;
|
||||
}
|
||||
this->lastTouchMillis = millis();
|
||||
validEvent = true;
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(ANYKEY)) {
|
||||
LOG_DEBUG("Canned message event any key pressed\n");
|
||||
@@ -225,7 +234,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
(this->runState == CANNED_MESSAGE_RUN_STATE_INACTIVE)) {
|
||||
return INT32_MAX;
|
||||
}
|
||||
LOG_DEBUG("Check status\n");
|
||||
// LOG_DEBUG("Check status\n");
|
||||
UIFrameEvent e = {false, true};
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE) {
|
||||
// TODO: might have some feedback of sendig state
|
||||
@@ -300,8 +309,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_ACTIVE;
|
||||
LOG_DEBUG("MOVE DOWN (%d):%s\n", this->currentMessageIndex, this->getCurrentMessage());
|
||||
}
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
e.frameChanged = true;
|
||||
} else if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT || this->runState == CANNED_MESSAGE_RUN_STATE_ACTIVE) {
|
||||
switch (this->payload) {
|
||||
case 0xb4: // left
|
||||
if (this->destSelect) {
|
||||
@@ -347,38 +355,49 @@ int32_t CannedMessageModule::runOnce()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x08: // backspace
|
||||
if (this->freetext.length() > 0) {
|
||||
if (this->cursor == this->freetext.length()) {
|
||||
this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
|
||||
} else {
|
||||
this->freetext = this->freetext.substring(0, this->cursor - 1) +
|
||||
this->freetext.substring(this->cursor, this->freetext.length());
|
||||
}
|
||||
this->cursor--;
|
||||
}
|
||||
break;
|
||||
case 0x09: // tab
|
||||
if (this->destSelect) {
|
||||
this->destSelect = false;
|
||||
} else {
|
||||
this->destSelect = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (this->cursor == this->freetext.length()) {
|
||||
this->freetext += this->payload;
|
||||
} else {
|
||||
this->freetext =
|
||||
this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor);
|
||||
}
|
||||
this->cursor += 1;
|
||||
if (this->freetext.length() > meshtastic_Constants_DATA_PAYLOAD_LEN) {
|
||||
this->cursor = meshtastic_Constants_DATA_PAYLOAD_LEN;
|
||||
this->freetext = this->freetext.substring(0, meshtastic_Constants_DATA_PAYLOAD_LEN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
e.frameChanged = true;
|
||||
switch (this->payload) {
|
||||
case 0x08: // backspace
|
||||
if (this->freetext.length() > 0) {
|
||||
if (this->cursor == this->freetext.length()) {
|
||||
this->freetext = this->freetext.substring(0, this->freetext.length() - 1);
|
||||
} else {
|
||||
this->freetext = this->freetext.substring(0, this->cursor - 1) +
|
||||
this->freetext.substring(this->cursor, this->freetext.length());
|
||||
}
|
||||
this->cursor--;
|
||||
}
|
||||
break;
|
||||
case 0x09: // tab
|
||||
if (this->destSelect) {
|
||||
this->destSelect = false;
|
||||
} else {
|
||||
this->destSelect = true;
|
||||
}
|
||||
break;
|
||||
case 0xb4: // left
|
||||
case 0xb7: // right
|
||||
// already handled above
|
||||
break;
|
||||
default:
|
||||
if (this->cursor == this->freetext.length()) {
|
||||
this->freetext += this->payload;
|
||||
} else {
|
||||
this->freetext =
|
||||
this->freetext.substring(0, this->cursor) + this->payload + this->freetext.substring(this->cursor);
|
||||
}
|
||||
this->cursor += 1;
|
||||
if (this->freetext.length() > meshtastic_Constants_DATA_PAYLOAD_LEN) {
|
||||
this->cursor = meshtastic_Constants_DATA_PAYLOAD_LEN;
|
||||
this->freetext = this->freetext.substring(0, meshtastic_Constants_DATA_PAYLOAD_LEN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this->lastTouchMillis = millis();
|
||||
this->notifyObservers(&e);
|
||||
@@ -406,6 +425,11 @@ const char *CannedMessageModule::getNextMessage()
|
||||
{
|
||||
return this->messages[this->getNextIndex()];
|
||||
}
|
||||
const char *CannedMessageModule::getMessageByIndex(int index)
|
||||
{
|
||||
return (index >= 0 && index < this->messagesCount) ? this->messages[index] : "";
|
||||
}
|
||||
|
||||
const char *CannedMessageModule::getNodeName(NodeNum node)
|
||||
{
|
||||
if (node == NODENUM_BROADCAST) {
|
||||
@@ -482,12 +506,31 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawStringf(0 + x, 0 + y, buffer, "To: %s", cannedMessageModule->getNodeName(this->dest));
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
|
||||
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
|
||||
display->setColor(WHITE);
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
|
||||
int lines = (display->getHeight() / FONT_HEIGHT_SMALL) - 1;
|
||||
if (lines == 3) {
|
||||
// static (old) behavior for small displays
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL, cannedMessageModule->getPrevMessage());
|
||||
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 2, cannedMessageModule->getCurrentMessage());
|
||||
display->setColor(WHITE);
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * 3, cannedMessageModule->getNextMessage());
|
||||
} else {
|
||||
// use entire display height for larger displays
|
||||
int topMsg = (messagesCount > lines && currentMessageIndex >= lines - 1) ? currentMessageIndex - lines + 2 : 0;
|
||||
for (int i = 0; i < std::min(messagesCount, lines); i++) {
|
||||
if (i == currentMessageIndex - topMsg) {
|
||||
display->fillRect(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), x + display->getWidth(),
|
||||
y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1), cannedMessageModule->getCurrentMessage());
|
||||
display->setColor(WHITE);
|
||||
} else {
|
||||
display->drawString(0 + x, 0 + y + FONT_HEIGHT_SMALL * (i + 1),
|
||||
cannedMessageModule->getMessageByIndex(topMsg + i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
const char *getCurrentMessage();
|
||||
const char *getPrevMessage();
|
||||
const char *getNextMessage();
|
||||
const char *getMessageByIndex(int index);
|
||||
const char *getNodeName(NodeNum node);
|
||||
bool shouldDraw();
|
||||
void eventUp();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "configuration.h"
|
||||
#include "input/InputBroker.h"
|
||||
#include "input/RotaryEncoderInterruptImpl1.h"
|
||||
#include "input/TrackballInterruptImpl1.h"
|
||||
#include "input/UpDownInterruptImpl1.h"
|
||||
#include "input/cardKbI2cImpl.h"
|
||||
#include "modules/AdminModule.h"
|
||||
@@ -24,7 +25,7 @@
|
||||
#include "modules/esp32/AudioModule.h"
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#endif
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "modules/RangeTestModule.h"
|
||||
#if (defined(ARCH_ESP32) || defined(ARCH_NRF52)) && !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||
@@ -60,6 +61,10 @@ void setupModules()
|
||||
cardKbI2cImpl = new CardKbI2cImpl();
|
||||
cardKbI2cImpl->init();
|
||||
#endif
|
||||
#if HAS_TRACKBALL
|
||||
trackballInterruptImpl1 = new TrackballInterruptImpl1();
|
||||
trackballInterruptImpl1->init();
|
||||
#endif
|
||||
#if HAS_SCREEN
|
||||
cannedMessageModule = new CannedMessageModule();
|
||||
#endif
|
||||
@@ -81,7 +86,7 @@ void setupModules()
|
||||
|
||||
storeForwardModule = new StoreForwardModule();
|
||||
#endif
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040)
|
||||
externalNotificationModule = new ExternalNotificationModule();
|
||||
new RangeTestModule();
|
||||
#endif
|
||||
@@ -92,4 +97,4 @@ void setupModules()
|
||||
// NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra
|
||||
// acks
|
||||
routingModule = new RoutingModule();
|
||||
}
|
||||
}
|
||||
@@ -52,11 +52,22 @@ bool PositionModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mes
|
||||
|
||||
nodeDB.updatePosition(getFrom(&mp), p);
|
||||
|
||||
// Only respond to location requests on the channel where we broadcast location.
|
||||
if (channels.getByIndex(mp.channel).role == meshtastic_Channel_Role_PRIMARY) {
|
||||
ignoreRequest = false;
|
||||
} else {
|
||||
ignoreRequest = true;
|
||||
}
|
||||
|
||||
return false; // Let others look at this message also if they want
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *PositionModule::allocReply()
|
||||
{
|
||||
if (ignoreRequest) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *node = service.refreshLocalMeshNode(); // should guarantee there is now a position
|
||||
assert(node->has_position);
|
||||
|
||||
|
||||
@@ -249,7 +249,7 @@ ProcessMessage SerialModuleRadio::handleReceived(const meshtastic_MeshPacket &mp
|
||||
|
||||
if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT ||
|
||||
moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_SIMPLE) {
|
||||
serialPrint->printf("%s", p.payload.bytes);
|
||||
serialPrint->write(p.payload.bytes, p.payload.size);
|
||||
} else if (moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_TEXTMSG) {
|
||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(getFrom(&mp));
|
||||
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
||||
|
||||
@@ -164,6 +164,8 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
|
||||
#endif
|
||||
{
|
||||
if (moduleConfig.mqtt.enabled) {
|
||||
LOG_DEBUG("Initializing MQTT\n");
|
||||
|
||||
assert(!mqtt);
|
||||
mqtt = this;
|
||||
|
||||
@@ -181,6 +183,14 @@ MQTT::MQTT() : concurrency::OSThread("mqtt"), mqttQueue(MAX_MQTT_QUEUE)
|
||||
if (!moduleConfig.mqtt.proxy_to_client_enabled)
|
||||
pubSub.setCallback(mqttCallback);
|
||||
#endif
|
||||
|
||||
if (moduleConfig.mqtt.proxy_to_client_enabled) {
|
||||
LOG_INFO("MQTT configured to use client proxy...\n");
|
||||
enabled = true;
|
||||
runASAP = true;
|
||||
reconnectCount = 0;
|
||||
publishStatus();
|
||||
}
|
||||
// preflightSleepObserver.observe(&preflightSleep);
|
||||
} else {
|
||||
disable();
|
||||
@@ -597,6 +607,15 @@ std::string MQTT::meshPacketToJson(meshtastic_MeshPacket *mp)
|
||||
if (int(decoded->sats_in_view)) {
|
||||
msgPayload["sats_in_view"] = new JSONValue((int)decoded->sats_in_view);
|
||||
}
|
||||
if ((int)decoded->PDOP) {
|
||||
msgPayload["PDOP"] = new JSONValue((int)decoded->PDOP);
|
||||
}
|
||||
if ((int)decoded->HDOP) {
|
||||
msgPayload["HDOP"] = new JSONValue((int)decoded->HDOP);
|
||||
}
|
||||
if ((int)decoded->VDOP) {
|
||||
msgPayload["VDOP"] = new JSONValue((int)decoded->VDOP);
|
||||
}
|
||||
jsonObj["payload"] = new JSONValue(msgPayload);
|
||||
} else {
|
||||
LOG_ERROR("Error decoding protobuf for position message!\n");
|
||||
|
||||
@@ -27,4 +27,12 @@ void getMacAddr(uint8_t *dmac)
|
||||
dmac[2] = src.id[4];
|
||||
dmac[1] = src.id[3];
|
||||
dmac[0] = src.id[2];
|
||||
}
|
||||
|
||||
void rp2040Setup()
|
||||
{
|
||||
/* Sets a random seed to make sure we get different random numbers on each boot.
|
||||
Taken from CPU cycle counter and ROSC oscillator, so should be pretty random.
|
||||
*/
|
||||
randomSeed(rp2040.hwrand32());
|
||||
}
|
||||
18
variants/nano-g2-ultra/platformio.ini
Normal file
18
variants/nano-g2-ultra/platformio.ini
Normal file
@@ -0,0 +1,18 @@
|
||||
; First prototype eink/nrf52840/sx1262 device
|
||||
[env:nano-g2-ultra]
|
||||
extends = nrf52840_base
|
||||
board = nano-g2-ultra
|
||||
debug_tool = jlink
|
||||
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library - NOTE: WE NOT LONGER USE TFT_eSPI, it was for an earlier version of the TTGO eink screens
|
||||
# -DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
|
||||
# add -DCFG_SYSVIEW if you want to use the Segger systemview tool for OS profiling.
|
||||
build_flags = ${nrf52840_base.build_flags} -Ivariants/nano-g2-ultra -D NANO_G2_ULTRA
|
||||
-L "${platformio.libdeps_dir}/${this.__env__}/BSEC2 Software Library/src/cortex-m4/fpv4-sp-d16-hard"
|
||||
build_src_filter = ${nrf52_base.build_src_filter} +<../variants/nano-g2-ultra>
|
||||
lib_deps =
|
||||
${nrf52840_base.lib_deps}
|
||||
adafruit/Adafruit BusIO@^1.13.2
|
||||
lewisxhe/PCF8563_Library@^1.0.1
|
||||
;upload_protocol = fs
|
||||
36
variants/nano-g2-ultra/variant.cpp
Normal file
36
variants/nano-g2-ultra/variant.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "variant.h"
|
||||
#include "nrf.h"
|
||||
#include "wiring_constants.h"
|
||||
#include "wiring_digital.h"
|
||||
|
||||
const uint32_t g_ADigitalPinMap[] = {
|
||||
// P0 - pins 0 and 1 are hardwired for xtal and should never be enabled
|
||||
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
||||
|
||||
// P1
|
||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};
|
||||
|
||||
void initVariant()
|
||||
{
|
||||
// Nothing need to be inited for now
|
||||
}
|
||||
197
variants/nano-g2-ultra/variant.h
Normal file
197
variants/nano-g2-ultra/variant.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
Copyright (c) 2014-2015 Arduino LLC. All right reserved.
|
||||
Copyright (c) 2016 Sandeep Mistry All right reserved.
|
||||
Copyright (c) 2018, Adafruit Industries (adafruit.com)
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _VARIANT_Nano_G2_
|
||||
#define _VARIANT_Nano_G2_
|
||||
|
||||
/** Master clock frequency */
|
||||
#define VARIANT_MCK (64000000ul)
|
||||
|
||||
#define USE_LFXO // Board uses 32khz crystal for LF
|
||||
//#define USE_LFRC // Board uses 32khz RC for LF
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "WVariant.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// Number of pins defined in PinDescription array
|
||||
#define PINS_COUNT (48)
|
||||
#define NUM_DIGITAL_PINS (48)
|
||||
#define NUM_ANALOG_INPUTS (1)
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED1 (-1)
|
||||
#define PIN_LED2 (-1)
|
||||
#define PIN_LED3 (-1)
|
||||
|
||||
#define LED_RED PIN_LED3
|
||||
#define LED_BLUE PIN_LED1
|
||||
#define LED_GREEN PIN_LED2
|
||||
|
||||
#define LED_BUILTIN LED_BLUE
|
||||
#define LED_CONN PIN_GREEN
|
||||
|
||||
#define LED_STATE_ON 0 // State when LED is lit
|
||||
//#define LED_INVERTED 1
|
||||
|
||||
/*
|
||||
* Buttons
|
||||
*/
|
||||
#define PIN_BUTTON1 (32 + 6)
|
||||
|
||||
#define EXT_NOTIFY_OUT (0 + 4) // Default pin to use for Ext Notify Module.
|
||||
|
||||
/*
|
||||
* Analog pins
|
||||
*/
|
||||
#define PIN_A4 (0 + 2) // Battery ADC
|
||||
|
||||
#define BATTERY_PIN PIN_A4
|
||||
|
||||
static const uint8_t A4 = PIN_A4;
|
||||
|
||||
#define ADC_RESOLUTION 14
|
||||
|
||||
/*
|
||||
* Serial interfaces
|
||||
*/
|
||||
#define PIN_SERIAL2_RX (0 + 22)
|
||||
#define PIN_SERIAL2_TX (0 + 20)
|
||||
|
||||
/**
|
||||
Wire Interfaces
|
||||
*/
|
||||
#define WIRE_INTERFACES_COUNT 1
|
||||
|
||||
#define PIN_WIRE_SDA (0 + 17)
|
||||
#define PIN_WIRE_SCL (0 + 15)
|
||||
|
||||
#define PIN_RTC_INT (0 + 14) // Interrupt from the PCF8563 RTC
|
||||
|
||||
/*
|
||||
External serial flash W25Q16JV_IQ
|
||||
*/
|
||||
|
||||
// QSPI Pins
|
||||
#define PIN_QSPI_SCK (0 + 8)
|
||||
#define PIN_QSPI_CS (32 + 7)
|
||||
#define PIN_QSPI_IO0 (0 + 6) // MOSI if using two bit interface
|
||||
#define PIN_QSPI_IO1 (0 + 26) // MISO if using two bit interface
|
||||
#define PIN_QSPI_IO2 (32 + 4) // WP if using two bit interface (i.e. not used)
|
||||
#define PIN_QSPI_IO3 (32 + 2) // HOLD if using two bit interface (i.e. not used)
|
||||
|
||||
// On-board QSPI Flash
|
||||
#define EXTERNAL_FLASH_DEVICES W25Q16JV_IQ
|
||||
#define EXTERNAL_FLASH_USE_QSPI
|
||||
|
||||
/*
|
||||
* Lora radio
|
||||
*/
|
||||
|
||||
#define USE_SX1262
|
||||
#define SX126X_CS (32 + 13) // FIXME - we really should define LORA_CS instead
|
||||
#define SX126X_DIO1 (32 + 10)
|
||||
// Note DIO2 is attached internally to the module to an analog switch for TX/RX switching
|
||||
//#define SX1262_DIO3 \
|
||||
(0 + 21) // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the main
|
||||
// CPU?
|
||||
#define SX126X_BUSY (32 + 11)
|
||||
#define SX126X_RESET (32 + 15)
|
||||
#define SX126X_E22 // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3
|
||||
|
||||
// #define LORA_DISABLE_SENDING // Define this to disable transmission for testing (power testing etc...)
|
||||
|
||||
// #undef SX126X_CS
|
||||
|
||||
/*
|
||||
* GPS pins
|
||||
*/
|
||||
|
||||
#define GPS_L76K
|
||||
|
||||
#define PIN_GPS_WAKE (0 + 13) // An output to wake GPS, low means allow sleep, high means force wake
|
||||
#define PIN_GPS_TX (0 + 9) // This is for bits going TOWARDS the CPU
|
||||
#define PIN_GPS_RX (0 + 10) // This is for bits going TOWARDS the GPS
|
||||
|
||||
//#define GPS_THREAD_INTERVAL 50
|
||||
|
||||
#define PIN_SERIAL1_RX PIN_GPS_TX
|
||||
#define PIN_SERIAL1_TX PIN_GPS_RX
|
||||
|
||||
// PCF8563 RTC Module
|
||||
#define PCF8563_RTC 0x51
|
||||
|
||||
/*
|
||||
* SPI Interfaces
|
||||
*/
|
||||
#define SPI_INTERFACES_COUNT 1
|
||||
|
||||
// For LORA, spi 0
|
||||
#define PIN_SPI_MISO (32 + 9)
|
||||
#define PIN_SPI_MOSI (0 + 11)
|
||||
#define PIN_SPI_SCK (0 + 12)
|
||||
|
||||
//#define PIN_PWR_EN (0 + 6)
|
||||
|
||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||
// #define USE_SEGGER
|
||||
|
||||
// Battery
|
||||
// The battery sense is hooked to pin A0 (2)
|
||||
// it is defined in the anlaolgue pin section of this file
|
||||
// and has 12 bit resolution
|
||||
#define BATTERY_SENSE_RESOLUTION_BITS 12
|
||||
#define BATTERY_SENSE_RESOLUTION 4096.0
|
||||
// Definition of milliVolt per LSB => 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096
|
||||
#define VBAT_MV_PER_LSB (0.73242188F)
|
||||
// Voltage divider value => 100K + 100K voltage divider on VBAT = (100K / (100K + 100K))
|
||||
#define VBAT_DIVIDER (0.5F)
|
||||
// Compensation factor for the VBAT divider
|
||||
#define VBAT_DIVIDER_COMP (2.0)
|
||||
// Fixed calculation of milliVolt from compensation value
|
||||
#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB)
|
||||
#undef AREF_VOLTAGE
|
||||
#define AREF_VOLTAGE 3.0
|
||||
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
|
||||
#define ADC_MULTIPLIER VBAT_DIVIDER_COMP
|
||||
#define VBAT_RAW_TO_SCALED(x) (REAL_VBAT_MV_PER_LSB * x)
|
||||
|
||||
#define HAS_RTC 1
|
||||
|
||||
/**
|
||||
OLED Screen Model
|
||||
*/
|
||||
#define ARDUINO_ARCH_AVR
|
||||
#define USE_SH1107_128_64
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Arduino objects - C++ only
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
@@ -19,6 +19,7 @@
|
||||
// SDA = 4
|
||||
// SCL = 5
|
||||
|
||||
#define EXT_NOTIFY_OUT 22
|
||||
#define BUTTON_PIN 17
|
||||
|
||||
#define LED_PIN PIN_LED
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
// SDA = 4
|
||||
// SCL = 5
|
||||
|
||||
#define EXT_NOTIFY_OUT 22
|
||||
#define BUTTON_PIN 17
|
||||
|
||||
#define BATTERY_PIN 26
|
||||
|
||||
@@ -16,8 +16,11 @@
|
||||
#define TFT_OFFSET_X 0
|
||||
#define TFT_OFFSET_Y 0
|
||||
#define SCREEN_ROTATE
|
||||
#define SCREEN_TRANSITION_FRAMERATE 1 // fps
|
||||
#define SCREEN_TRANSITION_FRAMERATE 5
|
||||
|
||||
#define HAS_TOUCHSCREEN 1
|
||||
#define SCREEN_TOUCH_INT 16
|
||||
#define TOUCH_I2C_PORT 0
|
||||
#define TOUCH_SLAVE_ADDRESS 0x5D // GT911
|
||||
|
||||
#define BUTTON_PIN 0
|
||||
@@ -43,14 +46,25 @@
|
||||
// keyboard
|
||||
#define I2C_SDA 18 // I2C pins for this board
|
||||
#define I2C_SCL 8
|
||||
#define BOARD_POWERON 10 // must be set to HIGH
|
||||
#define KB_SLAVE_ADDRESS 0x55
|
||||
#define KB_BL_PIN 46 // INT, set to INPUT
|
||||
#define KB_UP 2
|
||||
#define KB_DOWN 3
|
||||
#define KB_LEFT 1
|
||||
#define KB_RIGHT 15
|
||||
#define KB_POWERON 10 // must be set to HIGH
|
||||
#define KB_SLAVE_ADDRESS TDECK_KB_ADDR // 0x55
|
||||
#define KB_BL_PIN 46 // not used for now
|
||||
|
||||
// trackball
|
||||
#define HAS_TRACKBALL 1
|
||||
#define TB_UP 3
|
||||
#define TB_DOWN 15
|
||||
#define TB_LEFT 1
|
||||
#define TB_RIGHT 2
|
||||
#define TB_PRESS BUTTON_PIN
|
||||
|
||||
// microphone
|
||||
#define ES7210_SCK 47
|
||||
#define ES7210_DIN 14
|
||||
#define ES7210_LRCK 21
|
||||
#define ES7210_MCLK 48
|
||||
|
||||
// LoRa
|
||||
#define USE_SX1262
|
||||
#define USE_SX1268
|
||||
|
||||
|
||||
@@ -16,10 +16,13 @@
|
||||
#define TFT_OFFSET_X 0
|
||||
#define TFT_OFFSET_Y 0
|
||||
#define SCREEN_ROTATE
|
||||
#define SCREEN_TRANSITION_FRAMERATE 1 // fps
|
||||
#define SCREEN_TRANSITION_FRAMERATE 5 // fps
|
||||
|
||||
#define HAS_TOUCHSCREEN 1
|
||||
#define SCREEN_TOUCH_INT 16
|
||||
#define SCREEN_TOUCH_USE_I2C1 1
|
||||
#define TOUCH_SLAVE_ADDRESS 0x38 // GT911
|
||||
#define SCREEN_TOUCH_USE_I2C1
|
||||
#define TOUCH_I2C_PORT 1
|
||||
#define TOUCH_SLAVE_ADDRESS 0x38
|
||||
|
||||
#define I2C_SDA1 39 // Used for capacitive touch
|
||||
#define I2C_SCL1 40 // Used for capacitive touch
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[VERSION]
|
||||
major = 2
|
||||
minor = 1
|
||||
build = 20
|
||||
build = 22
|
||||
|
||||
Reference in New Issue
Block a user