mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-21 12:38:34 +00:00
Merge branch 'master' into tft-gui-work
This commit is contained in:
commit
8a2e29d45a
@ -73,6 +73,7 @@ build_flags = -Wno-missing-field-initializers
|
||||
-DRADIOLIB_EXCLUDE_FSK4
|
||||
-DRADIOLIB_EXCLUDE_APRS
|
||||
-DRADIOLIB_EXCLUDE_LORAWAN
|
||||
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||
|
||||
monitor_speed = 115200
|
||||
|
||||
|
@ -117,8 +117,16 @@ class LGFX : public lgfx::LGFX_Device
|
||||
static LGFX *tft = nullptr;
|
||||
|
||||
#elif defined(RAK14014)
|
||||
#include <RAK14014_FT6336U.h>
|
||||
#include <TFT_eSPI.h>
|
||||
TFT_eSPI *tft = nullptr;
|
||||
FT6336U ft6336u;
|
||||
|
||||
static uint8_t _rak14014_touch_int = false; // TP interrupt generation flag.
|
||||
static void rak14014_tpIntHandle(void)
|
||||
{
|
||||
_rak14014_touch_int = true;
|
||||
}
|
||||
|
||||
#elif defined(ST7789_CS)
|
||||
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
|
||||
@ -653,8 +661,12 @@ void TFTDisplay::sendCommand(uint8_t com)
|
||||
|
||||
void TFTDisplay::setDisplayBrightness(uint8_t _brightness)
|
||||
{
|
||||
#ifdef RAK14014
|
||||
// todo
|
||||
#else
|
||||
tft->setBrightness(_brightness);
|
||||
LOG_DEBUG("Brightness is set to value: %i \n", _brightness);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TFTDisplay::flipScreenVertically()
|
||||
@ -668,6 +680,7 @@ void TFTDisplay::flipScreenVertically()
|
||||
bool TFTDisplay::hasTouch(void)
|
||||
{
|
||||
#ifdef RAK14014
|
||||
return true;
|
||||
#elif !defined(M5STACK)
|
||||
return tft->touch() != nullptr;
|
||||
#else
|
||||
@ -678,6 +691,15 @@ bool TFTDisplay::hasTouch(void)
|
||||
bool TFTDisplay::getTouch(int16_t *x, int16_t *y)
|
||||
{
|
||||
#ifdef RAK14014
|
||||
if (_rak14014_touch_int) {
|
||||
_rak14014_touch_int = false;
|
||||
/* The X and Y axes have to be switched */
|
||||
*y = ft6336u.read_touch1_x();
|
||||
*x = TFT_HEIGHT - ft6336u.read_touch1_y();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#elif !defined(M5STACK)
|
||||
return tft->getTouch(x, y);
|
||||
#else
|
||||
@ -727,7 +749,10 @@ bool TFTDisplay::connect()
|
||||
#elif defined(RAK14014)
|
||||
tft->setRotation(1);
|
||||
tft->setSwapBytes(true);
|
||||
// tft->fillScreen(TFT_BLACK);
|
||||
// tft->fillScreen(TFT_BLACK);
|
||||
ft6336u.begin();
|
||||
pinMode(SCREEN_TOUCH_INT, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING);
|
||||
#elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2)
|
||||
tft->setRotation(1); // T-Deck has the TFT in landscape
|
||||
#elif defined(T_WATCH_S3)
|
||||
|
@ -49,7 +49,7 @@ CannedMessageModule::CannedMessageModule()
|
||||
LOG_INFO("CannedMessageModule is enabled\n");
|
||||
|
||||
// T-Watch interface currently has no way to select destination type, so default to 'node'
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NODE;
|
||||
#endif
|
||||
|
||||
@ -75,7 +75,7 @@ int CannedMessageModule::splitConfiguredMessages()
|
||||
|
||||
String messages = cannedMessageModuleConfig.messages;
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
String separator = messages.length() ? "|" : "";
|
||||
|
||||
messages = "[---- Free Text ----]" + separator + messages;
|
||||
@ -144,7 +144,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_SELECT)) {
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
if (this->currentMessageIndex == 0) {
|
||||
this->runState = CANNED_MESSAGE_RUN_STATE_FREETEXT;
|
||||
|
||||
@ -170,7 +170,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
e.frameChanged = true;
|
||||
this->currentMessageIndex = -1;
|
||||
|
||||
#ifndef T_WATCH_S3
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
@ -183,7 +183,7 @@ 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))) {
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_LEFT)) {
|
||||
this->payload = 0xb4;
|
||||
} else if (event->inputEvent == static_cast<char>(meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_RIGHT)) {
|
||||
@ -283,7 +283,7 @@ int CannedMessageModule::handleInputEvent(const InputEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
if (this->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
String keyTapped = keyForCoordinates(event->touchX, event->touchY);
|
||||
|
||||
@ -404,7 +404,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#ifndef T_WATCH_S3
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@ -417,7 +417,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#ifndef T_WATCH_S3
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@ -437,7 +437,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
powerFSM.trigger(EVENT_PRESS);
|
||||
return INT32_MAX;
|
||||
} else {
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
sendText(this->dest, indexChannels[this->channel], this->messages[this->currentMessageIndex], true);
|
||||
#else
|
||||
sendText(NODENUM_BROADCAST, channels.getPrimaryIndex(), this->messages[this->currentMessageIndex], true);
|
||||
@ -454,7 +454,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#ifndef T_WATCH_S3
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@ -471,7 +471,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#ifndef T_WATCH_S3
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@ -484,7 +484,7 @@ int32_t CannedMessageModule::runOnce()
|
||||
this->freetext = ""; // clear freetext
|
||||
this->cursor = 0;
|
||||
|
||||
#ifndef T_WATCH_S3
|
||||
#if !defined(T_WATCH_S3) && !defined(RAK14014)
|
||||
this->destSelect = CANNED_MESSAGE_DESTINATION_TYPE_NONE;
|
||||
#endif
|
||||
|
||||
@ -714,7 +714,7 @@ void CannedMessageModule::showTemporaryMessage(const String &message)
|
||||
setIntervalFromNow(2000);
|
||||
}
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
|
||||
String CannedMessageModule::keyForCoordinates(uint x, uint y)
|
||||
{
|
||||
@ -950,7 +950,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st
|
||||
display->drawString(10 + x, 0 + y + FONT_HEIGHT_SMALL, "Canned Message\nModule disabled.");
|
||||
} else if (cannedMessageModule->runState == CANNED_MESSAGE_RUN_STATE_FREETEXT) {
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
drawKeyboard(display, state, 0, 0);
|
||||
#else
|
||||
|
||||
|
@ -98,7 +98,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
int getNextIndex();
|
||||
int getPrevIndex();
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
void drawKeyboard(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
String keyForCoordinates(uint x, uint y);
|
||||
bool shift = false;
|
||||
@ -152,7 +152,7 @@ class CannedMessageModule : public SinglePortModule, public Observable<const UIF
|
||||
unsigned long lastTouchMillis = 0;
|
||||
String temporaryMessage;
|
||||
|
||||
#ifdef T_WATCH_S3
|
||||
#if defined(T_WATCH_S3) || defined(RAK14014)
|
||||
Letter keyboard[2][4][10] = {{{{"Q", 20, 0, 0, 0, 0},
|
||||
{"W", 22, 0, 0, 0, 0},
|
||||
{"E", 17, 0, 0, 0, 0},
|
||||
|
95
src/modules/DropzoneModule.cpp
Normal file
95
src/modules/DropzoneModule.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
|
||||
#include "DropzoneModule.h"
|
||||
#include "MeshService.h"
|
||||
#include "configuration.h"
|
||||
#include "gps/GeoCoord.h"
|
||||
#include "gps/RTC.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "modules/Telemetry/Sensor/DFRobotLarkSensor.h"
|
||||
#include "modules/Telemetry/UnitConversions.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
DropzoneModule *dropzoneModule;
|
||||
|
||||
int32_t DropzoneModule::runOnce()
|
||||
{
|
||||
// Send on a 5 second delay from receiving the matching request
|
||||
if (startSendConditions != 0 && (startSendConditions + 5000U) < millis()) {
|
||||
service.sendToMesh(sendConditions(), RX_SRC_LOCAL);
|
||||
startSendConditions = 0;
|
||||
}
|
||||
// Run every second to check if we need to send conditions
|
||||
return 1000;
|
||||
}
|
||||
|
||||
ProcessMessage DropzoneModule::handleReceived(const meshtastic_MeshPacket &mp)
|
||||
{
|
||||
auto &p = mp.decoded;
|
||||
char matchCompare[54];
|
||||
auto incomingMessage = reinterpret_cast<const char *>(p.payload.bytes);
|
||||
sprintf(matchCompare, "%s conditions", owner.short_name);
|
||||
if (strncasecmp(incomingMessage, matchCompare, strlen(matchCompare)) == 0) {
|
||||
LOG_DEBUG("Received dropzone conditions request\n");
|
||||
startSendConditions = millis();
|
||||
}
|
||||
|
||||
sprintf(matchCompare, "%s conditions", owner.long_name);
|
||||
if (strncasecmp(incomingMessage, matchCompare, strlen(matchCompare)) == 0) {
|
||||
LOG_DEBUG("Received dropzone conditions request\n");
|
||||
startSendConditions = millis();
|
||||
}
|
||||
return ProcessMessage::CONTINUE;
|
||||
}
|
||||
|
||||
meshtastic_MeshPacket *DropzoneModule::sendConditions()
|
||||
{
|
||||
char replyStr[200];
|
||||
/*
|
||||
CLOSED @ {HH:MM:SS}z
|
||||
Wind 2 kts @ 125°
|
||||
29.25 inHg 72°C
|
||||
*/
|
||||
uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true);
|
||||
int hour = 0, min = 0, sec = 0;
|
||||
if (rtc_sec > 0) {
|
||||
long hms = rtc_sec % SEC_PER_DAY;
|
||||
hms = (hms + SEC_PER_DAY) % SEC_PER_DAY;
|
||||
|
||||
hour = hms / SEC_PER_HOUR;
|
||||
min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||
sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN;
|
||||
}
|
||||
|
||||
// Check if the dropzone is open or closed by reading the analog pin
|
||||
// If pin is connected to GND (below 100 should be lower than floating voltage),
|
||||
// the dropzone is open
|
||||
auto dropzoneStatus = analogRead(A1) < 100 ? "OPEN" : "CLOSED";
|
||||
auto reply = allocDataPacket();
|
||||
|
||||
auto node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
if (sensor.hasSensor()) {
|
||||
meshtastic_Telemetry telemetry = meshtastic_Telemetry_init_zero;
|
||||
sensor.getMetrics(&telemetry);
|
||||
auto windSpeed = UnitConversions::MetersPerSecondToKnots(telemetry.variant.environment_metrics.wind_speed);
|
||||
auto windDirection = telemetry.variant.environment_metrics.wind_direction;
|
||||
auto temp = telemetry.variant.environment_metrics.temperature;
|
||||
auto baro = UnitConversions::HectoPascalToInchesOfMercury(telemetry.variant.environment_metrics.barometric_pressure);
|
||||
sprintf(replyStr, "%s @ %02d:%02d:%02dz\nWind %.2f kts @ %d°\nBaro %.2f inHg %.2f°C", dropzoneStatus, hour, min, sec,
|
||||
windSpeed, windDirection, baro, temp);
|
||||
} else {
|
||||
LOG_ERROR("No sensor found\n");
|
||||
sprintf(replyStr, "%s @ %02d:%02d:%02d\nNo sensor found", dropzoneStatus, hour, min, sec);
|
||||
}
|
||||
LOG_DEBUG("Conditions reply: %s\n", replyStr);
|
||||
reply->decoded.payload.size = strlen(replyStr); // You must specify how many bytes are in the reply
|
||||
memcpy(reply->decoded.payload.bytes, replyStr, reply->decoded.payload.size);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
#endif
|
37
src/modules/DropzoneModule.h
Normal file
37
src/modules/DropzoneModule.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
#include "SinglePortModule.h"
|
||||
#include "modules/Telemetry/Sensor/DFRobotLarkSensor.h"
|
||||
|
||||
/**
|
||||
* An example module that replies to a message with the current conditions
|
||||
* and status at the dropzone when it receives a text message mentioning it's name followed by "conditions"
|
||||
*/
|
||||
class DropzoneModule : public SinglePortModule, private concurrency::OSThread
|
||||
{
|
||||
DFRobotLarkSensor sensor;
|
||||
|
||||
public:
|
||||
/** Constructor
|
||||
* name is for debugging output
|
||||
*/
|
||||
DropzoneModule() : SinglePortModule("dropzone", meshtastic_PortNum_TEXT_MESSAGE_APP), concurrency::OSThread("DropzoneModule")
|
||||
{
|
||||
// Set up the analog pin for reading the dropzone status
|
||||
pinMode(PIN_A1, INPUT);
|
||||
}
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
protected:
|
||||
/** Called to handle a particular incoming message
|
||||
*/
|
||||
virtual ProcessMessage handleReceived(const meshtastic_MeshPacket &mp) override;
|
||||
|
||||
private:
|
||||
meshtastic_MeshPacket *sendConditions();
|
||||
uint32_t startSendConditions = 0;
|
||||
};
|
||||
|
||||
extern DropzoneModule *dropzoneModule;
|
||||
#endif
|
@ -70,6 +70,11 @@
|
||||
#include "modules/SerialModule.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
#include "modules/DropzoneModule.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create module instances here. If you are adding a new module, you must 'new' it here (or somewhere else)
|
||||
*/
|
||||
@ -100,6 +105,10 @@ void setupModules()
|
||||
#if !MESHTASTIC_EXCLUDE_ATAK
|
||||
atakPluginModule = new AtakPluginModule();
|
||||
#endif
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_DROPZONE
|
||||
dropzoneModule = new DropzoneModule();
|
||||
#endif
|
||||
// Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance
|
||||
// to a global variable.
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef _MT_DFROBOTLARKSENSOR_H
|
||||
#define _MT_DFROBOTLARKSENSOR_H
|
||||
#include "configuration.h"
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||
@ -21,4 +25,5 @@ class DFRobotLarkSensor : public TelemetrySensor
|
||||
virtual bool getMetrics(meshtastic_Telemetry *measurement) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
21
src/modules/Telemetry/UnitConversions.cpp
Normal file
21
src/modules/Telemetry/UnitConversions.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "UnitConversions.h"
|
||||
|
||||
float UnitConversions::CelsiusToFahrenheit(float celcius)
|
||||
{
|
||||
return (celcius * 9) / 5 + 32;
|
||||
}
|
||||
|
||||
float UnitConversions::MetersPerSecondToKnots(float metersPerSecond)
|
||||
{
|
||||
return metersPerSecond * 1.94384;
|
||||
}
|
||||
|
||||
float UnitConversions::MetersPerSecondToMilesPerHour(float metersPerSecond)
|
||||
{
|
||||
return metersPerSecond * 2.23694;
|
||||
}
|
||||
|
||||
float UnitConversions::HectoPascalToInchesOfMercury(float hectoPascal)
|
||||
{
|
||||
return hectoPascal * 0.029529983071445;
|
||||
}
|
10
src/modules/Telemetry/UnitConversions.h
Normal file
10
src/modules/Telemetry/UnitConversions.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
class UnitConversions
|
||||
{
|
||||
public:
|
||||
static float CelsiusToFahrenheit(float celcius);
|
||||
static float MetersPerSecondToKnots(float metersPerSecond);
|
||||
static float MetersPerSecondToMilesPerHour(float metersPerSecond);
|
||||
static float HectoPascalToInchesOfMercury(float hectoPascal);
|
||||
};
|
@ -17,6 +17,8 @@ lib_deps =
|
||||
https://github.com/RAKWireless/RAK13800-W5100S.git#1.0.2
|
||||
rakwireless/RAKwireless NCP5623 RGB LED library@^1.0.2
|
||||
bodmer/TFT_eSPI
|
||||
beegee-tokyo/RAKwireless RAK12034@^1.0.0
|
||||
beegee-tokyo/RAK14014-FT6336U @ 1.0.1
|
||||
debug_tool = jlink
|
||||
; If not set we will default to uploading over serial (first it forces bootloader entry by talking 1200bps to cdcacm)
|
||||
;upload_protocol = jlink
|
@ -307,10 +307,10 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
|
||||
#define SCREEN_ROTATE
|
||||
#define SCREEN_TRANSITION_FRAMERATE 5
|
||||
|
||||
#define HAS_TOUCHSCREEN 0
|
||||
#define SCREEN_TOUCH_INT 10 // From tp.h on the tracker open source code.
|
||||
#define TOUCH_I2C_PORT 0
|
||||
#define TOUCH_SLAVE_ADDRESS 0x5D // GT911
|
||||
#define HAS_TOUCHSCREEN 1
|
||||
#define SCREEN_TOUCH_INT WB_IO6
|
||||
|
||||
#define CANNED_MESSAGE_MODULE_ENABLE 1
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Arduino objects - C++ only
|
||||
|
Loading…
Reference in New Issue
Block a user