HW_Lib/lib/tft/tft.cpp

608 lines
17 KiB
C++

#include <valarray>
#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);
}
#define swap_(a, b) (a=(a)+(b),b=(a)-(b),a=(a)-(b))
void TFT_DrawLine(TFT_T *dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
uint16_t i;
if ((x1 < 0) || (x2 > dev->width) || (y1 < 0) || (y2 > dev->height))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 //画斜线
{//Bresenham算法
int p, twoDy, twoDyMinusDx, s1, s2;
int dx = abs(x2 - x1), dy = abs(y2 - y1);
if (dy > dx) //斜率大于1
{
p = 2 * dx - dy;
twoDy = 2 * dx;
twoDyMinusDx = 2 * (dx - dy);
if (y1 > y2)//斜率为负时 反转斜率
{
swap_(x1, x2);
swap_(y1, y2);
}
s1 = x2 > x1 ? 1 : -1;
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
while (y1 < y2) {
y1++;
if (p < 0) { p += twoDy; }
else {
x1 += s1;
p += twoDyMinusDx;
}
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
}
} else {
p = 2 * dy - dx;
twoDy = 2 * dy;
twoDyMinusDx = 2 * (dy - dx);
if (x1 > x2)//斜率为负时 反转斜率
{
swap_(x1, x2);
swap_(y1, y2);
}
s2 = y2 > y1 ? 1 : -1;
TFT_SetPixel(dev, x1, y1, POINT_COLOR);
while (x1 < x2) {
x1++;
if (p < 0) { p += twoDy; }
else {
y1 += s2;
p += twoDyMinusDx;
}
TFT_SetPixel(dev, x1, y1, 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 x0, uint16_t y0, uint16_t radius) {
int x = radius;
int y = 0;
int decision = 1 - x;
while (y <= x) {
TFT_SetPixel(dev, x0 + x, y0 + y, POINT_COLOR);
TFT_SetPixel(dev, x0 + y, y0 + x, POINT_COLOR);
TFT_SetPixel(dev, x0 - y, y0 + x, POINT_COLOR);
TFT_SetPixel(dev, x0 - x, y0 + y, POINT_COLOR);
TFT_SetPixel(dev, x0 - x, y0 - y, POINT_COLOR);
TFT_SetPixel(dev, x0 - y, y0 - x, POINT_COLOR);
TFT_SetPixel(dev, x0 + y, y0 - x, POINT_COLOR);
TFT_SetPixel(dev, x0 + x, y0 - y, POINT_COLOR);
y++;
if (decision <= 0) {
decision += 2 * y + 1;
} else {
x--;
decision += 2 * (y - x) + 1;
}
}
}
#define PI 3.14159265359
#define PI 3.14159265359
//void TFT_DrawArc(TFT_T *dev, uint16_t x0, uint16_t y0, uint16_t radius, int start_angle, int end_angle) {
// int x = radius;
// int y = 0;
// int decision = 1 - x;
// int change = 4 * (1 - x);
//
// int angle = start_angle;
//
// while (y <= x) {
// if (angle >= start_angle && angle <= end_angle) {
// TFT_SetPixel(dev, x0 + x, y0 + y, POINT_COLOR);
// TFT_SetPixel(dev, x0 + y, y0 + x, POINT_COLOR);
// TFT_SetPixel(dev, x0 - y, y0 + x, POINT_COLOR);
// TFT_SetPixel(dev, x0 - x, y0 + y, POINT_COLOR);
// TFT_SetPixel(dev, x0 - x, y0 - y, POINT_COLOR);
// TFT_SetPixel(dev, x0 - y, y0 - x, POINT_COLOR);
// TFT_SetPixel(dev, x0 + y, y0 - x, POINT_COLOR);
// TFT_SetPixel(dev, x0 + x, y0 - y, POINT_COLOR);
// }
//
// if (decision <= 0) {
// decision += 2 * y + 1;
// change += 2;
// } else {
// x--;
// decision += 2 * (y - x) + 1;
// change += 4 * ((y - x) + 1);
// }
//
// y++;
// angle = (int)(0.5 + (atan((double)y / x) * 180.0 / PI));
// }
//}
#define PI 3.14159265359
void TFT_DrawArc(TFT_T *dev, uint16_t x, uint16_t y, uint16_t radius, int start_angle, int end_angle) {
// 修复输入角度范围
if (start_angle < 0) {
start_angle = 0;
} else if (start_angle > 360) {
start_angle = 360;
}
if (end_angle < 0) {
end_angle = 0;
} else if (end_angle > 360) {
end_angle = 360;
}
double angle;
unsigned int cirx, ciry, lastX, lastY;
cirx = x;
ciry = y;
angle = start_angle;
while (angle <= end_angle) {
lastX = cirx + radius * sin(angle * PI / 180);
lastY = ciry - radius * cos(angle * PI / 180);
TFT_SetPixel(dev, lastX, lastY, POINT_COLOR);
angle = angle + 0.1;
}
}
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);
}
void TFT_DrawXCross(TFT_T *dev, uint16_t x, uint16_t y, uint8_t r) {
TFT_DrawLine(dev, x - r, y - r, x + r, y + r);
TFT_DrawLine(dev, x - r, y + r, x + r, y - r);
}
void TFT_DrawRoundedRect(TFT_T *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t radius) {
// 画四条直线
TFT_DrawLine(dev, x + radius, y, x + width - radius, y); // 上方横线
TFT_DrawLine(dev, x + radius, y + height, x + width - radius, y + height); // 下方横线
TFT_DrawLine(dev, x, y + radius, x, y + height - radius); // 左侧竖线
TFT_DrawLine(dev, x + width, y + radius, x + width, y + height - radius); // 右侧竖线
// 画四个圆角
TFT_DrawArc(dev, x + radius, y + radius, radius, 270, 360); // 左上角
TFT_DrawArc(dev, x + width - radius, y + radius, radius, 0, 90); // 右上角
TFT_DrawArc(dev, x + width - radius, y + height - radius, radius, 90, 180); // 右下角
TFT_DrawArc(dev, x + radius, y + height - radius, radius, 180, 270); // 左下角
}
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;
}
}