#include "display_ch.h" //#define _ASC16_ //#define _HZK16_ DisplayCh::DisplayCh(){ // Set default highlight color highlightcolor = RED; highlighted = false; // HZK16 is not used by default hzk16Used = false; hzk16Type = DontUsedHzk16; //pHzk16File = nullptr; //pAsc16File = nullptr; textwrap = true; _width = 320; _height = 240; } /*************************************************************************************** ** Function name: setTextWrap ** Description: Define if text should wrap at end of line ***************************************************************************************/ void DisplayCh::setTextWrap(boolean w) { textwrap = w; } /*************************************************************************************** ** Function name: setTextSize ** Description: Set the text size multiplier ***************************************************************************************/ void DisplayCh::setTextSize(uint8_t s) { if (s > 7) s = 7; // Limit the maximum size multiplier so byte variables can be used // for rendering textsize = (s > 0) ? s : 1; // Don't allow font size 0 // Calculate the text width and height. // It's 8 pixels wide and 16 pixels high in for ASCII characters, // and 16 pixels both wide and high for GBK characters in HZK16 mode. ascCharWidth = 8 * textsize; ascCharHeigth = 16 * textsize; gbkCharWidth = ascCharHeigth; gbkCharHeight = gbkCharWidth; } /*************************************************************************************** ** Function name: setCursor ** Description: Set the text cursor x,y position ***************************************************************************************/ void DisplayCh::setCursor(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; } /*************************************************************************************** ** Function name: setCursor ** Description: Set the text cursor x,y position and font ***************************************************************************************/ void DisplayCh::setCursor(int16_t x, int16_t y, uint8_t font) { textfont = font; cursor_x = x; cursor_y = y; } /*************************************************************************************** ** Function name: setTextColor ** Description: Set the font foreground colour (background is *transparent) ***************************************************************************************/ void DisplayCh::setTextColor(uint16_t c) { // For 'transparent' background, we'll set the bg // to the same as fg instead of using a flag textcolor = textbgcolor = c; } /*************************************************************************************** ** Function name: fillScreen ** Description: Clear the screen to defined colour ***************************************************************************************/ void DisplayCh::fillScreen(uint32_t color) { M5.Lcd.fillRect(0, 0, _width, _height, color); } /*************************************************************************************** ** Function name: setTextColor ** Description: Set the font foreground and background colour ***************************************************************************************/ void DisplayCh::setTextColor(uint16_t c, uint16_t b) { textcolor = c; textbgcolor = b; } /*************************************************************************************** ** Function name: loadHzk16 ** Description: loadHzk16 fonts ** Params: ** HZK16Path: HZK16 file path on TF card. e.g. /HZK16, means file on the *root dir of TF card. * ASC16Path: ASC16 file path on TF card. ***************************************************************************************/ void DisplayCh::loadHzk16(Hzk16Types hzkTypes,const char *HZK16Path, const char *ASC16Path) { if (hzk16Used) return; //Hzk16Types hzkTypes = InternalHzk16 if(hzkTypes == InternalHzk16){ //#if defined(_ASC16_) && defined(_HZK16_) pAscCharMatrix = (uint8_t *)&ASC16[0]; pGbkCharMatrix = (uint8_t *)&HZK16[0]; Serial.println("HZK16 path: Internal"); Serial.println("ASC16 path: Internal"); hzk16Used = initHzk16(true, nullptr, nullptr); } else { pAscCharMatrix = NULL; pGbkCharMatrix = NULL; Serial.print("HZK16 path: /SD"); Serial.println(HZK16Path); Serial.print("ASC16 path: /SD"); Serial.println(ASC16Path); hzk16Used = initHzk16(true, HZK16Path, ASC16Path); } Serial.print("HZK16 init result: "); Serial.println(isHzk16Used()); } /*************************************************************************************** ** Function name: disableHzk16 ** Description: disable Hzk16 fonts ** Params: ***************************************************************************************/ void DisplayCh::disableHzk16() { if (hzk16Used) { hzk16Used = initHzk16(false); } } bool DisplayCh::initHzk16(boolean use, const char *HZK16Path, const char *ASC16Path) { bool result = false; if (use == false) { // Do not use HZK16 and ASC16 fonts hzk16Type = DontUsedHzk16; Serial.println("Use default font."); } else if (pAscCharMatrix == NULL || pGbkCharMatrix == NULL) { // Use external HZK16 and ASC16 font on TF card. // Check if HZK16 and ASC16 files exist on TF card. if (SD.exists(HZK16Path) && SD.exists(ASC16Path)) { // Exists hzk16Type = ExternalHzk16; Serial.println("Use external HZK16 and ASC16 font."); } else { // Not exists hzk16Type = DontUsedHzk16; Serial.println("External font file HZK16/ASC16 lost, use default font."); } } else { // Use internal HZK16 and ASC16 fonts hzk16Type = InternalHzk16; Serial.println("Use internal HZK16 and ASC16 font."); } switch (hzk16Type) { case ExternalHzk16: { if (pHzk16File == NULL) { Hzk16File = SD.open(HZK16Path); pHzk16File = &Hzk16File; } if (pAsc16File == NULL) { Asc16File = SD.open(ASC16Path); pAsc16File = &Asc16File; } hzkBufCount = 0; break; } case InternalHzk16: { if (pAscCharMatrix == NULL || pGbkCharMatrix == NULL) { hzk16Type = DontUsedHzk16; } if (pHzk16File != NULL) { pHzk16File->close(); pHzk16File = NULL; } if (pAsc16File != NULL) { pAsc16File->close(); pAsc16File = NULL; } hzkBufCount = 0; break; } case DontUsedHzk16: { if (pHzk16File != NULL) { pHzk16File->close(); pHzk16File = NULL; } if (pAsc16File != NULL) { pAsc16File->close(); pAsc16File = NULL; } break; } } return hzk16Type != DontUsedHzk16; } void DisplayCh::writeHzkAsc(const char c) { if (c == '\n') { cursor_x = 0; cursor_y += ascCharHeigth; } else if (c != '\r') { uint32_t offset; uint8_t mask; uint16_t posX = cursor_x, posY = cursor_y; uint8_t charMatrix[16]; uint8_t *pCharMatrix; offset = (uint32_t)c * 16; if (hzk16Type == ExternalHzk16) { pAsc16File->seek(offset, SeekSet); pAsc16File->readBytes((char *)&charMatrix[0], 16); pCharMatrix = &charMatrix[0]; } else { if (pAscCharMatrix == NULL) { return; } pCharMatrix = pAscCharMatrix + offset; } // startWrite(); if (highlighted) { M5.Lcd.fillRect(cursor_x, cursor_y, ascCharWidth, ascCharHeigth, highlightcolor); } else if (istransparent == false) { M5.Lcd.fillRect(cursor_x, cursor_y, ascCharWidth, ascCharHeigth, textbgcolor); } for (uint8_t row = 0; row < 16; row++) { mask = 0x80; posX = cursor_x; for (uint8_t col = 0; col < 8; col++) { if ((*pCharMatrix & mask) != 0) { if (textsize == 1) { M5.Lcd.drawPixel(posX, posY, textcolor); } else { M5.Lcd.fillRect(posX, posY, textsize, textsize, textcolor); } } posX += textsize; mask >>= 1; } posY += textsize; pCharMatrix++; } // endWrite(); cursor_x += ascCharWidth; if (textwrap && ((cursor_x + ascCharWidth) > _width)) { cursor_x = 0; cursor_y += ascCharHeigth; } } } void DisplayCh::writeHzk(char* c){ char *ret = c; if(ret == NULL) return; while(*ret != '\0'){ while(*ret <= 0xA0){ if(*ret == '\0') return; writeHzkAsc(*ret); ret++; } writeHzkGbk(ret); ret++; ret++; } } void DisplayCh::writeHzkGbk(const char *c) { uint32_t offset; uint8_t mask; uint16_t posX = cursor_x, posY = cursor_y; uint8_t charMatrix[32]; uint8_t *pCharMatrix; offset = (uint32_t)(94 * (uint32_t)(c[0] - 0xA1) + (uint32_t)(c[1] - 0xA1)) * 32; if (hzk16Type == ExternalHzk16) { pHzk16File->seek(offset, SeekSet); pHzk16File->readBytes((char *)&charMatrix[0], 32); pCharMatrix = &charMatrix[0]; } else { if (pGbkCharMatrix == NULL) { return; } pCharMatrix = pGbkCharMatrix + offset; } // startWrite(); if (highlighted) { M5.Lcd.fillRect(cursor_x, cursor_y, gbkCharWidth, gbkCharHeight, highlightcolor); } else if (istransparent == false) { M5.Lcd.fillRect(cursor_x, cursor_y, gbkCharWidth, gbkCharHeight, textbgcolor); } for (uint8_t row = 0; row < 16; row++) { posX = cursor_x; mask = 0x80; for (uint8_t col = 0; col < 8; col++) { if ((*pCharMatrix & mask) != 0) { if (textsize == 1) { M5.Lcd.drawPixel(posX, posY, textcolor); } else { M5.Lcd.fillRect(posX, posY, textsize, textsize, textcolor); } } if ((*(pCharMatrix + 1) & mask) != 0) { if (textsize == 1) { M5.Lcd.drawPixel(posX + ascCharWidth, posY, textcolor); } else { M5.Lcd.fillRect(posX + ascCharWidth, posY, textsize, textsize, textcolor); } } mask >>= 1; posX += textsize; } posY += textsize; pCharMatrix += 2; } // endWrite(); cursor_x += gbkCharWidth; if (textwrap && ((cursor_x + gbkCharWidth) > _width)) { cursor_x = 0; cursor_y += gbkCharHeight; } }