-
        

Ergebnis 1 bis 4 von 4

Thema: State Machine aus Beispiel mit 5 Tasten

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    06.04.2008
    Beiträge
    18

    State Machine aus Beispiel mit 5 Tasten

    Anzeige

    Hallo Leute,

    ich wollte den Code aus dem Roboternetz / Wissen mal auf eine fünfte oder auch sechste Taste erweitern, doch bisher ohne Erfolg.

    Code:
    'Beispiel für ein State Machine Menü
    'Das Beispiel ist für den BASCOM-Simulator angepasst worden
    '  getestet mit Bascom 1.11.9.1
    '  Codelänge 2242 Byte
    
    $regfile = "m32def.dat"
    $framesize = 32                                             'Stack
    $swstack = 32
    $hwstack = 64
    $sim
    '
    'Hinweis: Im Simulator müssen die Eingaben in dem blauen "Terminal Emulator Window" erfolgen!
    'Auf der Tastatur ergeben sich für die VIER Joystick-Positionen folgende Umsetzungen
    '
    '              [Key_plus ]
    ' [Key_prev]   [         ]    [Key_next]
    '              [Key_minus]
    '
    '
    '              [ Taste_8 ]
    ' [Taste_4 ]   [         ]    [Taste_6 ]
    '              [ Taste_2 ]
    '
    'bzw. im ASCII-Code:
    
    Dim Keycode_string As String * 5  ' im Orginal 4
    'Key_plus|Key_minus|Key_prev|Key_next| Return
    Keycode_string = "{056}{050}{052}{054}{051}"   ' org fehlt {051}
    Dim Keycode(5) As Byte At Keycode_string Overlay  ' org (4) 
    Const Key_null = 0                                          'keine Taste gedrückt
    
    'Pins des LCD-Modules setzen ggf. an eigene Anschlüsse anpassen
    Config Lcd = 20 * 4
    Initlcd
    Cls
    
    '******** Joystick/Key Settings ***********************************************
    Dim Key As Byte                                             'key in Mainloop
    
    '******** LCD *****************************************************************
    Dim Lcd_textbuffer As String * 25
    
    '******** allg Variablen ******************************************************
    Dim I As Byte , J As Byte
    Dim W As Word
    
    '********* State Variables ****************************************************
    Dim State As Word                                           'aktueller State
    Dim State_renew As Byte                                     'Flag
    Dim State_gosub As Word                                     'aktuelles Unterprogramm
    
    'Initial state variables
    State_renew = 1
    State = Loadlabel(s10)                                      'Startbildschirm LADEN in dem Fall Stateview
    Key = Key_null                                              'keine Taste gedrückt
    
    
    '********** MAIN-Loop *********************************************************
    Do
        'Menüeintrag und Tastencodes finden und ggf. State wechseln
        'hier nur Tastendruck auswerten
        Gosub Change_state                                      '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        'Pointer nach Statuswechsel neu setzen
        If State_renew = 1 Then Gosub Change_state
    
        'Unterprogramm des aktuellen State anspringen
        LDS R31, {State_gosub+1}                                'High see Bascom-Doc Mixing ASM and BASIC
        LDS R30, {State_gosub}                                  'Low
        LSR R31                                                 'Division durch 2 (Alternativ ADR verwenden)
        ROR R30
        'Call zum Sub
        ICALL
    
    
       '---------------------------------------------------------------
       'place for your own code in main loop
       '---------------------------------------------------------------
    
       'LCD refresh wenn Menü verändert
       If State_renew = 1 Then
          State_renew = 0
          Gosub Lcd_print
       End If
    
       'Tastaturabfrage mit Halt nur für Simulator, ansonsten Sleep+Timer_ISR verwenden!!
        Key = Waitkey()
    
     Loop
    End
    
    '********* State routines ***************************************************
    '---------------------------------------------------------------
    'Subroutine: Change_state
    'Call from:  main loop
    'Purpose:    Status der State Machine feststellen und ggf. Wechseln
    'Result:     Pointer auf State / Variable State_renew
    '---------------------------------------------------------------
    Change_state:
        lds R8, {State}
        lds R9, {State + 1}
        For I = 1 To 5                        '  org 4
          Read W
          If Key = Keycode(i) Then
               If W <> Loadlabel(null) Then
                  State_renew = 1
                  Key = Key_null                                'reset key status after get a new state of state machine (prevent influence on GOSUBs)
                  State = W
               End If
          End If
        Next I
        Read State_gosub                                        'Adresse des akt. Unterprogramms einlesen
        Read Lcd_textbuffer                                     'read LCD text
    Return
    
    '---------------------------------------------------------------
    'Subroutine: Change_state_by_sub
    'Call from:  subroutine
    'Purpose:    change state of state machine by a subbroutine
    '---------------------------------------------------------------
    Change_state_by_sub:
       State_renew = 1
       Gosub Change_state
    Return
    
    '---------------------------------------------------------------
    'DATA:       State Machine
    'Result:     Pointers auf States , Unterprogramme
    '            Menütexte
    '---------------------------------------------------------------
    
    Null:
             'Null is a dummy flag for State and Gosub -> do nothing
             Return
    
    S10:
             Adr2 Null : Adr2 S11 : Adr2 Null : Adr2 S20 : Adr2 S20       'Key_plus|Key_minus|Key_prev|Key_next
             Adr2 Prog1wahl                                     'Subroutine for current State
             Data " "
                                'Menue Display Text
    
    S11:
             Adr2 S10 : Adr2 S12 : Adr2 Null : Adr2 Null : Adr2 S20       'Key_plus|Key_minus|Key_prev|Key_next
             Adr2 Prog2wahl
             Data " "
    
    S12:
             Adr2 S11 : Adr2 S13 : Adr2 Null : Adr2 Null : Adr2 S20
             Adr2 Prog3wahl
             Data " "
    
    S13:
             Adr2 S12 : Adr2 S14 : Adr2 Null : Adr2 S20 : Adr2 S20       'Key_plus|Key_minus|Key_prev|Key_next
             Adr2 Prog4wahl                                     'Subroutine for current State
             Data " "
                                'Menue Display Text
    
    S14:
             Adr2 S13 : Adr2 S15 : Adr2 Null : Adr2 Null : Adr2 S20       'Key_plus|Key_minus|Key_prev|Key_next
             Adr2 Prog5wahl
             Data " "
    
    S15:
             Adr2 S14 : Adr2 S16 : Adr2 Null : Adr2 Null : Adr2 S20
             Adr2 Prog6wahl
             Data " "
    
    S16:
             Adr2 S15 : Adr2 S17 : Adr2 Null : Adr2 S20 : Adr2 S20       'Key_plus|Key_minus|Key_prev|Key_next
             Adr2 Prog7wahl                                     'Subroutine for current State
             Data " "
                                'Menue Display Text
    
    S17:
             Adr2 S16 : Adr2 Null : Adr2 Null : Adr2 Null : Adr2 S20       'Key_plus|Key_minus|Key_prev|Key_next
             Adr2 Prog8wahl
             Data " "
    
    
    
    
    
    ''
    S20:
             Adr2 Null : Adr2 Null : Adr2 S10 : Adr2 Null
             Adr2 Menu1
             Data "Prog1"
    
    '********* LCD SUB routines ***************************************************
    '---------------------------------------------------------------
    'Subroutine: Lcd_print
    'Call from:  anywhere
    'Purpose:    gibt Lcd_textbuffer auf dem LCD-Display aus
    'Result:     LCD
    '---------------------------------------------------------------
    Prog1wahl:
      'Adjusts the Clock
        Lcd_textbuffer = "PUNKT1"
        Locate 1 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt2"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt3"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt4"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
      Return
    
    Prog2wahl:
      'Adjusts the Clock
        Lcd_textbuffer = "punkt1"
        Locate 1 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT2"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt3"
        Locate 3 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
    
      Return
    
    Prog3wahl:
      'Adjusts the Clock
    
        Lcd_textbuffer = "punkt2"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT3"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt4"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
      Return
    
    Prog4wahl:
      'Adjusts the Clock
    
        Lcd_textbuffer = "punkt3"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT4"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
      Return
    
    Prog5wahl:
      'Adjusts the Clock
        Lcd_textbuffer = "punkt2"
        Locate 1 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt3"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt4"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT5"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
    
      Return
    
    Prog6wahl:
      'Adjusts the Clock
        Lcd_textbuffer = "punkt3"
        Locate 1 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt4"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt5"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT6"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
    
      Return
    
    Prog7wahl:
      'Adjusts the Clock
        Lcd_textbuffer = "punkt4"
        Locate 1 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt5"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt6"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT7"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
    
      Return
    
      Prog8wahl:
      'Adjusts the Clock
        Lcd_textbuffer = "punkt5"
        Locate 1 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt6"
        Locate 2 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "punkt7"
        Locate 3 , 1
        Lcd Lcd_textbuffer
    
        Lcd_textbuffer = "PUNKT8"
        Locate 4 , 1
        Lcd Lcd_textbuffer
        State_renew = 0
    
      Return
    
    
    
    Lcd_print:                                                  'Print lcd_textbuffer
        Cls
        Lcd Lcd_textbuffer
        State_renew = 0
    Return
    
    
    Menu1:                                                      'Print lcd_textbuffer
        Cls
        Lcd Lcd_textbuffer
        State_renew = 0
    Return

    Ich habe wohl noch nicht ganz verstanden wie hier sehr clever und mit sehr wenig Aufwand die entsprechenden sub´s aufgerufen werden, wenn eine der Tasten betätigt wird.

    Kann mir jemand behilflich sein

    vielen dank
    olby2

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    28.03.2004
    Beiträge
    185
    Hallo olby2,

    worin besteht das Problem?
    Du musst beim Label S20 noch das Label für die fünfte Taste ergänzen, da sonst ICALL in die Leere führt.
    Code:
    S20:
             Adr2 Null : Adr2 Null : Adr2 S10 : Adr2 Null : Adr2 Null

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    06.04.2008
    Beiträge
    18

    State Machine aus Beispiel mit 5 Tasten

    Hallo Tomas,

    vielen dank für deine schnelle Antwort.

    Da habe ich wohl eine Zeile übersehen, in der noch eine Ergänzung notwendig war , vielen dank.

    Das Beispiel ist wohl für ein einzeiliges Display gemacht worden, wenn
    ich jetzt gleich mehlere Zeilen aus das Display bringen möchte ( a la Handymenu zum durchscrollen ) genügt es wohl nicht nur ein paar zusätzliche Data-Zeilen in die Tabelle zu bringen.

    Ich habe also eine Sub Aufgerufen, wo dann der entsprechende Inhalt aufs Display gebracht wird.

    Gibt es noch eine bessere, platzsparendere Möglichkeit ?

    vielen Dank für eure Hilfe

    cu
    olby2

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    28.03.2004
    Beiträge
    185
    wir hatten vor kurzen eine heftige Diskussion im Forum, in Folge dessen ich den State Machine Code mit ADR2 als Kompaktlösung entwickelt hatte:
    http://www.roboternetz.de/phpBB2/viewtopic.php?t=41890

    in dem Link in RNWissen findest Du weitere Ansätze... http://www.roboternetz.de/wissen/ind...e_Machine_Menu

    zur Frage:
    Ein mehrzeiliges Scrollmenü könnte man natürlich durch Aufbohren der DATA Zeilen erreichen und hier im Code ein paar Read LCD_Zeile_n ergänzen:
    Code:
        Read State_gosub                                        'Adresse des akt. Unterprogramms einlesen
        Read Lcd_textbuffer                                     'read LCD text
    Das ganze wäre uneffektiv, da alle Texte mehrfach auftauchen.
    Die bessere Lösung wäre hier, in der DATA Zeile nur die Nummer des Eintrages einer Texttabelle zu notieren und auf dem Display dann den Ausschnitt der Texttabelle darzustellen.
    Ähnlich der ersten Lösung in RNWissen.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •