Hallo biete hier mein Universal-menü
Menueeinträge und Untermenües sowie sprungmarken werden einfach ganz unten in die data zeile eingetragen.
Das prog baut dann selbständig ein 4 Zeilen menüe zusammen

das menue ist per Tastatur zu steuern (RS232 terminal) und kann auch simuliert werden
bei simulation die anweisung $sim noch ganz oben reinschreiben und neu kompilieren

einfach mal die kommentare durchlesen

Code:
$regfile = "m16def.dat"                                     ' specify the used micro
$crystal = 16000000                                         ' used crystal frequency
$baud = 9600                                                ' use baud rate
$hwstack = 32                                               ' default use 32 for the hardware stack
$swstack = 32                                               ' default use 10 for the SW stack
$framesize = 64                                             ' default use 40 for the frame space
Const Anzahl_eintrage_menu_ebene_01 = 10

Dim Menuepunkt As Byte
Dim Menuepunkt_intern As Byte
Dim Menuerichtung As Byte                                   'je nach richtung 1=hoch,2=runter,3=rechts,4=link
Dim Inkey_byte As Byte
Dim Inkey_string As String * 1
Dim Menue_aktion As Byte
Dim Menue_eintrag As String * 20
Dim Zeichen As String * 3
Dim Such_string As String * 3
Dim Faktor As Byte
Menuepunkt = 2


Declare Function Typ_von_untermenu(byref Menue_eintrag_tvu As Byte)as Byte
Declare Function Linkes_zeichen(byref Menue_punkt_lz As Byte)as String

Lcd_db4 Alias Portc.4
Lcd_db5 Alias Portc.5
Lcd_db6 Alias Portc.6
Lcd_db7 Alias Portc.7
Lcd_e Alias Portb.0
Lcd_rs Alias Portb.1

Config Lcd_db4 = Output
Config Lcd_db5 = Output
Config Lcd_db6 = Output
Config Lcd_db7 = Output
Config Lcd_e = Output
Config Lcd_rs = Output

Config Lcdpin = Pin , Db4 = Lcd_db4 , Db5 = Lcd_db5 , Db6 = Lcd_db6 , Db7 = Lcd_db7 , E = Lcd_e , Rs = Lcd_rs
Config Lcd = 20 * 4a , Chipset = Ks077
Initlcd

Waitms 500
Cls
Locate 1 , 1
Lcd "System gestartet"
Wait 5
Menuerichtung = 1
Gosub Lcd_update

Do
   Inkey_byte = Inkey()                                     'Taste aus RS232 buffer
   If Inkey_byte > 48 Then                                  'wenn taste grösser als zahl 0
      If Inkey_byte < 60 Then                               'und kleiner als 5
         Inkey_string = Chr(inkey_byte)                     'byte in string wandeln
         If Inkey_string = "8" Then Menuerichtung = 1
         If Inkey_string = "2" Then Menuerichtung = 2
         If Inkey_string = "4" Then Menuerichtung = 4
         If Inkey_string = "6" Then Menuerichtung = 3
         Gosub Lcd_update
      End If
   End If
Loop

End

Lcd_update:
   Menue_aktion = Typ_von_untermenu(menuepunkt)
   If Menue_aktion > 0 Then                                 'wenn untermenu ereigniss ist
      If Menuerichtung = 3 Then                             'und Taste rechts gedrückt wurde
         Waitms 5
         Cls
         Waitms 5
         Locate 1 , 1
         Lcd "Ereigniss:" ; Menue_aktion
         Waitms 5
         Return
      End If
   End If

   Cls
   Menuepunkt_intern = Menuepunkt
   Gosub Hole_menuepunkt
   Menuepunkt = Menuepunkt_intern

   Menuerichtung = 4
   Gosub Hole_menuepunkt
   If Menuepunkt_intern = 2 Then
      If Menuepunkt < Anzahl_eintrage_menu_ebene_01 Then
          Menue_eintrag = "Hauptmenue"
      Else
          Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
      End If
   Else
      Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
   End If
   Faktor = Len(menue_eintrag)
   Faktor = 20 - Faktor
   Faktor = Faktor / 2
   Locate 1 , Faktor
   Waitms 5
   Lcd Menue_eintrag
   Waitms 5
   Locate 2 , 1
   Waitms 5
   Menuepunkt_intern = Menuepunkt
   Menuerichtung = 1
   Gosub Hole_menuepunkt
   Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
   Lcd Menue_eintrag
   Waitms 5
   Locate 3 , 1
   Waitms 5
   Menuepunkt_intern = Menuepunkt
   Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
   Faktor = Len(menue_eintrag)
   If Faktor < 18 Then
      Menue_eintrag = "-> " + Menue_eintrag
   End If
   Lcd Menue_eintrag
   Waitms 5
   Locate 4 , 1
   Waitms 5
   Menuepunkt_intern = Menuepunkt
   Menuerichtung = 2
   Gosub Hole_menuepunkt
   Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
   Lcd Menue_eintrag
   Waitms 208
Return


Hole_menuepunkt:                                            'aktualisiert die variable menuepunkt_intern
   If Menuerichtung = 1 Then                                'Taste Menue hoch
      Menuepunkt_intern = Menuepunkt_intern - 2
      If Linkes_zeichen(menuepunkt_intern) = "#"then        'dann letzten Eintrag suchen,da menuebenenanfang erreicht
         Do
            Menuepunkt_intern = Menuepunkt_intern + 2
            Zeichen = Linkes_zeichen(menuepunkt_intern)
         Loop Until Zeichen = "#"                           'es wird vorwärts gesucht bis die nächste Menueebene beginnt
         Menuepunkt_intern = Menuepunkt_intern - 2          'dann zwei Einträge zurück
      End If
   Elseif Menuerichtung = 2 Then                            'Taste Menue runter
      Menuepunkt_intern = Menuepunkt_intern + 2
      If Linkes_zeichen(menuepunkt_intern) = "#"then        'wenn der Anfang der nächsten Ebene erreicht ist
         Do
            Menuepunkt_intern = Menuepunkt_intern - 2       'wird rückwärts gesucht
            Zeichen = Linkes_zeichen(menuepunkt_intern)
         Loop Until Zeichen = "#"                           'bis der Anfang dieser Menueebene gefunden ist
         Menuepunkt_intern = Menuepunkt_intern + 2          'dann ist der erste Eintrag 2 Schritte vorwärts
      End If
   Elseif Menuerichtung = 3 Then                            'wenn Taste rechts (Sprung in Unterebene)
      Menuepunkt_intern = Menuepunkt_intern + 1             'dann wird zum nächsten Eintrag gegangen (Sprungmarke)
      Such_string = Lookupstr(menuepunkt_intern , Menue)
      Such_string = "#" + Such_string                       'diesem Eintrag wird eine Raute vorangestellt
      Menuepunkt_intern = 0
      Do                                                    'und nach ihm vom ersten menueindex an gesucht
         Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
         Menuepunkt_intern = Menuepunkt_intern + 2
      Loop Until Menue_eintrag = Such_string                'wenn gefunden ist man in der richtigen Menueebene
   Elseif Menuerichtung = 4 Then                            'Taste links (Obermenu)
      Do
         Menuepunkt_intern = Menuepunkt_intern - 2          'wird rückwärts gesucht
         Zeichen = Linkes_zeichen(menuepunkt_intern)
      Loop Until Zeichen = "#"                              'bis Anfang gefunden
      Menuepunkt_intern = Menuepunkt_intern + 1             'dann um 1 erhöht
      Such_string = Lookupstr(menuepunkt_intern , Menue)
      Zeichen = Right(such_string , 1)                      'das 1.Zeichen von rechts wird gelesen
      Faktor = Val(zeichen)                                 'und in einen Faktor
      Faktor = Faktor * 2                                   'umgewandelt
      Such_string = Left(such_string , 2)                   'danach die zwei Zeichen von links
      Such_string = "#" + Such_string                       'mit Raute davor ergeben die Rücksprungebene
      Menuepunkt_intern = 0
      Do                                                    'es wird nach Rücksprungebene gesucht angefangen beim Index 0
         Menue_eintrag = Lookupstr(menuepunkt_intern , Menue)
         Menuepunkt_intern = Menuepunkt_intern + 2
      Loop Until Menue_eintrag = Such_string                'wenn gefunden
      Menuepunkt_intern = Menuepunkt_intern - 2             'werden die 2 die oben aufaddiert wieder abgezogen
      Menuepunkt_intern = Menuepunkt_intern + Faktor        'und um den Faktor nach vorn gesprungen
   End If
Return


Function Typ_von_untermenu(byref Menue_eintrag_tvu As Byte)as Byte       'schaut nach ob der übergebene menuepunkt auf ein ereigniss verweist
   Local Menue_eintrag_text_tvu As String * 20
   Local Menuepunkt_intern_tvu As Byte
   Local Ereigniss_nummer_text_tvu As String * 2
   Local Ereigniss_nummer_tvu As Byte
   Menuepunkt_intern_tvu = Menue_eintrag_tvu
   Menuepunkt_intern_tvu = Menuepunkt_intern_tvu + 1
   Menue_eintrag_text_tvu = Lookupstr(menuepunkt_intern_tvu , Menue)
   If Linkes_zeichen(menuepunkt_intern_tvu) = "!"then
      Ereigniss_nummer_text_tvu = Right(menue_eintrag_text_tvu , 2)
      Ereigniss_nummer_tvu = Val(ereigniss_nummer_text_tvu)
   Else
      Ereigniss_nummer_tvu = 0
   End If
   Typ_von_untermenu = Ereigniss_nummer_tvu
End Function


Function Linkes_zeichen(byref Menue_punkt_lz As Byte)as String       'gibt das erste Zeichen eines Menueeintrags zurück
   Local Menue_eintrag_text_lz As String * 20
   Local Zeichen_lz As String * 1
   Local Menuepunkt_intern_lz As Byte
   Menuepunkt_intern_lz = Menue_punkt_lz
   Menue_eintrag_text_lz = Lookupstr(menuepunkt_intern_lz , Menue)
   Zeichen_lz = Left(menue_eintrag_text_lz , 1)
   Linkes_zeichen = Zeichen_lz
End Function







' hinter der #  steht die Menueebene dahinter steht die Rücksprungadresse (Taste links) für diese Menueebene
' zB wird aus einem Eintrag der Ebene #04 (zB Abstand) in die Ebene #03 Eintrag 1 gesprungen (031)
' in diesem fall nach eingänge und von dort gehts zurück in ebene 1 eintrag 2 (012) das wäre dann "Tests"
' nach der Rücksprungadresse folgt der erste Menuepunt (max 20 Zeichen)und danach dessen Vorprung Adresse (Taste nach rechts)
' zB hinter "Einstellungen" steht 07 also verzweigt das Menue von dort in die Unterebene #07
' falls aus einem Menuepunkt nicht weiter in ein Untermenue gesprungen werden soll sondern ein bestimmdes Ereigniss stattfinden soll
' dann kommt als Vorsprungadresse (die Zahl hinter dem Eintrag) ein ! und eine Zahl von 1-99
' diese Zahl wird dann in der variable Ereigniss zurueckgegeben
' zB wenn man im Menuepunkt "Akku Laden" die Menue-vor Taste (Taste rechts) drückt wird der wert 02 zurueckgegeben dieser kann dann ausgewertet werden
' das Menue kann beliebig erweitert oder verändert werden.es ist nur das Format einzuhalten.

Menue:
Data "#01" , "011" , "Modus" , "02" , "Test" , "03" , "Einstellungen" , "07" , "Akku laden" , "!02"
Data "#02" , "011" , "Autonom" , "!03" , "Erkunden" , "!04" , "Manuell RC" , "!05" , "Manuell-Stick" , "!06"
Data "#03" , "012" , "Eingaenge" , "04" , "Ausgaenge" , "05"
Data "#04" , "031" , "Kollision" , "!07" , "Abstand" , "!08" , "Richtung" , "!09" , "Spannung" , "!10" , "Encoder" , "!77"
Data "#05" , "032" , "Antrieb" , "!11" , "Servos" , "06" , "Walze" , "!12" , "Lenkung" , "!13",
Data "#06" , "052" , "Servo links" , "!14" , "Servo rechts" , "!15"
Data "#07" , "013" , "Uhrzeit" , "08" , "Offset" , "!16"
Data "#08" , "071" , "Stunden" , "!17" , "Minuten" , "!18" , "Jahr" , "!19" , "Monat" , "!20"
Data "#EO"                                                  'muß am ende stehen damit das Ende der vorigen Ebene erkannt wird