mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-25 01:42:15 +00:00
eink display now kinda works
This commit is contained in:
parent
b0bbf95b03
commit
d88d2780f4
@ -234,9 +234,11 @@ board = eink
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/eink
|
||||
-DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/eink>
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
https://github.com/geeksville/EPD_Libraries.git
|
||||
TFT_eSPI
|
||||
|
||||
; The https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay board by @BigCorvus
|
||||
|
@ -14,10 +14,16 @@ bool NMEAGPS::setup()
|
||||
{
|
||||
#ifdef PIN_GPS_WAKE
|
||||
// FIXME, support using this pin to control GPS sleep
|
||||
// digitalWrite(PIN_GPS_WAKE, LOW);
|
||||
// digitalWrite(PIN_GPS_WAKE, HIGH);
|
||||
// pinMode(PIN_GPS_WAKE, OUTPUT);
|
||||
#endif
|
||||
|
||||
#ifdef PIN_GPS_PPS
|
||||
// pulse per second
|
||||
// FIXME - move into shared GPS code
|
||||
pinMode(PIN_GPS_PPS, INPUT);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
125
src/graphics/EInkDisplay.cpp
Normal file
125
src/graphics/EInkDisplay.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include "configuration.h"
|
||||
|
||||
#ifdef HAS_EINK
|
||||
#include "EInkDisplay.h"
|
||||
#include "SPILock.h"
|
||||
#include "epd1in54.h" // Screen specific library
|
||||
#include "graphics/configs.h"
|
||||
#include <SPI.h>
|
||||
#include <TFT_eSPI.h> // Graphics library and Sprite class
|
||||
|
||||
Epd ePaper; // Create an instance ePaper
|
||||
|
||||
TFT_eSPI glc = TFT_eSPI(); // Invoke the graphics library class
|
||||
TFT_eSprite frame = TFT_eSprite(&glc); // Invoke the Sprite class for the image frame buffer
|
||||
uint8_t *framePtr; // Pointer for the black frame buffer
|
||||
|
||||
#define COLORED 0
|
||||
#define UNCOLORED 1
|
||||
|
||||
#define INK COLORED // Black ink
|
||||
#define PAPER UNCOLORED // 'paper' background colour
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Update display - different displays have different function names in the default
|
||||
// Waveshare libraries :-(
|
||||
//------------------------------------------------------------------------------------
|
||||
#if defined(EPD1IN54B_H) || defined(EPD1IN54C_H) || defined(EPD2IN13B_H) || defined(EPD2IN7B_H) || defined(EPD2IN9B_H) || \
|
||||
defined(EPD4IN2_H)
|
||||
void updateDisplay(uint8_t *blackFrame = blackFramePtr, uint8_t *redFrame = redFramePtr)
|
||||
{
|
||||
ePaper.DisplayFrame(blackFrame, redFrame); // Update 3 colour display
|
||||
#else
|
||||
void updateDisplay(uint8_t *blackFrame = framePtr)
|
||||
{
|
||||
#if defined(EPD2IN7_H) || defined(EPD4IN2_H)
|
||||
ePaper.DisplayFrame(blackFrame); // Update 2 color display
|
||||
|
||||
#elif defined(EPD1IN54_H) || defined(EPD2IN13_H) || defined(EPD2IN9_H)
|
||||
ePaper.SetFrameMemory(blackFrame); // Update 2 colour display
|
||||
ePaper.DisplayFrame();
|
||||
#else
|
||||
#error "Selected ePaper library is not supported"
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
|
||||
{
|
||||
setGeometry(GEOMETRY_128_64); // FIXME - currently we lie and claim 128x64 because I'm not yet sure other resolutions will
|
||||
// work ie GEOMETRY_RAWMODE
|
||||
}
|
||||
|
||||
// FIXME quick hack to limit drawing to a very slow rate
|
||||
uint32_t lastDrawMsec;
|
||||
|
||||
// Write the buffer to the display memory
|
||||
void EInkDisplay::display(void)
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
|
||||
uint32_t now = millis();
|
||||
uint32_t sinceLast = now - lastDrawMsec;
|
||||
|
||||
if (framePtr && (sinceLast > 30 * 1000 || lastDrawMsec == 0)) {
|
||||
lastDrawMsec = now;
|
||||
|
||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
||||
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
|
||||
for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) {
|
||||
for (uint8_t x = 0; x < SCREEN_WIDTH; x++) {
|
||||
|
||||
// get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent
|
||||
auto b = buffer[x + (y / 8) * SCREEN_WIDTH];
|
||||
auto isset = b & (1 << (y & 7));
|
||||
frame.drawPixel(x, y, isset ? INK : PAPER);
|
||||
}
|
||||
}
|
||||
|
||||
updateDisplay(); // Send image to display and refresh
|
||||
|
||||
// Put screen to sleep to save power (if wanted)
|
||||
// ePaper.Sleep();
|
||||
}
|
||||
}
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
void EInkDisplay::sendCommand(uint8_t com)
|
||||
{
|
||||
(void)com;
|
||||
// Drop all commands to device (we just update the buffer)
|
||||
}
|
||||
|
||||
// Connect to the display
|
||||
bool EInkDisplay::connect()
|
||||
{
|
||||
DEBUG_MSG("Doing EInk init\n");
|
||||
|
||||
#ifdef PIN_EINK_EN
|
||||
digitalWrite(PIN_EINK_EN, HIGH);
|
||||
pinMode(PIN_EINK_EN, OUTPUT);
|
||||
#endif
|
||||
|
||||
// Initialise the ePaper library
|
||||
// FIXME - figure out how to use lut_partial_update
|
||||
if (ePaper.Init(lut_full_update) != 0) {
|
||||
DEBUG_MSG("ePaper init failed\n");
|
||||
return false;
|
||||
} else {
|
||||
frame.setColorDepth(1); // Must set the bits per pixel to 1 for ePaper displays
|
||||
// Set bit depth BEFORE creating Sprite, default is 16!
|
||||
|
||||
// Create a frame buffer in RAM of defined size and save the pointer to it
|
||||
// RAM needed is about (EPD_WIDTH * EPD_HEIGHT)/8 , ~5000 bytes for 200 x 200 pixels
|
||||
// Note: always create the Sprite before setting the Sprite rotation
|
||||
framePtr = (uint8_t *)frame.createSprite(EPD_WIDTH, EPD_HEIGHT);
|
||||
|
||||
frame.fillSprite(PAPER); // Fill frame with white
|
||||
/* frame.drawLine(0, 0, frame.width() - 1, frame.height() - 1, INK);
|
||||
frame.drawLine(0, frame.height() - 1, frame.width() - 1, 0, INK);
|
||||
updateDisplay(); */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
35
src/graphics/EInkDisplay.h
Normal file
35
src/graphics/EInkDisplay.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <OLEDDisplay.h>
|
||||
|
||||
/**
|
||||
* An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation.
|
||||
*
|
||||
* Remaining TODO:
|
||||
* optimize display() to only draw changed pixels (see other OLED subclasses for examples)
|
||||
* implement displayOn/displayOff to turn off the TFT device (and backlight)
|
||||
* Use the fast NRF52 SPI API rather than the slow standard arduino version
|
||||
*
|
||||
* turn radio back on - currently with both on spi bus is fucked? or are we leaving chip select asserted?
|
||||
*/
|
||||
class EInkDisplay : public OLEDDisplay
|
||||
{
|
||||
public:
|
||||
/* constructor
|
||||
FIXME - the parameters are not used, just a temporary hack to keep working like the old displays
|
||||
*/
|
||||
EInkDisplay(uint8_t address, int sda, int scl);
|
||||
|
||||
// Write the buffer to the display memory
|
||||
virtual void display(void);
|
||||
|
||||
protected:
|
||||
// the header size of the buffer used, e.g. for the SPI command header
|
||||
virtual int getBufferOffset(void) { return 0; }
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
virtual void sendCommand(uint8_t com);
|
||||
|
||||
// Connect to the display
|
||||
virtual bool connect();
|
||||
};
|
@ -10,7 +10,8 @@
|
||||
#include <SSD1306Wire.h>
|
||||
#endif
|
||||
|
||||
#include "TFT.h"
|
||||
#include "EInkDisplay.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include "TypedQueue.h"
|
||||
#include "commands.h"
|
||||
#include "concurrency/LockGuard.h"
|
||||
@ -47,7 +48,6 @@ class DebugInfo
|
||||
void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
|
||||
std::string channelName;
|
||||
|
||||
/// Protects all of internal state.
|
||||
@ -237,6 +237,8 @@ class Screen : public concurrency::PeriodicTask
|
||||
/** FIXME cleanup display abstraction */
|
||||
#ifdef ST7735_CS
|
||||
TFTDisplay dispdev;
|
||||
#elif defined(HAS_EINK)
|
||||
EInkDisplay dispdev;
|
||||
#elif defined(USE_SH1106)
|
||||
SH1106Wire dispdev;
|
||||
#else
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#ifdef ST7735_CS
|
||||
#include "SPILock.h"
|
||||
#include "TFT.h"
|
||||
#include "TFTDisplay.h"
|
||||
#include "graphics/configs.h"
|
||||
#include <SPI.h>
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
|
||||
@ -20,7 +20,6 @@ void TFTDisplay::display(void)
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
|
||||
#if 1
|
||||
// FIXME - only draw bits have changed (use backbuf similar to the other displays)
|
||||
// tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK);
|
||||
for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) {
|
||||
@ -32,7 +31,6 @@ void TFTDisplay::display(void)
|
||||
tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Send a command to the display (low level function)
|
||||
@ -52,12 +50,10 @@ bool TFTDisplay::connect()
|
||||
pinMode(ST7735_BACKLIGHT_EN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
tft.init();
|
||||
tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
// tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
@ -232,7 +232,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Initialize the screen first so we can show the logo while we start up everything else.
|
||||
#ifdef ST7735_CS
|
||||
#if defined(ST7735_CS) || defined(HAS_EINK)
|
||||
screen.setup();
|
||||
#else
|
||||
if (ssd1306_found)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "NRF52Bluetooth.h"
|
||||
#include "configuration.h"
|
||||
#include "graphics/TFT.h"
|
||||
#include "graphics/TFTDisplay.h"
|
||||
#include <assert.h>
|
||||
#include <ble_gap.h>
|
||||
#include <memory.h>
|
||||
|
5
src/pgmspace.h
Normal file
5
src/pgmspace.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
// dummy file to keep old arduino code happy
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte(addr) (*((unsigned const char *)addr))
|
@ -38,4 +38,7 @@ void initVariant()
|
||||
|
||||
pinMode(PIN_LED2, OUTPUT);
|
||||
ledOff(PIN_LED2);
|
||||
|
||||
pinMode(PIN_LED3, OUTPUT);
|
||||
ledOff(PIN_LED3);
|
||||
}
|
||||
|
@ -27,18 +27,22 @@
|
||||
/*
|
||||
@geeksville eink TODO:
|
||||
|
||||
enable reset as a button
|
||||
fix battery pin usage
|
||||
drive TCXO DIO3 enable high whenever we want the clock
|
||||
use PIN_GPS_WAKE to sleep the GPS
|
||||
use tp_ser_io as a button, it goes high when pressed
|
||||
|
||||
button not working
|
||||
get pps blinking on second board
|
||||
clean up eink drawing to not have the nasty timeout hack
|
||||
put eink to sleep when we think the screen is off
|
||||
enable flash on spi0, share chip selects on spi1.
|
||||
https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fspi.html enable reset as a button in
|
||||
bootloader fix battery pin usage drive TCXO DIO3 enable high whenever we want the clock use PIN_GPS_WAKE to sleep the GPS use
|
||||
tp_ser_io as a button, it goes high when pressed unify eink display classes
|
||||
|
||||
eink probably is // #include <GxGDEP015OC1/GxGDEP015OC1.h> // 1.54" b/w //G702-A
|
||||
https://github.com/Xinyuan-LilyGO/LilyGO_T5_V24
|
||||
200 x 200
|
||||
|
||||
feedback to ttgo:
|
||||
are D10 and D8 backwards on the GPS schematic? gps comms no work?
|
||||
leds don't work?
|
||||
use pcf8563 part for waking CPU? or remove it
|
||||
the mx25 flash chip is great!
|
||||
name: TTGO LoraCard (nice googablity, unique name, sounds slick, implies lora and small)
|
||||
@ -65,16 +69,16 @@ extern "C" {
|
||||
#define NUM_ANALOG_OUTPUTS (0)
|
||||
|
||||
// LEDs
|
||||
#define PIN_LED1 (0 + 13)
|
||||
#define PIN_LED2 (0 + 14)
|
||||
#define PIN_LED3 (0 + 15)
|
||||
#define PIN_LED1 (0 + 13) // green
|
||||
#define PIN_LED2 (0 + 14) // red
|
||||
#define PIN_LED3 (0 + 15) // blue
|
||||
|
||||
#define LED_RED PIN_LED2
|
||||
#define LED_GREEN PIN_LED1
|
||||
#define LED_BLUE PIN_LED3
|
||||
|
||||
#define LED_BUILTIN LED_GREEN
|
||||
#define LED_CONN LED_CONN
|
||||
#define LED_CONN PIN_BLUE
|
||||
|
||||
#define LED_STATE_ON 0 // State when LED is lit
|
||||
|
||||
@ -171,21 +175,28 @@ FIXME define/FIX flash access
|
||||
*/
|
||||
|
||||
#define PIN_EINK_EN (32 + 11)
|
||||
#define PIN_EINK_CS (0 + 31)
|
||||
#define PIN_EINK_CS (0 + 30)
|
||||
#define PIN_EINK_BUSY (0 + 3)
|
||||
#define PIN_EINK_DC (0 + 28)
|
||||
#define PIN_EINK_RES (0 + 2)
|
||||
#define PIN_EINK_SCLK (0 + 31)
|
||||
#define PIN_EINK_MOSI (0 + 29) // also called SDI
|
||||
|
||||
#define HAS_EINK
|
||||
|
||||
#define PIN_SPI1_MISO \
|
||||
(32 + 7) // FIXME not really needed, but for now the SPI code requires something to be defined, pick an used GPIO
|
||||
#define PIN_SPI1_MOSI PIN_EINK_MOSI
|
||||
#define PIN_SPI1_SCK PIN_EINK_SCLK
|
||||
|
||||
/*
|
||||
* Air530 GPS pins
|
||||
*/
|
||||
|
||||
#define PIN_GPS_WAKE (32 + 2)
|
||||
#define PIN_GPS_PPS (32 + 4)
|
||||
#define PIN_GPS_TX (32 + 9) // This is for bits going TOWARDS the GPS
|
||||
#define PIN_GPS_RX (32 + 8) // This is for bits going TOWARDS the CPU
|
||||
#define PIN_GPS_TX (32 + 8) // This is for bits going TOWARDS the GPS
|
||||
#define PIN_GPS_RX (32 + 9) // This is for bits going TOWARDS the CPU
|
||||
|
||||
#define PIN_SERIAL1_RX PIN_GPS_RX
|
||||
#define PIN_SERIAL1_TX PIN_GPS_TX
|
||||
@ -193,17 +204,17 @@ FIXME define/FIX flash access
|
||||
/*
|
||||
* SPI Interfaces
|
||||
*/
|
||||
#define SPI_INTERFACES_COUNT 1
|
||||
#define SPI_INTERFACES_COUNT 2
|
||||
|
||||
// For LORA
|
||||
#define PIN_SPI_MISO (0 + 23)
|
||||
#define PIN_SPI_MOSI (0 + 22)
|
||||
#define PIN_SPI_SCK (0 + 19)
|
||||
|
||||
static const uint8_t SS = SX1262_CS;
|
||||
static const uint8_t MOSI = PIN_SPI_MOSI;
|
||||
static const uint8_t MISO = PIN_SPI_MISO;
|
||||
static const uint8_t SCK = PIN_SPI_SCK;
|
||||
// static const uint8_t SS = SX1262_CS;
|
||||
// static const uint8_t MOSI = PIN_SPI_MOSI;
|
||||
// static const uint8_t MISO = PIN_SPI_MISO;
|
||||
// static const uint8_t SCK = PIN_SPI_SCK;
|
||||
|
||||
// To debug via the segger JLINK console rather than the CDC-ACM serial device
|
||||
#define USE_SEGGER
|
||||
|
Loading…
Reference in New Issue
Block a user