Michael Hope
51dddbdc17
The ESP8266 SPI implementation has a 'writePattern' function that writes a repeating sequence (in this case a solid colour) to the SPI port. This fills up the FIFO and increases the bus utilisation. Using this for clearing the screen cuts the demo run time from 4721 ms to 3601 ms. Also using this for the fast lines cuts the run time to 3424 ms. Signed-off-by: Michael Hope <mlhx@google.com>
748 lines
22 KiB
C++
Executable file
748 lines
22 KiB
C++
Executable file
/***************************************************
|
|
This is a library for the Adafruit 1.8" SPI display.
|
|
|
|
This library works with the Adafruit 1.8" TFT Breakout w/SD card
|
|
----> http://www.adafruit.com/products/358
|
|
The 1.8" TFT shield
|
|
----> https://www.adafruit.com/product/802
|
|
The 1.44" TFT breakout
|
|
----> https://www.adafruit.com/product/2088
|
|
as well as Adafruit raw 1.8" TFT display
|
|
----> http://www.adafruit.com/products/618
|
|
|
|
Check out the links above for our tutorials and wiring diagrams
|
|
These displays use SPI to communicate, 4 or 5 pins are required to
|
|
interface (RST is optional)
|
|
Adafruit invests time and resources providing this open source code,
|
|
please support Adafruit and open-source hardware by purchasing
|
|
products from Adafruit!
|
|
|
|
Written by Limor Fried/Ladyada for Adafruit Industries.
|
|
MIT license, all text above must be included in any redistribution
|
|
****************************************************/
|
|
|
|
#include "Adafruit_ST7735.h"
|
|
#include <limits.h>
|
|
#include "pins_arduino.h"
|
|
#include "wiring_private.h"
|
|
#include <SPI.h>
|
|
|
|
#if !defined(ST7735_USE_HWSPI_ONLY)
|
|
// Constructor when using software SPI. All output pins are configurable.
|
|
Adafruit_ST7735::Adafruit_ST7735(int8_t cs, int8_t rs, int8_t sid, int8_t sclk, int8_t rst)
|
|
: Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT_18)
|
|
{
|
|
_cs = cs;
|
|
_rs = rs;
|
|
_sid = sid;
|
|
_sclk = sclk;
|
|
_rst = rst;
|
|
hwSPI = false;
|
|
}
|
|
#endif
|
|
|
|
// 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.)
|
|
Adafruit_ST7735::Adafruit_ST7735(int8_t cs, int8_t rs, int8_t rst)
|
|
: Adafruit_GFX(ST7735_TFTWIDTH, ST7735_TFTHEIGHT_18) {
|
|
_cs = cs;
|
|
_rs = rs;
|
|
_rst = rst;
|
|
hwSPI = true;
|
|
_sid = _sclk = 0;
|
|
}
|
|
|
|
#if defined(CORE_TEENSY) && !defined(__AVR__)
|
|
#define __AVR__
|
|
#endif
|
|
|
|
#if defined(ST7735_USE_HWSPI_ONLY)
|
|
inline void Adafruit_ST7735::spiwrite(uint8_t c) {
|
|
SPI.transfer(c);
|
|
}
|
|
#elif defined(__AVR__)
|
|
inline void Adafruit_ST7735::spiwrite(uint8_t c) {
|
|
|
|
//Serial.println(c, HEX);
|
|
|
|
if (hwSPI) {
|
|
SPDR = c;
|
|
while(!(SPSR & _BV(SPIF)));
|
|
} else {
|
|
// Fast SPI bitbang swiped from LPD8806 library
|
|
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
|
if(c & bit) *dataport |= datapinmask;
|
|
else *dataport &= ~datapinmask;
|
|
*clkport |= clkpinmask;
|
|
*clkport &= ~clkpinmask;
|
|
}
|
|
}
|
|
}
|
|
#elif defined(__SAM3X8E__)
|
|
inline void Adafruit_ST7735::spiwrite(uint8_t c) {
|
|
|
|
//Serial.println(c, HEX);
|
|
|
|
if (hwSPI) {
|
|
SPI.transfer(c);
|
|
} else {
|
|
// Fast SPI bitbang swiped from LPD8806 library
|
|
for(uint8_t bit = 0x80; bit; bit >>= 1) {
|
|
if(c & bit) dataport->PIO_SODR |= datapinmask;
|
|
else dataport->PIO_CODR |= datapinmask;
|
|
clkport->PIO_SODR |= clkpinmask;
|
|
clkport->PIO_CODR |= clkpinmask;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
#error Unsupported board.
|
|
#endif
|
|
|
|
#if defined(ST7735_USE_HWSPI_WRITE16)
|
|
inline void Adafruit_ST7735::spiwrite16(uint16_t v) {
|
|
SPI.write16(v);
|
|
}
|
|
#else
|
|
inline void Adafruit_ST7735::spiwrite16(uint16_t v) {
|
|
spiwrite((uint8_t)(v >> 8));
|
|
spiwrite((uint8_t)(v >> 0));
|
|
}
|
|
#endif
|
|
|
|
#if defined(ST7735_USE_GENERIC_IO)
|
|
inline void Adafruit_ST7735::setCS(bool level) {
|
|
digitalWrite(_cs, level);
|
|
}
|
|
|
|
inline void Adafruit_ST7735::setRS(bool level) {
|
|
digitalWrite(_rs, level);
|
|
}
|
|
#elif defined(__AVR__)
|
|
inline void Adafruit_ST7735::setCS(bool level) {
|
|
if (level) {
|
|
*csport |= cspinmask;
|
|
} else {
|
|
*csport &= ~cspinmask;
|
|
}
|
|
}
|
|
|
|
inline void Adafruit_ST7735::setRS(bool level) {
|
|
if (level) {
|
|
*rsport |= rspinmask;
|
|
} else {
|
|
*rsport &= ~rspinmask;
|
|
}
|
|
}
|
|
#elif defined(__SAM3X8E__)
|
|
inline void Adafruit_ST7735::setCS(bool level) {
|
|
if (level) {
|
|
csport->PIO_SODR |= cspinmask;
|
|
} else {
|
|
csport->PIO_CODR |= cspinmask;
|
|
}
|
|
}
|
|
|
|
inline void Adafruit_ST7735::setRS(bool level) {
|
|
if (level) {
|
|
rsport->PIO_SODR |= rspinmask;
|
|
} else {
|
|
rsport->PIO_CODR |= rspinmask;
|
|
}
|
|
}
|
|
#else
|
|
#error Unsupported board.
|
|
#endif
|
|
|
|
void Adafruit_ST7735::writecommand(uint8_t c) {
|
|
setRS(false);
|
|
setCS(false);
|
|
|
|
//Serial.print("C ");
|
|
spiwrite(c);
|
|
|
|
setCS(true);
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::writedata(uint8_t c) {
|
|
setRS(true);
|
|
setCS(false);
|
|
|
|
//Serial.print("D ");
|
|
spiwrite(c);
|
|
|
|
setCS(true);
|
|
}
|
|
|
|
void Adafruit_ST7735::writedata16(uint16_t c) {
|
|
setRS(true);
|
|
setCS(false);
|
|
|
|
//Serial.print("D ");
|
|
spiwrite16(c);
|
|
|
|
setCS(true);
|
|
}
|
|
|
|
// Rather than a bazillion writecommand() and writedata() calls, screen
|
|
// initialization commands and arguments are organized in these tables
|
|
// stored in PROGMEM. The table may look bulky, but that's mostly the
|
|
// formatting -- storage-wise this is hundreds of bytes more compact
|
|
// than the equivalent code. Companion function follows.
|
|
#define DELAY 0x80
|
|
static const uint8_t PROGMEM
|
|
Bcmd[] = { // Initialization commands for 7735B screens
|
|
18, // 18 commands in list:
|
|
ST7735_SWRESET, DELAY, // 1: Software reset, no args, w/delay
|
|
50, // 50 ms delay
|
|
ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, no args, w/delay
|
|
255, // 255 = 500 ms delay
|
|
ST7735_COLMOD , 1+DELAY, // 3: Set color mode, 1 arg + delay:
|
|
0x05, // 16-bit color
|
|
10, // 10 ms delay
|
|
ST7735_FRMCTR1, 3+DELAY, // 4: Frame rate control, 3 args + delay:
|
|
0x00, // fastest refresh
|
|
0x06, // 6 lines front porch
|
|
0x03, // 3 lines back porch
|
|
10, // 10 ms delay
|
|
ST7735_MADCTL , 1 , // 5: Memory access ctrl (directions), 1 arg:
|
|
0x08, // Row addr/col addr, bottom to top refresh
|
|
ST7735_DISSET5, 2 , // 6: Display settings #5, 2 args, no delay:
|
|
0x15, // 1 clk cycle nonoverlap, 2 cycle gate
|
|
// rise, 3 cycle osc equalize
|
|
0x02, // Fix on VTL
|
|
ST7735_INVCTR , 1 , // 7: Display inversion control, 1 arg:
|
|
0x0, // Line inversion
|
|
ST7735_PWCTR1 , 2+DELAY, // 8: Power control, 2 args + delay:
|
|
0x02, // GVDD = 4.7V
|
|
0x70, // 1.0uA
|
|
10, // 10 ms delay
|
|
ST7735_PWCTR2 , 1 , // 9: Power control, 1 arg, no delay:
|
|
0x05, // VGH = 14.7V, VGL = -7.35V
|
|
ST7735_PWCTR3 , 2 , // 10: Power control, 2 args, no delay:
|
|
0x01, // Opamp current small
|
|
0x02, // Boost frequency
|
|
ST7735_VMCTR1 , 2+DELAY, // 11: Power control, 2 args + delay:
|
|
0x3C, // VCOMH = 4V
|
|
0x38, // VCOML = -1.1V
|
|
10, // 10 ms delay
|
|
ST7735_PWCTR6 , 2 , // 12: Power control, 2 args, no delay:
|
|
0x11, 0x15,
|
|
ST7735_GMCTRP1,16 , // 13: Magical unicorn dust, 16 args, no delay:
|
|
0x09, 0x16, 0x09, 0x20, // (seriously though, not sure what
|
|
0x21, 0x1B, 0x13, 0x19, // these config values represent)
|
|
0x17, 0x15, 0x1E, 0x2B,
|
|
0x04, 0x05, 0x02, 0x0E,
|
|
ST7735_GMCTRN1,16+DELAY, // 14: Sparkles and rainbows, 16 args + delay:
|
|
0x0B, 0x14, 0x08, 0x1E, // (ditto)
|
|
0x22, 0x1D, 0x18, 0x1E,
|
|
0x1B, 0x1A, 0x24, 0x2B,
|
|
0x06, 0x06, 0x02, 0x0F,
|
|
10, // 10 ms delay
|
|
ST7735_CASET , 4 , // 15: Column addr set, 4 args, no delay:
|
|
0x00, 0x02, // XSTART = 2
|
|
0x00, 0x81, // XEND = 129
|
|
ST7735_RASET , 4 , // 16: Row addr set, 4 args, no delay:
|
|
0x00, 0x02, // XSTART = 1
|
|
0x00, 0x81, // XEND = 160
|
|
ST7735_NORON , DELAY, // 17: Normal display on, no args, w/delay
|
|
10, // 10 ms delay
|
|
ST7735_DISPON , DELAY, // 18: Main screen turn on, no args, w/delay
|
|
255 }, // 255 = 500 ms delay
|
|
|
|
Rcmd1[] = { // Init for 7735R, part 1 (red or green tab)
|
|
15, // 15 commands in list:
|
|
ST7735_SWRESET, DELAY, // 1: Software reset, 0 args, w/delay
|
|
150, // 150 ms delay
|
|
ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, 0 args, w/delay
|
|
255, // 500 ms delay
|
|
ST7735_FRMCTR1, 3 , // 3: Frame rate ctrl - normal mode, 3 args:
|
|
0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
|
ST7735_FRMCTR2, 3 , // 4: Frame rate control - idle mode, 3 args:
|
|
0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D)
|
|
ST7735_FRMCTR3, 6 , // 5: Frame rate ctrl - partial mode, 6 args:
|
|
0x01, 0x2C, 0x2D, // Dot inversion mode
|
|
0x01, 0x2C, 0x2D, // Line inversion mode
|
|
ST7735_INVCTR , 1 , // 6: Display inversion ctrl, 1 arg, no delay:
|
|
0x07, // No inversion
|
|
ST7735_PWCTR1 , 3 , // 7: Power control, 3 args, no delay:
|
|
0xA2,
|
|
0x02, // -4.6V
|
|
0x84, // AUTO mode
|
|
ST7735_PWCTR2 , 1 , // 8: Power control, 1 arg, no delay:
|
|
0xC5, // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD
|
|
ST7735_PWCTR3 , 2 , // 9: Power control, 2 args, no delay:
|
|
0x0A, // Opamp current small
|
|
0x00, // Boost frequency
|
|
ST7735_PWCTR4 , 2 , // 10: Power control, 2 args, no delay:
|
|
0x8A, // BCLK/2, Opamp current small & Medium low
|
|
0x2A,
|
|
ST7735_PWCTR5 , 2 , // 11: Power control, 2 args, no delay:
|
|
0x8A, 0xEE,
|
|
ST7735_VMCTR1 , 1 , // 12: Power control, 1 arg, no delay:
|
|
0x0E,
|
|
ST7735_INVOFF , 0 , // 13: Don't invert display, no args, no delay
|
|
ST7735_MADCTL , 1 , // 14: Memory access control (directions), 1 arg:
|
|
0xC8, // row addr/col addr, bottom to top refresh
|
|
ST7735_COLMOD , 1 , // 15: set color mode, 1 arg, no delay:
|
|
0x05 }, // 16-bit color
|
|
|
|
Rcmd2green[] = { // Init for 7735R, part 2 (green tab only)
|
|
2, // 2 commands in list:
|
|
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
|
|
0x00, 0x02, // XSTART = 0
|
|
0x00, 0x7F+0x02, // XEND = 127
|
|
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
|
|
0x00, 0x01, // XSTART = 0
|
|
0x00, 0x9F+0x01 }, // XEND = 159
|
|
Rcmd2red[] = { // Init for 7735R, part 2 (red tab only)
|
|
2, // 2 commands in list:
|
|
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
|
|
0x00, 0x00, // XSTART = 0
|
|
0x00, 0x7F, // XEND = 127
|
|
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
|
|
0x00, 0x00, // XSTART = 0
|
|
0x00, 0x9F }, // XEND = 159
|
|
|
|
Rcmd2green144[] = { // Init for 7735R, part 2 (green 1.44 tab)
|
|
2, // 2 commands in list:
|
|
ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay:
|
|
0x00, 0x00, // XSTART = 0
|
|
0x00, 0x7F, // XEND = 127
|
|
ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay:
|
|
0x00, 0x00, // XSTART = 0
|
|
0x00, 0x7F }, // XEND = 127
|
|
|
|
Rcmd3[] = { // Init for 7735R, part 3 (red or green tab)
|
|
4, // 4 commands in list:
|
|
ST7735_GMCTRP1, 16 , // 1: Magical unicorn dust, 16 args, no delay:
|
|
0x02, 0x1c, 0x07, 0x12,
|
|
0x37, 0x32, 0x29, 0x2d,
|
|
0x29, 0x25, 0x2B, 0x39,
|
|
0x00, 0x01, 0x03, 0x10,
|
|
ST7735_GMCTRN1, 16 , // 2: Sparkles and rainbows, 16 args, no delay:
|
|
0x03, 0x1d, 0x07, 0x06,
|
|
0x2E, 0x2C, 0x29, 0x2D,
|
|
0x2E, 0x2E, 0x37, 0x3F,
|
|
0x00, 0x00, 0x02, 0x10,
|
|
ST7735_NORON , DELAY, // 3: Normal display on, no args, w/delay
|
|
10, // 10 ms delay
|
|
ST7735_DISPON , DELAY, // 4: Main screen turn on, no args w/delay
|
|
100 }; // 100 ms delay
|
|
|
|
|
|
// Companion code to the above tables. Reads and issues
|
|
// a series of LCD commands stored in PROGMEM byte array.
|
|
void Adafruit_ST7735::commandList(const uint8_t *addr) {
|
|
|
|
uint8_t numCommands, numArgs;
|
|
uint16_t ms;
|
|
|
|
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 & DELAY; // If hibit set, delay follows args
|
|
numArgs &= ~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 both 'B' and 'R' type displays
|
|
void Adafruit_ST7735::commonInit(const uint8_t *cmdList) {
|
|
colstart = rowstart = 0; // May be overridden in init func
|
|
|
|
pinMode(_rs, OUTPUT);
|
|
pinMode(_cs, OUTPUT);
|
|
#ifdef __AVR__
|
|
csport = portOutputRegister(digitalPinToPort(_cs));
|
|
rsport = portOutputRegister(digitalPinToPort(_rs));
|
|
#endif
|
|
#if defined(__SAM3X8E__)
|
|
csport = digitalPinToPort(_cs);
|
|
rsport = digitalPinToPort(_rs);
|
|
#endif
|
|
#if !defined(ST7735_USE_GENERIC_IO)
|
|
cspinmask = digitalPinToBitMask(_cs);
|
|
rspinmask = digitalPinToBitMask(_rs);
|
|
#endif
|
|
if(hwSPI) { // Using hardware SPI
|
|
SPI.begin();
|
|
#ifdef __AVR__
|
|
SPI.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz (half speed)
|
|
//Due defaults to 4mHz (clock divider setting of 21)
|
|
#elif defined(__SAM3X8E__)
|
|
SPI.setClockDivider(21); // 4 MHz
|
|
//Due defaults to 4mHz (clock divider setting of 21), but we'll set it anyway
|
|
#else
|
|
// Use 8MHz for other boards.
|
|
SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz
|
|
#endif
|
|
SPI.setBitOrder(MSBFIRST);
|
|
SPI.setDataMode(SPI_MODE0);
|
|
} else {
|
|
pinMode(_sclk, OUTPUT);
|
|
pinMode(_sid , OUTPUT);
|
|
#ifdef __AVR__
|
|
clkport = portOutputRegister(digitalPinToPort(_sclk));
|
|
dataport = portOutputRegister(digitalPinToPort(_sid));
|
|
#endif
|
|
#if defined(__SAM3X8E__)
|
|
clkport = digitalPinToPort(_sclk);
|
|
dataport = digitalPinToPort(_sid);
|
|
#endif
|
|
#if !defined(ST7735_USE_GENERIC_IO)
|
|
clkpinmask = digitalPinToBitMask(_sclk);
|
|
datapinmask = digitalPinToBitMask(_sid);
|
|
#endif
|
|
#ifdef __AVR__
|
|
*clkport &= ~clkpinmask;
|
|
*dataport &= ~datapinmask;
|
|
#endif
|
|
#if defined(__SAM3X8E__)
|
|
clkport ->PIO_CODR |= clkpinmask; // Set control bits to LOW (idle)
|
|
dataport->PIO_CODR |= datapinmask; // Signals are ACTIVE HIGH
|
|
#endif
|
|
}
|
|
|
|
// toggle RST low to reset; CS low so it'll listen to us
|
|
setCS(false);
|
|
if (_rst) {
|
|
pinMode(_rst, OUTPUT);
|
|
digitalWrite(_rst, HIGH);
|
|
delay(500);
|
|
digitalWrite(_rst, LOW);
|
|
delay(500);
|
|
digitalWrite(_rst, HIGH);
|
|
delay(500);
|
|
}
|
|
|
|
if(cmdList) commandList(cmdList);
|
|
}
|
|
|
|
|
|
// Initialization for ST7735B screens
|
|
void Adafruit_ST7735::initB(void) {
|
|
commonInit(Bcmd);
|
|
}
|
|
|
|
|
|
// Initialization for ST7735R screens (green or red tabs)
|
|
void Adafruit_ST7735::initR(uint8_t options) {
|
|
commonInit(Rcmd1);
|
|
if(options == INITR_GREENTAB) {
|
|
commandList(Rcmd2green);
|
|
colstart = 2;
|
|
rowstart = 1;
|
|
} else if(options == INITR_144GREENTAB) {
|
|
_height = ST7735_TFTHEIGHT_144;
|
|
commandList(Rcmd2green144);
|
|
colstart = 2;
|
|
rowstart = 3;
|
|
} else {
|
|
// colstart, rowstart left at default '0' values
|
|
commandList(Rcmd2red);
|
|
}
|
|
commandList(Rcmd3);
|
|
|
|
// if black, change MADCTL color filter
|
|
if (options == INITR_BLACKTAB) {
|
|
writecommand(ST7735_MADCTL);
|
|
writedata(0xC0);
|
|
}
|
|
|
|
tabcolor = options;
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1,
|
|
uint8_t y1) {
|
|
|
|
writecommand(ST7735_CASET); // Column addr set
|
|
writedata16(x0+colstart); // XSTART
|
|
writedata16(x1+colstart); // XEND
|
|
|
|
writecommand(ST7735_RASET); // Row addr set
|
|
writedata16(y0+rowstart); // YSTART
|
|
writedata16(y1+rowstart); // YEND
|
|
|
|
writecommand(ST7735_RAMWR); // write to RAM
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::pushColor(uint16_t color) {
|
|
setRS(true);
|
|
setCS(false);
|
|
|
|
spiwrite16(color);
|
|
|
|
setCS(true);
|
|
}
|
|
|
|
void Adafruit_ST7735::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);
|
|
writedata16(color);
|
|
}
|
|
|
|
void Adafruit_ST7735::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);
|
|
writeColor(color, h);
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::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);
|
|
|
|
writeColor(color, w);
|
|
}
|
|
|
|
|
|
|
|
void Adafruit_ST7735::fillScreen(uint16_t color) {
|
|
fillRect(0, 0, _width, _height, color);
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::writeColor(uint16_t color, uint16_t count) {
|
|
setRS(true);
|
|
setCS(false);
|
|
#if defined(ST7735_USE_HWSPI_WRITEPATTERN)
|
|
uint8_t pattern[] = { (uint8_t)(color >> 8), (uint8_t)(color >> 0) };
|
|
SPI.writePattern(pattern, sizeof(pattern), count);
|
|
#else
|
|
for (; count != 0; count--) {
|
|
spiwrite16(color);
|
|
}
|
|
#endif
|
|
setCS(true);
|
|
}
|
|
|
|
// fill a rectangle
|
|
void Adafruit_ST7735::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);
|
|
writeColor(color, w*h);
|
|
}
|
|
|
|
|
|
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
|
|
uint16_t Adafruit_ST7735::Color565(uint8_t r, uint8_t g, uint8_t b) {
|
|
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
|
|
}
|
|
|
|
|
|
#define MADCTL_MY 0x80
|
|
#define MADCTL_MX 0x40
|
|
#define MADCTL_MV 0x20
|
|
#define MADCTL_ML 0x10
|
|
#define MADCTL_RGB 0x00
|
|
#define MADCTL_BGR 0x08
|
|
#define MADCTL_MH 0x04
|
|
|
|
void Adafruit_ST7735::setRotation(uint8_t m) {
|
|
|
|
writecommand(ST7735_MADCTL);
|
|
rotation = m % 4; // can't be higher than 3
|
|
switch (rotation) {
|
|
case 0:
|
|
if (tabcolor == INITR_BLACKTAB) {
|
|
writedata(MADCTL_MX | MADCTL_MY | MADCTL_RGB);
|
|
} else {
|
|
writedata(MADCTL_MX | MADCTL_MY | MADCTL_BGR);
|
|
}
|
|
_width = ST7735_TFTWIDTH;
|
|
|
|
if (tabcolor == INITR_144GREENTAB)
|
|
_height = ST7735_TFTHEIGHT_144;
|
|
else
|
|
_height = ST7735_TFTHEIGHT_18;
|
|
|
|
break;
|
|
case 1:
|
|
if (tabcolor == INITR_BLACKTAB) {
|
|
writedata(MADCTL_MY | MADCTL_MV | MADCTL_RGB);
|
|
} else {
|
|
writedata(MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
|
}
|
|
|
|
if (tabcolor == INITR_144GREENTAB)
|
|
_width = ST7735_TFTHEIGHT_144;
|
|
else
|
|
_width = ST7735_TFTHEIGHT_18;
|
|
|
|
_height = ST7735_TFTWIDTH;
|
|
break;
|
|
case 2:
|
|
if (tabcolor == INITR_BLACKTAB) {
|
|
writedata(MADCTL_RGB);
|
|
} else {
|
|
writedata(MADCTL_BGR);
|
|
}
|
|
_width = ST7735_TFTWIDTH;
|
|
if (tabcolor == INITR_144GREENTAB)
|
|
_height = ST7735_TFTHEIGHT_144;
|
|
else
|
|
_height = ST7735_TFTHEIGHT_18;
|
|
|
|
break;
|
|
case 3:
|
|
if (tabcolor == INITR_BLACKTAB) {
|
|
writedata(MADCTL_MX | MADCTL_MV | MADCTL_RGB);
|
|
} else {
|
|
writedata(MADCTL_MX | MADCTL_MV | MADCTL_BGR);
|
|
}
|
|
if (tabcolor == INITR_144GREENTAB)
|
|
_width = ST7735_TFTHEIGHT_144;
|
|
else
|
|
_width = ST7735_TFTHEIGHT_18;
|
|
|
|
_height = ST7735_TFTWIDTH;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::invertDisplay(boolean i) {
|
|
writecommand(i ? ST7735_INVON : ST7735_INVOFF);
|
|
}
|
|
|
|
|
|
////////// stuff not actively being used, but kept for posterity
|
|
/*
|
|
|
|
uint8_t Adafruit_ST7735::spiread(void) {
|
|
uint8_t r = 0;
|
|
if (_sid > 0) {
|
|
r = shiftIn(_sid, _sclk, MSBFIRST);
|
|
} else {
|
|
//SID_DDR &= ~_BV(SID);
|
|
//int8_t i;
|
|
//for (i=7; i>=0; i--) {
|
|
// SCLK_PORT &= ~_BV(SCLK);
|
|
// r <<= 1;
|
|
// r |= (SID_PIN >> SID) & 0x1;
|
|
// SCLK_PORT |= _BV(SCLK);
|
|
//}
|
|
//SID_DDR |= _BV(SID);
|
|
|
|
}
|
|
return r;
|
|
}
|
|
|
|
|
|
void Adafruit_ST7735::dummyclock(void) {
|
|
|
|
if (_sid > 0) {
|
|
digitalWrite(_sclk, LOW);
|
|
digitalWrite(_sclk, HIGH);
|
|
} else {
|
|
// SCLK_PORT &= ~_BV(SCLK);
|
|
//SCLK_PORT |= _BV(SCLK);
|
|
}
|
|
}
|
|
uint8_t Adafruit_ST7735::readdata(void) {
|
|
*portOutputRegister(rsport) |= rspin;
|
|
|
|
*portOutputRegister(csport) &= ~ cspin;
|
|
|
|
uint8_t r = spiread();
|
|
|
|
*portOutputRegister(csport) |= cspin;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
uint8_t Adafruit_ST7735::readcommand8(uint8_t c) {
|
|
digitalWrite(_rs, LOW);
|
|
|
|
*portOutputRegister(csport) &= ~ cspin;
|
|
|
|
spiwrite(c);
|
|
|
|
digitalWrite(_rs, HIGH);
|
|
pinMode(_sid, INPUT); // input!
|
|
digitalWrite(_sid, LOW); // low
|
|
spiread();
|
|
uint8_t r = spiread();
|
|
|
|
|
|
*portOutputRegister(csport) |= cspin;
|
|
|
|
|
|
pinMode(_sid, OUTPUT); // back to output
|
|
return r;
|
|
}
|
|
|
|
|
|
uint16_t Adafruit_ST7735::readcommand16(uint8_t c) {
|
|
digitalWrite(_rs, LOW);
|
|
if (_cs)
|
|
digitalWrite(_cs, LOW);
|
|
|
|
spiwrite(c);
|
|
pinMode(_sid, INPUT); // input!
|
|
uint16_t r = spiread();
|
|
r <<= 8;
|
|
r |= spiread();
|
|
if (_cs)
|
|
digitalWrite(_cs, HIGH);
|
|
|
|
pinMode(_sid, OUTPUT); // back to output
|
|
return r;
|
|
}
|
|
|
|
uint32_t Adafruit_ST7735::readcommand32(uint8_t c) {
|
|
digitalWrite(_rs, LOW);
|
|
if (_cs)
|
|
digitalWrite(_cs, LOW);
|
|
spiwrite(c);
|
|
pinMode(_sid, INPUT); // input!
|
|
|
|
dummyclock();
|
|
dummyclock();
|
|
|
|
uint32_t r = spiread();
|
|
r <<= 8;
|
|
r |= spiread();
|
|
r <<= 8;
|
|
r |= spiread();
|
|
r <<= 8;
|
|
r |= spiread();
|
|
if (_cs)
|
|
digitalWrite(_cs, HIGH);
|
|
|
|
pinMode(_sid, OUTPUT); // back to output
|
|
return r;
|
|
}
|
|
|
|
*/
|