mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-18 19:12:09 +00:00
Merge branch 'master' into tft-gui-work
This commit is contained in:
commit
ba56d1d0f2
@ -1 +1 @@
|
|||||||
Subproject commit a3030d5ff187091c9fbbd08dd797cca5085736fe
|
Subproject commit 57ddb288e87438db3b5b99aa61f66a354c47bffb
|
@ -288,7 +288,7 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
|
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
|
||||||
}
|
}
|
||||||
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
|
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
|
||||||
drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
|
screen->drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,7 @@ size_t RedirectablePrint::write(uint8_t c)
|
|||||||
// serial port said (which could be zero)
|
// serial port said (which could be zero)
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RedirectablePrint::vprintf(const char *format, va_list arg)
|
size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_list arg)
|
||||||
{
|
{
|
||||||
va_list copy;
|
va_list copy;
|
||||||
static char printBuf[160];
|
static char printBuf[160];
|
||||||
@ -66,25 +66,39 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
|
|||||||
len = sizeof(printBuf) - 1;
|
len = sizeof(printBuf) - 1;
|
||||||
printBuf[sizeof(printBuf) - 2] = '\n';
|
printBuf[sizeof(printBuf) - 2] = '\n';
|
||||||
}
|
}
|
||||||
|
for (size_t f = 0; f < len; f++) {
|
||||||
|
if (!std::isprint(static_cast<unsigned char>(printBuf[f])) && printBuf[f] != '\n')
|
||||||
|
printBuf[f] = '#';
|
||||||
|
}
|
||||||
|
if (logLevel != nullptr) {
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||||
|
Print::write("\u001b[34m", 6);
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||||
|
Print::write("\u001b[32m", 6);
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
||||||
|
Print::write("\u001b[33m", 6);
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
|
||||||
|
Print::write("\u001b[31m", 6);
|
||||||
|
}
|
||||||
len = Print::write(printBuf, len);
|
len = Print::write(printBuf, len);
|
||||||
|
Print::write("\u001b[0m", 5);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
void RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
||||||
{
|
{
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||||
return 0;
|
return;
|
||||||
else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||||
return 0;
|
return;
|
||||||
else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
||||||
return 0;
|
return;
|
||||||
#endif
|
#endif
|
||||||
if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
|
if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) {
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
size_t r = 0;
|
|
||||||
#ifdef HAS_FREE_RTOS
|
#ifdef HAS_FREE_RTOS
|
||||||
if (inDebugPrint != nullptr && xSemaphoreTake(inDebugPrint, portMAX_DELAY) == pdTRUE) {
|
if (inDebugPrint != nullptr && xSemaphoreTake(inDebugPrint, portMAX_DELAY) == pdTRUE) {
|
||||||
#else
|
#else
|
||||||
@ -100,6 +114,14 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
|
|
||||||
// If we are the first message on a report, include the header
|
// If we are the first message on a report, include the header
|
||||||
if (!isContinuationMessage) {
|
if (!isContinuationMessage) {
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0)
|
||||||
|
Print::write("\u001b[34m", 6);
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0)
|
||||||
|
Print::write("\u001b[32m", 6);
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0)
|
||||||
|
Print::write("\u001b[33m", 6);
|
||||||
|
if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0)
|
||||||
|
Print::write("\u001b[31m", 6);
|
||||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
|
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile
|
||||||
if (rtc_sec > 0) {
|
if (rtc_sec > 0) {
|
||||||
long hms = rtc_sec % SEC_PER_DAY;
|
long hms = rtc_sec % SEC_PER_DAY;
|
||||||
@ -113,15 +135,15 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||||
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
|
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
r += ::printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
::printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||||
#else
|
#else
|
||||||
r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||||
#endif
|
#endif
|
||||||
} else
|
} else
|
||||||
#ifdef ARCH_PORTDUINO
|
#ifdef ARCH_PORTDUINO
|
||||||
r += ::printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
|
::printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000);
|
||||||
#else
|
#else
|
||||||
r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
|
printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto thread = concurrency::OSThread::currentThread;
|
auto thread = concurrency::OSThread::currentThread;
|
||||||
@ -133,7 +155,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
print("] ");
|
print("] ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r += vprintf(format, arg);
|
vprintf(logLevel, format, arg);
|
||||||
|
|
||||||
#if (HAS_WIFI || HAS_ETHERNET) && !defined(ARCH_PORTDUINO)
|
#if (HAS_WIFI || HAS_ETHERNET) && !defined(ARCH_PORTDUINO)
|
||||||
// if syslog is in use, collect the log messages and send them to syslog
|
// if syslog is in use, collect the log messages and send them to syslog
|
||||||
@ -211,7 +233,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len)
|
void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len)
|
||||||
|
@ -41,10 +41,10 @@ class RedirectablePrint : public Print
|
|||||||
* log message. Otherwise we assume more prints will come before the log message ends. This
|
* log message. Otherwise we assume more prints will come before the log message ends. This
|
||||||
* allows you to call logDebug a few times to build up a single log message line if you wish.
|
* allows you to call logDebug a few times to build up a single log message line if you wish.
|
||||||
*/
|
*/
|
||||||
size_t log(const char *logLevel, const char *format, ...) __attribute__((format(printf, 3, 4)));
|
void log(const char *logLevel, const char *format, ...) __attribute__((format(printf, 3, 4)));
|
||||||
|
|
||||||
/** like printf but va_list based */
|
/** like printf but va_list based */
|
||||||
size_t vprintf(const char *format, va_list arg);
|
size_t vprintf(const char *logLevel, const char *format, va_list arg);
|
||||||
|
|
||||||
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
|
void hexDump(const char *logLevel, unsigned char *buf, uint16_t len);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ void consolePrintf(const char *format, ...)
|
|||||||
{
|
{
|
||||||
va_list arg;
|
va_list arg;
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
console->vprintf(format, arg);
|
console->vprintf(nullptr, format, arg);
|
||||||
va_end(arg);
|
va_end(arg);
|
||||||
console->flush();
|
console->flush();
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,6 @@ namespace graphics
|
|||||||
// A text message frame + debug frame + all the node infos
|
// A text message frame + debug frame + all the node infos
|
||||||
FrameCallback *normalFrames;
|
FrameCallback *normalFrames;
|
||||||
static uint32_t targetFramerate = IDLE_FRAMERATE;
|
static uint32_t targetFramerate = IDLE_FRAMERATE;
|
||||||
static char btPIN[16] = "888888";
|
|
||||||
|
|
||||||
uint32_t logo_timeout = 5000; // 4 seconds for EACH logo
|
uint32_t logo_timeout = 5000; // 4 seconds for EACH logo
|
||||||
|
|
||||||
@ -229,7 +228,7 @@ static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
drawOEMIconScreen(region, display, state, x, y);
|
drawOEMIconScreen(region, display, state, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message)
|
void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message)
|
||||||
{
|
{
|
||||||
uint16_t x_offset = display->width() / 2;
|
uint16_t x_offset = display->width() / 2;
|
||||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
@ -237,19 +236,6 @@ static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
|||||||
display->drawString(x_offset + x, 26 + y, message);
|
display->drawString(x_offset + x, 26 + y, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
|
||||||
{
|
|
||||||
#ifdef ARCH_ESP32
|
|
||||||
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) {
|
|
||||||
drawFrameText(display, state, x, y, "Resuming...");
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
const char *region = myRegion ? myRegion->name : NULL;
|
|
||||||
drawIconScreen(region, display, state, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used on boot when a certificate is being created
|
// Used on boot when a certificate is being created
|
||||||
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
@ -1336,32 +1322,10 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp
|
|||||||
arrowPoints[i]->scale(getCompassDiam(display) * 0.6);
|
arrowPoints[i]->scale(getCompassDiam(display) * 0.6);
|
||||||
arrowPoints[i]->translate(compassX, compassY);
|
arrowPoints[i]->translate(compassX, compassY);
|
||||||
}
|
}
|
||||||
drawLine(display, tip, tail);
|
display->drawLine(tip.x, tip.y, tail.x, tail.y);
|
||||||
drawLine(display, leftArrow, tip);
|
display->drawLine(leftArrow.x, leftArrow.y, tip.x, tip.y);
|
||||||
drawLine(display, rightArrow, tip);
|
display->drawLine(rightArrow.x, rightArrow.y, tip.x, tip.y);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// 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);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// 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)
|
||||||
@ -1461,7 +1425,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
|||||||
myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians
|
myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians
|
||||||
else
|
else
|
||||||
myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||||
drawCompassNorth(display, compassX, compassY, myHeading);
|
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
||||||
|
|
||||||
if (hasValidPosition(node)) {
|
if (hasValidPosition(node)) {
|
||||||
// display direction toward node
|
// display direction toward node
|
||||||
@ -1562,7 +1526,7 @@ static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
|||||||
myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians
|
myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians
|
||||||
else
|
else
|
||||||
myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||||
drawCompassNorth(display, compassX, compassY, myHeading);
|
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
||||||
|
|
||||||
// Distance to Waypoint
|
// Distance to Waypoint
|
||||||
float d = GeoCoord::latLongToMeter(DegD(wp.latitude_i), DegD(wp.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
float d = GeoCoord::latLongToMeter(DegD(wp.latitude_i), DegD(wp.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||||
@ -1758,9 +1722,19 @@ void Screen::setup()
|
|||||||
|
|
||||||
// Add frames.
|
// Add frames.
|
||||||
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
|
EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST);
|
||||||
static FrameCallback bootFrames[] = {drawBootScreen};
|
alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void {
|
||||||
static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]);
|
#ifdef ARCH_ESP32
|
||||||
ui->setFrames(bootFrames, bootFrameCount);
|
if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) {
|
||||||
|
drawFrameText(display, state, x, y, "Resuming...");
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Draw region in upper left
|
||||||
|
const char *region = myRegion ? myRegion->name : NULL;
|
||||||
|
drawIconScreen(region, display, state, x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ui->setFrames(alertFrames, 1);
|
||||||
// No overlays.
|
// No overlays.
|
||||||
ui->setOverlays(nullptr, 0);
|
ui->setOverlays(nullptr, 0);
|
||||||
|
|
||||||
@ -2723,4 +2697,4 @@ int Screen::handleWaypoint(const meshtastic_MeshPacket *arg)
|
|||||||
} // namespace graphics
|
} // namespace graphics
|
||||||
#else
|
#else
|
||||||
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
|
||||||
#endif // HAS_SCREEN
|
#endif // HAS_SCREEN
|
@ -86,6 +86,68 @@ class Screen
|
|||||||
#define SEGMENT_WIDTH 16
|
#define SEGMENT_WIDTH 16
|
||||||
#define SEGMENT_HEIGHT 4
|
#define SEGMENT_HEIGHT 4
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
};
|
||||||
|
|
||||||
namespace graphics
|
namespace graphics
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -172,6 +234,30 @@ class Screen : public concurrency::OSThread
|
|||||||
|
|
||||||
void blink();
|
void blink();
|
||||||
|
|
||||||
|
void drawFrameText(OLEDDisplay *, OLEDDisplayUiState *, int16_t, int16_t, const char *);
|
||||||
|
|
||||||
|
// Draw north
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
display->drawLine(N1.x, N1.y, N3.x, N3.y);
|
||||||
|
display->drawLine(N2.x, N2.y, N4.x, N4.y);
|
||||||
|
display->drawLine(N1.x, N1.y, N4.x, N4.y);
|
||||||
|
}
|
||||||
|
|
||||||
/// Handle button press, trackball or swipe action)
|
/// Handle button press, trackball or swipe action)
|
||||||
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); }
|
||||||
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
|
void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); }
|
||||||
@ -457,92 +543,5 @@ 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
|
@ -22,7 +22,6 @@ typedef enum _meshtastic_Config_DeviceConfig_Role {
|
|||||||
The wifi radio and the oled screen will be put to sleep.
|
The wifi radio and the oled screen will be put to sleep.
|
||||||
This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. */
|
This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. */
|
||||||
meshtastic_Config_DeviceConfig_Role_ROUTER = 2,
|
meshtastic_Config_DeviceConfig_Role_ROUTER = 2,
|
||||||
/* Description: Combination of both ROUTER and CLIENT. Not for mobile devices. */
|
|
||||||
meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3,
|
meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3,
|
||||||
/* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list.
|
/* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list.
|
||||||
Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry
|
Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry
|
||||||
|
Loading…
Reference in New Issue
Block a user