mirror of https://github.com/arendst/Tasmota.git
commit
d7e8c41141
|
@ -0,0 +1,554 @@
|
|||
/***************************************************
|
||||
This is a library for the ST7789 IPS SPI display.
|
||||
|
||||
Originally written by Limor Fried/Ladyada for
|
||||
Adafruit Industries.
|
||||
|
||||
Modified by Ananev Ilia
|
||||
****************************************************/
|
||||
|
||||
#include "Arduino_ST7789.h"
|
||||
#include <limits.h>
|
||||
#include "pins_arduino.h"
|
||||
#include "wiring_private.h"
|
||||
#include <SPI.h>
|
||||
|
||||
const uint16_t ST7789_colors[]={ST7789_BLACK,ST7789_WHITE,ST7789_RED,ST7789_GREEN,ST7789_BLUE,ST7789_CYAN,ST7789_MAGENTA,\
|
||||
ST7789_YELLOW,ST7789_NAVY,ST7789_DARKGREEN,ST7789_DARKCYAN,ST7789_MAROON,ST7789_PURPLE,ST7789_OLIVE,\
|
||||
ST7789_LIGHTGREY,ST7789_DARKGREY,ST7789_ORANGE,ST7789_GREENYELLOW,ST7789_PINK};
|
||||
|
||||
|
||||
uint16_t Arduino_ST7789::GetColorFromIndex(uint8_t index) {
|
||||
if (index>=sizeof(ST7789_colors)/2) index=0;
|
||||
return ST7789_colors[index];
|
||||
}
|
||||
|
||||
static const uint8_t PROGMEM
|
||||
cmd_240x240[] = { // Initialization commands for 7789 screens
|
||||
10, // 9 commands in list:
|
||||
ST7789_SWRESET, ST_CMD_DELAY, // 1: Software reset, no args, w/delay
|
||||
150, // 150 ms delay
|
||||
ST7789_SLPOUT , ST_CMD_DELAY, // 2: Out of sleep mode, no args, w/delay
|
||||
255, // 255 = 500 ms delay
|
||||
ST7789_COLMOD , 1+ST_CMD_DELAY, // 3: Set color mode, 1 arg + delay:
|
||||
0x55, // 16-bit color
|
||||
10, // 10 ms delay
|
||||
ST7789_MADCTL , 1, // 4: Memory access ctrl (directions), 1 arg:
|
||||
0x00, // Row addr/col addr, bottom to top refresh
|
||||
ST7789_CASET , 4, // 5: Column addr set, 4 args, no delay:
|
||||
0x00, ST7789_240x240_XSTART, // XSTART = 0
|
||||
(ST7789_TFTWIDTH+ST7789_240x240_XSTART) >> 8,
|
||||
(ST7789_TFTWIDTH+ST7789_240x240_XSTART) & 0xFF, // XEND = 240
|
||||
ST7789_RASET , 4, // 6: Row addr set, 4 args, no delay:
|
||||
0x00, ST7789_240x240_YSTART, // YSTART = 0
|
||||
(ST7789_TFTHEIGHT+ST7789_240x240_YSTART) >> 8,
|
||||
(ST7789_TFTHEIGHT+ST7789_240x240_YSTART) & 0xFF, // YEND = 240
|
||||
ST7789_INVON , ST_CMD_DELAY, // 7: Inversion ON
|
||||
10,
|
||||
ST7789_NORON , ST_CMD_DELAY, // 8: Normal display on, no args, w/delay
|
||||
10, // 10 ms delay
|
||||
ST7789_DISPON , ST_CMD_DELAY, // 9: Main screen turn on, no args, w/delay
|
||||
255 }; // 255 = 500 ms delay
|
||||
|
||||
inline uint16_t swapcolor(uint16_t x) {
|
||||
return (x << 11) | (x & 0x07E0) | (x >> 11);
|
||||
}
|
||||
|
||||
#if defined (SPI_HAS_TRANSACTION)
|
||||
static SPISettings mySPISettings;
|
||||
#elif defined (__AVR__) || defined(CORE_TEENSY)
|
||||
static uint8_t SPCRbackup;
|
||||
static uint8_t mySPCR;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (SPI_HAS_TRANSACTION)
|
||||
#define SPI_BEGIN_TRANSACTION() if (_hwSPI) SPI.beginTransaction(mySPISettings)
|
||||
#define SPI_END_TRANSACTION() if (_hwSPI) SPI.endTransaction()
|
||||
#else
|
||||
#define SPI_BEGIN_TRANSACTION() (void)
|
||||
#define SPI_END_TRANSACTION() (void)
|
||||
#endif
|
||||
|
||||
// Constructor when using software SPI. All output pins are configurable.
|
||||
Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t sid, int8_t sclk, int8_t cs, int8_t bp)
|
||||
: Renderer(ST7789_TFTWIDTH, ST7789_TFTHEIGHT)
|
||||
{
|
||||
_cs = cs;
|
||||
_dc = dc;
|
||||
_sid = sid;
|
||||
_sclk = sclk;
|
||||
_rst = rst;
|
||||
_hwSPI = false;
|
||||
_bp = bp;
|
||||
if(dc == -1) _SPI9bit = true;
|
||||
else _SPI9bit = false;
|
||||
}
|
||||
|
||||
// Constructor when using hardware SPI. Faster, but must use SPI pins
|
||||
// specific to each board type (e.g. 11,13 for Uno, 51,52 for Mega, etc.)
|
||||
Arduino_ST7789::Arduino_ST7789(int8_t dc, int8_t rst, int8_t cs)
|
||||
: Renderer(ST7789_TFTWIDTH, ST7789_TFTHEIGHT) {
|
||||
_cs = cs;
|
||||
_dc = dc;
|
||||
_rst = rst;
|
||||
_hwSPI = true;
|
||||
_SPI9bit = false;
|
||||
_sid = _sclk = -1;
|
||||
}
|
||||
|
||||
|
||||
void Arduino_ST7789::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
setRotation(rot);
|
||||
//invertDisplay(false);
|
||||
invertDisplay(true);
|
||||
//setTextWrap(false); // Allow text to run off edges
|
||||
//cp437(true);
|
||||
setTextFont(font&3);
|
||||
setTextSize(size&7);
|
||||
setTextColor(ST7789_WHITE,ST7789_BLACK);
|
||||
setCursor(0,0);
|
||||
fillScreen(ST7789_BLACK);
|
||||
}
|
||||
|
||||
inline void Arduino_ST7789::spiwrite(uint8_t c)
|
||||
{
|
||||
|
||||
//Serial.println(c, HEX);
|
||||
|
||||
if (_hwSPI)
|
||||
{
|
||||
#if defined (SPI_HAS_TRANSACTION)
|
||||
SPI.transfer(c);
|
||||
#elif defined (__AVR__) || defined(CORE_TEENSY)
|
||||
SPCRbackup = SPCR;
|
||||
SPCR = mySPCR;
|
||||
SPI.transfer(c);
|
||||
SPCR = SPCRbackup;
|
||||
#elif defined (__arm__)
|
||||
SPI.setClockDivider(21); //4MHz
|
||||
SPI.setDataMode(SPI_MODE2);
|
||||
SPI.transfer(c);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if(_SPI9bit)
|
||||
{
|
||||
//9s bit send first
|
||||
#if defined(USE_FAST_IO)
|
||||
*clkport &= ~clkpinmask;
|
||||
if(_DCbit) *dataport |= datapinmask;
|
||||
else *dataport &= ~datapinmask;
|
||||
*clkport |= clkpinmask;
|
||||
#else
|
||||
digitalWrite(_sclk, LOW);
|
||||
if(_DCbit) digitalWrite(_sid, HIGH);
|
||||
else digitalWrite(_sid, LOW);
|
||||
digitalWrite(_sclk, HIGH);
|
||||
#endif
|
||||
|
||||
|
||||
// Fast SPI bitbang swiped from LPD8806 library
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
#if defined(USE_FAST_IO)
|
||||
*clkport &= ~clkpinmask;
|
||||
if(c & bit) *dataport |= datapinmask;
|
||||
else *dataport &= ~datapinmask;
|
||||
*clkport |= clkpinmask;
|
||||
#else
|
||||
digitalWrite(_sclk, LOW);
|
||||
if(c & bit) digitalWrite(_sid, HIGH);
|
||||
else digitalWrite(_sid, LOW);
|
||||
digitalWrite(_sclk, HIGH);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fast SPI bitbang swiped from LPD8806 library
|
||||
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
||||
#if defined(USE_FAST_IO)
|
||||
*clkport &= ~clkpinmask;
|
||||
if(c & bit) *dataport |= datapinmask;
|
||||
else *dataport &= ~datapinmask;
|
||||
*clkport |= clkpinmask;
|
||||
#else
|
||||
digitalWrite(_sclk, LOW);
|
||||
if(c & bit) digitalWrite(_sid, HIGH);
|
||||
else digitalWrite(_sid, LOW);
|
||||
digitalWrite(_sclk, HIGH);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ST7789::writecommand(uint8_t c) {
|
||||
|
||||
DC_LOW();
|
||||
CS_LOW();
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
spiwrite(c);
|
||||
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void Arduino_ST7789::writedata(uint8_t c) {
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
spiwrite(c);
|
||||
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
// Companion code to the above tables. Reads and issues
|
||||
// a series of LCD commands stored in PROGMEM byte array.
|
||||
void Arduino_ST7789::displayInit(const uint8_t *addr) {
|
||||
|
||||
uint8_t numCommands, numArgs;
|
||||
uint16_t ms;
|
||||
//<-----------------------------------------------------------------------------------------
|
||||
DC_HIGH();
|
||||
#if defined(USE_FAST_IO)
|
||||
*clkport |= clkpinmask;
|
||||
#else
|
||||
digitalWrite(_sclk, HIGH);
|
||||
#endif
|
||||
//<-----------------------------------------------------------------------------------------
|
||||
|
||||
numCommands = pgm_read_byte(addr++); // Number of commands to follow
|
||||
while(numCommands--) { // For each command...
|
||||
writecommand(pgm_read_byte(addr++)); // Read, issue command
|
||||
numArgs = pgm_read_byte(addr++); // Number of args to follow
|
||||
ms = numArgs & ST_CMD_DELAY; // If hibit set, delay follows args
|
||||
numArgs &= ~ST_CMD_DELAY; // Mask out delay bit
|
||||
while(numArgs--) { // For each argument...
|
||||
writedata(pgm_read_byte(addr++)); // Read, issue argument
|
||||
}
|
||||
|
||||
if(ms) {
|
||||
ms = pgm_read_byte(addr++); // Read post-command delay time (ms)
|
||||
if(ms == 255) ms = 500; // If 255, delay for 500 ms
|
||||
delay(ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initialization code common to all ST7789 displays
|
||||
void Arduino_ST7789::commonInit(const uint8_t *cmdList) {
|
||||
_ystart = _xstart = 0;
|
||||
_colstart = _rowstart = 0; // May be overridden in init func
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
if (_cs>=0) {
|
||||
pinMode(_cs, OUTPUT);
|
||||
}
|
||||
|
||||
if (_bp>=0) {
|
||||
pinMode(_bp, OUTPUT);
|
||||
}
|
||||
|
||||
|
||||
#if defined(USE_FAST_IO)
|
||||
dcport = portOutputRegister(digitalPinToPort(_dc));
|
||||
dcpinmask = digitalPinToBitMask(_dc);
|
||||
if (_cs>=0) {
|
||||
csport = portOutputRegister(digitalPinToPort(_cs));
|
||||
cspinmask = digitalPinToBitMask(_cs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(_hwSPI) { // Using hardware SPI
|
||||
#if defined (SPI_HAS_TRANSACTION)
|
||||
SPI.begin();
|
||||
mySPISettings = SPISettings(24000000, MSBFIRST, SPI_MODE2);
|
||||
#elif defined (__AVR__) || defined(CORE_TEENSY)
|
||||
SPCRbackup = SPCR;
|
||||
SPI.begin();
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4);
|
||||
SPI.setDataMode(SPI_MODE2);
|
||||
mySPCR = SPCR; // save our preferred state
|
||||
SPCR = SPCRbackup; // then restore
|
||||
#elif defined (__SAM3X8E__)
|
||||
SPI.begin();
|
||||
SPI.setClockDivider(21); //4MHz
|
||||
SPI.setDataMode(SPI_MODE2);
|
||||
#endif
|
||||
} else {
|
||||
pinMode(_sclk, OUTPUT);
|
||||
pinMode(_sid , OUTPUT);
|
||||
digitalWrite(_sclk, LOW);
|
||||
digitalWrite(_sid, LOW);
|
||||
|
||||
#if defined(USE_FAST_IO)
|
||||
clkport = portOutputRegister(digitalPinToPort(_sclk));
|
||||
dataport = portOutputRegister(digitalPinToPort(_sid));
|
||||
clkpinmask = digitalPinToBitMask(_sclk);
|
||||
datapinmask = digitalPinToBitMask(_sid);
|
||||
#endif
|
||||
}
|
||||
|
||||
// toggle RST low to reset; CS low so it'll listen to us
|
||||
CS_LOW();
|
||||
if (_rst != -1) {
|
||||
pinMode(_rst, OUTPUT);
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(50);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(50);
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(50);
|
||||
}
|
||||
|
||||
if(cmdList)
|
||||
displayInit(cmdList);
|
||||
}
|
||||
|
||||
void Arduino_ST7789::setRotation(uint8_t m) {
|
||||
|
||||
writecommand(ST7789_MADCTL);
|
||||
rotation = m % 4; // can't be higher than 3
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
writedata(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB);
|
||||
|
||||
_xstart = _colstart;
|
||||
// _ystart = _rowstart;
|
||||
_ystart = 80;
|
||||
break;
|
||||
case 1:
|
||||
writedata(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
|
||||
|
||||
_ystart = _colstart;
|
||||
// _xstart = _rowstart;
|
||||
_xstart = 80;
|
||||
break;
|
||||
case 2:
|
||||
writedata(ST7789_MADCTL_RGB);
|
||||
|
||||
_xstart = _colstart;
|
||||
_ystart = _rowstart;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
writedata(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);
|
||||
|
||||
_ystart = _colstart;
|
||||
_xstart = _rowstart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_ST7789::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1,
|
||||
uint16_t y1) {
|
||||
|
||||
uint16_t x_start = x0 + _xstart, x_end = x1 + _xstart;
|
||||
uint16_t y_start = y0 + _ystart, y_end = y1 + _ystart;
|
||||
|
||||
|
||||
writecommand(ST7789_CASET); // Column addr set
|
||||
writedata(x_start >> 8);
|
||||
writedata(x_start & 0xFF); // XSTART
|
||||
writedata(x_end >> 8);
|
||||
writedata(x_end & 0xFF); // XEND
|
||||
|
||||
writecommand(ST7789_RASET); // Row addr set
|
||||
writedata(y_start >> 8);
|
||||
writedata(y_start & 0xFF); // YSTART
|
||||
writedata(y_end >> 8);
|
||||
writedata(y_end & 0xFF); // YEND
|
||||
|
||||
writecommand(ST7789_RAMWR); // write to RAM
|
||||
}
|
||||
|
||||
void Arduino_ST7789::pushColor(uint16_t color) {
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
spiwrite(color >> 8);
|
||||
spiwrite(color);
|
||||
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void Arduino_ST7789::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
|
||||
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
|
||||
|
||||
setAddrWindow(x,y,x+1,y+1);
|
||||
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
spiwrite(color >> 8);
|
||||
spiwrite(color);
|
||||
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void Arduino_ST7789::drawFastVLine(int16_t x, int16_t y, int16_t h,
|
||||
uint16_t color) {
|
||||
|
||||
// Rudimentary clipping
|
||||
if((x >= _width) || (y >= _height)) return;
|
||||
if((y+h-1) >= _height) h = _height-y;
|
||||
setAddrWindow(x, y, x, y+h-1);
|
||||
|
||||
uint8_t hi = color >> 8, lo = color;
|
||||
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
while (h--) {
|
||||
spiwrite(hi);
|
||||
spiwrite(lo);
|
||||
}
|
||||
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void Arduino_ST7789::drawFastHLine(int16_t x, int16_t y, int16_t w,
|
||||
uint16_t color) {
|
||||
|
||||
// Rudimentary clipping
|
||||
if((x >= _width) || (y >= _height)) return;
|
||||
if((x+w-1) >= _width) w = _width-x;
|
||||
setAddrWindow(x, y, x+w-1, y);
|
||||
|
||||
uint8_t hi = color >> 8, lo = color;
|
||||
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
|
||||
while (w--) {
|
||||
spiwrite(hi);
|
||||
spiwrite(lo);
|
||||
}
|
||||
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void Arduino_ST7789::fillScreen(uint16_t color) {
|
||||
fillRect(0, 0, _width, _height, color);
|
||||
}
|
||||
|
||||
// fill a rectangle
|
||||
void Arduino_ST7789::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
|
||||
// rudimentary clipping (drawChar w/big text requires this)
|
||||
if((x >= _width) || (y >= _height)) return;
|
||||
if((x + w - 1) >= _width) w = _width - x;
|
||||
if((y + h - 1) >= _height) h = _height - y;
|
||||
|
||||
setAddrWindow(x, y, x+w-1, y+h-1);
|
||||
|
||||
uint8_t hi = color >> 8, lo = color;
|
||||
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
DC_HIGH();
|
||||
CS_LOW();
|
||||
for(y=h; y>0; y--) {
|
||||
for(x=w; x>0; x--) {
|
||||
spiwrite(hi);
|
||||
spiwrite(lo);
|
||||
}
|
||||
}
|
||||
CS_HIGH();
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
|
||||
uint16_t Arduino_ST7789::Color565(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
||||
}
|
||||
|
||||
void Arduino_ST7789::invertDisplay(boolean i) {
|
||||
writecommand(i ? ST7789_INVON : ST7789_INVOFF);
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
inline void Arduino_ST7789::CS_HIGH(void) {
|
||||
if(_cs>=0) {
|
||||
#if defined(USE_FAST_IO)
|
||||
*csport |= cspinmask;
|
||||
#else
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline void Arduino_ST7789::CS_LOW(void) {
|
||||
if(_cs>=0) {
|
||||
#if defined(USE_FAST_IO)
|
||||
*csport &= ~cspinmask;
|
||||
#else
|
||||
digitalWrite(_cs, LOW);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
inline void Arduino_ST7789::DC_HIGH(void) {
|
||||
_DCbit = true;
|
||||
#if defined(USE_FAST_IO)
|
||||
*dcport |= dcpinmask;
|
||||
#else
|
||||
digitalWrite(_dc, HIGH);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void Arduino_ST7789::DC_LOW(void) {
|
||||
_DCbit = false;
|
||||
#if defined(USE_FAST_IO)
|
||||
*dcport &= ~dcpinmask;
|
||||
#else
|
||||
digitalWrite(_dc, LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Arduino_ST7789::init(uint16_t width, uint16_t height) {
|
||||
commonInit(NULL);
|
||||
|
||||
_colstart = ST7789_240x240_XSTART;
|
||||
_rowstart = ST7789_240x240_YSTART;
|
||||
_height = height;
|
||||
_width = width;
|
||||
|
||||
displayInit(cmd_240x240);
|
||||
|
||||
setRotation(2);
|
||||
|
||||
}
|
||||
|
||||
void Arduino_ST7789::DisplayOnff(int8_t on) {
|
||||
if (on) {
|
||||
writecommand(ST7789_DISPON); //Display on
|
||||
if (_bp>=0) {
|
||||
digitalWrite(_bp,HIGH);
|
||||
}
|
||||
} else {
|
||||
writecommand(ST7789_DISPOFF);
|
||||
if (_bp>=0) {
|
||||
digitalWrite(_bp,LOW);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/***************************************************
|
||||
This is a library for the ST7789 IPS SPI display.
|
||||
|
||||
Originally written by Limor Fried/Ladyada for
|
||||
Adafruit Industries.
|
||||
|
||||
Modified by Ananev Ilia
|
||||
****************************************************/
|
||||
|
||||
#ifndef _ADAFRUIT_ST7789H_
|
||||
#define _ADAFRUIT_ST7789H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <renderer.h>
|
||||
|
||||
#if defined(__AVR__) || defined(CORE_TEENSY)
|
||||
#include <avr/pgmspace.h>
|
||||
#define USE_FAST_IO
|
||||
typedef volatile uint8_t RwReg;
|
||||
#elif defined(ARDUINO_STM32_FEATHER)
|
||||
typedef volatile uint32 RwReg;
|
||||
#define USE_FAST_IO
|
||||
#elif defined(ARDUINO_FEATHER52)
|
||||
typedef volatile uint32_t RwReg;
|
||||
#define USE_FAST_IO
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#elif defined(__SAM3X8E__)
|
||||
#undef __FlashStringHelper::F(string_literal)
|
||||
#define F(string_literal) string_literal
|
||||
#include <include/pio.h>
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
typedef unsigned char prog_uchar;
|
||||
#endif
|
||||
|
||||
#define SPI_HAS_TRANSACTION
|
||||
|
||||
|
||||
#define ST7789_TFTWIDTH 240
|
||||
#define ST7789_TFTHEIGHT 240
|
||||
|
||||
#define ST7789_240x240_XSTART 0
|
||||
#define ST7789_240x240_YSTART 0
|
||||
|
||||
#define ST_CMD_DELAY 0x80 // special signifier for command lists
|
||||
|
||||
#define ST7789_NOP 0x00
|
||||
#define ST7789_SWRESET 0x01
|
||||
#define ST7789_RDDID 0x04
|
||||
#define ST7789_RDDST 0x09
|
||||
|
||||
#define ST7789_SLPIN 0x10
|
||||
#define ST7789_SLPOUT 0x11
|
||||
#define ST7789_PTLON 0x12
|
||||
#define ST7789_NORON 0x13
|
||||
|
||||
#define ST7789_INVOFF 0x20
|
||||
#define ST7789_INVON 0x21
|
||||
#define ST7789_DISPOFF 0x28
|
||||
#define ST7789_DISPON 0x29
|
||||
#define ST7789_CASET 0x2A
|
||||
#define ST7789_RASET 0x2B
|
||||
#define ST7789_RAMWR 0x2C
|
||||
#define ST7789_RAMRD 0x2E
|
||||
|
||||
#define ST7789_PTLAR 0x30
|
||||
#define ST7789_COLMOD 0x3A
|
||||
#define ST7789_MADCTL 0x36
|
||||
|
||||
#define ST7789_MADCTL_MY 0x80
|
||||
#define ST7789_MADCTL_MX 0x40
|
||||
#define ST7789_MADCTL_MV 0x20
|
||||
#define ST7789_MADCTL_ML 0x10
|
||||
#define ST7789_MADCTL_RGB 0x00
|
||||
|
||||
#define ST7789_RDID1 0xDA
|
||||
#define ST7789_RDID2 0xDB
|
||||
#define ST7789_RDID3 0xDC
|
||||
#define ST7789_RDID4 0xDD
|
||||
|
||||
// Color definitions
|
||||
#undef BLACK
|
||||
#define BLACK 0x0000
|
||||
#define BLUE 0x001F
|
||||
#define RED 0xF800
|
||||
#define GREEN 0x07E0
|
||||
#define CYAN 0x07FF
|
||||
#define MAGENTA 0xF81F
|
||||
#define YELLOW 0xFFE0
|
||||
#undef WHITE
|
||||
#define WHITE 0xFFFF
|
||||
|
||||
|
||||
// Color definitions
|
||||
#define ST7789_BLACK 0x0000 /* 0, 0, 0 */
|
||||
#define ST7789_NAVY 0x000F /* 0, 0, 128 */
|
||||
#define ST7789_DARKGREEN 0x03E0 /* 0, 128, 0 */
|
||||
#define ST7789_DARKCYAN 0x03EF /* 0, 128, 128 */
|
||||
#define ST7789_MAROON 0x7800 /* 128, 0, 0 */
|
||||
#define ST7789_PURPLE 0x780F /* 128, 0, 128 */
|
||||
#define ST7789_OLIVE 0x7BE0 /* 128, 128, 0 */
|
||||
#define ST7789_LIGHTGREY 0xC618 /* 192, 192, 192 */
|
||||
#define ST7789_DARKGREY 0x7BEF /* 128, 128, 128 */
|
||||
#define ST7789_BLUE 0x001F /* 0, 0, 255 */
|
||||
#define ST7789_GREEN 0x07E0 /* 0, 255, 0 */
|
||||
#define ST7789_CYAN 0x07FF /* 0, 255, 255 */
|
||||
#define ST7789_RED 0xF800 /* 255, 0, 0 */
|
||||
#define ST7789_MAGENTA 0xF81F /* 255, 0, 255 */
|
||||
#define ST7789_YELLOW 0xFFE0 /* 255, 255, 0 */
|
||||
#define ST7789_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define ST7789_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define ST7789_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define ST7789_PINK 0xF81F
|
||||
|
||||
|
||||
class Arduino_ST7789 : public Renderer {
|
||||
|
||||
public:
|
||||
|
||||
Arduino_ST7789(int8_t DC, int8_t RST, int8_t SID, int8_t SCLK, int8_t CS = -1,int8_t bp = -1);
|
||||
Arduino_ST7789(int8_t DC, int8_t RST, int8_t CS = -1);
|
||||
|
||||
void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1),
|
||||
pushColor(uint16_t color),
|
||||
fillScreen(uint16_t color),
|
||||
drawPixel(int16_t x, int16_t y, uint16_t color),
|
||||
drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
|
||||
drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
|
||||
fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
setRotation(uint8_t r),
|
||||
invertDisplay(boolean i),
|
||||
DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font),
|
||||
|
||||
init(uint16_t width, uint16_t height);
|
||||
uint16_t Color565(uint8_t r, uint8_t g, uint8_t b);
|
||||
uint16_t GetColorFromIndex(uint8_t index);
|
||||
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { return Color565(r, g, b); }
|
||||
void DisplayOnff(int8_t on);
|
||||
|
||||
protected:
|
||||
uint8_t _colstart, _rowstart, _xstart, _ystart; // some displays need this changed
|
||||
|
||||
void displayInit(const uint8_t *addr);
|
||||
void spiwrite(uint8_t),
|
||||
writecommand(uint8_t c),
|
||||
writedata(uint8_t d),
|
||||
commonInit(const uint8_t *cmdList);
|
||||
|
||||
private:
|
||||
|
||||
inline void CS_HIGH(void);
|
||||
inline void CS_LOW(void);
|
||||
inline void DC_HIGH(void);
|
||||
inline void DC_LOW(void);
|
||||
|
||||
boolean _hwSPI;
|
||||
boolean _SPI9bit;
|
||||
boolean _DCbit;
|
||||
|
||||
int8_t _cs, _dc, _rst, _sid, _sclk, _bp;
|
||||
|
||||
#if defined(USE_FAST_IO)
|
||||
volatile RwReg *dataport, *clkport, *csport, *dcport;
|
||||
|
||||
#if defined(__AVR__) || defined(CORE_TEENSY) // 8 bit!
|
||||
uint8_t datapinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#else // 32 bit!
|
||||
uint32_t datapinmask, clkpinmask, cspinmask, dcpinmask;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,3 @@
|
|||
This is a library for the ST7789 IPS SPI display.
|
||||
|
||||
Also requires the Adafruit_GFX library for Arduino.
|
|
@ -0,0 +1,278 @@
|
|||
/***************************************************
|
||||
This is a library for the ST7789 IPS SPI display.
|
||||
|
||||
Originally written by Limor Fried/Ladyada for
|
||||
Adafruit Industries.
|
||||
|
||||
Modified by Ananev Ilia
|
||||
****************************************************/
|
||||
|
||||
#include <Adafruit_GFX.h> // Core graphics library by Adafruit
|
||||
#include <Arduino_ST7789.h> // Hardware-specific library for ST7789 (with or without CS pin)
|
||||
#include <SPI.h>
|
||||
|
||||
#define TFT_DC 8
|
||||
#define TFT_RST 9
|
||||
#define TFT_CS 10 // only for displays with CS pin
|
||||
#define TFT_MOSI 11 // for hardware SPI data pin (all of available pins)
|
||||
#define TFT_SCLK 13 // for hardware SPI sclk pin (all of available pins)
|
||||
|
||||
//You can use different type of hardware initialization
|
||||
//using hardware SPI (11, 13 on UNO; 51, 52 on MEGA; ICSP-4, ICSP-3 on DUE and etc)
|
||||
//Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST); //for display without CS pin
|
||||
//Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_CS); //for display with CS pin
|
||||
//or you can use software SPI on all available pins (slow)
|
||||
//Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK); //for display without CS pin
|
||||
//Arduino_ST7789 tft = Arduino_ST7789(TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS); //for display with CS pin
|
||||
Arduino_ST7789 tft = Arduino_ST7789(-1, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_CS); //for display with CS pin and DC via 9bit SPI
|
||||
|
||||
|
||||
float p = 3.1415926;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(9600);
|
||||
Serial.print("Hello! ST7789 TFT Test");
|
||||
|
||||
tft.init(240, 240); // initialize a ST7789 chip, 240x240 pixels
|
||||
|
||||
Serial.println("Initialized");
|
||||
|
||||
uint16_t time = millis();
|
||||
tft.fillScreen(BLACK);
|
||||
time = millis() - time;
|
||||
|
||||
Serial.println(time, DEC);
|
||||
delay(500);
|
||||
|
||||
// large block of text
|
||||
tft.fillScreen(BLACK);
|
||||
testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", WHITE);
|
||||
delay(1000);
|
||||
|
||||
// tft print function
|
||||
tftPrintTest();
|
||||
delay(4000);
|
||||
|
||||
// a single pixel
|
||||
tft.drawPixel(tft.width()/2, tft.height()/2, GREEN);
|
||||
delay(500);
|
||||
|
||||
// line draw test
|
||||
testlines(YELLOW);
|
||||
delay(500);
|
||||
|
||||
// optimized lines
|
||||
testfastlines(RED, BLUE);
|
||||
delay(500);
|
||||
|
||||
testdrawrects(GREEN);
|
||||
delay(500);
|
||||
|
||||
testfillrects(YELLOW, MAGENTA);
|
||||
delay(500);
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
testfillcircles(10, BLUE);
|
||||
testdrawcircles(10, WHITE);
|
||||
delay(500);
|
||||
|
||||
testroundrects();
|
||||
delay(500);
|
||||
|
||||
testtriangles();
|
||||
delay(500);
|
||||
|
||||
mediabuttons();
|
||||
delay(500);
|
||||
|
||||
Serial.println("done");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
tft.invertDisplay(true);
|
||||
delay(500);
|
||||
tft.invertDisplay(false);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void testlines(uint16_t color) {
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t x=0; x < tft.width(); x+=6) {
|
||||
tft.drawLine(0, 0, x, tft.height()-1, color);
|
||||
}
|
||||
for (int16_t y=0; y < tft.height(); y+=6) {
|
||||
tft.drawLine(0, 0, tft.width()-1, y, color);
|
||||
}
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t x=0; x < tft.width(); x+=6) {
|
||||
tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
|
||||
}
|
||||
for (int16_t y=0; y < tft.height(); y+=6) {
|
||||
tft.drawLine(tft.width()-1, 0, 0, y, color);
|
||||
}
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t x=0; x < tft.width(); x+=6) {
|
||||
tft.drawLine(0, tft.height()-1, x, 0, color);
|
||||
}
|
||||
for (int16_t y=0; y < tft.height(); y+=6) {
|
||||
tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
|
||||
}
|
||||
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t x=0; x < tft.width(); x+=6) {
|
||||
tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
|
||||
}
|
||||
for (int16_t y=0; y < tft.height(); y+=6) {
|
||||
tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawtext(char *text, uint16_t color) {
|
||||
tft.setCursor(0, 0);
|
||||
tft.setTextColor(color);
|
||||
tft.setTextWrap(true);
|
||||
tft.print(text);
|
||||
}
|
||||
|
||||
void testfastlines(uint16_t color1, uint16_t color2) {
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t y=0; y < tft.height(); y+=5) {
|
||||
tft.drawFastHLine(0, y, tft.width(), color1);
|
||||
}
|
||||
for (int16_t x=0; x < tft.width(); x+=5) {
|
||||
tft.drawFastVLine(x, 0, tft.height(), color2);
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawrects(uint16_t color) {
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t x=0; x < tft.width(); x+=6) {
|
||||
tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
|
||||
}
|
||||
}
|
||||
|
||||
void testfillrects(uint16_t color1, uint16_t color2) {
|
||||
tft.fillScreen(BLACK);
|
||||
for (int16_t x=tft.width()-1; x > 6; x-=6) {
|
||||
tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
|
||||
tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
|
||||
}
|
||||
}
|
||||
|
||||
void testfillcircles(uint8_t radius, uint16_t color) {
|
||||
for (int16_t x=radius; x < tft.width(); x+=radius*2) {
|
||||
for (int16_t y=radius; y < tft.height(); y+=radius*2) {
|
||||
tft.fillCircle(x, y, radius, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testdrawcircles(uint8_t radius, uint16_t color) {
|
||||
for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
|
||||
for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
|
||||
tft.drawCircle(x, y, radius, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testtriangles() {
|
||||
tft.fillScreen(BLACK);
|
||||
int color = 0xF800;
|
||||
int t;
|
||||
int w = tft.width()/2;
|
||||
int x = tft.height()-1;
|
||||
int y = 0;
|
||||
int z = tft.width();
|
||||
for(t = 0 ; t <= 15; t++) {
|
||||
tft.drawTriangle(w, y, y, x, z, x, color);
|
||||
x-=4;
|
||||
y+=4;
|
||||
z-=4;
|
||||
color+=100;
|
||||
}
|
||||
}
|
||||
|
||||
void testroundrects() {
|
||||
tft.fillScreen(BLACK);
|
||||
int color = 100;
|
||||
int i;
|
||||
int t;
|
||||
for(t = 0 ; t <= 4; t+=1) {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = tft.width()-2;
|
||||
int h = tft.height()-2;
|
||||
for(i = 0 ; i <= 16; i+=1) {
|
||||
tft.drawRoundRect(x, y, w, h, 5, color);
|
||||
x+=2;
|
||||
y+=3;
|
||||
w-=4;
|
||||
h-=6;
|
||||
color+=1100;
|
||||
}
|
||||
color+=100;
|
||||
}
|
||||
}
|
||||
|
||||
void tftPrintTest() {
|
||||
tft.setTextWrap(false);
|
||||
tft.fillScreen(BLACK);
|
||||
tft.setCursor(0, 30);
|
||||
tft.setTextColor(RED);
|
||||
tft.setTextSize(1);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(YELLOW);
|
||||
tft.setTextSize(2);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(GREEN);
|
||||
tft.setTextSize(3);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(BLUE);
|
||||
tft.setTextSize(4);
|
||||
tft.print(1234.567);
|
||||
delay(1500);
|
||||
tft.setCursor(0, 0);
|
||||
tft.fillScreen(BLACK);
|
||||
tft.setTextColor(WHITE);
|
||||
tft.setTextSize(0);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextSize(1);
|
||||
tft.setTextColor(GREEN);
|
||||
tft.print(p, 6);
|
||||
tft.println(" Want pi?");
|
||||
tft.println(" ");
|
||||
tft.print(8675309, HEX); // print 8,675,309 out in HEX!
|
||||
tft.println(" Print HEX!");
|
||||
tft.println(" ");
|
||||
tft.setTextColor(WHITE);
|
||||
tft.println("Sketch has been");
|
||||
tft.println("running for: ");
|
||||
tft.setTextColor(MAGENTA);
|
||||
tft.print(millis() / 1000);
|
||||
tft.setTextColor(WHITE);
|
||||
tft.print(" seconds.");
|
||||
}
|
||||
|
||||
void mediabuttons() {
|
||||
// play
|
||||
tft.fillScreen(BLACK);
|
||||
tft.fillRoundRect(25, 10, 78, 60, 8, WHITE);
|
||||
tft.fillTriangle(42, 20, 42, 60, 90, 40, RED);
|
||||
delay(500);
|
||||
// pause
|
||||
tft.fillRoundRect(25, 90, 78, 60, 8, WHITE);
|
||||
tft.fillRoundRect(39, 98, 20, 45, 5, GREEN);
|
||||
tft.fillRoundRect(69, 98, 20, 45, 5, GREEN);
|
||||
delay(500);
|
||||
// play color
|
||||
tft.fillTriangle(42, 20, 42, 60, 90, 40, BLUE);
|
||||
delay(50);
|
||||
// pause color
|
||||
tft.fillRoundRect(39, 98, 20, 45, 5, RED);
|
||||
tft.fillRoundRect(69, 98, 20, 45, 5, RED);
|
||||
// play color
|
||||
tft.fillTriangle(42, 20, 42, 60, 90, 40, GREEN);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ST7789 KEYWORD1
|
||||
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
setRotation KEYWORD2
|
||||
setAddrWindow KEYWORD2
|
||||
pushColor KEYWORD2
|
||||
drawPixel KEYWORD2
|
||||
drawFastVLine KEYWORD2
|
||||
drawFastHLine KEYWORD2
|
||||
fillRect KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
setRotation KEYWORD2
|
||||
height KEYWORD2
|
||||
width KEYWORD2
|
||||
invertDisplay KEYWORD2
|
||||
drawImage KEYWORD2
|
||||
setScrollArea KEYWORD2
|
||||
scroll KEYWORD2
|
|
@ -0,0 +1,9 @@
|
|||
name=Arduino ST7789 Library
|
||||
version=0.9.5
|
||||
author=Ananev Ilya
|
||||
maintainer=Ananev Ilya <ananevilya@gmail.com>
|
||||
sentence=This is a library for the ST7789 IPS SPI display.
|
||||
paragraph=This is a library for the ST7789 IPS SPI display.
|
||||
category=Display
|
||||
url=https://github.com/ananevilya/Arduino-ST7789-Library
|
||||
architectures=*
|
|
@ -0,0 +1,2 @@
|
|||
.vscode
|
||||
.DS_Store
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 lewis he
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,2 @@
|
|||
FT5206 Library
|
||||
=====================================
|
|
@ -0,0 +1,29 @@
|
|||
#######################################
|
||||
# Syntax Coloring Map For FT5206 Library By lewis He
|
||||
# github:https://github.com/lewisxhe
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
TP_Point KEYWORD1
|
||||
FT5206_Class KEYWORD1
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
adjustTheshold KEYWORD2
|
||||
getPoint KEYWORD2
|
||||
enterSleepMode KEYWORD2
|
||||
enterMonitorMode KEYWORD2
|
||||
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
|
@ -0,0 +1,10 @@
|
|||
name=FT5206_Library
|
||||
version=1.0.0
|
||||
author=Lewis He
|
||||
maintainer=Lewis He <lewishe@outlook.com>
|
||||
sentence=Arduino library for FT5206 chip.
|
||||
paragraph=Arduino library for FT5206 chip. Tested with ESP32
|
||||
category=Communication
|
||||
url=https://github.com/lewisxhe/FT5206_Library
|
||||
architectures=*
|
||||
architectures=esp32
|
|
@ -0,0 +1,108 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 lewis he
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
FT5206.cpp - Arduino library for FT5206 chip.
|
||||
Created by Lewis on April 17, 2019.
|
||||
github:https://github.com/lewisxhe/FT5206_Library
|
||||
*/
|
||||
/////////////////////////////////////////////////////////////////
|
||||
#include "FT5206.h"
|
||||
|
||||
int FT5206_Class::begin(TwoWire &port, uint8_t addr)
|
||||
{
|
||||
_i2cPort = &port;
|
||||
_address = addr;
|
||||
uint8_t val;
|
||||
_readByte(FT5206_VENDID_REG, 1, &val);
|
||||
//Serial.printf("vend id %d\n",val );
|
||||
if (val != FT5206_VENDID) {
|
||||
// return false;
|
||||
}
|
||||
_readByte(FT5206_CHIPID_REG, 1, &val);
|
||||
//Serial.printf("chip id %d\n",val );
|
||||
if ((val != FT6206_CHIPID) && (val != FT6236_CHIPID) && (val != FT6236U_CHIPID) && (val != FT5206U_CHIPID)) {
|
||||
return false;
|
||||
}
|
||||
_init = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// valid touching detect threshold.
|
||||
void FT5206_Class::adjustTheshold(uint8_t thresh)
|
||||
{
|
||||
if (!_init)return;
|
||||
_writeByte(FT5206_THRESHHOLD_REG, 1, &thresh);
|
||||
}
|
||||
|
||||
TP_Point FT5206_Class::getPoint(uint8_t num)
|
||||
{
|
||||
if (!_init) return TP_Point(0, 0);
|
||||
_readRegister();
|
||||
if ((_touches == 0) || (num > 1)) {
|
||||
return TP_Point(0, 0);
|
||||
} else {
|
||||
return TP_Point(_x[num], _y[num]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t FT5206_Class::touched()
|
||||
{
|
||||
if (!_init)return 0;
|
||||
uint8_t val = 0;
|
||||
_readByte(FT5206_TOUCHES_REG,1,&val);
|
||||
return val > 2 ? 0: val;
|
||||
}
|
||||
|
||||
void FT5206_Class::enterSleepMode()
|
||||
{
|
||||
if (!_init)return;
|
||||
uint8_t val = FT5206_SLEEP_IN;
|
||||
_writeByte(FT5206_POWER_REG, 1, &val);
|
||||
}
|
||||
|
||||
void FT5206_Class::enterMonitorMode()
|
||||
{
|
||||
if (!_init)return;
|
||||
uint8_t val = FT5206_MONITOR;
|
||||
_writeByte(FT5206_POWER_REG, 1, &val);
|
||||
}
|
||||
|
||||
void FT5206_Class::_readRegister()
|
||||
{
|
||||
_readByte(DEVIDE_MODE, 16, _data);
|
||||
_touches = _data[TD_STATUS];
|
||||
if ((_touches > 2) || (_touches == 0)) {
|
||||
_touches = 0;
|
||||
return;
|
||||
}
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
_x[i] = _data[TOUCH1_XH + i * 6] & 0x0F;
|
||||
_x[i] <<= 8;
|
||||
_x[i] |= _data[TOUCH1_XL + i * 6];
|
||||
_y[i] = _data[TOUCH1_YH + i * 6] & 0x0F;
|
||||
_y[i] <<= 8;
|
||||
_y[i] |= _data[TOUCH1_YL + i * 6];
|
||||
_id[i] = _data[TOUCH1_YH + i * 6] >> 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 lewis he
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
FT5206.h - Arduino library for FT5206 chip.
|
||||
Created by Lewis on April 17, 2019.
|
||||
github:https://github.com/lewisxhe/FT5206_Library
|
||||
*/
|
||||
/////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#define FT5206_SLAVE_ADDRESS (0x38)
|
||||
#define FT5206_MODE_REG (0x00)
|
||||
#define FT5206_TOUCHES_REG (0x02)
|
||||
#define FT5206_VENDID_REG (0xA8)
|
||||
#define FT5206_CHIPID_REG (0xA3)
|
||||
#define FT5206_THRESHHOLD_REG (0x80)
|
||||
#define FT5206_POWER_REG (0x87)
|
||||
|
||||
#define FT5206_MONITOR (0x01)
|
||||
#define FT5206_SLEEP_IN (0x03)
|
||||
|
||||
#define FT5206_VENDID 0x11
|
||||
#define FT6206_CHIPID 0x06
|
||||
#define FT6236_CHIPID 0x36
|
||||
#define FT6236U_CHIPID 0x64
|
||||
#define FT5206U_CHIPID 0x64
|
||||
|
||||
#define DEVIDE_MODE 0x00
|
||||
#define TD_STATUS 0x02
|
||||
#define TOUCH1_XH 0x03
|
||||
#define TOUCH1_XL 0x04
|
||||
#define TOUCH1_YH 0x05
|
||||
#define TOUCH1_YL 0x06
|
||||
|
||||
class TP_Point
|
||||
{
|
||||
public:
|
||||
TP_Point(void)
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
TP_Point(int16_t _x, int16_t _y)
|
||||
{
|
||||
x = _x;
|
||||
y = _y;
|
||||
}
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
};
|
||||
|
||||
|
||||
class FT5206_Class
|
||||
{
|
||||
public:
|
||||
FT5206_Class() {};
|
||||
int begin(TwoWire &port = Wire, uint8_t addr = FT5206_SLAVE_ADDRESS);
|
||||
// valid touching detect threshold.
|
||||
void adjustTheshold(uint8_t thresh);
|
||||
TP_Point getPoint(uint8_t num = 0);
|
||||
uint8_t touched();
|
||||
void enterSleepMode();
|
||||
void enterMonitorMode();
|
||||
private:
|
||||
void _readRegister();
|
||||
int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data)
|
||||
{
|
||||
_i2cPort->beginTransmission(_address);
|
||||
_i2cPort->write(reg);
|
||||
_i2cPort->endTransmission();
|
||||
_i2cPort->requestFrom(_address, nbytes);
|
||||
uint8_t index = 0;
|
||||
while (_i2cPort->available())
|
||||
data[index++] = _i2cPort->read();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data)
|
||||
{
|
||||
_i2cPort->beginTransmission(_address);
|
||||
_i2cPort->write(reg);
|
||||
for (uint8_t i = 0; i < nbytes; i++) {
|
||||
_i2cPort->write(data[i]);
|
||||
}
|
||||
_i2cPort->endTransmission();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t _address;
|
||||
uint8_t _data[16];
|
||||
uint16_t _x[2];
|
||||
uint16_t _y[2];
|
||||
uint16_t _id[2];
|
||||
uint8_t _touches = 0;
|
||||
bool _init = false;
|
||||
TwoWire *_i2cPort;
|
||||
};
|
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
xdsp_12_ST7789.ino - Display ST7789 support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Gerhard Mutz and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_ST7789
|
||||
|
||||
#define XDSP_12 12
|
||||
#define XI2C_38 38 // See I2CDEVICES.md
|
||||
|
||||
#undef COLORED
|
||||
#define COLORED 1
|
||||
#undef UNCOLORED
|
||||
#define UNCOLORED 0
|
||||
|
||||
// touch panel controller
|
||||
#undef FT5206_address
|
||||
#define FT5206_address 0x38
|
||||
|
||||
// using font 8 is opional (num=3)
|
||||
// very badly readable, but may be useful for graphs
|
||||
#undef USE_TINY_FONT
|
||||
#define USE_TINY_FONT
|
||||
|
||||
|
||||
#include <Arduino_ST7789.h>
|
||||
#include <FT5206.h>
|
||||
|
||||
// currently fixed
|
||||
#define BACKPLANE_PIN 2
|
||||
|
||||
extern uint8_t *buffer;
|
||||
extern uint8_t color_type;
|
||||
Arduino_ST7789 *st7789;
|
||||
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
extern VButton *buttons[];
|
||||
#endif
|
||||
FT5206_Class *touchp;
|
||||
uint8_t FT5206_found;
|
||||
TP_Point st7789_pLoc;
|
||||
uint8_t st7789_ctouch_counter = 0;
|
||||
#endif // USE_FT5206
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void ST7789_InitDriver()
|
||||
{
|
||||
if (!Settings.display_model) {
|
||||
Settings.display_model = XDSP_12;
|
||||
}
|
||||
|
||||
if (XDSP_12 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != ST7789_TFTWIDTH) {
|
||||
Settings.display_width = ST7789_TFTWIDTH;
|
||||
}
|
||||
if (Settings.display_height != ST7789_TFTHEIGHT) {
|
||||
Settings.display_height = ST7789_TFTHEIGHT;
|
||||
}
|
||||
|
||||
// disable screen buffer
|
||||
buffer=NULL;
|
||||
|
||||
// default colors
|
||||
fg_color = ST7789_WHITE;
|
||||
bg_color = ST7789_BLACK;
|
||||
|
||||
uint8_t bppin=BACKPLANE_PIN;
|
||||
if (PinUsed(GPIO_BACKLIGHT)) {
|
||||
bppin=Pin(GPIO_BACKLIGHT);
|
||||
}
|
||||
|
||||
uint8_t reset = -1;
|
||||
if (PinUsed(GPIO_OLED_RESET)) {
|
||||
reset=Pin(GPIO_OLED_RESET);
|
||||
}
|
||||
|
||||
uint8_t cs = -1;
|
||||
if (PinUsed(GPIO_SSPI_CS)) {
|
||||
cs=Pin(GPIO_SSPI_CS);
|
||||
} else if (PinUsed(GPIO_SPI_CS)) {
|
||||
cs=Pin(GPIO_SPI_CS);
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
#undef HW_SPI_MOSI
|
||||
#define HW_SPI_MOSI 23
|
||||
#undef HW_SPI_CLK
|
||||
#define HW_SPI_CLK 18
|
||||
#else
|
||||
#undef HW_SPI_MOSI
|
||||
#define HW_SPI_MOSI 13
|
||||
#undef HW_SPI_CLK
|
||||
#define HW_SPI_CLK 14
|
||||
#endif
|
||||
|
||||
// init renderer, may use hardware spi
|
||||
if (PinUsed(GPIO_SPI_CS) && (Pin(GPIO_SPI_MOSI)==HW_SPI_MOSI) && (Pin(GPIO_SPI_CLK)==HW_SPI_CLK) && PinUsed(GPIO_SPI_DC)) {
|
||||
st7789 = new Arduino_ST7789(Pin(GPIO_SPI_DC), reset, Pin(GPIO_SPI_MOSI), Pin(GPIO_SPI_CLK), cs, bppin);
|
||||
} else {
|
||||
if ((PinUsed(GPIO_SSPI_CS) || PinUsed(GPIO_OLED_RESET)) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) {
|
||||
st7789 = new Arduino_ST7789(Pin(GPIO_SSPI_DC), reset, Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_SCLK), cs, bppin);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
st7789->init(Settings.display_width,Settings.display_height);
|
||||
renderer = st7789;
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
|
||||
#ifdef SHOW_SPLASH
|
||||
// Welcome text
|
||||
renderer->setTextFont(2);
|
||||
renderer->setTextColor(ST7789_WHITE,ST7789_BLACK);
|
||||
renderer->DrawStringAt(30, 100, "ST7789 TFT!", ST7789_WHITE,0);
|
||||
delay(1000);
|
||||
#endif
|
||||
|
||||
color_type = COLOR_COLOR;
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_FT5206
|
||||
// start digitizer with fixed adress and pins for esp32
|
||||
#define SDA_2 23
|
||||
#define SCL_2 32
|
||||
Wire1.begin(SDA_2, SCL_2, 400000);
|
||||
touchp = new FT5206_Class();
|
||||
if (touchp->begin(Wire1, FT5206_address)) {
|
||||
FT5206_found=1;
|
||||
//I2cSetDevice(FT5206_address);
|
||||
I2cSetActiveFound(FT5206_address, "FT5206");
|
||||
} else {
|
||||
FT5206_found=0;
|
||||
}
|
||||
#endif // USE_FT5206
|
||||
#endif // ESP32
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
void ST7789_MQTT(uint8_t count,const char *cp) {
|
||||
ResponseTime_P(PSTR(",\"ST7789\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7);
|
||||
MqttPublishTeleSensor();
|
||||
}
|
||||
|
||||
void ST7789_RDW_BUTT(uint32_t count,uint32_t pwr) {
|
||||
buttons[count]->xdrawButton(pwr);
|
||||
if (pwr) buttons[count]->vpower|=0x80;
|
||||
else buttons[count]->vpower&=0x7f;
|
||||
}
|
||||
// check digitizer hit
|
||||
void FT5206Check() {
|
||||
uint16_t temp;
|
||||
uint8_t rbutt=0,vbutt=0;
|
||||
st7789_ctouch_counter++;
|
||||
if (2 == st7789_ctouch_counter) {
|
||||
// every 100 ms should be enough
|
||||
st7789_ctouch_counter=0;
|
||||
|
||||
if (touchp->touched()) {
|
||||
// did find a hit
|
||||
st7789_pLoc = touchp->getPoint(0);
|
||||
if (renderer) {
|
||||
uint8_t rot=renderer->getRotation();
|
||||
switch (rot) {
|
||||
case 0:
|
||||
temp=st7789_pLoc.y;
|
||||
st7789_pLoc.y=renderer->height()-st7789_pLoc.x;
|
||||
st7789_pLoc.x=temp;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
temp=st7789_pLoc.y;
|
||||
st7789_pLoc.y=st7789_pLoc.x;
|
||||
st7789_pLoc.x=renderer->width()-temp;
|
||||
break;
|
||||
}
|
||||
// now must compare with defined buttons
|
||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||
if (buttons[count]->contains(st7789_pLoc.x,st7789_pLoc.y)) {
|
||||
// did hit
|
||||
buttons[count]->press(true);
|
||||
if (buttons[count]->justPressed()) {
|
||||
if (!bflags) {
|
||||
uint8_t pwr=bitRead(power,rbutt);
|
||||
if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) {
|
||||
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
|
||||
ST7789_RDW_BUTT(count,!pwr);
|
||||
}
|
||||
} else {
|
||||
// virtual button
|
||||
const char *cp;
|
||||
if (bflags==1) {
|
||||
// toggle button
|
||||
buttons[count]->vpower^=0x80;
|
||||
cp="TBT";
|
||||
} else {
|
||||
// push button
|
||||
buttons[count]->vpower|=0x80;
|
||||
cp="PBT";
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
||||
ST7789_MQTT(count,cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!bflags) {
|
||||
rbutt++;
|
||||
} else {
|
||||
vbutt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// no hit
|
||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||
buttons[count]->press(false);
|
||||
if (buttons[count]->justReleased()) {
|
||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||
if (bflags>0) {
|
||||
if (bflags>1) {
|
||||
// push button
|
||||
buttons[count]->vpower&=0x7f;
|
||||
ST7789_MQTT(count,"PBT");
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
||||
}
|
||||
}
|
||||
if (!bflags) {
|
||||
// check if power button stage changed
|
||||
uint8_t pwr=bitRead(power,rbutt);
|
||||
uint8_t vpwr=(buttons[count]->vpower&0x80)>>7;
|
||||
if (pwr!=vpwr) {
|
||||
ST7789_RDW_BUTT(count,pwr);
|
||||
}
|
||||
rbutt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
st7789_pLoc.x=0;
|
||||
st7789_pLoc.y=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
#endif // USE_FT5206
|
||||
#endif // ESP32
|
||||
|
||||
/*********************************************************************************************/
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
bool Xdsp12(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR("touch %d - %d"), FT5206_found, function);
|
||||
|
||||
if (FUNC_DISPLAY_INIT_DRIVER == function) {
|
||||
ST7789_InitDriver();
|
||||
}
|
||||
else if (XDSP_12 == Settings.display_model) {
|
||||
switch (function) {
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
case FUNC_DISPLAY_EVERY_50_MSECOND:
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
if (FT5206_found) {
|
||||
FT5206Check();
|
||||
}
|
||||
#endif
|
||||
#endif // USE_FT5206
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DISPLAY_ST7789
|
||||
#endif // USE_DISPLAY
|
||||
#endif // USE_SPI
|
Loading…
Reference in New Issue