#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; } }