(→Siehe auch) |
K (→Sample Code Variante 2: übersichtlich mit ADR2) |
||
| (14 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
| Zeile 1: | Zeile 1: | ||
== Bascom State Machine Menu == | == Bascom State Machine Menu == | ||
| − | Beim der Umsetzung des AVR Butterfly IAR-C | + | Beim der Umsetzung des Beispielcodes von Atmel für AVR Butterfly [[http://www.mikrocontroller.net/articles/AVR_Butterfly]] (in IAR-C bzw. die GCC-Portierung) nach Bascom [[http://www.roboternetz.de/phpBB2/viewtopic.php?t=23231]] entstand folgende hoch effiziente State Machine zur Umsetzung eines Menüs für einen Datalogger. |
| − | Der Code wurde stark reduziert, so dass | + | Der Code wurde hier stark reduziert, so dass vom gesamten Programm das Menü als Rahmen mit allen Unterprogrammen (leer) übrig geblieben ist. |
== Die Menü-Struktur == | == Die Menü-Struktur == | ||
| + | Als Beispiel wird hier die um die Umsetzung '''des Menüs aus dem AVR Butterfly Evaluation Kit in Bascom''' gezeigt: | ||
[[Bild:Butterflymenu.png]] | [[Bild:Butterflymenu.png]] | ||
| − | == Sample Code == | + | == Sample Code Variante 1: Umsetzung des Codes aus dem AVR Butterfly Evaluation Kit == |
| + | Der Code ist die 1:1 Umsetzung des C-Codes aus dem AVR Butterfly Evaluation Kit. | ||
Das Code-Beispiel wurde '''für den Bascom Simulator optimiert''' und kann dort direkt mit den Ziffern-Tasten bedient werden (NumLock!). | Das Code-Beispiel wurde '''für den Bascom Simulator optimiert''' und kann dort direkt mit den Ziffern-Tasten bedient werden (NumLock!). | ||
Auf dem Simulator-LCD-Display werden die Ebenen mit angezeigt (3 -> 31 -> 32 -> 321 etc.) | Auf dem Simulator-LCD-Display werden die Ebenen mit angezeigt (3 -> 31 -> 32 -> 321 etc.) | ||
| + | |||
| + | Getestet im Bascom-Simulator der Versionen: | ||
| + | * BASCOM 1.11.9.1 [OK] | ||
| + | * BASCOM 1.11.8.7 [Probleme mir der LCD Darstellung] | ||
| + | * BASCOM 1.11.8.1 [OK] | ||
| + | |||
| + | Die Codelänge des Samples beträgt ca. 2300Byte. Der größte Teil geht für die LCD-Anzeige, Anzeigetexte etc. drauf. Der State Machine selber ist sehr schlank, da nur Pointer (Zeiger) gesetzt werden. | ||
Weitere Erklärungen stehen im Quelltext. | Weitere Erklärungen stehen im Quelltext. | ||
| Zeile 560: | Zeile 569: | ||
</pre> | </pre> | ||
| + | |||
| + | == Sample Code Variante 2: übersichtlich mit ADR2 == | ||
| + | Die Variante 1 ist leider unübersichtlich, da 3 Tabellen getrennt geführt werden (die State Machine, die Menütexte und die zugehörigen Unterprogrammeinsprünge). | ||
| + | Nachfolgend eine Variante, in der nur eine Tabelle geführt wird. Die Lösung wurde möglich, nachdem in Bascom in der Version 1.11.8.9 den Befehl ADR / ADR2 eingeführt wurde. | ||
| + | |||
| + | In jedem Datensatz stehen jetzt die Daten für die Verzweigung der State Machine (inf. Tastatureingabe), der Pointer für den Unterprogrammeinsprung und der Menütext zusammen. | ||
| + | Die Codelänge das Beispiel liegt gleichauf mit der Variante 1. Dafür ist das Menü deutlich einfacher zu editieren. | ||
| + | |||
| + | Weitere Erklärungen stehen im Quelltext. | ||
| + | Die Bedienung erfolgt wie bei Variante 1. | ||
| + | |||
| + | Da jetzt zur Vereinfachung Nummern für die States geführt werden, empfiehlt es sich ein Plan (siehe Grafik oben) anzulegen und jeden Kasten mit einer Nummer zu versehen. Die Zuordnung der Status-Nummern entsprechend der Tasten-Verzweigung (UP/DOWN etc.) ist dann schnell abgelesen. Alternativ kann man natürlich beliebige Labelnamen verwenden. | ||
| + | |||
| + | Getestet im Bascom-Simulator der Versionen: | ||
| + | * BASCOM 1.11.9.1 [OK] | ||
| + | |||
| + | <pre>'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 2028 Byte | ||
| + | |||
| + | $regfile = "m8def.dat" | ||
| + | $framesize = 32 'Stack | ||
| + | $swstack = 32 | ||
| + | $hwstack = 64 | ||
| + | $sim 'empty wait loops - faster simulation - not for real world!! | ||
| + | |||
| + | ' | ||
| + | '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: | ||
| + | Const Key_buttons = 4 'Anzahl der Tasten | ||
| + | Dim Keycode_string As String * Key_buttons | ||
| + | 'Key_plus|Key_minus|Key_prev|Key_next | ||
| + | Keycode_string = "{056}{050}{052}{054}" 'see scan codes in ASCII chart | ||
| + | Dim Keycode(key_buttons) As Byte At Keycode_string Overlay | ||
| + | Const Key_null = 0 'keine Taste gedrückt | ||
| + | |||
| + | '******** LCD Settings *********************************************** | ||
| + | Dim Lcd_textbuffer As String * 25 | ||
| + | |||
| + | 'Pins des LCD-Modules setzen ggf. an eigene Anschlüsse anpassen | ||
| + | Config Lcd = 16 * 1 | ||
| + | Initlcd | ||
| + | Cls | ||
| + | |||
| + | '******** Joystick/Key Settings *********************************************** | ||
| + | Dim Key As Byte 'key in Mainloop | ||
| + | |||
| + | '********* 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 | ||
| + | Key = Key_null 'keine Taste gedrückt | ||
| + | |||
| + | '******** allg Variablen ****************************************************** | ||
| + | Dim I As Byte , J As Byte | ||
| + | Dim W As Word | ||
| + | |||
| + | '********** 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 Key_buttons | ||
| + | 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 | ||
| + | 'Format: 1. Zeile: für jede Taste genau eine Verzeigung ADR2 (see Key_buttons=xx) | ||
| + | ' 2. Zeile: Sprunglabel als ADR2 für ein ggf. anzuspringendes Unterprogramm | ||
| + | ' 3. Zeile: Displaytext des akt. Status als DATA Feld | ||
| + | 'Hinweis: wenn nichts passieren soll wird das Label NULL eingetragen | ||
| + | '--------------------------------------------------------------- | ||
| + | |||
| + | Null: | ||
| + | 'Null is a dummy flag for State and Gosub -> do nothing | ||
| + | Return | ||
| + | |||
| + | S10: | ||
| + | Adr2 Null : Adr2 S20 : Adr2 Null : Adr2 S11 'Key_plus|Key_minus|Key_prev|Key_next | ||
| + | Adr2 Null 'Subroutine for current State | ||
| + | Data "1 Butterfly Bascom" 'Menue Display Text | ||
| + | S11: | ||
| + | Adr2 Null : Adr2 Null : Adr2 S10 : Adr2 Null 'Key_plus|Key_minus|Key_prev|Key_next | ||
| + | Adr2 Null | ||
| + | Data "11 Rev 2" | ||
| + | S20: | ||
| + | Adr2 S10 : Adr2 S30 : Adr2 Null : Adr2 S21 | ||
| + | Adr2 Null | ||
| + | Data "2 Time" | ||
| + | S21: | ||
| + | Adr2 Null : Adr2 S22 : Adr2 S20 : Adr2 S23 | ||
| + | Adr2 Null | ||
| + | Data "21 Clock" | ||
| + | S22: | ||
| + | Adr2 S21 : Adr2 Null : Adr2 S20 : Adr2 S24 | ||
| + | Adr2 Null | ||
| + | Data "22 Date" | ||
| + | S23: 'Show HH:MM:SS | ||
| + | Adr2 Null : Adr2 S24 : Adr2 S21 : Adr2 S25 | ||
| + | Adr2 Showclock | ||
| + | Data "" | ||
| + | S24: 'Show DD:MM:YY | ||
| + | Adr2 S23 : Adr2 Null : Adr2 S22 : Adr2 S26 | ||
| + | Adr2 Showdate | ||
| + | Data "" | ||
| + | S25: | ||
| + | Adr2 S27 : Adr2 Null : Adr2 S23 : Adr2 S65 | ||
| + | Adr2 Null | ||
| + | Data "211 Adjust Clock" | ||
| + | S26: | ||
| + | Adr2 Null : Adr2 S28 : Adr2 S24 : Adr2 S66 | ||
| + | Adr2 Null | ||
| + | Data "221 Adjust Date" | ||
| + | S27: | ||
| + | Adr2 Null : Adr2 S25 : Adr2 S23 : Adr2 S67 | ||
| + | Adr2 Null | ||
| + | Data "212 Clock Format" | ||
| + | S28: | ||
| + | Adr2 S26 : Adr2 Null : Adr2 S23 : Adr2 S68 | ||
| + | Adr2 Null | ||
| + | Data "222 Date Format" | ||
| + | S30: | ||
| + | Adr2 S20 : Adr2 S40 : Adr2 Null : Adr2 S31 | ||
| + | Adr2 Null | ||
| + | Data "3 DataLogger" | ||
| + | S31: | ||
| + | Adr2 Null : Adr2 S32 : Adr2 S30 : Adr2 S35 | ||
| + | Adr2 Null | ||
| + | Data "31 Log Cycle" | ||
| + | S32: | ||
| + | Adr2 S31 : Adr2 S33 : Adr2 S30 : Adr2 S36 | ||
| + | Adr2 Null | ||
| + | Data "32 Delete Flash" | ||
| + | S33: | ||
| + | Adr2 S32 : Adr2 S34 : Adr2 S30 : Adr2 S37 | ||
| + | Adr2 Null | ||
| + | Data "33 Show LogCount" | ||
| + | S34: | ||
| + | Adr2 S33 : Adr2 Null : Adr2 S30 : Adr2 S38 | ||
| + | Adr2 Null | ||
| + | Data "34 Print to RS232" | ||
| + | S35: 'HH:MM | ||
| + | Adr2 Null : Adr2 Null : Adr2 S31 : Adr2 Null | ||
| + | Adr2 Datalogger_setloginterval | ||
| + | Data "" | ||
| + | S36: | ||
| + | Adr2 Null : Adr2 Null : Adr2 S32 : Adr2 S76 | ||
| + | Adr2 Null | ||
| + | Data "321 RIGHT Delete DF" | ||
| + | S37: '1234 | ||
| + | Adr2 Null : Adr2 Null : Adr2 S33 : Adr2 Null | ||
| + | Adr2 Datalogger_logcount | ||
| + | Data "" | ||
| + | S38: | ||
| + | Adr2 Null : Adr2 Null : Adr2 S34 : Adr2 S78 | ||
| + | Adr2 Null | ||
| + | Data "341 RIGHT Print9600B" | ||
| + | S40: | ||
| + | Adr2 S30 : Adr2 S50 : Adr2 Null : Adr2 S41 | ||
| + | Adr2 Null | ||
| + | Data "4 ADC" | ||
| + | S41: | ||
| + | Adr2 Null : Adr2 S42 : Adr2 S40 : Adr2 S45 | ||
| + | Adr2 Null | ||
| + | Data "41 Temperature" | ||
| + | S42: | ||
| + | Adr2 S41 : Adr2 S43 : Adr2 S40 : Adr2 S46 | ||
| + | Adr2 Null | ||
| + | Data "42 Voltage" | ||
| + | S43: | ||
| + | Adr2 S42 : Adr2 S44 : Adr2 S40 : Adr2 S47 | ||
| + | Adr2 Null | ||
| + | Data "43 ADC Port RAW" | ||
| + | S44: | ||
| + | Adr2 S43 : Adr2 Null : Adr2 S40 : Adr2 S48 | ||
| + | Adr2 Null | ||
| + | Data "44 Battery" | ||
| + | S45: '+24°C | ||
| + | Adr2 Null : Adr2 Null : Adr2 S41 : Adr2 Null | ||
| + | Adr2 Temperaturefunc | ||
| + | Data "" | ||
| + | S46: '0 mV | ||
| + | Adr2 Null : Adr2 Null : Adr2 S42 : Adr2 Null | ||
| + | Adr2 Voltagefunc | ||
| + | Data "" | ||
| + | S47: 'CH:RAW | ||
| + | Adr2 Null : Adr2 Null : Adr2 S43 : Adr2 Null | ||
| + | Adr2 Adc_raw_func | ||
| + | Data "" | ||
| + | S48: '2900mV | ||
| + | Adr2 Null : Adr2 Null : Adr2 S44 : Adr2 Null | ||
| + | Adr2 Adc_batt_func | ||
| + | Data "" | ||
| + | S50: | ||
| + | Adr2 S40 : Adr2 Null : Adr2 Null : Adr2 S51 | ||
| + | Adr2 Null | ||
| + | Data "5 Options" | ||
| + | |||
| + | S51: | ||
| + | Adr2 Null : Adr2 S52 : Adr2 S50 : Adr2 S56 | ||
| + | Adr2 Null | ||
| + | Data "51 LCD contrast" | ||
| + | S52: | ||
| + | Adr2 S51 : Adr2 S53 : Adr2 S50 : Adr2 S57 | ||
| + | Adr2 Null | ||
| + | Data "52 Bootloader" | ||
| + | |||
| + | S53: | ||
| + | Adr2 S52 : Adr2 S54 : Adr2 S50 : Adr2 S83 | ||
| + | Adr2 Null | ||
| + | Data "53 LCD OFF" | ||
| + | |||
| + | S54: | ||
| + | Adr2 S53 : Adr2 S55 : Adr2 S50 : Adr2 S58 | ||
| + | Adr2 Null | ||
| + | Data "54 LCD Auto Power" | ||
| + | |||
| + | S55: | ||
| + | Adr2 S54 : Adr2 Null : Adr2 S50 : Adr2 S59 | ||
| + | Adr2 Null | ||
| + | Data "55 Key Click" | ||
| + | S56: '0...15 | ||
| + | Adr2 Null : Adr2 Null : Adr2 S51 : Adr2 Null | ||
| + | Adr2 Setcontrast | ||
| + | Data "" | ||
| + | S57: | ||
| + | Adr2 Null : Adr2 Null : Adr2 S52 : Adr2 S87 | ||
| + | Adr2 Null | ||
| + | Data "521 RIGHT bootloader" | ||
| + | |||
| + | S58: 'OFF/5..90min | ||
| + | Adr2 Null : Adr2 Null : Adr2 S54 : Adr2 Null | ||
| + | Adr2 Autopower | ||
| + | Data "" | ||
| + | S59: 'ON/OFF | ||
| + | Adr2 Null : Adr2 Null : Adr2 S55 : Adr2 Null | ||
| + | Adr2 Keyclick_set | ||
| + | Data "" | ||
| + | 'Untermenüs zu State 25 bis 28 | ||
| + | S65: 'sub for "211 Adjust Clock" | ||
| + | Adr2 S67 : Adr2 Null : Adr2 S23 : Adr2 Null | ||
| + | Adr2 Setclock | ||
| + | Data "" | ||
| + | S66: 'sub for "221 Adjust Date" | ||
| + | Adr2 Null : Adr2 S68 : Adr2 S24 : Adr2 Null | ||
| + | Adr2 Setdate | ||
| + | Data "" | ||
| + | S67: 'sub for "212 Clock Format" | ||
| + | Adr2 Null : Adr2 S65 : Adr2 S23 : Adr2 Null | ||
| + | Adr2 Setclockformat | ||
| + | Data "" | ||
| + | S68: 'sub for "222 Date Format" | ||
| + | Adr2 S66 : Adr2 Null : Adr2 S24 : Adr2 Null | ||
| + | Adr2 Setdateformat | ||
| + | Data "" | ||
| + | 'Untermenüs zu State 36 und 38 | ||
| + | S76: 'sub for "321 RIGHT Delete DF" | ||
| + | Adr2 Null : Adr2 Null : Adr2 S36 : Adr2 Null | ||
| + | Adr2 Datalogger_erase | ||
| + | Data "" | ||
| + | S78: 'sub for "341 RIGHT Print9600B" | ||
| + | Adr2 Null : Adr2 Null : Adr2 S38 : Adr2 Null | ||
| + | Adr2 Datalogger_rs232 | ||
| + | Data "" | ||
| + | 'Untermenü zu State 53 und 57 | ||
| + | S83: 'sub for "53 LCD OFF" | ||
| + | Adr2 Null : Adr2 Null : Adr2 S53 : Adr2 Null | ||
| + | Adr2 Power_off_func | ||
| + | Data "" | ||
| + | S87: 'sub for "521 RIGHT bootloader" | ||
| + | Adr2 Null : Adr2 Null : Adr2 S57 : Adr2 Null | ||
| + | Adr2 Bootfunc | ||
| + | Data "" | ||
| + | |||
| + | |||
| + | '********* LCD SUB routines *************************************************** | ||
| + | '--------------------------------------------------------------- | ||
| + | 'Subroutine: Lcd_print | ||
| + | 'Call from: anywhere | ||
| + | 'Purpose: gibt Lcd_textbuffer auf dem LCD-Display aus | ||
| + | 'Result: LCD | ||
| + | '--------------------------------------------------------------- | ||
| + | Lcd_print: 'Print lcd_textbuffer | ||
| + | Cls | ||
| + | Lcd Lcd_textbuffer | ||
| + | State_renew = 0 | ||
| + | Return | ||
| + | |||
| + | '********* SUB Clock routines************************************************** | ||
| + | Showclock: | ||
| + | 'Show the clock on the LCD | ||
| + | Lcd_textbuffer = "HH:MM:SS" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Setclock: | ||
| + | 'Adjusts the Clock | ||
| + | Lcd_textbuffer = "HH=11" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Setclockformat: | ||
| + | 'Adjusts the Clockformat (12H or 24H) | ||
| + | Lcd_textbuffer = "12H / 24H" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | '********* SUB date routines ************************************************** | ||
| + | Showdate: | ||
| + | 'Show the date on the LCD | ||
| + | Lcd_textbuffer = "DD.MM.YY" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Setdate: | ||
| + | 'Adjusts the Date | ||
| + | Lcd_textbuffer = "Month=12" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | '--------------------------------------------------------------- | ||
| + | Setdateformat: | ||
| + | 'Adjusts the Dateformat "DDMMYY" , "MMDDYY" , "YYMMDD" | ||
| + | Lcd_textbuffer = "DDMMYY/YYMMDD" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | '********* Datalogger routines ************************************************ | ||
| + | Datalogger_setloginterval: | ||
| + | 'set the datalog intervall HOUR:MINUTES | ||
| + | Lcd_textbuffer = "HH:MM" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Datalogger_erase: | ||
| + | 'erase the dataflash | ||
| + | State = Loadlabel(s32) 'St_datalogger_erase | ||
| + | Gosub Change_state_by_sub | ||
| + | Return | ||
| + | |||
| + | Datalogger_logcount: | ||
| + | 'Show DF_LogCount | ||
| + | Lcd_textbuffer = "1234" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Datalogger_rs232: | ||
| + | 'Print all DataLogs to RS232 | ||
| + | State = Loadlabel(s34) 'St_datalogger_rs232 as next status of state machine | ||
| + | Gosub Change_state_by_sub | ||
| + | Return | ||
| + | |||
| + | Temperaturefunc: | ||
| + | 'temperature measurement in °C | ||
| + | Lcd_textbuffer = "+24C" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Voltagefunc: | ||
| + | 'voltage measurement mV | ||
| + | Lcd_textbuffer = "0mV" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Adc_raw_func: | ||
| + | 'ADC Temperature/Voltage/Light result as RAW | ||
| + | Lcd_textbuffer = "CH:RAW" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Adc_batt_func: | ||
| + | 'battery voltage measurement | ||
| + | Lcd_textbuffer = "2900mV" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | '********* Sub MENU / OPTIONS ******************************** | ||
| + | Setcontrast: | ||
| + | 'Adjust the LCD contrast | ||
| + | Lcd_textbuffer = "0...15" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Bootfunc: | ||
| + | State = Loadlabel(s10) 'St_avrbf as next status of state machine | ||
| + | Gosub Change_state_by_sub | ||
| + | Return | ||
| + | |||
| + | Power_off_func: | ||
| + | 'LCD OFF | ||
| + | State = Loadlabel(s53) 'Return State is St_options_power_off | ||
| + | Gosub Change_state_by_sub | ||
| + | Return | ||
| + | |||
| + | Autopower: | ||
| + | 'Enable/Disable auto power save | ||
| + | Lcd_textbuffer = "ON/OFF" | ||
| + | Gosub Lcd_print | ||
| + | Return | ||
| + | |||
| + | Keyclick_set: | ||
| + | 'Enable/Disable keyclick | ||
| + | Lcd_textbuffer = "ON/OFF" | ||
| + | Gosub Lcd_print | ||
| + | Return</pre> | ||
=Siehe auch= | =Siehe auch= | ||
| − | *[[Sourcevergleich]] | + | *[[Sourcevergleich]] mit Hinweisen zu einer [[Sourcevergleich#Bascom (State Machine)|State Machine in BASCOM]] |
*[[Bascom]] | *[[Bascom]] | ||
| + | * AVR Butterfly Application code port to avr-gcc [[http://www.siwawi.arubi.uni-kl.de/avr_projects/#bf_app]] | ||
[[Kategorie:Software]] | [[Kategorie:Software]] | ||
[[Kategorie:Quellcode Bascom]] | [[Kategorie:Quellcode Bascom]] | ||
Aktuelle Version vom 16. August 2008, 12:21 Uhr
Inhaltsverzeichnis
Bascom State Machine Menu
Beim der Umsetzung des Beispielcodes von Atmel für AVR Butterfly [[1]] (in IAR-C bzw. die GCC-Portierung) nach Bascom [[2]] entstand folgende hoch effiziente State Machine zur Umsetzung eines Menüs für einen Datalogger.
Der Code wurde hier stark reduziert, so dass vom gesamten Programm das Menü als Rahmen mit allen Unterprogrammen (leer) übrig geblieben ist.
Die Menü-Struktur
Als Beispiel wird hier die um die Umsetzung des Menüs aus dem AVR Butterfly Evaluation Kit in Bascom gezeigt:
Sample Code Variante 1: Umsetzung des Codes aus dem AVR Butterfly Evaluation Kit
Der Code ist die 1:1 Umsetzung des C-Codes aus dem AVR Butterfly Evaluation Kit. Das Code-Beispiel wurde für den Bascom Simulator optimiert und kann dort direkt mit den Ziffern-Tasten bedient werden (NumLock!). Auf dem Simulator-LCD-Display werden die Ebenen mit angezeigt (3 -> 31 -> 32 -> 321 etc.)
Getestet im Bascom-Simulator der Versionen:
- BASCOM 1.11.9.1 [OK]
- BASCOM 1.11.8.7 [Probleme mir der LCD Darstellung]
- BASCOM 1.11.8.1 [OK]
Die Codelänge des Samples beträgt ca. 2300Byte. Der größte Teil geht für die LCD-Anzeige, Anzeigetexte etc. drauf. Der State Machine selber ist sehr schlank, da nur Pointer (Zeiger) gesetzt werden.
Weitere Erklärungen stehen im Quelltext.
'Beispiel für ein State Machine Menü
'Das Beispiel ist für den BASCOM-Simulator angepasst worden
' getestet mit BASCOM 1.11.8.1
' Codelänge 2362 Byte
'
'Hinweis: Im Simulator müssen die Eingaben in das "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
Const Key_null = 0 'keine Taste gedrückt
Const Key_next = 54
Const Key_prev = 52
Const Key_plus = 56
Const Key_minus = 50
'los gehts:
$regfile = "m32def.dat"
$framesize = 32 'Stack
$swstack = 32
$hwstack = 64
'Pins des LCD-Modules setzen ggf. an eigene Anschlüsse anpassen
Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.4 , Db6 = Portc.3 , Db7 = Portc.2 , E = Portc.6 , Rs = Portc.7
Config Lcdmode = Port
Config Lcdbus = 4 '4 bit mode
Config Lcd = 20 * 4
Initlcd
Cls
'******** state machine states ************************************************
' Menu state machine states
Const St_avrbf = 10
Const St_avrbf_rev = 11
Const St_time = 20
Const St_time_clock = 21
Const St_time_clock_func = 22
Const St_time_clock_adjust = 23
Const St_time_clock_adjust_func = 24
Const St_time_clockformat_adjust = 25
Const St_time_clockformat_adjust_func = 26
Const St_time_date = 27
Const St_time_date_func = 28
Const St_time_date_adjust = 29
Const St_time_date_adjust_func = 30
Const St_time_dateformat_adjust = 31
Const St_time_dateformat_adjust_func = 32
Const St_datalogger = 40
Const St_datalogger_logcycle = 41
Const St_datalogger_logcycle_func = 42
Const St_datalogger_erase = 43
Const St_datalogger_erase_select = 44
Const St_datalogger_erase_func = 45
Const St_datalogger_logcount = 46
Const St_datalogger_logcount_func = 47
Const St_datalogger_rs232 = 48
Const St_datalogger_rs232_select = 49
Const St_datalogger_rs232_func = 50
Const St_adc = 60
Const St_temperature = 65
Const St_temperature_func = 66
Const St_voltage = 70
Const St_voltage_func = 71
Const St_adc_raw = 75
Const St_adc_raw_func = 76
Const St_adc_batt = 80
Const St_adc_batt_func = 81
Const St_options = 90
Const St_options_display_contrast = 91
Const St_options_display_contrast_func = 92
Const St_options_power_off = 95
Const St_options_power_off_func = 97
Const St_options_auto_power_save = 100
Const St_options_auto_power_save_func = 101
Const St_options_keyclick = 105
Const St_options_keyclick_func = 106
Const St_options_boot = 110
Const St_options_boot_select = 111
Const St_options_boot_func = 112
'********* State Variables ****************************************************
Dim Tab_state As Byte , Tab_input As Byte , Tab_nextstate As Byte
Dim Tab_text As String * 25
Dim State As Byte , State_renew As Byte
'Initial state variables
State = St_avrbf
State_renew = 1
'******** 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 I1 As Byte
Dim W As Word , W1 As Word
'********** MAIN-Loop *********************************************************
Do
'Tastaturabfrage
Key = Inkey()
'Menüeintrag und Tastencodes finden
If Key <> Key_null Then 'save power
State_renew = 0
Restore State_machine
Do
Read Tab_state
Read Tab_input
Read Tab_nextstate
If State = Tab_state Then
If Key = Tab_input Then
State = Tab_nextstate
State_renew = 1 'LCD refresh
Key = Key_null 'reset key status after get a new state of state machine (prevent influence on GOSUBs)
End If
End If
Loop Until State_renew = 1 Or Tab_state = 255
End If
'Endlosschleife mit Unterprogrammen
Select Case State '320 Byte für 20 Gosub
Case St_time_clock_func : Gosub Showclock
Case St_time_clock_adjust_func : Gosub Setclock
Case St_time_clockformat_adjust_func : Gosub Setclockformat
Case St_time_date_func : Gosub Showdate
Case St_time_date_adjust_func : Gosub Setdate
Case St_time_dateformat_adjust_func : Gosub Setdateformat
Case St_datalogger_logcycle_func : Gosub Datalogger_setloginterval
Case St_datalogger_erase_func : Gosub Datalogger_erase
Case St_datalogger_logcount_func : Gosub Datalogger_logcount
Case St_datalogger_rs232_func : Gosub Datalogger_rs232
Case St_temperature_func : Gosub Temperaturefunc
Case St_voltage_func : Gosub Voltagefunc
Case St_adc_raw_func : Gosub Adc_raw_func
Case St_adc_batt_func : Gosub Adc_batt_func
Case St_options_display_contrast_func : Gosub Setcontrast
Case St_options_boot_func : Gosub Bootfunc
Case St_options_power_off_func : Gosub Power_off_func
Case St_options_auto_power_save_func : Gosub Autopower
Case St_options_keyclick_func : Gosub Keyclick_set
End Select
'---------------------------------------------------------------
'place for your own code in main loop
'---------------------------------------------------------------
'LCD refresh wenn Menü verändert
If State_renew = 1 Then
State_renew = 0
Restore Menu_text_data
Do
Read Tab_state
Read Tab_text
If State = Tab_state Then Lcd_textbuffer = Tab_text
Loop Until Tab_state = 255
Gosub Lcd_print
End If
Loop
End
'********* LCD SUB routines ***************************************************
'---------------------------------------------------------------
'Subroutine: Lcd_print
'Call from: anywhere
'Purpose: gibt Lcd_textbuffer auf dem LCD-Display aus
'Result: LCD
'---------------------------------------------------------------
Lcd_print: 'Print lcd_textbuffer
Cls
Lcd Lcd_textbuffer
Return
'********* SUB Clock routines**************************************************
Showclock:
'Show the clock on the LCD
Lcd_textbuffer = "HH:MM:SS"
Gosub Lcd_print
Return
Setclock:
'Adjusts the Clock
Lcd_textbuffer = "HH=11"
Gosub Lcd_print
Return
Setclockformat:
'Adjusts the Clockformat (12H or 24H)
Lcd_textbuffer = "12H / 24H"
Gosub Lcd_print
Return
'********* SUB date routines **************************************************
Showdate:
'Show the date on the LCD
Lcd_textbuffer = "DD.MM.YY"
Gosub Lcd_print
Return
Setdate:
'Adjusts the Date
Lcd_textbuffer = "Month=12"
Gosub Lcd_print
Return
'---------------------------------------------------------------
Setdateformat:
'Adjusts the Dateformat "DDMMYY" , "MMDDYY" , "YYMMDD"
Lcd_textbuffer = "DDMMYY/YYMMDD"
Gosub Lcd_print
Return
'********* Datalogger routines ************************************************
Datalogger_setloginterval:
'set the datalog intervall HOUR:MINUTES
Lcd_textbuffer = "HH:MM"
Gosub Lcd_print
Return
Datalogger_erase:
'erase the dataflash
State = St_datalogger_erase
State_renew = 1
Return
Datalogger_logcount:
'Show DF_LogCount
Lcd_textbuffer = "1234"
Gosub Lcd_print
Return
Datalogger_rs232:
'Print all DataLogs to RS232
State = St_datalogger_rs232 'next status of state machine
State_renew = 1
Return
Temperaturefunc:
'temperature measurement in °C
Lcd_textbuffer = "+24C"
Gosub Lcd_print
Return
Voltagefunc:
'voltage measurement mV
Lcd_textbuffer = "0mV"
Gosub Lcd_print
Return
Adc_raw_func:
'ADC Temperature/Voltage/Light result as RAW
Lcd_textbuffer = "CH:RAW"
Gosub Lcd_print
Return
Adc_batt_func:
'battery voltage measurement
Lcd_textbuffer = "2900mV"
Gosub Lcd_print
Return
'********* Sub MENU / OPTIONS ********************************
Setcontrast:
'Adjust the LCD contrast
Lcd_textbuffer = "0...15"
Gosub Lcd_print
Return
Bootfunc:
State = St_avrbf 'next status of state machine
State_renew = 1
Return
Power_off_func:
'LCD OFF
State = St_options_power_off
Return
Autopower:
'Enable/Disable auto power save
Lcd_textbuffer = "ON/OFF"
Gosub Lcd_print
Return
Keyclick_set:
'Enable/Disable keyclick
Lcd_textbuffer = "ON/OFF"
Gosub Lcd_print
Return
'*********** State Machine ***************************************************
'112 Datensätze der State Machine ca. 350 Byte
'State with xxx_func forward to GOSUB xxx in main loop
'
' [Key_plus ]
'[Key_prev] [Key_enter] [Key_next]
' [Key_minus]
State_machine:
' CURRENT_STATE INPUT NEXT_STATE
Data St_avrbf , Key_plus , St_options
Data St_avrbf , Key_next , St_avrbf_rev
Data St_avrbf , Key_minus , St_time
Data St_avrbf_rev , Key_prev , St_avrbf
'Date+Time-----------------------------------------------------------------
Data St_time , Key_plus , St_avrbf
Data St_time , Key_next , St_time_clock
Data St_time , Key_prev , St_avrbf
Data St_time , Key_minus , St_datalogger
Data St_time_clock , Key_plus , St_time_date
Data St_time_clock , Key_next , St_time_clock_func
Data St_time_clock , Key_prev , St_time
Data St_time_clock , Key_minus , St_time_date
Data St_time_clock_func , Key_prev , St_time_clock
Data St_time_clock_func , Key_next , St_time_clock_adjust
Data St_time_clock_func , Key_minus , St_time_date_func
Data St_time_clock_adjust , Key_plus , St_time_clockformat_adjust
Data St_time_clock_adjust , Key_next , St_time_clock_adjust_func
Data St_time_clock_adjust , Key_prev , St_time_clock_func
Data St_time_clock_adjust , Key_minus , St_time_clockformat_adjust
Data St_time_clock_adjust_func , Key_prev , St_time_clock_func
Data St_time_clockformat_adjust , Key_plus , St_time_clock_adjust
Data St_time_clockformat_adjust , Key_next , St_time_clockformat_adjust_func
Data St_time_clockformat_adjust , Key_prev , St_time_clock_func
Data St_time_clockformat_adjust , Key_minus , St_time_clock_adjust
Data St_time_clockformat_adjust_func , Key_prev , St_time_clock_func
Data St_time_date , Key_plus , St_time_clock
Data St_time_date , Key_next , St_time_date_func
Data St_time_date , Key_prev , St_time
Data St_time_date , Key_minus , St_time_clock
Data St_time_date_func , Key_plus , St_time_clock_func
Data St_time_date_func , Key_prev , St_time_date
Data St_time_date_func , Key_next , St_time_date_adjust
Data St_time_date_adjust , Key_plus , St_time_dateformat_adjust
Data St_time_date_adjust , Key_next , St_time_date_adjust_func
Data St_time_date_adjust , Key_prev , St_time_date_func
Data St_time_date_adjust , Key_minus , St_time_dateformat_adjust
Data St_time_date_adjust_func , Key_prev , St_time_date_func
Data St_time_dateformat_adjust , Key_plus , St_time_date_adjust
Data St_time_dateformat_adjust , Key_next , St_time_dateformat_adjust_func
Data St_time_dateformat_adjust , Key_prev , St_time_date_func
Data St_time_dateformat_adjust , Key_minus , St_time_date_adjust
Data St_time_dateformat_adjust_func , Key_prev , St_time_date_func
'Data Logger---------------------------------------------------------------
Data St_datalogger , Key_plus , St_time
Data St_datalogger , Key_next , St_datalogger_logcycle
Data St_datalogger , Key_prev , St_avrbf
Data St_datalogger , Key_minus , St_adc
Data St_datalogger_logcycle , Key_plus , St_datalogger_rs232
Data St_datalogger_logcycle , Key_next , St_datalogger_logcycle_func
Data St_datalogger_logcycle , Key_prev , St_datalogger
Data St_datalogger_logcycle , Key_minus , St_datalogger_erase
Data St_datalogger_logcycle_func , Key_prev , St_datalogger_logcycle
Data St_datalogger_erase , Key_plus , St_datalogger_logcycle
Data St_datalogger_erase , Key_next , St_datalogger_erase_select
Data St_datalogger_erase , Key_prev , St_datalogger
Data St_datalogger_erase , Key_minus , St_datalogger_logcount
Data St_datalogger_erase_select , Key_next , St_datalogger_erase_func
Data St_datalogger_erase_select , Key_prev , St_datalogger_erase
'SUB St_datalogger_erase_func -> new State = St_datalogger_erase
Data St_datalogger_logcount , Key_plus , St_datalogger_erase
Data St_datalogger_logcount , Key_next , St_datalogger_logcount_func
Data St_datalogger_logcount , Key_prev , St_datalogger
Data St_datalogger_logcount , Key_minus , St_datalogger_rs232
Data St_datalogger_logcount_func , Key_prev , St_datalogger_logcount
Data St_datalogger_rs232 , Key_plus , St_datalogger_logcount
Data St_datalogger_rs232 , Key_next , St_datalogger_rs232_select
Data St_datalogger_rs232 , Key_prev , St_datalogger
Data St_datalogger_rs232 , Key_minus , St_datalogger_logcycle
Data St_datalogger_rs232_select , Key_next , St_datalogger_rs232_func
Data St_datalogger_rs232_select , Key_prev , St_datalogger_rs232
'SUB St_datalogger_rs232_func -> new State = St_datalogger_rs232
'ADC-----------------------------------------------------------------------
Data St_adc , Key_plus , St_datalogger
Data St_adc , Key_next , St_temperature
Data St_adc , Key_prev , St_avrbf
Data St_adc , Key_minus , St_options
Data St_temperature , Key_plus , St_adc_raw
Data St_temperature , Key_next , St_temperature_func
Data St_temperature , Key_prev , St_avrbf
Data St_temperature , Key_minus , St_voltage
Data St_temperature_func , Key_prev , St_temperature
Data St_voltage , Key_plus , St_temperature
Data St_voltage , Key_next , St_voltage_func
Data St_voltage , Key_prev , St_avrbf
Data St_voltage , Key_minus , St_adc_raw
Data St_voltage_func , Key_prev , St_voltage
Data St_adc_raw , Key_plus , St_voltage
Data St_adc_raw , Key_next , St_adc_raw_func
Data St_adc_raw , Key_prev , St_avrbf
Data St_adc_raw , Key_minus , St_adc_batt
Data St_adc_raw_func , Key_prev , St_adc_raw
Data St_adc_batt , Key_plus , St_adc_raw
Data St_adc_batt , Key_next , St_adc_batt_func
Data St_adc_batt , Key_prev , St_avrbf
Data St_adc_batt , Key_minus , St_temperature
Data St_adc_batt_func , Key_prev , St_adc_batt
'Options-------------------------------------------------------------------
Data St_options , Key_plus , St_adc
Data St_options , Key_next , St_options_display_contrast
Data St_options , Key_prev , St_avrbf
Data St_options , Key_minus , St_avrbf
Data St_options_display_contrast , Key_plus , St_options_keyclick
Data St_options_display_contrast , Key_next , St_options_display_contrast_func
Data St_options_display_contrast , Key_prev , St_options
Data St_options_display_contrast , Key_minus , St_options_boot
Data St_options_display_contrast_func , Key_prev , St_options_display_contrast
Data St_options_boot , Key_plus , St_options_display_contrast
Data St_options_boot , Key_next , St_options_boot_select
Data St_options_boot , Key_prev , St_options
Data St_options_boot , Key_minus , St_options_power_off
Data St_options_boot_select , Key_next , St_options_boot_func
Data St_options_boot_select , Key_prev , St_options_boot
Data St_options_power_off , Key_plus , St_options_boot
Data St_options_power_off , Key_next , St_options_power_off_func
Data St_options_power_off , Key_prev , St_options
Data St_options_power_off , Key_minus , St_options_auto_power_save
'SUB St_options_power_off_func -> new State = St_options_power_off
Data St_options_auto_power_save , Key_plus , St_options_power_off
Data St_options_auto_power_save , Key_next , St_options_auto_power_save_func
Data St_options_auto_power_save , Key_prev , St_options
Data St_options_auto_power_save , Key_minus , St_options_keyclick
Data St_options_auto_power_save_func , Key_prev , St_options_auto_power_save
Data St_options_keyclick , Key_plus , St_options_auto_power_save
Data St_options_keyclick , Key_next , St_options_keyclick_func
Data St_options_keyclick , Key_prev , St_options
Data St_options_keyclick , Key_minus , St_options_display_contrast
Data St_options_keyclick_func , Key_prev , St_options_keyclick
'Stop Condition
Data 255 , 255 , 255
'************ menu text strings: max. length 24 Byte!! ***********************
Menu_text_data:
Data St_avrbf , "1 Butterfly Bascom"
Data St_avrbf_rev , "11 Rev 1"
Data St_time , "2 Time"
Data St_time_clock , "21 Clock"
Data St_time_clock_adjust , "211 Adjust Clock"
Data St_time_clockformat_adjust , "212 Clock Format"
Data St_time_date , "22 Date"
Data St_time_date_adjust , "221 Adjust Date"
Data St_time_dateformat_adjust , "222 Date Format"
Data St_datalogger , "3 DataLogger"
Data St_datalogger_logcycle , "31 Log Cycle"
Data St_datalogger_erase , "32 Delete Flash"
Data St_datalogger_erase_select , "321 RIGHT Delete DF"
Data St_datalogger_logcount , "33 Show LogCount"
Data St_datalogger_rs232 , "34 Print to RS232"
Data St_datalogger_rs232_select , "341 RIGHT Print9600B"
Data St_adc , "4 ADC"
Data St_temperature , "41 Temperature"
Data St_voltage , "42 Voltage"
Data St_adc_raw , "43 ADC Port RAW"
Data St_adc_batt , "44 Battery"
Data St_options , "5 Options"
Data St_options_display_contrast , "51 LCD contrast"
Data St_options_boot , "52 Bootloader"
Data St_options_boot_select , "521 RIGHT bootloader"
Data St_options_power_off , "53 LCD OFF"
Data St_options_auto_power_save , "54 LCD Auto Power"
Data St_options_keyclick , "55 Key Click"
Data 255 , "" 'Stop Condition
Sample Code Variante 2: übersichtlich mit ADR2
Die Variante 1 ist leider unübersichtlich, da 3 Tabellen getrennt geführt werden (die State Machine, die Menütexte und die zugehörigen Unterprogrammeinsprünge). Nachfolgend eine Variante, in der nur eine Tabelle geführt wird. Die Lösung wurde möglich, nachdem in Bascom in der Version 1.11.8.9 den Befehl ADR / ADR2 eingeführt wurde.
In jedem Datensatz stehen jetzt die Daten für die Verzweigung der State Machine (inf. Tastatureingabe), der Pointer für den Unterprogrammeinsprung und der Menütext zusammen. Die Codelänge das Beispiel liegt gleichauf mit der Variante 1. Dafür ist das Menü deutlich einfacher zu editieren.
Weitere Erklärungen stehen im Quelltext. Die Bedienung erfolgt wie bei Variante 1.
Da jetzt zur Vereinfachung Nummern für die States geführt werden, empfiehlt es sich ein Plan (siehe Grafik oben) anzulegen und jeden Kasten mit einer Nummer zu versehen. Die Zuordnung der Status-Nummern entsprechend der Tasten-Verzweigung (UP/DOWN etc.) ist dann schnell abgelesen. Alternativ kann man natürlich beliebige Labelnamen verwenden.
Getestet im Bascom-Simulator der Versionen:
- BASCOM 1.11.9.1 [OK]
'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 2028 Byte
$regfile = "m8def.dat"
$framesize = 32 'Stack
$swstack = 32
$hwstack = 64
$sim 'empty wait loops - faster simulation - not for real world!!
'
'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:
Const Key_buttons = 4 'Anzahl der Tasten
Dim Keycode_string As String * Key_buttons
'Key_plus|Key_minus|Key_prev|Key_next
Keycode_string = "{056}{050}{052}{054}" 'see scan codes in ASCII chart
Dim Keycode(key_buttons) As Byte At Keycode_string Overlay
Const Key_null = 0 'keine Taste gedrückt
'******** LCD Settings ***********************************************
Dim Lcd_textbuffer As String * 25
'Pins des LCD-Modules setzen ggf. an eigene Anschlüsse anpassen
Config Lcd = 16 * 1
Initlcd
Cls
'******** Joystick/Key Settings ***********************************************
Dim Key As Byte 'key in Mainloop
'********* 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
Key = Key_null 'keine Taste gedrückt
'******** allg Variablen ******************************************************
Dim I As Byte , J As Byte
Dim W As Word
'********** 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 Key_buttons
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
'Format: 1. Zeile: für jede Taste genau eine Verzeigung ADR2 (see Key_buttons=xx)
' 2. Zeile: Sprunglabel als ADR2 für ein ggf. anzuspringendes Unterprogramm
' 3. Zeile: Displaytext des akt. Status als DATA Feld
'Hinweis: wenn nichts passieren soll wird das Label NULL eingetragen
'---------------------------------------------------------------
Null:
'Null is a dummy flag for State and Gosub -> do nothing
Return
S10:
Adr2 Null : Adr2 S20 : Adr2 Null : Adr2 S11 'Key_plus|Key_minus|Key_prev|Key_next
Adr2 Null 'Subroutine for current State
Data "1 Butterfly Bascom" 'Menue Display Text
S11:
Adr2 Null : Adr2 Null : Adr2 S10 : Adr2 Null 'Key_plus|Key_minus|Key_prev|Key_next
Adr2 Null
Data "11 Rev 2"
S20:
Adr2 S10 : Adr2 S30 : Adr2 Null : Adr2 S21
Adr2 Null
Data "2 Time"
S21:
Adr2 Null : Adr2 S22 : Adr2 S20 : Adr2 S23
Adr2 Null
Data "21 Clock"
S22:
Adr2 S21 : Adr2 Null : Adr2 S20 : Adr2 S24
Adr2 Null
Data "22 Date"
S23: 'Show HH:MM:SS
Adr2 Null : Adr2 S24 : Adr2 S21 : Adr2 S25
Adr2 Showclock
Data ""
S24: 'Show DD:MM:YY
Adr2 S23 : Adr2 Null : Adr2 S22 : Adr2 S26
Adr2 Showdate
Data ""
S25:
Adr2 S27 : Adr2 Null : Adr2 S23 : Adr2 S65
Adr2 Null
Data "211 Adjust Clock"
S26:
Adr2 Null : Adr2 S28 : Adr2 S24 : Adr2 S66
Adr2 Null
Data "221 Adjust Date"
S27:
Adr2 Null : Adr2 S25 : Adr2 S23 : Adr2 S67
Adr2 Null
Data "212 Clock Format"
S28:
Adr2 S26 : Adr2 Null : Adr2 S23 : Adr2 S68
Adr2 Null
Data "222 Date Format"
S30:
Adr2 S20 : Adr2 S40 : Adr2 Null : Adr2 S31
Adr2 Null
Data "3 DataLogger"
S31:
Adr2 Null : Adr2 S32 : Adr2 S30 : Adr2 S35
Adr2 Null
Data "31 Log Cycle"
S32:
Adr2 S31 : Adr2 S33 : Adr2 S30 : Adr2 S36
Adr2 Null
Data "32 Delete Flash"
S33:
Adr2 S32 : Adr2 S34 : Adr2 S30 : Adr2 S37
Adr2 Null
Data "33 Show LogCount"
S34:
Adr2 S33 : Adr2 Null : Adr2 S30 : Adr2 S38
Adr2 Null
Data "34 Print to RS232"
S35: 'HH:MM
Adr2 Null : Adr2 Null : Adr2 S31 : Adr2 Null
Adr2 Datalogger_setloginterval
Data ""
S36:
Adr2 Null : Adr2 Null : Adr2 S32 : Adr2 S76
Adr2 Null
Data "321 RIGHT Delete DF"
S37: '1234
Adr2 Null : Adr2 Null : Adr2 S33 : Adr2 Null
Adr2 Datalogger_logcount
Data ""
S38:
Adr2 Null : Adr2 Null : Adr2 S34 : Adr2 S78
Adr2 Null
Data "341 RIGHT Print9600B"
S40:
Adr2 S30 : Adr2 S50 : Adr2 Null : Adr2 S41
Adr2 Null
Data "4 ADC"
S41:
Adr2 Null : Adr2 S42 : Adr2 S40 : Adr2 S45
Adr2 Null
Data "41 Temperature"
S42:
Adr2 S41 : Adr2 S43 : Adr2 S40 : Adr2 S46
Adr2 Null
Data "42 Voltage"
S43:
Adr2 S42 : Adr2 S44 : Adr2 S40 : Adr2 S47
Adr2 Null
Data "43 ADC Port RAW"
S44:
Adr2 S43 : Adr2 Null : Adr2 S40 : Adr2 S48
Adr2 Null
Data "44 Battery"
S45: '+24°C
Adr2 Null : Adr2 Null : Adr2 S41 : Adr2 Null
Adr2 Temperaturefunc
Data ""
S46: '0 mV
Adr2 Null : Adr2 Null : Adr2 S42 : Adr2 Null
Adr2 Voltagefunc
Data ""
S47: 'CH:RAW
Adr2 Null : Adr2 Null : Adr2 S43 : Adr2 Null
Adr2 Adc_raw_func
Data ""
S48: '2900mV
Adr2 Null : Adr2 Null : Adr2 S44 : Adr2 Null
Adr2 Adc_batt_func
Data ""
S50:
Adr2 S40 : Adr2 Null : Adr2 Null : Adr2 S51
Adr2 Null
Data "5 Options"
S51:
Adr2 Null : Adr2 S52 : Adr2 S50 : Adr2 S56
Adr2 Null
Data "51 LCD contrast"
S52:
Adr2 S51 : Adr2 S53 : Adr2 S50 : Adr2 S57
Adr2 Null
Data "52 Bootloader"
S53:
Adr2 S52 : Adr2 S54 : Adr2 S50 : Adr2 S83
Adr2 Null
Data "53 LCD OFF"
S54:
Adr2 S53 : Adr2 S55 : Adr2 S50 : Adr2 S58
Adr2 Null
Data "54 LCD Auto Power"
S55:
Adr2 S54 : Adr2 Null : Adr2 S50 : Adr2 S59
Adr2 Null
Data "55 Key Click"
S56: '0...15
Adr2 Null : Adr2 Null : Adr2 S51 : Adr2 Null
Adr2 Setcontrast
Data ""
S57:
Adr2 Null : Adr2 Null : Adr2 S52 : Adr2 S87
Adr2 Null
Data "521 RIGHT bootloader"
S58: 'OFF/5..90min
Adr2 Null : Adr2 Null : Adr2 S54 : Adr2 Null
Adr2 Autopower
Data ""
S59: 'ON/OFF
Adr2 Null : Adr2 Null : Adr2 S55 : Adr2 Null
Adr2 Keyclick_set
Data ""
'Untermenüs zu State 25 bis 28
S65: 'sub for "211 Adjust Clock"
Adr2 S67 : Adr2 Null : Adr2 S23 : Adr2 Null
Adr2 Setclock
Data ""
S66: 'sub for "221 Adjust Date"
Adr2 Null : Adr2 S68 : Adr2 S24 : Adr2 Null
Adr2 Setdate
Data ""
S67: 'sub for "212 Clock Format"
Adr2 Null : Adr2 S65 : Adr2 S23 : Adr2 Null
Adr2 Setclockformat
Data ""
S68: 'sub for "222 Date Format"
Adr2 S66 : Adr2 Null : Adr2 S24 : Adr2 Null
Adr2 Setdateformat
Data ""
'Untermenüs zu State 36 und 38
S76: 'sub for "321 RIGHT Delete DF"
Adr2 Null : Adr2 Null : Adr2 S36 : Adr2 Null
Adr2 Datalogger_erase
Data ""
S78: 'sub for "341 RIGHT Print9600B"
Adr2 Null : Adr2 Null : Adr2 S38 : Adr2 Null
Adr2 Datalogger_rs232
Data ""
'Untermenü zu State 53 und 57
S83: 'sub for "53 LCD OFF"
Adr2 Null : Adr2 Null : Adr2 S53 : Adr2 Null
Adr2 Power_off_func
Data ""
S87: 'sub for "521 RIGHT bootloader"
Adr2 Null : Adr2 Null : Adr2 S57 : Adr2 Null
Adr2 Bootfunc
Data ""
'********* LCD SUB routines ***************************************************
'---------------------------------------------------------------
'Subroutine: Lcd_print
'Call from: anywhere
'Purpose: gibt Lcd_textbuffer auf dem LCD-Display aus
'Result: LCD
'---------------------------------------------------------------
Lcd_print: 'Print lcd_textbuffer
Cls
Lcd Lcd_textbuffer
State_renew = 0
Return
'********* SUB Clock routines**************************************************
Showclock:
'Show the clock on the LCD
Lcd_textbuffer = "HH:MM:SS"
Gosub Lcd_print
Return
Setclock:
'Adjusts the Clock
Lcd_textbuffer = "HH=11"
Gosub Lcd_print
Return
Setclockformat:
'Adjusts the Clockformat (12H or 24H)
Lcd_textbuffer = "12H / 24H"
Gosub Lcd_print
Return
'********* SUB date routines **************************************************
Showdate:
'Show the date on the LCD
Lcd_textbuffer = "DD.MM.YY"
Gosub Lcd_print
Return
Setdate:
'Adjusts the Date
Lcd_textbuffer = "Month=12"
Gosub Lcd_print
Return
'---------------------------------------------------------------
Setdateformat:
'Adjusts the Dateformat "DDMMYY" , "MMDDYY" , "YYMMDD"
Lcd_textbuffer = "DDMMYY/YYMMDD"
Gosub Lcd_print
Return
'********* Datalogger routines ************************************************
Datalogger_setloginterval:
'set the datalog intervall HOUR:MINUTES
Lcd_textbuffer = "HH:MM"
Gosub Lcd_print
Return
Datalogger_erase:
'erase the dataflash
State = Loadlabel(s32) 'St_datalogger_erase
Gosub Change_state_by_sub
Return
Datalogger_logcount:
'Show DF_LogCount
Lcd_textbuffer = "1234"
Gosub Lcd_print
Return
Datalogger_rs232:
'Print all DataLogs to RS232
State = Loadlabel(s34) 'St_datalogger_rs232 as next status of state machine
Gosub Change_state_by_sub
Return
Temperaturefunc:
'temperature measurement in °C
Lcd_textbuffer = "+24C"
Gosub Lcd_print
Return
Voltagefunc:
'voltage measurement mV
Lcd_textbuffer = "0mV"
Gosub Lcd_print
Return
Adc_raw_func:
'ADC Temperature/Voltage/Light result as RAW
Lcd_textbuffer = "CH:RAW"
Gosub Lcd_print
Return
Adc_batt_func:
'battery voltage measurement
Lcd_textbuffer = "2900mV"
Gosub Lcd_print
Return
'********* Sub MENU / OPTIONS ********************************
Setcontrast:
'Adjust the LCD contrast
Lcd_textbuffer = "0...15"
Gosub Lcd_print
Return
Bootfunc:
State = Loadlabel(s10) 'St_avrbf as next status of state machine
Gosub Change_state_by_sub
Return
Power_off_func:
'LCD OFF
State = Loadlabel(s53) 'Return State is St_options_power_off
Gosub Change_state_by_sub
Return
Autopower:
'Enable/Disable auto power save
Lcd_textbuffer = "ON/OFF"
Gosub Lcd_print
Return
Keyclick_set:
'Enable/Disable keyclick
Lcd_textbuffer = "ON/OFF"
Gosub Lcd_print
Return
Siehe auch
- Sourcevergleich mit Hinweisen zu einer State Machine in BASCOM
- Bascom
- AVR Butterfly Application code port to avr-gcc [[3]]