Gibt es was effektiveres als eine Lookup-Table für bis zu 255 Elemente?

Ich habe eine lookup-Table mit Texten, die in einem Byte codiert sind.
Derzeit sind da 70+ Texte versteckt.

struct UnitTable
{
  uint8_t pic;
  char *value;
};

Gibt es etwas sinnvolleres als:

void displayValue(const byte einheit)
{
for (byte b=0; b<elementcount; b++)
{
  if (unittable[b].pic == einheit)
  {
    // machwas
  }
}
}

um an die Inhalte zu kommen?
Was nicht geht: Ein direkter Zugriff über das Byte einheit auf das Element in der Structur, da es derzeit nur etwa 70 Element egibt, die aber nicht fortlaufend durchnumeriert sind.

Meine Idee war jetzt die Initialisierung von b aus der Schleife zu nehmen und vorher mit wenigstens einem if()die Hälfte zu erschlagen:

void displayValue(const byte einheit)
{
  byte b = einheit > 35 ? 35 : 0;
  for (;b < elementcount; b++)
  {
    if (unittable[b].pic == einheit)
    {
      // machwas
    }
  }
}

Andere Vorschläge?

Definiere "sinnvoll" :slight_smile:
Wie immer: Speicher sparen oder Laufzeit gewinnen?

Bastel doch zwei Arrays:
Einen elementcount langen mit den Zeigern auf die Texte und einen zweiten, 256 Byte langen, der den Index auf die Texttabelle hält. Da musst Du nur einen Wert (0, 255) als "leer" definieren.
Dann kannst Du mit einheit direkt aus dem zweiten Array den Index für den ersten holen.

1 Like

Besteht die Möglichkeit, die Elemente sortiert abzulegen?
Ich weiß jetzt nicht mehr, wie es heißt, aber der Weg wäre dann:

  • Greife auf die Mitte zu.
  • ist das element dort kleiner, als das gesuchte, greife auf die Mitte des oberen Teils zu, sonst auf die Mitte des unteren Teils.
  • usw. bis gefunden

Gruß Tommy

1 Like

Meinst Du "Binäre Suche"?

Hast Recht.

Gruß Tommy

Die Idee hatte ich so ähnlich auch schon. Einfach ein Array mit 256 Einträgen anfertigen und die ungenutzten einfach mit "N/A" stehen zu lassen.

Ja.
Die Sortierung bestimme ich selbst.
Das würde ja fast schon an mein Konstrukt ran kommen.

Das ist sicher die schnellste Methode, kostet aber je nach Größe des Pointers und Füllgrad (70) mehr Speicher.

1 Like

Genau das ist mein Problem.

Ich bräuchte 1030 Bytes als Arbeitspuffer, weitere für das zwischenspeichern eines Streams und vermutlich nochmal 500 bytes allein für das ganze andere Geraffel.

Und der UNO hat nicht soviel.

Vielleicht die Texte mit dem flash_helper verschieben....

Ich denk mal drüber nach.

auf welchem Microcontroller?

1 Like

Momentan auf einem 328.Das Projekt wird vermutlich zu groß werden und auch zeitlich recht kritisch, dass ich mit größeren Speichern arbeiten muss und dann auf einen MEGA umsteige, wenn gar nichts mehr geht.

wonach möchtest du optimieren? Speicherbedarf (SRAM oder PROGMEM) oder Zugriffsgeschwindigkeit? Einfachster Zugriff?

1 Like

Momentan auf Geschwindigkeit.
Der Stream kommt mit 9600 und ich darf kein byte verlieren.
Ich weiss nicht wie lang der tatsächlich ist und kann daher auch keinen "passenden" Zwischenspeicher anlegen. Daher müssen die Daten "onTheFly" verarbeitet werden.
SmartMessageLanguage eben.

Ich weiß. Wir haben das hier schon hundertfach durchgekaut. Ein fester Puffer für die Nachricht geht nicht. Die Norm gibt das nicht her und es gibt noch mehr als nur die optische Schnittstelle am Stromzähler :wink:

Ein Hash Table, wie es Forth in seinem Vocabulary macht und nachfolgend eine einfach verkettete Liste.

Unbelegt: 9600 ist doch langsam genug dass du dir auf einen AVR leisten kannst, ein Array mit 70 Einträge durchzuscannen (evtl. mit break bei Erfolg ausbrechen).

Ist es nicht? Zeig mal ein wenig Code um das nachvollziehen zu können.

2 Likes

Mir gehen Bytes aus dem Stream während der Verarbeitung verloren, da ich immer warten muss, bis eine Nachricht selbst vollständig da ist.
Erst dann kann ich anhand der CRC feststellen ob die ordentlich ist - das funktioniert auch.
Ich habe auch während der Übernahme des Streams schon die Adressen wo ich was finde.
Aber während der Ausgabe läuft der Stream weiter.
Also heisst es erstmal die Ausgabe optimieren.

Bei einem atmega328 würde ich immer erstmal auf Speicherplatz optimieren.

Bei 9600 hast du mindestens 1000 µs Zeit, ein Byte zu "verarbeiten" und 64.000 µs Zeit, bis der Serielle Eingangs-Puffer überläuft. Bei SML sind sehr viele Bytes drin, die du einfach ignorierst.

Wenn du die Liste sortieren kannst, brauchst du bei binärem Suchen max. 7 Zugriffe für deine 70 (max. 127) Elemente. Da bleibt dein Eingangspuffer immer komplett leergelesen, schätze ich.
( Was machst du mit dem gefundenen Text ? Nicht dass du an der falschen Stelle optimierst :slight_smile: )

1 Like

Naja. Ich mach ja das mit dem SML schon ne Weile.
Ohne Ausgaben geht das schon. :wink:

Ne im Ernst: Du kannst nicht einfach so irgendwas ignorieren, wenn es richtig sein soll.
Es braucht jedes TL-Byte.
Und jedes Inhalt-Bytet, sonst gibts kein CRC.

Das ist auch alles nicht das Problem.
Während des Streams einlesen merke ich mir wo sich was befindet.
Aber erst wenn die Nachricht vollständig da ist, darf ich die inhaltlich verarbeiten.

Die nächste Nachricht beginnt aber bereits 1ms nach dem Ende der zu verarbeitenden Nachricht.
(Es gibt keine Pause zwischen den Nachrichten! Die Pause ist zulässig zwischen 2 Dateien)
In der Zeit muss also alles was ich an Infos habe ausgegeben werden.

Die 64ms für das füllen des FIFO passen nur dann, wenn die letzte Leerung genau auf das letze Byte der Nachricht gepasst hat.
Das ist aber seltenst (bis gar nicht) der Fall.

Das mit den 7 Zugriffen ist wohl der beste Anzśatz.

Ja, natürlich darfst du kein Zeichen verlieren.
Aber bei vielen Zeichen hast du weniger zu tun, als mehrfach eine Tabelle zu durchsuchen, war mein Standpunkt. Selbst wenn du selten mal mehr als 1 ms brauchen solltest, hast du das nach ein paar einfach zu verarbeitenden Zeichen wieder aufgeholt und dein Uno wartet geduldig, bis wieder ein Zeichen kommt.

Da hättest du viel Zeit ... ( wenn es zwischen zwei Dateien zu eng wird )

1 Like

Aber kein testbarer Code, auch keinen Testdaten.
Nix...
Wofür haben wir denn die Forenregeln, zum ignorieren?

So gesehen schon.
Nur klappt das eben nicht.

Bei einer Werteliste mit 20 Listenelementen, denen jeweils 7 Werteelemente zugeordnet sind, klemmt es mit der Ausgabe.

Da darf ich aber nix berechnen und ausgeben, da ja noch nicht bekannt ist, ob der Inhalt stimmt.
Die CRC sind die vorletzten 2byte der Nachricht.
Solange ich die nicht gültig habe, kann ich mir nur merken wo ich was finde.

Ich kann auch nicht auf das Ende der Datei warten.
Eine (SML)Datei hat eine unbestimmte Länge.
Die einzige feste Größe, die die Norm vorgibt ist eine Nachrichtenlänge.
Diese darf nicht mehr als 1024 bytes sein.
Eine Datei besteht aus mindestens 2 Nachrichten. (Open/Close)
Die Wertelisten stehen dazwischen und dürfen in mehreren Nachrichten aufgeteilt werden.
Damit sind die Grenzen gesetzt.

Ich habe eine Frage gestellt und auch passenden Code zur Frage geliefert.
Aber Du hast natürlich recht. Es muss nicht die Norm erklärt werden.