Эх сурвалжийг харах

Merge pull request #889 from fdlamotte/sensecap_indicator

Sensecap indicator
ripplebiz 9 сар өмнө
parent
commit
5b4544b9fe

+ 125 - 0
src/helpers/ui/LGFXDisplay.cpp

@@ -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);
+}

+ 39 - 0
src/helpers/ui/LGFXDisplay.h

@@ -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);
+};

+ 128 - 0
variants/sensecap_indicator-espnow/SCIndicatorDisplay.h

@@ -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) {}
+};

+ 50 - 0
variants/sensecap_indicator-espnow/platformio.ini

@@ -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

+ 56 - 0
variants/sensecap_indicator-espnow/target.cpp

@@ -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
+}

+ 29 - 0
variants/sensecap_indicator-espnow/target.h

@@ -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();