Forum: Compiler & IDEs [Suche] Menüsystem, welches man dynamisch befüllen kann


von Sven S. (schwerminator)


Lesenswert?

Hallo,
ich suche ein Menüsystem, bei dem man wärend des Programmablaufs 
Menüeinträge hinzufügen kann. Das hat den Hintergrund, dass einige 
Menüeinträge aus einem externen EEPROM geholt werden sollen. Kennt ihr 
da Menüsysteme, die so etwas leisten? Bei allen, die ich gefunden habe 
sind die Menüeinträge in Anzahl und/oder Inhalt durch das Programm von 
vornherein festgelegt.

Ich hoffe, ihr habt mein Anliegen verstanden und wisst Rat ;)

mfG, Sven

von Frank L. (franklink)


Lesenswert?

Hallo Sven,
generell würde ich erstmal sagen, ein Menüsystem aus einem externen 
EEprom könnte sich genaus verhalten, wie eins, dass aus dem Progmem 
gelesen wird.

Wenn Du die Struktur kennst, in dem Deine Menüstruktur im EEProm 
abgelegt ist, kannst Du es auslesen.

Der jeweils aktuelle Menüpunkt wird dabei in den RAM gelesen. Eine 
Gesamtabbildung im RAM dürfte in den meisten Fällen zu Speicherproblemen 
führen.

Gruß
Frank

von Sven S. (schwerminator)


Lesenswert?

Hallo Frank,
ich habe bis jetzt tinymenu 
(http://www.avrfreaks.net/index.php?module=Freaks%20Academy&func=viewItem&item_id=249&item_type=project) 
verwendet. Das System funktioniert auch sehr gut, hat aber eben zwei 
entscheidene Nachteile:

1. Die Daten werden im SRAM abgelegt, nicht im PRGMEM. Das ist nicht 
allzu tragisch, weil ich viel Speicher habe (4k) und mein Menü nicht 
allzu groß wird.
2. Die Daten sind statisch in structs abgelegt. Ich weiß nicht, wie ich 
das modifizieren soll, weil ich bei Pointern, Structs und Arrays in 
Kombination einfach noch nicht so geübt bin.

Hier sind die Typedefinitions:
1
// So sieht ein (Sub-)Menu aus:
2
typedef struct menu_s {
3
  uint8_t top_entry;        //  top displayed entry
4
  uint8_t current_entry;    // currently highlighted entry
5
  uint8_t num_entries;      //  total # of entries in menu
6
  struct menu_s *previous; // previous menu (for backtracking)
7
  menu_entry_t entry[];
8
} menu_t;
9
10
// Und so ein Eintrag (entry)
11
typedef struct menu_entry_s {
12
  uint8_t flags;                             // see flag definitions above
13
  void (*select)(void *arg, char *name);  // routine to call when selected
14
  char name[MENU_ENTRY_NAMELEN];            // name to display for this entry
15
  void *value;                              // value to pass to select function
16
} menu_entry_t;

Kann man das Ganze überhaupt nach meinen Bedürfnissen umstricken, oder 
muss man sich über ein neues Konzept Gedanken machen?

Ich freue mich auf konstruktive Vorschläge. Gruß, Sven

von Frank L. (franklink)


Lesenswert?

Hallo Sven,
dazu müsste ich ein wenig mehr wissen.

1. Liegen in Deinem EEProm nur die reinen Menüinformationen also Texte 
Vorgänger, Nachfolger usw.? Wie erfolgt die Abildung im EEprom?

2. Wo liegen die Nutzerroutinen, die aus dem Menüsystem heraus 
angesprungen werden? Wie soll die Zuordnung von Menüeintrag zu 
Nutzerroutine erfolgen?

3. Warum liegen die Menüdaten überhaupt in einem externen EEProm?

4. Ist mit externen EEProm tatsächlich ein Baustein gemeint der nicht im 
Mikrocontroller steckt?

Grundsätzlich kannst Du jede Struktur im Speicher anlegen bzw. 
erweitern. An Stelle eines Arrays kannst Du z.B. verkettete Listen 
nehmen und diese über Dein EEProm initialisieren.

Ich arbeite zur Zeit an einem Konzept um Menü- und Dialogstrukturen auf 
einem LCD abbilden zu können. Allerdings basiert das auf einer 
Array-Struktur, indem das Menüsystem komplett über PROGMEM abgebildet 
wird. Für Dich also in dieser Form nicht geeignet.

Gruß
Frank

von Sven S. (schwerminator)


Lesenswert?

Hi Frank,
ich merke schon, ich muss ein wenig weiter ausholen: Das Ganze wird eine 
Art Universalfernbedienung, bei der die Befehle editierbar bleiben 
sollen. Deshalb liegen sowohl Daten- (2), Kontroll- (1) als auch 
Textbytes (15) im externen EEPROM (24LC64). Nun habe ich mir 
vorgestellt, dass sobald ich im Menü auf den Punkt "Send Command" gehe, 
die entsprechenden Befehle aus dem EEPROM geladen werden und die Texte 
auf dem Display dargestellt werden. Ein Teil des Menüs kann also 
weiterhin fest im ROM liegen, aber ein Teil soll eben immer dynamisch 
aus dem EEPROM geladen werden.
Im Kontrollbyte eines jeden 18-Byte langen Befehl steht drin, für 
welches Gerät er gedacht wird, wodurch dann eine entsprechende Funktion 
mit den Datenbytes als Parameter aufgerufen wird. Die Einträge müssen im 
Menu nicht besonders geordnet werden. Ich hoffe mein Anliegen ist etwas 
klarer geworden...

mfG, Sven

von Frank L. (franklink)


Lesenswert?

Hallo Sven,
das heisst, Du willst für verschiedene Fernbedienungen die Codes im 
EEPROM speichern und bei Bedarf entsprechend aus dem EEPROM laden und 
verwenden. Ist das richtig?

Da die Fernebdienung aber immer nur einen Code ausführen kann, ist es 
doch aus meiner Sicht gar nicht notwendig mehr als ein Kommando im 
Speicher zu halten. Oder sehe ich das falsch?

Ich arbeite bei meinem LCD-Menü auschließlich mit PROGMEM. Wird ein Menü 
angezeigt, lade ich die notwendigen Informationen aus dem PROGMEm in den 
RAM. Dabei hole ich mir immer nur die aktuell notwendigen Information 
und kopiere sie in einen Zwischenbereich der die Darstellung auf dem 
Display übernimmt.

Du stellst vorher einmal ein, wie das Display aufgeteilt ist Anzahl 
Menüspalten und Anzahl Menüzeilen im Display. Dem entsprechend 
initialisiere ich durch den Compiler und Defines meine Struktur.

Alles andere passiert ausschliesslich durch direktes lesen aus PROGMEM.

Die gleiche Vorgehensweise kannst Du auch für Dein EEPROM verwenden.

Wenn ich es richtig verstanden habe, wählst Du aus welche Fernbedienung 
Du benutzen möchtest (TV, TUNER, ... ), dann betätigst Du eine Taste. 
Der Controller schaut an Hand der eingestellten Fernbedineung und dem 
Tastendruck in der im EEPROM gespeicherten Tabelle nach welches Kommando 
und welcher Text dazu gehört. Kopiert diese in das RAM und führt das 
ganze aus (also Text auf Display und SendCMD).

Damit benötigst Du lediglich eine Lookuptabelle für die verschiedenen 
Fernbdienungen und eine Tabelle mit den ganzen Befehlen pro 
Fernbedienung
Korrigiere mich wenn ich falsch liege. In der Lookuptabelle für die 
Fernbedienungen legst Du jeweils den Anfang und das Ende des Bereichs 
innerhalb der Befehlstabelle fest der für die gewählte Fernbedienung 
gültig ist. Wenn jetzt eine Taste gedrückt wird, kann sich der 
Controller aus der Fernbedienungstabelle das Offset für den Beginn der 
Befehlstabelle für diese eine Fernbedienung holen, hat er dieses Offset 
kann er in der Befehlstabelle das entsprechende Kommando für die 
gedrückte Taste holen. Kopier diesen Ausschnitt aus dem EEPROM in das 
RAM und Du hast alle Daten die Du benötigst um das eine Kommando 
auszuführen.

Gruß
Frank

von Sven S. (schwerminator)


Lesenswert?

Hi Frank,
ich glaube nun sind wir uns in den Grundzügen einig, nur dass wenn man 
auf Tuner oder TV klickt, ein Submenü geöffnet wird, das aus den Texten 
der einzelnen "Tasten" besteht. Also muss beim Klick auf TV bzw. Tuner 
das Laden der Texte aus dem EEPROM beginnen.
1
Ich arbeite bei meinem LCD-Menü auschließlich mit PROGMEM. Wird ein Menü
2
angezeigt, lade ich die notwendigen Informationen aus dem PROGMEm in den
3
RAM. Dabei hole ich mir immer nur die aktuell notwendigen Information
4
und kopiere sie in einen Zwischenbereich der die Darstellung auf dem
5
Display übernimmt.
6
7
Du stellst vorher einmal ein, wie das Display aufgeteilt ist Anzahl
8
Menüspalten und Anzahl Menüzeilen im Display. Dem entsprechend
9
initialisiere ich durch den Compiler und Defines meine Struktur.
10
11
Alles andere passiert ausschliesslich durch direktes lesen aus PROGMEM.
12
13
Die gleiche Vorgehensweise kannst Du auch für Dein EEPROM verwenden.

Würdest du mir für diese Prozesse den Code zur Verfügung stellen, sodass 
ich ihn für den EEPROM-Gebrauch umbauen kann?

von Frank L. (franklink)


Lesenswert?

Hallo Sven,
klar, schicke ich Dir nachher per Mail.

Gruß
Frank

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.