Skip to content

Commit d4ea436

Browse files
committed
added generic SPI TFT wrapper
1 parent b8ca7d1 commit d4ea436

File tree

3 files changed

+530
-0
lines changed

3 files changed

+530
-0
lines changed

Adafruit_SPITFT.cpp

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
/***************************************************
2+
This is our library for generic SPI TFT Displays with
3+
address windows and 16 bit color (e.g. ILI9341, HX8357D, ST7735...)
4+
5+
Check out the links above for our tutorials and wiring diagrams
6+
These displays use SPI to communicate, 4 or 5 pins are required to
7+
interface (RST is optional)
8+
Adafruit invests time and resources providing this open source code,
9+
please support Adafruit and open-source hardware by purchasing
10+
products from Adafruit!
11+
12+
Written by Limor Fried/Ladyada for Adafruit Industries.
13+
MIT license, all text above must be included in any redistribution
14+
****************************************************/
15+
16+
17+
#include "Adafruit_SPITFT.h"
18+
#ifndef ARDUINO_STM32_FEATHER
19+
#include "pins_arduino.h"
20+
#ifndef RASPI
21+
#include "wiring_private.h"
22+
#endif
23+
#endif
24+
#include <limits.h>
25+
26+
#include "Adafruit_SPITFT_Macros.h"
27+
28+
29+
30+
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
31+
uint16_t Adafruit_SPITFT::color565(uint8_t r, uint8_t g, uint8_t b) {
32+
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
33+
}
34+
35+
Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
36+
int8_t cs, int8_t dc, int8_t mosi,
37+
int8_t sclk, int8_t rst, int8_t miso)
38+
: Adafruit_GFX(w, h) {
39+
_cs = cs;
40+
_dc = dc;
41+
_rst = rst;
42+
_sclk = sclk;
43+
_mosi = mosi;
44+
_miso = miso;
45+
_freq = 0;
46+
#ifdef USE_FAST_PINIO
47+
csport = portOutputRegister(digitalPinToPort(_cs));
48+
cspinmask = digitalPinToBitMask(_cs);
49+
dcport = portOutputRegister(digitalPinToPort(_dc));
50+
dcpinmask = digitalPinToBitMask(_dc);
51+
clkport = portOutputRegister(digitalPinToPort(_sclk));
52+
clkpinmask = digitalPinToBitMask(_sclk);
53+
mosiport = portOutputRegister(digitalPinToPort(_mosi));
54+
mosipinmask = digitalPinToBitMask(_mosi);
55+
if(miso >= 0){
56+
misoport = portInputRegister(digitalPinToPort(_miso));
57+
misopinmask = digitalPinToBitMask(_miso);
58+
} else {
59+
misoport = 0;
60+
misopinmask = 0;
61+
}
62+
#endif
63+
}
64+
65+
Adafruit_SPITFT::Adafruit_SPITFT(uint16_t w, uint16_t h,
66+
int8_t cs, int8_t dc, int8_t rst)
67+
: Adafruit_GFX(w, h) {
68+
_cs = cs;
69+
_dc = dc;
70+
_rst = rst;
71+
_sclk = -1;
72+
_mosi = -1;
73+
_miso = -1;
74+
_freq = 0;
75+
#ifdef USE_FAST_PINIO
76+
csport = portOutputRegister(digitalPinToPort(_cs));
77+
cspinmask = digitalPinToBitMask(_cs);
78+
dcport = portOutputRegister(digitalPinToPort(_dc));
79+
dcpinmask = digitalPinToBitMask(_dc);
80+
clkport = 0;
81+
clkpinmask = 0;
82+
mosiport = 0;
83+
mosipinmask = 0;
84+
misoport = 0;
85+
misopinmask = 0;
86+
#endif
87+
}
88+
89+
90+
void Adafruit_SPITFT::initSPI(uint32_t freq)
91+
{
92+
_freq = freq;
93+
94+
// Control Pins
95+
pinMode(_dc, OUTPUT);
96+
digitalWrite(_dc, LOW);
97+
pinMode(_cs, OUTPUT);
98+
digitalWrite(_cs, HIGH);
99+
100+
// Software SPI
101+
if(_sclk >= 0){
102+
pinMode(_mosi, OUTPUT);
103+
digitalWrite(_mosi, LOW);
104+
pinMode(_sclk, OUTPUT);
105+
digitalWrite(_sclk, HIGH);
106+
if(_miso >= 0){
107+
pinMode(_miso, INPUT);
108+
}
109+
}
110+
111+
// Hardware SPI
112+
SPI_BEGIN();
113+
114+
// toggle RST low to reset
115+
if (_rst >= 0) {
116+
pinMode(_rst, OUTPUT);
117+
digitalWrite(_rst, HIGH);
118+
delay(100);
119+
digitalWrite(_rst, LOW);
120+
delay(100);
121+
digitalWrite(_rst, HIGH);
122+
delay(200);
123+
}
124+
}
125+
126+
uint8_t Adafruit_SPITFT::spiRead() {
127+
if(_sclk < 0){
128+
return HSPI_READ();
129+
}
130+
if(_miso < 0){
131+
return 0;
132+
}
133+
uint8_t r = 0;
134+
for (uint8_t i=0; i<8; i++) {
135+
SSPI_SCK_LOW();
136+
SSPI_SCK_HIGH();
137+
r <<= 1;
138+
if (SSPI_MISO_READ()){
139+
r |= 0x1;
140+
}
141+
}
142+
return r;
143+
}
144+
145+
void Adafruit_SPITFT::spiWrite(uint8_t b) {
146+
if(_sclk < 0){
147+
HSPI_WRITE(b);
148+
return;
149+
}
150+
for(uint8_t bit = 0x80; bit; bit >>= 1){
151+
if((b) & bit){
152+
SSPI_MOSI_HIGH();
153+
} else {
154+
SSPI_MOSI_LOW();
155+
}
156+
SSPI_SCK_LOW();
157+
SSPI_SCK_HIGH();
158+
}
159+
}
160+
161+
162+
/*
163+
* Transaction API
164+
* */
165+
166+
void Adafruit_SPITFT::startWrite(void){
167+
SPI_BEGIN_TRANSACTION();
168+
SPI_CS_LOW();
169+
}
170+
171+
void Adafruit_SPITFT::endWrite(void){
172+
SPI_CS_HIGH();
173+
SPI_END_TRANSACTION();
174+
}
175+
176+
void Adafruit_SPITFT::writeCommand(uint8_t cmd){
177+
SPI_DC_LOW();
178+
spiWrite(cmd);
179+
SPI_DC_HIGH();
180+
}
181+
182+
void Adafruit_SPITFT::pushColor(uint16_t color) {
183+
startWrite();
184+
SPI_WRITE16(color);
185+
endWrite();
186+
}
187+
188+
189+
void Adafruit_SPITFT::writePixel(uint16_t color){
190+
SPI_WRITE16(color);
191+
}
192+
193+
void Adafruit_SPITFT::writePixels(uint16_t * colors, uint32_t len){
194+
SPI_WRITE_PIXELS((uint8_t*)colors , len * 2);
195+
}
196+
197+
void Adafruit_SPITFT::writeColor(uint16_t color, uint32_t len){
198+
#ifdef SPI_HAS_WRITE_PIXELS
199+
if(_sclk >= 0){
200+
for (uint32_t t=0; t<len; t++){
201+
writePixel(color);
202+
}
203+
return;
204+
}
205+
static uint16_t temp[SPI_MAX_PIXELS_AT_ONCE];
206+
size_t blen = (len > SPI_MAX_PIXELS_AT_ONCE)?SPI_MAX_PIXELS_AT_ONCE:len;
207+
uint16_t tlen = 0;
208+
209+
for (uint32_t t=0; t<blen; t++){
210+
temp[t] = color;
211+
}
212+
213+
while(len){
214+
tlen = (len>blen)?blen:len;
215+
writePixels(temp, tlen);
216+
len -= tlen;
217+
}
218+
#else
219+
uint8_t hi = color >> 8, lo = color;
220+
if(_sclk < 0){ //AVR Optimization
221+
for (uint32_t t=len; t; t--){
222+
HSPI_WRITE(hi);
223+
HSPI_WRITE(lo);
224+
}
225+
return;
226+
}
227+
for (uint32_t t=len; t; t--){
228+
spiWrite(hi);
229+
spiWrite(lo);
230+
}
231+
#endif
232+
}
233+
234+
void Adafruit_SPITFT::writePixel(int16_t x, int16_t y, uint16_t color) {
235+
if((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) return;
236+
setAddrWindow(x,y,1,1);
237+
writePixel(color);
238+
}
239+
240+
void Adafruit_SPITFT::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
241+
if((x >= _width) || (y >= _height)) return;
242+
int16_t x2 = x + w - 1, y2 = y + h - 1;
243+
if((x2 < 0) || (y2 < 0)) return;
244+
245+
// Clip left/top
246+
if(x < 0) {
247+
x = 0;
248+
w = x2 + 1;
249+
}
250+
if(y < 0) {
251+
y = 0;
252+
h = y2 + 1;
253+
}
254+
255+
// Clip right/bottom
256+
if(x2 >= _width) w = _width - x;
257+
if(y2 >= _height) h = _height - y;
258+
259+
int32_t len = (int32_t)w * h;
260+
setAddrWindow(x, y, w, h);
261+
writeColor(color, len);
262+
}
263+
264+
void Adafruit_SPITFT::writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
265+
writeFillRect(x, y, 1, h, color);
266+
}
267+
268+
void Adafruit_SPITFT::writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
269+
writeFillRect(x, y, w, 1, color);
270+
}
271+
272+
void Adafruit_SPITFT::drawPixel(int16_t x, int16_t y, uint16_t color){
273+
startWrite();
274+
writePixel(x, y, color);
275+
endWrite();
276+
}
277+
278+
void Adafruit_SPITFT::drawFastVLine(int16_t x, int16_t y,
279+
int16_t h, uint16_t color) {
280+
startWrite();
281+
writeFastVLine(x, y, h, color);
282+
endWrite();
283+
}
284+
285+
void Adafruit_SPITFT::drawFastHLine(int16_t x, int16_t y,
286+
int16_t w, uint16_t color) {
287+
startWrite();
288+
writeFastHLine(x, y, w, color);
289+
endWrite();
290+
}
291+
292+
void Adafruit_SPITFT::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
293+
uint16_t color) {
294+
startWrite();
295+
writeFillRect(x,y,w,h,color);
296+
endWrite();
297+
}
298+
299+
// Adapted from https://github.com/PaulStoffregen/ILI9341_t3
300+
// by Marc MERLIN. See examples/pictureEmbed to use this.
301+
// 5/6/2017: function name and arguments have changed for compatibility
302+
// with current GFX library and to avoid naming problems in prior
303+
// implementation. Formerly drawBitmap() with arguments in different order.
304+
void Adafruit_SPITFT::drawRGBBitmap(int16_t x, int16_t y,
305+
uint16_t *pcolors, int16_t w, int16_t h) {
306+
307+
int16_t x2, y2; // Lower-right coord
308+
if(( x >= _width ) || // Off-edge right
309+
( y >= _height) || // " top
310+
((x2 = (x+w-1)) < 0 ) || // " left
311+
((y2 = (y+h-1)) < 0) ) return; // " bottom
312+
313+
int16_t bx1=0, by1=0, // Clipped top-left within bitmap
314+
saveW=w; // Save original bitmap width value
315+
if(x < 0) { // Clip left
316+
w += x;
317+
bx1 = -x;
318+
x = 0;
319+
}
320+
if(y < 0) { // Clip top
321+
h += y;
322+
by1 = -y;
323+
y = 0;
324+
}
325+
if(x2 >= _width ) w = _width - x; // Clip right
326+
if(y2 >= _height) h = _height - y; // Clip bottom
327+
328+
pcolors += by1 * saveW + bx1; // Offset bitmap ptr to clipped top-left
329+
startWrite();
330+
setAddrWindow(x, y, w, h); // Clipped area
331+
while(h--) { // For each (clipped) scanline...
332+
writePixels(pcolors, w); // Push one (clipped) row
333+
pcolors += saveW; // Advance pointer by one full (unclipped) line
334+
}
335+
endWrite();
336+
}

0 commit comments

Comments
 (0)