Tasmota/lib/Adafruit_GFX-1.2.2.07/Adafruit_SPITFT.cpp

337 lines
8.4 KiB
C++

/***************************************************
This is our library for generic SPI TFT Displays with
address windows and 16 bit color (e.g. ILI9341, HX8357D, ST7735...)
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_SPITFT.h"
#ifndef ARDUINO_STM32_FEATHER
#include "pins_arduino.h"
#ifndef RASPI
#include "wiring_private.h"
#endif
#endif
#include <limits.h>
#include "Adafruit_SPITFT_Macros.h"
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
uint16_t Adafruit_SPITFT::color565(uint8_t r, uint8_t g, uint8_t b) {
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
}
Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
int8_t cs, int8_t dc, int8_t mosi,
int8_t sclk, int8_t rst, int8_t miso)
: Adafruit_GFX(w, h) {
_cs = cs;
_dc = dc;
_rst = rst;
_sclk = sclk;
_mosi = mosi;
_miso = miso;
_freq = 0;
#ifdef USE_FAST_PINIO
csport = portOutputRegister(digitalPinToPort(_cs));
cspinmask = digitalPinToBitMask(_cs);
dcport = portOutputRegister(digitalPinToPort(_dc));
dcpinmask = digitalPinToBitMask(_dc);
clkport = portOutputRegister(digitalPinToPort(_sclk));
clkpinmask = digitalPinToBitMask(_sclk);
mosiport = portOutputRegister(digitalPinToPort(_mosi));
mosipinmask = digitalPinToBitMask(_mosi);
if(miso >= 0){
misoport = portInputRegister(digitalPinToPort(_miso));
misopinmask = digitalPinToBitMask(_miso);
} else {
misoport = 0;
misopinmask = 0;
}
#endif
}
Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
int8_t cs, int8_t dc, int8_t rst)
: Adafruit_GFX(w, h) {
_cs = cs;
_dc = dc;
_rst = rst;
_sclk = -1;
_mosi = -1;
_miso = -1;
_freq = 0;
#ifdef USE_FAST_PINIO
csport = portOutputRegister(digitalPinToPort(_cs));
cspinmask = digitalPinToBitMask(_cs);
dcport = portOutputRegister(digitalPinToPort(_dc));
dcpinmask = digitalPinToBitMask(_dc);
clkport = 0;
clkpinmask = 0;
mosiport = 0;
mosipinmask = 0;
misoport = 0;
misopinmask = 0;
#endif
}
void Adafruit_SPITFT::initSPI(uint32_t freq)
{
_freq = freq;
// Control Pins
pinMode(_dc, OUTPUT);
digitalWrite(_dc, LOW);
pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH);
// Software SPI
if(_sclk >= 0){
pinMode(_mosi, OUTPUT);
digitalWrite(_mosi, LOW);
pinMode(_sclk, OUTPUT);
digitalWrite(_sclk, HIGH);
if(_miso >= 0){
pinMode(_miso, INPUT);
}
}
// Hardware SPI
SPI_BEGIN();
// toggle RST low to reset
if (_rst >= 0) {
pinMode(_rst, OUTPUT);
digitalWrite(_rst, HIGH);
delay(100);
digitalWrite(_rst, LOW);
delay(100);
digitalWrite(_rst, HIGH);
delay(200);
}
}
uint8_t Adafruit_SPITFT::spiRead() {
if(_sclk < 0){
return HSPI_READ();
}
if(_miso < 0){
return 0;
}
uint8_t r = 0;
for (uint8_t i=0; i<8; i++) {
SSPI_SCK_LOW();
SSPI_SCK_HIGH();
r <<= 1;
if (SSPI_MISO_READ()){
r |= 0x1;
}
}
return r;
}
void Adafruit_SPITFT::spiWrite(uint8_t b) {
if(_sclk < 0){
HSPI_WRITE(b);
return;
}
for(uint8_t bit = 0x80; bit; bit >>= 1){
if((b) & bit){
SSPI_MOSI_HIGH();
} else {
SSPI_MOSI_LOW();
}
SSPI_SCK_LOW();
SSPI_SCK_HIGH();
}
}
/*
* Transaction API
* */
void Adafruit_SPITFT::startWrite(void){
SPI_BEGIN_TRANSACTION();
SPI_CS_LOW();
}
void Adafruit_SPITFT::endWrite(void){
SPI_CS_HIGH();
SPI_END_TRANSACTION();
}
void Adafruit_SPITFT::writeCommand(uint8_t cmd){
SPI_DC_LOW();
spiWrite(cmd);
SPI_DC_HIGH();
}
void Adafruit_SPITFT::pushColor(uint16_t color) {
startWrite();
SPI_WRITE16(color);
endWrite();
}
void Adafruit_SPITFT::writePixel(uint16_t color){
SPI_WRITE16(color);
}
void Adafruit_SPITFT::writePixels(uint16_t * colors, uint32_t len){
SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
}
void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len){
#ifdef SPI_HAS_WRITE_PIXELS
if(_sclk >= 0){
for (uint32_t t=0; t<len; t++){
writePixel(color);
}
return;
}
static uint16_t temp[SPI_MAX_PIXELS_AT_ONCE];
size_t blen = (len > SPI_MAX_PIXELS_AT_ONCE)?SPI_MAX_PIXELS_AT_ONCE:len;
uint16_t tlen = 0;
for (uint32_t t=0; t<blen; t++){
temp[t] = color;
}
while(len){
tlen = (len>blen)?blen:len;
writePixels(temp, tlen);
len -= tlen;
}
#else
uint8_t hi = color >> 8, lo = color;
if(_sclk < 0){ //AVR Optimization
for (uint32_t t=len; t; t--){
HSPI_WRITE(hi);
HSPI_WRITE(lo);
}
return;
}
for (uint32_t t=len; t; t--){
spiWrite(hi);
spiWrite(lo);
}
#endif
}
void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
setAddrWindow(x,y,1,1);
writePixel(color);
}
void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
if((x >= _width) || (y >= _height)) return;
int16_t x2 = x + w - 1, y2 = y + h - 1;
if((x2 < 0) || (y2 < 0)) return;
// Clip left/top
if(x < 0) {
x = 0;
w = x2 + 1;
}
if(y < 0) {
y = 0;
h = y2 + 1;
}
// Clip right/bottom
if(x2 >= _width) w = _width - x;
if(y2 >= _height) h = _height - y;
int32_t len = (int32_t)w * h;
setAddrWindow(x, y, w, h);
writeColor(color, len);
}
void Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
writeFillRect(x, y, 1, h, color);
}
void Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
writeFillRect(x, y, w, 1, color);
}
void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color){
startWrite();
writePixel(x, y, color);
endWrite();
}
void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y,
int16_t h, uint16_t color) {
startWrite();
writeFastVLine(x, y, h, color);
endWrite();
}
void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y,
int16_t w, uint16_t color) {
startWrite();
writeFastHLine(x, y, w, color);
endWrite();
}
void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
uint16_t color) {
startWrite();
writeFillRect(x,y,w,h,color);
endWrite();
}
// Adapted from https://github.com/PaulStoffregen/ILI9341_t3
// by Marc MERLIN. See examples/pictureEmbed to use this.
// 5/6/2017: function name and arguments have changed for compatibility
// with current GFX library and to avoid naming problems in prior
// implementation. Formerly drawBitmap() with arguments in different order.
void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
uint16_t *pcolors, int16_t w, int16_t h) {
int16_t x2, y2; // Lower-right coord
if(( x >= _width ) || // Off-edge right
( y >= _height) || // " top
((x2 = (x+w-1)) < 0 ) || // " left
((y2 = (y+h-1)) < 0) ) return; // " bottom
int16_t bx1=0, by1=0, // Clipped top-left within bitmap
saveW=w; // Save original bitmap width value
if(x < 0) { // Clip left
w += x;
bx1 = -x;
x = 0;
}
if(y < 0) { // Clip top
h += y;
by1 = -y;
y = 0;
}
if(x2 >= _width ) w = _width - x; // Clip right
if(y2 >= _height) h = _height - y; // Clip bottom
pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
startWrite();
setAddrWindow(x, y, w, h); // Clipped area
while(h--) { // For each (clipped) scanline...
writePixels(pcolors, w); // Push one (clipped) row
pcolors += saveW; // Advance pointer by one full (unclipped) line
}
endWrite();
}