/*
UTFT.cpp - Multi-Platform library support for Color TFT LCD Boards
Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved
This library is the continuation of my ITDB02_Graph, ITDB02_Graph16
and RGB_GLCD libraries for Arduino and chipKit. As the number of
supported display modules and controllers started to increase I felt
it was time to make a single, universal library as it will be much
easier to maintain in the future.
Basic functionality of this library was origianlly based on the
demo-code provided by ITead studio (for the ITDB02 modules) and
NKC Electronics (for the RGB GLCD module/shield).
This library supports a number of 8bit, 16bit and serial graphic
displays, and will work with both Arduino, chipKit boards and select
TI LaunchPads. For a full list of tested display modules and controllers,
see the document UTFT_Supported_display_modules_&_controllers.pdf.
When using 8bit and 16bit display modules there are some
requirements you must adhere to. These requirements can be found
in the document UTFT_Requirements.pdf.
There are no special requirements when using serial displays.
You can find the latest version of the library at
http://www.RinkyDinkElectronics.com/
This library is free software; you can redistribute it and/or
modify it under the terms of the CC BY-NC-SA 3.0 license.
Please see the included documents for further information.
Commercial use of this library requires you to buy a license that
will allow commercial use. This includes using the library,
modified or not, as a tool to sell products.
The license applies to all part of the library including the
examples and tools supplied with the library.
*/
#include "UTFT.h"
// Include hardware-specific functions for the correct MCU
#if defined(__AVR__)
#include <avr/pgmspace.h>
#endif
void UTFT::writeB(byte b) {
#if DISP_TRANSFER>8
writeW(b); // always 16-bit
#elif DISP_TRANSFER==1
for (byte m=0x80; m; m>>=1) {
if (VL & 0x80) DISP_SDA(1); else DISP_SDA(0);
DISP_SCL(0);
DISP_SCL(1);
}
#else
DISP_OUT(b);
DISP_WR(0);
DISP_WR(1);
#endif
}
void UTFT::writeW(word w) {
#if DISP_TRANSFER<=8
writeB(w>>8);
writeB(w);
#elif defined(DISP_ALE)
DISP_OUT(w>>8);
DISP_ALE(1);
DISP_ALE(0);
DISP_OUT(w);
DISP_WR(0);
DISP_WR(1);
#else
DISP_OUT(w);
DISP_WR(0);
DISP_WR(1);
#endif
}
void UTFT::InitLCD(byte orientation) {
orient=orientation;
DISP_INIT();
#ifdef DISP_DDR
DISP_DDR(1); // data port is output port
#endif
#ifdef DISP_RST
DISP_RST(1);
delay(5);
DISP_RST(0);
delay(15);
DISP_RST(1);
delay(15);
#endif
DISP_CS(0);
#if defined(DISP_HX8347A)
#include "tft_drivers/hx8347a/initlcd.h"
#elif defined(DISP_HX8340B_8)
#include "tft_drivers/hx8340b/8/initlcd.h"
#elif defined(DISP_HX8340B_S)
#include "tft_drivers/hx8340b/s/initlcd.h"
#elif defined(DISP_HX8352A)
#include "tft_drivers/hx8352a/initlcd.h"
#elif defined(DISP_ILI9327)
#include "tft_drivers/ili9327/initlcd.h"
#elif defined(DISP_SSD1289)
#include "tft_drivers/ssd1289/initlcd.h"
#elif defined(DISP_ILI9325C)
#include "tft_drivers/ili9325c/initlcd.h"
#elif defined(DISP_ILI9325D)
#include "tft_drivers/ili9325d/default/initlcd.h"
#elif defined(DISP_ILI9325D_ALT)
#include "tft_drivers/ili9325d/alt/initlcd.h"
#elif defined(DISP_ST7735)
#include "tft_drivers/st7735/std/initlcd.h"
#elif defined(DISP_ST7735_ALT)
#include "tft_drivers/st7735/alt/initlcd.h"
#elif defined(DISP_ST7735S)
#include "tft_drivers/st7735s/initlcd.h"
#elif defined(DISP_PCF8833)
#include "tft_drivers/pcf8833/initlcd.h"
#elif defined(DISP_S1D19122)
#include "tft_drivers/s1d19122/initlcd.h"
#elif defined(DISP_SSD1963_480)
#include "tft_drivers/ssd1963/480/initlcd.h"
#elif defined(DISP_SSD1963_800)
#include "tft_drivers/ssd1963/800/initlcd.h"
#elif defined(DISP_SSD1963_800_ALT)
#include "tft_drivers/ssd1963/800alt/initlcd.h"
#elif defined(DISP_S6D1121)
#include "tft_drivers/s6d1121/initlcd.h"
#elif defined(DISP_ILI9481)
#include "tft_drivers/ili9481/initlcd.h"
#elif defined(DISP_S6D0164)
#include "tft_drivers/s6d0164/initlcd.h"
#elif defined(DISP_ILI9341_S4P)
#include "tft_drivers/ili9341/s4p/initlcd.h"
#elif defined(DISP_ILI9341)
#include "tft_drivers/ili9341/initlcd.h"
#elif defined(DISP_R61581)
#include "tft_drivers/r61581/initlcd.h"
#elif defined(DISP_ILI9486)
#include "tft_drivers/ili9486/initlcd.h"
#elif defined(DISP_CPLD)
#include "tft_drivers/cpld/initlcd.h"
#elif defined(DISP_HX8353C)
#include "tft_drivers/hx8353c/initlcd.h"
#else
# error Undefined DISP_xxx definition!
#endif
DISP_CS(1);
setColor(255, 255, 255);
setBackColor(0, 0, 0);
cfont.font=0;
_transparent = false;
}
void UTFT::setWindow(int x1, int y1, int x2, int y2) {
if (orient==LANDSCAPE) {
SWAP(x1,y1);
SWAP(x2,y2)
y1=DISP_Y_SIZE-1-y1;
y2=DISP_Y_SIZE-1-y2;
SWAP(y1,y2)
}
setXY(x1,y1,x2,y2);
}
void UTFT::setXY(int x1, int y1, int x2, int y2) {
/*** ILI ***/
#if defined(DISP_ILI9325C)
#include "tft_drivers/ili9325c/setxy.h"
#elif defined(DISP_ILI9325D) || defined(DISP_ILI9325D_ALT)
#include "tft_drivers/ili9325d/setxy.h"
#elif defined(DISP_ILI9327)
#include "tft_drivers/ili9327/setxy.h"
#elif defined(DISP_ILI9341)
#include "tft_drivers/ili9341/setxy.h"
#elif defined(DISP_ILI9481)
#include "tft_drivers/ili9481/setxy.h"
#elif defined(DISP_ILI9486)
#include "tft_drivers/ili9486/setxy.h"
/*** HX ***/
#elif defined(DISP_HX8340B_8)
#include "tft_drivers/hx8340b/8/setxy.h"
#elif defined(DISP_HX8340B_S)
#include "tft_drivers/hx8340b/s/setxy.h"
#elif defined(DISP_HX8347A)
#include "tft_drivers/hx8347a/setxy.h"
#elif defined(DISP_HX8352A)
#include "tft_drivers/hx8352a/setxy.h"
#elif defined(DISP_HX8353C)
#include "tft_drivers/hx8353c/setxy.h"
/*** ST, SxD ***/
#elif defined(DISP_ST7735) || defined(DISP_ST7735_ALT) || defined(DISP_ST7735S)
#include "tft_drivers/st7735/setxy.h"
#elif defined(DISP_S1D19122)
#include "tft_drivers/s1d19122/setxy.h"
#elif defined(DISP_S6D1121)
#include "tft_drivers/s6d1121/setxy.h"
#elif defined(DISP_S6D0164)
#include "tft_drivers/s6d0164/setxy.h"
/*** SSD ***/
#elif defined(DISP_SSD1289)
#include "tft_drivers/ssd1289/setxy.h"
#elif defined(DISP_SSD1963_480) || defined(DISP_SSD1963_800) || defined(DISP_SSD1963_800_ALT)
#include "tft_drivers/ssd1963/setxy.h"
/*** other ***/
#elif defined(DISP_PCF8833)
#include "tft_drivers/pcf8833/setxy.h"
#elif defined(DISP_R61581)
#include "tft_drivers/r61581/setxy.h"
#elif defined(DISP_CPLD)
#include "tft_drivers/cpld/setxy.h"
#else
# error Add code here!
#endif
#ifdef DISP_RS
DISP_RS(1);
#endif
}
void UTFT::_fast_fill(word w, int dx, int dy) {
#ifdef __AVR__ // 8-bit optimized
long pix=(long)dx*dy;
if (!pix) return;
byte rep0=pix;
byte rep1=pix>>8;
byte rep2=pix>>16;
if (rep0) ++rep1;
if (rep1) ++rep2;
#define DO do do do
#define WHILE() while(--rep0); while(--rep1); while(--rep2)
#else // 16-bit optimized
if (dx<dy) SWAP(dx,dy);
if (!dy) return;
#define DO do do
#define WHILE() while(--dx); while(--dy);
#endif
#if DISP_TRANSFER==16
DISP_OUT(w);
DO{
DISP_WR(0);
DISP_WR(1);
}WHILE();
#elif DISP_TRANSFER==8
if (w>>8==(w&0xFF)) {
DISP_OUT(w);
DO{
DISP_WR(0);
DISP_WR(1);
DISP_WR(0);
DISP_WR(1);
}WHILE();
}else{
DO{
DISP_OUT(w>>8);
DISP_WR(0);
DISP_WR(1);
DISP_OUT(w);
DISP_WR(0);
DISP_WR(1);
}WHILE();
}
#else
DO{
setPixel(w);
}WHILE();
#endif
#undef DO
#undef WHILE
}
void UTFT::drawRect(int x1, int y1, int x2, int y2) {
if (x1>x2) SWAP(x1, x2);
if (y1>y2) SWAP(y1, y2);
drawHLine(x1, y1, x2-x1);
drawHLine(x1, y2, x2-x1);
drawVLine(x1, y1, y2-y1);
drawVLine(x2, y1, y2-y1);
}
void UTFT::drawRoundRect(int x1, int y1, int x2, int y2)
{
if (x1>x2)
{
SWAP(x1, x2);
}
if (y1>y2)
{
SWAP(y1, y2);
}
if ((x2-x1)>4 && (y2-y1)>4)
{
drawPixel(x1+1,y1+1);
drawPixel(x2-1,y1+1);
drawPixel(x1+1,y2-1);
drawPixel(x2-1,y2-1);
drawHLine(x1+2, y1, x2-x1-4);
drawHLine(x1+2, y2, x2-x1-4);
drawVLine(x1, y1+2, y2-y1-4);
drawVLine(x2, y1+2, y2-y1-4);
}
}
void UTFT::fillRect(int x1, int y1, int x2, int y2) {
if (x1>x2) SWAP(x1, x2);
if (y1>y2) SWAP(y1, y2);
DISP_CS(0);
setWindow(x1, y1, x2, y2);
_fast_fill(fc,x2-x1+1,y2-y1+1);
DISP_CS(1);
}
void UTFT::fillRoundRect(int x1, int y1, int x2, int y2) {
if (x1>x2) SWAP(x1, x2);
if (y1>y2) SWAP(y1, y2);
if ((x2-x1)>4 && (y2-y1)>4)
{
for (int i=0; i<((y2-y1)/2)+1; i++)
{
switch(i)
{
case 0:
drawHLine(x1+2, y1+i, x2-x1-4);
drawHLine(x1+2, y2-i, x2-x1-4);
break;
case 1:
drawHLine(x1+1, y1+i, x2-x1-2);
drawHLine(x1+1, y2-i, x2-x1-2);
break;
default:
drawHLine(x1, y1+i, x2-x1);
drawHLine(x1, y2-i, x2-x1);
}
}
}
}
void UTFT::drawCircle(int x, int y, int radius) {
int f = 1 - radius;
int ddF_x = 1;
int ddF_y = -2 * radius;
int x1 = 0;
int y1 = radius;
DISP_CS(0);
setPixel(x, y + radius);
setPixel(x, y - radius);
setPixel(x + radius, y);
setPixel(x - radius, y);
while(x1 < y1)
{
if(f >= 0)
{
y1--;
ddF_y += 2;
f += ddF_y;
}
x1++;
ddF_x += 2;
f += ddF_x;
setPixel(x + x1, y + y1);
setPixel(x - x1, y + y1);
setPixel(x + x1, y - y1);
setPixel(x - x1, y - y1);
setPixel(x + y1, y + x1);
setPixel(x - y1, y + x1);
setPixel(x + y1, y - x1);
setPixel(x - y1, y - x1);
}
DISP_CS(1);
clrXY();
}
void UTFT::fillCircle(int x, int y, int radius) {
for(int y1=-radius; y1<=0; y1++)
for(int x1=-radius; x1<=0; x1++)
if(x1*x1+y1*y1 <= radius*radius)
{
drawHLine(x+x1, y+y1, 2*(-x1));
drawHLine(x+x1, y-y1, 2*(-x1));
break;
}
}
void UTFT::fillScr(word color) {
long i;
DISP_CS(0);
clrXY();
_fast_fill(color,DISP_X_SIZE,DISP_Y_SIZE);
DISP_CS(1);
}
void UTFT::drawPixel(int x, int y)
{
DISP_CS(0);
setPixel(x,y);
clrXY();
DISP_CS(1);
}
void UTFT::drawLine(int x1, int y1, int x2, int y2)
{
if (y1==y2)
drawHLine(x1, y1, x2-x1);
else if (x1==x2)
drawVLine(x1, y1, y2-y1);
else
{
unsigned int dx = (x2 > x1 ? x2 - x1 : x1 - x2);
short xstep = x2 > x1 ? 1 : -1;
unsigned int dy = (y2 > y1 ? y2 - y1 : y1 - y2);
short ystep = y2 > y1 ? 1 : -1;
int col = x1, row = y1;
DISP_CS(0);
if (dx < dy)
{
int t = - (dy >> 1);
while (true)
{
setPixel(col, row);
if (row == y2)
return;
row += ystep;
t += dx;
if (t >= 0)
{
col += xstep;
t -= dy;
}
}
}
else
{
int t = - (dx >> 1);
while (true)
{
setPixel(col, row);
if (col == x2)
return;
col += xstep;
t += dy;
if (t >= 0)
{
row += ystep;
t -= dx;
}
}
}
DISP_CS(1);
}
clrXY();
}
void UTFT::drawHLine(int x, int y, int l) {
if (l<0) {l = -l; x -= l;}
DISP_CS(0);
setWindow(x, y, x+l, y);
_fast_fill(fc,l,1);
clrXY();
DISP_CS(1);
}
void UTFT::drawVLine(int x, int y, int l) {
if (l<0) {l = -l; y -= l;}
DISP_CS(0);
setWindow(x, y, x, y+l);
_fast_fill(fc,l,1);
clrXY();
DISP_CS(1);
}
void UTFT::printChar(byte c, int x, int y)
{
byte i,ch;
word j;
word temp;
DISP_CS(0);
if (!_transparent)
{
if (orient==PORTRAIT)
{
setWindow(x,y,x+cfont.x_size-1,y+cfont.y_size-1);
temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
for(j=0;j<((cfont.x_size/8)*cfont.y_size);j++)
{
ch=pgm_read_byte(&cfont.font[temp]);
for(i=0;i<8;i++)
{
if((ch&(1<<(7-i)))!=0)
{
setPixel();
}
else
{
setPixel(bc);
}
}
temp++;
}
}
else
{
temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
for(j=0;j<((cfont.x_size/8)*cfont.y_size);j+=(cfont.x_size/8))
{
setWindow(x,y+(j/(cfont.x_size/8)),x+cfont.x_size-1,y+(j/(cfont.x_size/8)));
for (int zz=(cfont.x_size/8)-1; zz>=0; zz--)
{
ch=pgm_read_byte(&cfont.font[temp+zz]);
for(i=0;i<8;i++)
{
if((ch&(1<<i))!=0)
{
setPixel();
}
else
{
setPixel(bc);
}
}
}
temp+=(cfont.x_size/8);
}
}
}
else
{
temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
for(j=0;j<cfont.y_size;j++)
{
for (int zz=0; zz<(cfont.x_size/8); zz++)
{
ch=pgm_read_byte(&cfont.font[temp+zz]);
for(i=0;i<8;i++)
{
if((ch&(1<<(7-i)))!=0)
{
setWindow(x+i+(zz*8),y+j,x+i+(zz*8)+1,y+j+1);
setPixel();
}
}
}
temp+=(cfont.x_size/8);
}
}
DISP_CS(1);
clrXY();
}
void UTFT::rotateChar(byte c, int x, int y, int pos, int deg)
{
byte i,j,ch;
word temp;
int newx,newy;
double radian;
radian=deg*0.0175;
DISP_CS(0);
temp=((c-cfont.offset)*((cfont.x_size/8)*cfont.y_size))+4;
for(j=0;j<cfont.y_size;j++)
{
for (int zz=0; zz<(cfont.x_size/8); zz++)
{
ch=pgm_read_byte(&cfont.font[temp+zz]);
for(i=0;i<8;i++)
{
newx=x+(((i+(zz*8)+(pos*cfont.x_size))*cos(radian))-((j)*sin(radian)));
newy=y+(((j)*cos(radian))+((i+(zz*8)+(pos*cfont.x_size))*sin(radian)));
setWindow(newx,newy,newx+1,newy+1);
if((ch&(1<<(7-i)))!=0)
{
setPixel();
}
else
{
if (!_transparent)
setPixel(bc);
}
}
}
temp+=(cfont.x_size/8);
}
DISP_CS(1);
clrXY();
}
void UTFT::print(const char *st, int x, int y, int deg)
{
int stl, i;
stl = strlen(st);
if (x==RIGHT)
x=getDisplayXSize()-(stl*cfont.x_size);
if (x==CENTER)
x=(getDisplayXSize()-(stl*cfont.x_size))/2;
for (i=0; i<stl; i++)
if (deg==0)
printChar(*st++, x + (i*(cfont.x_size)), y);
else
rotateChar(*st++, x, y, i, deg);
}
void UTFT::print(String st, int x, int y, int deg)
{
char buf[st.length()+1];
st.toCharArray(buf, st.length()+1);
print(buf, x, y, deg);
}
void UTFT::printNumI(long num, int x, int y, int length, char filler)
{
char buf[25];
char st[27];
boolean neg=false;
int c=0, f=0;
if (num==0)
{
if (length!=0)
{
for (c=0; c<(length-1); c++)
st[c]=filler;
st[c]=48;
st[c+1]=0;
}
else
{
st[0]=48;
st[1]=0;
}
}
else
{
if (num<0)
{
neg=true;
num=-num;
}
while (num>0)
{
buf[c]=48+(num % 10);
c++;
num=(num-(num % 10))/10;
}
buf[c]=0;
if (neg)
{
st[0]=45;
}
if (length>(c+neg))
{
for (int i=0; i<(length-c-neg); i++)
{
st[i+neg]=filler;
f++;
}
}
for (int i=0; i<c; i++)
{
st[i+neg+f]=buf[c-i-1];
}
st[c+neg+f]=0;
}
print(st,x,y);
}
void UTFT::printNumF(double num, byte dec, int x, int y, char divider, int length, char filler)
{
char st[27];
boolean neg=false;
if (dec<1)
dec=1;
else if (dec>5)
dec=5;
if (num<0)
neg = true;
_convert_float(st, num, length, dec);
if (divider != '.')
{
for (int i=0; i<sizeof(st); i++)
if (st[i]=='.')
st[i]=divider;
}
if (filler != ' ')
{
if (neg)
{
st[0]='-';
for (int i=1; i<sizeof(st); i++)
if ((st[i]==' ') || (st[i]=='-'))
st[i]=filler;
}
else
{
for (int i=0; i<sizeof(st); i++)
if (st[i]==' ')
st[i]=filler;
}
}
print(st,x,y);
}
void UTFT::setFont(const byte*font) {
cfont.font=font;
cfont.x_size=pgm_read_byte(font++);
cfont.y_size=pgm_read_byte(font++);
cfont.offset=pgm_read_byte(font++);
cfont.numchars=pgm_read_byte(font++);
}
void UTFT::drawBitmap(int x, int y, int sx, int sy, const word*data, int scale)
{
unsigned int col;
int tx, ty, tc, tsx, tsy;
if (scale==1)
{
if (orient==PORTRAIT)
{
DISP_CS(0);
setWindow(x, y, x+sx-1, y+sy-1);
for (tc=0; tc<(sx*sy); tc++)
{
col=pgm_read_word(&data[tc]);
setPixel(col);
}
DISP_CS(1);
}
else
{
DISP_CS(0);
for (ty=0; ty<sy; ty++)
{
setWindow(x, y+ty, x+sx-1, y+ty);
for (tx=sx-1; tx>=0; tx--)
{
col=pgm_read_word(&data[(ty*sx)+tx]);
setPixel(col);
}
}
DISP_CS(1);
}
}
else
{
if (orient==PORTRAIT)
{
DISP_CS(0);
for (ty=0; ty<sy; ty++)
{
setWindow(x, y+(ty*scale), x+((sx*scale)-1), y+(ty*scale)+scale);
for (tsy=0; tsy<scale; tsy++)
for (tx=0; tx<sx; tx++)
{
col=pgm_read_word(&data[(ty*sx)+tx]);
for (tsx=0; tsx<scale; tsx++)
setPixel(col);
}
}
DISP_CS(1);
}
else
{
DISP_CS(0);
for (ty=0; ty<sy; ty++)
{
for (tsy=0; tsy<scale; tsy++)
{
setWindow(x, y+(ty*scale)+tsy, x+((sx*scale)-1), y+(ty*scale)+tsy);
for (tx=sx-1; tx>=0; tx--)
{
col=pgm_read_word(&data[(ty*sx)+tx]);
for (tsx=0; tsx<scale; tsx++)
setPixel(col);
}
}
}
DISP_CS(1);
}
}
clrXY();
}
void UTFT::drawBitmap(int x, int y, int sx, int sy, const word*data, int deg, int rox, int roy)
{
unsigned int col;
int tx, ty, newx, newy;
double radian;
radian=deg*0.0175;
if (deg==0)
drawBitmap(x, y, sx, sy, data);
else
{
DISP_CS(0);
for (ty=0; ty<sy; ty++)
for (tx=0; tx<sx; tx++)
{
col=pgm_read_word(&data[(ty*sx)+tx]);
newx=x+rox+(((tx-rox)*cos(radian))-((ty-roy)*sin(radian)));
newy=y+roy+(((ty-roy)*cos(radian))+((tx-rox)*sin(radian)));
setWindow(newx, newy, newx, newy);
setPixel(col);
}
DISP_CS(1);
}
clrXY();
}
void UTFT::lcdOff() {
#ifdef DISP_PCF8833
DISP_CS(0);
writeC(0x28);
DISP_CS(1);
#elif defined(DISP_CPLD)
DISP_CS(0);
writeCW(0x01,0x0000);
writeC(0x0F);
DISP_CS(1);
#endif
}
void UTFT::lcdOn() {
#ifdef DISP_PCF8833
DISP_CS(0);
writeC(0x29);
DISP_CS(1);
#elif defined(DISP_CPLD)
DISP_CS(0);
writeCW(0x01,0x0010);
writeC(0x0F);
DISP_CS(1);
#endif
}
void UTFT::setContrast(char c) {
#ifdef DISP_PCF8833
DISP_CS(0);
if (c>64) c=64;
writeC(0x25);
writeB(c);
DISP_CS(1);
#endif
}
void UTFT::setBrightness(byte br) {
#ifdef DISP_CPLD
DISP_CS(0);
if (br>16) br=16;
writeCW(0x01,br);
writeC(0x0F);
DISP_CS(1);
#endif
}
void UTFT::setDisplayPage(byte page) {
#ifdef DISP_CPLD
DISP_CS(0);
if (page>7) page=7;
writeCW(0x04,page);
writeC(0x0F);
DISP_CS(1);
#endif
}
void UTFT::setWritePage(byte page) {
#ifdef DISP_CPLD
DISP_CS(0);
if (page>7) page=7;
writeCW(0x05,page);
writeC(0x0F);
DISP_CS(1);
#endif
}
void UTFT::_convert_float(char *buf, double num, int width, byte prec) {
#ifdef __AVR___
dtostrf(num, width, prec, buf);
#else
char format[10];
sprintf(format, "%%%i.%if", width, prec);
sprintf(buf, format, num);
#endif
}
Detected encoding: ASCII (7 bit) | 2
|