3Byte Variablen , Wege zum uint12_t [gelöst]

ich stell mir gerade die Frage welche elegante Möglichkeit es gäbe eine 3 Byte Variable zu definieren.

Ein Union mit drei separten uint8_t?

Anwenden möchte ich das mit einer Struktur im PROGMEM die aktuell ein Mapping von UTF8 Codes auf den LCD Zeichensatz hält.
Da ich aber kein Mapping von 4 Byte UTF8 brauche sondern meine UTF8 Codes max. 3 Bytes haben, würde ich gern das nicht benötigte Byte generell einsparen.

struct Mapping {
  uint32_t utf8;           
  uint8_t c;
};

const Mapping ROM_A00[] PROGMEM =  {
  {0xC3A4, 0xE1},   // ä   // sorted to top, assumption: ä ö ü are used more often
  {0xC3B6, 0xEF},   // ö
  {0xC3BC, 0xF5},   // ü
  {0xC384, 'A'},  // Ä       
  {0xC396, 'O'},  // Ö
  {0xC39C, 'U'},  // Ü
  {0xC39F, 0xE2},   // ß to GREEK SMALL LETTER BETA
  {0xC2A3, 0xED},   // Pound SIGN
  {0xC2A5, 0x5C},   // YEN SIGN
  {0xC2B0, 0xDF},   // DEGREE SIGN#
  {0xE28690, 0x7F}, // LEFTWARDS ARROW
  {0xE28692, 0x7E}, // RIGHTWARDS ARROW
usw
struct Mapping
{
  uint8_t utf8[3];
  uint8_t c;

  Mapping(uint32_t utf8)
  {
    this->utf8[0] = utf8;
    this->utf8[1] = utf8 >> 8;
    this->utf8[2] = utf8 >> 16;
  }

  uint32_t operator ()()
  {
    return (uint32_t)utf8[2] << 16 | (uint16_t)utf8[1] << 8 | utf8[0];
  }
};

void setup(void)
{
  Serial.begin(9600);

  Mapping mapping(0xB0A010);
  Serial.println(mapping.utf8[0], HEX);
  Serial.println(mapping.utf8[1], HEX);
  Serial.println(mapping.utf8[2], HEX);
  Serial.println(mapping(), HEX);
}

void loop(void)
{ }

Behandelt so nur utf8. Das Zeichen c muss man noch ergänzen. Aber es geht erst mal nur um das Abspeichern

1 Like

Was willst Du denn so spezielles speichern, und was spricht gegen c-Strings? C++ verwendet doch standardmäßig UTF8:

void setup() {
    // put your setup code here, to run once:
    Serial.begin ( 115200 );
    Serial.print("Länge von \"abc\" = "); Serial.println ( strlen("abc") );
    Serial.print("Länge von \"öäü\" = "); Serial.println ( strlen("öäü") );
    Serial.print("Länge von 'a' = "); Serial.println ( sizeof('a'));
    Serial.print("Länge von 'ö' = "); Serial.println ( sizeof('ö') );
}

void loop() {
    // put your main code here, to run repeatedly:

}
}

void loop() {
    // put your main code here, to run repeatedly:

}

ergibt:

Länge von "abc" = 3
Länge von "öäü" = 6
Länge von 'a' = 1
Länge von 'ö' = 2

hab mich da vermutlich eh nur verrannt. Das mit dem Array wird schon passen, komme aber erst am Abend dazu.

Wie angesprochen es wird eine Mapping Tabelle UTF8 --> LCD Character ROM Set.
Aktuell habe ich das in einer Wurst von Switch-Case Anweisungen. Das migriere ich rüber auf eben eine PROGMEM Tabelle.

Vermutlich liegen die Zeichen, die das Display darstellen kann, in der Unicode BMP (Basic Mapping Page), brauchen also nur 2 Byte (wchar_t).

jeep, werde mir für die 3byter einfach Entsprechungen im BMP suchen...

{0xE28690, 0x7F, 0}, // LEFTWARDS ARROW
{0xE28692, 0x7E, 0}, // RIGHTWARDS ARROW
{0xE2889A, 0xE8, 0}, // SQUARE ROOT
{0xE2889D, 0xE0, 0}, // PROPORTIONAL TO
{0xE2889E, 0xF3, 0} // Infiniy

microbahner:
C++ verwendet doch standardmäßig UTF-8

Das würde ich nicht so allgemein formulieren, stimmt aber jedenfalls für die Arduino-IDE.

avr-gcc warnt immerhin
warning: multi-character character constant [-Wmultichar]
bei sizeof('ö')

Dr Dietrich: Also mich hat die Suche in den 2 Byte utf-8 Zeichen nicht wirklich weitergebracht. Die Unicode-BMP hilft mir ja wenig, wenn ich als Input UTF-8 erhalte.

Naja egal, jedenfals habe ich jetzt meine Mapping-Tabelle auf 2 Byte eingekürzt. Für die fünf 3-Byte Zeichen die ich aktuell habe muss ich halt einen Kompromiss nehmen.

Ich mappe die zwei LSB, und wenn ich dafür ein Zeichen habe, dann gibts eben den Pfeil auf dem LCD, egal, ob ich zunächst e3 oder e2 erhalten habe

e3 86 90 I DEOGRAPHIC ANNOTATION LINKING MARK
e2 86 90 LEFTWARDS ARROW

immer noch besser als 3 wahllose Zeichen die sonst kämen...

AFAIK benutzt Unicode nur 21 Bit, damit wäre sowohl 0xE2 als auch 0x90 als MSB falsch. Woher bekommst Du denn diese seltsamen Codes?

UTF-8 kann doch in Unicode Zeichen umgerechnet werden, wieso machst Du das nicht?

Wenn ich mich nicht verrechnet habe, dann bedeutet UTF-8 E3 86 90 in Unicode 0x3190, also 16 Bit wie ich vermutet habe.

Okay, verrechnet, der richtige Unicode ist 0x4063.

DrDiettrich:
AFAIK benutzt Unicode nur 21 Bit, damit wäre sowohl 0xE2 als auch 0x90 als MSB falsch. Woher bekommst Du denn diese seltsamen Codes?

ich bekomme UTF8 Codes mittels gewöhnlicher print Ausgabe in meine write methode:

lcd.print( "→");

UTF-8 kann doch in Unicode Zeichen umgerechnet werden, wieso machst Du das nicht?
Wenn ich mich nicht verrechnet habe, dann bedeutet UTF-8 E3 86 90 in Unicode 0x3190, also 16 Bit wie ich vermutet habe.

dann müsste ich jedes Zeichen das ich suchen will, zunächst umrechnen und diesen zusätzlichen Rechenschritt werde ich nicht machen.

PS: du kannst die Frage als gelöst betrachten.