Preparation PlatformIO

This commit is contained in:
Serge NOEL
2026-02-11 17:16:06 +01:00
parent 52c72d27d8
commit 7206746130
54 changed files with 147 additions and 1234 deletions

View File

@@ -0,0 +1,164 @@
/* 7pt font https://rop.nl/truetype2gfx/ */
const uint8_t FreeSans7pt7bBitmaps[] = {
0x00, 0xFF, 0x40, 0xB6, 0xD0, 0x12, 0x28, 0xD3, 0xF2, 0x44, 0xBF, 0x94,
0x48, 0x90, 0x10, 0x71, 0x52, 0x95, 0x0E, 0x07, 0x09, 0xD2, 0xA5, 0xF0,
0x81, 0x00, 0x00, 0x87, 0x88, 0x89, 0x08, 0x90, 0x72, 0x00, 0x00, 0x04,
0xE0, 0x91, 0x09, 0x11, 0x0E, 0x30, 0x48, 0x48, 0x48, 0x30, 0x52, 0x9A,
0x8C, 0x8E, 0xFA, 0xF0, 0x29, 0x49, 0x24, 0x99, 0x22, 0x91, 0x24, 0x9A,
0x49, 0x48, 0x4F, 0x4A, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0xD8, 0xE0,
0xC0, 0x10, 0x22, 0x04, 0x44, 0x88, 0x33, 0x68, 0xE1, 0x86, 0x18, 0x61,
0x89, 0xE0, 0x13, 0xF1, 0x11, 0x11, 0x11, 0x18, 0xCD, 0x0A, 0x10, 0x61,
0x8C, 0x30, 0x40, 0xFC, 0x38, 0xC9, 0x18, 0x31, 0xC3, 0x80, 0xE1, 0x46,
0xF8, 0x04, 0x18, 0x71, 0xE2, 0xC9, 0xB3, 0x7F, 0x0C, 0x18, 0x7E, 0x81,
0x02, 0x07, 0xC8, 0xC0, 0x81, 0x46, 0xF8, 0x31, 0x28, 0x60, 0xFB, 0x38,
0x61, 0x8D, 0xE0, 0xFC, 0x10, 0x82, 0x10, 0xC2, 0x08, 0x61, 0x00, 0x18,
0xC9, 0x1A, 0x33, 0xCD, 0x90, 0xA1, 0x46, 0xF8, 0x73, 0x68, 0xE1, 0x8F,
0x72, 0x43, 0x8B, 0xE0, 0xC0, 0x0C, 0x40, 0x0D, 0xC0, 0x00, 0x33, 0x30,
0xE0, 0xE0, 0x40, 0xFC, 0x00, 0x00, 0x03, 0x03, 0x03, 0x1D, 0xC8, 0x00,
0x7B, 0x38, 0x43, 0x18, 0x43, 0x00, 0x00, 0xC0, 0x0F, 0xC0, 0xC3, 0x08,
0x04, 0x8E, 0xB4, 0xCC, 0xA4, 0x47, 0x22, 0x29, 0x12, 0x4E, 0xE3, 0x00,
0x0E, 0x00, 0x1F, 0x00, 0x0C, 0x0E, 0x05, 0x02, 0xC2, 0x21, 0x11, 0xFC,
0x82, 0x41, 0x60, 0xC0, 0xFC, 0x86, 0x82, 0x82, 0xFC, 0x86, 0x82, 0x83,
0x82, 0xFC, 0x3E, 0x43, 0xC1, 0x80, 0x80, 0x80, 0x81, 0x81, 0x43, 0x7E,
0xFC, 0xC6, 0xC3, 0xC1, 0xC1, 0xC1, 0xC1, 0xC3, 0xC6, 0xFC, 0xFF, 0x83,
0x06, 0x0F, 0xF8, 0x30, 0x60, 0xC1, 0xFC, 0xFF, 0x83, 0x06, 0x0F, 0xD8,
0x30, 0x60, 0xC1, 0x80, 0x3E, 0x21, 0xB0, 0x50, 0x08, 0x04, 0x3E, 0x03,
0x03, 0x41, 0x9F, 0x40, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x81,
0x81, 0x81, 0xFF, 0xFF, 0xF0, 0x04, 0x10, 0x41, 0x04, 0x10, 0x71, 0xCD,
0xE0, 0x82, 0x84, 0x88, 0x90, 0xB0, 0xD8, 0x8C, 0x84, 0x86, 0x83, 0x82,
0x08, 0x20, 0x82, 0x08, 0x20, 0x83, 0xF0, 0xC1, 0xE0, 0xE8, 0x74, 0x7A,
0x2C, 0x96, 0x5B, 0x29, 0x8C, 0xC6, 0x40, 0xC1, 0xC1, 0xA1, 0xB1, 0x91,
0x89, 0x8D, 0x85, 0x87, 0x83, 0x3E, 0x21, 0xA0, 0x70, 0x18, 0x0C, 0x06,
0x03, 0x03, 0x43, 0x1F, 0x00, 0xFD, 0x8F, 0x0E, 0x1C, 0x7F, 0xB0, 0x60,
0xC1, 0x80, 0x3E, 0x21, 0xA0, 0x70, 0x18, 0x0C, 0x06, 0x03, 0x0B, 0x43,
0x1F, 0x80, 0x20, 0xFE, 0xC3, 0xC1, 0xC1, 0xC6, 0xFE, 0xC3, 0xC3, 0xC3,
0xC1, 0x7C, 0xC6, 0x82, 0xC0, 0x70, 0x1E, 0x02, 0x83, 0xC2, 0x7C, 0xFF,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xC3, 0x7E, 0x41, 0xA0, 0x98, 0x44, 0x62,
0x21, 0x90, 0x58, 0x28, 0x1C, 0x06, 0x00, 0xC2, 0x1A, 0x38, 0x91, 0x44,
0xCA, 0x26, 0x53, 0x14, 0x50, 0xA2, 0x85, 0x14, 0x38, 0xE0, 0x82, 0x00,
0x41, 0x11, 0x8C, 0x82, 0x80, 0xC0, 0xE0, 0x50, 0x44, 0x63, 0x20, 0xC0,
0xC1, 0xB0, 0x88, 0xC6, 0xC1, 0x40, 0x60, 0x20, 0x10, 0x08, 0x04, 0x00,
0x7F, 0x03, 0x06, 0x04, 0x08, 0x18, 0x30, 0x60, 0x40, 0xFF, 0xEA, 0xAA,
0xAA, 0xC0, 0x88, 0x04, 0x40, 0x22, 0x01, 0xE4, 0x92, 0x49, 0x24, 0x9E,
0x23, 0x15, 0x29, 0x00, 0x00, 0x44, 0xFA, 0x20, 0xBE, 0x8A, 0x2F, 0xC0,
0x82, 0x08, 0x3E, 0x8E, 0x18, 0x61, 0x8F, 0xE0, 0x7C, 0x89, 0x06, 0x0C,
0x08, 0x9F, 0x00, 0x02, 0x04, 0x0B, 0xD4, 0x78, 0x70, 0xE1, 0x46, 0xF4,
0x7A, 0x38, 0x7F, 0x82, 0x37, 0x80, 0x34, 0x4F, 0x44, 0x44, 0x44, 0x7A,
0x8F, 0x1E, 0x1C, 0x68, 0xDE, 0x83, 0x44, 0x70, 0x82, 0x08, 0x3E, 0x8E,
0x18, 0x61, 0x86, 0x10, 0x9F, 0xC0, 0x41, 0x55, 0x55, 0xC0, 0x82, 0x08,
0x26, 0xB3, 0x8F, 0x24, 0x8A, 0x30, 0xFF, 0xC0, 0xFF, 0xC6, 0x62, 0x31,
0x18, 0x8C, 0x46, 0x22, 0xFA, 0x38, 0x61, 0x86, 0x18, 0x40, 0x7C, 0x8D,
0x0E, 0x14, 0x28, 0xCF, 0x00, 0xFA, 0x38, 0x61, 0x86, 0x3F, 0xA0, 0x82,
0x00, 0x7E, 0x8F, 0x0E, 0x1C, 0x28, 0xDE, 0x81, 0x02, 0x04, 0xFA, 0x49,
0x20, 0x7D, 0x14, 0x0E, 0x05, 0x17, 0xC0, 0x4B, 0xA4, 0x92, 0x60, 0x8E,
0x38, 0xE3, 0x8E, 0x3F, 0x40, 0xC4, 0x89, 0x33, 0x42, 0x86, 0x0C, 0x00,
0xCC, 0xD3, 0x24, 0xC9, 0x5E, 0x73, 0x0C, 0xC3, 0x30, 0x44, 0xA3, 0x84,
0x29, 0xA4, 0x40, 0x44, 0x89, 0x31, 0x42, 0x86, 0x04, 0x08, 0x20, 0xC0,
0x7C, 0x31, 0x8C, 0x21, 0x0F, 0xC0, 0x69, 0x25, 0xA6, 0x49, 0x26, 0xFF,
0xF8, 0xC6, 0x66, 0x22, 0x12, 0x26, 0x66, 0xC0, 0xE6, 0x70 };
const GFXglyph FreeSans7pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
{ 1, 1, 10, 4, 2, -9 }, // 0x21 '!'
{ 3, 3, 4, 5, 1, -9 }, // 0x22 '"'
{ 5, 7, 10, 8, 0, -9 }, // 0x23 '#'
{ 14, 7, 13, 8, 0, -10 }, // 0x24 '$'
{ 26, 12, 10, 12, 0, -9 }, // 0x25 '%'
{ 41, 8, 10, 9, 1, -9 }, // 0x26 '&'
{ 51, 1, 4, 3, 1, -9 }, // 0x27 '''
{ 52, 3, 13, 5, 1, -9 }, // 0x28 '('
{ 57, 3, 13, 5, 1, -9 }, // 0x29 ')'
{ 62, 4, 4, 5, 1, -9 }, // 0x2A '*'
{ 64, 6, 7, 8, 1, -6 }, // 0x2B '+'
{ 70, 2, 3, 4, 1, 0 }, // 0x2C ','
{ 71, 3, 1, 5, 1, -3 }, // 0x2D '-'
{ 72, 2, 1, 4, 1, 0 }, // 0x2E '.'
{ 73, 4, 10, 4, 0, -9 }, // 0x2F '/'
{ 78, 6, 10, 8, 1, -9 }, // 0x30 '0'
{ 86, 4, 10, 8, 1, -9 }, // 0x31 '1'
{ 91, 7, 10, 8, 0, -9 }, // 0x32 '2'
{ 100, 7, 10, 8, 0, -9 }, // 0x33 '3'
{ 109, 7, 10, 8, 0, -9 }, // 0x34 '4'
{ 118, 7, 10, 8, 0, -9 }, // 0x35 '5'
{ 127, 6, 10, 8, 1, -9 }, // 0x36 '6'
{ 135, 6, 10, 8, 1, -9 }, // 0x37 '7'
{ 143, 7, 10, 8, 0, -9 }, // 0x38 '8'
{ 152, 6, 10, 8, 1, -9 }, // 0x39 '9'
{ 160, 2, 7, 4, 1, -6 }, // 0x3A ':'
{ 162, 2, 9, 4, 1, -6 }, // 0x3B ';'
{ 165, 6, 7, 8, 1, -6 }, // 0x3C '<'
{ 171, 6, 3, 8, 1, -4 }, // 0x3D '='
{ 174, 6, 7, 8, 1, -6 }, // 0x3E '>'
{ 180, 6, 10, 8, 1, -9 }, // 0x3F '?'
{ 188, 13, 12, 14, 0, -9 }, // 0x40 '@'
{ 208, 9, 10, 9, 0, -9 }, // 0x41 'A'
{ 220, 8, 10, 9, 1, -9 }, // 0x42 'B'
{ 230, 8, 10, 10, 1, -9 }, // 0x43 'C'
{ 240, 8, 10, 10, 1, -9 }, // 0x44 'D'
{ 250, 7, 10, 9, 1, -9 }, // 0x45 'E'
{ 259, 7, 10, 8, 1, -9 }, // 0x46 'F'
{ 268, 9, 10, 11, 1, -9 }, // 0x47 'G'
{ 280, 8, 10, 10, 1, -9 }, // 0x48 'H'
{ 290, 2, 10, 4, 1, -9 }, // 0x49 'I'
{ 293, 6, 10, 7, 0, -9 }, // 0x4A 'J'
{ 301, 8, 10, 9, 1, -9 }, // 0x4B 'K'
{ 311, 6, 10, 8, 1, -9 }, // 0x4C 'L'
{ 319, 9, 10, 11, 1, -9 }, // 0x4D 'M'
{ 331, 8, 10, 10, 1, -9 }, // 0x4E 'N'
{ 341, 9, 10, 11, 1, -9 }, // 0x4F 'O'
{ 353, 7, 10, 9, 1, -9 }, // 0x50 'P'
{ 362, 9, 11, 11, 1, -9 }, // 0x51 'Q'
{ 375, 8, 10, 10, 1, -9 }, // 0x52 'R'
{ 385, 8, 10, 9, 1, -9 }, // 0x53 'S'
{ 395, 8, 10, 8, 0, -9 }, // 0x54 'T'
{ 405, 8, 10, 10, 1, -9 }, // 0x55 'U'
{ 415, 9, 10, 9, 0, -9 }, // 0x56 'V'
{ 427, 13, 10, 13, 0, -9 }, // 0x57 'W'
{ 444, 9, 10, 9, 0, -9 }, // 0x58 'X'
{ 456, 9, 10, 9, 0, -9 }, // 0x59 'Y'
{ 468, 8, 10, 8, 0, -9 }, // 0x5A 'Z'
{ 478, 2, 13, 4, 1, -9 }, // 0x5B '['
{ 482, 4, 10, 4, 0, -9 }, // 0x5C '\'
{ 487, 3, 13, 4, 0, -9 }, // 0x5D ']'
{ 492, 5, 5, 6, 1, -9 }, // 0x5E '^'
{ 496, 8, 1, 8, 0, 3 }, // 0x5F '_'
{ 497, 3, 2, 5, 0, -9 }, // 0x60 '`'
{ 498, 6, 7, 8, 1, -6 }, // 0x61 'a'
{ 504, 6, 10, 8, 1, -9 }, // 0x62 'b'
{ 512, 7, 7, 7, 0, -6 }, // 0x63 'c'
{ 519, 7, 10, 8, 0, -9 }, // 0x64 'd'
{ 528, 6, 7, 8, 1, -6 }, // 0x65 'e'
{ 534, 4, 10, 4, 0, -9 }, // 0x66 'f'
{ 539, 7, 10, 8, 0, -6 }, // 0x67 'g'
{ 548, 6, 10, 8, 1, -9 }, // 0x68 'h'
{ 556, 1, 10, 3, 1, -9 }, // 0x69 'i'
{ 558, 2, 13, 3, 0, -9 }, // 0x6A 'j'
{ 562, 6, 10, 7, 1, -9 }, // 0x6B 'k'
{ 570, 1, 10, 3, 1, -9 }, // 0x6C 'l'
{ 572, 9, 7, 11, 1, -6 }, // 0x6D 'm'
{ 580, 6, 7, 8, 1, -6 }, // 0x6E 'n'
{ 586, 7, 7, 8, 0, -6 }, // 0x6F 'o'
{ 593, 6, 10, 8, 1, -6 }, // 0x70 'p'
{ 601, 7, 10, 8, 0, -6 }, // 0x71 'q'
{ 610, 3, 7, 5, 1, -6 }, // 0x72 'r'
{ 613, 6, 7, 7, 0, -6 }, // 0x73 's'
{ 619, 3, 9, 4, 0, -8 }, // 0x74 't'
{ 623, 6, 7, 8, 1, -6 }, // 0x75 'u'
{ 629, 7, 7, 7, 0, -6 }, // 0x76 'v'
{ 636, 10, 7, 10, 0, -6 }, // 0x77 'w'
{ 645, 6, 7, 7, 0, -6 }, // 0x78 'x'
{ 651, 7, 10, 7, 0, -6 }, // 0x79 'y'
{ 660, 6, 7, 7, 0, -6 }, // 0x7A 'z'
{ 666, 3, 13, 5, 1, -9 }, // 0x7B '{'
{ 671, 1, 13, 4, 1, -9 }, // 0x7C '|'
{ 673, 4, 13, 5, 0, -9 }, // 0x7D '}'
{ 680, 6, 2, 8, 1, -5 } }; // 0x7E '~'
const GFXfont FreeSans7pt7b = {
(uint8_t *)FreeSans7pt7bBitmaps,
(GFXglyph *)FreeSans7pt7bGlyphs,
0x20, 0x7E, 23 };
// Approx. 1354 bytes

View File

@@ -0,0 +1,153 @@
/* 6pt font https://rop.nl/truetype2gfx/ */
const uint8_t FreeSansBold6pt7bBitmaps[] = {
0x00, 0xFF, 0x57, 0xC0, 0xBB, 0x90, 0x2C, 0x5B, 0xFB, 0x44, 0x9F, 0x96,
0x28, 0x11, 0xFD, 0xF4, 0x70, 0x71, 0x77, 0x7C, 0x40, 0x71, 0x36, 0x8D,
0x81, 0xD0, 0x0B, 0xC2, 0x91, 0x24, 0x4F, 0x00, 0xF1, 0x63, 0x87, 0x1E,
0xA7, 0x66, 0xFE, 0xE0, 0x32, 0x64, 0x4C, 0xC4, 0x46, 0x20, 0x89, 0x92,
0x49, 0x69, 0x00, 0x2A, 0x65, 0x21, 0x09, 0xF2, 0x10, 0xF2, 0xFF, 0xF0,
0x24, 0x24, 0x84, 0x01, 0xE4, 0xF3, 0xCF, 0x3C, 0xD3, 0x78, 0x3C, 0x92,
0x49, 0x01, 0xF4, 0xF3, 0x0C, 0x66, 0x18, 0xFC, 0x01, 0xEC, 0xC3, 0x18,
0x30, 0xF3, 0x78, 0x18, 0xA2, 0x92, 0xCB, 0xF0, 0x82, 0x7D, 0x05, 0x1F,
0x0C, 0x3C, 0xDE, 0x01, 0xF4, 0xF0, 0xFF, 0x3C, 0x53, 0x78, 0xFC, 0x31,
0x84, 0x30, 0xC2, 0x08, 0x01, 0xE4, 0xD3, 0x39, 0x3C, 0x73, 0x78, 0x01,
0xEC, 0xF3, 0xCD, 0xF0, 0xD3, 0x78, 0xF0, 0xF0, 0xF0, 0xF7, 0x00, 0x77,
0x30, 0x38, 0x10, 0xFF, 0xC1, 0xF0, 0x83, 0x81, 0xC3, 0x7B, 0x00, 0x73,
0xE8, 0x82, 0x18, 0xC2, 0x0C, 0x30, 0x0F, 0x06, 0x18, 0x81, 0x27, 0x94,
0x93, 0x22, 0x64, 0x4A, 0xFE, 0x60, 0x06, 0x20, 0x38, 0x00, 0x18, 0x1C,
0x1C, 0x34, 0x36, 0x26, 0x7E, 0x63, 0xC3, 0xF9, 0xFB, 0x1E, 0x2F, 0x98,
0xF1, 0xE7, 0xFC, 0x38, 0xFB, 0x1C, 0x08, 0x10, 0x31, 0xE3, 0x7C, 0xF1,
0xFB, 0x1E, 0x3C, 0x78, 0xF1, 0xE6, 0xF8, 0xFF, 0xFC, 0x30, 0xFF, 0x0C,
0x30, 0xFC, 0xFF, 0xFC, 0x30, 0xFB, 0x0C, 0x30, 0xC0, 0x1C, 0x3F, 0x63,
0x40, 0x47, 0x47, 0x61, 0x73, 0x3F, 0xC7, 0x8F, 0x1E, 0x3F, 0xF8, 0xF1,
0xE3, 0xC6, 0xFF, 0xFF, 0xC0, 0x0C, 0x30, 0xC3, 0x0C, 0x3C, 0xF3, 0x78,
0xC7, 0x9B, 0x67, 0x8F, 0x1B, 0x36, 0x66, 0xC6, 0xC3, 0x0C, 0x30, 0xC3,
0x0C, 0x30, 0xFC, 0xC7, 0xE7, 0xE7, 0xE7, 0xE7, 0xFF, 0xFB, 0xDB, 0xDB,
0xC7, 0x8F, 0x9F, 0x3F, 0x7B, 0xF3, 0xE7, 0xC6, 0x1C, 0x1F, 0x98, 0xC8,
0x3C, 0x1A, 0x0D, 0x84, 0xE6, 0x3E, 0x00, 0xF3, 0xFC, 0x71, 0xFF, 0xEC,
0x30, 0xC0, 0x1C, 0x1F, 0x98, 0xC8, 0x34, 0x1A, 0x0D, 0x94, 0xE6, 0x3F,
0x80, 0x00, 0xF9, 0xFF, 0x1E, 0x3F, 0xDF, 0xB1, 0xE3, 0xC6, 0x38, 0xFD,
0x1B, 0x07, 0xC1, 0xF0, 0xB3, 0x7E, 0xFF, 0xFC, 0x60, 0xC1, 0x83, 0x06,
0x0C, 0x18, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE6, 0x7C, 0xC3, 0x42,
0x66, 0x66, 0x24, 0x3C, 0x3C, 0x18, 0x18, 0xC4, 0x79, 0xCD, 0x39, 0x35,
0x66, 0xAC, 0x57, 0x8E, 0xE1, 0x8C, 0x31, 0x80, 0xC7, 0x66, 0x3C, 0x3C,
0x18, 0x38, 0x3C, 0x66, 0x66, 0xC3, 0x66, 0x66, 0x3C, 0x3C, 0x18, 0x18,
0x18, 0x18, 0xFF, 0xFC, 0x30, 0xE1, 0x86, 0x18, 0x60, 0xFE, 0xFE, 0x49,
0x24, 0x93, 0x80, 0x91, 0x24, 0x49, 0xFC, 0x92, 0x49, 0x27, 0x80, 0x63,
0x95, 0xB8, 0x80, 0xFE, 0x48, 0x7F, 0x33, 0xF3, 0xCD, 0xF0, 0x82, 0x08,
0x3E, 0xCE, 0x38, 0xF2, 0xF8, 0x7D, 0x3C, 0x30, 0x4D, 0xE0, 0x04, 0x10,
0x5F, 0x4F, 0x1C, 0x53, 0x7C, 0x7B, 0x3F, 0xF0, 0x4D, 0xE0, 0x37, 0x6F,
0x66, 0x66, 0x60, 0x7D, 0x3C, 0x71, 0x6D, 0xF0, 0x5F, 0x10, 0x84, 0x21,
0xFC, 0xC6, 0x31, 0x88, 0xDF, 0x80, 0x51, 0x55, 0x5F, 0x84, 0x21, 0x3B,
0x73, 0xD3, 0x98, 0xFF, 0x80, 0xFF, 0x6C, 0xE6, 0x73, 0x39, 0x9C, 0xCC,
0xFE, 0x63, 0x18, 0xC4, 0x7C, 0x8B, 0x1E, 0x36, 0x4F, 0x80, 0xFB, 0x38,
0xE3, 0xCB, 0xE8, 0x20, 0x80, 0x7D, 0x3C, 0x71, 0x4D, 0xF0, 0x41, 0x04,
0xBA, 0x49, 0x00, 0x7D, 0x37, 0x87, 0xCD, 0xF0, 0x66, 0xF6, 0x66, 0x67,
0x8C, 0x63, 0x1D, 0xFC, 0xCD, 0x36, 0x8A, 0x38, 0xC0, 0xCD, 0xAE, 0x95,
0x4E, 0xE7, 0x71, 0xB0, 0x6D, 0xE3, 0x0E, 0x69, 0x30, 0xCD, 0x36, 0x9A,
0x38, 0xC3, 0x1C, 0x40, 0xF8, 0x63, 0x18, 0xC3, 0xF0, 0x37, 0x66, 0x6C,
0x66, 0x66, 0x30, 0xFF, 0xE0, 0x99, 0x24, 0xDA, 0x4B, 0x00, 0xC5, 0xC0 };
const GFXglyph FreeSansBold6pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 3, 0, 0 }, // 0x20 ' '
{ 1, 2, 9, 4, 1, -8 }, // 0x21 '!'
{ 4, 4, 3, 6, 1, -8 }, // 0x22 '"'
{ 6, 7, 8, 7, 0, -7 }, // 0x23 '#'
{ 13, 6, 10, 7, 0, -8 }, // 0x24 '$'
{ 21, 10, 8, 10, 0, -7 }, // 0x25 '%'
{ 31, 7, 9, 8, 1, -8 }, // 0x26 '&'
{ 39, 1, 3, 3, 1, -8 }, // 0x27 '''
{ 40, 4, 11, 4, 0, -8 }, // 0x28 '('
{ 46, 3, 11, 4, 0, -8 }, // 0x29 ')'
{ 51, 4, 4, 5, 0, -8 }, // 0x2A '*'
{ 53, 5, 6, 7, 1, -5 }, // 0x2B '+'
{ 57, 2, 4, 3, 1, -1 }, // 0x2C ','
{ 58, 4, 2, 4, 0, -3 }, // 0x2D '-'
{ 59, 2, 2, 3, 1, -1 }, // 0x2E '.'
{ 60, 3, 8, 3, 0, -7 }, // 0x2F '/'
{ 63, 6, 9, 7, 0, -8 }, // 0x30 '0'
{ 70, 3, 8, 7, 1, -7 }, // 0x31 '1'
{ 73, 6, 9, 7, 0, -8 }, // 0x32 '2'
{ 80, 6, 9, 7, 0, -8 }, // 0x33 '3'
{ 87, 6, 8, 7, 0, -7 }, // 0x34 '4'
{ 93, 6, 8, 7, 0, -7 }, // 0x35 '5'
{ 99, 6, 9, 7, 0, -8 }, // 0x36 '6'
{ 106, 6, 8, 7, 0, -7 }, // 0x37 '7'
{ 112, 6, 9, 7, 0, -8 }, // 0x38 '8'
{ 119, 6, 9, 7, 0, -8 }, // 0x39 '9'
{ 126, 2, 6, 4, 1, -5 }, // 0x3A ':'
{ 128, 2, 8, 4, 1, -5 }, // 0x3B ';'
{ 130, 6, 6, 7, 0, -5 }, // 0x3C '<'
{ 135, 5, 4, 7, 1, -4 }, // 0x3D '='
{ 138, 6, 6, 7, 0, -5 }, // 0x3E '>'
{ 143, 6, 9, 7, 1, -8 }, // 0x3F '?'
{ 150, 11, 11, 11, 0, -8 }, // 0x40 '@'
{ 166, 8, 9, 8, 0, -8 }, // 0x41 'A'
{ 175, 7, 9, 8, 1, -8 }, // 0x42 'B'
{ 183, 7, 9, 8, 1, -8 }, // 0x43 'C'
{ 191, 7, 9, 8, 1, -8 }, // 0x44 'D'
{ 199, 6, 9, 8, 1, -8 }, // 0x45 'E'
{ 206, 6, 9, 7, 1, -8 }, // 0x46 'F'
{ 213, 8, 9, 9, 0, -8 }, // 0x47 'G'
{ 222, 7, 9, 8, 1, -8 }, // 0x48 'H'
{ 230, 2, 9, 3, 1, -8 }, // 0x49 'I'
{ 233, 6, 9, 7, 0, -8 }, // 0x4A 'J'
{ 240, 7, 9, 8, 1, -8 }, // 0x4B 'K'
{ 248, 6, 9, 7, 1, -8 }, // 0x4C 'L'
{ 255, 8, 9, 10, 1, -8 }, // 0x4D 'M'
{ 264, 7, 9, 8, 1, -8 }, // 0x4E 'N'
{ 272, 9, 9, 9, 0, -8 }, // 0x4F 'O'
{ 283, 6, 9, 8, 1, -8 }, // 0x50 'P'
{ 290, 9, 10, 9, 0, -8 }, // 0x51 'Q'
{ 302, 7, 9, 8, 1, -8 }, // 0x52 'R'
{ 310, 7, 9, 8, 0, -8 }, // 0x53 'S'
{ 318, 7, 9, 7, 0, -8 }, // 0x54 'T'
{ 326, 7, 9, 8, 1, -8 }, // 0x55 'U'
{ 334, 8, 9, 8, 0, -8 }, // 0x56 'V'
{ 343, 11, 9, 11, 0, -8 }, // 0x57 'W'
{ 356, 8, 9, 8, 0, -8 }, // 0x58 'X'
{ 365, 8, 9, 8, 0, -8 }, // 0x59 'Y'
{ 374, 7, 9, 7, 0, -8 }, // 0x5A 'Z'
{ 382, 3, 11, 4, 1, -8 }, // 0x5B '['
{ 387, 3, 8, 3, 0, -7 }, // 0x5C '\'
{ 390, 3, 11, 4, 0, -8 }, // 0x5D ']'
{ 395, 5, 5, 7, 1, -7 }, // 0x5E '^'
{ 399, 7, 1, 7, 0, 2 }, // 0x5F '_'
{ 400, 3, 2, 4, 0, -8 }, // 0x60 '`'
{ 401, 6, 6, 7, 0, -5 }, // 0x61 'a'
{ 406, 6, 9, 7, 1, -8 }, // 0x62 'b'
{ 413, 6, 6, 7, 0, -5 }, // 0x63 'c'
{ 418, 6, 9, 7, 0, -8 }, // 0x64 'd'
{ 425, 6, 6, 7, 0, -5 }, // 0x65 'e'
{ 430, 4, 9, 4, 0, -8 }, // 0x66 'f'
{ 435, 6, 9, 7, 0, -5 }, // 0x67 'g'
{ 442, 5, 9, 7, 1, -8 }, // 0x68 'h'
{ 448, 1, 9, 3, 1, -8 }, // 0x69 'i'
{ 450, 2, 12, 3, 0, -8 }, // 0x6A 'j'
{ 453, 5, 9, 7, 1, -8 }, // 0x6B 'k'
{ 459, 1, 9, 3, 1, -8 }, // 0x6C 'l'
{ 461, 9, 6, 10, 1, -5 }, // 0x6D 'm'
{ 468, 5, 6, 7, 1, -5 }, // 0x6E 'n'
{ 472, 7, 6, 7, 0, -5 }, // 0x6F 'o'
{ 478, 6, 9, 7, 1, -5 }, // 0x70 'p'
{ 485, 6, 9, 7, 0, -5 }, // 0x71 'q'
{ 492, 3, 6, 5, 1, -5 }, // 0x72 'r'
{ 495, 6, 6, 7, 0, -5 }, // 0x73 's'
{ 500, 4, 8, 4, 0, -7 }, // 0x74 't'
{ 504, 5, 6, 7, 1, -5 }, // 0x75 'u'
{ 508, 6, 6, 7, 0, -5 }, // 0x76 'v'
{ 513, 9, 6, 9, 0, -5 }, // 0x77 'w'
{ 520, 6, 6, 7, 0, -5 }, // 0x78 'x'
{ 525, 6, 9, 7, 0, -5 }, // 0x79 'y'
{ 532, 6, 6, 6, 0, -5 }, // 0x7A 'z'
{ 537, 4, 11, 5, 0, -8 }, // 0x7B '{'
{ 543, 1, 11, 3, 1, -8 }, // 0x7C '|'
{ 545, 3, 11, 5, 1, -8 }, // 0x7D '}'
{ 550, 5, 2, 7, 1, -3 } }; // 0x7E '~'
const GFXfont FreeSansBold6pt7b = {
(uint8_t *)FreeSansBold6pt7bBitmaps,
(GFXglyph *)FreeSansBold6pt7bGlyphs,
0x20, 0x7E, 19 };
// Approx. 1224 bytes

View File

@@ -0,0 +1,62 @@
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
Simple XPT2046 SPI/Bitbang interface for PacoMouseCYD
*/
#ifndef XPT2046_TS_h
#define XPT2046_TS_h
#include "Arduino.h"
#include "config.h"
#ifdef USE_XPT2046_SPI
#include <SPI.h>
#endif
typedef struct {
uint16_t x;
uint16_t y;
uint16_t z;
} TSPoint;
struct TouchCalibration {
uint16_t xMin;
uint16_t xMax;
uint16_t yMin;
uint16_t yMax;
uint16_t rotation;
};
class XPT2046_TS {
public:
XPT2046_TS(uint8_t mosiPin, uint8_t misoPin, uint8_t clkPin, uint8_t csPin);
void begin(uint16_t width = 240, uint16_t height = 320);
bool touched();
TSPoint getTouch();
void setRotation(uint8_t n);
void setCalibration(uint16_t xMin, uint16_t xMax, uint16_t yMin, uint16_t yMax);
TouchCalibration getCalibration();
void readData(uint16_t *x, uint16_t *y, uint16_t *z);
private:
uint8_t _mosiPin;
uint8_t _misoPin;
uint8_t _clkPin;
uint8_t _csPin;
uint8_t _irqPin;
uint16_t _width;
uint16_t _height;
uint16_t _xraw;
uint16_t _yraw;
uint16_t _zraw;
uint32_t _msraw;
TouchCalibration cal;
#ifdef USE_XPT2046_SPI
SPIClass *hspi = NULL;
#endif
#ifdef USE_XPT2046_BITBANG
uint16_t readSPI(byte command);
#endif
void update();
};
#endif

View File

@@ -0,0 +1,184 @@
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
*/
#ifndef PACOMOUSECYD_CFG_H
#define PACOMOUSECYD_CFG_H
#define CYD_TFT_28 0 // Cheap Yellow Display 2.8"
#define CYD_TFT_24 1 // Cheap Yellow Display 2.4"
#define CYD_TFT_32 2 // Cheap Yellow Display 3.2"
#define CYD_USER_DEFINED 3 // User defined board
#define PRESENT 1
#define UNUSED 0
#define MODE_SPI 0
#define MODE_BITBANG 1
////////////////////////////////////////////////////////////
// ***** USER OPTIONS *****
////////////////////////////////////////////////////////////
// Seleccione la version hardware del CYD (Cheap Yellow Display) - Select the hardware version of CYD (Cheap Yellow Display): CYD_TFT_28 / CYD_TFT_24 / CYD_TFT_32 / CYD_USER_DEFINED
// Use el archivo User_Setup.h correcto para la libreria TFT_eSPI - Use the correct User_Setup.h file for library TFT_eSPI
#define CYD_HW_VERSION CYD_TFT_28
// Max. locomotoras guardadas en stack (hasta 254) - Max. locomotives saved in stack (up to 254):
#define LOCOS_IN_STACK 100
// Delimitador en fichero CSV - CSV file delimiter: ';' / ','
#define CSV_FILE_DELIMITER ';'
#if (CYD_HW_VERSION == CYD_USER_DEFINED)
////////////////////////////////////////////////////////////
// ***** USER DEFINED HARDWARE *****
////////////////////////////////////////////////////////////
// Seleccione el modo de acceso al chip XPT2046 - Select XPT2046 chip access mode : MODE_SPI / MODE_BITBANG
#define XPT_MODE MODE_SPI
// Seleccione rotacion de la pantalla tactil - Select Touchscreen rotation: 0 / 1 / 2 / 3
#define XPT_ROTATION 3
// Touchscreen
#define XPT2046_IRQ 36 // T_IRQ
#define XPT2046_MOSI 13 // T_DIN
#define XPT2046_MISO 12 // T_OUT
#define XPT2046_CLK 14 // T_CLK
#define XPT2046_CS 33 // T_CS
// Seleccione si usa el LED RGB - Select if use the RGB LED: PRESENT / UNUSED
#define USE_RGB_LED PRESENT
//RGB LED Pins
#define RGB_LED_R 4
#define RGB_LED_G 17
#define RGB_LED_B 16
//SD Pins
#define SD_CS 5
// Encoder Pins
#define ENCODER_A 22
#define ENCODER_B 21
#define ENCODER_SW 35
#endif
////////////////////////////////////////////////////////////
// ***** END OF USER DEFINED HARDWARE *****
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// ***** END OF USER OPTIONS *****
////////////////////////////////////////////////////////////
#if (CYD_HW_VERSION == CYD_TFT_28)
#define USE_CYD_28 1 // Cheap Yellow Display 2.8" (2432S028R)
#endif
#if (CYD_HW_VERSION == CYD_TFT_24)
#define USE_CYD_24 1 // Cheap Yellow Display 2.4" (2432S024R)
#endif
#if (CYD_HW_VERSION == CYD_TFT_32)
#define USE_CYD_24 1 // Cheap Yellow Display 3.2" (2432S032R)
#endif
#if (CYD_HW_VERSION == CYD_USER_DEFINED)
#if (XPT_MODE == MODE_SPI) // Cheap Yellow Display other type
#define USE_XPT2046_SPI
#endif
#if (XPT_MODE == MODE_BITBANG)
#define USE_XPT2046_BITBANG
#endif
#endif
#if defined(USE_CYD_28) && defined(USE_CYD_24)
#error Seleccione solo un tipo de CYD (Cheap Yellow Display) - Select only one type of CYD (Cheap Yellow Display)
#endif
#define USER_MIN_BL 64 // User min backlight
#define SYS_MIN_BL 32 // System inactivity backlight
#ifdef USE_CYD_28
// Touchscreen pins
#define XPT2046_IRQ 36 // T_IRQ
#define XPT2046_MOSI 32 // T_DIN
#define XPT2046_MISO 39 // T_OUT
#define XPT2046_CLK 25 // T_CLK
#define XPT2046_CS 33 // T_CS
#define USE_XPT2046_BITBANG
#define XPT_ROTATION 0
/*
// I2C pins
#define I2C_SDA 27
#define I2C_SCL 22
*/
//RGB LED
#define RGB_LED_R 4
#define RGB_LED_G 16
#define RGB_LED_B 17
#define USE_RGB_LED PRESENT
//SD Pins
#define SD_CS 5
// Encoder
#define ENCODER_A 22
#define ENCODER_B 27
#define ENCODER_SW 35
#endif
#ifdef USE_CYD_24
// Touchscreen pins
#define XPT2046_IRQ 36 // T_IRQ
#define XPT2046_MOSI 13 // T_DIN
#define XPT2046_MISO 12 // T_OUT
#define XPT2046_CLK 14 // T_CLK
#define XPT2046_CS 33 // T_CS
#define USE_XPT2046_SPI
#define XPT_ROTATION 0
/*
// I2C pins
#define I2C_SDA 21
#define I2C_SCL 22
*/
//RGB LED
#define RGB_LED_R 4
#define RGB_LED_G 17
#define RGB_LED_B 16
#define USE_RGB_LED PRESENT
//SD Pins
#define SD_CS 5
// Encoder
#define ENCODER_A 22
#define ENCODER_B 21
#define ENCODER_SW 35
#endif
#endif

View File

@@ -0,0 +1,151 @@
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
Very basic Graphical User Interface (GUI) for PacoMouseCYD
All data in absolute coordinates
*/
#include <TFT_eSPI.h> // Graphics and font library for ILI9341 driver chip v2.5.43
#include "FreeSans7pt7b.h"
#include "FreeSansBold6pt7b.h"
#define MAX_OBJ_STACK 100
#define MAX_LABEL_LNG 150
#define TMR_RESOLUTION 100
#define NOT_USED 0xFF
#define OBJ_NOT_FOUND 0xFFFF
////////////////////////////////////////////////////////////
// ***** FONTS *****
////////////////////////////////////////////////////////////
#ifndef LOAD_GFXFF
ERROR_Please_enable_LOAD_GFXFF_in_User_Setup!
#endif
#define GFXFF 1
#define FSS7 &FreeSans7pt7b
#define FSS9 &FreeSans9pt7b
#define FSSB6 &FreeSansBold6pt7b
#define FSSB9 &FreeSansBold9pt7b
#define FSSB12 &FreeSansBold12pt7b
////////////////////////////////////////////////////////////
// ***** COLORS *****
////////////////////////////////////////////////////////////
// Colour definitions for 64K colour mode (RGB565)
// Bits 0..4 -> Blue 0..4
// Bits 5..10 -> Green 0..5
// Bits 11..15 -> Red 0..4
// Assign human-readable names to some common 16-bit color values: http://rinkydinkelectronics.com/calc_rgb565.php
// Examples: https://github.com/newdigate/rgb565_colors
#define COLOR_WHITE 0xFFFF
#define COLOR_BLACK 0x0000
#define COLOR_BLUE 0x001F
#define COLOR_NAVY 0x000F
#define COLOR_AQUA 0x5D1C
#define COLOR_SKYBLUE 0x867D
#define COLOR_RED 0xF882
#define COLOR_DARKRED 0x8800
#define COLOR_PINK 0xF97F
#define COLOR_MAGENTA 0xF81F
#define COLOR_GREEN 0x0780
#define COLOR_GREENYELLOW 0xAFE5
#define COLOR_DARKGREEN 0x03E0
#define COLOR_CYAN 0x07FF
#define COLOR_DARKCYAN 0x03EF
#define COLOR_YELLOW 0xFFE0
#define COLOR_GOLD 0xDD24
#define COLOR_LIGHTGREY 0xC618
#define COLOR_DARKGREY 0x7BEF
#define COLOR_LIGHTBLACK 0x4A49
#define COLOR_SMOKYBLACK 0x1061
#define COLOR_CHARCOAL 0x3A2A
#define COLOR_VIOLET 0x9199
#define COLOR_BROWN 0x8200
#define COLOR_ORANGE 0xFD20
#define COLOR_LIME 0x87E0
#define COLOR_MAROON 0x7800
#define COLOR_PURPLE 0x780F
#define COLOR_OLIVE 0x7BE0
#define COLOR_SILVER 0xA510
#define COLOR_CREAM 0xFFF9
#define COLOR_GHOST_WHITE 0xF7BF
#define COLOR_BACKGROUND 0xB5B6 // 0xB6B6B6
#define COLOR_TRANSPARENT TFT_TRANSPARENT
const uint16_t colorDraw[] = {COLOR_BLACK, COLOR_BLUE, COLOR_RED, COLOR_MAGENTA, COLOR_GREEN, COLOR_CYAN, COLOR_YELLOW, COLOR_WHITE,
COLOR_BACKGROUND, COLOR_TRANSPARENT, COLOR_GHOST_WHITE, COLOR_AQUA, COLOR_CREAM, COLOR_SMOKYBLACK, COLOR_SKYBLUE,
COLOR_GOLD,
};
////////////////////////////////////////////////////////////
// ***** OBJECT *****
////////////////////////////////////////////////////////////
enum objTypeGUI {OBJ_UNDEF, OBJ_TIMER, OBJ_WIN, OBJ_BUTTON, OBJ_LABEL, OBJ_TXT, OBJ_BAR, OBJ_DRAWSTR, OBJ_ICON, OBJ_KEYBOARD, OBJ_SWITCH,
OBJ_GAUGE, OBJ_LPIC, OBJ_FNC, OBJ_SLIDER, OBJ_RADIO, OBJ_CHAR,
};
struct wObj { // Graphic objects
uint16_t objType;
uint16_t objID;
};
struct wObj objStack[MAX_OBJ_STACK]; // Object stack
uint16_t endObjStack;
uint16_t lastWinStack;
////////////////////////////////////////////////////////////
// ***** EVENT *****
////////////////////////////////////////////////////////////
enum EventGUI {EVNT_CLICK, EVNT_DRAW, EVNT_WOPEN, EVNT_WCLOSE, EVNT_TIMER, EVNT_BOOT};
typedef struct { // Events
uint16_t objType;
uint16_t objID;
uint16_t eventID;
} wEvent;
wEvent eventStack[32]; // stack for events (size 32, hardcoded in functions. Don't change!)
uint16_t eventIn;
uint16_t eventOut;
uint16_t eventsPending;
uint16_t lastClickX;
uint16_t lastClickY;
////////////////////////////////////////////////////////////
// ***** TIMER *****
////////////////////////////////////////////////////////////
enum timers {TMR_BLIGHT, TMR_END_LOGO, TMR_POWER, TMR_SPEEDO, TMR_INFO, TMR_WAIT, TMR_STEAM, TMR_ACCESSORY, TMR_SCAN, TMR_FNC_ECOS,
TMR_STA_RUN,
MAX_SYS_TIMER
};
enum timerType {TMR_STOP, TMR_ONESHOT, TMR_PERIODIC};
typedef struct {
uint16_t tmrDelay;
uint16_t tmrCount;
uint16_t type;
} wTimer;
wTimer wTimerStack[MAX_SYS_TIMER];
uint32_t timerSys;
#if (TFT_WIDTH == 240)
#include "gui240x320.h"
#endif
#if (TFT_WIDTH == 320)
#include "gui320x480.h"
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,298 @@
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
This software and associated files are a DIY project that is not intended for commercial use.
This software uses libraries with different licenses, follow all their different terms included.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.
Sources are only provided for building and uploading to the device.
You are not allowed to modify the source code or fork/publish this project.
Commercial use is forbidden.
*/
// OPCODES
#define OPC_GPOFF 0x82 // GLOBAL power OFF request
#define OPC_GPON 0x83 // GLOBAL power ON request
#define OPC_LOCO_SPD 0xA0 // SET SLOT speed
#define OPC_LOCO_DIRF 0xA1 // SET SLOT dir,F0-4 state
#define OPC_LOCO_SND 0xA2 // SET SLOT sound functions
#define OPC_LOCO_F9F12 0xA3 // Uhlenbrock
#define OPC_SW_REQ 0xB0 // REQ SWITCH function
#define OPC_SW_REP 0xB1 // Turnout SENSOR state REPORT
#define OPC_INPUT_REP 0xB2 // General SENSOR Input codes
#define OPC_LONG_ACK 0xB4 // Long acknowledge
#define OPC_SLOT_STAT1 0xB5 // WRITE slot stat1
#define OPC_MOVE_SLOTS 0xBA // MOVE slot SRC to DEST
#define OPC_RQ_SL_DATA 0xBB // Request SLOT DATA/status block
#define OPC_SW_STATE 0xBC // REQ state of SWITCH
#define OPC_LOCO_ADR_UHLI 0xBE // REQ loco ADR Uhlenbrock
#define OPC_LOCO_ADR 0xBF // REQ loco ADR
#define OPC_UHLI_FUN 0xD4 // Uhlenbrock
#define OPC_PEER_XFER 0xE5 // move 8 bytes PEER to PEER, SRC->DST
#define OPC_SL_RD_UHLI 0xE6 // SLOT DATA return, 21 bytes Uhlenbrock
#define OPC_SL_RD_DATA 0xE7 // SLOT DATA return, 10 bytes
#define OPC_IMM_PACKET 0xED // SEND n-byte packet immediate
#define OPC_WR_SL_UHLI 0xEE // WRITE SLOT DATA, 21 bytes Uhlenbrock
#define OPC_WR_SL_DATA 0xEF // WRITE SLOT DATA, 10 bytes
// BIT MASK
#define OPC_SW_REP_INPUTS 0x40 // sensor inputs, outputs otherwise
#define OPC_SW_REP_SW 0x20 // switch input, aux input otherwise
#define OPC_SW_REP_HI 0x10 // input is HI, LO otherwise
#define OPC_SW_REP_CLOSED 0x20 // 'Closed' line is ON, OFF otherwise
#define OPC_SW_REP_THROWN 0x10 // 'Thrown' line is ON, OFF otherwise
#define OPC_SW_REQ_DIR 0x20 // switch direction - closed/thrown
#define OPC_SW_REQ_OUT 0x10 // output On/Off
#define OPC_INPUT_REP_SW 0x20 // input is switch input, aux otherwise
#define OPC_INPUT_REP_HI 0x10 // input is HI, LO otherwise
#define STAT1_SL_BUSY 0x20 // BUSY/ACTIVE: bit encoding for SLOT activity
#define STAT1_SL_ACTIVE 0x10
#define GTRK_PROG_BUSY 0x08 // programming track is Busy
#define GTRK_IDLE 0x02 // 0 = Track paused, B'cast EMERG STOP, 1 = Power On
#define GTRK_POWER 0x01 // DCC packets are on and global power is up
// VALUES
#define SLOT_0 0x00 // Slot 0. Identifies command station type if implemented
#define SLOT_FC 0x7B // Fast clock slot
#define SLOT_PRG 0x7C // This slot communicates with the programming track
#define UHLI_PRG_START 0x41 // Intellibox II program task
#define UHLI_PRG_END 0x40
#define LNCV_REQID_CFGREAD 0x1F // LNCV task
#define LNCV_REQID_CFGWRITE 0x20
#define LNCV_REQID_CFGREQUEST 0x21
#define LNCV_FLAG_PRON 0x80
#define LNCV_FLAG_PROFF 0x40
// Message structure to determine the size of a message
typedef struct {
uint8_t command; /* LocoNet Op Code */
uint8_t mesg_size; /* size of the message in bytes */
} szMsg;
/* Turnout sensor state report */
typedef struct swrep_t {
uint8_t command;
uint8_t sn1; /* first byte of report */
uint8_t sn2; /* second byte of report */
uint8_t chksum; /* exclusive-or checksum for the message */
} swRepMsg;
/* Request Switch function */
typedef struct swreq_t {
uint8_t command;
uint8_t sw1; /* first byte of request */
uint8_t sw2; /* second byte of request */
uint8_t chksum; /* exclusive-or checksum for the message */
} swReqMsg;
/* Sensor input report */
typedef struct inputrep_t {
uint8_t command;
uint8_t in1; /* first byte of report */
uint8_t in2; /* second byte of report */
uint8_t chksum; /* exclusive-or checksum for the message */
} inputRepMsg;
/* Slot data request */
typedef struct slotreq_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t pad; /* should be zero */
uint8_t chksum; /* exclusive-or checksum for the message */
} slotReqMsg;
/* Read/Write Slot data messages */
typedef struct rwslotdata_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t slot; /* slot number for this request */
uint8_t stat; /* slot status */
uint8_t adr; /* loco address */
uint8_t spd; /* command speed */
uint8_t dirf; /* direction and F0-F4 bits */
uint8_t trk; /* track status */
uint8_t ss2; /* slot status 2 (tells how to use ID1/ID2 & ADV Consist*/
uint8_t adr2; /* loco address high */
uint8_t snd; /* Sound 1-4 / F5-F8 */
uint8_t id1; /* ls 7 bits of ID code */
uint8_t id2; /* ms 7 bits of ID code */
uint8_t chksum; /* exclusive-or checksum for the message */
} rwSlotDataMsg;
/* Fast Clock Message */
typedef struct fastclock_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t slot; /* slot number for this request */
uint8_t clk_rate; /* 0 = Freeze clock, 1 = normal, 10 = 10:1 etc. Max is 0x7f */
uint8_t frac_minsl; /* fractional minutes. not for external use. */
uint8_t frac_minsh;
uint8_t mins_60; /* 256 - minutes */
uint8_t track_stat; /* track status */
uint8_t hours_24; /* 256 - hours */
uint8_t days; /* clock rollovers */
uint8_t clk_cntrl; /* bit 6 = 1; data is valid clock info */
/* " " 0; ignore this reply */
uint8_t id1; /* id1/id2 is device id of last device to set the clock */
uint8_t id2; /* " " = zero shows not set has happened */
uint8_t chksum; /* exclusive-or checksum for the message */
} fastClockMsg;
/* Programmer Task Message (used in Start and Final Reply, both )*/
typedef struct progtask_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t slot; /* slot number for this request - slot 124 is programmer */
uint8_t pcmd; /* programmer command */
uint8_t pstat; /* programmer status error flags in reply message */
uint8_t hopsa; /* Ops mode - 7 high address bits of loco to program */
uint8_t lopsa; /* Ops mode - 7 low address bits of loco to program */
uint8_t trk; /* track status. Note: bit 3 shows if prog track is busy */
uint8_t cvh; /* hi 3 bits of CV# and msb of data7 */
uint8_t cvl; /* lo 7 bits of CV# */
uint8_t data7; /* 7 bits of data to program, msb is in cvh above */
uint8_t pad2;
uint8_t pad3;
uint8_t chksum; /* exclusive-or checksum for the message */
} progTaskMsg;
/* Set slot sound functions */
typedef struct locosnd_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t snd; /* sound/function request */
uint8_t chksum; /* exclusive-or checksum for the message */
} locoSndMsg;
/* Set slot direction and F0-F4 functions */
typedef struct locodirf_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t dirf; /* direction & function request */
uint8_t chksum; /* exclusive-or checksum for the message */
} locoDirfMsg;
/* Set slot speed functions */
typedef struct locospd_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t spd; /* speed request */
uint8_t chksum; /* exclusive-or checksum for the message */
} locoSpdMsg;
/* send packet immediate message */
typedef struct sendpkt_t {
uint8_t command;
uint8_t mesg_size; /* ummmmm, size of the message in bytes? */
uint8_t val7f; /* fixed value of 0x7f */
uint8_t reps; /* repeat count */
uint8_t dhi; /* high bits of data bytes */
uint8_t im1;
uint8_t im2;
uint8_t im3;
uint8_t im4;
uint8_t im5;
uint8_t chksum; /* exclusive-or checksum for the message */
} sendPktMsg;
/* Long ACK message */
typedef struct longack_t {
uint8_t command;
uint8_t opcode; /* op-code of message getting the response (msb=0) */
uint8_t ack1; /* response code */
uint8_t chksum; /* exclusive-or checksum for the message */
} longAckMsg;
/* Write slot status message */
typedef struct slotstat_t {
uint8_t command;
uint8_t slot; /* slot number for this request */
uint8_t stat; /* status to be written */
uint8_t chksum; /* exclusive-or checksum for the message */
} slotStatusMsg;
/* Move/Link Slot Message */
typedef struct slotmove_t {
uint8_t command;
uint8_t src; /* source slot number for the move/link */
uint8_t dest; /* destination slot for the move/link */
uint8_t chksum; /* exclusive-or checksum for the message */
} slotMoveMsg;
typedef struct
{
uint8_t command; // OPC_PEER_XFER for replies, OPC_IMM_PACKET for commands
uint8_t mesg_size; // 15 bytes
uint8_t SRC; // source
uint8_t DSTL; // destination, low byte
uint8_t DSTH; // destination, high byte
uint8_t ReqId; // Request ID, distinguishes commands
uint8_t PXCT1; // MSBs of following data
uint8_t D0; // Data Bytes
uint8_t D1;
uint8_t D2;
uint8_t D3;
uint8_t D4;
uint8_t D5;
uint8_t D6;
} UhlenbrockMsg;
typedef struct
{
uint8_t command; // OPC_SL_RD_UHLI for replies, OPC_WR_SL_UHLI for commands
uint8_t mesg_size; // 21 bytes
uint8_t unk0;
uint8_t slot; // slot number
uint8_t stat; // slot status
uint8_t adr; // loco address
uint8_t adr2; // loco address high
uint8_t trk; // track status
uint8_t spd; // command speed
uint8_t fhi; // function high bits: F12,F20,F28
uint8_t dirf; // direction and F0-F4 bits
uint8_t snd2; // F5..F11
uint8_t snd3; // F13..F19
uint8_t snd4; // F21..F27
uint8_t unk1; // steps???
uint8_t unk2;
uint8_t unk3;
uint8_t unk4;
uint8_t unk5;
uint8_t unk6;
} UhliSlotMsg;
typedef union {
szMsg sz ;
swRepMsg srp ;
swReqMsg srq ;
inputRepMsg ir ;
slotReqMsg sr ;
rwSlotDataMsg sd ;
fastClockMsg fc ;
progTaskMsg pt ;
locoSndMsg ls ;
locoDirfMsg ldf ;
locoSpdMsg lsp ;
sendPktMsg sp ;
longAckMsg lack ;
slotStatusMsg ss ;
slotMoveMsg sm ;
UhlenbrockMsg ub;
UhliSlotMsg usd;
uint8_t data[32] ;
} lnMsg ;

View File

@@ -0,0 +1,581 @@
/* PacoMouseCYD throttle -- F. Cañada 2025-2026 -- https://usuaris.tinet.cat/fmco/
*/
// Added LANG_FRENCH for French language support
enum language {LANG_ENGLISH, LANG_SPANISH, LANG_CATALAN, LANG_GERMAN, LANG_FRENCH, MAX_LANG};
// Added French translations (LANG_FRENCH) where possible. If missing, falls back to English.
static const char *translations[][MAX_LANG] =
{
// DON'T CHANGE ORDER: Same order defined in labelObj. If a complete translation is missing, must be English definition.
{ // LBL_PACO_TXT
[LANG_ENGLISH] = "PacoMouseCYD",
[LANG_FRENCH] = "PacoMouseCYD",
},
{ // LBL_INIT
[LANG_ENGLISH] = "Welcome!",
[LANG_SPANISH] = "Bienvenido!",
[LANG_CATALAN] = "Benvingut!",
[LANG_GERMAN] = "Willkommen!",
[LANG_FRENCH] = "Bienvenue!",
},
{ // LBL_CONNECT
[LANG_ENGLISH] = "Connecting...",
[LANG_SPANISH] = "Conectando...",
[LANG_CATALAN] = "Connectant...",
[LANG_GERMAN] = "Verbindung...",
[LANG_FRENCH] = "Connexion...",
},
{ // LBL_PRESS
[LANG_ENGLISH] = "Touch to start...",
[LANG_SPANISH] = "Toca para empezar...",
[LANG_CATALAN] = "Toca per iniciar...",
[LANG_GERMAN] = "Beruhren Sie den\nBildschirm, um \nzu beginnen...",
[LANG_FRENCH] = "Touchez l'écran pour\ncommencer...",
},
{ // LBL_CAL
[LANG_ENGLISH] = "To calibrate the\ntouchscreen, touch the\ncorners that appear\nwith the pen.",
[LANG_SPANISH] = "Para calibrar la pantalla,\ntoque las esquinas que\naparecen con el lapiz",
[LANG_CATALAN] = "Per calibrar la pantalla,\ntoqueu les cantonades que\napareixen amb el llapis",
[LANG_GERMAN] = "Um den Touchscreen\nzu kalibrieren, beruhren\nSie die angezeigten Ecken\nmit dem Stift.",
[LANG_FRENCH] = "Pour calibrer l'écran tactile,\ntouchez les coins affichés\navec le stylet.",
},
{ // LBL_CAL_DONE
[LANG_ENGLISH] = "Calibration done.",
[LANG_SPANISH] = "Calibracion realizada.",
[LANG_CATALAN] = "Calibratge realitzat.",
[LANG_GERMAN] = "Kalibrierung\nabgeschlossen.",
[LANG_FRENCH] = "Calibration terminée.",
},
{ // LBL_SCAN
[LANG_ENGLISH] = "SSID WiFi\nScanning...",
[LANG_SPANISH] = "SSID WiFi\nBuscando......",
[LANG_CATALAN] = "SSID WiFi\nEscanejant...",
[LANG_GERMAN] = "SSID WiFi\nScannen...",
[LANG_FRENCH] = "SSID WiFi\nRecherche...",
},
{ // LBL_SSID_SCAN
[LANG_ENGLISH] = "SSID WiFi",
[LANG_FRENCH] = "SSID WiFi",
},
{ // LBL_SSID
[LANG_ENGLISH] = "SSID",
[LANG_FRENCH] = "SSID",
},
{ // LBL_IP
[LANG_ENGLISH] = "IP",
[LANG_FRENCH] = "IP",
},
{ // LBL_PWD_HIDE
[LANG_ENGLISH] = "Password",
[LANG_SPANISH] = NULL,
[LANG_CATALAN] = NULL,
[LANG_GERMAN] = "Passwort",
[LANG_FRENCH] = "Mot de passe",
},
{ // LBL_PORT
[LANG_ENGLISH] = "Port",
[LANG_SPANISH] = "Puerto",
[LANG_FRENCH] = "Port",
},
{ // LBL_PROTOCOL
[LANG_ENGLISH] = "Protocol",
[LANG_SPANISH] = "Protocolo",
[LANG_CATALAN] = NULL,
[LANG_GERMAN] = "Protokoll",
[LANG_FRENCH] = "Protocole",
},
{ // LBL_SEL_PROT
[LANG_ENGLISH] = "Protocol",
[LANG_SPANISH] = "Protocolo",
[LANG_CATALAN] = NULL,
[LANG_GERMAN] = "Protokoll",
[LANG_FRENCH] = "Protocole",
},
{ // LBL_SEL_Z21
[LANG_ENGLISH] = "Z21",
[LANG_FRENCH] = "Z21",
},
{ // LBL_SEL_XNET
[LANG_ENGLISH] = "Xpressnet LAN",
[LANG_FRENCH] = "Xpressnet LAN",
},
{ // LBL_SEL_ECOS
[LANG_ENGLISH] = "ECoS",
[LANG_FRENCH] = "ECoS",
},
{ // LBL_SEL_LNET
[LANG_ENGLISH] = "Loconet sur TCP/IP",
},
{ // LBL_SEL_LBSERVER
[LANG_ENGLISH] = "LBServer",
[LANG_FRENCH] = "LBServer",
},
{ // LBL_SEL_BINARY
[LANG_ENGLISH] = "Binaire",
},
{ // LBL_OPTIONS
[LANG_ENGLISH] = "Options",
[LANG_SPANISH] = "Opciones",
[LANG_CATALAN] = "Opcions",
[LANG_GERMAN] = "Optionen",
[LANG_FRENCH] = "Options",
},
{ // LBL_NAME
[LANG_ENGLISH] = "Name",
[LANG_SPANISH] = "Nombre",
[LANG_CATALAN] = "Nom",
[LANG_GERMAN] = NULL,
[LANG_FRENCH] = "Nom",
},
{ // LBL_ADDR
[LANG_ENGLISH] = "Address",
[LANG_SPANISH] = "Direccion",
[LANG_CATALAN] = "Direccio",
[LANG_GERMAN] = "Adresse",
[LANG_FRENCH] = "Adresse",
},
{ // LBL_IMAGE
[LANG_ENGLISH] = "Image",
[LANG_SPANISH] = "Imagen",
[LANG_CATALAN] = "Imatge",
[LANG_GERMAN] = "Bild",
[LANG_FRENCH] = "Image",
},
{ // LBL_VMAX
[LANG_ENGLISH] = "Speed max.",
[LANG_SPANISH] = "Vel. max.",
[LANG_CATALAN] = "Vel. max.",
[LANG_GERMAN] = "Geschw.max.",
[LANG_FRENCH] = "Vitesse max.",
},
{ // LBL_FUNC
[LANG_ENGLISH] = "Functions",
[LANG_SPANISH] = "Funciones",
[LANG_CATALAN] = "Funcions",
[LANG_GERMAN] = "Funktionen",
[LANG_FRENCH] = "Fonctions",
},
{ // LBL_SERVICE
[LANG_ENGLISH] = "Service Mode",
[LANG_SPANISH] = "Modo Servicio",
[LANG_CATALAN] = "Mode Servei",
[LANG_GERMAN] = "Servicemodus",
[LANG_FRENCH] = "Mode Service",
},
{ // LBL_KMH
[LANG_ENGLISH] = "km/h",
[LANG_FRENCH] = "km/h",
},
{ // LBL_SHUNTING
[LANG_ENGLISH] = "Shunting",
[LANG_SPANISH] = "Maniobras",
[LANG_CATALAN] = "Maniobres",
[LANG_GERMAN] = "Rangieren",
[LANG_FRENCH] = "Manœuvre",
},
{ // LBL_RATE
[LANG_ENGLISH] = "Rate 1:",
[LANG_SPANISH] = "Ratio 1:",
[LANG_CATALAN] = "Ratio 1:",
[LANG_GERMAN] = NULL,
[LANG_FRENCH] = "Rapport 1:",
},
{ // LBL_CHG_WIFI
[LANG_ENGLISH] = "Reset to apply\nchanges",
[LANG_SPANISH] = "Reinicie para\naplicar los\ncambios",
[LANG_CATALAN] = "Reiniciar per \naplicar els\ncanvis",
[LANG_GERMAN] = "Neustart, um die\nAnderungen zu\nübernehmen",
[LANG_FRENCH] = "Redémarrez pour\nappliquer les\nchangements",
},
{ // LBL_EDIT_FUNC
[LANG_ENGLISH] = "Functions",
[LANG_SPANISH] = "Funciones",
[LANG_CATALAN] = "Funcions",
[LANG_GERMAN] = "Funktionen",
[LANG_FRENCH] = "Fonctions",
},
{ // LBL_STACK_FULL
[LANG_ENGLISH] = "Locomotive stack\nfull!",
[LANG_SPANISH] = "Almacen de\nlocomotoras\nlleno!",
[LANG_CATALAN] = "Magatzem de\nlocomotores\nple!",
[LANG_GERMAN] = "Lokomotivstapel\nvoll!",
[LANG_FRENCH] = "Pile de locomotives\npleine!",
},
{ // LBL_STOP_0
[LANG_ENGLISH] = "Speed 0",
[LANG_SPANISH] = "Velocidad 0",
[LANG_CATALAN] = "Velocitat 0",
[LANG_GERMAN] = "Geschw. 0",
[LANG_FRENCH] = "Vitesse 0",
},
{ // LBL_STOP_E
[LANG_ENGLISH] = "Emerg. Stop",
[LANG_SPANISH] = "Stop Emerg.",
[LANG_CATALAN] = "Stop Emerg.",
[LANG_GERMAN] = "Not-Halt",
[LANG_FRENCH] = "Arrêt d'urgence",
},
{ // LBL_SEL_IMAGE
[LANG_ENGLISH] = "Image",
[LANG_SPANISH] = "Imagen",
[LANG_CATALAN] = "Imatge",
[LANG_GERMAN] = "Bild",
},
{ // LBL_MENU_DRIVE
[LANG_ENGLISH] = "Drive",
[LANG_SPANISH] = "Conducir",
[LANG_CATALAN] = "Conduir",
[LANG_GERMAN] = "Fahren",
},
{ // LBL_MENU_ACC
[LANG_ENGLISH] = "Accesory",
[LANG_SPANISH] = "Accesorios",
[LANG_CATALAN] = "Accesoris",
[LANG_GERMAN] = "Zubehorartikel",
},
{ // LBL_MENU_CV
[LANG_ENGLISH] = "CV Programming",
[LANG_SPANISH] = "Programar CV",
[LANG_CATALAN] = "Programar CV",
[LANG_GERMAN] = "CV-Programmierung",
},
{ // LBL_MENU_CFG
[LANG_ENGLISH] = "Configure",
[LANG_SPANISH] = "Configurar",
[LANG_CATALAN] = "Configurar",
[LANG_GERMAN] = "Einstellungen",
},
{ // LBL_MENU_UTILS
[LANG_ENGLISH] = "Utilities",
[LANG_SPANISH] = "Utilidades",
[LANG_CATALAN] = "Utilitats",
[LANG_GERMAN] = "Dienstprogramme",
},
{ // LBL_CFG_LANG
[LANG_ENGLISH] = "Language",
[LANG_SPANISH] = "Idioma",
[LANG_CATALAN] = "Idioma",
[LANG_GERMAN] = "Sprache",
},
{ // LBL_CFG_SCR
[LANG_ENGLISH] = "Screen",
[LANG_SPANISH] = "Pantalla",
[LANG_CATALAN] = "Pantalla",
[LANG_GERMAN] = "Bildschirm",
},
{ // LBL_CFG_SPD
[LANG_ENGLISH] = "Speed",
[LANG_SPANISH] = "Velocidad",
[LANG_CATALAN] = "Velocitat",
[LANG_GERMAN] = "Geschwindigkeit",
},
{ // LBL_CFG_WIFI
[LANG_ENGLISH] = "WiFi",
},
{ // LBL_CFG_FCLK
[LANG_ENGLISH] = "Fast Clock",
[LANG_SPANISH] = "Reloj",
[LANG_CATALAN] = "Rellotge",
[LANG_GERMAN] = "Uhr",
},
{ // LBL_CFG_LOCK
[LANG_ENGLISH] = "Lock",
[LANG_SPANISH] = "Bloquear",
[LANG_CATALAN] = "Bloquejar",
[LANG_GERMAN] = "Sperre",
},
{ // LBL_CFG_ABOUT
[LANG_ENGLISH] = "About...",
[LANG_SPANISH] = "Acerca...",
[LANG_CATALAN] = "Sobre...",
[LANG_GERMAN] = "Info...",
},
{ // LBL_SCR_ROTATE
[LANG_ENGLISH] = "Rotate",
[LANG_SPANISH] = "Girar",
[LANG_CATALAN] = "Girar",
[LANG_GERMAN] = "Drehen",
},
{ // LBL_PACO_WEB
[LANG_ENGLISH] = "https://usuaris.tinet.cat/fmco",
},
{ // LBL_LOCK_LOK
[LANG_ENGLISH] = "Locomotives",
[LANG_SPANISH] = "Locomotoras",
[LANG_CATALAN] = "Locomotores",
[LANG_GERMAN] = "Lokomotiven",
},
{ // LBL_LOCK_ACC
[LANG_ENGLISH] = "Accesory",
[LANG_SPANISH] = "Accesorios",
[LANG_CATALAN] = "Accesoris",
[LANG_GERMAN] = "Zubehorartikel",
},
{ // LBL_LOCK_PRG
[LANG_ENGLISH] = "Programming",
[LANG_SPANISH] = "Programar",
[LANG_CATALAN] = "Programar",
[LANG_GERMAN] = "Programmierung",
},
/*
{ // LBL_OPT_ROCO
[LANG_ENGLISH] = "Turntable offset",
[LANG_SPANISH] = "Offset Plataforma",
[LANG_CATALAN] = "Offset Plataforma",
[LANG_GERMAN] = "Drehscheibe Versatz",
},
*/
{ // LBL_OPT_ADR
[LANG_ENGLISH] = "Short Addr. (1 to 99)",
[LANG_SPANISH] = "Dir. corta (1 a 99)",
[LANG_CATALAN] = "Dir. curta (1 a 99)",
[LANG_GERMAN] = "Kurze Adr. (1 bis 99)",
},
{ // LBL_OPT_IB2
[LANG_ENGLISH] = "IBII / DR5000",
},
{ // LBL_OPT_UHLI
[LANG_ENGLISH] = "Uhlenbrock",
},
{ // LBL_OPT_DIG
[LANG_ENGLISH] = "Digitrax",
},
{ // LBL_ESTOP
[LANG_ENGLISH] = "Emergency Stop",
[LANG_SPANISH] = "Stop Emergencia",
[LANG_CATALAN] = "Stop Emergencia",
[LANG_GERMAN] = "Nothalt",
},
{ // LBL_SCALE
[LANG_ENGLISH] = "Scale",
[LANG_SPANISH] = "Escala",
[LANG_CATALAN] = "Escala",
[LANG_GERMAN] = "Skala",
},
{ // LBL_MM
[LANG_ENGLISH] = "mm",
},
{ // LBL_SCALE_H0
[LANG_ENGLISH] = "H0",
},
{ // LBL_SCALE_N
[LANG_ENGLISH] = "N",
},
{ // LBL_SCALE_TT
[LANG_ENGLISH] = "TT",
},
{ // LBL_SCALE_Z
[LANG_ENGLISH] = "Z",
},
{ // LBL_SCALE_0
[LANG_ENGLISH] = "0",
},
{ // LBL_MEASURE
[LANG_ENGLISH] = "Measuring",
[LANG_SPANISH] = "Midiendo",
[LANG_CATALAN] = "Mesurant",
[LANG_GERMAN] = "Messung",
},
{ // LBL_CV_ADDR
[LANG_ENGLISH] = "Loco Address",
[LANG_SPANISH] = "Direcc. Loco",
[LANG_CATALAN] = "Direcc. Loco",
[LANG_GERMAN] = "Lokadresse",
},
{ // LBL_CV_SPD_L
[LANG_ENGLISH] = "Speed min.",
[LANG_SPANISH] = "Velocidad min.",
[LANG_CATALAN] = "Velocitat min.",
[LANG_GERMAN] = "Minimale Geschw.",
},
{ // LBL_CV_SPD_M
[LANG_ENGLISH] = "Speed mid.",
[LANG_SPANISH] = "Velocidad media",
[LANG_CATALAN] = "Velocitat mitja",
[LANG_GERMAN] = "Mittlere Geschw.",
},
{ // LBL_CV_SPD_H
[LANG_ENGLISH] = "Speed max.",
[LANG_SPANISH] = "Velocidad max.",
[LANG_CATALAN] = "Velocitat max.",
[LANG_GERMAN] = "Maximale Geschw.",
},
{ // LBL_CV_ACC
[LANG_ENGLISH] = "Acceleration",
[LANG_SPANISH] = "Aceleracion",
[LANG_CATALAN] = "Acceleracio",
[LANG_GERMAN] = "Beschleunig",
},
{ // LBL_CV_DEC
[LANG_ENGLISH] = "Braking",
[LANG_SPANISH] = "Frenado",
[LANG_CATALAN] = "Frenada",
[LANG_GERMAN] = "Bremsen",
},
{ // LBL_CV_CFG
[LANG_ENGLISH] = "Configuration",
[LANG_SPANISH] = "Configuracion",
[LANG_CATALAN] = "Configuracio",
[LANG_GERMAN] = "Konfiguration",
},
{ // LBL_CV_MAN
[LANG_ENGLISH] = "Manufacturer",
[LANG_SPANISH] = "Fabricante",
[LANG_CATALAN] = "Fabricant",
[LANG_GERMAN] = "Hersteller",
},
{ // LBL_CV
[LANG_ENGLISH] = "CV",
},
{ // LBL_LNCV
[LANG_ENGLISH] = "LNCV",
},
{ // LBL_POM
[LANG_ENGLISH] = "PoM",
},
{ // LBL_BITS
[LANG_ENGLISH] = "Bits",
},
{ // LBL_CV_ERROR
[LANG_ENGLISH] = "CV ERROR",
[LANG_SPANISH] = "ERROR CV",
[LANG_CATALAN] = "ERROR CV",
[LANG_GERMAN] = "CV-FEHLER",
},
{ // LBL_UTIL_SPEED
[LANG_ENGLISH] = "Measure speed",
[LANG_SPANISH] = "Medir velocidad",
[LANG_CATALAN] = "Mesurar velocitat",
[LANG_GERMAN] = "Geschw. messen",
},
{ // LBL_UTIL_STEAM
[LANG_ENGLISH] = "Steam locomotive",
[LANG_SPANISH] = "Locomotora de vapor",
[LANG_CATALAN] = "Locomotora de vapor",
[LANG_GERMAN] = "Dampflokomotive",
},
{ // LBL_UTIL_SCAN
[LANG_ENGLISH] = "WiFi Analyzer",
[LANG_SPANISH] = "Analizador de WiFi",
[LANG_CATALAN] = "Analitzador de WiFi",
[LANG_GERMAN] = "WLAN-Analysator",
},
{ // LBL_UTIL_STA
[LANG_ENGLISH] = "Station Run",
[LANG_SPANISH] = "Carrera de estaciones",
[LANG_CATALAN] = "Carrera d'estacions",
[LANG_GERMAN] = "Bahnhofsrennen",
},
{ // LBL_ASK_SURE
[LANG_ENGLISH] = "Are you sure?",
[LANG_SPANISH] = "Estas seguro?",
[LANG_CATALAN] = "Segur?",
[LANG_GERMAN] = "Bist du sicher?",
},
{ // LBL_OPT_DISCOVER
[LANG_ENGLISH] = "Discover",
[LANG_SPANISH] = "Descubrir",
[LANG_CATALAN] = "Descobrir",
[LANG_GERMAN] = "Entdecken",
},
{ // LBL_LNCV_ART
[LANG_ENGLISH] = "Article",
[LANG_SPANISH] = "Articulo",
[LANG_CATALAN] = NULL,
[LANG_GERMAN] = "Artikel",
},
{ // LBL_LNCV_MOD
[LANG_ENGLISH] = "Module",
[LANG_SPANISH] = "Modulo",
[LANG_CATALAN] = "Modul",
[LANG_GERMAN] = "Modul",
},
{ // LBL_LNCV_NUM
[LANG_ENGLISH] = "LNCV",
},
{ // LBL_ACC_TYPE
[LANG_ENGLISH] = "Accessory type",
[LANG_SPANISH] = "Tipo accesorio",
[LANG_CATALAN] = "Tipus accessori",
[LANG_GERMAN] = "Zubehortyp",
},
{ // LBL_ACC_NAME
[LANG_ENGLISH] = "Name",
[LANG_SPANISH] = "Nombre",
[LANG_CATALAN] = "Nom",
[LANG_GERMAN] = NULL,
},
{ // LBL_ACC_ADDR
[LANG_ENGLISH] = "Addr.",
[LANG_SPANISH] = "Dir.",
[LANG_CATALAN] = "Dir.",
[LANG_GERMAN] = "Adr.",
},
{ // LBL_STA_RUN
[LANG_ENGLISH] = "Station Run",
[LANG_SPANISH] = "Carrera de estaciones",
[LANG_CATALAN] = "Carrera d'estacions",
[LANG_GERMAN] = "Bahnhofsrennen",
},
{ // LBL_STA_LEVEL
[LANG_ENGLISH] = "Level:",
[LANG_SPANISH] = "Nivel:",
[LANG_CATALAN] = "Nivell:",
[LANG_GERMAN] = NULL,
},
{ // LBL_STA_START
[LANG_ENGLISH] = "Start",
[LANG_SPANISH] = "Iniciar",
[LANG_CATALAN] = "Iniciar",
[LANG_GERMAN] = "Starten",
},
{ // LBL_STA_INSTR
[LANG_ENGLISH] = "Go to the station of your\ndestination color.\nPress it when you arrive",
[LANG_SPANISH] = "Ve a la estacion del color\nde tu destino.\nPulsala cuando llegues",
[LANG_CATALAN] = "Ves a l'estacio del color\nde la teva destinacio.\nPrem-la quan arribis",
[LANG_GERMAN] = "Gehen Sie sich zum Bahnhof\nIhrer Zielfarbe. Klicken Sie\ndas Symbol, wenn Sie ankommen",
},
{ // LBL_STA_EXCEL
[LANG_ENGLISH] = "Excellent!",
[LANG_SPANISH] = "Excelente!",
[LANG_CATALAN] = "Excel.lent!",
[LANG_GERMAN] = "Exzellent!",
},
{ // LBL_STA_GREAT
[LANG_ENGLISH] = "Great!",
[LANG_SPANISH] = "Muy bien!",
[LANG_CATALAN] = "Molt be!",
[LANG_GERMAN] = "Sehr gut!",
},
{ // LBL_STA_TIMEOUT
[LANG_ENGLISH] = "TIME'S UP\nThanks for playing",
[LANG_SPANISH] = "FIN DEL TIEMPO\nGracias por jugar",
[LANG_CATALAN] = "FINAL DEL TEMPS\nGracies per jugar",
[LANG_GERMAN] = "DIE ZEIT IST UM\nDanke furs Spielen",
},
{ // LBL_STA_STATIONS
[LANG_ENGLISH] = "Stations",
[LANG_SPANISH] = "Estaciones",
[LANG_CATALAN] = "Estacions",
[LANG_GERMAN] = "Bahnhofe",
},
{ // LBL_STA_TURNOUTS
[LANG_ENGLISH] = "Turnouts",
[LANG_SPANISH] = "Desvios",
[LANG_CATALAN] = "Agulles",
[LANG_GERMAN] = "Weichen",
},
{ // LBL_STA_TIME
[LANG_ENGLISH] = "Time",
[LANG_SPANISH] = "Tiempo",
[LANG_CATALAN] = "Temps",
[LANG_GERMAN] = "Zeit",
},
{ // LBL_STA_DESC
[LANG_ENGLISH] = "Address Orientat. Inverted",
[LANG_SPANISH] = "Direcc. Orientac. Invertido",
[LANG_CATALAN] = "Direcc. Orientacio Invertit",
[LANG_GERMAN] = "Adresse Ausricht. Invertiert",
},
};