Many changes!

Works in native SPI with Teensy LC, can use alt pin on Teensy's, fixed
small bugs, works with more CPU, faster with DUE.
This commit is contained in:
sumotoy 2015-06-09 01:24:09 +02:00
parent d86d1629ec
commit de588aabf9
6 changed files with 1094 additions and 701 deletions

View file

@ -4,78 +4,94 @@
#include "wiring_private.h"
#include <SPI.h>
#if defined(SPI_HAS_TRANSACTION)
static SPISettings ILI9163C_SPI;
#endif
//constructors
TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT){
#if defined(__MK20DX128__) || defined(__MK20DX256__)
TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,uint8_t mosi,uint8_t sclk) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT)
{
_cs = cspin;
_rs = dcpin;
_rst = rstpin;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
#else
_sid = _sclk = 0;
#endif
}
_mosi = mosi;
_sclk = sclk;
}
#elif defined(__MKL26Z64__)
TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin,bool useSPI1) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT)
{
_cs = cspin;
_rs = dcpin;
_rst = rstpin;
_useSPI1 = useSPI1;
}
#else
TFT_ILI9163C::TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin) : Adafruit_GFX(_TFTWIDTH,_TFTHEIGHT)
{
_cs = cspin;
_rs = dcpin;
_rst = rstpin;
}
#endif
TFT_ILI9163C::TFT_ILI9163C(uint8_t CS, uint8_t DC) : Adafruit_GFX(_TFTWIDTH, _TFTHEIGHT) {
_cs = CS;
_rs = DC;
_rst = 0;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
#else
_sid = _sclk = 0;
#endif
}
//Arduino Uno, Leonardo, Mega, Teensy 2.0, etc
#ifdef __AVR__
#if defined(__AVR__)
inline void TFT_ILI9163C::spiwrite(uint8_t c){
inline void TFT_ILI9163C::spiwrite(uint8_t c)
{
SPDR = c;
while(!(SPSR & _BV(SPIF)));
}
}
void TFT_ILI9163C::writecommand(uint8_t c){
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
void TFT_ILI9163C::writecommand(uint8_t c)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
*rsport &= ~rspinmask;//low
*csport &= ~cspinmask;//low
spiwrite(c);
*csport |= cspinmask;//hi
#ifdef SPI_HAS_TRANSACTION
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
}
void TFT_ILI9163C::writedata(uint8_t c){
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
void TFT_ILI9163C::writedata(uint8_t c)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
*rsport |= rspinmask;
*csport &= ~cspinmask;
*rsport |= rspinmask;//hi
*csport &= ~cspinmask;//low
spiwrite(c);
*csport |= cspinmask;
#ifdef SPI_HAS_TRANSACTION
*csport |= cspinmask;//hi
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
}
void TFT_ILI9163C::writedata16(uint16_t d){
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
void TFT_ILI9163C::writedata16(uint16_t d)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
*rsport |= rspinmask;
*csport &= ~cspinmask;
*rsport |= rspinmask;//hi
*csport &= ~cspinmask;//low
spiwrite(d >> 8);
spiwrite(d);
*csport |= cspinmask;
#ifdef SPI_HAS_TRANSACTION
*csport |= cspinmask;//hi
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
}
void TFT_ILI9163C::setBitrate(uint32_t n){
void TFT_ILI9163C::setBitrate(uint32_t n)
{
#if !defined (SPI_HAS_TRANSACTION)
if (n >= 8000000) {
SPI.setClockDivider(SPI_CLOCK_DIV2);
@ -87,78 +103,179 @@ void TFT_ILI9163C::setBitrate(uint32_t n){
SPI.setClockDivider(SPI_CLOCK_DIV16);
}
#endif
}
#elif defined(__SAM3X8E__)
// Arduino Due
inline void TFT_ILI9163C::spiwrite(uint8_t c){
}
#elif defined(__SAM3X8E__)// Arduino Due
inline void TFT_ILI9163C::spiwrite(uint8_t c)
{
SPI.transfer(c);
}
}
void TFT_ILI9163C::writecommand(uint8_t c){
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
void TFT_ILI9163C::writecommand(uint8_t c)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
rsport->PIO_CODR |= rspinmask;//LO
csport->PIO_CODR |= cspinmask;//LO
spiwrite(c);
csport->PIO_SODR |= cspinmask;//HI
#ifdef SPI_HAS_TRANSACTION
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
}
void TFT_ILI9163C::writedata(uint8_t c){
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
void TFT_ILI9163C::writedata(uint8_t c)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
rsport->PIO_SODR |= rspinmask;//HI
csport->PIO_CODR |= cspinmask;//LO
spiwrite(c);
csport->PIO_SODR |= cspinmask;//HI
#ifdef SPI_HAS_TRANSACTION
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
}
void TFT_ILI9163C::writedata16(uint16_t d){
#ifdef SPI_HAS_TRANSACTION
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
void TFT_ILI9163C::writedata16(uint16_t d)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
rsport->PIO_SODR |= rspinmask;//HI
csport->PIO_CODR |= cspinmask;//LO
spiwrite(d >> 8);
spiwrite(d);
csport->PIO_SODR |= cspinmask;//HI
#ifdef SPI_HAS_TRANSACTION
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
}
void TFT_ILI9163C::setBitrate(uint32_t n){
#if !defined (SPI_HAS_TRANSACTION)
uint32_t divider=1;
void TFT_ILI9163C::setBitrate(uint32_t n)
{
#if !defined(SPI_HAS_TRANSACTION)
uint32_t divider = 1;
while (divider < 255) {
if (n >= 84000000 / divider) break;
divider = divider - 1;
}
SPI.setClockDivider(divider);
#endif
}
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
//Teensy 3.0 & 3.1
}
#elif defined(__MKL26Z64__)//Teensy LC (preliminary
void TFT_ILI9163C::setBitrate(uint32_t n){
void TFT_ILI9163C::writecommand(uint8_t c)
{
SPI.beginTransaction(ILI9163C_SPI);
digitalWriteFast(_rs,LOW);
digitalWriteFast(_cs,LOW);
if (_useSPI1){
SPI1.transfer(c);
} else {
SPI.transfer(c);
}
digitalWriteFast(_cs,HIGH);
SPI.endTransaction();
}
void TFT_ILI9163C::writedata(uint8_t c)
{
SPI.beginTransaction(ILI9163C_SPI);
digitalWriteFast(_rs,HIGH);
digitalWriteFast(_cs,LOW);
if (_useSPI1){
SPI1.transfer(c);
} else {
SPI.transfer(c);
}
digitalWriteFast(_cs,HIGH);
SPI.endTransaction();
}
void TFT_ILI9163C::writedata16(uint16_t d)
{
SPI.beginTransaction(ILI9163C_SPI);
digitalWriteFast(_rs,HIGH);
digitalWriteFast(_cs,LOW);
if (_useSPI1){
SPI1.transfer16(d);
} else {
SPI.transfer16(d);
}
digitalWriteFast(_cs,HIGH);
SPI.endTransaction();
}
void TFT_ILI9163C::setBitrate(uint32_t n)
{
//nop
}
}
#elif defined(__MK20DX128__) || defined(__MK20DX256__)//Teensy 3.0 & 3.1
void TFT_ILI9163C::setBitrate(uint32_t n)
{
//nop
}
#else
void TFT_ILI9163C::writecommand(uint8_t c)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
digitalWrite(_rs,LOW);
digitalWrite(_cs,LOW);
SPI.transfer(c);
digitalWrite(_cs,HIGH);
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void TFT_ILI9163C::writedata(uint8_t c)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
digitalWrite(_rs,HIGH);
digitalWrite(_cs,LOW);
SPI.transfer(c);
digitalWrite(_cs,HIGH);
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void TFT_ILI9163C::writedata16(uint16_t d)
{
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(ILI9163C_SPI);
#endif
digitalWrite(_rs,HIGH);
digitalWrite(_cs,LOW);
SPI.transfer(d >> 8);
SPI.transfer(d);
digitalWrite(_cs,HIGH);
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void TFT_ILI9163C::setBitrate(uint32_t n)
{
//nop
}
#endif //#if defined(TEENSY3.x)
void TFT_ILI9163C::begin(void) {
void TFT_ILI9163C::begin(void)
{
sleep = 0;
#ifdef __AVR__
#if defined(__AVR__)
pinMode(_rs, OUTPUT);
pinMode(_cs, OUTPUT);
csport = portOutputRegister(digitalPinToPort(_cs));
@ -166,13 +283,14 @@ void TFT_ILI9163C::begin(void) {
cspinmask = digitalPinToBitMask(_cs);
rspinmask = digitalPinToBitMask(_rs);
SPI.begin();
#if !defined (SPI_HAS_TRANSACTION)
#if !defined(SPI_HAS_TRANSACTION)
SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
#else
ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0);
#endif
// toggle RST low to reset; CS low so it'll listen to us
*csport &= ~cspinmask;
*csport &= ~cspinmask;// toggle CS low so it'll listen to us
#elif defined(__SAM3X8E__)
pinMode(_rs, OUTPUT);
pinMode(_cs, OUTPUT);
@ -181,14 +299,34 @@ void TFT_ILI9163C::begin(void) {
cspinmask = digitalPinToBitMask(_cs);
rspinmask = digitalPinToBitMask(_rs);
SPI.begin();
#if !defined (SPI_HAS_TRANSACTION)
SPI.setClockDivider(11); // 8 MHz
#if !defined(SPI_HAS_TRANSACTION)
SPI.setClockDivider(5); // 8 MHz
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
#else
ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0);
#endif
// toggle RST low to reset; CS low so it'll listen to us
csport ->PIO_CODR |= cspinmask; // Set control bits to LOW (idle)
csport ->PIO_CODR |= cspinmask; // toggle CS low so it'll listen to us
#elif defined(__MKL26Z64__)//Teensy LC (preliminary)
pinMode(_rs, OUTPUT);
pinMode(_cs, OUTPUT);
if (_useSPI1){
ILI9163C_SPI = SPISettings(12000000, MSBFIRST, SPI_MODE0);
SPI1.begin();
} else {
ILI9163C_SPI = SPISettings(24000000, MSBFIRST, SPI_MODE0);
SPI.begin();
}
digitalWriteFast(_cs, LOW);
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
ILI9163C_SPI = SPISettings(30000000, MSBFIRST, SPI_MODE0);
if ((_mosi == 11 || _mosi == 7) && (_sclk == 13 || _sclk == 14)) {
SPI.setMOSI(_mosi);
SPI.setSCK(_sclk);
} else {
return;
}
SPI.begin();
if (SPI.pinIsChipSelect(_cs, _rs)) {
pcs_data = SPI.setCS(_cs);
@ -198,8 +336,20 @@ void TFT_ILI9163C::begin(void) {
pcs_command = 0;
return;
}
#else//all the rest of possible boards
pinMode(_rs, OUTPUT);
pinMode(_cs, OUTPUT);
SPI.begin();
#if !defined(SPI_HAS_TRANSACTION)
SPI.setClockDivider(4);
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
#else
ILI9163C_SPI = SPISettings(8000000, MSBFIRST, SPI_MODE0);
#endif
digitalWrite(_cs, LOW);
#endif
if (_rst != 0) {
if (_rst != 255) {
pinMode(_rst, OUTPUT);
digitalWrite(_rst, HIGH);
delay(500);
@ -238,38 +388,28 @@ void TFT_ILI9163C::begin(void) {
void TFT_ILI9163C::chipInit() {
uint8_t i;
#if defined(__GAMMASET1)
const uint8_t pGammaSet[15]= {0x36,0x29,0x12,0x22,0x1C,0x15,0x42,0xB7,0x2F,0x13,0x12,0x0A,0x11,0x0B,0x06};
const uint8_t nGammaSet[15]= {0x09,0x16,0x2D,0x0D,0x13,0x15,0x40,0x48,0x53,0x0C,0x1D,0x25,0x2E,0x34,0x39};
#elif defined(__GAMMASET2)
const uint8_t pGammaSet[15]= {0x3F,0x21,0x12,0x22,0x1C,0x15,0x42,0xB7,0x2F,0x13,0x02,0x0A,0x01,0x00,0x00};
const uint8_t nGammaSet[15]= {0x09,0x18,0x2D,0x0D,0x13,0x15,0x40,0x48,0x53,0x0C,0x1D,0x25,0x2E,0x24,0x29};
#elif defined(__GAMMASET3)
const uint8_t pGammaSet[15]= {0x3F,0x26,0x23,0x30,0x28,0x10,0x55,0xB7,0x40,0x19,0x10,0x1E,0x02,0x01,0x00};
//&const uint8_t nGammaSet[15]= {0x00,0x19,0x1C,0x0F,0x14,0x0F,0x2A,0x48,0x3F,0x06,0x1D,0x21,0x3D,0x3F,0x3F};
const uint8_t nGammaSet[15]= {0x09,0x18,0x2D,0x0D,0x13,0x15,0x40,0x48,0x53,0x0C,0x1D,0x25,0x2E,0x24,0x29};
#else
const uint8_t pGammaSet[15]= {0x3F,0x25,0x1C,0x1E,0x20,0x12,0x2A,0x90,0x24,0x11,0x00,0x00,0x00,0x00,0x00};
const uint8_t nGammaSet[15]= {0x20,0x20,0x20,0x20,0x05,0x15,0x00,0xA7,0x3D,0x18,0x25,0x2A,0x2B,0x2B,0x3A};
#endif
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_cont(CMD_SWRESET);//software reset
delay(500);
writecommand_cont(CMD_SLPOUT);//exit sleep
delay(5);
writecommand_cont(CMD_PIXFMT);//Set Color Format 16bit
writedata8_cont(0x05);
delay(5);
writecommand_cont(CMD_GAMMASET);//default gamma curve 3
writedata8_cont(0x08);//0x04
delay(1);
writecommand_cont(CMD_GAMRSEL);//Enable Gamma adj
writedata8_cont(0x01);
delay(1);
writecommand_cont(CMD_NORML);
writecommand_cont(CMD_NORML);
writecommand_cont(CMD_DFUNCTR);
writedata8_cont(0b11111111);//
@ -279,6 +419,7 @@ void TFT_ILI9163C::chipInit() {
for (i=0;i<15;i++){
writedata8_cont(pGammaSet[i]);
}
writecommand_cont(CMD_NGAMMAC);//Negative Gamma Correction Setting
for (i=0;i<15;i++){
writedata8_cont(nGammaSet[i]);
@ -324,29 +465,39 @@ void TFT_ILI9163C::chipInit() {
writedata16_cont(_GRAMHEIGH - __OFFSET);
writedata16_last(0);
endProc();
SPI.endTransaction();
colorSpace(_colorspaceData);
setRotation(0);
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_cont(CMD_DISPON);//display ON
delay(1);
writecommand_last(CMD_RAMWR);//Memory Write
SPI.endTransaction();
delay(1);
#else
writecommand(CMD_SWRESET);//software reset
delay(500);
writecommand(CMD_SLPOUT);//exit sleep
delay(5);
writecommand(CMD_PIXFMT);//Set Color Format 16bit
writedata(0x05);
delay(5);
writecommand(CMD_GAMMASET);//default gamma curve 3
writedata(0x04);//0x04
delay(1);
writecommand(CMD_GAMRSEL);//Enable Gamma adj
writedata(0x01);
delay(1);
writecommand(CMD_NORML);
writecommand(CMD_DFUNCTR);
@ -357,6 +508,7 @@ void TFT_ILI9163C::chipInit() {
for (i=0;i<15;i++){
writedata(pGammaSet[i]);
}
writecommand(CMD_NGAMMAC);//Negative Gamma Correction Setting
for (i=0;i<15;i++){
writedata(nGammaSet[i]);
@ -366,20 +518,25 @@ void TFT_ILI9163C::chipInit() {
writedata(0x08);//0x0C//0x08
writedata(0x02);//0x14//0x08
delay(1);
writecommand(CMD_DINVCTR);//display inversion
writedata(0x07);
delay(1);
writecommand(CMD_PWCTR1);//Set VRH1[4:0] & VC[2:0] for VCI1 & GVDD
writedata(0x0A);//4.30 - 0x0A
writedata(0x02);//0x05
delay(1);
writecommand(CMD_PWCTR2);//Set BT[2:0] for AVDD & VCL & VGH & VGL
writedata(0x02);
delay(1);
writecommand(CMD_VCOMCTR1);//Set VMH[6:0] & VML[6:0] for VOMH & VCOML
writedata(0x50);//0x50
writedata(99);//0x5b
delay(1);
writecommand(CMD_VCOMOFFS);
writedata(0);//0x40
delay(1);
@ -396,7 +553,9 @@ void TFT_ILI9163C::chipInit() {
writedata16(__OFFSET);
writedata16(_GRAMHEIGH - __OFFSET);
writedata16(0);
colorSpace(_colorspaceData);
setRotation(0);
writecommand(CMD_DISPON);//display ON
delay(1);
@ -422,7 +581,7 @@ void TFT_ILI9163C::colorSpace(uint8_t cspace) {
void TFT_ILI9163C::invertDisplay(boolean i) {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(i ? CMD_DINVON : CMD_DINVOF);
SPI.endTransaction();
#else
@ -433,17 +592,17 @@ void TFT_ILI9163C::invertDisplay(boolean i) {
void TFT_ILI9163C::display(boolean onOff) {
if (onOff){
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(CMD_DISPON);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_DISPON);
#endif
} else {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(CMD_DISPOFF);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_DISPOFF);
#endif
@ -453,17 +612,17 @@ void TFT_ILI9163C::display(boolean onOff) {
void TFT_ILI9163C::idleMode(boolean onOff) {
if (onOff){
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(CMD_IDLEON);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_IDLEON);
#endif
} else {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(CMD_IDLEOF);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_IDLEOF);
#endif
@ -475,9 +634,9 @@ void TFT_ILI9163C::sleepMode(boolean mode) {
if (sleep == 1) return;//already sleeping
sleep = 1;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(CMD_SLPIN);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_SLPIN);
#endif
@ -486,9 +645,9 @@ void TFT_ILI9163C::sleepMode(boolean mode) {
if (sleep == 0) return; //Already awake
sleep = 0;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_last(CMD_SLPOUT);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_SLPOUT);
#endif
@ -501,12 +660,12 @@ void TFT_ILI9163C::defineScrollArea(uint16_t tfa, uint16_t bfa){
int16_t vsa = _GRAMHEIGH - tfa - bfa;
if (vsa >= 0) {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_cont(CMD_VSCLLDEF);
writedata16_cont(tfa);
writedata16_cont(vsa);
writedata16_last(bfa);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_VSCLLDEF);
writedata16(tfa);
@ -519,10 +678,10 @@ void TFT_ILI9163C::defineScrollArea(uint16_t tfa, uint16_t bfa){
void TFT_ILI9163C::scroll(uint16_t adrs) {
if (adrs <= _GRAMHEIGH) {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_cont(CMD_VSSTADRS);
writedata16_last(adrs + __OFFSET);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_VSSTADRS);
writedata16(adrs + __OFFSET);
@ -535,16 +694,14 @@ void TFT_ILI9163C::scroll(uint16_t adrs) {
void TFT_ILI9163C::clearScreen(uint16_t color) {
int px;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
//writecommand_cont(CMD_RAMWR);
SPI.beginTransaction(ILI9163C_SPI);
_setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);
for (px = 0;px < _GRAMSIZE; px++){
writedata16_cont(color);
}
writecommand_last(CMD_NOP);
endProc();
SPI.endTransaction();
#else
//writecommand(CMD_RAMWR);
setAddr(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//go home
for (px = 0;px < _GRAMSIZE; px++){
writedata16(color);
@ -568,16 +725,16 @@ void TFT_ILI9163C::pushData(uint16_t color) {
void TFT_ILI9163C::endPushData() {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
writecommand_last(CMD_NOP);
endProc();
SPI.endTransaction();
#endif
}
void TFT_ILI9163C::pushColor(uint16_t color) {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writedata16_last(color);
endProc();
SPI.endTransaction();
#else
writedata16(color);
#endif
@ -585,7 +742,7 @@ void TFT_ILI9163C::pushColor(uint16_t color) {
void TFT_ILI9163C::writeScreen24(const uint32_t *bitmap,uint16_t size) {
uint16_t color;
int px;
uint16_t px;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
writecommand_cont(CMD_RAMWR);
for (px = 0;px < size; px++){//16384
@ -593,7 +750,7 @@ void TFT_ILI9163C::writeScreen24(const uint32_t *bitmap,uint16_t size) {
writedata16_cont(color);
}
_setAddrWindow(0x00,0x00,_GRAMWIDTH,_GRAMHEIGH);//home
endProc();
SPI.endTransaction();
#else
writecommand(CMD_RAMWR);
for (px = 0;px < size; px++){
@ -627,7 +784,7 @@ void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) {
setAddr(x,y,x+1,y+1);
#if defined(__MK20DX128__) || defined(__MK20DX256__)
writedata16_last(color);
endProc();
SPI.endTransaction();
#else
writedata16(color);
#endif
@ -635,13 +792,6 @@ void TFT_ILI9163C::drawPixel(int16_t x, int16_t y, uint16_t color) {
void TFT_ILI9163C::endProc(void){
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.endTransaction();
#endif
}
void TFT_ILI9163C::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
// Rudimentary clipping
if (boundaryCheck(x,y)) return;
@ -658,7 +808,9 @@ void TFT_ILI9163C::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color
writedata16(color);
#endif
}
endProc();
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
bool TFT_ILI9163C::boundaryCheck(int16_t x,int16_t y){
@ -682,7 +834,9 @@ void TFT_ILI9163C::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color
writedata16(color);
#endif
}
endProc();
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
void TFT_ILI9163C::fillScreen(uint16_t color) {
@ -707,7 +861,9 @@ void TFT_ILI9163C::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t
writedata16_last(color);
#endif
}
endProc();
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
#if defined(__MK20DX128__) || defined(__MK20DX256__)
@ -753,7 +909,8 @@ void TFT_ILI9163C::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint1
ystep = -1;
}
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
int16_t xbegin = x0;
if (steep) {
for (; x0<=x1; x0++) {
@ -798,7 +955,7 @@ void TFT_ILI9163C::drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint1
}
void TFT_ILI9163C::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
HLine(x, y, w, color);
HLine(x, y+h-1, w, color);
VLine(x, y, h, color);
@ -812,7 +969,7 @@ void TFT_ILI9163C::drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t
void TFT_ILI9163C::setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
_setAddrWindow(x0,y0,x1,y1);
#else
setAddrWindow(x0,y0,x1,y1);
@ -821,7 +978,7 @@ void TFT_ILI9163C::setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1){
void TFT_ILI9163C::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
_setAddrWindow(x0,y0,x1,y1);
SPI.endTransaction();
#else
@ -894,10 +1051,10 @@ void TFT_ILI9163C::setRotation(uint8_t m) {
}
colorSpace(_colorspaceData);
#if defined(__MK20DX128__) || defined(__MK20DX256__)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
SPI.beginTransaction(ILI9163C_SPI);
writecommand_cont(CMD_MADCTL);
writedata8_last(_Mactrl_Data);
endProc();
SPI.endTransaction();
#else
writecommand(CMD_MADCTL);
writedata(_Mactrl_Data);

View file

@ -80,6 +80,8 @@
0.7: Init correction.Clear Screen fix v3 (last time?)
0.75: SPI transactions for arduino's (beta)
0.8: Compatiblke with IDE 1.0.6 (teensyduino 1.20) and IDE 1.6.x (teensyduino 1.21b)
0.9: Many changes! Now works with more CPU's, alternative pins for Teensy and Teensy LC
Works (in standard SPI) with Teensy LC.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BugList of the current version:
@ -105,154 +107,47 @@ Done!
#ifndef _TFT_ILI9163CLIB_H_
#define _TFT_ILI9163CLIB_H_
//defined(__MKL26Z64__)
#include "Arduino.h"
#include "Print.h"
#include <Adafruit_GFX.h>
//DID YOU HAVE A RED PCB, BLACk PCB or WHAT DISPLAY TYPE???????????? ---> SELECT HERE <----
#define __144_RED_PCB__//128x128
//#define __144_BLACK_PCB__//128x128
//#define __22_RED_PCB__//240x320
//---------------------------------------
#include "_settings/TFT_ILI9163C_settings.h"
#if defined(__SAM3X8E__)
#if !defined(_ADAFRUIT_GFX_VARIANT)
#ifdef __AVR__
#include <avr/pgmspace.h>
#elif defined(__SAM3X8E__)
#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;
#define SPICLOCK 8000000
#endif
#ifdef __AVR__
#include <avr/pgmspace.h>
#define SPICLOCK 8000000
#endif
#if defined(__MK20DX128__) || defined(__MK20DX256__)
#define SPICLOCK 30000000
#endif
#endif
#if defined(__144_RED_PCB__)
/*
This display:
http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI-Color-TFT-LCD-Display-Module-/271422122271
This particular display has a design error! The controller has 3 pins to configure to constrain
the memory and resolution to a fixed dimension (in that case 128x128) but they leaved those pins
configured for 128x160 so there was several pixel memory addressing problems.
I solved by setup several parameters that dinamically fix the resolution as needed so below
the parameters for this diplay. If you have a strain or a correct display (can happen with chinese)
you can copy those parameters and create setup for different displays.
*/
#define _TFTWIDTH 128//the REAL W resolution of the TFT
#define _TFTHEIGHT 128//the REAL H resolution of the TFT
#define _GRAMWIDTH 128
#define _GRAMHEIGH 160//160
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH//*see note 1
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET3 //uncomment for another gamma
#define __OFFSET 32//*see note 2
//Tested!
#elif defined (__144_BLACK_PCB__)
#define _TFTWIDTH 128//the REAL W resolution of the TFT
#define _TFTHEIGHT 128//the REAL H resolution of the TFT
#define _GRAMWIDTH 128
#define _GRAMHEIGH 128
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH//*see note 1
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET1 //uncomment for another gamma
#define __OFFSET 0
//not tested
#elif defined (__22_RED_PCB__)
/*
Like this one:
http://www.ebay.it/itm/2-2-Serial-SPI-TFT-LCD-Display-Module-240x320-Chip-ILI9340C-PCB-Adapter-SD-Card-/281304733556
Not tested!
*/
#define _TFTWIDTH 240//the REAL W resolution of the TFT
#define _TFTHEIGHT 320//the REAL H resolution of the TFT
#define _GRAMWIDTH 240
#define _GRAMHEIGH 320
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET1 //uncomment for another gamma
#define __OFFSET 0
#else
#define _TFTWIDTH 128//128
#define _TFTHEIGHT 160//160
#define _GRAMWIDTH 128
#define _GRAMHEIGH 160
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET1
#define __OFFSET 0
#endif
/*
Note 1: The __144_RED_PCB__ display has hardware addressing of 128 x 160
but the tft resolution it's 128 x 128 so the dram should be set correctly
Note 2: This is the offset between image in RAM and TFT. In that case 160 - 128 = 32;
*/
//--------- Keep out hands from here!-------------
#define BLACK 0x0000
#define WHITE 0xFFFF
//ILI9163C registers-----------------------
#define CMD_NOP 0x00//Non operation
#define CMD_SWRESET 0x01//Soft Reset
#define CMD_SLPIN 0x10//Sleep ON
#define CMD_SLPOUT 0x11//Sleep OFF
#define CMD_PTLON 0x12//Partial Mode ON
#define CMD_NORML 0x13//Normal Display ON
#define CMD_DINVOF 0x20//Display Inversion OFF
#define CMD_DINVON 0x21//Display Inversion ON
#define CMD_GAMMASET 0x26//Gamma Set (0x01[1],0x02[2],0x04[3],0x08[4])
#define CMD_DISPOFF 0x28//Display OFF
#define CMD_DISPON 0x29//Display ON
#define CMD_IDLEON 0x39//Idle Mode ON
#define CMD_IDLEOF 0x38//Idle Mode OFF
#define CMD_CLMADRS 0x2A//Column Address Set
#define CMD_PGEADRS 0x2B//Page Address Set
#include "_settings/TFT_ILI9163C_registers.h"
#define CMD_RAMWR 0x2C//Memory Write
#define CMD_RAMRD 0x2E//Memory Read
#define CMD_CLRSPACE 0x2D//Color Space : 4K/65K/262K
#define CMD_PARTAREA 0x30//Partial Area
#define CMD_VSCLLDEF 0x33//Vertical Scroll Definition
#define CMD_TEFXLON 0x35//Tearing Effect Line ON
#define CMD_TEFXLOF 0x34//Tearing Effect Line OFF
#define CMD_MADCTL 0x36//Memory Access Control
#define CMD_VSSTADRS 0x37//Vertical Scrolling Start address
#define CMD_PIXFMT 0x3A//Interface Pixel Format
#define CMD_FRMCTR1 0xB1//Frame Rate Control (In normal mode/Full colors)
#define CMD_FRMCTR2 0xB2//Frame Rate Control(In Idle mode/8-colors)
#define CMD_FRMCTR3 0xB3//Frame Rate Control(In Partial mode/full colors)
#define CMD_DINVCTR 0xB4//Display Inversion Control
#define CMD_RGBBLK 0xB5//RGB Interface Blanking Porch setting
#define CMD_DFUNCTR 0xB6//Display Fuction set 5
#define CMD_SDRVDIR 0xB7//Source Driver Direction Control
#define CMD_GDRVDIR 0xB8//Gate Driver Direction Control
#define CMD_PWCTR1 0xC0//Power_Control1
#define CMD_PWCTR2 0xC1//Power_Control2
#define CMD_PWCTR3 0xC2//Power_Control3
#define CMD_PWCTR4 0xC3//Power_Control4
#define CMD_PWCTR5 0xC4//Power_Control5
#define CMD_VCOMCTR1 0xC5//VCOM_Control 1
#define CMD_VCOMCTR2 0xC6//VCOM_Control 2
#define CMD_VCOMOFFS 0xC7//VCOM Offset Control
#define CMD_PGAMMAC 0xE0//Positive Gamma Correction Setting
#define CMD_NGAMMAC 0xE1//Negative Gamma Correction Setting
#define CMD_GAMRSEL 0xF2//GAM_R_SEL
class TFT_ILI9163C : public Adafruit_GFX {
public:
TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin);
TFT_ILI9163C(uint8_t CS, uint8_t DC);//connect rst pin to VDD
#if defined(__MK20DX128__) || defined(__MK20DX256__)
TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin=255,uint8_t mosi=11,uint8_t sclk=13);
#elif defined(__MKL26Z64__)
TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin=255,bool useSPI1=false);
#else
TFT_ILI9163C(uint8_t cspin,uint8_t dcpin,uint8_t rstpin=255);
#endif
//TFT_ILI9163C(uint8_t CS, uint8_t DC);//connect rst pin to VDD
void begin(void),
setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1),//graphic Addressing
@ -283,45 +178,68 @@ class TFT_ILI9163C : public Adafruit_GFX {
//convert 24bit color into packet 16 bit one (credits for this are all mine)
inline uint16_t Color24To565(int32_t color_) { return ((((color_ >> 16) & 0xFF) / 8) << 11) | ((((color_ >> 8) & 0xFF) / 4) << 5) | (((color_) & 0xFF) / 8);}
void setBitrate(uint32_t n);
private:
uint8_t _Mactrl_Data;//container for the memory access control data
protected:
volatile uint8_t _Mactrl_Data;//container for the memory access control data
uint8_t _colorspaceData;
void colorSpace(uint8_t cspace);
void setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
void endProc(void);
uint8_t sleep;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
//
#else
void writecommand(uint8_t c);
void writedata(uint8_t d);
void writedata16(uint16_t d);
/* inline void startTransaction(void){
//__attribute__((always_inline)) {
#if defined(SPI_HAS_TRANSACTION)
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
#endif
void chipInit();
bool boundaryCheck(int16_t x,int16_t y);
void homeAddress();
#if defined(__AVR__)
*csport &= ~cspinmask;//low
#elif defined(__SAM3X8E__)
csport->PIO_CODR |= cspinmask;//LO
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
//nop
#elif defined(__MKL26Z64__)
digitalWriteFast(_cs,LOW);
#else
digitalWrite(_cs,LOW);
#endif
} */
/* inline void stopTransaction(void){
//__attribute__((always_inline)) {
#if defined(__AVR__)
*csport |= cspinmask;//hi
#elif defined(__SAM3X8E__)
csport->PIO_SODR |= cspinmask;//HI
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
//nop
#elif defined(__MKL26Z64__)
digitalWriteFast(_cs,HIGH);
#else
digitalWrite(_cs,HIGH);
#endif
#if defined(SPI_HAS_TRANSACTION)
SPI.endTransaction();
#endif
}
*/
#if defined(__AVR__)
void spiwrite(uint8_t);
volatile uint8_t *dataport, *clkport, *csport, *rsport;
uint8_t _cs,_rs,_sid,_sclk,_rst;
uint8_t _cs,_rs,_rst;
uint8_t datapinmask, clkpinmask, cspinmask, rspinmask;
#endif // #ifdef __AVR__
#if defined(__SAM3X8E__)
#elif defined(__SAM3X8E__)
void spiwrite(uint8_t);
Pio *dataport, *clkport, *csport, *rsport;
uint8_t _cs,_rs,_sid,_sclk,_rst;
uint8_t _cs,_rs,_rst;
uint32_t datapinmask, clkpinmask, cspinmask, rspinmask;
#endif // #if defined(__SAM3X8E__)
#if defined(__MK20DX128__) || defined(__MK20DX256__)
//Here's Paul Stoffregen magic in action...
#elif defined(__MKL26Z64__)
uint8_t _cs,_rs,_rst;
bool _useSPI1;
#elif defined(__MK20DX128__) || defined(__MK20DX256__)
uint8_t _cs, _rs, _rst;
uint8_t pcs_data, pcs_command;
uint8_t _miso, _mosi, _sclk;
void _setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);//graphic Addressing for Teensy
//Here's Paul Stoffregen magic in action...
void waitFifoNotFull(void) {
uint32_t sr;
uint32_t tmp __attribute__((unused));
@ -341,14 +259,17 @@ class TFT_ILI9163C : public Adafruit_GFX {
do {
#if ARDUINO >= 160
sr = KINETISK_SPI0.SR;
if (sr & 0xF0) tmp = KINETISK_SPI0.POPR; // drain RX FIFO
#else
sr = SPI0.SR;
#endif
if (sr & 0xF0) tmp = SPI0_POPR; // drain RX FIFO
#endif
} while ((sr & 0xF0F0) > 0); // wait both RX & TX empty
}
void waitTransmitComplete(void) __attribute__((always_inline)) {
#if !defined(__FORCECOMPAT_SPI)//faster
void waitTransmitComplete(void)
__attribute__((always_inline)) {
uint32_t tmp __attribute__((unused));
#if ARDUINO >= 160
while (!(KINETISK_SPI0.SR & SPI_SR_TCF)) ; // wait until final output done
@ -357,8 +278,38 @@ class TFT_ILI9163C : public Adafruit_GFX {
#endif
tmp = SPI0_POPR; // drain the final RX FIFO word
}
#else
void waitTransmitComplete(uint32_t mcr)
__attribute__((always_inline)) {
uint32_t tmp __attribute__((unused));
#if ARDUINO >= 160
while (1) {
uint32_t sr = KINETISK_SPI0.SR;
if (sr & SPI_SR_EOQF) break; // wait for last transmit
if (sr & 0xF0) tmp = KINETISK_SPI0.POPR;
}
KINETISK_SPI0.SR = SPI_SR_EOQF;
SPI0_MCR = mcr;
while (KINETISK_SPI0.SR & 0xF0) {
tmp = KINETISK_SPI0.POPR;
}
#else
while (1) {
uint32_t sr = SPI0.SR;
if (sr & SPI_SR_EOQF) break; // wait for last transmit
if (sr & 0xF0) tmp = SPI0_POPR;
}
SPI0.SR = SPI_SR_EOQF;
SPI0_MCR = mcr;
while (SPI0.SR & 0xF0) {
tmp = SPI0_POPR;
}
#endif
}
#endif
void writecommand_cont(uint8_t c) __attribute__((always_inline)) {
void writecommand_cont(uint8_t c)
__attribute__((always_inline)) {
#if ARDUINO >= 160
KINETISK_SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
#else
@ -367,7 +318,8 @@ class TFT_ILI9163C : public Adafruit_GFX {
waitFifoNotFull();
}
void writedata8_cont(uint8_t c) __attribute__((always_inline)) {
void writedata8_cont(uint8_t c)
__attribute__((always_inline)) {
#if ARDUINO >= 160
KINETISK_SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
#else
@ -376,7 +328,8 @@ class TFT_ILI9163C : public Adafruit_GFX {
waitFifoNotFull();
}
void writedata16_cont(uint16_t d) __attribute__((always_inline)) {
void writedata16_cont(uint16_t d)
__attribute__((always_inline)) {
#if ARDUINO >= 160
KINETISK_SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_CONT;
#else
@ -385,7 +338,9 @@ class TFT_ILI9163C : public Adafruit_GFX {
waitFifoNotFull();
}
void writecommand_last(uint8_t c) __attribute__((always_inline)) {
#if !defined(__FORCECOMPAT_SPI)
void writecommand_last(uint8_t c)
__attribute__((always_inline)) {
waitFifoEmpty();
#if ARDUINO >= 160
KINETISK_SPI0.SR = SPI_SR_TCF;
@ -397,7 +352,9 @@ class TFT_ILI9163C : public Adafruit_GFX {
waitTransmitComplete();
}
void writedata8_last(uint8_t c) __attribute__((always_inline)) {
void writedata8_last(uint8_t c)
__attribute__((always_inline)) {
waitFifoEmpty();
#if ARDUINO >= 160
KINETISK_SPI0.SR = SPI_SR_TCF;
@ -409,7 +366,8 @@ class TFT_ILI9163C : public Adafruit_GFX {
waitTransmitComplete();
}
void writedata16_last(uint16_t d) __attribute__((always_inline)) {
void writedata16_last(uint16_t d)
__attribute__((always_inline)) {
waitFifoEmpty();
#if ARDUINO >= 160
KINETISK_SPI0.SR = SPI_SR_TCF;
@ -420,25 +378,74 @@ class TFT_ILI9163C : public Adafruit_GFX {
#endif
waitTransmitComplete();
}
#else
void writecommand_last(uint8_t c)
__attribute__((always_inline)) {
uint32_t mcr = SPI0_MCR;
#if ARDUINO >= 160
KINETISK_SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
#else
SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
#endif
waitTransmitComplete(mcr);
}
void HLine(int16_t x, int16_t y, int16_t w, uint16_t color) __attribute__((always_inline)) {
void writedata8_last(uint8_t c)
__attribute__((always_inline)) {
uint32_t mcr = SPI0_MCR;
#if ARDUINO >= 160
KINETISK_SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
#else
SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_EOQ;
#endif
waitTransmitComplete(mcr);
}
void writedata16_last(uint16_t d)
__attribute__((always_inline)) {
uint32_t mcr = SPI0_MCR;
#if ARDUINO >= 160
KINETISK_SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_EOQ;
#else
SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1) | SPI_PUSHR_EOQ;
#endif
waitTransmitComplete(mcr);
}
#endif
void HLine(int16_t x, int16_t y, int16_t w, uint16_t color)
__attribute__((always_inline)) {
_setAddrWindow(x, y, x+w-1, y);
//writecommand_cont(CMD_RAMWR);//not needed
do { writedata16_cont(color); } while (--w > 0);
}
void Pixel(int16_t x, int16_t y, uint16_t color) __attribute__((always_inline)) {
_setAddrWindow(x, y, x, y);
//writecommand_cont(CMD_RAMWR);//not needed
writedata16_cont(color);
}
void VLine(int16_t x, int16_t y, int16_t h, uint16_t color) __attribute__((always_inline)) {
void VLine(int16_t x, int16_t y, int16_t h, uint16_t color)
__attribute__((always_inline)) {
_setAddrWindow(x, y, x, y+h-1);
//writecommand_cont(CMD_RAMWR);//not needed
do { writedata16_cont(color); } while (--h > 0);
}
void Pixel(int16_t x, int16_t y, uint16_t color)
__attribute__((always_inline)) {
_setAddrWindow(x, y, x, y);
writedata16_cont(color);
}
#else
uint8_t _cs,_rs,_rst;
#endif
#if !defined(__MK20DX128__) && !defined(__MK20DX256__)
void writecommand(uint8_t c);
void writedata(uint8_t d);
void writedata16(uint16_t d);
#endif
private:
void colorSpace(uint8_t cspace);
void setAddr(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
uint8_t sleep;
void chipInit();
bool boundaryCheck(int16_t x,int16_t y);
void homeAddress();
};
#endif

View file

@ -0,0 +1,54 @@
#ifndef _TFT_ILI9163C_REG_H_
#define _TFT_ILI9163C_REG_H_
//ILI9163C registers-----------------------
#define CMD_NOP 0x00//Non operation
#define CMD_SWRESET 0x01//Soft Reset
#define CMD_SLPIN 0x10//Sleep ON
#define CMD_SLPOUT 0x11//Sleep OFF
#define CMD_PTLON 0x12//Partial Mode ON
#define CMD_NORML 0x13//Normal Display ON
#define CMD_DINVOF 0x20//Display Inversion OFF
#define CMD_DINVON 0x21//Display Inversion ON
#define CMD_GAMMASET 0x26//Gamma Set (0x01[1],0x02[2],0x04[3],0x08[4])
#define CMD_DISPOFF 0x28//Display OFF
#define CMD_DISPON 0x29//Display ON
#define CMD_IDLEON 0x39//Idle Mode ON
#define CMD_IDLEOF 0x38//Idle Mode OFF
#define CMD_CLMADRS 0x2A//Column Address Set
#define CMD_PGEADRS 0x2B//Page Address Set
#define CMD_RAMWR 0x2C//Memory Write
#define CMD_RAMRD 0x2E//Memory Read
#define CMD_CLRSPACE 0x2D//Color Space : 4K/65K/262K
#define CMD_PARTAREA 0x30//Partial Area
#define CMD_VSCLLDEF 0x33//Vertical Scroll Definition
#define CMD_TEFXLON 0x35//Tearing Effect Line ON
#define CMD_TEFXLOF 0x34//Tearing Effect Line OFF
#define CMD_MADCTL 0x36//Memory Access Control
#define CMD_VSSTADRS 0x37//Vertical Scrolling Start address
#define CMD_PIXFMT 0x3A//Interface Pixel Format
#define CMD_FRMCTR1 0xB1//Frame Rate Control (In normal mode/Full colors)
#define CMD_FRMCTR2 0xB2//Frame Rate Control(In Idle mode/8-colors)
#define CMD_FRMCTR3 0xB3//Frame Rate Control(In Partial mode/full colors)
#define CMD_DINVCTR 0xB4//Display Inversion Control
#define CMD_RGBBLK 0xB5//RGB Interface Blanking Porch setting
#define CMD_DFUNCTR 0xB6//Display Fuction set 5
#define CMD_SDRVDIR 0xB7//Source Driver Direction Control
#define CMD_GDRVDIR 0xB8//Gate Driver Direction Control
#define CMD_PWCTR1 0xC0//Power_Control1
#define CMD_PWCTR2 0xC1//Power_Control2
#define CMD_PWCTR3 0xC2//Power_Control3
#define CMD_PWCTR4 0xC3//Power_Control4
#define CMD_PWCTR5 0xC4//Power_Control5
#define CMD_VCOMCTR1 0xC5//VCOM_Control 1
#define CMD_VCOMCTR2 0xC6//VCOM_Control 2
#define CMD_VCOMOFFS 0xC7//VCOM Offset Control
#define CMD_PGAMMAC 0xE0//Positive Gamma Correction Setting
#define CMD_NGAMMAC 0xE1//Negative Gamma Correction Setting
#define CMD_GAMRSEL 0xF2//GAM_R_SEL
#endif

View file

@ -0,0 +1,159 @@
#ifndef _TFT_ILI9163C_USETT_H_
#define _TFT_ILI9163C_USETT_H_
//DID YOU HAVE A RED PCB, BLACk PCB or WHAT DISPLAY TYPE????????????
// ---> SELECT HERE <----
#define __144_RED_PCB__//128x128
//#define __144_BLACK_PCB__//128x128
//#define __22_RED_PCB__//240x320
//---------------------------------------
#if defined(__144_RED_PCB__)
/*
This display:
http://www.ebay.com/itm/Replace-Nokia-5110-LCD-1-44-Red-Serial-128X128-SPI-Color-TFT-LCD-Display-Module-/271422122271
This particular display has a design error! The controller has 3 pins to configure to constrain
the memory and resolution to a fixed dimension (in that case 128x128) but they leaved those pins
configured for 128x160 so there was several pixel memory addressing problems.
I solved by setup several parameters that dinamically fix the resolution as needed so below
the parameters for this diplay. If you have a strain or a correct display (can happen with chinese)
you can copy those parameters and create setup for different displays.
*/
#define _TFTWIDTH 128//the REAL W resolution of the TFT
#define _TFTHEIGHT 128//the REAL H resolution of the TFT
#define _GRAMWIDTH 128
#define _GRAMHEIGH 160//160
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH//*see note 1
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET3 //uncomment for another gamma
#define __OFFSET 32//*see note 2
//Tested!
#elif defined (__144_BLACK_PCB__)
#define _TFTWIDTH 128//the REAL W resolution of the TFT
#define _TFTHEIGHT 128//the REAL H resolution of the TFT
#define _GRAMWIDTH 128
#define _GRAMHEIGH 128
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH//*see note 1
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET1 //uncomment for another gamma
#define __OFFSET 0
//not tested
#elif defined (__22_RED_PCB__)
/*
Like this one:
http://www.ebay.it/itm/2-2-Serial-SPI-TFT-LCD-Display-Module-240x320-Chip-ILI9340C-PCB-Adapter-SD-Card-/281304733556
Not tested!
*/
#define _TFTWIDTH 240//the REAL W resolution of the TFT
#define _TFTHEIGHT 320//the REAL H resolution of the TFT
#define _GRAMWIDTH 240
#define _GRAMHEIGH 320
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET1 //uncomment for another gamma
#define __OFFSET 0
#else
#define _TFTWIDTH 128//128
#define _TFTHEIGHT 160//160
#define _GRAMWIDTH 128
#define _GRAMHEIGH 160
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET1
#define __OFFSET 0
#endif
#if defined(__GAMMASET1)
const uint8_t pGammaSet[15]= {0x36,0x29,0x12,0x22,0x1C,0x15,0x42,0xB7,0x2F,0x13,0x12,0x0A,0x11,0x0B,0x06};
const uint8_t nGammaSet[15]= {0x09,0x16,0x2D,0x0D,0x13,0x15,0x40,0x48,0x53,0x0C,0x1D,0x25,0x2E,0x34,0x39};
#elif defined(__GAMMASET2)
const uint8_t pGammaSet[15]= {0x3F,0x21,0x12,0x22,0x1C,0x15,0x42,0xB7,0x2F,0x13,0x02,0x0A,0x01,0x00,0x00};
const uint8_t nGammaSet[15]= {0x09,0x18,0x2D,0x0D,0x13,0x15,0x40,0x48,0x53,0x0C,0x1D,0x25,0x2E,0x24,0x29};
#elif defined(__GAMMASET3)
const uint8_t pGammaSet[15]= {0x3F,0x26,0x23,0x30,0x28,0x10,0x55,0xB7,0x40,0x19,0x10,0x1E,0x02,0x01,0x00};
const uint8_t nGammaSet[15]= {0x09,0x18,0x2D,0x0D,0x13,0x15,0x40,0x48,0x53,0x0C,0x1D,0x25,0x2E,0x24,0x29};
#else
const uint8_t pGammaSet[15]= {0x3F,0x25,0x1C,0x1E,0x20,0x12,0x2A,0x90,0x24,0x11,0x00,0x00,0x00,0x00,0x00};
const uint8_t nGammaSet[15]= {0x20,0x20,0x20,0x20,0x05,0x15,0x00,0xA7,0x3D,0x18,0x25,0x2A,0x2B,0x2B,0x3A};
#endif
/*
Note 1: The __144_RED_PCB__ display has hardware addressing of 128 x 160
but the tft resolution it's 128 x 128 so the dram should be set correctly
Note 2: This is the offset between image in RAM and TFT. In that case 160 - 128 = 32;
*/
#endif
/*
Benchmark Time (microseconds)
Screen fill 74697
Text 4841
Lines 16025
Horiz/Vert Lines 5028
Rectangles (outline) 4181
Rectangles (filled) 91225
Circles (filled) 14452
Circles (outline) 16397
Triangles (outline) 5069
Triangles (filled) 30715
Rounded rects (outline) 10382
Rounded rects (filled) 99552
Done!
Benchmark Time (microseconds)
Screen fill 74697
Text 4453
Text2 16541
Lines 16027
Horiz/Vert Lines 5029
Rectangles (outline) 4185
Rectangles (filled) 91223
Circles (filled) 14408
Circles (outline) 15082
Triangles (outline) 5067
Triangles (filled) 17439
Rounded rects (outline) 10023
Rounded rects (filled) 99513
Done!
Benchmark Time (microseconds)
Screen fill 277415
Text 11618
Text2 36043
Lines 58163
Horiz/Vert Lines 18655
Rectangles (outline) 15391
Rectangles (filled) 338450
Circles (filled) 53050
Circles (outline) 39227
Triangles (outline) 18302
Triangles (filled) 64198
Rounded rects (outline) 29676
Rounded rects (filled) 368960
Done!
Benchmark Time (microseconds)
Screen fill 277422
Text 13066
Lines 58240
Horiz/Vert Lines 18655
Rectangles (outline) 15422
Rectangles (filled) 339230
Circles (filled) 53049
Circles (outline) 43195
Triangles (outline) 18350
Triangles (filled) 113536
Rounded rects (outline) 31470
Rounded rects (filled) 369703
Done!
*/

View file

@ -33,15 +33,17 @@ You are using 4 wire SPI here, so:
Teensy 3.x can use: 2,6,9,10,15,20,21,22,23
Arduino's 8 bit: any
DUE: check arduino site
If you do not use reset, tie it to +3V3
IMPORTANT!!!
If you do not use reset pin, tie it to +3V3!! Do not leave floating!
*/
TFT_ILI9163C tft = TFT_ILI9163C(__CS, __DC);
void setup() {
Serial.begin(9600);
//while (!Serial);
Serial.begin(38400);
long unsigned debug_start = millis ();
while (!Serial && ((millis () - debug_start) <= 5000)) ;
tft.begin();
Serial.println(F("Benchmark Time (microseconds)"));
@ -53,6 +55,10 @@ void setup() {
Serial.println(testText());
delay(3000);
Serial.print(F("Text2 "));
Serial.println(testText2());
delay(3000);
Serial.print(F("Lines "));
Serial.println(testLines(CYAN));
delay(500);
@ -66,14 +72,14 @@ void setup() {
delay(500);
Serial.print(F("Rectangles (filled) "));
Serial.println(testFilledRects(YELLOW,MAGENTA));
Serial.println(testFilledRects(YELLOW, MAGENTA));
delay(500);
Serial.print(F("Circles (filled) "));
Serial.println(testFilledCircles(10,MAGENTA));
Serial.println(testFilledCircles(10, MAGENTA));
Serial.print(F("Circles (outline) "));
Serial.println(testCircles(10,WHITE));
Serial.println(testCircles(10, WHITE));
delay(500);
Serial.print(F("Triangles (outline) "));
@ -96,7 +102,7 @@ void setup() {
}
void loop(void) {
for(uint8_t rotation=0; rotation<4; rotation++) {
for (uint8_t rotation = 0; rotation < 4; rotation++) {
tft.setRotation(rotation);
testText();
delay(2000);
@ -131,6 +137,16 @@ unsigned long testText() {
tft.setTextColor(GREEN);
tft.setTextSize(4);
tft.println("Hello");
return micros() - start;
}
unsigned long testText2() {
tft.fillScreen();
unsigned long start = micros();
tft.setCursor(0, 0);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.println("I implore thee,");
tft.setTextSize(1);
@ -155,9 +171,9 @@ unsigned long testLines(uint16_t color) {
x1 = y1 = 0;
y2 = h - 1;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t = micros() - start; // fillScreen doesn't count against timing
tft.fillScreen();
@ -166,9 +182,9 @@ unsigned long testLines(uint16_t color) {
y1 = 0;
y2 = h - 1;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = 0;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t += micros() - start;
tft.fillScreen();
@ -177,9 +193,9 @@ unsigned long testLines(uint16_t color) {
y1 = h - 1;
y2 = 0;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t += micros() - start;
tft.fillScreen();
@ -188,9 +204,9 @@ unsigned long testLines(uint16_t color) {
y1 = h - 1;
y2 = 0;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = 0;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
return micros() - start;
}
@ -201,8 +217,8 @@ unsigned long testFastLines(uint16_t color1, uint16_t color2) {
tft.fillScreen();
start = micros();
for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
for (y = 0; y < h; y += 5) tft.drawFastHLine(0, y, w, color1);
for (x = 0; x < w; x += 5) tft.drawFastVLine(x, 0, h, color2);
return micros() - start;
}
@ -216,9 +232,9 @@ unsigned long testRects(uint16_t color) {
tft.fillScreen();
n = min(tft.width(), tft.height());
start = micros();
for(i=2; i<n; i+=6) {
for (i = 2; i < n; i += 6) {
i2 = i / 2;
tft.drawRect(cx-i2, cy-i2, i, i, color);
tft.drawRect(cx - i2, cy - i2, i, i, color);
}
return micros() - start;
@ -232,13 +248,13 @@ unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
tft.fillScreen();
n = min(tft.width(), tft.height());
for(i=n; i>0; i-=6) {
for (i = n; i > 0; i -= 6) {
i2 = i / 2;
start = micros();
tft.fillRect(cx-i2, cy-i2, i, i, color1);
tft.fillRect(cx - i2, cy - i2, i, i, color1);
t += micros() - start;
// Outlines are not included in timing results
tft.drawRect(cx-i2, cy-i2, i, i, color2);
tft.drawRect(cx - i2, cy - i2, i, i, color2);
}
return t;
@ -250,8 +266,8 @@ unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
tft.fillScreen();
start = micros();
for(x=radius; x<w; x+=r2) {
for(y=radius; y<h; y+=r2) {
for (x = radius; x < w; x += r2) {
for (y = radius; y < h; y += r2) {
tft.fillCircle(x, y, radius, color);
}
}
@ -268,8 +284,8 @@ unsigned long testCircles(uint8_t radius, uint16_t color) {
// Screen is not cleared for this one -- this is
// intentional and does not affect the reported time.
start = micros();
for(x=0; x<w; x+=r2) {
for(y=0; y<h; y+=r2) {
for (x = 0; x < w; x += r2) {
for (y = 0; y < h; y += r2) {
tft.drawCircle(x, y, radius, color);
}
}
@ -285,7 +301,7 @@ unsigned long testTriangles() {
tft.fillScreen();
n = min(cx, cy);
start = micros();
for(i=0; i<n; i+=5) {
for (i = 0; i < n; i += 5) {
tft.drawTriangle(
cx , cy - i, // peak
cx - i, cy + i, // bottom left
@ -303,7 +319,7 @@ unsigned long testFilledTriangles() {
tft.fillScreen();
start = micros();
for(i=min(cx,cy); i>10; i-=5) {
for (i = min(cx, cy); i > 10; i -= 5) {
start = micros();
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
tft.Color565(0, i, i));
@ -324,9 +340,9 @@ unsigned long testRoundRects() {
tft.fillScreen();
w = min(tft.width(), tft.height());
start = micros();
for(i=0; i<w; i+=6) {
for (i = 0; i < w; i += 6) {
i2 = i / 2;
tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.Color565(i, 0, 0));
tft.drawRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.Color565(i, 0, 0));
}
return micros() - start;
@ -340,9 +356,9 @@ unsigned long testFilledRoundRects() {
tft.fillScreen();
start = micros();
for(i=min(tft.width(), tft.height()); i>20; i-=6) {
for (i = min(tft.width(), tft.height()); i > 20; i -= 6) {
i2 = i / 2;
tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.Color565(0, i, 0));
tft.fillRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.Color565(0, i, 0));
}
return micros() - start;

View file

@ -1,5 +1,5 @@
name=TFT_ILI9163C
version=0.8
version=0.9
author=Max MC Costa
maintainer=sumotoy <sumotoy@gmail.com>
sentence=A fast SPI driver for TFT drived by ILI9163C, fully SPI Transaction compatible and very fast with Teensy 3