mirror of https://github.com/meshcore-dev/MeshCore
committed by
GitHub
6 changed files with 427 additions and 0 deletions
@ -0,0 +1,125 @@ |
|||||
|
#include "LGFXDisplay.h" |
||||
|
|
||||
|
bool LGFXDisplay::begin() { |
||||
|
turnOn(); |
||||
|
display->init(); |
||||
|
display->setRotation(1); |
||||
|
display->setBrightness(64); |
||||
|
display->setColorDepth(8); |
||||
|
display->setTextColor(TFT_WHITE); |
||||
|
|
||||
|
buffer.setColorDepth(8); |
||||
|
buffer.setPsram(true); |
||||
|
buffer.createSprite(width(), height()); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::turnOn() { |
||||
|
// display->wakeup();
|
||||
|
if (!_isOn) { |
||||
|
display->wakeup(); |
||||
|
} |
||||
|
_isOn = true; |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::turnOff() { |
||||
|
if (_isOn) { |
||||
|
display->sleep(); |
||||
|
} |
||||
|
_isOn = false; |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::clear() { |
||||
|
// display->clearDisplay();
|
||||
|
buffer.clearDisplay(); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::startFrame(Color bkg) { |
||||
|
// display->startWrite();
|
||||
|
// display->getScanLine();
|
||||
|
buffer.clearDisplay(); |
||||
|
buffer.setTextColor(TFT_WHITE); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::setTextSize(int sz) { |
||||
|
buffer.setTextSize(sz); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::setColor(Color c) { |
||||
|
// _color = (c != 0) ? ILI9342_WHITE : ILI9342_BLACK;
|
||||
|
switch (c) { |
||||
|
case DARK: |
||||
|
_color = TFT_BLACK; |
||||
|
break; |
||||
|
case LIGHT: |
||||
|
_color = TFT_WHITE; |
||||
|
break; |
||||
|
case RED: |
||||
|
_color = TFT_RED; |
||||
|
break; |
||||
|
case GREEN: |
||||
|
_color = TFT_GREEN; |
||||
|
break; |
||||
|
case BLUE: |
||||
|
_color = TFT_BLUE; |
||||
|
break; |
||||
|
case YELLOW: |
||||
|
_color = TFT_YELLOW; |
||||
|
break; |
||||
|
case ORANGE: |
||||
|
_color = TFT_ORANGE; |
||||
|
break; |
||||
|
default: |
||||
|
_color = TFT_WHITE; |
||||
|
} |
||||
|
buffer.setTextColor(_color); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::setCursor(int x, int y) { |
||||
|
buffer.setCursor(x, y); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::print(const char* str) { |
||||
|
buffer.println(str); |
||||
|
// Serial.println(str);
|
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::fillRect(int x, int y, int w, int h) { |
||||
|
buffer.fillRect(x, y, w, h, _color); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::drawRect(int x, int y, int w, int h) { |
||||
|
buffer.drawRect(x, y, w, h, _color); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) { |
||||
|
buffer.drawBitmap(x, y, bits, w, h, _color); |
||||
|
} |
||||
|
|
||||
|
uint16_t LGFXDisplay::getTextWidth(const char* str) { |
||||
|
return buffer.textWidth(str); |
||||
|
} |
||||
|
|
||||
|
void LGFXDisplay::endFrame() { |
||||
|
display->startWrite(); |
||||
|
if (UI_ZOOM != 1) { |
||||
|
buffer.pushRotateZoom(display, display->width()/2, display->height()/2 , 0, UI_ZOOM, UI_ZOOM); |
||||
|
} else { |
||||
|
buffer.pushSprite(display, 0, 0); |
||||
|
} |
||||
|
display->endWrite(); |
||||
|
} |
||||
|
|
||||
|
bool LGFXDisplay::getTouch(int *x, int *y) { |
||||
|
lgfx::v1::touch_point_t point; |
||||
|
display->getTouch(&point); |
||||
|
if (UI_ZOOM != 1) { |
||||
|
*x = point.x / UI_ZOOM; |
||||
|
*y = point.y / UI_ZOOM; |
||||
|
} else { |
||||
|
*x = point.x; |
||||
|
*y = point.y; |
||||
|
} |
||||
|
return (*x >= 0) && (*y >= 0); |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <helpers/ui/DisplayDriver.h> |
||||
|
|
||||
|
#define LGFX_USE_V1 |
||||
|
#include <LovyanGFX.hpp> |
||||
|
|
||||
|
#ifndef UI_ZOOM |
||||
|
#define UI_ZOOM 1 |
||||
|
#endif |
||||
|
|
||||
|
class LGFXDisplay : public DisplayDriver { |
||||
|
protected: |
||||
|
LGFX_Device* display; |
||||
|
LGFX_Sprite buffer; |
||||
|
|
||||
|
bool _isOn = false; |
||||
|
int _color = TFT_WHITE; |
||||
|
|
||||
|
public: |
||||
|
LGFXDisplay(int w, int h, LGFX_Device &disp) |
||||
|
: DisplayDriver(w/UI_ZOOM, h/UI_ZOOM), display(&disp) {} |
||||
|
bool begin(); |
||||
|
bool isOn() override { return _isOn; } |
||||
|
void turnOn() override; |
||||
|
void turnOff() override; |
||||
|
void clear() override; |
||||
|
void startFrame(Color bkg = DARK) override; |
||||
|
void setTextSize(int sz) override; |
||||
|
void setColor(Color c) override; |
||||
|
void setCursor(int x, int y) override; |
||||
|
void print(const char* str) override; |
||||
|
void fillRect(int x, int y, int w, int h) override; |
||||
|
void drawRect(int x, int y, int w, int h) override; |
||||
|
void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override; |
||||
|
uint16_t getTextWidth(const char* str) override; |
||||
|
void endFrame() override; |
||||
|
virtual bool getTouch(int *x, int *y); |
||||
|
}; |
||||
@ -0,0 +1,128 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <helpers/ui/LGFXDisplay.h> |
||||
|
|
||||
|
#define LGFX_USE_V1 |
||||
|
#include <LovyanGFX.hpp> |
||||
|
|
||||
|
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp> |
||||
|
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp> |
||||
|
|
||||
|
class LGFX : public lgfx::LGFX_Device |
||||
|
{ |
||||
|
lgfx::Panel_ST7701 _panel_instance; |
||||
|
lgfx::Bus_RGB _bus_instance; |
||||
|
lgfx::Light_PWM _light_instance; |
||||
|
lgfx::Touch_FT5x06 _touch_instance; |
||||
|
|
||||
|
public: |
||||
|
const uint16_t screenWidth = 480; |
||||
|
const uint16_t screenHeight = 480; |
||||
|
|
||||
|
bool hasButton(void) { return true; } |
||||
|
|
||||
|
LGFX(void) |
||||
|
{ |
||||
|
{ |
||||
|
auto cfg = _panel_instance.config(); |
||||
|
cfg.memory_width = 480; |
||||
|
cfg.memory_height = 480; |
||||
|
cfg.panel_width = screenWidth; |
||||
|
cfg.panel_height = screenHeight; |
||||
|
cfg.offset_x = 0; |
||||
|
cfg.offset_y = 0; |
||||
|
cfg.offset_rotation = 1; |
||||
|
_panel_instance.config(cfg); |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
auto cfg = _panel_instance.config_detail(); |
||||
|
cfg.pin_cs = 4 | IO_EXPANDER; |
||||
|
cfg.pin_sclk = 41; |
||||
|
cfg.pin_mosi = 48; |
||||
|
cfg.use_psram = 1; |
||||
|
_panel_instance.config_detail(cfg); |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
auto cfg = _bus_instance.config(); |
||||
|
cfg.panel = &_panel_instance; |
||||
|
|
||||
|
cfg.freq_write = 8000000; |
||||
|
cfg.pin_henable = 18; |
||||
|
|
||||
|
cfg.pin_pclk = 21; |
||||
|
cfg.pclk_active_neg = 0; |
||||
|
cfg.pclk_idle_high = 0; |
||||
|
cfg.de_idle_high = 1; |
||||
|
|
||||
|
cfg.pin_hsync = 16; |
||||
|
cfg.hsync_polarity = 0; |
||||
|
cfg.hsync_front_porch = 10; |
||||
|
cfg.hsync_pulse_width = 8; |
||||
|
cfg.hsync_back_porch = 50; |
||||
|
|
||||
|
cfg.pin_vsync = 17; |
||||
|
cfg.vsync_polarity = 0; |
||||
|
cfg.vsync_front_porch = 10; |
||||
|
cfg.vsync_pulse_width = 8; |
||||
|
cfg.vsync_back_porch = 20; |
||||
|
|
||||
|
cfg.pin_d0 = 15; |
||||
|
cfg.pin_d1 = 14; |
||||
|
cfg.pin_d2 = 13; |
||||
|
cfg.pin_d3 = 12; |
||||
|
cfg.pin_d4 = 11; |
||||
|
cfg.pin_d5 = 10; |
||||
|
cfg.pin_d6 = 9; |
||||
|
cfg.pin_d7 = 8; |
||||
|
cfg.pin_d8 = 7; |
||||
|
cfg.pin_d9 = 6; |
||||
|
cfg.pin_d10 = 5; |
||||
|
cfg.pin_d11 = 4; |
||||
|
cfg.pin_d12 = 3; |
||||
|
cfg.pin_d13 = 2; |
||||
|
cfg.pin_d14 = 1; |
||||
|
cfg.pin_d15 = 0; |
||||
|
|
||||
|
_bus_instance.config(cfg); |
||||
|
} |
||||
|
_panel_instance.setBus(&_bus_instance); |
||||
|
|
||||
|
{ |
||||
|
auto cfg = _light_instance.config(); |
||||
|
cfg.pin_bl = 45; |
||||
|
_light_instance.config(cfg); |
||||
|
} |
||||
|
_panel_instance.light(&_light_instance); |
||||
|
|
||||
|
{ |
||||
|
auto cfg = _touch_instance.config(); |
||||
|
cfg.pin_cs = GPIO_NUM_NC; |
||||
|
cfg.x_min = 0; |
||||
|
cfg.x_max = 479; |
||||
|
cfg.y_min = 0; |
||||
|
cfg.y_max = 479; |
||||
|
cfg.pin_int = GPIO_NUM_NC; |
||||
|
cfg.pin_rst = GPIO_NUM_NC; |
||||
|
cfg.bus_shared = true; |
||||
|
cfg.offset_rotation = 0; |
||||
|
|
||||
|
cfg.i2c_port = 0; |
||||
|
cfg.i2c_addr = 0x48; |
||||
|
cfg.pin_sda = 39; |
||||
|
cfg.pin_scl = 40; |
||||
|
cfg.freq = 400000; |
||||
|
_touch_instance.config(cfg); |
||||
|
_panel_instance.setTouch(&_touch_instance); |
||||
|
} |
||||
|
|
||||
|
setPanel(&_panel_instance); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
class SCIndicatorDisplay : public LGFXDisplay { |
||||
|
LGFX disp; |
||||
|
public: |
||||
|
SCIndicatorDisplay() : LGFXDisplay(480, 480, disp) {} |
||||
|
}; |
||||
@ -0,0 +1,50 @@ |
|||||
|
[SenseCapIndicator-ESPNow] |
||||
|
extends = esp32_base |
||||
|
board = esp32-s3-devkitc-1 |
||||
|
board_build.arduino.memory_type = qio_opi |
||||
|
board_build.flash_mode = qio |
||||
|
board_build.psram_type = opi |
||||
|
board_upload.flash_size = 8MB |
||||
|
board_upload.maximum_size = 8388608 |
||||
|
board_build.partitions = default.csv |
||||
|
build_flags = |
||||
|
${esp32_base.build_flags} |
||||
|
-D PIN_BOARD_SDA=39 |
||||
|
-D PIN_BOARD_SCL=40 |
||||
|
-D DISPLAY_CLASS=SCIndicatorDisplay |
||||
|
-D DISPLAY_LINES=21 |
||||
|
-D LINE_LENGTH=53 |
||||
|
-D DISABLE_WIFI_OTA=1 |
||||
|
-D IO_EXPANDER=0x40 |
||||
|
-D IO_EXPANDER_IRQ=42 |
||||
|
-D UI_ZOOM=3.5 |
||||
|
-D UI_RECENT_LIST_SIZE=9 |
||||
|
-D UI_SENSORS_PAGE=1 |
||||
|
-D PIN_USER_BTN=38 |
||||
|
-D HAS_TOUCH |
||||
|
-I variants/sensecap_indicator-espnow |
||||
|
build_src_filter = ${esp32_base.build_src_filter} |
||||
|
+<../variants/sensecap_indicator-espnow/*.cpp> |
||||
|
+<helpers/esp32/ESPNOWRadio.cpp> |
||||
|
+<helpers/ui/LGFXDisplay.cpp> |
||||
|
+<helpers/sensors/*> |
||||
|
lib_deps=${esp32_base.lib_deps} |
||||
|
adafruit/Adafruit BusIO @ ^1.17.2 |
||||
|
lovyan03/LovyanGFX @ ^1.2.7 |
||||
|
|
||||
|
[env:SenseCapIndicator-ESPNow_comp_radio_usb] |
||||
|
extends =SenseCapIndicator-ESPNow |
||||
|
build_flags = |
||||
|
${SenseCapIndicator-ESPNow.build_flags} |
||||
|
-I examples/companion_radio/ui-new |
||||
|
-D MAX_CONTACTS=300 |
||||
|
-D MAX_GROUP_CHANNELS=8 |
||||
|
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1 |
||||
|
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1 |
||||
|
; NOTE: DO NOT ENABLE --> -D ESPNOW_DEBUG_LOGGING=1 |
||||
|
build_src_filter = ${SenseCapIndicator-ESPNow.build_src_filter} |
||||
|
+<../examples/companion_radio/ui-new/*.cpp> |
||||
|
+<../examples/companion_radio/*.cpp> |
||||
|
lib_deps = |
||||
|
${SenseCapIndicator-ESPNow.lib_deps} |
||||
|
densaugeo/base64 @ ~1.4.0 |
||||
@ -0,0 +1,56 @@ |
|||||
|
#include <Arduino.h> |
||||
|
#include "target.h" |
||||
|
#include <helpers/ArduinoHelpers.h> |
||||
|
|
||||
|
ESP32Board board; |
||||
|
|
||||
|
ESPNOWRadio radio_driver; |
||||
|
|
||||
|
ESP32RTCClock rtc_clock; |
||||
|
#if defined(ENV_INCLUDE_GPS) |
||||
|
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, (mesh::RTCClock*)&rtc_clock); |
||||
|
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); |
||||
|
#else |
||||
|
EnvironmentSensorManager sensors = EnvironmentSensorManager(); |
||||
|
#endif |
||||
|
|
||||
|
#ifdef DISPLAY_CLASS |
||||
|
DISPLAY_CLASS display; |
||||
|
#ifdef PIN_USER_BTN |
||||
|
MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true); |
||||
|
#endif |
||||
|
#endif |
||||
|
|
||||
|
bool radio_init() { |
||||
|
rtc_clock.begin(); |
||||
|
|
||||
|
radio_driver.init(); |
||||
|
|
||||
|
return true; // success
|
||||
|
} |
||||
|
|
||||
|
uint32_t radio_get_rng_seed() { |
||||
|
return millis() + radio_driver.intID(); // TODO: where to get some entropy?
|
||||
|
} |
||||
|
|
||||
|
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { |
||||
|
// no-op
|
||||
|
} |
||||
|
|
||||
|
void radio_set_tx_power(uint8_t dbm) { |
||||
|
radio_driver.setTxPower(dbm); |
||||
|
} |
||||
|
|
||||
|
// NOTE: as we are using the WiFi radio, the ESP_IDF will have enabled hardware RNG:
|
||||
|
// https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/random.html
|
||||
|
class ESP_RNG : public mesh::RNG { |
||||
|
public: |
||||
|
void random(uint8_t* dest, size_t sz) override { |
||||
|
esp_fill_random(dest, sz); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
mesh::LocalIdentity radio_new_identity() { |
||||
|
ESP_RNG rng; |
||||
|
return mesh::LocalIdentity(&rng); // create new random identity
|
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <helpers/ESP32Board.h> |
||||
|
#include <helpers/esp32/ESPNOWRadio.h> |
||||
|
#include <helpers/SensorManager.h> |
||||
|
#include <helpers/sensors/EnvironmentSensorManager.h> |
||||
|
#ifdef ENV_INCLUDE_GPS |
||||
|
#include <helpers/sensors/MicroNMEALocationProvider.h> |
||||
|
#endif |
||||
|
#ifdef DISPLAY_CLASS |
||||
|
#include "SCIndicatorDisplay.h" |
||||
|
#include <helpers/ui/MomentaryButton.h> |
||||
|
#endif |
||||
|
|
||||
|
extern ESP32Board board; |
||||
|
extern ESPNOWRadio radio_driver; |
||||
|
extern ESP32RTCClock rtc_clock; |
||||
|
extern EnvironmentSensorManager sensors; |
||||
|
|
||||
|
#ifdef DISPLAY_CLASS |
||||
|
extern DISPLAY_CLASS display; |
||||
|
extern MomentaryButton user_btn; |
||||
|
#endif |
||||
|
|
||||
|
bool radio_init(); |
||||
|
uint32_t radio_get_rng_seed(); |
||||
|
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); |
||||
|
void radio_set_tx_power(uint8_t dbm); |
||||
|
mesh::LocalIdentity radio_new_identity(); |
||||
Loading…
Reference in new issue