/***************************************************
This is a library for the ST7789 IPS SPI display.
Written by Ananev Ilya.
****************************************************/
#include <Adafruit_ST7789>
#include <limits.h>
#include <SPI.h>
static const uint8_t PROGMEM
cmd2_240x240[] = { // Initialization commands for 7789 screens
7, // 6 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_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
static const uint8_t PROGMEM
generic_st7789[] = { // Init commands for 7789 screens
9, // 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
10, // 10 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: Mem access ctrl (directions), 1 arg:
0x08, // Row/col addr, bottom-top refresh
ST7789_CASET , 4, // 5: Column addr set, 4 args, no delay:
0x00,
0, // XSTART = 0
0,
240, // XEND = 240
ST7789_RASET , 4, // 6: Row addr set, 4 args, no delay:
0x00,
0, // YSTART = 0
320>>8,
320&0xFF, // YEND = 320
ST7789_INVON , ST_CMD_DELAY, // 7: hack
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, delay
10 }; // 10 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()
#define SPI_END_TRANSACTION()
#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)
: Adafruit_GFX(ST7789_TFTWIDTH_240, ST7789_TFTHEIGHT_240)
{
_cs = cs;
_dc = dc;
_sid = sid;
_sclk = sclk;
_rst = rst;
_hwSPI = 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)
: Adafruit_GFX(ST7789_TFTWIDTH_240, ST7789_TFTHEIGHT_240) {
_cs = cs;
_dc = dc;
_rst = rst;
_hwSPI = true;
_sid = _sclk = -1;
}
inline void Arduino_ST7789::spiwrite(uint8_t c)
{
SPI.transfer(c);
}
void Arduino_ST7789::writecommand(uint8_t c) {
SPI_BEGIN_TRANSACTION();
DC_LOW();
CS_LOW();
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) {
pinMode(_cs, OUTPUT);
}
SPI.begin();
#if defined(USE_FAST_IO)
dcport = portOutputRegister(digitalPinToPort(_dc));
dcpinmask = digitalPinToBitMask(_dc);
if(_cs) {
csport = portOutputRegister(digitalPinToPort(_cs));
cspinmask = digitalPinToBitMask(_cs);
}
#endif
if(_hwSPI) { // Using hardware SPI
#if defined (SPI_HAS_TRANSACTION)
mySPISettings = SPISettings(30000000, 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) {
uint8_t madctl = 0;
rotation = m & 3; // can't be higher than 3
switch (rotation) {
case 0:
madctl = ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB;
_xstart = _colstart;
_ystart = _rowstart;
_width = _WIDTH;
_height = _HEIGHT;
break;
case 1:
madctl = ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB;
_xstart = _rowstart;
_ystart = _colstart;
_height = _WIDTH;
_width = _HEIGHT;
break;
case 2:
madctl = ST7789_MADCTL_RGB;
if ((_WIDTH == 135) && (_HEIGHT == 240)) {
_xstart = _colstart;
_ystart = _rowstart;
} else {
_xstart = 0;
_ystart = 0;
}
_width = _WIDTH;
_height = _HEIGHT;
break;
case 3:
madctl = ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB;
if ((_WIDTH == 135) && (_HEIGHT == 240)) {
_xstart = _rowstart;
_ystart = _colstart;
} else {
_xstart = 0;
_ystart = 0;
}
_height = _WIDTH;
_width = _HEIGHT;
break;
}
writecommand(ST7789_MADCTL);
writedata( madctl );
}
void Arduino_ST7789::setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1,
uint8_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) {
pinSetFast(_cs);
}
inline void Arduino_ST7789::CS_LOW(void) {
pinResetFast(_cs);
}
inline void Arduino_ST7789::DC_HIGH(void) {
pinSetFast(_dc);
}
inline void Arduino_ST7789::DC_LOW(void) {
pinResetFast(_dc);
}
void Arduino_ST7789::init(uint16_t width, uint16_t height) {
commonInit(NULL);
if ((width == 240) && (height == 240)) { // 1.3" and 1.54" displays
_colstart = 0;
_rowstart = 80;
} else if ((width == 135) && (height == 240)) { // 1.13" display
_colstart = 53;
_rowstart = 40;
} else {
_colstart = 0;
_rowstart = 0;
}
// Next two lines are to work around a bug in the current mfGFX
// where WIDTH and HEIGHT are set to "const", preventing change
_WIDTH = width;
_HEIGHT = height;
displayInit( generic_st7789 );
setRotation(0);
}
/***************************************************
This is a library for the ST7789 IPS SPI display.
Written by Ananev Ilya. Forked from
https://github.com/lspoplove/Arduino-ST7789-Library
and adapted for Particle Photon by @jenschr to
https://github.com/jenschr/Arduino-ST7789-Library
Tested with this display from Adafruit:
https://learn.adafruit.com/adafruit-1-14-240x135-color-tft-breakout/pinouts
****************************************************/
#ifndef _ADAFRUIT_ST7789H_
#define _ADAFRUIT_ST7789H_
#if ARDUINO >= 100
#include "Arduino.h"
#include "Print.h"
#elif defined (PARTICLE)
#include <application.h>
#else
#include "WProgram.h"
#endif
#if defined(PARTICLE)
#include <Adafruit_mfGFX.h>
#else
#include <Adafruit_GFX.h>
#endif
#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 ST7789_TFTWIDTH_240 240
#define ST7789_TFTHEIGHT_240 240
#define ST7789_240x240_XSTART 53
#define ST7789_240x240_YSTART 40
#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
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
class Arduino_ST7789 : public Adafruit_GFX {
public:
Arduino_ST7789(int8_t DC, int8_t RST, int8_t SID, int8_t SCLK, int8_t CS = -1);
Arduino_ST7789(int8_t DC, int8_t RST, int8_t CS = -1);
void setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_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),
init(uint16_t width, uint16_t height);
uint16_t Color565(uint8_t r, uint8_t g, uint8_t b);
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) { return Color565(r, g, b); }
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;
int8_t _cs, _dc, _rst, _sid, _sclk;
int16_t _WIDTH, _HEIGHT;
#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
You meean like this?