olby2
15.08.2008, 10:58
Hallo Leute,
ich wollte den Code aus dem Roboternetz / Wissen mal auf eine fünfte oder auch sechste Taste erweitern, doch bisher ohne Erfolg.
'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
ich wollte den Code aus dem Roboternetz / Wissen mal auf eine fünfte oder auch sechste Taste erweitern, doch bisher ohne Erfolg.
'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