§ Код функции

Здесь используется prn для вывода на экран. В данном случае — не реализована, оставлена на дальнейшее усмотрение и как няшная заглушка ^_^.
1void print(const char* s) {
2
3    int i = 0, n = 0;
4    while (s[i]) {
5        byte ch = s[i++];
6        if (ch == 0xD0) { // Главный набор
7            ch = s[i++];
8            ch = (ch == 0x81 ? 0xF0 : ch - 0x10);
9        } else if (ch == 0xD1) { // Вторичный набор
10            ch = s[i++];
11            ch = (ch == 0x91 ? 0xF1 : ch + (ch < 0xB0 ? 0x60 : 0x10));
12        }
13        prn(ch);
14        n++;
15    }
16}

§ Для AVR-контроллера

Помимо обычного вывода символов, существует также ESC-код 1Bh [ATTR], который позволяет менять цвет дальнейших символов на лету. Переменная cursor_attr должна быть объявлена.
1void print(const char* s, byte pgm = 0) {
2
3    byte ch, nx, ct;
4    int  i = 0, n = 0;
5    while ((ch = (pgm ? pgm_read_byte(&s[i++]) : s[i++]))) {
6
7        ct = (ch == 0x1B);
8
9        // Считывание дополнительного байта UTF8 или CTL
10        if (ch == 0xD0 || ch == 0xD1 || ch == 0x1B) {
11
12            // Прочитать следующий символ
13            nx = (pgm ? pgm_read_byte(&s[i++]) : s[i++]);
14
15            // Разбор дополнительного байта
16            if      (ch == 0xD0) { ch = (nx == 0x81 ? 0xF0 : nx - 0x10); }
17            else if (ch == 0xD1) { ch = (nx == 0x91 ? 0xF1 : nx + (nx < 0xB0 ? 0x60 : 0x10)); }
18            else if (ct) { cursor_attr = nx; continue; }
19        }
20
21        prn(ch);
22        n++;
23    }
24}