T-keyboard/lib/T-0.99TFT/src/TFT_GC9D01N.cpp

787 lines
14 KiB
C++

#include "TFT_GC9D01N.h"
#include "Fonts.h"
void TFT_GC9D01N_Class::begin_tft_write()
{
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0)); // RP2040 SDK -> 68us delay!
CS_L;
// SET_BUS_WRITE_MODE;
}
void TFT_GC9D01N_Class::end_tft_write()
{
// SPI_BUSY_CHECK; // Check send complete and clean out unused rx data
CS_H;
SPI.endTransaction(); // RP2040 SDK -> 0.7us delay
}
void TFT_GC9D01N_Class::writedata(uint8_t d)
{
begin_tft_write();
DC_D; // Play safe, but should already be in data mode 高电平1为数据
SPI.transfer(d);
CS_L; // Allow more hold time for low VDI rail
end_tft_write();
}
void TFT_GC9D01N_Class::writecommand(uint8_t c)
{
begin_tft_write();
DC_C; //高电平1为数据
SPI.transfer(c);//tft_Write_8(c);
DC_D;
end_tft_write();
}
void TFT_GC9D01N_Class::lcd_init()
{
RST_H;
delay(80);
RST_L;
delay(80);
RST_H;
delay(480);
writecommand(0xFE);
writecommand(0xEF);
writecommand(0x80);
writedata(0xFF);
writecommand(0x81);
writedata(0xFF);
writecommand(0x82);
writedata(0xFF);
writecommand(0x83);
writedata(0xFF);
writecommand(0x84);
writedata(0xFF);
writecommand(0x85);
writedata(0xFF);
writecommand(0x86);
writedata(0xFF);
writecommand(0x87);
writedata(0xFF);
writecommand(0x88);
writedata(0xFF);
writecommand(0x89);
writedata(0xFF);
writecommand(0x8A);
writedata(0xFF);
writecommand(0x8B);
writedata(0xFF);
writecommand(0x8C);
writedata(0xFF);
writecommand(0x8D);
writedata(0xFF);
writecommand(0x8E);
writedata(0xFF);
writecommand(0x8F);
writedata(0xFF);
writecommand(0x3A);
writedata(0x05);
writecommand(0xEC);
writedata(0x11);
writecommand(0x7E);
writedata(0x7a);
writecommand(0x74);
writedata(0x02);
writedata(0x0E);
writedata(0x00);
writedata(0x00);
writedata(0x28);
writedata(0x00);
writedata(0x00);
writecommand(0x98);
writedata(0x3E);
writecommand(0x99);
writedata(0x3E);
writecommand(0xB5);
writedata(0x0E);
writedata(0x0E);
writecommand(0x60);
writedata(0x38);
writedata(0x09);
writedata(0x6D);
writedata(0x67);
writecommand(0x63);
writedata(0x38);
writedata(0xAD);
writedata(0x6D);
writedata(0x67);
writedata(0x05);
writecommand(0x64);
writedata(0x38);
writedata(0x0B);
writedata(0x70);
writedata(0xAB);
writedata(0x6D);
writedata(0x67);
writecommand(0x66);
writedata(0x38);
writedata(0x0F);
writedata(0x70);
writedata(0xAF);
writedata(0x6d);
writedata(0x67);
writecommand(0x6A);
writedata(0x00);
writedata(0x00);
writecommand(0x68);
writedata(0x3B);
writedata(0x08);
writedata(0x04);
writedata(0x00);
writedata(0x04);
writedata(0x64);
writedata(0x67);
writecommand(0x6C);
writedata(0x22);
writedata(0x02);
writedata(0x22);
writedata(0x02);
writedata(0x22);
writedata(0x22);
writedata(0x50);
writecommand(0x6E);
writedata(0x00);
writedata(0x00);
writedata(0x00);
writedata(0x00);
writedata(0x07);
writedata(0x01);
writedata(0x13);
writedata(0x11);
writedata(0x0B);
writedata(0x09);
writedata(0x16);
writedata(0x15);
writedata(0x1D);
writedata(0x1E);
writedata(0x00);
writedata(0x00);
writedata(0x00);
writedata(0x00);
writedata(0x1E);
writedata(0x1D);
writedata(0x15);
writedata(0x16);
writedata(0x0A);
writedata(0x0C);
writedata(0x12);
writedata(0x14);
writedata(0x02);
writedata(0x08);
writedata(0x00);
writedata(0x00);
writedata(0x00);
writedata(0x00);
writecommand(0xA9);
writedata(0x1B);
writecommand(0xA8);
writedata(0x6B);
writecommand(0xA8);
writedata(0x6D);
writecommand(0xA7);
writedata(0x40);
writecommand(0xAD);
writedata(0x47);
writecommand(0xAF);
writedata(0x73);
writecommand(0xAF);
writedata(0x73);
writecommand(0xAC);
writedata(0x44);
writecommand(0xA3);
writedata(0x6C);
writecommand(0xCB);
writedata(0x00);
writecommand(0xCD);
writedata(0x22);
writecommand(0xC2);
writedata(0x10);
writecommand(0xC5);
writedata(0x00);
writecommand(0xC6);
writedata(0x0E);
writecommand(0xC7);
writedata(0x1f);
writecommand(0xC8);
writedata(0x0E);
writecommand(0xbf);
writedata(0x00);
writecommand(0xF9);
writedata(0x20);
writecommand(0x9b);
writedata(0x3b);
writecommand(0x93);
writedata(0x33);
writedata(0x7f);
writedata(0x00);
writecommand(0x70);
writedata(0x0E);
writedata(0x0f);
writedata(0x03);
writedata(0x0e);
writedata(0x0f);
writedata(0x03);
writecommand(0x71);
writedata(0x0e);
writedata(0x16);
writedata(0x03);
writecommand(0x91);
writedata(0x0e);
writedata(0x09);
writecommand(0xc3);
writedata(0x2c);
writecommand(0xc4);
writedata(0x1a);
writecommand(0xf0);
writedata(0x51);
writedata(0x13);
writedata(0x0c);
writedata(0x06);
writedata(0x00);
writedata(0x2f);
writecommand(0xf2);
writedata(0x51);
writedata(0x13);
writedata(0x0c);
writedata(0x06);
writedata(0x00);
writedata(0x33);
writecommand(0xf1);
writedata(0x3c);
writedata(0x94);
writedata(0x4f);
writedata(0x33);
writedata(0x34);
writedata(0xCf);
writecommand(0xf3);
writedata(0x4d);
writedata(0x94);
writedata(0x4f);
writedata(0x33);
writedata(0x34);
writedata(0xCf);
#define TFT_MAD_MY 0x80
#define TFT_MAD_MX 0x40
#define TFT_MAD_MV 0x20
#define TFT_MAD_ML 0x10
writecommand(0x36);
//#if LANDSCAPE
//writedata(0x00 | TFT_MAD_MX | TFT_MAD_MY);
#if (LANDSCAPE==2)||(PORTRAIT==2)
writedata(0x00);
#else
writedata(0x00 | TFT_MAD_MX | TFT_MAD_MY);
#endif
writecommand(0x11);
delay(200);
writecommand(0x29);
writecommand(0x2C);
}
//init lcd
int TFT_GC9D01N_Class::begin()
{
pinMode(TFT_BL, OUTPUT);
pinMode(TFT_SCLK, OUTPUT);
pinMode(TFT_MISO, OUTPUT);
pinMode(TFT_MOSI, OUTPUT);
pinMode(TFT_DC, OUTPUT);
pinMode(TFT_CS, OUTPUT);
pinMode(TFT_RST, OUTPUT);
ledcSetup(1, 1000, 10);
ledcAttachPin(TFT_BL, 1);
ledcWrite(1, 220);
// digitalWrite(TFT_BL, HIGH); //开启背光
delay(100);
SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, TFT_CS);
lcd_init();
return 1;
}
void TFT_GC9D01N_Class::backlight(uint8_t state)
{
ledcWrite(1, state);// digitalWrite(TFT_BL, state);
}
/**
* @brief Select the block area to write to 选择写的块区域
* @note
* @param Xstart:
* @param Xend:
* @param Ystart:
* @param Yend:
* @retval None
*/
void TFT_GC9D01N_Class::BlockWrite(unsigned int Xstart, unsigned int Xend, unsigned int Ystart, unsigned int Yend)
{
writecommand(0x2A);
writedata(Xstart >> 8);
writedata(Xstart);
writedata(Xend >> 8);
writedata(Xend);
writecommand(0x2B);
writedata(Ystart >> 8);
writedata(Ystart);
writedata(Yend >> 8);
writedata(Yend);
writecommand(0x2c);
}
/**
* @brief Drawing function
* @note
* @param Xstart: starting x-coordinate x坐标开始
* @param Ystart: starting y-coordinate y坐标结束
* @param w: The width of the image
* @param h: The height of the image
* @param color:
* @retval None
*/
void TFT_GC9D01N_Class::DrawImage(unsigned int Xstart, unsigned int Ystart, unsigned int w, unsigned int h, uint16_t *color)
{
unsigned int i, j;
unsigned int Xend = Xstart + w;
unsigned int Yend = Ystart + h;
BlockWrite(Xstart, Xend - 1, Ystart, Yend - 1);
uint32_t len = w * h;
#if LANDSCAPE
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
CS_L;
DC_D;
for (int i = 0; i <= h; i++) {
for (int j = w - 1 ; j >= 0 ; j--) {
SPI.transfer16(*(color + ((j * (Yend - Ystart)) + (i))));
}
}
CS_H;
SPI.endTransaction();
#else
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
CS_L;
DC_D;
for (int i = 0; i <= h; i++) {
for (int j = w - 1 ; j >= 0 ; j--) {
SPI.transfer16(*color);
color++;
}
}
CS_H;
SPI.endTransaction();
#endif
}
void TFT_GC9D01N_Class::DispColor(unsigned int Xstart, unsigned int Ystart, unsigned int Xend, unsigned int Yend, unsigned int color)
{
unsigned int i, j;
uint32_t len = TFT_HEIGHT * TFT_WIDTH;
BlockWrite(Xstart, Xend - 1, Ystart, Yend - 1);
SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));
CS_L;
DC_D;
for (i = 0; i <= TFT_HEIGHT; i++) {
for (j = 0; j < TFT_WIDTH; j++) {
SPI.transfer16(color);
}
}
CS_H;
SPI.endTransaction();
}
void TFT_GC9D01N_Class::WriteOneDot(unsigned int color)
{
CS_L;
DC_D;
writedata(color >> 8);
writedata(color);
CS_H;
}
unsigned char ToOrd( char ch)
{
if (ch < 32) {
ch = 95;
} else if ((ch >= 32) && (ch <= 47)) {
ch = (ch - 32) + 10 + 62;
} else if ((ch >= 48) && (ch <= 57)) {
ch = ch - 48;
} else if ((ch >= 58) && (ch <= 64)) {
ch = (ch - 58) + 10 + 62 + 16;
} else if ((ch >= 65) && (ch <= 126)) {
ch = (ch - 65) + 10;
} else if (ch > 126) {
ch = 95;
}
return ch;
}
void hz816_s90(const unsigned char *p_ucHz, unsigned char *p_ucResult) //A conversion function that rotates an 8x16 character font 90 degrees clockwise 把8x16字符字模顺时针旋转90度的转换函数
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char uiBuffer[16];
for (a = 0; a < 16; a++)
{
uiBuffer[a] = p_ucHz[a];
}
c = 0;
for (a = 0; a < 8; a++)
{
for (b = 0; b < 8; b++)
{
p_ucResult[c] = p_ucResult[c] << 1;
p_ucResult[c] = p_ucResult[c] & 0xfe;
if (uiBuffer[15 - b] >= 0x80)
{
p_ucResult[c] = p_ucResult[c] + 1;
}
uiBuffer[15 - b] = uiBuffer[15 - b] << 1;
}
c++;
for (b = 0; b < 8; b++)
{
p_ucResult[c] = p_ucResult[c] << 1;
p_ucResult[c] = p_ucResult[c] & 0xfe;
if (uiBuffer[7 - b] >= 0x80)
{
p_ucResult[c] = p_ucResult[c] + 1;
}
uiBuffer[7 - b] = uiBuffer[7 - b] << 1;
}
c++;
}
}
void hz816_s270(const unsigned char *p_ucHz, unsigned char *p_ucResult)
{
unsigned char a;
unsigned char b;
unsigned char c;
unsigned char uiBuffer[16];
for (a = 0; a < 16; a++)
{
uiBuffer[a] = p_ucHz[a];
}
c = 0;
for (a = 0; a < 8; a++)
{
for (b = 0; b < 8; b++)
{
p_ucResult[c] = p_ucResult[c] << 1;
if ((uiBuffer[b] & 0x01) >= 0x01)
{
p_ucResult[c] = p_ucResult[c] + 1;
}
uiBuffer[b] = uiBuffer[b] >> 1;
}
c++;
for (b = 0; b < 8; b++)
{
p_ucResult[c] = p_ucResult[c] << 1;
if ((uiBuffer[8 + b] & 0x01) >= 0x01)
{
p_ucResult[c] = p_ucResult[c] + 1;
}
uiBuffer[8 + b] = uiBuffer[8 + b] >> 1;
}
c++;
}
}
void TFT_GC9D01N_Class::DispOneChar( char ord, unsigned int Xstart, unsigned int Ystart, unsigned int TextColor, unsigned int BackColor) // ord:0~95
{
unsigned char hou[16] = {0};
unsigned char i, j;
unsigned char *p;
unsigned char dat;
unsigned int index;
index = ord;
if (index > 95)
index = 95;
index = index * ((FONT_W / 8) * FONT_H);
p = ascii;
p = p + index ;
#if LANDSCAPE
int y = Ystart;
y = y - 23;
Ystart = abs(y);
BlockWrite(Ystart, Ystart + (FONT_H - 1), Xstart, Xstart + (FONT_W - 1));
hz816_s90(p, hou);
for (i = 0; i < (FONT_W / 8 * FONT_H); i++) {
dat = hou[i];
for (j = 0; j < 8; j++) {
if ((dat << j) & 0x80) {
WriteOneDot(TextColor);
} else {
WriteOneDot(BackColor);
}
}
}
#else
BlockWrite(Xstart, Xstart + (FONT_W - 1), Ystart, Ystart + (FONT_H - 1));
for (i = 0; i < (FONT_W / 8 * FONT_H); i++) {
dat = *p++;
for (j = 0; j < 8; j++) {
if ((dat << j) & 0x80) {
WriteOneDot(TextColor);
} else {
WriteOneDot(BackColor);
}
}
}
#endif
}
void TFT_GC9D01N_Class::DispStr( char *str, unsigned int Xstart, unsigned int Ystart, unsigned int TextColor, unsigned int BackColor)
{
while (!(*str == '\0')) {
DispOneChar(ToOrd(*str++), Xstart, Ystart, TextColor, BackColor);
#if LANDSCAPE
if (Xstart > ((TFT_HEIGHT - 1) - FONT_W)) {
//Xstart = 0;
//Ystart = Ystart - FONT_H;
} else {
Xstart = Xstart + FONT_W;
}
if (Ystart > ((TFT_WIDTH - 1) - FONT_H)) {
Ystart = 23;
}
#else
if (Xstart > ((TFT_WIDTH - 1) - FONT_W)) {
Xstart = 0;
Ystart = Ystart + FONT_H;
} else {
Xstart = Xstart + FONT_W;
}
if (Ystart > ((TFT_HEIGHT - 1) - FONT_H)) {
Ystart = 0;
}
#endif
}
BlockWrite(0, TFT_WIDTH - 1, 0, TFT_HEIGHT - 1);
}