mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-17 02:22:05 +00:00
Merge branch 'master' into tft-gui-work
This commit is contained in:
commit
ad5dbc2a84
@ -35,7 +35,7 @@
|
|||||||
"svd_path": "nrf52840.svd",
|
"svd_path": "nrf52840.svd",
|
||||||
"openocd_target": "nrf52840-mdk-rs"
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino", "freertos"],
|
||||||
"name": "WisCore RAK4631 Board",
|
"name": "WisCore RAK4631 Board",
|
||||||
"upload": {
|
"upload": {
|
||||||
"maximum_ram_size": 248832,
|
"maximum_ram_size": 248832,
|
||||||
|
@ -80,7 +80,7 @@ monitor_speed = 115200
|
|||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
jgromes/RadioLib@~6.6.0
|
jgromes/RadioLib@~6.6.0
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#2b40affbe7f7dc63b6c00fa88e7e12ed1f8e1719 ; ESP8266_SSD1306
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
|
||||||
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
||||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||||
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||||
@ -151,4 +151,3 @@ lib_deps =
|
|||||||
|
|
||||||
|
|
||||||
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
|
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 4da558d0f73c46ef91b74431facee73c09affbfc
|
Subproject commit a3030d5ff187091c9fbbd08dd797cca5085736fe
|
7
pyocd.yaml
Normal file
7
pyocd.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# This is a config file to control pyocd ICE debugger probe options (only used for NRF52 targets with hardware debugging connections)
|
||||||
|
# for more info see FIXMEURL
|
||||||
|
|
||||||
|
# console or telnet
|
||||||
|
semihost_console_type: telnet
|
||||||
|
enable_semihosting: True
|
||||||
|
telnet_port: 4444
|
@ -16,6 +16,8 @@
|
|||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#ifdef RAK_4631
|
#ifdef RAK_4631
|
||||||
#include "Fusion/Fusion.h"
|
#include "Fusion/Fusion.h"
|
||||||
|
#include "graphics/Screen.h"
|
||||||
|
#include "graphics/ScreenFonts.h"
|
||||||
#include <Rak_BMX160.h>
|
#include <Rak_BMX160.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -101,7 +103,11 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
bmx160.getAllData(&magAccel, NULL, &gAccel);
|
bmx160.getAllData(&magAccel, NULL, &gAccel);
|
||||||
|
|
||||||
// expirimental calibrate routine. Limited to between 10 and 30 seconds after boot
|
// expirimental calibrate routine. Limited to between 10 and 30 seconds after boot
|
||||||
if (millis() > 10 * 1000 && millis() < 30 * 1000) {
|
if (millis() > 12 * 1000 && millis() < 30 * 1000) {
|
||||||
|
if (!showingScreen) {
|
||||||
|
showingScreen = true;
|
||||||
|
screen->startAlert((FrameCallback)drawFrameCalibration);
|
||||||
|
}
|
||||||
if (magAccel.x > highestX)
|
if (magAccel.x > highestX)
|
||||||
highestX = magAccel.x;
|
highestX = magAccel.x;
|
||||||
if (magAccel.x < lowestX)
|
if (magAccel.x < lowestX)
|
||||||
@ -114,6 +120,9 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
highestZ = magAccel.z;
|
highestZ = magAccel.z;
|
||||||
if (magAccel.z < lowestZ)
|
if (magAccel.z < lowestZ)
|
||||||
lowestZ = magAccel.z;
|
lowestZ = magAccel.z;
|
||||||
|
} else if (showingScreen && millis() >= 30 * 1000) {
|
||||||
|
showingScreen = false;
|
||||||
|
screen->endAlert();
|
||||||
}
|
}
|
||||||
|
|
||||||
int highestRealX = highestX - (highestX + lowestX) / 2;
|
int highestRealX = highestX - (highestX + lowestX) / 2;
|
||||||
@ -255,11 +264,33 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
Adafruit_LIS3DH lis;
|
Adafruit_LIS3DH lis;
|
||||||
Adafruit_LSM6DS3TRC lsm;
|
Adafruit_LSM6DS3TRC lsm;
|
||||||
SensorBMA423 bmaSensor;
|
SensorBMA423 bmaSensor;
|
||||||
|
bool BMA_IRQ = false;
|
||||||
#ifdef RAK_4631
|
#ifdef RAK_4631
|
||||||
|
bool showingScreen = false;
|
||||||
RAK_BMX160 bmx160;
|
RAK_BMX160 bmx160;
|
||||||
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
||||||
|
|
||||||
|
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
int x_offset = display->width() / 2;
|
||||||
|
int y_offset = display->height() <= 80 ? 0 : 32;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(x, y, "Calibrating\nCompass");
|
||||||
|
int16_t compassX = 0, compassY = 0;
|
||||||
|
|
||||||
|
// coordinates for the center of the compass/circle
|
||||||
|
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||||
|
compassX = x + display->getWidth() - getCompassDiam(display) / 2 - 5;
|
||||||
|
compassY = y + display->getHeight() / 2;
|
||||||
|
} else {
|
||||||
|
compassX = x + display->getWidth() - getCompassDiam(display) / 2 - 5;
|
||||||
|
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
|
||||||
|
}
|
||||||
|
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
|
||||||
|
drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
bool BMA_IRQ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -181,8 +181,9 @@ int32_t ButtonThread::runOnce()
|
|||||||
case BUTTON_EVENT_LONG_PRESSED: {
|
case BUTTON_EVENT_LONG_PRESSED: {
|
||||||
LOG_BUTTON("Long press!\n");
|
LOG_BUTTON("Long press!\n");
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
if (screen)
|
if (screen) {
|
||||||
screen->startShutdownScreen();
|
screen->startAlert("Shutting down...");
|
||||||
|
}
|
||||||
playBeep();
|
playBeep();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,14 @@
|
|||||||
|
|
||||||
#include "SerialConsole.h"
|
#include "SerialConsole.h"
|
||||||
|
|
||||||
|
// If defined we will include support for ARM ICE "semihosting" for a virtual
|
||||||
|
// console over the JTAG port (to replace the normal serial port)
|
||||||
|
// Note: Normally this flag is passed into the gcc commandline by platformio.ini.
|
||||||
|
// for an example see env:rak4631_dap.
|
||||||
|
// #ifndef USE_SEMIHOSTING
|
||||||
|
// #define USE_SEMIHOSTING
|
||||||
|
// #endif
|
||||||
|
|
||||||
#define DEBUG_PORT (*console) // Serial debug port
|
#define DEBUG_PORT (*console) // Serial debug port
|
||||||
|
|
||||||
#ifdef USE_SEGGER
|
#ifdef USE_SEGGER
|
||||||
|
@ -8,13 +8,11 @@ enum class Cmd {
|
|||||||
SET_ON,
|
SET_ON,
|
||||||
SET_OFF,
|
SET_OFF,
|
||||||
ON_PRESS,
|
ON_PRESS,
|
||||||
START_BLUETOOTH_PIN_SCREEN,
|
START_ALERT_FRAME,
|
||||||
|
STOP_ALERT_FRAME,
|
||||||
START_FIRMWARE_UPDATE_SCREEN,
|
START_FIRMWARE_UPDATE_SCREEN,
|
||||||
STOP_BLUETOOTH_PIN_SCREEN,
|
|
||||||
STOP_BOOT_SCREEN,
|
STOP_BOOT_SCREEN,
|
||||||
PRINT,
|
PRINT,
|
||||||
START_SHUTDOWN_SCREEN,
|
|
||||||
START_REBOOT_SCREEN,
|
|
||||||
SHOW_PREV_FRAME,
|
SHOW_PREV_FRAME,
|
||||||
SHOW_NEXT_FRAME
|
SHOW_NEXT_FRAME
|
||||||
};
|
};
|
@ -379,7 +379,7 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
|||||||
// in the array of "drawScreen" functions; however,
|
// in the array of "drawScreen" functions; however,
|
||||||
// the passed-state doesn't quite reflect the "current"
|
// the passed-state doesn't quite reflect the "current"
|
||||||
// screen, so we have to detect it.
|
// screen, so we have to detect it.
|
||||||
if (state->frameState == IN_TRANSITION && state->transitionFrameRelationship == INCOMING) {
|
if (state->frameState == IN_TRANSITION && state->transitionFrameRelationship == TransitionRelationship_INCOMING) {
|
||||||
// if we're transitioning from the end of the frame list back around to the first
|
// if we're transitioning from the end of the frame list back around to the first
|
||||||
// frame, then we want this to be `0`
|
// frame, then we want this to be `0`
|
||||||
module_frame = state->transitionFrameTarget;
|
module_frame = state->transitionFrameTarget;
|
||||||
@ -393,31 +393,6 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
|||||||
pi.drawFrame(display, state, x, y);
|
pi.drawFrame(display, state, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
|
||||||
{
|
|
||||||
int x_offset = display->width() / 2;
|
|
||||||
int y_offset = display->height() <= 80 ? 0 : 32;
|
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
|
||||||
display->setFont(FONT_MEDIUM);
|
|
||||||
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
display->setFont(FONT_LARGE);
|
|
||||||
String displayPin(btPIN);
|
|
||||||
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
|
|
||||||
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
|
|
||||||
display->drawString(x_offset + x, y_offset + y, pin);
|
|
||||||
|
|
||||||
display->setFont(FONT_SMALL);
|
|
||||||
String deviceName = "Name: ";
|
|
||||||
deviceName.concat(getDeviceName());
|
|
||||||
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
|
|
||||||
display->drawString(x_offset + x, y_offset + y, deviceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
@ -1307,49 +1282,6 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
namespace
|
|
||||||
{
|
|
||||||
|
|
||||||
/// A basic 2D point class for drawing
|
|
||||||
class Point
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
float x, y;
|
|
||||||
|
|
||||||
Point(float _x, float _y) : x(_x), y(_y) {}
|
|
||||||
|
|
||||||
/// Apply a rotation around zero (standard rotation matrix math)
|
|
||||||
void rotate(float radian)
|
|
||||||
{
|
|
||||||
float cos = cosf(radian), sin = sinf(radian);
|
|
||||||
float rx = x * cos + y * sin, ry = -x * sin + y * cos;
|
|
||||||
|
|
||||||
x = rx;
|
|
||||||
y = ry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void translate(int16_t dx, int dy)
|
|
||||||
{
|
|
||||||
x += dx;
|
|
||||||
y += dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scale(float f)
|
|
||||||
{
|
|
||||||
// We use -f here to counter the flip that happens
|
|
||||||
// on the y axis when drawing and rotating on screen
|
|
||||||
x *= f;
|
|
||||||
y *= -f;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
static void drawLine(OLEDDisplay *d, const Point &p1, const Point &p2)
|
|
||||||
{
|
|
||||||
d->drawLine(p1.x, p1.y, p2.x, p2.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a recent lat/lon return a guess of the heading the user is walking on.
|
* Given a recent lat/lon return a guess of the heading the user is walking on.
|
||||||
*
|
*
|
||||||
@ -1380,31 +1312,6 @@ static float estimatedHeading(double lat, double lon)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t getCompassDiam(OLEDDisplay *display)
|
|
||||||
{
|
|
||||||
uint16_t diam = 0;
|
|
||||||
uint16_t offset = 0;
|
|
||||||
|
|
||||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT)
|
|
||||||
offset = FONT_HEIGHT_SMALL;
|
|
||||||
|
|
||||||
// get the smaller of the 2 dimensions and subtract 20
|
|
||||||
if (display->getWidth() > (display->getHeight() - offset)) {
|
|
||||||
diam = display->getHeight() - offset;
|
|
||||||
// if 2/3 of the other size would be smaller, use that
|
|
||||||
if (diam > (display->getWidth() * 2 / 3)) {
|
|
||||||
diam = display->getWidth() * 2 / 3;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
diam = display->getWidth();
|
|
||||||
if (diam > ((display->getHeight() - offset) * 2 / 3)) {
|
|
||||||
diam = (display->getHeight() - offset) * 2 / 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return diam - 20;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// We will skip one node - the one for us, so we just blindly loop over all
|
/// We will skip one node - the one for us, so we just blindly loop over all
|
||||||
/// nodes
|
/// nodes
|
||||||
static size_t nodeIndex;
|
static size_t nodeIndex;
|
||||||
@ -1428,7 +1335,7 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
|
|||||||
drawLine(display, leftArrow, tip);
|
drawLine(display, leftArrow, tip);
|
||||||
drawLine(display, rightArrow, tip);
|
drawLine(display, rightArrow, tip);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// Draw north
|
// Draw north
|
||||||
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
|
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
|
||||||
{
|
{
|
||||||
@ -1449,7 +1356,7 @@ static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t com
|
|||||||
drawLine(display, N1, N3);
|
drawLine(display, N1, N3);
|
||||||
drawLine(display, N2, N4);
|
drawLine(display, N2, N4);
|
||||||
drawLine(display, N1, N4);
|
drawLine(display, N1, N4);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Get a string representation of the time passed since something happened
|
// Get a string representation of the time passed since something happened
|
||||||
static void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength)
|
static void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength)
|
||||||
@ -2023,13 +1930,22 @@ int32_t Screen::runOnce()
|
|||||||
case Cmd::SHOW_NEXT_FRAME:
|
case Cmd::SHOW_NEXT_FRAME:
|
||||||
handleShowNextFrame();
|
handleShowNextFrame();
|
||||||
break;
|
break;
|
||||||
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
case Cmd::START_ALERT_FRAME: {
|
||||||
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
showingBootScreen = false; // this should avoid the edge case where an alert triggers before the boot screen goes away
|
||||||
|
showingNormalScreen = false;
|
||||||
|
alertFrames[0] = alertFrame;
|
||||||
|
#ifdef USE_EINK
|
||||||
|
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
|
||||||
|
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
|
||||||
|
handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?)
|
||||||
|
#endif
|
||||||
|
setFrameImmediateDraw(alertFrames);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case Cmd::START_FIRMWARE_UPDATE_SCREEN:
|
case Cmd::START_FIRMWARE_UPDATE_SCREEN:
|
||||||
handleStartFirmwareUpdateScreen();
|
handleStartFirmwareUpdateScreen();
|
||||||
break;
|
break;
|
||||||
case Cmd::STOP_BLUETOOTH_PIN_SCREEN:
|
case Cmd::STOP_ALERT_FRAME:
|
||||||
case Cmd::STOP_BOOT_SCREEN:
|
case Cmd::STOP_BOOT_SCREEN:
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC); // E-Ink: Explicitly use full-refresh for next frame
|
EINK_ADD_FRAMEFLAG(dispdev, COSMETIC); // E-Ink: Explicitly use full-refresh for next frame
|
||||||
setFrames();
|
setFrames();
|
||||||
@ -2038,12 +1954,6 @@ int32_t Screen::runOnce()
|
|||||||
handlePrint(cmd.print_text);
|
handlePrint(cmd.print_text);
|
||||||
free(cmd.print_text);
|
free(cmd.print_text);
|
||||||
break;
|
break;
|
||||||
case Cmd::START_SHUTDOWN_SCREEN:
|
|
||||||
handleShutdownScreen();
|
|
||||||
break;
|
|
||||||
case Cmd::START_REBOOT_SCREEN:
|
|
||||||
handleRebootScreen();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Invalid screen cmd\n");
|
LOG_ERROR("Invalid screen cmd\n");
|
||||||
}
|
}
|
||||||
@ -2284,17 +2194,6 @@ void Screen::setFrames()
|
|||||||
setFastFramerate(); // Draw ASAP
|
setFastFramerate(); // Draw ASAP
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::handleStartBluetoothPinScreen(uint32_t pin)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("showing bluetooth screen\n");
|
|
||||||
showingNormalScreen = false;
|
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // E-Ink: Explicitly use fast-refresh for next frame
|
|
||||||
|
|
||||||
static FrameCallback frames[] = {drawFrameBluetooth};
|
|
||||||
snprintf(btPIN, sizeof(btPIN), "%06u", pin);
|
|
||||||
setFrameImmediateDraw(frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
|
void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
|
||||||
{
|
{
|
||||||
ui->disableAllIndicators();
|
ui->disableAllIndicators();
|
||||||
@ -2302,41 +2201,6 @@ void Screen::setFrameImmediateDraw(FrameCallback *drawFrames)
|
|||||||
setFastFramerate();
|
setFastFramerate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::handleShutdownScreen()
|
|
||||||
{
|
|
||||||
LOG_DEBUG("showing shutdown screen\n");
|
|
||||||
showingNormalScreen = false;
|
|
||||||
#ifdef USE_EINK
|
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
|
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
|
|
||||||
handleSetOn(true); // Ensure power-on to receive deep-sleep screensaver (PowerFSM should handle?)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
|
||||||
drawFrameText(display, state, x, y, "Shutting down...");
|
|
||||||
};
|
|
||||||
static FrameCallback frames[] = {frame};
|
|
||||||
|
|
||||||
setFrameImmediateDraw(frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Screen::handleRebootScreen()
|
|
||||||
{
|
|
||||||
LOG_DEBUG("showing reboot screen\n");
|
|
||||||
showingNormalScreen = false;
|
|
||||||
#ifdef USE_EINK
|
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); // Use fast-refresh for next frame, no skip please
|
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, BLOCKING); // Edge case: if this frame is promoted to COSMETIC, wait for update
|
|
||||||
handleSetOn(true); // Power-on to show rebooting screen (PowerFSM should handle?)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
auto frame = [](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
|
||||||
drawFrameText(display, state, x, y, "Rebooting...");
|
|
||||||
};
|
|
||||||
static FrameCallback frames[] = {frame};
|
|
||||||
setFrameImmediateDraw(frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Screen::handleStartFirmwareUpdateScreen()
|
void Screen::handleStartFirmwareUpdateScreen()
|
||||||
{
|
{
|
||||||
LOG_DEBUG("showing firmware screen\n");
|
LOG_DEBUG("showing firmware screen\n");
|
||||||
|
@ -21,15 +21,13 @@ class Screen
|
|||||||
void print(const char *) {}
|
void print(const char *) {}
|
||||||
void doDeepSleep() {}
|
void doDeepSleep() {}
|
||||||
void forceDisplay(bool forceUiUpdate = false) {}
|
void forceDisplay(bool forceUiUpdate = false) {}
|
||||||
void startBluetoothPinScreen(uint32_t pin) {}
|
|
||||||
void stopBluetoothPinScreen() {}
|
|
||||||
void startRebootScreen() {}
|
|
||||||
void startShutdownScreen() {}
|
|
||||||
void startFirmwareUpdateScreen() {}
|
void startFirmwareUpdateScreen() {}
|
||||||
void increaseBrightness() {}
|
void increaseBrightness() {}
|
||||||
void decreaseBrightness() {}
|
void decreaseBrightness() {}
|
||||||
void setFunctionSymbal(std::string) {}
|
void setFunctionSymbal(std::string) {}
|
||||||
void removeFunctionSymbal(std::string) {}
|
void removeFunctionSymbal(std::string) {}
|
||||||
|
void startAlert(const char *) {}
|
||||||
|
void endAlert() {}
|
||||||
};
|
};
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#else
|
#else
|
||||||
@ -38,6 +36,8 @@ class Screen
|
|||||||
#include <OLEDDisplayUi.h>
|
#include <OLEDDisplayUi.h>
|
||||||
|
|
||||||
#include "../configuration.h"
|
#include "../configuration.h"
|
||||||
|
#include "gps/GeoCoord.h"
|
||||||
|
#include "graphics/ScreenFonts.h"
|
||||||
|
|
||||||
#ifdef USE_ST7567
|
#ifdef USE_ST7567
|
||||||
#include <ST7567Wire.h>
|
#include <ST7567Wire.h>
|
||||||
@ -177,15 +177,29 @@ class Screen : public concurrency::OSThread
|
|||||||
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
|
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
|
||||||
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
|
void showNextFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_NEXT_FRAME}); }
|
||||||
|
|
||||||
/// Starts showing the Bluetooth PIN screen.
|
// generic alert start
|
||||||
//
|
void startAlert(FrameCallback _alertFrame)
|
||||||
// Switches over to a static frame showing the Bluetooth pairing screen
|
{
|
||||||
// with the PIN.
|
alertFrame = _alertFrame;
|
||||||
void startBluetoothPinScreen(uint32_t pin)
|
ScreenCmd cmd;
|
||||||
|
cmd.cmd = Cmd::START_ALERT_FRAME;
|
||||||
|
enqueueCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startAlert(const char *_alertMessage)
|
||||||
|
{
|
||||||
|
startAlert([_alertMessage](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||||
|
uint16_t x_offset = display->width() / 2;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(x_offset + x, 26 + y, _alertMessage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void endAlert()
|
||||||
{
|
{
|
||||||
ScreenCmd cmd;
|
ScreenCmd cmd;
|
||||||
cmd.cmd = Cmd::START_BLUETOOTH_PIN_SCREEN;
|
cmd.cmd = Cmd::STOP_ALERT_FRAME;
|
||||||
cmd.bluetooth_pin = pin;
|
|
||||||
enqueueCmd(cmd);
|
enqueueCmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,20 +210,6 @@ class Screen : public concurrency::OSThread
|
|||||||
enqueueCmd(cmd);
|
enqueueCmd(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startShutdownScreen()
|
|
||||||
{
|
|
||||||
ScreenCmd cmd;
|
|
||||||
cmd.cmd = Cmd::START_SHUTDOWN_SCREEN;
|
|
||||||
enqueueCmd(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void startRebootScreen()
|
|
||||||
{
|
|
||||||
ScreenCmd cmd;
|
|
||||||
cmd.cmd = Cmd::START_REBOOT_SCREEN;
|
|
||||||
enqueueCmd(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to allow the AccelerometerThread to set the heading if a sensor provides it
|
// Function to allow the AccelerometerThread to set the heading if a sensor provides it
|
||||||
// Mutex needed?
|
// Mutex needed?
|
||||||
void setHeading(long _heading)
|
void setHeading(long _heading)
|
||||||
@ -228,9 +228,6 @@ class Screen : public concurrency::OSThread
|
|||||||
void setFunctionSymbal(std::string sym);
|
void setFunctionSymbal(std::string sym);
|
||||||
void removeFunctionSymbal(std::string sym);
|
void removeFunctionSymbal(std::string sym);
|
||||||
|
|
||||||
/// Stops showing the bluetooth PIN screen.
|
|
||||||
void stopBluetoothPinScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BLUETOOTH_PIN_SCREEN}); }
|
|
||||||
|
|
||||||
/// Stops showing the boot screen.
|
/// Stops showing the boot screen.
|
||||||
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
|
void stopBootScreen() { enqueueCmd(ScreenCmd{.cmd = Cmd::STOP_BOOT_SCREEN}); }
|
||||||
|
|
||||||
@ -366,6 +363,7 @@ class Screen : public concurrency::OSThread
|
|||||||
bool isAUTOOled = false;
|
bool isAUTOOled = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FrameCallback alertFrames[1];
|
||||||
struct ScreenCmd {
|
struct ScreenCmd {
|
||||||
Cmd cmd;
|
Cmd cmd;
|
||||||
union {
|
union {
|
||||||
@ -391,11 +389,8 @@ class Screen : public concurrency::OSThread
|
|||||||
void handleOnPress();
|
void handleOnPress();
|
||||||
void handleShowNextFrame();
|
void handleShowNextFrame();
|
||||||
void handleShowPrevFrame();
|
void handleShowPrevFrame();
|
||||||
void handleStartBluetoothPinScreen(uint32_t pin);
|
|
||||||
void handlePrint(const char *text);
|
void handlePrint(const char *text);
|
||||||
void handleStartFirmwareUpdateScreen();
|
void handleStartFirmwareUpdateScreen();
|
||||||
void handleShutdownScreen();
|
|
||||||
void handleRebootScreen();
|
|
||||||
/// Rebuilds our list of frames (screens) to default ones.
|
/// Rebuilds our list of frames (screens) to default ones.
|
||||||
void setFrames();
|
void setFrames();
|
||||||
|
|
||||||
@ -433,6 +428,9 @@ class Screen : public concurrency::OSThread
|
|||||||
bool digitalWatchFace = true;
|
bool digitalWatchFace = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// callback for current alert frame
|
||||||
|
FrameCallback alertFrame;
|
||||||
|
|
||||||
/// Queue of commands to execute in doTask.
|
/// Queue of commands to execute in doTask.
|
||||||
TypedQueue<ScreenCmd> cmdQueue;
|
TypedQueue<ScreenCmd> cmdQueue;
|
||||||
/// Whether we are using a display
|
/// Whether we are using a display
|
||||||
@ -459,4 +457,92 @@ class Screen : public concurrency::OSThread
|
|||||||
};
|
};
|
||||||
|
|
||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
/// A basic 2D point class for drawing
|
||||||
|
class Point
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point(float _x, float _y) : x(_x), y(_y) {}
|
||||||
|
|
||||||
|
/// Apply a rotation around zero (standard rotation matrix math)
|
||||||
|
void rotate(float radian)
|
||||||
|
{
|
||||||
|
float cos = cosf(radian), sin = sinf(radian);
|
||||||
|
float rx = x * cos + y * sin, ry = -x * sin + y * cos;
|
||||||
|
|
||||||
|
x = rx;
|
||||||
|
y = ry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void translate(int16_t dx, int dy)
|
||||||
|
{
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void scale(float f)
|
||||||
|
{
|
||||||
|
// We use -f here to counter the flip that happens
|
||||||
|
// on the y axis when drawing and rotating on screen
|
||||||
|
x *= f;
|
||||||
|
y *= -f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
static void drawLine(OLEDDisplay *d, const Point &p1, const Point &p2)
|
||||||
|
{
|
||||||
|
d->drawLine(p1.x, p1.y, p2.x, p2.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t getCompassDiam(OLEDDisplay *display)
|
||||||
|
{
|
||||||
|
uint16_t diam = 0;
|
||||||
|
uint16_t offset = 0;
|
||||||
|
|
||||||
|
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT)
|
||||||
|
offset = FONT_HEIGHT_SMALL;
|
||||||
|
|
||||||
|
// get the smaller of the 2 dimensions and subtract 20
|
||||||
|
if (display->getWidth() > (display->getHeight() - offset)) {
|
||||||
|
diam = display->getHeight() - offset;
|
||||||
|
// if 2/3 of the other size would be smaller, use that
|
||||||
|
if (diam > (display->getWidth() * 2 / 3)) {
|
||||||
|
diam = display->getWidth() * 2 / 3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
diam = display->getWidth();
|
||||||
|
if (diam > ((display->getHeight() - offset) * 2 / 3)) {
|
||||||
|
diam = (display->getHeight() - offset) * 2 / 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return diam - 20;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw north
|
||||||
|
static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading)
|
||||||
|
{
|
||||||
|
// If north is supposed to be at the top of the compass we want rotation to be +0
|
||||||
|
if (config.display.compass_north_top)
|
||||||
|
myHeading = -0;
|
||||||
|
|
||||||
|
Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f);
|
||||||
|
Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f);
|
||||||
|
Point *rosePoints[] = {&N1, &N2, &N3, &N4};
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
// North on compass will be negative of heading
|
||||||
|
rosePoints[i]->rotate(-myHeading);
|
||||||
|
rosePoints[i]->scale(getCompassDiam(display));
|
||||||
|
rosePoints[i]->translate(compassX, compassY);
|
||||||
|
}
|
||||||
|
drawLine(display, N1, N3);
|
||||||
|
drawLine(display, N2, N4);
|
||||||
|
drawLine(display, N1, N4);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
@ -28,8 +28,8 @@
|
|||||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define fontHeight(font) ((font)[1] + 1) // height is position 1
|
#define _fontHeight(font) ((font)[1] + 1) // height is position 1
|
||||||
|
|
||||||
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
|
#define FONT_HEIGHT_SMALL _fontHeight(FONT_SMALL)
|
||||||
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
|
#define FONT_HEIGHT_MEDIUM _fontHeight(FONT_MEDIUM)
|
||||||
#define FONT_HEIGHT_LARGE fontHeight(FONT_LARGE)
|
#define FONT_HEIGHT_LARGE _fontHeight(FONT_LARGE)
|
@ -1029,7 +1029,7 @@ void setup()
|
|||||||
nodeDB->saveToDisk(SEGMENT_CONFIG);
|
nodeDB->saveToDisk(SEGMENT_CONFIG);
|
||||||
if (!rIf->reconfigure()) {
|
if (!rIf->reconfigure()) {
|
||||||
LOG_WARN("Reconfigure failed, rebooting\n");
|
LOG_WARN("Reconfigure failed, rebooting\n");
|
||||||
screen->startRebootScreen();
|
screen->startAlert("Rebooting...");
|
||||||
rebootAtMsec = millis() + 5000;
|
rebootAtMsec = millis() + 5000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
|||||||
|
|
||||||
if (didFactoryReset) {
|
if (didFactoryReset) {
|
||||||
LOG_INFO("Rebooting due to factory reset");
|
LOG_INFO("Rebooting due to factory reset");
|
||||||
screen->startRebootScreen();
|
screen->startAlert("Rebooting...");
|
||||||
rebootAtMsec = millis() + (5 * 1000);
|
rebootAtMsec = millis() + (5 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,9 @@ PB_BIND(meshtastic_QueueStatus, meshtastic_QueueStatus, AUTO)
|
|||||||
PB_BIND(meshtastic_FromRadio, meshtastic_FromRadio, 2)
|
PB_BIND(meshtastic_FromRadio, meshtastic_FromRadio, 2)
|
||||||
|
|
||||||
|
|
||||||
|
PB_BIND(meshtastic_FileInfo, meshtastic_FileInfo, AUTO)
|
||||||
|
|
||||||
|
|
||||||
PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)
|
PB_BIND(meshtastic_ToRadio, meshtastic_ToRadio, 2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -711,6 +711,14 @@ typedef struct _meshtastic_QueueStatus {
|
|||||||
uint32_t mesh_packet_id;
|
uint32_t mesh_packet_id;
|
||||||
} meshtastic_QueueStatus;
|
} meshtastic_QueueStatus;
|
||||||
|
|
||||||
|
/* Individual File info for the device */
|
||||||
|
typedef struct _meshtastic_FileInfo {
|
||||||
|
/* The fully qualified path of the file */
|
||||||
|
char file_name[228];
|
||||||
|
/* The size of the file in bytes */
|
||||||
|
uint32_t size_bytes;
|
||||||
|
} meshtastic_FileInfo;
|
||||||
|
|
||||||
typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t;
|
typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t;
|
||||||
/* Compressed message payload */
|
/* Compressed message payload */
|
||||||
typedef struct _meshtastic_Compressed {
|
typedef struct _meshtastic_Compressed {
|
||||||
@ -815,6 +823,8 @@ typedef struct _meshtastic_FromRadio {
|
|||||||
meshtastic_DeviceMetadata metadata;
|
meshtastic_DeviceMetadata metadata;
|
||||||
/* MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) */
|
/* MQTT Client Proxy Message (device sending to client / phone for publishing to MQTT) */
|
||||||
meshtastic_MqttClientProxyMessage mqttClientProxyMessage;
|
meshtastic_MqttClientProxyMessage mqttClientProxyMessage;
|
||||||
|
/* File system manifest messages */
|
||||||
|
meshtastic_FileInfo fileInfo;
|
||||||
};
|
};
|
||||||
} meshtastic_FromRadio;
|
} meshtastic_FromRadio;
|
||||||
|
|
||||||
@ -958,6 +968,7 @@ extern "C" {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
|
#define meshtastic_Compressed_portnum_ENUMTYPE meshtastic_PortNum
|
||||||
|
|
||||||
|
|
||||||
@ -985,6 +996,7 @@ extern "C" {
|
|||||||
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_default {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_default {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
#define meshtastic_FromRadio_init_default {0, 0, {meshtastic_MeshPacket_init_default}}
|
||||||
|
#define meshtastic_FileInfo_init_default {"", 0}
|
||||||
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
#define meshtastic_ToRadio_init_default {0, {meshtastic_MeshPacket_init_default}}
|
||||||
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
#define meshtastic_Compressed_init_default {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||||
#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
|
#define meshtastic_NeighborInfo_init_default {0, 0, 0, 0, {meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default, meshtastic_Neighbor_init_default}}
|
||||||
@ -1008,6 +1020,7 @@ extern "C" {
|
|||||||
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
#define meshtastic_LogRecord_init_zero {"", 0, "", _meshtastic_LogRecord_Level_MIN}
|
||||||
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
#define meshtastic_QueueStatus_init_zero {0, 0, 0, 0}
|
||||||
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
#define meshtastic_FromRadio_init_zero {0, 0, {meshtastic_MeshPacket_init_zero}}
|
||||||
|
#define meshtastic_FileInfo_init_zero {"", 0}
|
||||||
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
#define meshtastic_ToRadio_init_zero {0, {meshtastic_MeshPacket_init_zero}}
|
||||||
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
#define meshtastic_Compressed_init_zero {_meshtastic_PortNum_MIN, {0, {0}}}
|
||||||
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
|
#define meshtastic_NeighborInfo_init_zero {0, 0, 0, 0, {meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero, meshtastic_Neighbor_init_zero}}
|
||||||
@ -1110,6 +1123,8 @@ extern "C" {
|
|||||||
#define meshtastic_QueueStatus_free_tag 2
|
#define meshtastic_QueueStatus_free_tag 2
|
||||||
#define meshtastic_QueueStatus_maxlen_tag 3
|
#define meshtastic_QueueStatus_maxlen_tag 3
|
||||||
#define meshtastic_QueueStatus_mesh_packet_id_tag 4
|
#define meshtastic_QueueStatus_mesh_packet_id_tag 4
|
||||||
|
#define meshtastic_FileInfo_file_name_tag 1
|
||||||
|
#define meshtastic_FileInfo_size_bytes_tag 2
|
||||||
#define meshtastic_Compressed_portnum_tag 1
|
#define meshtastic_Compressed_portnum_tag 1
|
||||||
#define meshtastic_Compressed_data_tag 2
|
#define meshtastic_Compressed_data_tag 2
|
||||||
#define meshtastic_Neighbor_node_id_tag 1
|
#define meshtastic_Neighbor_node_id_tag 1
|
||||||
@ -1144,6 +1159,7 @@ extern "C" {
|
|||||||
#define meshtastic_FromRadio_xmodemPacket_tag 12
|
#define meshtastic_FromRadio_xmodemPacket_tag 12
|
||||||
#define meshtastic_FromRadio_metadata_tag 13
|
#define meshtastic_FromRadio_metadata_tag 13
|
||||||
#define meshtastic_FromRadio_mqttClientProxyMessage_tag 14
|
#define meshtastic_FromRadio_mqttClientProxyMessage_tag 14
|
||||||
|
#define meshtastic_FromRadio_fileInfo_tag 15
|
||||||
#define meshtastic_ToRadio_packet_tag 1
|
#define meshtastic_ToRadio_packet_tag 1
|
||||||
#define meshtastic_ToRadio_want_config_id_tag 3
|
#define meshtastic_ToRadio_want_config_id_tag 3
|
||||||
#define meshtastic_ToRadio_disconnect_tag 4
|
#define meshtastic_ToRadio_disconnect_tag 4
|
||||||
@ -1321,7 +1337,8 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,channel,channel), 10) \
|
|||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,queueStatus,queueStatus), 11) \
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,queueStatus,queueStatus), 11) \
|
||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 12) \
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,xmodemPacket,xmodemPacket), 12) \
|
||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13) \
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,metadata,metadata), 13) \
|
||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 14)
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttClientProxyMessage), 14) \
|
||||||
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,fileInfo,fileInfo), 15)
|
||||||
#define meshtastic_FromRadio_CALLBACK NULL
|
#define meshtastic_FromRadio_CALLBACK NULL
|
||||||
#define meshtastic_FromRadio_DEFAULT NULL
|
#define meshtastic_FromRadio_DEFAULT NULL
|
||||||
#define meshtastic_FromRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
|
#define meshtastic_FromRadio_payload_variant_packet_MSGTYPE meshtastic_MeshPacket
|
||||||
@ -1335,6 +1352,13 @@ X(a, STATIC, ONEOF, MESSAGE, (payload_variant,mqttClientProxyMessage,mqttC
|
|||||||
#define meshtastic_FromRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
|
#define meshtastic_FromRadio_payload_variant_xmodemPacket_MSGTYPE meshtastic_XModem
|
||||||
#define meshtastic_FromRadio_payload_variant_metadata_MSGTYPE meshtastic_DeviceMetadata
|
#define meshtastic_FromRadio_payload_variant_metadata_MSGTYPE meshtastic_DeviceMetadata
|
||||||
#define meshtastic_FromRadio_payload_variant_mqttClientProxyMessage_MSGTYPE meshtastic_MqttClientProxyMessage
|
#define meshtastic_FromRadio_payload_variant_mqttClientProxyMessage_MSGTYPE meshtastic_MqttClientProxyMessage
|
||||||
|
#define meshtastic_FromRadio_payload_variant_fileInfo_MSGTYPE meshtastic_FileInfo
|
||||||
|
|
||||||
|
#define meshtastic_FileInfo_FIELDLIST(X, a) \
|
||||||
|
X(a, STATIC, SINGULAR, STRING, file_name, 1) \
|
||||||
|
X(a, STATIC, SINGULAR, UINT32, size_bytes, 2)
|
||||||
|
#define meshtastic_FileInfo_CALLBACK NULL
|
||||||
|
#define meshtastic_FileInfo_DEFAULT NULL
|
||||||
|
|
||||||
#define meshtastic_ToRadio_FIELDLIST(X, a) \
|
#define meshtastic_ToRadio_FIELDLIST(X, a) \
|
||||||
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \
|
X(a, STATIC, ONEOF, MESSAGE, (payload_variant,packet,packet), 1) \
|
||||||
@ -1434,6 +1458,7 @@ extern const pb_msgdesc_t meshtastic_MyNodeInfo_msg;
|
|||||||
extern const pb_msgdesc_t meshtastic_LogRecord_msg;
|
extern const pb_msgdesc_t meshtastic_LogRecord_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
|
extern const pb_msgdesc_t meshtastic_QueueStatus_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_FromRadio_msg;
|
extern const pb_msgdesc_t meshtastic_FromRadio_msg;
|
||||||
|
extern const pb_msgdesc_t meshtastic_FileInfo_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
|
extern const pb_msgdesc_t meshtastic_ToRadio_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_Compressed_msg;
|
extern const pb_msgdesc_t meshtastic_Compressed_msg;
|
||||||
extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
|
extern const pb_msgdesc_t meshtastic_NeighborInfo_msg;
|
||||||
@ -1459,6 +1484,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
|||||||
#define meshtastic_LogRecord_fields &meshtastic_LogRecord_msg
|
#define meshtastic_LogRecord_fields &meshtastic_LogRecord_msg
|
||||||
#define meshtastic_QueueStatus_fields &meshtastic_QueueStatus_msg
|
#define meshtastic_QueueStatus_fields &meshtastic_QueueStatus_msg
|
||||||
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
|
#define meshtastic_FromRadio_fields &meshtastic_FromRadio_msg
|
||||||
|
#define meshtastic_FileInfo_fields &meshtastic_FileInfo_msg
|
||||||
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
|
#define meshtastic_ToRadio_fields &meshtastic_ToRadio_msg
|
||||||
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
|
#define meshtastic_Compressed_fields &meshtastic_Compressed_msg
|
||||||
#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg
|
#define meshtastic_NeighborInfo_fields &meshtastic_NeighborInfo_msg
|
||||||
@ -1478,6 +1504,7 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg;
|
|||||||
#define meshtastic_Compressed_size 243
|
#define meshtastic_Compressed_size 243
|
||||||
#define meshtastic_Data_size 270
|
#define meshtastic_Data_size 270
|
||||||
#define meshtastic_DeviceMetadata_size 46
|
#define meshtastic_DeviceMetadata_size 46
|
||||||
|
#define meshtastic_FileInfo_size 236
|
||||||
#define meshtastic_FromRadio_size 510
|
#define meshtastic_FromRadio_size 510
|
||||||
#define meshtastic_Heartbeat_size 0
|
#define meshtastic_Heartbeat_size 0
|
||||||
#define meshtastic_LogRecord_size 81
|
#define meshtastic_LogRecord_size 81
|
||||||
|
@ -137,7 +137,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
#if defined(ARCH_ESP32) && !MESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
if (BleOta::getOtaAppVersion().isEmpty()) {
|
if (BleOta::getOtaAppVersion().isEmpty()) {
|
||||||
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
|
LOG_INFO("No OTA firmware available, scheduling regular reboot in %d seconds\n", s);
|
||||||
screen->startRebootScreen();
|
screen->startAlert("Rebooting...");
|
||||||
} else {
|
} else {
|
||||||
screen->startFirmwareUpdateScreen();
|
screen->startFirmwareUpdateScreen();
|
||||||
BleOta::switchToOtaApp();
|
BleOta::switchToOtaApp();
|
||||||
@ -145,7 +145,7 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
LOG_INFO("Not on ESP32, scheduling regular reboot in %d seconds\n", s);
|
LOG_INFO("Not on ESP32, scheduling regular reboot in %d seconds\n", s);
|
||||||
screen->startRebootScreen();
|
screen->startAlert("Rebooting...");
|
||||||
#endif
|
#endif
|
||||||
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
|
rebootAtMsec = (s < 0) ? 0 : (millis() + s * 1000);
|
||||||
break;
|
break;
|
||||||
@ -815,7 +815,7 @@ void AdminModule::handleGetChannel(const meshtastic_MeshPacket &req, uint32_t ch
|
|||||||
void AdminModule::reboot(int32_t seconds)
|
void AdminModule::reboot(int32_t seconds)
|
||||||
{
|
{
|
||||||
LOG_INFO("Rebooting in %d seconds\n", seconds);
|
LOG_INFO("Rebooting in %d seconds\n", seconds);
|
||||||
screen->startRebootScreen();
|
screen->startAlert("Rebooting...");
|
||||||
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
|
rebootAtMsec = (seconds < 0) ? 0 : (millis() + seconds * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,14 +597,14 @@ int32_t CannedMessageModule::runOnce()
|
|||||||
// handle fn+s for shutdown
|
// handle fn+s for shutdown
|
||||||
case 0x9b:
|
case 0x9b:
|
||||||
if (screen)
|
if (screen)
|
||||||
screen->startShutdownScreen();
|
screen->startAlert("Shutting down...");
|
||||||
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
|
shutdownAtMsec = millis() + DEFAULT_SHUTDOWN_SECONDS * 1000;
|
||||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||||
break;
|
break;
|
||||||
// and fn+r for reboot
|
// and fn+r for reboot
|
||||||
case 0x90:
|
case 0x90:
|
||||||
if (screen)
|
if (screen)
|
||||||
screen->startRebootScreen();
|
screen->startAlert("Rebooting...");
|
||||||
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
|
rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000;
|
||||||
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
runState = CANNED_MESSAGE_RUN_STATE_INACTIVE;
|
||||||
break;
|
break;
|
||||||
|
@ -188,7 +188,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
|||||||
if (lastMeasurementPacket == nullptr) {
|
if (lastMeasurementPacket == nullptr) {
|
||||||
// If there's no valid packet, display "Environment"
|
// If there's no valid packet, display "Environment"
|
||||||
display->drawString(x, y, "Environment");
|
display->drawString(x, y, "Environment");
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL), "No measurement");
|
display->drawString(x, y += _fontHeight(FONT_SMALL), "No measurement");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,31 +213,31 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Continue with the remaining details
|
// Continue with the remaining details
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Temp/Hum: " + last_temp + " / " +
|
"Temp/Hum: " + last_temp + " / " +
|
||||||
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
String(lastMeasurement.variant.environment_metrics.relative_humidity, 0) + "%");
|
||||||
|
|
||||||
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
|
if (lastMeasurement.variant.environment_metrics.barometric_pressure != 0) {
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA");
|
"Press: " + String(lastMeasurement.variant.environment_metrics.barometric_pressure, 0) + "hPA");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastMeasurement.variant.environment_metrics.voltage != 0) {
|
if (lastMeasurement.variant.environment_metrics.voltage != 0) {
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Volt/Cur: " + String(lastMeasurement.variant.environment_metrics.voltage, 0) + "V / " +
|
"Volt/Cur: " + String(lastMeasurement.variant.environment_metrics.voltage, 0) + "V / " +
|
||||||
String(lastMeasurement.variant.environment_metrics.current, 0) + "mA");
|
String(lastMeasurement.variant.environment_metrics.current, 0) + "mA");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastMeasurement.variant.environment_metrics.iaq != 0) {
|
if (lastMeasurement.variant.environment_metrics.iaq != 0) {
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL), "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq));
|
display->drawString(x, y += _fontHeight(FONT_SMALL), "IAQ: " + String(lastMeasurement.variant.environment_metrics.iaq));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastMeasurement.variant.environment_metrics.distance != 0)
|
if (lastMeasurement.variant.environment_metrics.distance != 0)
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Water Level: " + String(lastMeasurement.variant.environment_metrics.distance, 0) + "mm");
|
"Water Level: " + String(lastMeasurement.variant.environment_metrics.distance, 0) + "mm");
|
||||||
|
|
||||||
if (lastMeasurement.variant.environment_metrics.weight != 0)
|
if (lastMeasurement.variant.environment_metrics.weight != 0)
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
|
"Weight: " + String(lastMeasurement.variant.environment_metrics.weight, 0) + "kg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s
|
|||||||
display->drawString(x, y, "Power Telemetry");
|
display->drawString(x, y, "Power Telemetry");
|
||||||
if (lastMeasurementPacket == nullptr) {
|
if (lastMeasurementPacket == nullptr) {
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement");
|
display->drawString(x, y += _fontHeight(FONT_MEDIUM), "No measurement");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,22 +120,22 @@ void PowerTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *s
|
|||||||
auto &p = lastMeasurementPacket->decoded;
|
auto &p = lastMeasurementPacket->decoded;
|
||||||
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_Telemetry_msg, &lastMeasurement)) {
|
if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, &meshtastic_Telemetry_msg, &lastMeasurement)) {
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
|
display->drawString(x, y += _fontHeight(FONT_MEDIUM), "Measurement Error");
|
||||||
LOG_ERROR("Unable to decode last packet");
|
LOG_ERROR("Unable to decode last packet");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
display->setFont(FONT_SMALL);
|
display->setFont(FONT_SMALL);
|
||||||
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
|
String last_temp = String(lastMeasurement.variant.environment_metrics.temperature, 0) + "°C";
|
||||||
display->drawString(x, y += fontHeight(FONT_MEDIUM) - 2, "From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
display->drawString(x, y += _fontHeight(FONT_MEDIUM) - 2, "From: " + String(lastSender) + "(" + String(agoSecs) + "s)");
|
||||||
if (lastMeasurement.variant.power_metrics.ch1_voltage != 0) {
|
if (lastMeasurement.variant.power_metrics.ch1_voltage != 0) {
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Ch 1 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch1_voltage, 0) + "V / " +
|
"Ch 1 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch1_voltage, 0) + "V / " +
|
||||||
String(lastMeasurement.variant.power_metrics.ch1_current, 0) + "mA");
|
String(lastMeasurement.variant.power_metrics.ch1_current, 0) + "mA");
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Ch 2 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch2_voltage, 0) + "V / " +
|
"Ch 2 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch2_voltage, 0) + "V / " +
|
||||||
String(lastMeasurement.variant.power_metrics.ch2_current, 0) + "mA");
|
String(lastMeasurement.variant.power_metrics.ch2_current, 0) + "mA");
|
||||||
display->drawString(x, y += fontHeight(FONT_SMALL),
|
display->drawString(x, y += _fontHeight(FONT_SMALL),
|
||||||
"Ch 3 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch3_voltage, 0) + "V / " +
|
"Ch 3 Volt/Cur: " + String(lastMeasurement.variant.power_metrics.ch3_voltage, 0) + "V / " +
|
||||||
String(lastMeasurement.variant.power_metrics.ch3_current, 0) + "mA");
|
String(lastMeasurement.variant.power_metrics.ch3_current, 0) + "mA");
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,33 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
LOG_INFO("*** Enter passkey %d on the peer side ***\n", passkey);
|
LOG_INFO("*** Enter passkey %d on the peer side ***\n", passkey);
|
||||||
|
|
||||||
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
||||||
screen->startBluetoothPinScreen(passkey);
|
#if HAS_SCREEN
|
||||||
|
screen->startAlert([passkey](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||||
|
char btPIN[16] = "888888";
|
||||||
|
snprintf(btPIN, sizeof(btPIN), "%06u", passkey);
|
||||||
|
int x_offset = display->width() / 2;
|
||||||
|
int y_offset = display->height() <= 80 ? 0 : 32;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
display->setFont(FONT_LARGE);
|
||||||
|
String displayPin(btPIN);
|
||||||
|
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
|
||||||
|
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
|
||||||
|
display->drawString(x_offset + x, y_offset + y, pin);
|
||||||
|
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
String deviceName = "Name: ";
|
||||||
|
deviceName.concat(getDeviceName());
|
||||||
|
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
|
||||||
|
display->drawString(x_offset + x, y_offset + y, deviceName);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
passkeyShowing = true;
|
passkeyShowing = true;
|
||||||
|
|
||||||
return passkey;
|
return passkey;
|
||||||
@ -94,7 +120,7 @@ class NimbleBluetoothServerCallback : public NimBLEServerCallbacks
|
|||||||
|
|
||||||
if (passkeyShowing) {
|
if (passkeyShowing) {
|
||||||
passkeyShowing = false;
|
passkeyShowing = false;
|
||||||
screen->stopBluetoothPinScreen();
|
screen->endAlert();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +290,31 @@ bool NRF52Bluetooth::onPairingPasskey(uint16_t conn_handle, uint8_t const passke
|
|||||||
{
|
{
|
||||||
LOG_INFO("BLE pairing process started with passkey %.3s %.3s\n", passkey, passkey + 3);
|
LOG_INFO("BLE pairing process started with passkey %.3s %.3s\n", passkey, passkey + 3);
|
||||||
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
powerFSM.trigger(EVENT_BLUETOOTH_PAIR);
|
||||||
screen->startBluetoothPinScreen(configuredPasskey);
|
screen->startAlert([](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||||
|
char btPIN[16] = "888888";
|
||||||
|
snprintf(btPIN, sizeof(btPIN), "%06u", configuredPasskey);
|
||||||
|
int x_offset = display->width() / 2;
|
||||||
|
int y_offset = display->height() <= 80 ? 0 : 32;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
display->setFont(FONT_LARGE);
|
||||||
|
String displayPin(btPIN);
|
||||||
|
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
|
||||||
|
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
|
||||||
|
display->drawString(x_offset + x, y_offset + y, pin);
|
||||||
|
|
||||||
|
display->setFont(FONT_SMALL);
|
||||||
|
String deviceName = "Name: ";
|
||||||
|
deviceName.concat(getDeviceName());
|
||||||
|
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
|
||||||
|
display->drawString(x_offset + x, y_offset + y, deviceName);
|
||||||
|
});
|
||||||
if (match_request) {
|
if (match_request) {
|
||||||
uint32_t start_time = millis();
|
uint32_t start_time = millis();
|
||||||
while (millis() < start_time + 30000) {
|
while (millis() < start_time + 30000) {
|
||||||
@ -307,7 +331,7 @@ void NRF52Bluetooth::onPairingCompleted(uint16_t conn_handle, uint8_t auth_statu
|
|||||||
LOG_INFO("BLE pairing success\n");
|
LOG_INFO("BLE pairing success\n");
|
||||||
else
|
else
|
||||||
LOG_INFO("BLE pairing failed\n");
|
LOG_INFO("BLE pairing failed\n");
|
||||||
screen->stopBluetoothPinScreen();
|
screen->endAlert();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NRF52Bluetooth::sendLog(const char *logMessage)
|
void NRF52Bluetooth::sendLog(const char *logMessage)
|
||||||
|
@ -149,13 +149,43 @@ void nrf52Loop()
|
|||||||
checkSDEvents();
|
checkSDEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SEMIHOSTING
|
||||||
|
#include <SemihostingStream.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: this variable is in BSS and therfore false by default. But the gdbinit
|
||||||
|
* file will be installing a temporary breakpoint that changes wantSemihost to true.
|
||||||
|
*/
|
||||||
|
bool wantSemihost;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on semihosting if the ICE debugger wants it.
|
||||||
|
*/
|
||||||
|
void nrf52InitSemiHosting()
|
||||||
|
{
|
||||||
|
if (wantSemihost) {
|
||||||
|
static SemihostingStream semiStream;
|
||||||
|
// We must dynamically alloc because the constructor does semihost operations which
|
||||||
|
// would crash any load not talking to a debugger
|
||||||
|
semiStream.open();
|
||||||
|
semiStream.println("Semihosting starts!");
|
||||||
|
// Redirect our serial output to instead go via the ICE port
|
||||||
|
console->setDestination(&semiStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void nrf52Setup()
|
void nrf52Setup()
|
||||||
{
|
{
|
||||||
auto why = NRF_POWER->RESETREAS;
|
uint32_t why = NRF_POWER->RESETREAS;
|
||||||
// per
|
// per
|
||||||
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
|
// https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpower.html
|
||||||
LOG_DEBUG("Reset reason: 0x%x\n", why);
|
LOG_DEBUG("Reset reason: 0x%x\n", why);
|
||||||
|
|
||||||
|
#ifdef USE_SEMIHOSTING
|
||||||
|
nrf52InitSemiHosting();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Per
|
// Per
|
||||||
// https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse
|
// https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/monitor-mode-debugging-with-j-link-and-gdbeclipse
|
||||||
// This is the recommended setting for Monitor Mode Debugging
|
// This is the recommended setting for Monitor Mode Debugging
|
||||||
|
@ -38,7 +38,7 @@ void powerCommandsCheck()
|
|||||||
|
|
||||||
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
#if defined(ARCH_ESP32) || defined(ARCH_NRF52)
|
||||||
if (shutdownAtMsec) {
|
if (shutdownAtMsec) {
|
||||||
screen->startShutdownScreen();
|
screen->startAlert("Shutting down...");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ lib_deps =
|
|||||||
debug_tool = jlink
|
debug_tool = jlink
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||||
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
|
; Note: as of 6/2013 the serial/bootloader based programming takes approximately 30 seconds
|
||||||
;upload_protocol = jlink
|
;upload_protocol = jlink
|
||||||
@ -27,26 +28,92 @@ debug_tool = jlink
|
|||||||
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
|
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
|
||||||
; programming time is about the same as the bootloader version.
|
; programming time is about the same as the bootloader version.
|
||||||
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
|
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
|
||||||
[env:rak4631_dap]
|
[env:rak4631_dbg]
|
||||||
extends = env:rak4631
|
extends = env:rak4631
|
||||||
board_level = extra
|
board_level = extra
|
||||||
; pyocd pack --i nrf52840
|
|
||||||
|
; if the builtin version of openocd has a buggy version of semihosting, so use the external version
|
||||||
|
; platform_packages = platformio/tool-openocd@^3.1200.0
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${env:rak4631.build_flags}
|
||||||
|
-D USE_SEMIHOSTING
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${env:rak4631.lib_deps}
|
||||||
|
https://github.com/geeksville/Armduino-Semihosting.git#35b538fdf208c3530c1434cd099a08e486672ee4
|
||||||
|
|
||||||
|
; NOTE: the pyocd support for semihosting is buggy. So I switched to using the builtin platformio support for the stlink adapter which worked much better.
|
||||||
|
; However the built in openocd version in platformio has buggy support for TCP to semihosting.
|
||||||
|
;
|
||||||
|
; So I'm now trying the external openocd - but the openocd scripts for nrf52.cfg assume you are using a DAP adapter not an STLINK adapter.
|
||||||
|
; In theory I could change those scripts. But for now I'm trying going back to a DAP adapter but with the external openocd.
|
||||||
|
|
||||||
|
upload_protocol = stlink
|
||||||
; eventually use platformio/tool-pyocd@^2.3600.0 instad
|
; eventually use platformio/tool-pyocd@^2.3600.0 instad
|
||||||
upload_protocol = custom
|
;upload_protocol = custom
|
||||||
upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE
|
;upload_command = pyocd flash -t nrf52840 $UPLOADERFLAGS $SOURCE
|
||||||
|
|
||||||
|
; We want the initial breakpoint at setup() instead of main(). Also we want to enable semihosting at that point so instead of
|
||||||
|
; debug_init_break = tbreak setup
|
||||||
|
; we just turn off the platformio tbreak and do it in .gdbinit (where we have more flexibility for scripting)
|
||||||
|
; also we use a permanent breakpoint so it gets reused each time we restart the debugging session?
|
||||||
|
debug_init_break = tbreak setup
|
||||||
|
|
||||||
|
; Note: add "monitor arm semihosting_redirect tcp 4444 all" if you want the stdout from the device to go to that port number instead
|
||||||
|
; (for use by meshtastic command line)
|
||||||
|
; monitor arm semihosting disable
|
||||||
|
; monitor debug_level 3
|
||||||
|
;
|
||||||
|
; IMPORTANT: fileio must be disabled before using port 5555 - openocd ver 0.12 has a bug where if enabled it never properly parses the special :tt name
|
||||||
|
; for stdio access.
|
||||||
|
; monitor arm semihosting_redirect tcp 5555 stdio
|
||||||
|
|
||||||
|
; Also note: it is _impossible_ to do non blocking reads on the semihost console port (an oversight when ARM specified the semihost API).
|
||||||
|
; So we'll neve be able to general purpose bi-directional communication with the device over semihosting.
|
||||||
|
debug_extra_cmds =
|
||||||
|
echo Running .gdbinit script
|
||||||
|
monitor arm semihosting enable
|
||||||
|
monitor arm semihosting_fileio enable
|
||||||
|
monitor arm semihosting_redirect disable
|
||||||
|
commands 1
|
||||||
|
echo Breakpoint at setup() has semihosting console, connect to it with "telnet localhost 5555"
|
||||||
|
set wantSemihost = true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
; Only reprogram the board if the code has changed
|
; Only reprogram the board if the code has changed
|
||||||
debug_load_mode = modified
|
debug_load_mode = modified
|
||||||
;debug_load_mode = manual
|
;debug_load_mode = manual
|
||||||
debug_tool = custom
|
debug_tool = stlink
|
||||||
|
;debug_tool = custom
|
||||||
|
; debug_server =
|
||||||
|
; openocd
|
||||||
|
; -f
|
||||||
|
; /usr/local/share/openocd/scripts/interface/stlink.cfg
|
||||||
|
; -f
|
||||||
|
; /usr/local/share/openocd/scripts/target/nrf52.cfg
|
||||||
|
; $PLATFORMIO_CORE_DIR/packages/tool-openocd/openocd/scripts/interface/cmsis-dap.cfg
|
||||||
|
|
||||||
|
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
|
||||||
|
; programming time is about the same as the bootloader version.
|
||||||
|
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
|
||||||
; We manually pass in the elf file so that pyocd can reverse engineer FreeRTOS data (running threads, etc...)
|
; We manually pass in the elf file so that pyocd can reverse engineer FreeRTOS data (running threads, etc...)
|
||||||
debug_server =
|
;debug_server =
|
||||||
pyocd
|
; pyocd
|
||||||
gdbserver
|
; gdbserver
|
||||||
-t
|
; -j
|
||||||
nrf52840
|
; ${platformio.workspace_dir}/..
|
||||||
--elf
|
; -t
|
||||||
${platformio.build_dir}/${this.__env__}/firmware.elf
|
; nrf52840
|
||||||
|
; --semihosting
|
||||||
|
; --elf
|
||||||
|
; ${platformio.build_dir}/${this.__env__}/firmware.elf
|
||||||
|
|
||||||
|
; If you want to debug the semihosting support you can turn on extra logging in pyocd with
|
||||||
|
; -L
|
||||||
|
; pyocd.debug.semihost.trace=debug
|
||||||
|
|
||||||
; The following is not needed because it automatically tries do this
|
; The following is not needed because it automatically tries do this
|
||||||
;debug_server_ready_pattern = -.*GDB server started on port \d+.*
|
;debug_server_ready_pattern = -.*GDB server started on port \d+.*
|
||||||
;debug_port = localhost:3333
|
;debug_port = localhost:3333
|
@ -1,4 +1,4 @@
|
|||||||
[VERSION]
|
[VERSION]
|
||||||
major = 2
|
major = 2
|
||||||
minor = 3
|
minor = 3
|
||||||
build = 14
|
build = 15
|
||||||
|
Loading…
Reference in New Issue
Block a user