Skip to content

Commit

Permalink
Merge pull request meshtastic#3544 from garethhcoleman/unphone
Browse files Browse the repository at this point in the history
New device unPhone using HX8357D LCD and XPT2046 touchscreen
  • Loading branch information
caveman99 authored Apr 4, 2024
2 parents f0b6ff9 + 4cdfae7 commit 9b2d862
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 16 deletions.
15 changes: 8 additions & 7 deletions src/graphics/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
{
char usersString[20];
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
Expand Down Expand Up @@ -955,7 +955,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
#elif defined(USE_SSD1306)
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
Expand Down Expand Up @@ -1101,7 +1101,7 @@ void Screen::setup()
// Standard behaviour is to FLIP the screen (needed on T-Beam). If this config item is set, unflip it, and thereby logically
// flip it. If you have a headache now, you're welcome.
if (!config.display.flip_screen) {
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014)
#if defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
#else
dispdev->flipScreenVertically();
Expand Down Expand Up @@ -1686,7 +1686,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#ifdef ARCH_ESP32
if (millis() - storeForwardModule->lastHeartbeat >
(storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
Expand All @@ -1697,7 +1697,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
imgQuestion);
#endif
} else {
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1);
Expand All @@ -1711,7 +1711,8 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#endif
} else {
// TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1);
Expand Down Expand Up @@ -1974,4 +1975,4 @@ int Screen::handleInputEvent(const InputEvent *event)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN
2 changes: 1 addition & 1 deletion src/graphics/ScreenFonts.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "graphics/fonts/OLEDDisplayFontsUA.h"
#endif

#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS)) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
Expand Down
113 changes: 110 additions & 3 deletions src/graphics/TFTDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,95 @@ class LGFX : public lgfx::LGFX_Device
};

static LGFX *tft = nullptr;

#elif defined(HX8357_CS)
#include <LovyanGFX.hpp> // Graphics and font library for HX8357 driver chip

class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_HX8357D _panel_instance;
lgfx::Bus_SPI _bus_instance;
#if defined(USE_XPT2046)
lgfx::ITouch *_touch_instance;
// lgfx::Touch_XPT2046 _touch_instance;
#endif

#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || \
public:
LGFX(void)
{
// Panel_HX8357D
{
// configure SPI
auto cfg = _bus_instance.config();

cfg.spi_host = HX8357_SPI_HOST;
cfg.spi_mode = 0;
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = HX8357_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = HX8357_MOSI; // Set SPI MOSI pin number
cfg.pin_miso = HX8357_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = HX8357_RS; // Set SPI DC pin number (-1 = disable)

_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
}
{
// Set the display panel control.
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.

cfg.pin_cs = HX8357_CS; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = HX8357_RESET; // Pin number where RST is connected (-1 = disable)
cfg.pin_busy = HX8357_BUSY; // Pin number where BUSY is connected (-1 = disable)

cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is upside down)
cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = TFT_INVERT; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit = false;
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)

_panel_instance.config(cfg);
}
#if defined(USE_XPT2046)
{
// Configure settings for touch control.
_touch_instance = new lgfx::Touch_XPT2046;
auto touch_cfg = _touch_instance->config();

touch_cfg.pin_cs = TOUCH_CS;
touch_cfg.x_min = 0;
touch_cfg.x_max = TFT_HEIGHT - 1;
touch_cfg.y_min = 0;
touch_cfg.y_max = TFT_WIDTH - 1;
touch_cfg.pin_int = -1;
touch_cfg.bus_shared = true;
touch_cfg.offset_rotation = 1;

_touch_instance->config(touch_cfg);
//_panel_instance->setTouch(_touch_instance);
}
#endif
setPanel(&_panel_instance);
}
};

static LGFX *tft = nullptr;

#endif

#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || \
(ARCH_PORTDUINO && HAS_SCREEN != 0)
#include "SPILock.h"
#include "TFTDisplay.h"
Expand Down Expand Up @@ -487,7 +573,13 @@ void TFTDisplay::sendCommand(uint8_t com)
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, LOW);
#endif

#ifdef UNPHONE
Wire.beginTransmission(0x26);
Wire.write(0x02);
Wire.write(0x04); // Backlight on
Wire.write(0x22); // G&B LEDs off
Wire.endTransmission();
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
tft->setBrightness(172);
Expand All @@ -514,6 +606,13 @@ void TFTDisplay::sendCommand(uint8_t com)
#ifdef VTFT_CTRL
digitalWrite(VTFT_CTRL, HIGH);
#endif
#ifdef UNPHONE
Wire.beginTransmission(0x26);
Wire.write(0x02);
Wire.write(0x00); // Backlight off
Wire.write(0x22); // G&B LEDs off
Wire.endTransmission();
#endif
#ifdef RAK14014
#elif !defined(M5STACK)
tft->setBrightness(0);
Expand Down Expand Up @@ -585,6 +684,14 @@ bool TFTDisplay::connect()
pinMode(ST7735_BL_V05, OUTPUT);
digitalWrite(ST7735_BL_V05, TFT_BACKLIGHT_ON);
#endif
#ifdef UNPHONE
Wire.beginTransmission(0x26);
Wire.write(0x02);
Wire.write(0x04); // Backlight on
Wire.write(0x22); // G&B LEDs off
Wire.endTransmission();
LOG_INFO("Power to TFT Backlight\n");
#endif

tft->init();

Expand All @@ -606,4 +713,4 @@ bool TFTDisplay::connect()
return true;
}

#endif
#endif
5 changes: 3 additions & 2 deletions src/graphics/images.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3
const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF};
const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF};

#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || ARCH_PORTDUINO) && \
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) || defined(HX8357_CS) || \
ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
Expand All @@ -30,4 +31,4 @@ const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1,
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
#endif

#include "img/icon.xbm"
#include "img/icon.xbm"
18 changes: 16 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,20 @@ void setup()
if (config.display.oled != meshtastic_Config_DisplayConfig_OledType_OLED_AUTO)
screen_model = config.display.oled;

#ifdef UNPHONE
// initialise IO expander with pinmodes
Wire.beginTransmission(0x26);
Wire.write(0x06);
Wire.write(0x7A);
Wire.write(0xDD);
Wire.endTransmission();
Wire.beginTransmission(0x26);
Wire.write(0x02);
Wire.write(0x04); // Backlight on
Wire.write(0x22); // G&B LEDs off
Wire.endTransmission();
#endif

#if defined(USE_SH1107)
screen_model = meshtastic_Config_DisplayConfig_OledType_OLED_SH1107; // set dimension of 128x128
display_geometry = GEOMETRY_128_128;
Expand Down Expand Up @@ -686,7 +700,7 @@ void setup()

// Don't call screen setup until after nodedb is setup (because we need
// the current region name)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS)
#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) || defined(HX8357_CS)
screen->setup();
#elif defined(ARCH_PORTDUINO)
if (screen_found.port != ScanI2C::I2CPort::NO_I2C || settingsMap[displayPanel]) {
Expand Down Expand Up @@ -986,4 +1000,4 @@ void loop()
mainDelay.delay(delayMsec);
}
// if (didWake) LOG_DEBUG("wake!\n");
}
}
4 changes: 3 additions & 1 deletion src/platform/esp32/architecture.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@
#define HW_VENDOR meshtastic_HardwareModel_CHATTER_2
#elif defined(STATION_G2)
#define HW_VENDOR meshtastic_HardwareModel_STATION_G2
#elif defined(UNPHONE)
#define HW_VENDOR meshtastic_HardwareModel_UNPHONE
#endif

// -----------------------------------------------------------------------------
Expand All @@ -157,4 +159,4 @@
#define LORA_CS 18
#endif

#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 // FIXME: may be different on ESP32-S3, etc.
#define SERIAL0_RX_GPIO 3 // Always GPIO3 on ESP32 // FIXME: may be different on ESP32-S3, etc.
16 changes: 16 additions & 0 deletions variants/unphone/platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[env:unphone]
;build_type = debug ; to make it possible to step through our jtag debugger
extends = esp32s3_base
board_level = extra
board = unphone9
upload_speed = 921600
monitor_speed = 115200
monitor_filters = esp32_exception_decoder

build_flags = ${esp32_base.build_flags}
-D UNPHONE
-D BOARD_HAS_PSRAM
-I variants/unphone

lib_deps = ${esp32s3_base.lib_deps}
lovyan03/LovyanGFX@^1.1.8
61 changes: 61 additions & 0 deletions variants/unphone/variant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#define SPI_SCK 39
#define SPI_MOSI 40
#define SPI_MISO 41

// We use the RFM95W LoRa module
#define USE_RF95
#define LORA_SCK SPI_SCK
#define LORA_MOSI SPI_MOSI
#define LORA_MISO SPI_MISO
#define LORA_CS 44
#define LORA_DIO0 10 // AKA LORA_IRQ
#define LORA_RESET 42
#define LORA_DIO1 11
#define LORA_DIO2 RADIOLIB_NC // Not really used

// HX8357 TFT LCD
#define HX8357_CS 48
#define HX8357_RS 47 // AKA DC
#define HX8357_RESET 46
#define HX8357_SCK SPI_SCK
#define HX8357_MOSI SPI_MOSI
#define HX8357_MISO SPI_MISO
#define HX8357_BUSY -1
#define HX8357_SPI_HOST SPI2_HOST
#define SPI_FREQUENCY 40000000
#define SPI_READ_FREQUENCY 16000000
#define TFT_HEIGHT 480
#define TFT_WIDTH 320
#define TFT_OFFSET_X 0
#define TFT_OFFSET_Y 0
#define TFT_OFFSET_ROTATION 6 // the unPhone's screen is wired unusually, 0 is typical value here
#define TFT_INVERT false
#define SCREEN_ROTATE true
#define SCREEN_TRANSITION_FRAMERATE 5

#define HAS_TOUCHSCREEN 1
#define USE_XPT2046 1
#define TOUCH_CS 38

#define HAS_GPS 0 // the unphone doesn't have a gps module
#undef GPS_RX_PIN
#undef GPS_TX_PIN

#define HAS_SDCARD 1
#define SDCARD_CS 43

#define LED_PIN 13 // the red part of the RGB LED
#define LED_INVERTED 1

#define BUTTON_PIN 21 // Button 3 - square - top button in landscape mode
#define BUTTON_NEED_PULLUP // we do need a helping hand up

#define I2C_SDA 3 // I2C pins for this board
#define I2C_SCL 4

// ratio of voltage divider = 3.20 (R1=100k, R2=220k)
// #define ADC_MULTIPLIER 3.2

// #define BATTERY_PIN 13 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
// #define ADC_CHANNEL ADC2_GPIO13_CHANNEL
// #define BAT_MEASURE_ADC_UNIT 2

0 comments on commit 9b2d862

Please sign in to comment.