480 lines
13 KiB
C++
480 lines
13 KiB
C++
#include "tft.h"
|
|
#include "ascii_font.h"
|
|
|
|
|
|
#ifdef HZK_FONT
|
|
#include "font_chuc.h"
|
|
#endif
|
|
|
|
#ifdef TFT_ST7735
|
|
#include "ST7735.h"
|
|
#endif
|
|
|
|
#ifdef TFT_ST7796
|
|
#include "ST7796.h"
|
|
#endif
|
|
|
|
const uint8_t initcmd[] = {0};
|
|
TFT_Color_t POINT_COLOR;
|
|
TFT_Color_t BACK_COLOR;
|
|
uint8_t *cmdIndex;
|
|
void TFT_Init(TFT_T *dev) {
|
|
if(dev == NULL)
|
|
{
|
|
return;
|
|
}
|
|
uint8_t count, temp;
|
|
cmdIndex = (uint8_t *) initcmd;
|
|
#ifdef TFT_ST7735
|
|
if (dev->id==ST7735_ID) {
|
|
cmdIndex= (uint8_t *) st7735initcmd;
|
|
dev->setxcmd = ST7735_CASET;
|
|
dev->setycmd = ST7735_RASET;
|
|
dev->wgramcmd = ST7735_WRITE_RAM;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TFT_ST7735
|
|
if (dev->id==ST7796_ID) {
|
|
cmdIndex= (uint8_t *) st7796initcmd;
|
|
dev->setxcmd = ST7796_CASET;
|
|
dev->setycmd = ST7796_RASET;
|
|
dev->wgramcmd = ST7796_WRITE_RAM;
|
|
}
|
|
#endif
|
|
while (*cmdIndex) {
|
|
temp = *cmdIndex++;
|
|
count = temp & 0x7F;
|
|
dev->writeReg(*cmdIndex,cmdIndex + 1, count - 1);
|
|
cmdIndex += count;
|
|
|
|
if (0x81 == temp) {
|
|
dev->delay(150);
|
|
}
|
|
}
|
|
TFT_SetDir(dev,dev->dir);
|
|
}
|
|
|
|
uint32_t TFT_ReadID(TFT_T *dev) {
|
|
uint32_t id = 0;
|
|
#ifdef TFT_ST7735
|
|
ST7735_ReadID(dev, id);
|
|
#endif
|
|
|
|
#ifdef TFT_ST7796
|
|
ST7796_ReadID(dev, id);
|
|
#endif
|
|
return id;
|
|
}
|
|
|
|
void TFT_SetDir(TFT_T *dev, TFT_DIR_T dir) {
|
|
uint8_t tmp;
|
|
#ifdef TFT_ST7735
|
|
ST7735_SetDir(dev, dir);
|
|
#endif
|
|
#ifdef TFT_ST7796
|
|
ST7796_SetDir(dev, dir);
|
|
#endif
|
|
}
|
|
|
|
void TFT_SetCur(TFT_T *dev, uint16_t x, uint16_t y) {
|
|
#ifdef TFT_ST7735
|
|
ST7735_OFFSET(dev,x,y);
|
|
#endif
|
|
|
|
#ifdef TFT_ST7796
|
|
ST7796_OFFSET(dev,x,y);
|
|
#endif
|
|
uint8_t tmp[2];
|
|
tmp[0] = x >> 8U;
|
|
tmp[1] = x & 0xFFU;
|
|
dev->writeReg(dev->setxcmd,tmp, 2);
|
|
|
|
tmp[0] = y >> 8U;
|
|
tmp[1] = y & 0xFFU;
|
|
dev->writeReg(dev->setycmd,tmp, 2);
|
|
|
|
tmp[0] = 0;
|
|
dev->writeReg(dev->wgramcmd,tmp,0);
|
|
}
|
|
|
|
void TFT_SetColor(uint16_t pcolor,uint16_t bcolor){
|
|
POINT_COLOR.color=pcolor;
|
|
BACK_COLOR.color=bcolor;
|
|
}
|
|
|
|
void TFT_SetWindow(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height) {
|
|
#ifdef TFT_ST7735
|
|
ST7735_OFFSET(dev,x,y);
|
|
#endif
|
|
|
|
#ifdef TFT_ST7796
|
|
ST7796_OFFSET(dev,x,y);
|
|
#endif
|
|
uint8_t tmp[4];
|
|
tmp[0] = x >> 8U;
|
|
tmp[1] = x & 0xFFU;
|
|
tmp[2] = (x + width - 1) >> 8U;
|
|
tmp[3] = (x + width - 1) & 0xFFU;
|
|
dev->writeReg(dev->setxcmd,tmp, 4);
|
|
|
|
tmp[0] = y >> 8U;
|
|
tmp[1] = y & 0xFFU;
|
|
tmp[2] = (y + height - 1) >> 8U;
|
|
tmp[3] = (y + height - 1) & 0xFFU;
|
|
dev->writeReg(dev->setycmd,tmp, 4);
|
|
|
|
tmp[0] = 0;
|
|
dev->writeReg(dev->wgramcmd,tmp,0);
|
|
}
|
|
|
|
TFT_Color_t TFT_GetPixel(TFT_T *dev,uint16_t x, uint16_t y){
|
|
uint8_t pixel_lsb, pixel_msb;
|
|
uint8_t tmp;
|
|
TFT_Color_t rec;
|
|
rec.color=0;
|
|
/* Set Cursor */
|
|
TFT_SetCur(dev,x,y);
|
|
#ifdef TFT_ST7735
|
|
ST7735_ReadRam(dev,rec);
|
|
#endif
|
|
|
|
#ifdef TFT_ST7796
|
|
ST7796_ReadRam(dev,rec);
|
|
#endif
|
|
return rec;
|
|
}
|
|
|
|
void TFT_SetPixel(TFT_T *dev,uint16_t x, uint16_t y,TFT_Color_t color){
|
|
if((x>=dev->width) || (y >= dev->height)){ return;}
|
|
TFT_SetCur(dev,x,y);
|
|
dev->sendData(color.u8, 2);
|
|
}
|
|
|
|
void TFT_SetBacklight(TFT_T *dev,uint8_t value){
|
|
dev->blacklight(value);
|
|
}
|
|
|
|
void TFT_DrawHLineColor(TFT_T *dev, uint16_t x, uint16_t y, uint16_t len,TFT_Color_t *color){
|
|
if(x+len>dev->width)return;
|
|
TFT_SetCur(dev,x,y);
|
|
dev->sendData(color->u8,len*2);
|
|
}
|
|
|
|
void TFT_FillRect(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height,TFT_Color_t *color){
|
|
if(x+width>dev->width||y+height>dev->height)return;
|
|
uint32_t i;
|
|
TFT_SetWindow(dev,x,y,width,height);
|
|
for (i = 0; i < height; ++i) {
|
|
TFT_DrawHLineColor(dev,x,y+i,width,color);
|
|
color+=width;
|
|
}
|
|
// dev->sendData(color->u8, size*2);
|
|
}
|
|
|
|
void TFT_DrawHLine(TFT_T *dev, uint16_t x, uint16_t y, uint16_t len,TFT_Color_t color){
|
|
uint16_t i;
|
|
uint8_t pdata[dev->width*2];
|
|
if(x+len>dev->width)return;
|
|
TFT_SetCur(dev,x,y);
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
/* Exchange LSB and MSB to fit LCD specification */
|
|
pdata[2U*i] = color.u8[0];
|
|
pdata[(2U*i) + 1U] = color.u8[1];
|
|
// pdata[(2U*i) + 1U] = (uint8_t)(Color >> 8);
|
|
// pdata[2U*i] = (uint8_t)(Color);
|
|
}
|
|
dev->sendData(pdata,len*2);
|
|
}
|
|
|
|
void TFT_Fill(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height,TFT_Color_t color){
|
|
if(x+width>dev->width||y+height>dev->height)return;
|
|
uint32_t i;
|
|
TFT_SetWindow(dev,x,y,width,height);
|
|
for (i=0;i<height;i++){
|
|
TFT_DrawHLine(dev,x,y+i,width,color);
|
|
}
|
|
}
|
|
|
|
void TFT_FillColor(TFT_T *dev,TFT_Color_t color){
|
|
dev->sendData(color.u8, 2);
|
|
}
|
|
|
|
|
|
|
|
void TFT_DrawLine(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
|
|
uint16_t i, k, k1, k2;
|
|
if ((x1 < 0) || (x2 > dev->width) || (y1 < 0) || (y2 > dev->height) || (x1 > x2) || (y1 > y2))return;
|
|
if (x1 == x2) //画竖线
|
|
{
|
|
for (i = 0; i < (y2 - y1); i++) {
|
|
TFT_SetPixel(dev, x1, y1 + i,POINT_COLOR);
|
|
}
|
|
} else if (y1 == y2) //画横线
|
|
{
|
|
for (i = 0; i < (x2 - x1); i++) {
|
|
TFT_SetPixel(dev, x1 + i, y1,POINT_COLOR);
|
|
}
|
|
} else //画斜线
|
|
{
|
|
k1 = y2 - y1;
|
|
k2 = x2 - x1;
|
|
k = k1 * 10 / k2;
|
|
for (i = 0; i < (x2 - x1); i++) {
|
|
TFT_SetPixel(dev, x1 + i, y1 + i * k / 10,POINT_COLOR);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TFT_DrawRect(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
|
|
TFT_DrawLine(dev, x1, y1, x2, y1); // Top side
|
|
TFT_DrawLine(dev, x1, y1, x1, y2); // Left side
|
|
TFT_DrawLine(dev, x2, y1, x2, y2); // Right side
|
|
TFT_DrawLine(dev, x1, y2, x2, y2); // Bottom side
|
|
}
|
|
|
|
void TFT_DrawCircle(TFT_T *dev, uint16_t x, uint16_t y, uint16_t r) {
|
|
int a, b, num;
|
|
a = 0;
|
|
b = r;
|
|
while (2 * b * b >= r * r) {
|
|
TFT_SetPixel(dev, x + a, y - b,POINT_COLOR);
|
|
TFT_SetPixel(dev, x - a, y - b,POINT_COLOR);
|
|
TFT_SetPixel(dev, x - a, y + b,POINT_COLOR);
|
|
TFT_SetPixel(dev, x + a, y + b,POINT_COLOR);
|
|
TFT_SetPixel(dev, x + b, y + a,POINT_COLOR);
|
|
TFT_SetPixel(dev, x + b, y - a,POINT_COLOR);
|
|
TFT_SetPixel(dev, x - b, y - a,POINT_COLOR);
|
|
TFT_SetPixel(dev, x - b, y + a,POINT_COLOR);
|
|
|
|
a++;
|
|
num = (a * a + b * b) - r * r;//计算画的点离圆心的距离
|
|
if (num > 0) {
|
|
b--;
|
|
a--;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TFT_ShowChar(TFT_T *dev, uint16_t x, uint16_t y, uint8_t chr, uint16_t size,bool mode) {
|
|
uint16_t i, m, temp, size2, chr1;
|
|
uint16_t ys = y;
|
|
size2 = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2); //得到字体一个字符对应点阵集所占的字节数
|
|
chr1 = chr - ' '; //计算偏移后的值
|
|
for (i = 0; i < size2; i++) {
|
|
if (size == 12) { temp = asc2_1206[chr1][i]; } //调用1206字体
|
|
else if (size == 16) { temp = asc2_1608[chr1][i]; } //调用1608字体
|
|
else if (size == 24) { temp = asc2_2412[chr1][i]; } //调用2412字体
|
|
else return;
|
|
for (m = 0; m < 8; m++) //写入数据
|
|
{
|
|
if (temp & 0x80)TFT_SetPixel(dev, x, ys,POINT_COLOR);
|
|
else if(!mode) TFT_SetPixel(dev, x, ys,BACK_COLOR);
|
|
temp <<= 1;
|
|
ys++;
|
|
if ((ys - y) == size) {
|
|
ys = y;
|
|
x++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TFT_ShowString(TFT_T *dev, uint16_t x, uint16_t y, uint8_t *str, uint16_t size,bool mode) {
|
|
while ((*str >= ' ') && (*str <= '~'))//判断是不是非法字符!
|
|
{
|
|
TFT_ShowChar(dev, x, y, *str, size,mode);
|
|
x += size / 2;
|
|
if (x > dev->width - size) //换行
|
|
{
|
|
x = 0;
|
|
y += size;
|
|
}
|
|
str++;
|
|
}
|
|
}
|
|
#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit)
|
|
|
|
void TFT_HBSet(TFT_T *dev, uint8_t x, uint8_t y, uint8_t data, bool mode) {
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
if(GET_BIT(data, i)){
|
|
TFT_SetPixel(dev, x + 7 - i, y, POINT_COLOR);
|
|
} else if(!mode){
|
|
TFT_SetPixel(dev, x + 7 - i, y, BACK_COLOR);
|
|
}
|
|
}
|
|
}
|
|
#ifdef HZK_FONT
|
|
|
|
void TFT_ShowCHChr(TFT_T *dev, uint8_t x, uint8_t y, Chinese_t *hzk, bool mode) {
|
|
uint8_t ziku_bytes = ((Hzk_size + 7) / 8 * 8) / 8;
|
|
for (uint8_t i = 0, ziku_byte_n = 0, size2 = Hzk_size * ziku_bytes; i < size2; i++) {
|
|
TFT_HBSet(dev, x + ziku_byte_n * 8, y, hzk->data[i], mode);
|
|
if (++ziku_byte_n >= ziku_bytes) {
|
|
ziku_byte_n = 0;
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
#ifdef UTF8_TO_UNICODE
|
|
|
|
#include "font_t.h"
|
|
|
|
#define GET_LOW_BYTE0(x) ((x >> 0) & 0x000000ff) /* 获取第0个字节 */
|
|
#define GET_LOW_BYTE1(x) ((x >> 8) & 0x000000ff) /* 获取第1个字节 */
|
|
|
|
void TFT_ShowCHString(TFT_T *dev, uint16_t x, uint16_t y, uint8_t *str,bool mode) {
|
|
uint32_t unicode_letter;
|
|
uint16_t step;
|
|
while (*str != '\0') {
|
|
bool found = false;
|
|
step = Font_utf8_to_unicode(str, &unicode_letter);
|
|
if (step != 0) {
|
|
Chinese_t *hzk = find_chinese_data(GET_LOW_BYTE1(unicode_letter), GET_LOW_BYTE0(unicode_letter));
|
|
if(hzk!=NULL){
|
|
TFT_ShowCHChr(dev, x, y, hzk, mode);
|
|
x += Hzk_size;
|
|
str += step;
|
|
found = true;
|
|
}
|
|
}
|
|
if (!found) {
|
|
TFT_ShowChar(dev, x, y, *str, Hzk_size,1);
|
|
x += Hzk_size / 2;
|
|
str++;
|
|
}
|
|
if (x > dev->width - Hzk_size) {
|
|
x = 0;
|
|
y += Hzk_size;
|
|
}
|
|
}
|
|
}
|
|
|
|
#else
|
|
void TFT_ShowCHString(TFT_T *dev, uint16_t x, uint16_t y, uint8_t *str,bool mode) {
|
|
uint16_t index;
|
|
while (*str != '\0') {
|
|
bool found = false;
|
|
for (index = 0; index < sizeof(Hzk) / sizeof(Chinese_t); index++) {
|
|
if (Hzk[index].unicode[0] == str[0] && Hzk[index].unicode[1] == str[1]) // 对比汉字区码位码
|
|
{
|
|
TFT_ShowCHChr(dev, x, y, &Hzk[index],mode);
|
|
x += Hzk_size;
|
|
str++;
|
|
str++;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
TFT_ShowChar(dev, x, y, *str, Hzk_size,mode);
|
|
x += Hzk_size / 2;
|
|
str++;
|
|
}
|
|
if (x > dev->width - Hzk_size) {
|
|
x = 0;
|
|
y += Hzk_size;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
#ifdef LVGL_FONT
|
|
#include "font.h"
|
|
void draw_rect(Font_f_t *fd, uint16_t *data, size_t len) {
|
|
TFT_T *dev=(TFT_T*)fd->dev;
|
|
TFT_Color_t tmp;
|
|
TFT_SetCur(dev,fd->x,fd->y);
|
|
while (len--){
|
|
tmp.color=*data;
|
|
TFT_FillColor(dev,tmp);
|
|
data++;
|
|
}
|
|
}
|
|
|
|
void TFT_DisplayString(TFT_T *dev, const lv_font_t *font, uint8_t *s, uint16_t x, uint16_t y,bool mode) {
|
|
uint32_t unicode_letter;
|
|
Font_f_t fd = {.dev=dev, .dev_w=dev->width, .show=draw_rect};
|
|
while (*s) {
|
|
if (font) {
|
|
s += Font_utf8_to_unicode(s, &unicode_letter);
|
|
x += Font_draw_letter(font, &fd, unicode_letter, x, y);
|
|
x += 0; //字间距
|
|
} else {
|
|
TFT_ShowChar(dev, x, y, *s, 12,mode);
|
|
x += 12;
|
|
s++;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
uint32_t TFT_Pow(uint16_t m, uint16_t n) {
|
|
uint32_t result = 1;
|
|
while (n--) {
|
|
result *= m;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void TFT_ShowNum(TFT_T *dev, uint16_t x, uint16_t y, uint32_t num, uint16_t len, uint8_t size1) {
|
|
uint16_t t, temp;
|
|
for (t = 0; t < len; t++) {
|
|
temp = (num / TFT_Pow(10, len - t - 1)) % 10;
|
|
if (temp == 0) {
|
|
TFT_ShowChar(dev, x + (size1 / 2) * t, y, '0', size1,1);
|
|
} else {
|
|
TFT_ShowChar(dev, x + (size1 / 2) * t, y, temp + '0', size1,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TFT_ShowPic(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, TFT_Color_t *bmp) {
|
|
if(x+width>dev->width||y+height>dev->height)return;
|
|
uint32_t j;
|
|
for(j = 0; j < height; j++)
|
|
{
|
|
TFT_DrawHLineColor(dev,x,y+j,width, bmp);
|
|
bmp+=width;
|
|
}
|
|
}
|
|
|
|
void TFT_DrawCross(TFT_T *dev, uint16_t x, uint16_t y, uint8_t r) {
|
|
TFT_DrawLine(dev, x - r, y, x + r, y);
|
|
TFT_DrawLine(dev, x, y - r, x, y + r);
|
|
}
|
|
|
|
uint16_t invertRGB565(uint16_t color) {
|
|
// 分离颜色分量
|
|
uint8_t r = (color >> 11) & 0x1F; // 取出红色分量
|
|
uint8_t g = (color >> 5) & 0x3F; // 取出绿色分量
|
|
uint8_t b = color & 0x1F; // 取出蓝色分量
|
|
|
|
// 取反颜色分量
|
|
r = 31 - r;
|
|
g = 63 - g;
|
|
b = 31 - b;
|
|
|
|
// 重新组合颜色分量
|
|
return (r << 11) | (g << 5) | b;
|
|
}
|
|
|
|
void TFT_ShowBar(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, float progress) {
|
|
if (x + width > dev->width || y + height > dev->height || progress > 1)return;
|
|
uint16_t xp = (width - x) * progress;
|
|
TFT_Fill(dev, x, y, xp, height, POINT_COLOR);
|
|
if (progress < 1)TFT_Fill(dev, xp, y, width, height, BACK_COLOR);
|
|
if (height >= 12 && height < 32) {
|
|
uint8_t tmp[7];
|
|
uint16_t sp = (width - x) / 2 - 3 * ((height >= 24) ? 24 : (height >= 16) ? 16 : 12) / 2;
|
|
TFT_Color_t temp = POINT_COLOR;
|
|
POINT_COLOR.u16 = invertRGB565(POINT_COLOR.u16);
|
|
sprintf((char *) tmp, "%05.2f%%", progress * 100);
|
|
if (xp < sp)TFT_ShowString(dev, sp, y, tmp, (height >= 24) ? 24 : (height >= 16) ? 16 : 12, 0);
|
|
else TFT_ShowString(dev, sp, y, tmp, (height >= 24) ? 24 : (height >= 16) ? 16 : 12, 1);
|
|
POINT_COLOR = temp;
|
|
}
|
|
}
|