TFT LCD(ili9486) Korean arduino mega(2560)

Hello I'm trying to print Korean on LCD(ili9486).
I tried Chinese letter library and it worked!
Since Korean and Chinese both use UTF8(about 3byte), I hope there is solution..

Since I'm new, I can't upload ino file:(
So code below is little weird... (square = square brackets)
Can anyone help me?

#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)
{
}

Thank you<|>

I think that your topic might get better exposure in the Display section of the forum and hence it has been moved.

Please edit your post, select all code and click the </> button to apply so-called code tags and next save your post. It makes it easier to read, easier to copy and prevents the forum software from incorrect interpretation of the code (e.g. [] instead of []).

I suggest that you use <U8g2_for_Adafruit_GFX.h> which is available from the IDE Library Manager

#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;

#include <U8g2_for_Adafruit_GFX.h>
U8G2_FOR_ADAFRUIT_GFX u8g2_for_adafruit_gfx;

void setup()
{
    tft.begin(tft.readID());
    u8g2_for_adafruit_gfx.begin(tft);                 // connect u8g2 procedures to Adafruit GFX
    u8g2_for_adafruit_gfx.setForegroundColor(TFT_WHITE);  // apply Adafruit GFX color
    u8g2_for_adafruit_gfx.setBackgroundColor(TFT_BLACK);  // apply Adafruit GFX color
}

const char utf8_msg[] = "由沙子制成的城堡最竟落入海中"
                           ;

void loop(void) 
{
    //u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_japanese2);  // use japanese
    //u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_chinese2);  // use chinese2 for all the glyphs of "你好世界"

    //u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_korean2);  // use korean for all the glyphs of "헬로월드"
    u8g2_for_adafruit_gfx.setFont(u8g2_font_unifont_t_korean1);  // use korean for all the glyphs of "헬로월드"
    //u8g2_for_adafruit_gfx.setFont(u8g2_font_10x20_t_cyrillic);  // use cyrillic for all the glyphs in "Привет, мир"
    //u8g2_for_adafruit_gfx.setFont(u8g2_font_inr24_t_cyrillic);  // use cyrillic for all the glyphs in "Привет, мир" 
    u8g2_for_adafruit_gfx.setFontDirection(0);
    tft.fillScreen(TFT_BLACK);
    u8g2_for_adafruit_gfx.setCursor(0, 30);
    u8g2_for_adafruit_gfx.print("Hello World!");
    u8g2_for_adafruit_gfx.setCursor(0, 60);
    //u8g2_for_adafruit_gfx.print("こんにちは世界"     ); // Japanese "Hello World"
    //u8g2_for_adafruit_gfx.print("你好世界");        // Chinese "Hello World"
    u8g2_for_adafruit_gfx.print("헬로월드");   // Korean "Hello World"
    //u8g2_for_adafruit_gfx.print("Привет, мир");        // Russian "Hello World"
    u8g2_for_adafruit_gfx.setCursor(0, 80);
    u8g2_for_adafruit_gfx.print(utf8_msg);

    delay(1000);
}

EDIT. Sorry, I ran this sketch on a STM32. I did not notice the Mega2560 i.e. AVR
The korean2 font is too big for an AVR. I have changed to korean1

I did not look at your program. I don't understand Korean.

If a Korean font is small, you can just have an array of 16x16 bitmaps like your example.
Chinese and Japanese have so many "characters" that you need an efficient way to store them e.g. U8g2

David.

Thank you very much! :+1: It works! You saved me:)
Though.. not perfectly :sweat_smile:
Some letters doesn't come up. If I put "캡스톤디자인" it comes out "스디자인"
Maybe because font is too big as you said...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.