Ralim / IronOS

Open Source Soldering Iron firmware
https://ralim.github.io/IronOS/
GNU General Public License v3.0
7.17k stars 712 forks source link

A single Multi-Lingual firmware #222

Closed jonnieZG closed 4 years ago

jonnieZG commented 6 years ago

Since we are already talking about broadening the setup menu, should we consider making a multi-lingual firmware, where the default language would be English, and a user could choose his favorite language from the Setup?

That would make distribution of compiled firmware much easier, since there would be just a single HEX file, instead one HEX for each language.

Ralim commented 6 years ago

The big question for this will mostly be flash space, if after the new menu there is enough space to build all the languages in and we split up the font table to account for the overlapping Russian and Latin (I think?) sections then I'm happy to make it multi lingual. Another thing is that we still don't even have Korean and Chinese or japanese in the firmware yet either and they all need more font space.

We could look into build time calculating the font table and stripping unused characters as well, but I'm not that familiar with the best way to do that with c++? (all ears if you know)

jonnieZG commented 6 years ago

If the problem is the available memory for all the fonts, we could have several groups of firmwares (all of them would have a common English option):

The other option might be, as you suggested, making a pre-compile script that would cleanup the Font.c from the unnecessary characters, but I haven't yet considered all the pitfalls of such a solution... As I think about it, I am more and more biased towards that approach.

jonnieZG commented 6 years ago

Here's my rough idea for making all of the languages supported in the same FW version:

  1. Instead of using a fixed pointer for each string, that is selected by #defined language, each string will be defined by an array of pointers, with a language ID as a key.
  2. Instead of the current Translation.c we will have a RawTranslation.c with all of the language strings loaded in the same time.
  3. All the strings that appear for printing will HAVE to be externalized in Translation.c file.
  4. Instead of Font.c we will have a RawFont.c with both the big and the small font defined, with all the characters from all the languages that are supported. That would be a huge file, but it won't be compiled entirely, because...
  5. There will be a pre-compile script that will read and modify the RawTranslation.c and RawFont.c and automatically generate Translation.c and Font.c files from them, in the following way:
    • It will first scan all the characters that appear in RawTranslation.c strings
    • For each character it will lookup in a newly generated Font.c if that particular character was already used.
    • For a new (unused) character, it will create two new Font.c entries taken from RawFont.c (one for small and one for big bitmap) with a current index. Character's indexes will be assigned in order in order of character's appearances, e.g. if the first character that appeared in the translation strings was 'T', then the character 'T' would have index 0, and all the appearances of 'T' in the new Translation.c file would be replaced by a 16-bit value of 0. If the second char to appear is 'h', the same will be done, but the 'h' would now be indexed as 1. Consequently, the Translation.c would result in a human-unreadable file, but that is not important, because we will be able to read them on the iron screen, because...
  6. The print routine will be modified to display bitmaps according to the indexes from the automatically Translation.c and Font.c, instead of the old UTF-8 encoding.

Basically, that new script of ours will be changing UTF-8 encoding into a dynamic 16-bit encoding of characters, by their order of appearance. That will significantly reduce number of defined character bitmaps, to just those that are actually used in the strings.

I did a rough count, so for all the currently defined strings in the current languages that we have right now there will be ~200 different characters. For Japanese, Chinese and Korean, there will be additional ~400 chars (~600 in total). That would require 600 24 bytes for big, plus 600 6 bytes for small font, resulting in a total of ~18kB for all the required character definitions.

How much total flash memory does the TS100 have? It's a STM32F103T8Ux and it has 64kB, right?

I did not count in Arabic language, because it has Right-To-Left script, so it would require some additional tinkering, so we might consider adding it.

Good?

jonnieZG commented 6 years ago

I have some further improvements to the above idea, and I am willing to make them myself one of these days.

Instead of the RawTranslation.c we will have one translation_XX.properties for each language (XX being the language code). It will be a file with set key-value pairs, key being a code of each string. These files would be edited from a JavaScript application, and after saving, the application would make the final Translation.c and Font.h files.

Ralim commented 6 years ago

Hi, We have about 15kb to play with for font data on the unit to leave room for the rest of the firmware etc, as we have 48k after the DFU bootloader, then less the program size, plus the 2kb consumed by the settings and boot up screen images (as these are page aligned on their own pages).

I'm all for having a binary searchable lookup section for the font data.

Also any scripts that need to be run to generate these files need to be callable by make on Linux, so probably JavaScript is out as a language for doing the processing in at this point on time. Cross platform support should be a priority so that users who are using the system workbench for stm32 can still use the files that are generated.

Otherwise i agree with your concept. Would make for a nice big clunky pre processor but otherwise would be nice.

I was thinking of a smallish c program that could be compiled in the first stage before the main program but need to check for integration with the ide as well.

Don't really want to check in the processed files as they may change randomly and bloat the repository..

jonnieZG commented 6 years ago

As much as for the strings editor goes, I thought of making a user-friendly(sh) GUI in HTML5 that would produce the "source" property or Json files for the fonts and the text strings. The pre-processor can be written in C++ so it could be called by make, to construct the target C and H files.

15kB is a bit less than I expected, but we don't have the Korean, Chinese and Japanese yet, so it should be fine for the languages we have by now. We also need to count in the space taken by the strings, so I am thinking of compressing them in some way. E.g. having encoded characters from the range 0x00-0x7F taking just one byte, while those starting with 0x8--- taking two bytes (similar to the UTF-8 principle.

If hit the 15kB limit when the Asian languages kick in, I can work out a font compression algorithm as well, but all in good time. BTW, do we have any volunteers (preferably native speakers) for translating the messages to Japanese, Chinese and Korean?

I think this whole thing is worth the effort, because having a single multi-lingual firmware instead of having a different version for each language, adds a substantial value to the device.

Ralim commented 6 years ago

Ah, right I get what you mean now. That is certainly a possibility, I'm currently in toying with seeing if I can make the c++ evaluation at compile time work to building the data at compile time so they can be constants in the firmware. Not sure if this will work, need to toy with it.

At this point, should we just stick with utf-8 encoding and then optimise the encoding later on when we run out of space.

I'm not massively concerned with space just yet, since we already encode the entire font table and we still have a couple of k of flash space left.

I'm thinking a plan of attack of :

  1. Add a language menu and change to compiling all the current languages into the firmware
  2. Optimise the font table at compile time to reduce firmware size
  3. Add in Japanese, Chinese and Korean.

I think the first stage might just fit, and would let us proof of concept the idea.

I think if we are only compiling in the needed fonts, and we just use a b-tree to sort from utf8 to font index we should be okay for room.

I agree it's definitely worth the effort!

I'm sure if we convert over the fonts and post for interest people will show up, people seem to keep showing up around here that love the firmware so I'm sure people will :)

jonnieZG commented 6 years ago

If we stick with UTF-8, then we'd have to have an additional mapping between charCode and bitmapData, and that map might get quite big. So if we encode the chars as I described, we eliminate the need of having a translation map. Instead of that, we'll just have 8-16 bit char being mapped to a bitmap directly in order of appearance. We will just have to ensure that space ' ' and digits '0'-'9' always have the same code (for example codes 0-9 for digits, and 10 for space) so you could more easily print numeric values.

Having a JavaScript editor that would generate one property or json file per language would certainly result in less conflicts, and I would also implement length checking for each string.

Ralim commented 6 years ago

@jonnieZG I understand, was thinking UTF-8 even with the extra lookup might be less code to implement -> Faster release is mostly why :)

Looks like this could be compute able using the constexpr keyword in normal C++, but I haven't tested this in the microcontroller build as of yet. Planning to make a standalone c++ app to test this and then if that works back-port this to the firmware.

Alternately we could have a javascript tool to manage the editing and output pre-processed files for this, and just have those particular files stored in git-lfs. Then just perform the calculation before building release builds. This probably depends on how good you are with javascript too (I'm not a web person)

With the allocation to uint16_t I agree we could keep the UTF-8 style of using the 0x80 bit as a marker for extended format. We could then just sort all chars by usage counts to decide on the <0x80 values as you suggest.

jonnieZG commented 6 years ago

@Ralim, I didn't work with STM32, but according to my experience with Arduino, I believe that using constexpr or const alone is not enough. If you want some data to be stored in flash memory, you will also have to write a method that fetches that data back from the FLASH into the RAM, when you want to work with it (e.g. to draw a character bitmap). See this.

I think that mere marking an array with constexpr and reading that data using array[...] just won't work.

Just as an illustration of the above, Arduino C++ uses a modifier keyword PROGMEM that stores data to FLASH:

static constexpr uint16_t MY_STATIC_DATA[SIZE] PROGMEM
    = { 0x0000, 0x1234, ...}

To fetch that data during runtime, you have a method like this one:

/** \ingroup avr_pgmspace
    \def pgm_read_byte(address_short)
    Read a byte from the program space with a 16-bit (near) address. 

    \note The address is a byte address. 
    The address is in the program space. */

#define pgm_read_byte(address_short)    pgm_read_byte_near(address_short)
Ralim commented 6 years ago

Constexpr and reading data are different things.

On the STM32 when the data array is marked as being a constant It will be left in flash and not copied to ram. So you can work with it directly. There are other ways to force this to happen, but the easiest way to verifify is to take a pointer to the content and print that to the LCD screen and see if it starts with 0x08.....

Which is where the internal flash is mapped to. Compilers are also getting alot better at spotting read only variables and leaving them in flash.

The settings structure on the other hand is an example where we operate with a ram copy and read/write it back and forth between the flash.

I can go into more on this if you want.

With constexpr we are telling the compiler it can evaluate this particular function at compile time and just store the results. This is often used for things such as calculating constants that don't change in the firmware but might change on new versions. Such as the sizeof command.

So the array would be a compile time constant with its contents defined by calling a constexpr function.

Doridian commented 6 years ago

You can squeeze some size out if needed by swapping -O2 for -Os

-O2
Linking TS100_EN.elf
arm-none-eabi-size -x Hexfile/TS100_EN.elf
   text    data     bss     dec     hex filename
 0x9f0c   0x6e8  0x3400   55796    d9f4 Hexfile/TS100_EN.elf
arm-none-eabi-objcopy Hexfile/TS100_EN.elf -O ihex Hexfile/TS100_EN.hex

-Os
Linking TS100_EN.elf
arm-none-eabi-size -x Hexfile/TS100_EN.elf
   text    data     bss     dec     hex filename
 0x94bc   0x6e8  0x3400   53156    cfa4 Hexfile/TS100_EN.elf
arm-none-eabi-objcopy Hexfile/TS100_EN.elf -O ihex Hexfile/TS100_EN.hex

I have also tried enabling LTO, but it seems the generated assembly doesn't quite work then (the assembler fails)...

Ralim commented 6 years ago

@Doridian I'm aware I can swap to Os, but I would rather not until I have verified the timing characteristics for all of the ISR's under that compiling option. :)

jonnieZG commented 6 years ago

I've made a translation editor #249 that produces separate JSON files for each language, and now I'm working on Python script that will build a Translation.cpp from these JSON files.

Ralim commented 6 years ago

Thanks @jonnieZG. I'll bug fix the 2.03 RC and then look into this for making a new release :)

(I'm not ignoring you, I really appreciate the work, just busy)

jonnieZG commented 6 years ago

For the beginning, I've made a Python script that builds the Translation.cpp from JSON files for the single-language version file, just to see if the language files are ok.

I am writing now a proof-of-concept that will use multi-lingual messages.

jonnieZG commented 6 years ago

@Ralim, this is the concept that I had in mind. See example below. It can write a corresponding weekday name in one of the defined languages, but the same concept will be applied to all the required strings.

It is only that instead of the characters array, we'll be having an array of bitmaps for each character. I am just not sure whether the compiler will put that const char arrays into the flash memory... I've tested the concept in this online compiler

#include <iostream>

using namespace std;

// START Auto-Generated Block

#define LANG_EN 0
#define LANG_HR 1
#define LANG_COUNT 2

// Generic Strings
#define STR_sunday 0
#define STR_monday 1
#define STR_tuesday 2

// Instead of having ASCII codes, we'll be having an array of bitmaps for each character
// 0=END, S=1, u=2, n=3, d=4, a=5, y=6, M=7, o=8, T=9, e=10, s=11, N=12, j=13, l=14, P=15, k=16, U=17, t=18, r=19
const char chars[] = {'S','u','n','d','a','y','M','o','T','e','s','N','j','l','P','k','U','t','r'};

const char sunday_en[] = {1,2,3,4,5,6,0}; // Sunday
const char monday_en[] = {7,8,3,4,5,6,0}; // Monday
const char tuesday_en[] = {9,2,10,11,4,5,6,0}; // Tuesday

const char sunday_hr[] = {12,10,4,13,10,14,13,5,0}; // Nedjelja
const char monday_hr[] = {15,8,3,10,4,13,10,14,13,5,16,0}; // Ponedjeljak
const char tuesday_hr[] = {17,18,8,19,5,16,0}; // Utorak

const char* strings[3][LANG_COUNT] = {
    {sunday_en, sunday_hr}, 
    {monday_en, monday_hr}, 
    {tuesday_en, tuesday_hr}, 
};

// END Auto-Generated Block

int print(const char *str[][LANG_COUNT], int stringId, int languageId) {
    const char *pc = str[stringId][languageId];
    while (true) {
        const char c = *pc;
        if (c == 0)
            break;
        // Instead of printing an ASCII char, we'll be rendering a corresponding bitmap
        int charIndex = (int)c - 1; // we'll also have to handle two-byte encoded chars for bytes > 127
        cout << chars[charIndex];
        pc++;
    }
    cout << endl;
}
int main()
{   
    print(strings, STR_monday, LANG_HR);
    return 0;
}
jonnieZG commented 6 years ago

Ok, I've made a much more accurate calculation, and with the total of the current 17 languages, and the described encoding, we have the following size:

This is definitely much more than we expected, but as I see it, we have 2 options:

a. We cut down the descriptions to bare minimum, or remove them completely. Without the descriptions we will have just ~16000 bytes for strings in all 17 languages.

b. We split the languages into 2 or 3 groups by regions, each group having English as a common language. That way we would have a multi-lingual firmwares, but there would be 2 or 3 of them with different language groups.

My script reuses strings, rather then making multiple definitions of a same string (using define). It keeps the existing ASCII range unchaged, but for chars above 127, it first writes lowest 7 bits with 8th bit set to 1, and then the rest of the bits in the next string. For example, a 16-bit value of 00010010 01101011 will be encoded as two bytes: 11101011 (least significant byte first, with bit7 set to 1) and 00100100

This is the file that my script generated for English, Croatian and Russian languages.

#ifndef I14N_H_
#define I14N_H_
#include <hardware.h>

/********** AUTOMATICALLY GENERATED - DO NOT EDIT **********/

enum ShortNameType {
    SHORT_NAME_SINGLE_LINE = 1, SHORT_NAME_DOUBLE_LINE = 2,
};

// ================ COMMON CONSTANTS ================

#define LANG_COUNT  3    /* Number of languages */

// ---- Special Character Codes ----

#define CHAR_EOS    0    /* End-of-String */

// ---- Language IDs ----

#define LANG_EN     0   /* English */
#define LANG_HR     1   /* Hrvatski */
#define LANG_RU     2   /* Русский */

// ================ STRING INDEXES ================

// ---- Message Strings ----

#define L_MS_LANGUAGECODE                        0
#define L_MS_LANGUAGELOCALNAME                   1
#define L_MS_SETTINGSCALIBRATIONWARNING          2
#define L_MS_SETTINGSRESETWARNING                3
#define L_MS_UVLOWARNINGSTRING                   4
#define L_MS_UNDERVOLTAGESTRING                  5
#define L_MS_INPUTVOLTAGESTRING                  6
#define L_MS_WARNINGTIPTEMPSTRING                7
#define L_MS_BADTIPSTRING                        8
#define L_MS_SLEEPINGSIMPLESTRING                9
#define L_MS_SLEEPINGADVANCEDSTRING              10
#define L_MS_WARNINGSIMPLESTRING                 11
#define L_MS_WARNINGADVANCEDSTRING               12
#define L_MS_SLEEPINGTIPADVANCEDSTRING           13
#define L_MS_IDLETIPSTRING                       14
#define L_MS_IDLESETSTRING                       15
#define L_MS_TIPDISCONNECTEDSTRING               16
#define L_MS_SOLDERINGADVANCEDPOWERPROMPT        17
#define L_MS_RESETOK                             18
#define L_MS_OFFSTRING                           19
#define L_MS_SETTINGRIGHTCHAR                    20
#define L_MS_SETTINGLEFTCHAR                     21
#define L_MS_SETTINGAUTOCHAR                     22
#define L_MS_SETTINGFASTCHAR                     23
#define L_MS_SETTINGSLOWCHAR                     24

// ---- Settings Groups ----

#define L_SG_SOLDERINGMENU                       0
#define L_SG_POWERSAVINGMENU                     1
#define L_SG_UIMENU                              2
#define L_SG_ADVANCEDMENU                        3

// ---- Settings Names ----

#define L_SN_POWERSOURCE                         0
#define L_SN_SLEEPTEMPERATURE                    1
#define L_SN_SLEEPTIMEOUT                        2
#define L_SN_SHUTDOWNTIMEOUT                     3
#define L_SN_MOTIONSENSITIVITY                   4
#define L_SN_TEMPERATUREUNIT                     5
#define L_SN_ADVANCEDIDLE                        6
#define L_SN_DISPLAYROTATION                     7
#define L_SN_BOOSTENABLED                        8
#define L_SN_BOOSTTEMPERATURE                    9
#define L_SN_AUTOSTART                           10
#define L_SN_COOLDOWNBLINK                       11
#define L_SN_TEMPERATURECALIBRATION              12
#define L_SN_SETTINGSRESET                       13
#define L_SN_VOLTAGECALIBRATION                  14
#define L_SN_ADVANCEDSOLDERING                   15
#define L_SN_SCROLLINGSPEED                      16
#define L_SN_LANGUAGE                            17

// ================ Translation Strings - English (EN) ================

// ---- Message Strings (EN) ----

const char _L_MS_LANGUAGECODE_EN[] =    // EN
    "EN";
const char _L_MS_LANGUAGELOCALNAME_EN[] =    // English
    "English";
const char _L_MS_SETTINGSCALIBRATIONWARNING_EN[] =    // Please ensure the tip is at room temperature before continuing!
    "Please ensure the tip is at room temperature before continuing!";
const char _L_MS_SETTINGSRESETWARNING_EN[] =    // Are you sure to reset settings to default values?
    "Are you sure to reset settings to default values?";
const char _L_MS_UVLOWARNINGSTRING_EN[] =    // DC LOW
    "DC LOW";
const char _L_MS_UNDERVOLTAGESTRING_EN[] =    // Undervoltage
    "Undervoltage";
const char _L_MS_INPUTVOLTAGESTRING_EN[] =    // Input V: 
    "Input V: ";
const char _L_MS_WARNINGTIPTEMPSTRING_EN[] =    // Tip Temp: 
    "Tip Temp: ";
const char _L_MS_BADTIPSTRING_EN[] =    // BAD TIP
    "BAD TIP";
const char _L_MS_SLEEPINGSIMPLESTRING_EN[] =    // Zzzz
    "Zzzz";
const char _L_MS_SLEEPINGADVANCEDSTRING_EN[] =    // Sleeping...
    "Sleeping...";
const char _L_MS_WARNINGSIMPLESTRING_EN[] =    // HOT!
    "HOT!";
const char _L_MS_WARNINGADVANCEDSTRING_EN[] =    // !!! TIP HOT !!!
    "!!! TIP HOT !!!";
const char _L_MS_SLEEPINGTIPADVANCEDSTRING_EN[] =    // Tip:
    "Tip:";
#define _L_MS_IDLETIPSTRING_EN    _L_MS_SLEEPINGTIPADVANCEDSTRING_EN     /* Tip: */
const char _L_MS_IDLESETSTRING_EN[] =    //  Set:
    " Set:";
const char _L_MS_TIPDISCONNECTEDSTRING_EN[] =    // TIP DISCONNECTED
    "TIP DISCONNECTED";
const char _L_MS_SOLDERINGADVANCEDPOWERPROMPT_EN[] =    // Power: 
    "Power: ";
const char _L_MS_RESETOK_EN[] =    // RESET OK
    "RESET OK";
const char _L_MS_OFFSTRING_EN[] =    // Off
    "Off";
const char _L_MS_SETTINGRIGHTCHAR_EN[] =    // R
    "R";
const char _L_MS_SETTINGLEFTCHAR_EN[] =    // L
    "L";
const char _L_MS_SETTINGAUTOCHAR_EN[] =    // A
    "A";
const char _L_MS_SETTINGFASTCHAR_EN[] =    // F
    "F";
const char _L_MS_SETTINGSLOWCHAR_EN[] =    // S
    "S";

// ---- Settings Groups (EN) ----

const char _L_SG_SOLDERINGMENU_EN[] =    // Soldering|Settings
    "Soldering\nSettings";
const char _L_SG_POWERSAVINGMENU_EN[] =    // Sleep|Modes
    "Sleep\nModes";
const char _L_SG_UIMENU_EN[] =    // User|Interface
    "User\nInterface";
const char _L_SG_ADVANCEDMENU_EN[] =    // Advanced|Options
    "Advanced\nOptions";

// ---- Settings Groups Descriptions (EN) ----

const char _L_SGD_SOLDERINGMENU_EN[] =    // Soldering settings
    "Soldering settings";
const char _L_SGD_POWERSAVINGMENU_EN[] =    // Power Saving Settings
    "Power Saving Settings";
const char _L_SGD_UIMENU_EN[] =    // User Interface settings
    "User Interface settings";
const char _L_SGD_ADVANCEDMENU_EN[] =    // Advanced options
    "Advanced options";

// ---- Settings Names (EN) ----

const char _L_SN_POWERSOURCE_EN[] =    // Power|source
    "Power\nsource";
const char _L_SN_SLEEPTEMPERATURE_EN[] =    // Sleep|temp
    "Sleep\ntemp";
const char _L_SN_SLEEPTIMEOUT_EN[] =    // Sleep|timeout
    "Sleep\ntimeout";
const char _L_SN_SHUTDOWNTIMEOUT_EN[] =    // Shutdown|timeout
    "Shutdown\ntimeout";
const char _L_SN_MOTIONSENSITIVITY_EN[] =    // Motion|sensitivity
    "Motion\nsensitivity";
const char _L_SN_TEMPERATUREUNIT_EN[] =    // Temperature|units
    "Temperature\nunits";
const char _L_SN_ADVANCEDIDLE_EN[] =    // Detailed|idle screen
    "Detailed\nidle screen";
const char _L_SN_DISPLAYROTATION_EN[] =    // Display|orientation
    "Display\norientation";
const char _L_SN_BOOSTENABLED_EN[] =    // Boost mode|enabled
    "Boost mode\nenabled";
const char _L_SN_BOOSTTEMPERATURE_EN[] =    // Boost|temp
    "Boost\ntemp";
const char _L_SN_AUTOSTART_EN[] =    // Auto|start
    "Auto\nstart";
const char _L_SN_COOLDOWNBLINK_EN[] =    // Cooldown|blink
    "Cooldown\nblink";
const char _L_SN_TEMPERATURECALIBRATION_EN[] =    // Calibrate|temperature?
    "Calibrate\ntemperature?";
const char _L_SN_SETTINGSRESET_EN[] =    // Factory|reset?
    "Factory\nreset?";
const char _L_SN_VOLTAGECALIBRATION_EN[] =    // Calibrate|input voltage?
    "Calibrate\ninput voltage?";
const char _L_SN_ADVANCEDSOLDERING_EN[] =    // Detailed|solder screen
    "Detailed\nsolder screen";
const char _L_SN_SCROLLINGSPEED_EN[] =    // Description|Scroll Speed
    "Description\nScroll Speed";
const char _L_SN_LANGUAGE_EN[] =    // Language|
    "Language\n";

// ---- Settings Descriptions (EN) ----

const char _L_SND_POWERSOURCE_EN[] =    // Power source. Sets cutoff voltage. <DC 10V> <S 3.3V per cell>
    "Power source. Sets cutoff voltage. <DC 10V> <S 3.3V per cell>";
const char _L_SND_SLEEPTEMPERATURE_EN[] =    // Sleep Temperature <C>
    "Sleep Temperature <C>";
const char _L_SND_SLEEPTIMEOUT_EN[] =    // Sleep Timeout <Minutes/Seconds>
    "Sleep Timeout <Minutes/Seconds>";
const char _L_SND_SHUTDOWNTIMEOUT_EN[] =    // Shutdown Timeout <Minutes>
    "Shutdown Timeout <Minutes>";
const char _L_SND_MOTIONSENSITIVITY_EN[] =    // Motion Sensitivity <0.Off 1.least sensitive 9.most sensitive>
    "Motion Sensitivity <0.Off 1.least sensitive 9.most sensitive>";
const char _L_SND_TEMPERATUREUNIT_EN[] =    // Temperature Unit <C=Celsius F=Fahrenheit>
    "Temperature Unit <C=Celsius F=Fahrenheit>";
const char _L_SND_ADVANCEDIDLE_EN[] =    // Display detailed information in a smaller font on the idle screen.
    "Display detailed information in a smaller font on the idle screen.";
const char _L_SND_DISPLAYROTATION_EN[] =    // Display Orientation <A. Automatic L. Left Handed R. Right Handed>
    "Display Orientation <A. Automatic L. Left Handed R. Right Handed>";
const char _L_SND_BOOSTENABLED_EN[] =    // Enable front key enters boost mode 450C mode when soldering
    "Enable front key enters boost mode 450C mode when soldering";
const char _L_SND_BOOSTTEMPERATURE_EN[] =    // Temperature when in \"boost\" mode
    "Temperature when in \"boost\" mode";
const char _L_SND_AUTOSTART_EN[] =    // Automatically starts the iron into soldering on power up. T=Soldering, S= Sleep mode,F=Off
    "Automatically starts the iron into soldering on power up. T=Soldering, S= Sleep mode,F=Off";
const char _L_SND_COOLDOWNBLINK_EN[] =    // Blink the temperature on the cooling screen while the tip is still hot.
    "Blink the temperature on the cooling screen while the tip is still hot.";
const char _L_SND_TEMPERATURECALIBRATION_EN[] =    // Calibrate tip offset.
    "Calibrate tip offset.";
const char _L_SND_SETTINGSRESET_EN[] =    // Reset all settings
    "Reset all settings";
const char _L_SND_VOLTAGECALIBRATION_EN[] =    // VIN Calibration. Buttons adjust, long press to exit
    "VIN Calibration. Buttons adjust, long press to exit";
const char _L_SND_ADVANCEDSOLDERING_EN[] =    // Display detailed information while soldering
    "Display detailed information while soldering";
const char _L_SND_SCROLLINGSPEED_EN[] =    // Speed this text scrolls past at
    "Speed this text scrolls past at";
const char _L_SND_LANGUAGE_EN[] =    // 
    "";

// ================ Translation Strings - Hrvatski (HR) ================

// ---- Message Strings (HR) ----

const char _L_MS_LANGUAGECODE_HR[] =    // HR
    "HR";
const char _L_MS_LANGUAGELOCALNAME_HR[] =    // Hrvatski
    "Hrvatski";
const char _L_MS_SETTINGSCALIBRATIONWARNING_HR[] =    // Provjerite da je vršak ohlađen na sobnu temperaturu prije nego što nastavite!
    "Provjerite da je vr\x80\x1""ak ohla\x81\x1""en na sobnu temperaturu prije nego \x80\x1""to nastavite!";
const char _L_MS_SETTINGSRESETWARNING_HR[] =    // Jeste li sigurni da želite sve postavke vratiti na tvorničke vrijednosti?
    "Jeste li sigurni da \x82\x1""elite sve postavke vratiti na tvorni\x83\x1""ke vrijednosti?";
const char _L_MS_UVLOWARNINGSTRING_HR[] =    // BATERIJA
    "BATERIJA";
const char _L_MS_UNDERVOLTAGESTRING_HR[] =    // PRENIZAK NAPON
    "PRENIZAK NAPON";
const char _L_MS_INPUTVOLTAGESTRING_HR[] =    // Napajanje: 
    "Napajanje: ";
const char _L_MS_WARNINGTIPTEMPSTRING_HR[] =    // Temp vrha: 
    "Temp vrha: ";
const char _L_MS_BADTIPSTRING_HR[] =    // LOŠ VRH
    "LO\x84\x1"" VRH";
const char _L_MS_SLEEPINGSIMPLESTRING_HR[] =    // Zzz
    "Zzz ";
const char _L_MS_SLEEPINGADVANCEDSTRING_HR[] =    // SPAVANJE...
    "SPAVANJE...";
const char _L_MS_WARNINGSIMPLESTRING_HR[] =    // VRUĆ
    "VRU\x85\x1";
const char _L_MS_WARNINGADVANCEDSTRING_HR[] =    // !!! VRUĆE !!!
    "!!! VRU\x85\x1""E !!!";
const char _L_MS_SLEEPINGTIPADVANCEDSTRING_HR[] =    // Vrh: 
    "Vrh: ";
#define _L_MS_IDLETIPSTRING_HR    _L_MS_SLEEPINGTIPADVANCEDSTRING_HR     /* Vrh:  */
const char _L_MS_IDLESETSTRING_HR[] =    //  / 
    " / ";
const char _L_MS_TIPDISCONNECTEDSTRING_HR[] =    // VRH NIJE SPOJEN!
    "VRH NIJE SPOJEN!";
const char _L_MS_SOLDERINGADVANCEDPOWERPROMPT_HR[] =    // Snaga: 
    "Snaga: ";
#define _L_MS_RESETOK_HR    _L_MS_RESETOK_EN     /* RESET OK */
const char _L_MS_OFFSTRING_HR[] =    // Ne
    "Ne";
const char _L_MS_SETTINGRIGHTCHAR_HR[] =    // D
    "D";
#define _L_MS_SETTINGLEFTCHAR_HR    _L_MS_SETTINGLEFTCHAR_EN     /* L */
#define _L_MS_SETTINGAUTOCHAR_HR    _L_MS_SETTINGAUTOCHAR_EN     /* A */
const char _L_MS_SETTINGFASTCHAR_HR[] =    // B
    "B";
#define _L_MS_SETTINGSLOWCHAR_HR    _L_MS_SETTINGSLOWCHAR_EN     /* S */

// ---- Settings Groups (HR) ----

const char _L_SG_SOLDERINGMENU_HR[] =    // Postavke|lemljenja
    "Postavke\nlemljenja";
const char _L_SG_POWERSAVINGMENU_HR[] =    // Ušteda|energije
    "U\x80\x1""teda\nenergije";
const char _L_SG_UIMENU_HR[] =    // Korisničko|sučelje
    "Korisni\x83\x1""ko\nsu\x83\x1""elje";
const char _L_SG_ADVANCEDMENU_HR[] =    // Napredne|opcije
    "Napredne\nopcije";

// ---- Settings Groups Descriptions (HR) ----

const char _L_SGD_SOLDERINGMENU_HR[] =    // Postavke pri lemljenju
    "Postavke pri lemljenju";
const char _L_SGD_POWERSAVINGMENU_HR[] =    // Postavke spavanja i štednje energije
    "Postavke spavanja i \x80\x1""tednje energije";
const char _L_SGD_UIMENU_HR[] =    // Postavke korisničkog sučelja
    "Postavke korisni\x83\x1""kog su\x83\x1""elja";
const char _L_SGD_ADVANCEDMENU_HR[] =    // Upravljanje naprednim opcijama
    "Upravljanje naprednim opcijama";

// ---- Settings Names (HR) ----

const char _L_SN_POWERSOURCE_HR[] =    // Izvor|napajanja
    "Izvor\nnapajanja";
const char _L_SN_SLEEPTEMPERATURE_HR[] =    // Temp|spavanja
    "Temp\nspavanja";
const char _L_SN_SLEEPTIMEOUT_HR[] =    // Vrijeme|spavanja
    "Vrijeme\nspavanja";
const char _L_SN_SHUTDOWNTIMEOUT_HR[] =    // Vrijeme|gašenja
    "Vrijeme\nga\x80\x1""enja";
const char _L_SN_MOTIONSENSITIVITY_HR[] =    // Osjetljivost|pokreta
    "Osjetljivost\npokreta";
const char _L_SN_TEMPERATUREUNIT_HR[] =    // Jedinica|temperature
    "Jedinica\ntemperature";
const char _L_SN_ADVANCEDIDLE_HR[] =    // Detalji|pri čekanju
    "Detalji\npri \x83\x1""ekanju";
const char _L_SN_DISPLAYROTATION_HR[] =    // Rotacija|ekrana
    "Rotacija\nekrana";
const char _L_SN_BOOSTENABLED_HR[] =    // Boost|način
    "Boost\nna\x83\x1""in";
#define _L_SN_BOOSTTEMPERATURE_HR    _L_SN_BOOSTTEMPERATURE_EN     /* Boost|temp */
#define _L_SN_AUTOSTART_HR    _L_SN_AUTOSTART_EN     /* Auto|start */
const char _L_SN_COOLDOWNBLINK_HR[] =    // Upozorenje|pri hlađenju
    "Upozorenje\npri hla\x81\x1""enju";
const char _L_SN_TEMPERATURECALIBRATION_HR[] =    // Kalibracija|temperature
    "Kalibracija\ntemperature";
const char _L_SN_SETTINGSRESET_HR[] =    // Tvorničke|postavke
    "Tvorni\x83\x1""ke\npostavke";
const char _L_SN_VOLTAGECALIBRATION_HR[] =    // Kalibracija|napona napajanja
    "Kalibracija\nnapona napajanja";
const char _L_SN_ADVANCEDSOLDERING_HR[] =    // Detalji|pri lemljenju
    "Detalji\npri lemljenju";
const char _L_SN_SCROLLINGSPEED_HR[] =    // Brzina|poruka
    "Brzina\nporuka";
const char _L_SN_LANGUAGE_HR[] =    // Jezik|
    "Jezik\n";

// ---- Settings Descriptions (HR) ----

const char _L_SND_POWERSOURCE_HR[] =    // Izvor napajanja. Postavlja napon isključivanja. <DC 10V> <S 3.3V po ćeliji>
    "Izvor napajanja. Postavlja napon isklju\x83\x1""ivanja. <DC 10V> <S 3.3V po \x86\x1""eliji>";
const char _L_SND_SLEEPTEMPERATURE_HR[] =    // Temperatura na koju se spušta lemilica nakon određenog vremena mirovanja. <C/F>
    "Temperatura na koju se spu\x80\x1""ta lemilica nakon odre\x81\x1""enog vremena mirovanja. <C/F>";
const char _L_SND_SLEEPTIMEOUT_HR[] =    // Vrijeme mirovanja nakon kojega lemilica spušta temperaturu. <Minute/Sekunde>
    "Vrijeme mirovanja nakon kojega lemilica spu\x80\x1""ta temperaturu. <Minute/Sekunde>";
const char _L_SND_SHUTDOWNTIMEOUT_HR[] =    // Vrijeme mirovanja nakon kojega će se lemilica ugasiti. <Minute>
    "Vrijeme mirovanja nakon kojega \x86\x1""e se lemilica ugasiti. <Minute>";
const char _L_SND_MOTIONSENSITIVITY_HR[] =    // Osjetljivost prepoznavanja pokreta. <0=Ugašeno, 1=Najmanje osjetljivo, 9=Najosjetljivije>
    "Osjetljivost prepoznavanja pokreta. <0=Uga\x80\x1""eno, 1=Najmanje osjetljivo, 9=Najosjetljivije>";
const char _L_SND_TEMPERATUREUNIT_HR[] =    // Jedinica temperature. <C=Celzij, F=Fahrenheit>
    "Jedinica temperature. <C=Celzij, F=Fahrenheit>";
const char _L_SND_ADVANCEDIDLE_HR[] =    // Prikazivanje detaljnih informacija tijekom čekanja.
    "Prikazivanje detaljnih informacija tijekom \x83\x1""ekanja.";
const char _L_SND_DISPLAYROTATION_HR[] =    // Orijentacija ekrana. <A=Automatski, L=Ljevoruki, D=Desnoruki>
    "Orijentacija ekrana. <A=Automatski, L=Ljevoruki, D=Desnoruki>";
const char _L_SND_BOOSTENABLED_HR[] =    // Držanjem prednjeg gumba prilikom lemljenja aktivira se pojačani (Boost) način.
    "Dr\x82\x1""anjem prednjeg gumba prilikom lemljenja aktivira se poja\x83\x1""ani (Boost) na\x83\x1""in.";
const char _L_SND_BOOSTTEMPERATURE_HR[] =    // Temperatura u pojačanom (Boost) načinu.
    "Temperatura u poja\x83\x1""anom (Boost) na\x83\x1""inu.";
const char _L_SND_AUTOSTART_HR[] =    // Ako je aktivno, lemilica po uključivanju napajanja odmah počinje grijati.
    "Ako je aktivno, lemilica po uklju\x83\x1""ivanju napajanja odmah po\x83\x1""inje grijati.";
const char _L_SND_COOLDOWNBLINK_HR[] =    // Bljeskanje temperature prilikom hlađenja, ako je lemilica vruća.
    "Bljeskanje temperature prilikom hla\x81\x1""enja, ako je lemilica vru\x86\x1""a.";
const char _L_SND_TEMPERATURECALIBRATION_HR[] =    // Kalibriranje temperature mjeri razliku temperatura vrška i drške, dok je lemilica hladna.
    "Kalibriranje temperature mjeri razliku temperatura vr\x80\x1""ka i dr\x80\x1""ke, dok je lemilica hladna.";
const char _L_SND_SETTINGSRESET_HR[] =    // Vraćanje svih postavki na tvorničke vrijednosti.
    "Vra\x86\x1""anje svih postavki na tvorni\x83\x1""ke vrijednosti.";
const char _L_SND_VOLTAGECALIBRATION_HR[] =    // Kalibracija ulaznog napona. Podešavanje gumbima, dugački pritisak za kraj.
    "Kalibracija ulaznog napona. Pode\x80\x1""avanje gumbima, duga\x83\x1""ki pritisak za kraj.";
const char _L_SND_ADVANCEDSOLDERING_HR[] =    // Prikazivanje detaljnih informacija tijekom lemljenja.
    "Prikazivanje detaljnih informacija tijekom lemljenja.";
const char _L_SND_SCROLLINGSPEED_HR[] =    // Brzina kretanja dugačkih poruka. <B=brzo, S=sporo>
    "Brzina kretanja duga\x83\x1""kih poruka. <B=brzo, S=sporo>";
#define _L_SND_LANGUAGE_HR    _L_SND_LANGUAGE_EN     /*  */

// ================ Translation Strings - Русский (RU) ================

// ---- Message Strings (RU) ----

const char _L_MS_LANGUAGECODE_RU[] =    // RU
    "RU";
const char _L_MS_LANGUAGELOCALNAME_RU[] =    // Русский
    {135,1,136,1,137,1,137,1,138,1,139,1,140,1,0};
const char _L_MS_SETTINGSCALIBRATIONWARNING_RU[] =    // Убедитесь, что жало остыло до комнатной температуры, прежде чем продолжать!
    {141,1,142,1,143,1,144,1,139,1,145,1,143,1,137,1,146,1,44,32,147,1,145,1,148,1,32,149,1,150,1,151,1,148,1,32,148,1,137,1,145,1,152,1,151,1,148,1,32,144,1,148,1,32,138,1,148,1,153,1,154,1,150,1,145,1,154,1,148,1,140,1,32,145,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,152,1,44,32,155,1,156,1,143,1,149,1,144,1,143,1,32,147,1,143,1,153,1,32,155,1,156,1,148,1,144,1,148,1,151,1,149,1,150,1,145,1,146,1,33,0};
const char _L_MS_SETTINGSRESETWARNING_RU[] =    // Вы действительно хотите сбросить настройки до значений по умолчанию?
    {157,1,152,1,32,144,1,143,1,140,1,137,1,145,1,158,1,139,1,145,1,143,1,151,1,146,1,154,1,148,1,32,159,1,148,1,145,1,139,1,145,1,143,1,32,137,1,142,1,156,1,148,1,137,1,139,1,145,1,146,1,32,154,1,150,1,137,1,145,1,156,1,148,1,140,1,138,1,139,1,32,144,1,148,1,32,160,1,154,1,150,1,147,1,143,1,154,1,139,1,140,1,32,155,1,148,1,32,136,1,153,1,148,1,151,1,147,1,150,1,154,1,139,1,161,1,63,0};
const char _L_MS_UVLOWARNINGSTRING_RU[] =    // АККУМ--
    {162,1,163,1,163,1,141,1,164,1,45,45,0};
const char _L_MS_UNDERVOLTAGESTRING_RU[] =    // Под питанием
    {165,1,148,1,144,1,32,155,1,139,1,145,1,150,1,154,1,139,1,143,1,153,1,0};
const char _L_MS_INPUTVOLTAGESTRING_RU[] =    // Питание(B):
    {165,1,139,1,145,1,150,1,154,1,139,1,143,1,40,66,41,58,0};
const char _L_MS_WARNINGTIPTEMPSTRING_RU[] =    // Жало t°:
    "\xA6\x1\x96\x1\x97\x1\x94\x1"" t\xA7\x1"": ";
const char _L_MS_BADTIPSTRING_RU[] =    // Жало--
    {166,1,150,1,151,1,148,1,45,45,0};
const char _L_MS_SLEEPINGSIMPLESTRING_RU[] =    // Сон
    {168,1,148,1,154,1,0};
const char _L_MS_SLEEPINGADVANCEDSTRING_RU[] =    // Ожидание...
    {169,1,149,1,139,1,144,1,150,1,154,1,139,1,143,1,46,46,46,0};
const char _L_MS_WARNINGSIMPLESTRING_RU[] =    //  АЙ!
    " \xA2\x1\xAA\x1""!";
const char _L_MS_WARNINGADVANCEDSTRING_RU[] =    // ВНИМАНИЕ ГОРЯЧО!
    {157,1,171,1,172,1,164,1,162,1,171,1,172,1,173,1,32,174,1,169,1,135,1,175,1,176,1,169,1,33,0};
const char _L_MS_SLEEPINGTIPADVANCEDSTRING_RU[] =    // Жало:
    {166,1,150,1,151,1,148,1,58,0};
#define _L_MS_IDLETIPSTRING_RU    _L_MS_SLEEPINGTIPADVANCEDSTRING_RU     /* Жало: */
const char _L_MS_IDLESETSTRING_RU[] =    //  ->
    " ->";
const char _L_MS_TIPDISCONNECTEDSTRING_RU[] =    // Жало отключено!
    {166,1,150,1,151,1,148,1,32,148,1,145,1,138,1,151,1,161,1,147,1,143,1,154,1,148,1,33,0};
const char _L_MS_SOLDERINGADVANCEDPOWERPROMPT_RU[] =    // Питание:
    {165,1,139,1,145,1,150,1,154,1,139,1,143,1,58,32,0};
#define _L_MS_RESETOK_RU    _L_MS_RESETOK_EN     /* RESET OK */
#define _L_MS_OFFSTRING_RU    _L_MS_OFFSTRING_EN     /* Off */
const char _L_MS_SETTINGRIGHTCHAR_RU[] =    // П
    {165,1,0};
const char _L_MS_SETTINGLEFTCHAR_RU[] =    // Л
    {177,1,0};
#define _L_MS_SETTINGAUTOCHAR_RU    _L_MS_SETTINGAUTOCHAR_EN     /* A */
const char _L_MS_SETTINGFASTCHAR_RU[] =    // +
    "+";
const char _L_MS_SETTINGSLOWCHAR_RU[] =    // -
    "-";

// ---- Settings Groups (RU) ----

const char _L_SG_SOLDERINGMENU_RU[] =    // Пайка|
    {165,1,150,1,140,1,138,1,150,1,10,0};
const char _L_SG_POWERSAVINGMENU_RU[] =    // Сон|
    {168,1,148,1,154,1,10,0};
const char _L_SG_UIMENU_RU[] =    // Интерфейс|
    {172,1,154,1,145,1,143,1,156,1,178,1,143,1,140,1,137,1,10,0};
const char _L_SG_ADVANCEDMENU_RU[] =    // Другие|
    {179,1,156,1,136,1,180,1,139,1,143,1,10,0};

// ---- Settings Groups Descriptions (RU) ----

const char _L_SGD_SOLDERINGMENU_RU[] =    // Настройки для режима пайки. Действуют при включенном жале.
    {171,1,150,1,137,1,145,1,156,1,148,1,140,1,138,1,139,1,32,144,1,151,1,181,1,32,156,1,143,1,149,1,139,1,153,1,150,1,32,155,1,150,1,140,1,138,1,139,1,46,32,179,1,143,1,140,1,137,1,145,1,158,1,136,1,161,1,145,1,32,155,1,156,1,139,1,32,158,1,138,1,151,1,161,1,147,1,143,1,154,1,154,1,148,1,153,1,32,149,1,150,1,151,1,143,1,46,0};
const char _L_SGD_POWERSAVINGMENU_RU[] =    // Настройки при бездействии. Полезно что бы не обжечься и случайно не сжечь жилище.
    {171,1,150,1,137,1,145,1,156,1,148,1,140,1,138,1,139,1,32,155,1,156,1,139,1,32,142,1,143,1,160,1,144,1,143,1,140,1,137,1,145,1,158,1,139,1,139,1,46,32,165,1,148,1,151,1,143,1,160,1,154,1,148,1,32,147,1,145,1,148,1,32,142,1,152,1,32,154,1,143,1,32,148,1,142,1,149,1,143,1,147,1,146,1,137,1,181,1,32,139,1,32,137,1,151,1,136,1,147,1,150,1,140,1,154,1,148,1,32,154,1,143,1,32,137,1,149,1,143,1,147,1,146,1,32,149,1,139,1,151,1,139,1,182,1,143,1,46,0};
const char _L_SGD_UIMENU_RU[] =    // Пользовательский интерфейс
    {165,1,148,1,151,1,146,1,160,1,148,1,158,1,150,1,145,1,143,1,151,1,146,1,137,1,138,1,139,1,140,1,32,139,1,154,1,145,1,143,1,156,1,178,1,143,1,140,1,137,1,0};
const char _L_SGD_ADVANCEDMENU_RU[] =    // Расширенные настройки. Дополнительные удобства.
    {135,1,150,1,137,1,183,1,139,1,156,1,143,1,154,1,154,1,152,1,143,1,32,154,1,150,1,137,1,145,1,156,1,148,1,140,1,138,1,139,1,46,32,179,1,148,1,155,1,148,1,151,1,154,1,139,1,145,1,143,1,151,1,146,1,154,1,152,1,143,1,32,136,1,144,1,148,1,142,1,137,1,145,1,158,1,150,1,46,0};

// ---- Settings Names (RU) ----

const char _L_SN_POWERSOURCE_RU[] =    // Источник|питания
    {172,1,137,1,145,1,148,1,147,1,154,1,139,1,138,1,10,155,1,139,1,145,1,150,1,154,1,139,1,181,1,0};
const char _L_SN_SLEEPTEMPERATURE_RU[] =    // Темпер.|сна
    {184,1,143,1,153,1,155,1,143,1,156,1,46,10,137,1,154,1,150,1,0};
const char _L_SN_SLEEPTIMEOUT_RU[] =    // Таймаут|сна
    {184,1,150,1,140,1,153,1,150,1,136,1,145,1,10,137,1,154,1,150,1,0};
const char _L_SN_SHUTDOWNTIMEOUT_RU[] =    // Время до|отключения
    {157,1,156,1,143,1,153,1,181,1,32,144,1,148,1,10,148,1,145,1,138,1,151,1,161,1,147,1,143,1,154,1,139,1,181,1,0};
const char _L_SN_MOTIONSENSITIVITY_RU[] =    // Чувст. сенсо-|ра движения
    {176,1,136,1,158,1,137,1,145,1,46,32,137,1,143,1,154,1,137,1,148,1,45,10,156,1,150,1,32,144,1,158,1,139,1,149,1,143,1,154,1,139,1,181,1,0};
const char _L_SN_TEMPERATUREUNIT_RU[] =    // Формат темпе-|ратуры(C°/F°)
    {185,1,148,1,156,1,153,1,150,1,145,1,32,145,1,143,1,153,1,155,1,143,1,45,10,156,1,150,1,145,1,136,1,156,1,152,1,40,67,167,1,47,70,167,1,41,0};
const char _L_SN_ADVANCEDIDLE_RU[] =    // Подробный ре-|жим ожидания
    {165,1,148,1,144,1,156,1,148,1,142,1,154,1,152,1,140,1,32,156,1,143,1,45,10,149,1,139,1,153,1,32,148,1,149,1,139,1,144,1,150,1,154,1,139,1,181,1,0};
const char _L_SN_DISPLAYROTATION_RU[] =    // Автоповорот|экрана
    {162,1,158,1,145,1,148,1,155,1,148,1,158,1,148,1,156,1,148,1,145,1,10,186,1,138,1,156,1,150,1,154,1,150,1,0};
const char _L_SN_BOOSTENABLED_RU[] =    // Режим|Турбо
    {135,1,143,1,149,1,139,1,153,1,10,184,1,136,1,156,1,142,1,148,1,0};
const char _L_SN_BOOSTTEMPERATURE_RU[] =    // Темпер.|Турбо
    {184,1,143,1,153,1,155,1,143,1,156,1,46,10,184,1,136,1,156,1,142,1,148,1,0};
const char _L_SN_AUTOSTART_RU[] =    // Горячий|старт
    {174,1,148,1,156,1,181,1,147,1,139,1,140,1,10,137,1,145,1,150,1,156,1,145,1,0};
const char _L_SN_COOLDOWNBLINK_RU[] =    // Показ t° при|остывании
    {165,1,148,1,138,1,150,1,160,1,32,116,167,1,32,155,1,156,1,139,1,10,148,1,137,1,145,1,152,1,158,1,150,1,154,1,139,1,139,1,0};
const char _L_SN_TEMPERATURECALIBRATION_RU[] =    // Калибровка|температуры
    {163,1,150,1,151,1,139,1,142,1,156,1,148,1,158,1,138,1,150,1,10,145,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,152,1,0};
const char _L_SN_SETTINGSRESET_RU[] =    // Сбросить все|настройки
    {168,1,142,1,156,1,148,1,137,1,139,1,145,1,146,1,32,158,1,137,1,143,1,10,154,1,150,1,137,1,145,1,156,1,148,1,140,1,138,1,139,1,0};
const char _L_SN_VOLTAGECALIBRATION_RU[] =    // Калибровка|напряжения
    {163,1,150,1,151,1,139,1,142,1,156,1,148,1,158,1,138,1,150,1,10,154,1,150,1,155,1,156,1,181,1,149,1,143,1,154,1,139,1,181,1,0};
const char _L_SN_ADVANCEDSOLDERING_RU[] =    // Подробный ре-|напряжения
    {165,1,148,1,144,1,156,1,148,1,142,1,154,1,152,1,140,1,32,156,1,143,1,45,10,154,1,150,1,155,1,156,1,181,1,149,1,143,1,154,1,139,1,181,1,0};
const char _L_SN_SCROLLINGSPEED_RU[] =    // Скорость|текста
    {168,1,138,1,148,1,156,1,148,1,137,1,145,1,146,1,10,145,1,143,1,138,1,137,1,145,1,150,1,0};
const char _L_SN_LANGUAGE_RU[] =    // Язык|
    {175,1,160,1,152,1,138,1,10,0};

// ---- Settings Descriptions (RU) ----

const char _L_SND_POWERSOURCE_RU[] =    // Установка напряжения отключения <DC=10V, 3S=9.9V, 4S=13.2V, 5S=16.5V, 6S=19.8V>
    "\x8D\x1\x89\x1\x91\x1\x96\x1\x9A\x1\x94\x1\x9E\x1\x8A\x1\x96\x1"" \x9A\x1\x96\x1\x9B\x1\x9C\x1\xB5\x1\x95\x1\x8F\x1\x9A\x1\x8B\x1\xB5\x1"" \x94\x1\x91\x1\x8A\x1\x97\x1\xA1\x1\x93\x1\x8F\x1\x9A\x1\x8B\x1\xB5\x1"" <DC=10V, 3S=9.9V, 4S=13.2V, 5S=16.5V, 6S=19.8V>";
const char _L_SND_SLEEPTEMPERATURE_RU[] =    // Температура режима ожидания <C°/F°>
    {184,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,150,1,32,156,1,143,1,149,1,139,1,153,1,150,1,32,148,1,149,1,139,1,144,1,150,1,154,1,139,1,181,1,32,60,67,167,1,47,70,167,1,62,0};
const char _L_SND_SLEEPTIMEOUT_RU[] =    // Время до перехода в режим ожидания <Доступно отключение>
    {157,1,156,1,143,1,153,1,181,1,32,144,1,148,1,32,155,1,143,1,156,1,143,1,159,1,148,1,144,1,150,1,32,158,1,32,156,1,143,1,149,1,139,1,153,1,32,148,1,149,1,139,1,144,1,150,1,154,1,139,1,181,1,32,60,179,1,148,1,137,1,145,1,136,1,155,1,154,1,148,1,32,148,1,145,1,138,1,151,1,161,1,147,1,143,1,154,1,139,1,143,1,62,0};
const char _L_SND_SHUTDOWNTIMEOUT_RU[] =    // Время до отключения <Доступно отключение>
    {157,1,156,1,143,1,153,1,181,1,32,144,1,148,1,32,148,1,145,1,138,1,151,1,161,1,147,1,143,1,154,1,139,1,181,1,32,60,179,1,148,1,137,1,145,1,136,1,155,1,154,1,148,1,32,148,1,145,1,138,1,151,1,161,1,147,1,143,1,154,1,139,1,143,1,62,0};
const char _L_SND_MOTIONSENSITIVITY_RU[] =    // Акселерометр <0=Выкл., 1=мин. чувствительный, 9=макс. чувствительный>
    {162,1,138,1,137,1,143,1,151,1,143,1,156,1,148,1,153,1,143,1,145,1,156,1,32,60,48,61,157,1,152,1,138,1,151,1,46,44,32,49,61,153,1,139,1,154,1,46,32,147,1,136,1,158,1,137,1,145,1,158,1,139,1,145,1,143,1,151,1,146,1,154,1,152,1,140,1,44,32,57,61,153,1,150,1,138,1,137,1,46,32,147,1,136,1,158,1,137,1,145,1,158,1,139,1,145,1,143,1,151,1,146,1,154,1,152,1,140,1,62,0};
const char _L_SND_TEMPERATUREUNIT_RU[] =    // Единица измерения температуры <C=Цельсий, F=Фаренгейт>
    {173,1,144,1,139,1,154,1,139,1,187,1,150,1,32,139,1,160,1,153,1,143,1,156,1,143,1,154,1,139,1,181,1,32,145,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,152,1,32,60,67,61,188,1,143,1,151,1,146,1,137,1,139,1,140,1,44,32,70,61,185,1,150,1,156,1,143,1,154,1,180,1,143,1,140,1,145,1,62,0};
const char _L_SND_ADVANCEDIDLE_RU[] =    // Показывать детальную в режиме настроек <Вместо картинки>
    {165,1,148,1,138,1,150,1,160,1,152,1,158,1,150,1,145,1,146,1,32,144,1,143,1,145,1,150,1,151,1,146,1,154,1,136,1,161,1,32,158,1,32,156,1,143,1,149,1,139,1,153,1,143,1,32,154,1,150,1,137,1,145,1,156,1,148,1,143,1,138,1,32,60,157,1,153,1,143,1,137,1,145,1,148,1,32,138,1,150,1,156,1,145,1,139,1,154,1,138,1,139,1,62,0};
const char _L_SND_DISPLAYROTATION_RU[] =    // Ориентация дисплея <A=Автоповорот, L=Левша, R=Правша>
    {169,1,156,1,139,1,143,1,154,1,145,1,150,1,187,1,139,1,181,1,32,144,1,139,1,137,1,155,1,151,1,143,1,181,1,32,60,65,61,162,1,158,1,145,1,148,1,155,1,148,1,158,1,148,1,156,1,148,1,145,1,44,32,76,61,177,1,143,1,158,1,183,1,150,1,44,32,82,61,165,1,156,1,150,1,158,1,183,1,150,1,62,0};
const char _L_SND_BOOSTENABLED_RU[] =    // Турбо-режим при удержании кнопки А при пайке
    {184,1,136,1,156,1,142,1,148,1,45,156,1,143,1,149,1,139,1,153,1,32,155,1,156,1,139,1,32,136,1,144,1,143,1,156,1,149,1,150,1,154,1,139,1,139,1,32,138,1,154,1,148,1,155,1,138,1,139,1,32,162,1,32,155,1,156,1,139,1,32,155,1,150,1,140,1,138,1,143,1,0};
const char _L_SND_BOOSTTEMPERATURE_RU[] =    // Температура в Турбо-режиме
    {184,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,150,1,32,158,1,32,184,1,136,1,156,1,142,1,148,1,45,156,1,143,1,149,1,139,1,153,1,143,1,0};
const char _L_SND_AUTOSTART_RU[] =    // Автоматический переход в режим пайки при включении питания
    {162,1,158,1,145,1,148,1,153,1,150,1,145,1,139,1,147,1,143,1,137,1,138,1,139,1,140,1,32,155,1,143,1,156,1,143,1,159,1,148,1,144,1,32,158,1,32,156,1,143,1,149,1,139,1,153,1,32,155,1,150,1,140,1,138,1,139,1,32,155,1,156,1,139,1,32,158,1,138,1,151,1,161,1,147,1,143,1,154,1,139,1,139,1,32,155,1,139,1,145,1,150,1,154,1,139,1,181,1,0};
const char _L_SND_COOLDOWNBLINK_RU[] =    // Показывать температуру на экране охлаждения, пока жало остается горячим, при этом экран моргает
    {165,1,148,1,138,1,150,1,160,1,152,1,158,1,150,1,145,1,146,1,32,145,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,136,1,32,154,1,150,1,32,186,1,138,1,156,1,150,1,154,1,143,1,32,148,1,159,1,151,1,150,1,149,1,144,1,143,1,154,1,139,1,181,1,44,32,155,1,148,1,138,1,150,1,32,149,1,150,1,151,1,148,1,32,148,1,137,1,145,1,150,1,143,1,145,1,137,1,181,1,32,180,1,148,1,156,1,181,1,147,1,139,1,153,1,44,32,155,1,156,1,139,1,32,186,1,145,1,148,1,153,1,32,186,1,138,1,156,1,150,1,154,1,32,153,1,148,1,156,1,180,1,150,1,143,1,145,1,0};
const char _L_SND_TEMPERATURECALIBRATION_RU[] =    // Калибровка температурного датчика
    {163,1,150,1,151,1,139,1,142,1,156,1,148,1,158,1,138,1,150,1,32,145,1,143,1,153,1,155,1,143,1,156,1,150,1,145,1,136,1,156,1,154,1,148,1,180,1,148,1,32,144,1,150,1,145,1,147,1,139,1,138,1,150,1,0};
const char _L_SND_SETTINGSRESET_RU[] =    // Сброс всех настроек к исходным значения
    {168,1,142,1,156,1,148,1,137,1,32,158,1,137,1,143,1,159,1,32,154,1,150,1,137,1,145,1,156,1,148,1,143,1,138,1,32,138,1,32,139,1,137,1,159,1,148,1,144,1,154,1,152,1,153,1,32,160,1,154,1,150,1,147,1,143,1,154,1,139,1,181,1,0};
const char _L_SND_VOLTAGECALIBRATION_RU[] =    // Калибровка напряжения входа. Настройка кнопками, нажать и удержать чтобы завершить.
    {163,1,150,1,151,1,139,1,142,1,156,1,148,1,158,1,138,1,150,1,32,154,1,150,1,155,1,156,1,181,1,149,1,143,1,154,1,139,1,181,1,32,158,1,159,1,148,1,144,1,150,1,46,32,171,1,150,1,137,1,145,1,156,1,148,1,140,1,138,1,150,1,32,138,1,154,1,148,1,155,1,138,1,150,1,153,1,139,1,44,32,154,1,150,1,149,1,150,1,145,1,146,1,32,139,1,32,136,1,144,1,143,1,156,1,149,1,150,1,145,1,146,1,32,147,1,145,1,148,1,142,1,152,1,32,160,1,150,1,158,1,143,1,156,1,183,1,139,1,145,1,146,1,46,0};
const char _L_SND_ADVANCEDSOLDERING_RU[] =    // Показывать детальную информацию при пайке
    {165,1,148,1,138,1,150,1,160,1,152,1,158,1,150,1,145,1,146,1,32,144,1,143,1,145,1,150,1,151,1,146,1,154,1,136,1,161,1,32,139,1,154,1,178,1,148,1,156,1,153,1,150,1,187,1,139,1,161,1,32,155,1,156,1,139,1,32,155,1,150,1,140,1,138,1,143,1,0};
const char _L_SND_SCROLLINGSPEED_RU[] =    // Скорость прокрутки текста
    {168,1,138,1,148,1,156,1,148,1,137,1,145,1,146,1,32,155,1,156,1,148,1,138,1,156,1,136,1,145,1,138,1,139,1,32,145,1,143,1,138,1,137,1,145,1,150,1,0};
#define _L_SND_LANGUAGE_RU    _L_SND_LANGUAGE_EN     /*  */

// ================ MENU TYPES PER LANGUAGE ================

const ShortNameType L_MENU_TYPE[] = {
    SHORT_NAME_DOUBLE_LINE,    /* EN */
    SHORT_NAME_DOUBLE_LINE,    /* HR */
    SHORT_NAME_DOUBLE_LINE,    /* RU */
};

// ================ STRING POINTER ARRAYS ================

// ---- Pointer Array: Messages ----

const char* const L_ARR_MS[25][LANG_COUNT] = {
  { _L_MS_LANGUAGECODE_EN, _L_MS_LANGUAGECODE_HR, _L_MS_LANGUAGECODE_RU,  },
  { _L_MS_LANGUAGELOCALNAME_EN, _L_MS_LANGUAGELOCALNAME_HR, _L_MS_LANGUAGELOCALNAME_RU,  },
  { _L_MS_SETTINGSCALIBRATIONWARNING_EN, _L_MS_SETTINGSCALIBRATIONWARNING_HR, _L_MS_SETTINGSCALIBRATIONWARNING_RU,  },
  { _L_MS_SETTINGSRESETWARNING_EN, _L_MS_SETTINGSRESETWARNING_HR, _L_MS_SETTINGSRESETWARNING_RU,  },
  { _L_MS_UVLOWARNINGSTRING_EN, _L_MS_UVLOWARNINGSTRING_HR, _L_MS_UVLOWARNINGSTRING_RU,  },
  { _L_MS_UNDERVOLTAGESTRING_EN, _L_MS_UNDERVOLTAGESTRING_HR, _L_MS_UNDERVOLTAGESTRING_RU,  },
  { _L_MS_INPUTVOLTAGESTRING_EN, _L_MS_INPUTVOLTAGESTRING_HR, _L_MS_INPUTVOLTAGESTRING_RU,  },
  { _L_MS_WARNINGTIPTEMPSTRING_EN, _L_MS_WARNINGTIPTEMPSTRING_HR, _L_MS_WARNINGTIPTEMPSTRING_RU,  },
  { _L_MS_BADTIPSTRING_EN, _L_MS_BADTIPSTRING_HR, _L_MS_BADTIPSTRING_RU,  },
  { _L_MS_SLEEPINGSIMPLESTRING_EN, _L_MS_SLEEPINGSIMPLESTRING_HR, _L_MS_SLEEPINGSIMPLESTRING_RU,  },
  { _L_MS_SLEEPINGADVANCEDSTRING_EN, _L_MS_SLEEPINGADVANCEDSTRING_HR, _L_MS_SLEEPINGADVANCEDSTRING_RU,  },
  { _L_MS_WARNINGSIMPLESTRING_EN, _L_MS_WARNINGSIMPLESTRING_HR, _L_MS_WARNINGSIMPLESTRING_RU,  },
  { _L_MS_WARNINGADVANCEDSTRING_EN, _L_MS_WARNINGADVANCEDSTRING_HR, _L_MS_WARNINGADVANCEDSTRING_RU,  },
  { _L_MS_SLEEPINGTIPADVANCEDSTRING_EN, _L_MS_SLEEPINGTIPADVANCEDSTRING_HR, _L_MS_SLEEPINGTIPADVANCEDSTRING_RU,  },
  { _L_MS_IDLETIPSTRING_EN, _L_MS_IDLETIPSTRING_HR, _L_MS_IDLETIPSTRING_RU,  },
  { _L_MS_IDLESETSTRING_EN, _L_MS_IDLESETSTRING_HR, _L_MS_IDLESETSTRING_RU,  },
  { _L_MS_TIPDISCONNECTEDSTRING_EN, _L_MS_TIPDISCONNECTEDSTRING_HR, _L_MS_TIPDISCONNECTEDSTRING_RU,  },
  { _L_MS_SOLDERINGADVANCEDPOWERPROMPT_EN, _L_MS_SOLDERINGADVANCEDPOWERPROMPT_HR, _L_MS_SOLDERINGADVANCEDPOWERPROMPT_RU,  },
  { _L_MS_RESETOK_EN, _L_MS_RESETOK_HR, _L_MS_RESETOK_RU,  },
  { _L_MS_OFFSTRING_EN, _L_MS_OFFSTRING_HR, _L_MS_OFFSTRING_RU,  },
  { _L_MS_SETTINGRIGHTCHAR_EN, _L_MS_SETTINGRIGHTCHAR_HR, _L_MS_SETTINGRIGHTCHAR_RU,  },
  { _L_MS_SETTINGLEFTCHAR_EN, _L_MS_SETTINGLEFTCHAR_HR, _L_MS_SETTINGLEFTCHAR_RU,  },
  { _L_MS_SETTINGAUTOCHAR_EN, _L_MS_SETTINGAUTOCHAR_HR, _L_MS_SETTINGAUTOCHAR_RU,  },
  { _L_MS_SETTINGFASTCHAR_EN, _L_MS_SETTINGFASTCHAR_HR, _L_MS_SETTINGFASTCHAR_RU,  },
  { _L_MS_SETTINGSLOWCHAR_EN, _L_MS_SETTINGSLOWCHAR_HR, _L_MS_SETTINGSLOWCHAR_RU,  },
};

// ---- Pointer Array: Settings Groups ----

const char* const L_ARR_SG[4][LANG_COUNT] = {
  { _L_SG_SOLDERINGMENU_EN, _L_SG_SOLDERINGMENU_HR, _L_SG_SOLDERINGMENU_RU,  },
  { _L_SG_POWERSAVINGMENU_EN, _L_SG_POWERSAVINGMENU_HR, _L_SG_POWERSAVINGMENU_RU,  },
  { _L_SG_UIMENU_EN, _L_SG_UIMENU_HR, _L_SG_UIMENU_RU,  },
  { _L_SG_ADVANCEDMENU_EN, _L_SG_ADVANCEDMENU_HR, _L_SG_ADVANCEDMENU_RU,  },
};

// ---- Pointer Array: Settings Groups Descriptions ----

const char* const L_ARR_SGD[4][LANG_COUNT] = {
  { _L_SGD_SOLDERINGMENU_EN, _L_SGD_SOLDERINGMENU_HR, _L_SGD_SOLDERINGMENU_RU,  },
  { _L_SGD_POWERSAVINGMENU_EN, _L_SGD_POWERSAVINGMENU_HR, _L_SGD_POWERSAVINGMENU_RU,  },
  { _L_SGD_UIMENU_EN, _L_SGD_UIMENU_HR, _L_SGD_UIMENU_RU,  },
  { _L_SGD_ADVANCEDMENU_EN, _L_SGD_ADVANCEDMENU_HR, _L_SGD_ADVANCEDMENU_RU,  },
};

// ---- Pointer Array: Settings Names ----

const char* const L_ARR_SN[18][LANG_COUNT] = {
  { _L_SN_POWERSOURCE_EN, _L_SN_POWERSOURCE_HR, _L_SN_POWERSOURCE_RU,  },
  { _L_SN_SLEEPTEMPERATURE_EN, _L_SN_SLEEPTEMPERATURE_HR, _L_SN_SLEEPTEMPERATURE_RU,  },
  { _L_SN_SLEEPTIMEOUT_EN, _L_SN_SLEEPTIMEOUT_HR, _L_SN_SLEEPTIMEOUT_RU,  },
  { _L_SN_SHUTDOWNTIMEOUT_EN, _L_SN_SHUTDOWNTIMEOUT_HR, _L_SN_SHUTDOWNTIMEOUT_RU,  },
  { _L_SN_MOTIONSENSITIVITY_EN, _L_SN_MOTIONSENSITIVITY_HR, _L_SN_MOTIONSENSITIVITY_RU,  },
  { _L_SN_TEMPERATUREUNIT_EN, _L_SN_TEMPERATUREUNIT_HR, _L_SN_TEMPERATUREUNIT_RU,  },
  { _L_SN_ADVANCEDIDLE_EN, _L_SN_ADVANCEDIDLE_HR, _L_SN_ADVANCEDIDLE_RU,  },
  { _L_SN_DISPLAYROTATION_EN, _L_SN_DISPLAYROTATION_HR, _L_SN_DISPLAYROTATION_RU,  },
  { _L_SN_BOOSTENABLED_EN, _L_SN_BOOSTENABLED_HR, _L_SN_BOOSTENABLED_RU,  },
  { _L_SN_BOOSTTEMPERATURE_EN, _L_SN_BOOSTTEMPERATURE_HR, _L_SN_BOOSTTEMPERATURE_RU,  },
  { _L_SN_AUTOSTART_EN, _L_SN_AUTOSTART_HR, _L_SN_AUTOSTART_RU,  },
  { _L_SN_COOLDOWNBLINK_EN, _L_SN_COOLDOWNBLINK_HR, _L_SN_COOLDOWNBLINK_RU,  },
  { _L_SN_TEMPERATURECALIBRATION_EN, _L_SN_TEMPERATURECALIBRATION_HR, _L_SN_TEMPERATURECALIBRATION_RU,  },
  { _L_SN_SETTINGSRESET_EN, _L_SN_SETTINGSRESET_HR, _L_SN_SETTINGSRESET_RU,  },
  { _L_SN_VOLTAGECALIBRATION_EN, _L_SN_VOLTAGECALIBRATION_HR, _L_SN_VOLTAGECALIBRATION_RU,  },
  { _L_SN_ADVANCEDSOLDERING_EN, _L_SN_ADVANCEDSOLDERING_HR, _L_SN_ADVANCEDSOLDERING_RU,  },
  { _L_SN_SCROLLINGSPEED_EN, _L_SN_SCROLLINGSPEED_HR, _L_SN_SCROLLINGSPEED_RU,  },
  { _L_SN_LANGUAGE_EN, _L_SN_LANGUAGE_HR, _L_SN_LANGUAGE_RU,  },
};

// ---- Pointer Array: Settings Names Descriptions ----

const char* const L_ARR_SND[18][LANG_COUNT] = {
  { _L_SND_POWERSOURCE_EN, _L_SND_POWERSOURCE_HR, _L_SND_POWERSOURCE_RU,  },
  { _L_SND_SLEEPTEMPERATURE_EN, _L_SND_SLEEPTEMPERATURE_HR, _L_SND_SLEEPTEMPERATURE_RU,  },
  { _L_SND_SLEEPTIMEOUT_EN, _L_SND_SLEEPTIMEOUT_HR, _L_SND_SLEEPTIMEOUT_RU,  },
  { _L_SND_SHUTDOWNTIMEOUT_EN, _L_SND_SHUTDOWNTIMEOUT_HR, _L_SND_SHUTDOWNTIMEOUT_RU,  },
  { _L_SND_MOTIONSENSITIVITY_EN, _L_SND_MOTIONSENSITIVITY_HR, _L_SND_MOTIONSENSITIVITY_RU,  },
  { _L_SND_TEMPERATUREUNIT_EN, _L_SND_TEMPERATUREUNIT_HR, _L_SND_TEMPERATUREUNIT_RU,  },
  { _L_SND_ADVANCEDIDLE_EN, _L_SND_ADVANCEDIDLE_HR, _L_SND_ADVANCEDIDLE_RU,  },
  { _L_SND_DISPLAYROTATION_EN, _L_SND_DISPLAYROTATION_HR, _L_SND_DISPLAYROTATION_RU,  },
  { _L_SND_BOOSTENABLED_EN, _L_SND_BOOSTENABLED_HR, _L_SND_BOOSTENABLED_RU,  },
  { _L_SND_BOOSTTEMPERATURE_EN, _L_SND_BOOSTTEMPERATURE_HR, _L_SND_BOOSTTEMPERATURE_RU,  },
  { _L_SND_AUTOSTART_EN, _L_SND_AUTOSTART_HR, _L_SND_AUTOSTART_RU,  },
  { _L_SND_COOLDOWNBLINK_EN, _L_SND_COOLDOWNBLINK_HR, _L_SND_COOLDOWNBLINK_RU,  },
  { _L_SND_TEMPERATURECALIBRATION_EN, _L_SND_TEMPERATURECALIBRATION_HR, _L_SND_TEMPERATURECALIBRATION_RU,  },
  { _L_SND_SETTINGSRESET_EN, _L_SND_SETTINGSRESET_HR, _L_SND_SETTINGSRESET_RU,  },
  { _L_SND_VOLTAGECALIBRATION_EN, _L_SND_VOLTAGECALIBRATION_HR, _L_SND_VOLTAGECALIBRATION_RU,  },
  { _L_SND_ADVANCEDSOLDERING_EN, _L_SND_ADVANCEDSOLDERING_HR, _L_SND_ADVANCEDSOLDERING_RU,  },
  { _L_SND_SCROLLINGSPEED_EN, _L_SND_SCROLLINGSPEED_HR, _L_SND_SCROLLINGSPEED_RU,  },
  { _L_SND_LANGUAGE_EN, _L_SND_LANGUAGE_HR, _L_SND_LANGUAGE_RU,  },
};

// ================ FONT 12x16 ================
const uint8_t FONT_12x16[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //    #32     20
0x00,0x00,0x00,0x00,0x7c,0xff,0xff,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x33,0x00,0x00,0x00,0x00,0x00, //    #33  !  21
0x00,0x00,0x00,0x3c,0x3c,0x00,0x00,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //    #34  "  22
0x00,0x00,0x10,0x90,0xf0,0x7e,0x1e,0x90,0xf0,0x7e,0x1e,0x10,0x00,0x02,0x1e,0x1f,0x03,0x02,0x1e,0x1f,0x03,0x02,0x00,0x00, //    #35  #  23
0x00,0x00,0x78,0xfc,0xcc,0xff,0xff,0xcc,0xcc,0x88,0x00,0x00,0x00,0x00,0x04,0x0c,0x0c,0x3f,0x3f,0x0c,0x0f,0x07,0x00,0x00, //    #36  $  24
0x00,0x00,0x38,0x38,0x38,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x00,0x30,0x38,0x1c,0x0e,0x07,0x03,0x01,0x38,0x38,0x38,0x00, //    #37  %  25
0x00,0x00,0x00,0xb8,0xfc,0xc6,0xe2,0x3e,0x1c,0x00,0x00,0x00,0x00,0x00,0x1f,0x3f,0x31,0x21,0x37,0x1e,0x1c,0x36,0x22,0x00, //    #38  &  26
0x00,0x00,0x00,0x00,0x27,0x3f,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //    #39  '  27
0x00,0x00,0x00,0xf0,0xfc,0xfe,0x07,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0f,0x1f,0x38,0x20,0x20,0x00,0x00,0x00, //    #40  (  28
0x00,0x00,0x00,0x01,0x01,0x07,0xfe,0xfc,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x38,0x1f,0x0f,0x03,0x00,0x00,0x00, //    #41  )  29
0x00,0x00,0x98,0xb8,0xe0,0xf8,0xf8,0xe0,0xb8,0x98,0x00,0x00,0x00,0x00,0x0c,0x0e,0x03,0x0f,0x0f,0x03,0x0e,0x0c,0x00,0x00, //    #42  *  2a
0x00,0x00,0x80,0x80,0x80,0xf0,0xf0,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x0f,0x0f,0x01,0x01,0x01,0x00,0x00, //    #43  +  2b
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0xf8,0x78,0x00,0x00,0x00,0x00,0x00, //    #44  ,  2c
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00, //    #45  -  2d
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00, //    #46  .  2e
0x00,0x00,0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x00,0x18,0x1c,0x0e,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00, //    #47  /  2f
0x00,0xf8,0xfe,0x06,0x03,0x83,0xc3,0x63,0x33,0x1e,0xfe,0xf8,0x00,0x07,0x1f,0x1e,0x33,0x31,0x30,0x30,0x30,0x18,0x1f,0x07, //    #48  0  30
0x00,0x00,0x00,0x0c,0x0c,0x0e,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x3f,0x3f,0x30,0x30,0x30,0x00, //    #49  1  31
0x00,0x1c,0x1e,0x07,0x03,0x03,0x83,0xc3,0xe3,0x77,0x3e,0x1c,0x00,0x30,0x38,0x3c,0x3e,0x37,0x33,0x31,0x30,0x30,0x30,0x30, //    #50  2  32
0x00,0x0c,0x0e,0x07,0xc3,0xc3,0xc3,0xc3,0xc3,0xe7,0x7e,0x3c,0x00,0x0c,0x1c,0x38,0x30,0x30,0x30,0x30,0x30,0x39,0x1f,0x0e, //    #51  3  33
0x00,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x07,0xff,0xff,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x3f,0x3f,0x03,0x03, //    #52  4  34
0x00,0x3f,0x7f,0x63,0x63,0x63,0x63,0x63,0x63,0xe3,0xc3,0x83,0x00,0x0c,0x1c,0x38,0x30,0x30,0x30,0x30,0x30,0x38,0x1f,0x0f, //    #53  5  35
0x00,0xc0,0xf0,0xf8,0xdc,0xce,0xc7,0xc3,0xc3,0xc3,0x80,0x00,0x00,0x0f,0x1f,0x39,0x30,0x30,0x30,0x30,0x30,0x39,0x1f,0x0f, //    #54  6  36
0x00,0x03,0x03,0x03,0x03,0x03,0x03,0xc3,0xf3,0x3f,0x0f,0x03,0x00,0x00,0x00,0x00,0x30,0x3c,0x0f,0x03,0x00,0x00,0x00,0x00, //    #55  7  37
0x00,0x00,0xbc,0xfe,0xe7,0xc3,0xc3,0xc3,0xe7,0xfe,0xbc,0x00,0x00,0x0f,0x1f,0x39,0x30,0x30,0x30,0x30,0x30,0x39,0x1f,0x0f, //    #56  8  38
0x00,0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,0xc3,0xe7,0xfe,0xfc,0x00,0x00,0x00,0x30,0x30,0x30,0x38,0x1c,0x0e,0x07,0x03,0x00, //    #57  9  39
0x00,0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00, //    #58  :  3a
0x00,0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0xfc,0x7c,0x00,0x00,0x00,0x00,0x00, //    #59  ;  3b
0x00,0x00,0xc0,0xe0,0xf0,0x38,0x1c,0x0e,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0e,0x1c,0x38,0x30,0x00,0x00, //    #60  <  3c
0x00,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x00, //    #61  =  3d
0x00,0x00,0x03,0x07,0x0e,0x1c,0x38,0xf0,0xe0,0xc0,0x00,0x00,0x00,0x00,0x30,0x38,0x1c,0x0e,0x07,0x03,0x01,0x00,0x00,0x00, //    #62  >  3e
0x00,0x1c,0x1e,0x07,0x03,0x83,0xc3,0xe3,0x77,0x3e,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x37,0x00,0x00,0x00,0x00,0x00, //    #63  ?  3f
0x00,0xf8,0xfe,0x07,0xf3,0xfb,0x1b,0xfb,0xfb,0x07,0xfe,0xf8,0x00,0x0f,0x1f,0x18,0x33,0x37,0x36,0x37,0x37,0x36,0x03,0x01, //    #64  @  40
0x00,0x00,0x00,0xe0,0xfc,0x1f,0x1f,0xfc,0xe0,0x00,0x00,0x00,0x00,0x38,0x3f,0x07,0x06,0x06,0x06,0x06,0x07,0x3f,0x38,0x00, //    #65  A  41
0x00,0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xe7,0xfe,0xbc,0x00,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x39,0x1f,0x0f,0x00, //    #66  B  42
0x00,0xf0,0xfc,0x0e,0x07,0x03,0x03,0x03,0x07,0x0e,0x0c,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x30,0x30,0x38,0x1c,0x0c,0x00, //    #67  C  43
0x00,0xff,0xff,0x03,0x03,0x03,0x03,0x07,0x0e,0xfc,0xf0,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x38,0x1c,0x0f,0x03,0x00, //    #68  D  44
0x00,0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x03,0x03,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00, //    #69  E  45
0x00,0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x03,0x03,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //    #70  F  46
0x00,0xf0,0xfc,0x0e,0x07,0x03,0xc3,0xc3,0xc3,0xc7,0xc6,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x30,0x30,0x30,0x3f,0x3f,0x00, //    #71  G  47
0x00,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xff,0xff,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //    #72  H  48
0x00,0x00,0x00,0x03,0x03,0xff,0xff,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x3f,0x3f,0x30,0x30,0x00,0x00,0x00, //    #73  I  49
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x0e,0x1e,0x38,0x30,0x30,0x30,0x30,0x38,0x1f,0x07,0x00, //    #74  J  4a
0x00,0xff,0xff,0xc0,0xe0,0xf0,0x38,0x1c,0x0e,0x07,0x03,0x00,0x00,0x3f,0x3f,0x00,0x01,0x03,0x07,0x0e,0x1c,0x38,0x30,0x00, //    #75  K  4b
0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00, //    #76  L  4c
0x00,0xff,0xff,0x1e,0x78,0xe0,0xe0,0x78,0x1e,0xff,0xff,0x00,0x00,0x3f,0x3f,0x00,0x00,0x01,0x01,0x00,0x00,0x3f,0x3f,0x00, //    #77  M  4d
0x00,0xff,0xff,0x0e,0x38,0xf0,0xc0,0x00,0x00,0xff,0xff,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x03,0x07,0x1c,0x3f,0x3f,0x00, //    #78  N  4e
0x00,0xf0,0xfc,0x0e,0x07,0x03,0x03,0x07,0x0e,0xfc,0xf0,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x30,0x38,0x1c,0x0f,0x03,0x00, //    #79  O  4f
0x00,0xff,0xff,0x83,0x83,0x83,0x83,0x83,0xc7,0xfe,0x7c,0x00,0x00,0x3f,0x3f,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, //    #80  P  50
0x00,0xf0,0xfc,0x0e,0x07,0x03,0x03,0x07,0x0e,0xfc,0xf0,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x36,0x3e,0x1c,0x3f,0x33,0x00, //    #81  Q  51
0x00,0xff,0xff,0x83,0x83,0x83,0x83,0x83,0xc7,0xfe,0x7c,0x00,0x00,0x3f,0x3f,0x01,0x01,0x03,0x07,0x0f,0x1d,0x38,0x30,0x00, //    #82  R  52
0x00,0x3c,0x7e,0xe7,0xc3,0xc3,0xc3,0xc3,0xc7,0x8e,0x0c,0x00,0x00,0x0c,0x1c,0x38,0x30,0x30,0x30,0x30,0x39,0x1f,0x0f,0x00, //    #83  S  53
0x00,0x00,0x03,0x03,0x03,0xff,0xff,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00, //    #84  T  54
0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x07,0x1f,0x38,0x30,0x30,0x30,0x30,0x38,0x1f,0x07,0x00, //    #85  U  55
0x00,0x07,0x3f,0xf8,0xc0,0x00,0x00,0xc0,0xf8,0x3f,0x07,0x00,0x00,0x00,0x00,0x01,0x0f,0x3e,0x3e,0x0f,0x01,0x00,0x00,0x00, //    #86  V  56
0x00,0xff,0xff,0x00,0x00,0x80,0x80,0x00,0x00,0xff,0xff,0x00,0x00,0x3f,0x3f,0x1c,0x06,0x03,0x03,0x06,0x1c,0x3f,0x3f,0x00, //    #87  W  57
0x00,0x03,0x0f,0x1c,0x30,0xe0,0xe0,0x30,0x1c,0x0f,0x03,0x00,0x00,0x30,0x3c,0x0e,0x03,0x01,0x01,0x03,0x0e,0x3c,0x30,0x00, //    #88  X  58
0x00,0x03,0x0f,0x3c,0xf0,0xc0,0xc0,0xf0,0x3c,0x0f,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00, //    #89  Y  59
0x00,0x03,0x03,0x03,0x03,0xc3,0xe3,0x33,0x1f,0x0f,0x03,0x00,0x00,0x30,0x3c,0x3e,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x00, //    #90  Z  5a
0x00,0x00,0x00,0xff,0xff,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x00,0x00,0x00, //    #91  [  5b
0x00,0x0e,0x1c,0x38,0x70,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0e,0x1c,0x18, //    #92  \  5c
0x00,0x00,0x00,0x03,0x03,0x03,0x03,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x30,0x3f,0x3f,0x00,0x00,0x00, //    #93  ]  5d
0x00,0x60,0x70,0x38,0x1c,0x0e,0x07,0x0e,0x1c,0x38,0x70,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //    #94  ^  5e
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, //    #95  _  5f
0x00,0x00,0x00,0x00,0x00,0x3e,0x7e,0x4e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //    #96  `  60
0x00,0x00,0x40,0x60,0x60,0x60,0x60,0x60,0x60,0xe0,0xc0,0x00,0x00,0x1c,0x3e,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x3f,0x00, //    #97  a  61
0x00,0xff,0xff,0xc0,0x60,0x60,0x60,0x60,0xe0,0xc0,0x80,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x38,0x1f,0x0f,0x00, //    #98  b  62
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0x60,0x60,0xc0,0x80,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x30,0x18,0x08,0x00, //    #99  c  63
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0xe0,0xc0,0xff,0xff,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x30,0x3f,0x3f,0x00, //   #100  d  64
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0x60,0x60,0xc0,0x80,0x00,0x00,0x0f,0x1f,0x3b,0x33,0x33,0x33,0x33,0x33,0x13,0x01,0x00, //   #101  e  65
0x00,0xc0,0xc0,0xfc,0xfe,0xc7,0xc3,0xc3,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //   #102  f  66
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0x60,0x60,0xe0,0xe0,0x00,0x00,0x03,0xc7,0xce,0xcc,0xcc,0xcc,0xcc,0xe6,0x7f,0x3f,0x00, //   #103  g  67
0x00,0xff,0xff,0xc0,0x60,0x60,0x60,0xe0,0xc0,0x80,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00, //   #104  h  68
0x00,0x00,0x00,0x00,0x60,0xec,0xec,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x3f,0x3f,0x30,0x30,0x00,0x00,0x00, //   #105  i  69
0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xec,0xec,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xe0,0xc0,0xc0,0xff,0x7f,0x00,0x00,0x00, //   #106  j  6a
0x00,0x00,0xff,0xff,0x00,0x80,0xc0,0xe0,0x60,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x03,0x07,0x0f,0x1c,0x38,0x30,0x00,0x00, //   #107  k  6b
0x00,0x00,0x00,0x00,0x03,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x3f,0x3f,0x30,0x30,0x00,0x00,0x00, //   #108  l  6c
0x00,0xe0,0xc0,0xe0,0xe0,0xc0,0xc0,0xe0,0xe0,0xc0,0x80,0x00,0x00,0x3f,0x3f,0x00,0x00,0x3f,0x3f,0x00,0x00,0x3f,0x3f,0x00, //   #109  m  6d
0x00,0x00,0xe0,0xe0,0x60,0x60,0x60,0x60,0xe0,0xc0,0x80,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #110  n  6e
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0x60,0xe0,0xc0,0x80,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x38,0x1f,0x0f,0x00, //   #111  o  6f
0x00,0xe0,0xe0,0x60,0x60,0x60,0x60,0x60,0xe0,0xc0,0x80,0x00,0x00,0xff,0xff,0x0c,0x18,0x18,0x18,0x18,0x1c,0x0f,0x07,0x00, //   #112  p  70
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0x60,0x60,0xe0,0xe0,0x00,0x00,0x07,0x0f,0x1c,0x18,0x18,0x18,0x18,0x0c,0xff,0xff,0x00, //   #113  q  71
0x00,0x00,0xe0,0xe0,0xc0,0x60,0x60,0x60,0x60,0xe0,0xc0,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //   #114  r  72
0x00,0xc0,0xe0,0x60,0x60,0x60,0x60,0x60,0x40,0x00,0x00,0x00,0x00,0x11,0x33,0x33,0x33,0x33,0x33,0x3f,0x1e,0x00,0x00,0x00, //   #115  s  73
0x00,0x60,0x60,0xfe,0xfe,0x60,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x3f,0x30,0x30,0x30,0x30,0x00,0x00,0x00, //   #116  t  74
0x00,0xe0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x18,0x3f,0x3f,0x00, //   #117  u  75
0x00,0x60,0xe0,0x80,0x00,0x00,0x00,0x00,0x80,0xe0,0x60,0x00,0x00,0x00,0x01,0x07,0x1e,0x38,0x38,0x1e,0x07,0x01,0x00,0x00, //   #118  v  76
0x00,0xe0,0xe0,0x00,0x00,0xe0,0xe0,0x00,0x00,0xe0,0xe0,0x00,0x00,0x07,0x1f,0x38,0x1c,0x0f,0x0f,0x1c,0x38,0x1f,0x07,0x00, //   #119  w  77
0x00,0x60,0xe0,0xc0,0x80,0x00,0x80,0xc0,0xe0,0x60,0x00,0x00,0x00,0x30,0x38,0x1d,0x0f,0x07,0x0f,0x1d,0x38,0x30,0x00,0x00, //   #120  x  78
0x00,0x00,0x60,0xe0,0x80,0x00,0x00,0x80,0xe0,0x60,0x00,0x00,0x00,0x00,0x00,0x81,0xe7,0x7e,0x1e,0x07,0x01,0x00,0x00,0x00, //   #121  y  79
0x00,0x60,0x60,0x60,0x60,0x60,0xe0,0xe0,0x60,0x20,0x00,0x00,0x00,0x30,0x38,0x3c,0x36,0x33,0x31,0x30,0x30,0x30,0x00,0x00, //   #122  z  7a
0x00,0x00,0x80,0xc0,0xfc,0x7e,0x07,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x1f,0x3f,0x70,0x60,0x60,0x60,0x00,0x00, //   #123  {  7b
0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00, //   #124  |  7c
0x00,0x00,0x03,0x03,0x03,0x07,0x7e,0xfc,0xc0,0x80,0x00,0x00,0x00,0x00,0x60,0x60,0x60,0x70,0x3f,0x1f,0x01,0x00,0x00,0x00, //   #125  }  7d
0x00,0x10,0x18,0x0c,0x04,0x0c,0x18,0x10,0x18,0x0c,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //   #126  ~  7e
0x00,0x00,0x80,0xc0,0x60,0x30,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x0f,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0f,0x0f,0x00, //   #127    7f
0x00,0xc0,0xe0,0x64,0x6c,0x68,0x6c,0x64,0x40,0x00,0x00,0x00,0x00,0x11,0x33,0x33,0x33,0x33,0x33,0x3f,0x1e,0x00,0x00,0x00, //   #128  š  c5 a1
0x00,0x80,0xc0,0xe0,0x60,0x60,0x60,0xe4,0xc4,0xff,0xff,0x04,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x30,0x3f,0x3f,0x00, //   #129  đ  c4 91
0x00,0x60,0x60,0x64,0x6c,0x68,0xec,0xe4,0x60,0x20,0x00,0x00,0x00,0x30,0x38,0x3c,0x36,0x33,0x31,0x30,0x30,0x30,0x00,0x00, //   #130  ž  c5 be
0x00,0x80,0xc0,0xe0,0x64,0x6c,0x68,0x6c,0x64,0xc0,0x80,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x30,0x18,0x08,0x00, //   #131  č  c4 8d
0x00,0x60,0xf0,0xf8,0x99,0x9b,0x9a,0x9b,0x99,0x30,0x20,0x00,0x00,0x0c,0x1c,0x39,0x31,0x31,0x31,0x31,0x3b,0x1f,0x0e,0x00, //   #132  Š  c5 a0
0x00,0x80,0xe0,0x70,0x38,0x18,0x1a,0x1b,0x39,0x70,0x60,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x30,0x30,0x38,0x1c,0x0c,0x00, //   #133  Ć  c4 86
0x00,0x80,0xc0,0xe0,0x60,0x60,0x68,0x6c,0x64,0xc0,0x80,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x30,0x18,0x08,0x00, //   #134  ć  c4 87
0x00,0xff,0xff,0x83,0x83,0x83,0x83,0x83,0xc7,0xfe,0x7c,0x00,0x00,0x3f,0x3f,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00, //   #135  Р  d0 a0
0x00,0x30,0xf0,0xc0,0x00,0x00,0x00,0x00,0xc0,0xf0,0x30,0x00,0x00,0x60,0xe0,0xc3,0xe7,0x7c,0x3c,0x0f,0x03,0x00,0x00,0x00, //   #136  у  d1 83
0x00,0xc0,0xe0,0x70,0x30,0x30,0x30,0x30,0x70,0x60,0x40,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x38,0x18,0x08,0x00, //   #137  с  d1 81
0x00,0xf0,0xf0,0x80,0x80,0xc0,0xe0,0x70,0x30,0x10,0x00,0x00,0x00,0x3f,0x3f,0x03,0x03,0x07,0x0e,0x1c,0x38,0x30,0x20,0x00, //   #138  к  d0 ba
0x00,0xf0,0xf0,0x00,0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x1c,0x0e,0x07,0x03,0x01,0x00,0x3f,0x3f,0x00, //   #139  и  d0 b8
0x00,0xf0,0xf0,0x00,0x04,0x08,0x88,0xc4,0xe0,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x1c,0x0e,0x07,0x03,0x01,0x00,0x3f,0x3f,0x00, //   #140  й  d0 b9
0x00,0x07,0x1f,0x7c,0xf0,0xc0,0xc0,0xf0,0x7c,0x1f,0x07,0x00,0x00,0x00,0x30,0x30,0x3c,0x0f,0x07,0x01,0x00,0x00,0x00,0x00, //   #141  У  d0 a3
0x00,0xe0,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x1f,0x3f,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x1e,0x00, //   #142  б  d0 b1
0x00,0xe0,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0xf0,0xe0,0x00,0x00,0x1f,0x3f,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x33,0x00, //   #143  е  d0 b5
0x00,0x00,0xc0,0xe0,0x70,0x30,0x30,0x30,0xf0,0xf0,0x00,0x00,0x00,0x60,0x7f,0x3f,0x30,0x30,0x30,0x30,0x3f,0x7f,0x60,0x00, //   #144  д  d0 b4
0x00,0x30,0x30,0x30,0x30,0xf0,0xf0,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00, //   #145  т  d1 82
0x00,0xf0,0xf0,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x3f,0x3f,0x31,0x31,0x31,0x31,0x31,0x3b,0x1f,0x0e,0x00, //   #146  ь  d1 8c
0x00,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x3f,0x3f,0x00, //   #147  ч  d1 87
0x00,0xc0,0xe0,0x70,0x30,0x30,0x30,0x30,0x70,0xe0,0xc0,0x00,0x00,0x0f,0x1f,0x38,0x30,0x30,0x30,0x30,0x38,0x1f,0x0f,0x00, //   #148  о  d0 be
0x00,0x30,0xf0,0xc0,0x00,0xf0,0xf0,0x00,0xc0,0xf0,0x30,0x00,0x00,0x30,0x3c,0x0f,0x03,0x3f,0x3f,0x03,0x0f,0x3c,0x30,0x00, //   #149  ж  d0 b6
0x00,0x00,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xf0,0xe0,0x00,0x00,0x1e,0x3f,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x3f,0x00, //   #150  а  d0 b0
0x00,0x00,0xc0,0xe0,0x70,0x30,0x30,0x30,0x30,0xf0,0xf0,0x00,0x00,0x30,0x3f,0x1f,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #151  л  d0 bb
0x00,0xf0,0xf0,0x80,0x80,0x80,0x00,0x00,0x00,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x31,0x31,0x3b,0x1f,0x0e,0x00,0x3f,0x3f,0x00, //   #152  ы  d1 8b
0x00,0xf0,0xf0,0xe0,0xc0,0x80,0x80,0xc0,0xe0,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x00,0x01,0x03,0x03,0x01,0x00,0x3f,0x3f,0x00, //   #153  м  d0 bc
0x00,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x03,0x03,0x03,0x03,0x03,0x03,0x3f,0x3f,0x00, //   #154  н  d0 bd
0x00,0xf0,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #155  п  d0 bf
0x00,0xf0,0xf0,0x30,0x30,0x30,0x30,0x30,0x70,0xe0,0xc0,0x00,0x00,0xff,0xff,0x0c,0x0c,0x0c,0x0c,0x0c,0x0e,0x07,0x03,0x00, //   #156  р  d1 80
0x00,0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xe7,0xfe,0xbc,0x00,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x39,0x1f,0x0f,0x00, //   #157  В  d0 92
0x00,0xf0,0xf0,0x30,0x30,0x30,0x30,0x30,0xf0,0xe0,0x00,0x00,0x00,0x3f,0x3f,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x1e,0x00, //   #158  в  d0 b2
0x00,0x30,0x70,0xc0,0x80,0x00,0x00,0x80,0xc0,0x70,0x30,0x00,0x00,0x30,0x38,0x0c,0x07,0x03,0x03,0x07,0x0c,0x38,0x30,0x00, //   #159  х  d1 85
0x00,0x60,0x70,0x30,0x30,0x30,0x30,0x30,0x30,0xf0,0xe0,0x00,0x00,0x18,0x38,0x30,0x33,0x33,0x33,0x33,0x33,0x3f,0x1d,0x00, //   #160  з  d0 b7
0x00,0xf0,0xf0,0x00,0xe0,0xf0,0x30,0x30,0x30,0xf0,0xe0,0x00,0x00,0x3f,0x3f,0x03,0x1f,0x3f,0x30,0x30,0x30,0x3f,0x1f,0x00, //   #161  ю  d1 8e
0x00,0x80,0xe0,0x78,0x1e,0x07,0x07,0x1e,0x78,0xe0,0x80,0x00,0x00,0x3f,0x3f,0x06,0x06,0x06,0x06,0x06,0x06,0x3f,0x3f,0x00, //   #162  А  d0 90
0x00,0xff,0xff,0xc0,0xe0,0xf0,0x38,0x1c,0x0e,0x07,0x03,0x00,0x00,0x3f,0x3f,0x00,0x01,0x03,0x07,0x0e,0x1c,0x38,0x30,0x00, //   #163  К  d0 9a
0x00,0xff,0xff,0x1e,0x78,0xe0,0xe0,0x78,0x1e,0xff,0xff,0x00,0x00,0x3f,0x3f,0x00,0x00,0x01,0x01,0x00,0x00,0x3f,0x3f,0x00, //   #164  М  d0 9c
0x00,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0xff,0xff,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #165  П  d0 9f
0x00,0x03,0x0f,0xfc,0xe0,0xff,0xff,0xe0,0xfc,0x0f,0x03,0x00,0x00,0x38,0x3f,0x07,0x00,0x3f,0x3f,0x00,0x07,0x3f,0x38,0x00, //   #166  Ж  d0 96
0x00,0x00,0x00,0x1e,0x3f,0x33,0x33,0x3f,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //   #167  °  c2 b0
0x00,0xf0,0xfc,0x0e,0x07,0x03,0x03,0x03,0x07,0x0e,0x0c,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x30,0x30,0x38,0x1c,0x0c,0x00, //   #168  С  d0 a1
0x00,0xf0,0xfc,0x0e,0x07,0x03,0x03,0x07,0x0e,0xfc,0xf0,0x00,0x00,0x03,0x0f,0x1c,0x38,0x30,0x30,0x38,0x1c,0x0f,0x03,0x00, //   #169  О  d0 9e
0x00,0xff,0xff,0x00,0x02,0xc3,0xf1,0x38,0x0e,0xff,0xff,0x00,0x00,0x3f,0x3f,0x1c,0x07,0x03,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #170  Й  d0 99
0x00,0xff,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xff,0xff,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #171  Н  d0 9d
0x00,0xff,0xff,0x00,0x00,0xc0,0xf0,0x38,0x0e,0xff,0xff,0x00,0x00,0x3f,0x3f,0x1c,0x07,0x03,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #172  И  d0 98
0x00,0xff,0xff,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x03,0x03,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00, //   #173  Е  d0 95
0x00,0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //   #174  Г  d0 93
0x00,0x7c,0xfe,0xc7,0x83,0x83,0x83,0x83,0x83,0xff,0xff,0x00,0x00,0x30,0x38,0x1d,0x0f,0x07,0x03,0x01,0x01,0x3f,0x3f,0x00, //   #175  Я  d0 af
0x00,0x7f,0xff,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #176  Ч  d0 a7
0x00,0x00,0xf0,0xfc,0x1e,0x07,0x03,0x03,0x03,0xff,0xff,0x00,0x00,0x30,0x3f,0x1f,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00, //   #177  Л  d0 9b
0x00,0x80,0xc0,0x60,0x60,0xf0,0xf0,0x60,0x60,0xc0,0x80,0x00,0x00,0x0f,0x1f,0x30,0x30,0xff,0xff,0x30,0x30,0x1f,0x0f,0x00, //   #178  ф  d1 84
0x00,0x00,0xf8,0xfe,0x0f,0x03,0x03,0x03,0xff,0xff,0x00,0x00,0x00,0x70,0x7f,0x1f,0x18,0x18,0x18,0x18,0x1f,0x7f,0x70,0x00, //   #179  Д  d0 94
0x00,0xf0,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //   #180  г  d0 b3
0x00,0xc0,0xe0,0x70,0x30,0x30,0x30,0x30,0x30,0xf0,0xf0,0x00,0x00,0x21,0x33,0x3b,0x1e,0x0e,0x06,0x06,0x06,0x3f,0x3f,0x00, //   #181  я  d1 8f
0x00,0xf0,0xf0,0x00,0x00,0xf0,0xf0,0x00,0x00,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x30,0x30,0x3f,0x3f,0x30,0x30,0x3f,0xff,0xe0, //   #182  щ  d1 89
0x00,0xf0,0xf0,0x00,0x00,0xe0,0xe0,0x00,0x00,0xf0,0xf0,0x00,0x00,0x3f,0x3f,0x30,0x30,0x3f,0x3f,0x30,0x30,0x3f,0x3f,0x00, //   #183  ш  d1 88
0x00,0x03,0x03,0x03,0x03,0xff,0xff,0x03,0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x3f,0x00,0x00,0x00,0x00,0x00, //   #184  Т  d0 a2
0x00,0xf8,0xfc,0x0e,0x06,0xff,0xff,0x06,0x0e,0xfc,0xf8,0x00,0x00,0x03,0x07,0x0e,0x0c,0x3f,0x3f,0x0c,0x0e,0x07,0x03,0x00, //   #185  Ф  d0 a4
0x00,0x40,0x60,0x70,0x30,0x30,0x30,0x30,0x70,0xe0,0xc0,0x00,0x00,0x08,0x18,0x38,0x30,0x33,0x33,0x33,0x3b,0x1f,0x0f,0x00, //   #186  э  d1 8d
0x00,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0x00,0x00,0x00,0x3f,0x3f,0x30,0x30,0x30,0x30,0x30,0x3f,0xff,0xf0,0x00, //   #187  ц  d1 86
0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x1f,0x1f,0x18,0x18,0x18,0x18,0x18,0x1f,0x7f,0x78,0x00, //   #188  Ц  d0 a6
};

// ================ FONT 6x8 ================
const uint8_t FONT_6x8[] = {
0x00,0x00,0x00,0x00,0x00,0x00, //    #32     20
0x00,0x00,0x4f,0x00,0x00,0x00, //    #33  !  21
0x00,0x07,0x00,0x07,0x00,0x00, //    #34  "  22
0x14,0x7f,0x14,0x7f,0x14,0x00, //    #35  #  23
0x24,0x2a,0x7f,0x2a,0x12,0x00, //    #36  $  24
0x23,0x13,0x08,0x64,0x62,0x00, //    #37  %  25
0x36,0x49,0x56,0x20,0x58,0x00, //    #38  &  26
0x00,0x05,0x03,0x00,0x00,0x00, //    #39  '  27
0x00,0x1c,0x22,0x41,0x00,0x00, //    #40  (  28
0x00,0x41,0x22,0x1c,0x00,0x00, //    #41  )  29
0x14,0x08,0x3e,0x08,0x14,0x00, //    #42  *  2a
0x08,0x08,0x3e,0x08,0x08,0x00, //    #43  +  2b
0x00,0x50,0x30,0x00,0x00,0x00, //    #44  ,  2c
0x08,0x08,0x08,0x08,0x08,0x00, //    #45  -  2d
0x00,0x60,0x60,0x00,0x00,0x00, //    #46  .  2e
0x20,0x10,0x08,0x04,0x02,0x00, //    #47  /  2f
0x3e,0x51,0x49,0x45,0x3e,0x00, //    #48  0  30
0x00,0x42,0x7f,0x40,0x00,0x00, //    #49  1  31
0x42,0x61,0x51,0x49,0x46,0x00, //    #50  2  32
0x21,0x41,0x45,0x4b,0x31,0x00, //    #51  3  33
0x18,0x14,0x12,0x7f,0x10,0x00, //    #52  4  34
0x27,0x45,0x45,0x45,0x39,0x00, //    #53  5  35
0x3c,0x4a,0x49,0x49,0x30,0x00, //    #54  6  36
0x01,0x71,0x09,0x05,0x03,0x00, //    #55  7  37
0x36,0x49,0x49,0x49,0x36,0x00, //    #56  8  38
0x06,0x49,0x49,0x29,0x1e,0x00, //    #57  9  39
0x00,0x36,0x36,0x00,0x00,0x00, //    #58  :  3a
0x00,0x56,0x36,0x00,0x00,0x00, //    #59  ;  3b
0x08,0x14,0x22,0x41,0x00,0x00, //    #60  <  3c
0x14,0x14,0x14,0x14,0x14,0x00, //    #61  =  3d
0x00,0x41,0x22,0x14,0x08,0x00, //    #62  >  3e
0x02,0x01,0x51,0x09,0x06,0x00, //    #63  ?  3f
0x32,0x49,0x79,0x41,0x3e,0x00, //    #64  @  40
0x7e,0x09,0x09,0x09,0x7e,0x00, //    #65  A  41
0x7f,0x49,0x49,0x49,0x36,0x00, //    #66  B  42
0x3e,0x41,0x41,0x41,0x22,0x00, //    #67  C  43
0x7f,0x41,0x41,0x22,0x1c,0x00, //    #68  D  44
0x7f,0x49,0x49,0x49,0x41,0x00, //    #69  E  45
0x7f,0x09,0x09,0x09,0x01,0x00, //    #70  F  46
0x3e,0x41,0x41,0x49,0x7a,0x00, //    #71  G  47
0x7f,0x08,0x08,0x08,0x7f,0x00, //    #72  H  48
0x00,0x41,0x7f,0x41,0x00,0x00, //    #73  I  49
0x20,0x40,0x41,0x3f,0x01,0x00, //    #74  J  4a
0x7f,0x08,0x14,0x22,0x41,0x00, //    #75  K  4b
0x7f,0x40,0x40,0x40,0x40,0x00, //    #76  L  4c
0x7f,0x02,0x0c,0x02,0x7f,0x00, //    #77  M  4d
0x7f,0x04,0x08,0x10,0x7f,0x00, //    #78  N  4e
0x3e,0x41,0x41,0x41,0x3e,0x00, //    #79  O  4f
0x7f,0x09,0x09,0x09,0x06,0x00, //    #80  P  50
0x3e,0x41,0x51,0x21,0x5e,0x00, //    #81  Q  51
0x7f,0x09,0x19,0x29,0x46,0x00, //    #82  R  52
0x26,0x49,0x49,0x49,0x32,0x00, //    #83  S  53
0x01,0x01,0x7f,0x01,0x01,0x00, //    #84  T  54
0x3f,0x40,0x40,0x40,0x3f,0x00, //    #85  U  55
0x1f,0x20,0x40,0x20,0x1f,0x00, //    #86  V  56
0x3f,0x40,0x38,0x40,0x3f,0x00, //    #87  W  57
0x63,0x14,0x08,0x14,0x63,0x00, //    #88  X  58
0x07,0x08,0x70,0x08,0x07,0x00, //    #89  Y  59
0x61,0x51,0x49,0x45,0x43,0x00, //    #90  Z  5a
0x00,0x7f,0x41,0x41,0x00,0x00, //    #91  [  5b
0x02,0x04,0x08,0x10,0x20,0x00, //    #92  \  5c
0x00,0x41,0x41,0x7f,0x00,0x00, //    #93  ]  5d
0x04,0x02,0x01,0x02,0x04,0x00, //    #94  ^  5e
0x40,0x40,0x40,0x40,0x40,0x00, //    #95  _  5f
0x00,0x03,0x05,0x00,0x00,0x00, //    #96  `  60
0x20,0x54,0x54,0x54,0x78,0x00, //    #97  a  61
0x7f,0x48,0x44,0x44,0x38,0x00, //    #98  b  62
0x38,0x44,0x44,0x44,0x20,0x00, //    #99  c  63
0x38,0x44,0x44,0x48,0x7f,0x00, //   #100  d  64
0x38,0x54,0x54,0x54,0x18,0x00, //   #101  e  65
0x00,0x04,0x7e,0x05,0x01,0x00, //   #102  f  66
0x08,0x54,0x54,0x54,0x3c,0x00, //   #103  g  67
0x7f,0x08,0x04,0x04,0x78,0x00, //   #104  h  68
0x00,0x44,0x7d,0x40,0x00,0x00, //   #105  i  69
0x20,0x40,0x44,0x3d,0x00,0x00, //   #106  j  6a
0x00,0x7f,0x10,0x28,0x44,0x00, //   #107  k  6b
0x00,0x41,0x7f,0x40,0x00,0x00, //   #108  l  6c
0x7c,0x04,0x78,0x04,0x78,0x00, //   #109  m  6d
0x7c,0x08,0x04,0x04,0x78,0x00, //   #110  n  6e
0x38,0x44,0x44,0x44,0x38,0x00, //   #111  o  6f
0x7c,0x14,0x14,0x14,0x08,0x00, //   #112  p  70
0x08,0x14,0x14,0x14,0x7c,0x00, //   #113  q  71
0x7c,0x08,0x04,0x04,0x08,0x00, //   #114  r  72
0x48,0x54,0x54,0x54,0x24,0x00, //   #115  s  73
0x04,0x3e,0x44,0x40,0x20,0x00, //   #116  t  74
0x3c,0x40,0x40,0x20,0x7c,0x00, //   #117  u  75
0x0c,0x30,0x40,0x30,0x0c,0x00, //   #118  v  76
0x3c,0x40,0x30,0x40,0x3c,0x00, //   #119  w  77
0x44,0x24,0x38,0x48,0x44,0x00, //   #120  x  78
0x44,0x48,0x30,0x10,0x0c,0x00, //   #121  y  79
0x44,0x64,0x54,0x4c,0x44,0x00, //   #122  z  7a
0x08,0x36,0x41,0x00,0x00,0x00, //   #123  {  7b
0x00,0x00,0x77,0x00,0x00,0x00, //   #124  |  7c
0x00,0x00,0x41,0x36,0x08,0x00, //   #125  }  7d
0x02,0x01,0x02,0x04,0x02,0x00, //   #126  ~  7e
0x04,0x02,0x01,0x02,0x04,0x00, //   #127    7f
0x48,0x55,0x56,0x55,0x24,0x00, //   #128  š  c5 a1
0x38,0x44,0x44,0x4A,0x7F,0x00, //   #129  đ  c4 91
0x44,0x65,0x56,0x4d,0x44,0x00, //   #130  ž  c5 be
0x38,0x45,0x46,0x45,0x20,0x00, //   #131  č  c4 8d
0x08,0x55,0x56,0x55,0x20,0x00, //   #132  Š  c5 a0
0x38,0x44,0x46,0x45,0x28,0x00, //   #133  Ć  c4 86
0x38,0x44,0x46,0x45,0x20,0x00, //   #134  ć  c4 87
0x7f,0x09,0x09,0x09,0x06,0x00, //   #135  Р  d0 a0
0x4c,0x50,0x20,0x10,0x0c,0x00, //   #136  у  d1 83
0x38,0x44,0x44,0x44,0x20,0x00, //   #137  с  d1 81
0x7c,0x10,0x28,0x44,0x00,0x00, //   #138  к  d0 ba
0x7c,0x20,0x10,0x08,0x7c,0x00, //   #139  и  d0 b8
0x7c,0x21,0x12,0x09,0x7c,0x00, //   #140  й  d0 b9
0x47,0x48,0x30,0x08,0x07,0x00, //   #141  У  d0 a3
0x3c,0x4a,0x4a,0x4a,0x30,0x00, //   #142  б  d0 b1
0x38,0x54,0x54,0x54,0x18,0x00, //   #143  е  d0 b5
0x40,0x3c,0x24,0x3c,0x60,0x00, //   #144  д  d0 b4
0x04,0x04,0x7c,0x04,0x04,0x00, //   #145  т  d1 82
0x00,0x7c,0x50,0x20,0x00,0x00, //   #146  ь  d1 8c
0x0c,0x10,0x10,0x10,0x7c,0x00, //   #147  ч  d1 87
0x38,0x44,0x44,0x44,0x38,0x00, //   #148  о  d0 be
0x6c,0x10,0x7c,0x10,0x6c,0x00, //   #149  ж  d0 b6
0x20,0x54,0x54,0x54,0x78,0x00, //   #150  а  d0 b0
0x40,0x3c,0x04,0x04,0x7c,0x00, //   #151  л  d0 bb
0x7c,0x50,0x20,0x00,0x7c,0x00, //   #152  ы  d1 8b
0x7c,0x08,0x10,0x08,0x7c,0x00, //   #153  м  d0 bc
0x7c,0x10,0x10,0x10,0x7c,0x00, //   #154  н  d0 bd
0x7c,0x04,0x04,0x04,0x7c,0x00, //   #155  п  d0 bf
0x7c,0x14,0x14,0x14,0x08,0x00, //   #156  р  d1 80
0x7f,0x49,0x49,0x49,0x36,0x00, //   #157  В  d0 92
0x7c,0x54,0x54,0x54,0x28,0x00, //   #158  в  d0 b2
0x44,0x28,0x10,0x28,0x44,0x00, //   #159  х  d1 85
0x28,0x44,0x54,0x54,0x28,0x00, //   #160  з  d0 b7
0x7c,0x10,0x38,0x44,0x38,0x00, //   #161  ю  d1 8e
0x7e,0x09,0x09,0x09,0x7e,0x00, //   #162  А  d0 90
0x7f,0x08,0x14,0x22,0x41,0x00, //   #163  К  d0 9a
0x7f,0x02,0x04,0x02,0x7f,0x00, //   #164  М  d0 9c
0x7f,0x01,0x01,0x01,0x7f,0x00, //   #165  П  d0 9f
0x77,0x08,0x7f,0x08,0x77,0x00, //   #166  Ж  d0 96
0x00,0x00,0x07,0x05,0x07,0x00, //   #167  °  c2 b0
0x3e,0x41,0x41,0x41,0x22,0x00, //   #168  С  d0 a1
0x3e,0x41,0x41,0x41,0x3e,0x00, //   #169  О  d0 9e
0x7c,0x21,0x12,0x09,0x7c,0x00, //   #170  Й  d0 99
0x7f,0x08,0x08,0x08,0x7f,0x00, //   #171  Н  d0 9d
0x7f,0x10,0x08,0x04,0x7f,0x00, //   #172  И  d0 98
0x7f,0x49,0x49,0x49,0x41,0x00, //   #173  Е  d0 95
0x7f,0x01,0x01,0x01,0x01,0x00, //   #174  Г  d0 93
0x46,0x29,0x19,0x09,0x7f,0x00, //   #175  Я  d0 af
0x07,0x08,0x08,0x08,0x7f,0x00, //   #176  Ч  d0 a7
0x40,0x3f,0x01,0x01,0x7f,0x00, //   #177  Л  d0 9b
0x18,0x24,0x7e,0x24,0x18,0x00, //   #178  ф  d1 84
0x60,0x3f,0x21,0x3f,0x60,0x00, //   #179  Д  d0 94
0x7c,0x04,0x04,0x04,0x04,0x00, //   #180  г  d0 b3
0x48,0x34,0x14,0x14,0x7c,0x00, //   #181  я  d1 8f
0x3c,0x20,0x3c,0x20,0x7c,0x00, //   #182  щ  d1 89
0x3c,0x20,0x3c,0x20,0x3c,0x00, //   #183  ш  d1 88
0x01,0x01,0x7f,0x01,0x01,0x00, //   #184  Т  d0 a2
0x0c,0x12,0x7f,0x12,0x0c,0x00, //   #185  Ф  d0 a4
0x28,0x44,0x54,0x54,0x28,0x00, //   #186  э  d1 8d
0x3c,0x20,0x20,0x3c,0x60,0x00, //   #187  ц  d1 86
0x3f,0x20,0x20,0x3f,0x60,0x00, //   #188  Ц  d0 a6
};
#endif /* I14N_H_ */
Ralim commented 6 years ago

Thank you for your continued work on this :)

Bummer that it wont fit. Out of curiosity, is there a way to group the languages so that they have the maximum overlap of font symbols to reduce font table size possibly?

I'm happy to go with your best feeling on this really, since you are making great progress :) Is there also an encoding system we could look into using to split strings if they have overlap? so some things are composed of joins of sub strings? (No idea if that will work).

It may be possible to find a trivial compression algorithm we could use on the fonts possibly?

jonnieZG commented 6 years ago

I have compiled my code, and it seems that we have just around 12000 bytes for fonts and strings data, not 15000 as you presumed. It is enough just for 4 languages at a time, or 3 languages if one of them uses Cyrillic script.

I will see how much would we gain by using Huffman coding (i.e. Deflate compression).

Ralim commented 6 years ago

Hmm, Huffman might reduce some encoding but not a huge amount i dont think.

The firmware has continued to grow as we work on this, which is not helping with the flash space utilization :cry:

jonnieZG commented 6 years ago

@Ralim, IT WORKS!!! This video shows the first multilingual version that does not use any compression. This specific package is compiled for English, Croatian and Russian. If there was another Latin-script language instead of Russian, there would be place for 4 instead of 3 languages.

Now I'll make a version that uses Huffman compression for text and fonts, so I expect it to be able to squeeze in 6-7 languages per package. Huffman gives about 45% compression on text files. Not all-in-one, but still much better than having just one language per build.

If we want to squeeze in more languages, the translators should consider shortening descriptions to the bare minimum, and use them only in places where really needed.

jonnieZG commented 6 years ago

@Ralim, I am doing an overall test with Latin and CyriIlic and all the current translations, and I am getting ~40% compression of the font data (4217 instead of 6690 bytes), but only if I unpack it after boot directly into the RAM and use it from there. Dynamic unpacking (reading and unpacking each character before displaying) would drop the compression rate to ~25%.

So I was wondering if you could estimate how much extra RAM do we currently have? It would make things easier if I could first unpack both fonts into RAM, rather than doing on-the-fly decompression

jonnieZG commented 6 years ago

Just reporting that I've been quite busy on some other projects the last couple of weeks, but I will complete the implementation of this feature in the next month or so.

Mrkvozrout commented 6 years ago

I already asked this in other issue, but this is the better place - copied from #273

@jonnieZG @Ralim Please take this as my opinion that triggers discussion, don't take it bad or personally.

Is it still a good idea to strive for multilingual FW when there is not enough memory to have all in 1 (or at least whole language familly in 1) comfortably?

It would be a nice feature, BUT:

222 Multilingual feature would be nice with enough space, but not with all these downsides. It is a nice excercise to optimize the code and memory usage but when it goes that far so description lengths are limited or removed (effectivelly meaning new features with menu options are forbidden) - I don't like the idea any more.

jonnieZG commented 6 years ago

@Mrkvozrout, I am glad you are stating your opinion. I am not taking this personally. :) This feature is probably a matter of taste, so I will state my opinions, but it is up to @Ralim to give a final "go" or "no go".

The only downside of this concept that I see is the additional step in the build procedure that creates a CPP or HPP file from the JSON files, but that is done automatically by a python script. Even the original string values are kept in clear text in the comments next to the compressed data.

Plus, we get a user-friendly HTML5 interface for editing the translations, that checks for untranslated or deprecated strings, and length constraints.

Mrkvozrout commented 6 years ago

From what you said, the best compromise could be to just add the English to every language (just two langs in each bundle). I might switch between Czech and English, but I will surely not switch to Ukraine, Croatian or even Slovak (even if I understand Slovak out of box :D ). It would add value but not eat all memory :)

jonnieZG commented 6 years ago

Decompression has a very small code footprint, so it would also pay to implement it if we just had only one language. It also saves a lot of memory on the fonts. On the other side, it can be more requiring towards RAM, but I still have to test it.

@Mrkvozrout, the two of us basically agree on the matter, except that I would like to push the concept of packing the languages into groups, as long as the memory allows us to. Once we approach the memory limit, we keep the English + one language per build, since sizewise it would be pretty much the same as having one language and font with no compression at all.

Mrkvozrout commented 6 years ago

Since you count with adjusting package size in future, I am OK with it ;)

Ralim commented 6 years ago

Hi, I'm still looking forward to packing this feature in. Current builds are low on ROM (code) room at the moment (3k approx), but I'm hoping we will gain more with the reduce font data etc as well. There is currently at least 5k of RAM free for on the fly use.

I'm currently working through sections of the code base still trying to find the lockup bug, and cleaning up sections as I go too, so might be able to free up some more flash space hopefully as well.

I like the sound of packing English+ at least one extra language in each build. Is it worth having the system try and find pairings that maximize compression at compile time?

I'm happy to use a github-pages site to host the editor or throw it on my site (ralimtek.com) to keep it easy to find.

ghost commented 6 years ago

Maybe a web configuration tool capable of building a firmware depending on users needs would find a compromise between discordant opinions. E.g.: @jonnieZG's concept of the translation tool would reamin, but it will be readjusted in order to include a page with check boxes and a bar indicating memory space; in order to choose which feature to have on firmware, such as animated icons or multilanguality, depending on residual resources.

jonnieZG commented 6 years ago

@federck , that's one brilliantly sweet idea!!!

Mrkvozrout commented 6 years ago

This is what I have in my mind for some time :) something like lua FW builder for ESP8266 https://nodemcu-build.com