#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
extern int print_unicode(uint16_t unicode);
uint8_t utf8_msg[] = "由沙子制成的城堡最竟落入海中"
;
uint8_t utf8_fail[] = "由沙子製成的城堡最終落入海中"
;
uint8_t utf8_duff[] = "屁股今天比昨天便宜便宜"
;
uint8_t utf8_veter72[] = "Test (Ceshi):测试Settings (Shezhi):设置"
;
uint16_t unicode_msg[] = {
0x7531, 0x6c99, 0x5b50, 0x5236, 0x6210, 0x7684, 0x57ce, 0x5821,
0x6700, 0x7adf, 0x843d, 0x5165, 0x6d77, 0x4e2d,
};
typedef struct {
uint16_t code;
uint16_t bits[16];
} font_table_t;
const font_table_t table[] PROGMEM = {
{ 0x7531, {0x0100, 0x0100, 0x0100, 0x0100, 0x3FF8, 0x2108, 0x2108, 0x2108, 0x2108, 0x3FF8, 0x2108, 0x2108, 0x2108, 0x2108, 0x3FF8, 0x2008, } },
{ 0x6C99, {0x0040, 0x2040, 0x1040, 0x1148, 0x8144, 0x4242, 0x4242, 0x1448, 0x1048, 0x2048, 0xE010, 0x2010, 0x2020, 0x2040, 0x2180, 0x0600, } },
{ 0x5B50, {0x0000, 0x7FF8, 0x0010, 0x0020, 0x0040, 0x0180, 0x0100, 0xFFFE, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0500, 0x0200, } },
{ 0x5236, {0x0404, 0x2404, 0x2404, 0x3FA4, 0x4424, 0x0424, 0xFFE4, 0x0424, 0x0424, 0x3FA4, 0x24A4, 0x24A4, 0x2684, 0x2504, 0x0414, 0x0408, } },
{ 0x6210, {0x0050, 0x0048, 0x0040, 0x3FFE, 0x2040, 0x2040, 0x2044, 0x3E44, 0x2244, 0x2228, 0x2228, 0x2212, 0x2A32, 0x444A, 0x4086, 0x8102, } },
{ 0x7684, {0x1040, 0x1040, 0x2040, 0x7E7C, 0x4284, 0x4284, 0x4304, 0x4244, 0x7E24, 0x4224, 0x4204, 0x4204, 0x4204, 0x7E04, 0x4228, 0x0010, } },
{ 0x57CE, {0x2028, 0x2024, 0x2020, 0x27FE, 0x2420, 0xFC20, 0x2424, 0x27A4, 0x24A4, 0x24A8, 0x24A8, 0x3C90, 0xE692, 0x492A, 0x0846, 0x1082, } },
{ 0x5821, {0x0800, 0x0BF8, 0x1208, 0x33F8, 0x5040, 0x97FC, 0x1150, 0x1248, 0x1446, 0x1140, 0x0100, 0x3FF8, 0x0100, 0x0100, 0xFFFE, 0x0000, } },
{ 0x6700, {0x1FF0, 0x1010, 0x1FF0, 0x1010, 0x1FF0, 0x0000, 0xFFFE, 0x2200, 0x3EF8, 0x2288, 0x3E90, 0x2250, 0x2F20, 0xF250, 0x4288, 0x0306, } },
{ 0x7ADF, {0x0200, 0x0100, 0x3FF8, 0x0820, 0x0440, 0xFFFE, 0x0000, 0x1FF0, 0x1010, 0x1FF0, 0x1010, 0x1FF0, 0x0440, 0x0842, 0x1042, 0x603E, } },
{ 0x843D, {0x0820, 0x0820, 0xFFFE, 0x0820, 0x2080, 0x10F8, 0x1108, 0x8290, 0x4860, 0x4998, 0x1606, 0xE1F8, 0x2108, 0x2108, 0x21F8, 0x2108, } },
{ 0x5165, {0x0000, 0x0F00, 0x0100, 0x0100, 0x0100, 0x0280, 0x0280, 0x0280, 0x0440, 0x0440, 0x0820, 0x0820, 0x1010, 0x2010, 0x4008, 0x8006, } },
{ 0x6D77, {0x0100, 0x2100, 0x11FC, 0x1200, 0x85F8, 0x4128, 0x4928, 0x0928, 0x17FE, 0x1148, 0xE248, 0x2248, 0x23FC, 0x2008, 0x2050, 0x0020, } },
{ 0x4E2D, {0x0100, 0x0100, 0x0100, 0x0100, 0x3FF8, 0x2108, 0x2108, 0x2108, 0x2108, 0x2108, 0x3FF8, 0x2108, 0x0100, 0x0100, 0x0100, 0x0100, } },
{ 0x5C41, {0x0000, 0x3FF8, 0x2008, 0x2008, 0x3FF8, 0x2000, 0x2840, 0x2840, 0x2844, 0x2F48, 0x2850, 0x2860, 0x4844, 0x4944, 0x8A44, 0x0C3C, } },
{ 0x80A1, {0x0000, 0x3CF8, 0x2488, 0x2488, 0x2488, 0x3D06, 0x2600, 0x25FC, 0x2484, 0x3C84, 0x2448, 0x2450, 0x2420, 0x4450, 0x5488, 0x8B06, } },
{ 0x4ECA, {0x0100, 0x0100, 0x0280, 0x0440, 0x0820, 0x1210, 0x2108, 0xC106, 0x0000, 0x1FF0, 0x0010, 0x0020, 0x0020, 0x0040, 0x0080, 0x0100, } },
{ 0x5929, {0x0000, 0x3FF8, 0x0100, 0x0100, 0x0100, 0x0100, 0xFFFE, 0x0100, 0x0280, 0x0280, 0x0440, 0x0440, 0x0820, 0x1010, 0x2008, 0xC006, } },
{ 0x6BD4, {0x0080, 0x2080, 0x2080, 0x2084, 0x2088, 0x2090, 0x3EA0, 0x20C0, 0x2080, 0x2080, 0x2080, 0x2082, 0x2682, 0x3882, 0x207E, 0x0000, } },
{ 0x6628, {0x0100, 0x0100, 0x7900, 0x49FE, 0x4A80, 0x4A80, 0x4C80, 0x78F8, 0x4880, 0x4880, 0x4880, 0x48FC, 0x7880, 0x4880, 0x0080, 0x0080, } },
{ 0x5929, {0x0000, 0x3FF8, 0x0100, 0x0100, 0x0100, 0x0100, 0xFFFE, 0x0100, 0x0280, 0x0280, 0x0440, 0x0440, 0x0820, 0x1010, 0x2008, 0xC006, } },
{ 0x4FBF, {0x1000, 0x17FE, 0x1040, 0x27FC, 0x2444, 0x6444, 0x67FC, 0xA444, 0x2444, 0x27FC, 0x2240, 0x2140, 0x2080, 0x2140, 0x2230, 0x2C0E, } },
{ 0x5B9C, {0x0200, 0x0100, 0x7FFE, 0x4002, 0x8004, 0x1FF0, 0x1010, 0x1010, 0x1FF0, 0x1010, 0x1010, 0x1FF0, 0x1010, 0x1010, 0xFFFE, 0x0000, } },
{ 0x88FD, {0x2404, 0x3FA4, 0x4424, 0xFFA4, 0x0424, 0x3F84, 0x2494, 0x2588, 0x0200, 0x0100, 0xFFFE, 0x0488, 0x0C50, 0x3420, 0xC518, 0x0606, } },
{ 0x7D42, {0x1040, 0x1040, 0x207C, 0x2884, 0x4988, 0xF250, 0x1020, 0x2050, 0x4888, 0xFB06, 0x2860, 0x2010, 0xA808, 0xA8C0, 0xA020, 0x2010, } },
{ 0x6D4B, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, } },
{ 0x8BD5, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, } },
{ 0x8BBE, {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, } },
{ 0x7F6E, {0x0000, 0x7FFC, 0x4444, 0x7FFC, 0x0100, 0x7FFC, 0x0100, 0x1FF0, 0x1010, 0x1FF0, 0x5010, 0x5FF0, 0x5010, 0x5FF0, 0x4000, 0x7FFC, } },
};
int UTF8toUnicode(const uint8_t *s)
{
int wid = 0;
uint16_t wc;
int len = strlen(s);
for ( int i = 0; i < len; )
{
uint8_t c = s[i];
if ( (c & 0x80) == 0 )
{
wc = c;
++i;
}
// most Chinese UTF8 sequences are 2 or 3 byte
else if ( (c & 0xE0) == 0xC0 )
{
wc = (s[i] & 0x1F) << 6;
wc |= (s[i + 1] & 0x3F);
i += 2;
}
else if ( (c & 0xF0) == 0xE0 )
{
wc = (s[i] & 0xF) << 12;
wc |= (s[i + 1] & 0x3F) << 6;
wc |= (s[i + 2] & 0x3F);
i += 3;
}
// it is UNLIKELY that you have 4,5,6-byte UTF8 sequences
// and I make no attempt to support 24-bit Unicode
else if ( (c & 0xF8) == 0xF0 )
{
wc = (s[i] & 0x7) << 18;
wc |= (s[i + 1] & 0x3F) << 12;
wc |= (s[i + 2] & 0x3F) << 6;
wc |= (s[i + 3] & 0x3F);
i += 4;
}
else if ( (c & 0xFC) == 0xF8 )
{
wc = (s[i] & 0x3) << 24;
wc |= (s[i] & 0x3F) << 18;
wc |= (s[i] & 0x3F) << 12;
wc |= (s[i] & 0x3F) << 6;
wc |= (s[i] & 0x3F);
i += 5;
}
else if ( (c & 0xFE) == 0xFC )
{
wc = (s[i] & 0x1) << 30;
wc |= (s[i] & 0x3F) << 24;
wc |= (s[i] & 0x3F) << 18;
wc |= (s[i] & 0x3F) << 12;
wc |= (s[i] & 0x3F) << 6;
wc |= (s[i] & 0x3F);
i += 6;
}
//Serial.print("0x");
//Serial.println(wc, HEX);
if (wc > 0x7f) {
print_unicode(wc);
}
else tft.print((char)wc);
wid += (wc > 0x7F) ? 16 : 8;
}
return wid;
}
void show_letter16_P(const uint16_t *buf, uint8_t w, uint8_t h, uint16_t color, uint16_t bg, int16_t x, int16_t y)
{
uint16_t bits, carry;
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
if ((col & 15) == 0) bits = pgm_read_word(buf++);
tft.drawPixel(x + col, y + row, (bits & 0x8000) ? color : bg);
bits <<= 1;
}
}
}
int print_unicode(uint16_t unicode)
{
int x = tft.getCursorX(), y = tft.getCursorY();
int siz = sizeof(table) / sizeof(table[0]);
int j;
for (j = 0; j < siz; j++) {
if (pgm_read_word(&table[j].code) == unicode) {
show_letter16_P(&table[j].bits[0], 16, 16, WHITE, RED, x, y);
break;
}
}
if (j >= siz) tft.fillRect(x, y, 16, 16, GREEN);
tft.setCursor(x + 16, y);
return 16;
}
void setup(void)
{
Serial.begin(9600);
Serial.println("Chinese print");
tft.begin(tft.readID());
tft.setRotation(1);
tft.fillScreen(BLACK);
tft.setCursor(0, 0);
tft.print("Chinese print");
delay(1000);
tft.setCursor(0, 100);
UTF8toUnicode(utf8_msg);
tft.setCursor(5, 120);
UTF8toUnicode(utf8_fail);
tft.setCursor(15, 140);
UTF8toUnicode(utf8_duff);
tft.setCursor(5, 160);
UTF8toUnicode(utf8_veter72);
}
void loop(void)
{
}