'##############################################################################
'
' DrMaFu_Senso.BAS                                             Stand 22.03.2017
' ----------------                                             (C) Markus Fulde
'
' Version 1.1
'
' Gesamtsoftware Steuerprogramm für das Geocaching-Spiel Senso
'
' Das Projekt verfüg über die folgenden Funktions- und Teilkomponenten:
' - Spannungsversorgung via 9V Batterie und 5V über Festspannungsregler
' - Mikrocontroller ATmega8L (inkl. ISP, RS232 und Reset)
' - LCD-Display 1x8 EA DOGM081L-A von Electronic Assembly
' - Die Helligkeit des Display soll über PWM einstellbar sein
' - Bei Innaktivität soll das Display abgeschaltet werden können
' - Bei Innaktivität soll der ATmega in einen Sleep-Mode gehen
' - Hauptschalter für Spannungsversorgung
' - 4 Tasten (ROT, GELB, GRÜN, BLAU) zur Bedienung des Spiels
' - 4 LED's (ROT, GELB, GRÜN, BLAU) zur Bedienung des Spiels
' - LED-Anzeigen für Betriebsanzeige
' - Gehäuse mit Batteriefach und Displayfenster
' - Soundausgabe über Lautsprecher
'
'##############################################################################

'------------------------------------------------------------------------------
' Allgemeines zum Spiel:
'------------------------------------------------------------------------------
'
' Die Wikipedia schreibt zum Senso folgendes:
'
' Senso (im englischen Sprachraum Simon) ist ein von Ralph Baer - dem Entwickler
' der 1972 erschienenen ersten TV-Spielekonsole Magnavox Odyssey - und
' Howard J. Morrison entwickeltes und in mehreren Ländern patentier-tes
' elektronisches Spiel, welches 1978 bei Milton Bradley veröffentlicht wurde und
' sich besonders in den 1980er Jahren großer Beliebtheit erfreute. 1979 befand
' es sich auf der Auswahlliste zum Spiel des Jahres. Neuerdings wird das Spiel
' auch in Deutschland als Simon verkauft.
'
' Idee:
' Senso kann allein oder mit mehreren Personen gespielt werden. Das Spiel
' besteht aus vier großen Feldern in den Farben Rot, Blau, Gelb und Grün. Diese
' leuchten abwechselnd auf und geben dabei für jede Farbe einen kurzen,
' individuellen Signalton von sich. Der Spieler muss sich diese Reihenfolge
' merken und nach Abschluss der Vorgabe durch das Spiel wiederholen. Mit jeder
' Runde kommt eine weitere Farb-Ton-Kombination hinzu. Mit steigendem
' Schwierigkeitsgrad leuchten die Felder in schnellerer Reihenfolge auf.
'
' In diesem Geocaching-Projekt Senso wird das Spielkonzept dazu benutzt, eine
' kleine Elektronik zu entwickeln welche im Gelände versteckt wird, die nach
' jedem erfolgreichem Spiel die finalen Geokoordinaten der finalen Dose anzeigt.
' Es muss eine Reihenfolge von insgesamt 10 Vorgaben richtig absolviert werden,
' damit das Spiel sein Ge-heimnis und damit die finalen Koordinaten Preis gibt.
'
' Im Wesentlichen geht es bei diesem Projekt aber auch umn den Ersatz des
' originalen Geocaching-Spiels das schon seit vielen Jahren Vorort liegt und
' durch Vandalismus zerstört wurde. Wasser und Elektronik vertragen sich einfach'
' zu schlecht.
'
' Anmerkung:
' Der Source-Code für Senso entsteht mit diesem Projekt neu. Es werden neue
' Funktionen und eine andere Display-Technologier wie im Original eingesetzt.
' Teile des Source-Codes von DF1SAM wurden dabei übernommen.
'
' -----------------------------------------------------------------------------

'------------------------------------------------------------------------------
' Compilerinstruktionen und Compilerdirektiven
'------------------------------------------------------------------------------
$regfile = "m8def.dat"                                      ' Definitionsdatei für ATmega128 laden
$crystal = 8000000                                          ' Quarzfrequenz für 16 MHz festlegen

$hwstack = 128                                              ' HW-Stack auf 128 Bytes erweitern
$swstack = 64                                               ' SW-Stack auf 64 Bytes erweitern
$framesize = 80                                             ' Framesize auf 80 Byte festlegen

$baud = 19200                                               ' Baudrate für RS232 Traceausgabe definieren

'------------------------------------------------------------------------------
' Allgemeine Zusatzinformatonen zu Programmbeginn
'------------------------------------------------------------------------------

' -- Fuses aus ATmega8 ausgelesen ---------------------------------------------
'   HIGH 0xD9
'   LOW  0xE4 = Int. RC Osc. 8 MHz; Start-up time: 6 CK + 64 ms

' -- Allgemeine Informationen zur Sounderzeugung ------------------------------
'     | |C||D| | |F||G||A| | |C||D| | |F||G||A| | |C||D| | |F||G||A| |
'     | |1||1| | |1||1||1| | |2||2| | |2||2||2| | |3||3| | |3||3||3| | |
'     | |#||#| | |#||#||#| | |#||#| | |#||#||#| | |#||#| | |#||#||#| | |
'     |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | |
'     |C1|D1|E1|F1|G1|A1|H1|C2|D2|E2|F2|G2|A2|H2|C3|D3|E3|F3|G3|A3|H3| |
'     |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__| |
'
' (1/1)   - 2 sec
' (1/2)   - 1 sec
' (1/4)   - 0,5 sec
' (1/8)   - 0,25 sec
' (1/16)  - 0,125 sec
' (1/32)  - 0,0625 sec
'
' *****   FORMAT TO FUNCTIONS SOUND  *****
'
' Sound Speaker , Pulses , Periods
' Speaker - port for generations of sound
' Periods - sound frequency (1-65535)
' Pulses  - duration of sound (1-65535)
'
' Periods = Abc[F_crystal / (k * F_nota)]
' Pulses  = Abc[(T_period * F_crystal) / (k * Periods)]
'
' F_crystal - clockrate of controller, Hz
' F_nota    - frequency a notes, Hz
' k = 12    - amount of tacts, for which is formed one period of sound
' T_period  - duration of sounding a notes, sec
' Abc       - function of truncation whole number
'
'===============================================================================
' Table of values Pulses,Periods for 3 octaves at frequency of quartz 8000000 Hz
'===============================================================================
'Note|Freqvency|Periods|Pulses 1/1|Pulses 1/2|Pulses 1/4|Pulses 1/8|Pulses 1/16|
'===============================================================================
' C1 |  261,63 |  2548 |    523   |    262   |    131   |    65    |     33    |
'Cis1|  277,18 |  2405 |    554   |    277   |    139   |    69    |     35    |
' D1 |  293,66 |  2270 |    587   |    294   |    147   |    73    |     37    |
'Dis1|  311,13 |  2143 |    622   |    311   |    156   |    78    |     39    |
' E1 |  329,63 |  2022 |    659   |    330   |    165   |    82    |     41    |
' F1 |  349,23 |  1909 |    698   |    349   |    175   |    87    |     44    |
'Fis1|  369,99 |  1802 |    740   |    370   |    185   |    92    |     46    |
' G1 |  392,00 |  1701 |    784   |    392   |    196   |    98    |     49    |
'Gis1|  415,30 |  1605 |    831   |    415   |    208   |   104    |     52    |
' A1 |  440,00 |  1515 |    880   |    440   |    220   |   110    |     55    |
'Ais1|  466,16 |  1430 |    932   |    466   |    233   |   117    |     58    |
' B1 |  493,88 |  1350 |    988   |    494   |    247   |   124    |     62    |
'===============================================================================
' C2 |  523,25 |  1274 |   1047   |    523   |    262   |   131    |     65    |
'Cis2|  554,36 |  1203 |   1109   |    554   |    277   |   139    |     69    |
' D2 |  587,32 |  1135 |   1175   |    587   |    294   |   147    |     73    |
'Dis2|  622,26 |  1071 |   1245   |    622   |    311   |   156    |     78    |
' E2 |  659,26 |  1011 |   1319   |    659   |    330   |   165    |     82    |
' F2 |  698,46 |   954 |   1397   |    698   |    349   |   175    |     87    |
'Fis2|  739,98 |   901 |   1480   |    740   |    370   |   185    |     92    |
' G2 |  784,00 |   850 |   1568   |    784   |    392   |   196    |     98    |
'Gis2|  830,60 |   803 |   1661   |    831   |    415   |   208    |    104    |
' A2 |  880,00 |   758 |   1720   |    880   |    440   |   220    |    110    |
'Ais2|  932,32 |   715 |   1865   |    932   |    466   |   233    |    117    |
' B2 |  987,75 |   675 |   1976   |    988   |    494   |   247    |    124    |
'===============================================================================
' C3 | 1046,50 |   637 |   2093   |   1047   |    523   |   262    |    131    |
'Cis3| 1108,70 |   601 |   2218   |   1109   |    554   |   277    |    139    |
' D3 | 1174,60 |   566 |   2350   |   1175   |    587   |   294    |    147    |
'Dis3| 1244,50 |   536 |   2490   |   1245   |    622   |   311    |    156    |
' E3 | 1318,50 |   483 |   2638   |   1319   |    659   |   330    |    165    |
' F3 | 1396,90 |   477 |   2794   |   1397   |    698   |   349    |    175    |
'Fis3| 1480,00 |   450 |   2960   |   1480   |    740   |   370    |    185    |
' G3 | 1568,00 |   425 |   3136   |   1568   |    784   |   392    |    196    |
'Gis3| 1661,20 |   401 |   3322   |   1661   |    831   |   415    |    208    |
' A3 | 1720,00 |   388 |   3440   |   1720   |    880   |   440    |    220    |
'Ais3| 1864,60 |   358 |   3730   |   1865   |    932   |   466    |    233    |
' B3 | 1975,50 |   337 |   3952   |   1976   |    988   |   494    |    247    |
'===============================================================================

'------------------------------------------------------------------------------
' Anmerkungen zum Programm:
'------------------------------------------------------------------------------

' [1] Zufallszahlengenerator in BASCOM
' Die Rnd() Funktion Arbeitet Nicht Wirklich Zufällig. Hierzu Sagt Mcv Folgendes:
' The Rnd() Function Returns An Integer / Word And Needs An Internal Storage Of 2 Bytes.
' (___rseed). Each New Call To Rnd() Will Give A New Positive Random Number.
' notice Notice that it is a software based generated number.
' And each time you will restart your program the same sequence will be created.
'
' You can use a different SEED value by dimensioning and assigning ___RSEED yourself:
' Dim ___rseed as word : ___rseed = 10234
' Dim I as word : I = rnd(10)
'
' When your application uses a timer you can assign ___RSEED with the timer value.
' This will give a better random number.
'
' Aus diesem Grund wird hier in der Software beim Auslesen der Batteriespannung
' die SEED-Variable des Zufallszahlengenerators neu gesetzt um mehr
' Zufälligkeit zu erzeugen.
'

' [2] Nach umfangreichen Tests stell sich nach wie vor heraus, dass die
' Zufallszahl bzw. das Pattern nicht ausreichend zufällig ist und sich Reihen-
' folgen dauerhaft / oft wiederholen. Aus diesem Grund wurden die Pattern für
' die Sensowerte offline erzeugt und im Data-Bereich gehalten.
' Mit einer Zufallszahl von 1 -100 wird nun willkürlich ein Pattern aus dem
' Databereich geladen.
' Eine andere Möglichkeit hätte - wie in der originalen Senso-Implementierung
' dadurch bestanden, die Zeit welche zwischen 2 Tastendrücken verstreicht in
' einen Zufallswert umzurechnen. Dieses Verfahren kam hier nicht zum Einsatz
' da ich von Anfang an die Kombinationen berechnet haben wollte.

' [3] Die originale Senso-Implementierung basiert auf vielen GOTO's
' Da ich ein Gener von GOTO's bin wurde die Implementierung komplett über-
' arbeitet und auf "saubere" Programmabläufe umgestellt.

'------------------------------------------------------------------------------
' Definition von Ressourcen
'------------------------------------------------------------------------------

' ----- LED's -----
Alive_led_pin Alias Pinb.0                                  ' GPIO für Alive-LED (für DDR oder Input)
Alive_led Alias Portb.0                                     ' GPIO für Alive-LED für Output oder Pullup)

' Oberste LED im Kreutz ist die Blaue LED und zugleich die Start-LED bei Standby

Led_blau_pin Alias Pinb.6                                   ' LED1: GPIO für blaue LED (für DDR oder Input)
Led_blau Alias Portb.6                                      ' LED1: GPIO für blaue LED (für Output oder Pullup)

' im Uhrzeigersinn folgen dann

Led_rot_pin Alias Pinb.7                                    ' LED2: GPIO für rote LED (für DDR oder Input)
Led_rot Alias Portb.7                                       ' LED2: GPIO für rote LED (für Output oder Pullup)

Led_gruen_pin Alias Pind.5                                  ' LED3: GPIO für gruene LED (für DDR oder Input)
Led_gruen Alias Portd.5                                     ' LED3: GPIO für gruene LED (für Output oder Pullup)

Led_gelb_pin Alias Pind.6                                   ' LED4: GPIO für gelbe LED (für DDR oder Input)
Led_gelb Alias Portd.6                                      ' LED4: GPIO für gelbe LED (für Output oder Pullup)

' ----- LCD-Display -----
' LCD-Display
Lcd_bit_0 Alias Portc.2                                     ' GPIO für LCD Bit 0
Lcd_bit_1 Alias Portc.3                                     ' GPIO für LCD Bit 1
Lcd_bit_2 Alias Portc.4                                     ' GPIO für LCD Bit 2
Lcd_bit_3 Alias Portc.5                                     ' GPIO für LCD Bit 3
Lcd_e Alias Portb.2                                         ' GPIO für LCD E
Lcd_rs Alias Portc.1                                        ' GPIO für LCD RS

' ----- Key / Tasten -----

' BLAU
Key_taster1_pin Alias Pind.3                                ' KEY1: GPIO für Taste 1 BLAU (für DDR oder Input)
Key_taster1 Alias Portd.3                                   ' KEY1: GPIO für Taste 1 BLAU (für Output oder Pullup)

' ROT
Key_taster2_pin Alias Pind.2                                ' KEY2: GPIO für Taste 2 ROT (für DDR oder Input)
Key_taster2 Alias Portd.2                                   ' KEY2: GPIO für Taste 2 ROT (für Output oder Pullup)

' GRÜN
Key_taster3_pin Alias Pind.4                                ' KEY3: GPIO für Taste 3 GRÜN (für DDR oder Input)
Key_taster3 Alias Portd.4                                   ' KEY3: GPIO für Taste 3 GRÜN (für Output oder Pullup)

' GELB
Key_taster4_pin Alias Pind.7                                ' KEY4: GPIO für Taste 4 GELB (für DDR oder Input)
Key_taster4 Alias Portd.7                                   ' KEY4: GPIO für Taste 4 GELB (für Output oder Pullup)

' ----- Sound -----
Speaker_pin Alias Pinb.1                                    ' GPIO für Sound-Ausgabe (für DDR oder Input)
Speaker Alias Portb.1                                       ' GPIO für Sound-Ausgabe (für Output oder Pullup)

'------------------------------------------------------------------------------
' Definition von Konstaten
'------------------------------------------------------------------------------

' ----- Für Testumgebung bzw. Traceausgaben -----
Const Main_testmodus = 0                                    ' Flag für Testmodus Allgemeinsystem
Const Batterie_testmodus = 0                                ' Flag für Batteriemanagement
Const Lcd_testmodus = 0                                     ' Flag für Testmodus rund um das LCD-Display
Const Game_testmodus = 0                                    ' Flag für Testmodus der Spielsteuerung
Const Bypass_testmodus = 0                                  ' Flag für Testmodus des Bypass-Modes
Const Eeprom_testmodus = 0                                  ' Flag für Testmodus der Eeprom-Daten
Const Key_testmodus = 0                                     ' Flag für Testmodus der Taster

' ----- Allgemeine Systemkonstanten -----

' Tatsächliches Allgemeines
Const Led_aus = 0                                           ' LED Konstake für LED aus im echten Spiel
Const Led_ein = 1                                           ' LED Konstake für LED ein im echten Spiel

' Const Led_aus = 1                                           ' Achtung !! bei STK500 ist Logik gedreht!!
' Const Led_ein = 0                                           ' Achtung !! bei STK500 ist Logik gedreht!!

Const False = 0                                             ' Boolsche Variable für Falsch
Const True = 1                                              ' Boolsche Variable für Richtig

Const Pullup_aus = 0                                        ' Konstante für PullUp AUS
Const Pullup_ein = 1                                        ' Konstante für PullUp EIN

' Zeitvorgabe für Sekunden-Timer
Const Timervorgabe = 34286                                  ' Timer von 1 Sekunden (SekundenTick)

' ----- Tasten -----

' Konstanten für Überprüfung der Tasten
'                     G  GBR
'                     E  NLT
'                     |  |||
'                     76543210
Const Key_all_key = &B10011100
Const Key_ge__key = &B10000000
Const Key_gn__key = &B00010000
Const Key_bl__key = &B00001000
Const Key_rt__key = &B00000100

Const Key_all_key_not = &B01100011
Const Key_ge__key_not = &B01111111
Const Key_gn__key_not = &B11101111
Const Key_bl__key_not = &B11110111
Const Key_rt__key_not = &B11111011

Const Key_all_key_pressed = &B00000000
Const Key_masked_key_aktive = &B00000000

Const Key_entprellzeit = 20                                 ' Entprellzeit für Tasten in ms

Const Key_pressed = 0                                       ' Signalzustand für Taster gedrückt

Const Key_bl_num = 1                                        ' Nummerierung der Tasten - Taste 1 ist BLAU
Const Key_rt_num = 2                                        ' Nummerierung der Tasten - Taste 2 ist ROT
Const Key_gn_num = 3                                        ' Nummerierung der Tasten - Taste 3 ist GRUEN
Const Key_ge_num = 4                                        ' Nummerierung der Tasten - Taste 4 ist GELB

' ----- LCD -----

' Anmerkung: Wert von 35 ist der beste Wert welcher durch Versuche ermittelt wurde!!
Const Lcd_kontrast_default = 35                             ' LCD-Default-Kontrast

' Anmerkung: Wert von 70 ist der beste Wert welcher durch Versuche ermittelt wurde!!
Const Lcd_helligkeit_default = 70                           ' LCD-Default-Helligkeit

Const Lcd_helligkeit_aus = 0                                ' Wert für Display aus
Const Lcd_abschaltzeit = 10                                 ' Defaultwert auf 10 Sekunden festgelegt

Const Lcd_beleuchtung_status_ein = 1                        ' Statuswert für LCD Beleuchtung ein
Const Lcd_beleuchtung_status_aus = 0                        ' Statuswert für LCD Beleuchtung aus

Const Lcd_shift_speed = 500                                 ' Scrollgeschwindigkeit für Text-Shift
Const Lcd_countdown_speed = 250                             ' Countdowngeschwindigkeit nach Spielstart

' ----- EEPROM -----
Const Ee_default_version_value = 1                          ' Version für persistente Daten

' ----- SOUND -----
Const Sound_ton1 = 637                                      ' Tonlage BLAU Ton
Const Sound_dauer1 = 262                                    ' Tondauer BLAU Ton

Const Sound_ton2 = 483                                      ' Tonlage ROT Ton
Const Sound_dauer2 = 330                                    ' Tondauer ROT Ton

Const Sound_ton3 = 425                                      ' Tonlage GRÜN Ton
Const Sound_dauer3 = 392                                    ' Tondauer GRÜN Ton

Const Sound_ton4 = 337                                      ' Tonlage GELB Ton
Const Sound_dauer4 = 494                                    ' Tondauer GELB Ton

Const Sound_falschton = 715                                 ' Tonlage FALSCH Ton
Const Sound_falschdauer = 233                               ' Tondauer FALSCH Ton

' ----- ADC: Batteriespannung -----
Const Adc_channel_number = 0                                ' Auswahl von ADC0 an dem Batteriespannung gemessen werden soll

' ----- Spielsteuerung ----

Const Game_anzahl_text = 100                                ' Anzahl der Text im DATA Bereich

Const Game_mode_idle = 0                                    ' Konstante für Spielsteuerung - Idle Mode
Const Game_mode_start = 1                                   ' Konstante für Spielsteuerung - Start Mode
Const Game_mode_spiel = 2                                   ' Konstante für Spielsteuerung - Response Mode
Const Game_mode_aktion = 3                                  ' Konstante für Spielsteuerung - Request Mode

Const Game_play_sensolevel_speed = 250                      ' Geschwindigkeit mit der Sensolevel abgespielt werden woll in msec
Const Game_play_winsound_speed = 30                         ' Geschwindigkeit des Abspielens es Winsounds in msec

Const Game_play_pause_delay = 500                           ' Delaygeschwindigkeit während Spiel zwischen Tasten und Feedback  in msec
Const Game_play_response_delay = 100                        ' Delayzeit nach Request-Ausgabe bis Response in msec

Const Game_play_loop_counter = 200                          ' Schleifenanzahl bildet Timeout-Zeit
'Const Game_play_loop_counter = 800                          ' Schleifenanzahl bildet Timeout-Zeit - for debug only

Const Game_play_timeout_delay = 10                          ' Delay in Tastenabfrage für Timeout in msex
Const Game_timeout_delay = 2                                ' Delay wie lange Timeout angezeigt werden soll in sec

Const Game_show_finaly_delay = 2                            ' Delayzeit für Ausgabe der Finalen Koordinaten in sec

Const Game_play_level_pause = 1000                          ' Delayzeit zwischen erolgreicher richtiger Eingabe und nextem Level in msec

' ----- LED's -----
Const Led_speed_testroutine = 100                           ' Geschwindigkeit der LED-Testroutine in msec

'------------------------------------------------------------------------------
' Definition von Variablen und Datentypen
'------------------------------------------------------------------------------

' ----- Temporäre Hilfsvariablen -----
Dim Temp_index As Byte                                      ' Temporäre Zahlvariable
Dim Temp_byte_1 As Byte                                     ' Temporäre Byte Variable 1
Dim Temp_byte_2 As Byte                                     ' Temporäre Byte Variable 2
Dim Temp_byte_3 As Byte                                     ' Temporäre Byte Variable 3

Dim Temp_word_1 As Word                                     ' Temporäre Word Variable 1
Dim Temp_word_2 As Word                                     ' Temporäre Word Variable 2
Dim Temp_word_3 As Word                                     ' Temporäre Word Variable 2

Dim Temp_string_1 As String * 8                             ' Temporäre String Variable mit 8 Zeichen + Delimiter

' ----- System -----
Dim Sectick_counter As Word                                 ' Globaler Sekundenzähler

' ----- Arbeitsvariablen für Spieleablauf -----
Dim Game_ablaufstatus As Byte                               ' Arbeitsvariable für System-Status

' ----- Variablen für LCD-Display -----
Dim Lcd_kontrastwert As Byte                                ' Arbeitsvariable für Kontrastwert
Dim Lcd_helligkeit As Byte                                  ' Arbeitsvariable für Displayhelligkeit
Dim Lcd_abschaltcounter As Word                             ' Variable für Abschaltzeitpunkt
Dim Lcd_beleuchtung_status As Byte                          ' Arbeitsvariable für Zustand der Hintergrundbeleuchtugn

' ----- EEPROM -----
Dim Ee_data_version_value As Eram Byte At &H0000            ' EEPROM Datenstruktur internes EEPROM - Init-Index / Version
Dim Ee_data_bypass_counter As Eram Word At &H0001           ' EEPROM Datenstruktur internes EEPROM - Counter
Dim Ee_version_value As Byte                                ' BYTE Arbeitsvariable für Daten-Version
Dim Ee_bypass_counter As Word                               ' WORD Arbeitsvariable für Bypasscounter

' ----- GAME: Spielsteuerung -----
Dim Game_senso(10) As Byte                                  ' Matrix für Sensowerte
Dim Game_sensolevel As Byte                                 ' Index-Counter für Spielschleife

' ----- ADC: Batteriespannung -----
' Batteriespannung wird zwar nicht überwacht aber für ___seed verwendet
Dim Adc_channel As Byte                                     ' Arbeitsvariable für ADC-Kanalauswahl

'------------------------------------------------------------------------------
' Prototyping
'------------------------------------------------------------------------------

' ----- LCD und Print -----
Declare Sub Lcd_print_level(byval Value As Byte)            ' Funktion zum Schreiben der Rundezahl auf dem Display

' ----- KEY -----
Declare Function Key_check_all_key() As Byte                ' Prototyp für Funktion zur Prüfung einer Taste
Declare Function Key_check_any_key() As Byte                ' Prototyp für Funktion zur Prüfung beliebiger Tasten

' ----- GAME -----
Declare Sub Game_eingabe(byval Value_key As Byte , Byval Value_gameplay As Byte )       ' Funktion zur Auswertung der Tasteneingabe
Declare Sub Game_play_zu_langsam(byval Value_gameplay As Byte )       ' Funktion zur Ausgabe von ZU LANGSAM

'------------------------------------------------------------------------------
' Konfiguration und Basiseinstellungen (Projekt und Testumgebung)
'------------------------------------------------------------------------------

' --------------------------------- CONFIG ------------------------------------

' ----- Timer -----

' Konfiguration eines Timers für 1 Sekunden Timer-Tick (Scheduler und Alive)
Config Timer1 = Timer , Prescale = 256                      ' Timer 1 verwenden
On Timer1 Sekunden_tick                                     ' Interrupt Routine
Timer1 = Timervorgabe
Enable Timer1                                               ' Interrupt für Sekunden-Tack freigeben

' Konfiguration Timer 2 für Hardware-PWM an OC2 (D.7)
Config Timer2 = Pwm , Prescale = 128 , Compare Pwm = Clear Up       ' Timer 2 verwenden
Enable Timer2                                               ' Interrupt für PWM Timer 2 freigeben

' ----- LCD Display -----

' Konfiguration LCD Display
Config Lcdpin = Pin , Db4 = Lcd_bit_0 , Db5 = Lcd_bit_1 , Db6 = Lcd_bit_2 , Db7 = Lcd_bit_3 , E = Lcd_e , Rs = Lcd_rs
Config Lcd = 16 * 1 , Chipset = Dogm162v5                   ' DOG-M Treiber laden
Config Lcdbus = 4                                           ' LCD arbeitet über 4-Bit

Gosub Lcd_init                                              ' LCD grundlegend initialisieren

'                   12345678
Locate 1 , 1 : Lcd "********"

' Definition benutzerdefinierter Zeichen
Deflcdchar 0 , 32 , 27 , 32 , 4 , 4 , 17 , 17 , 14          ' Smily lachen
Deflcdchar 1 , 27 , 32 , 4 , 4 , 32 , 14 , 17 , 17          ' Smily weinen

' ----- ADC: Batterieueberwachung -----
' Konfiguration ADC Single-Mode und automatische Prescaler Setting
' Der Single-Mode wir bei BASCOM in Verbindung mit der Funktion GETADC() verwendet
' Der Prescaler teilt den internen Tackt durch 2, 4, 8,16,32,64 or 128 da der ADC
' einen Takt zwischen 50-200 kHz benötigt.
' Das AUTO Feature von BASCOM, setzt automatisch die höchste mögliche Taktrate
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc

' ------------------------------- Port's und Pin's ----------------------------

' ----- LED-Konfigurationen -----
Config Alive_led_pin = Output                               ' GPIO für Alive-LED ist Output

' ----- LED-Konfigurationen -----
Config Led_blau_pin = Output                                ' GPIO für blaue LED auf Output schalten
Config Led_gruen_pin = Output                               ' GPIO für grüne LED auf Output schalten
Config Led_rot_pin = Output                                 ' GPIO für rote LED auf Output schalten
Config Led_gelb_pin = Output                                ' GPIO für blaue LED auf Output schalten

' ----- KEY-Tasten-Konfiguration -----
Config Key_taster1_pin = Input                              ' GPIO für Taste 1 auf Inupt schalten und PullUp aktivieren
Key_taster1 = Pullup_ein

Config Key_taster2_pin = Input                              ' GPIO für Taste 2 auf Inupt schalten und PullUp aktivieren
Key_taster2 = Pullup_ein

Config Key_taster3_pin = Input                              ' GPIO für Taste 3 auf Inupt schalten und PullUp aktivieren
Key_taster3 = Pullup_ein

Config Key_taster4_pin = Input                              ' GPIO für Taste 4 auf Inupt schalten und PullUp aktivieren
Key_taster4 = Pullup_ein

' ------------------------------ Variablen und Werte --------------------------

' ----- LEDs -----
Led_blau = Led_aus
Led_gruen = Led_aus
Led_rot = Led_aus
Led_gelb = Led_aus

' ----- System -----
Sectick_counter = 0                                         ' Globaler Sekundenzähler initialisieren

' ----- LCD-Display -----
Lcd_kontrastwert = Lcd_kontrast_default                     ' Kontrastwert
Lcd_helligkeit = Lcd_helligkeit_default                     ' Displayhelligkleit

' ----- ADC_ Batteriespannungsueberwachung -----
Adc_channel = Adc_channel_number                            ' Spannungsteiler zur Batterispannungsmessung hängt an ADC0

' ----- Spielesteuerung -----
Game_ablaufstatus = Game_mode_idle                          ' Steuervariable für Spielablaufsteuerung

' In Abhängigkeit der Konstante Traceausgabe schreiben
#if Game_testmodus
   Print "Set Game Mode = 0 - Neustart"
#endif

'------------------------------------------------------------------------------
' Und los gehts, hier noch die Restarbeiten
'------------------------------------------------------------------------------

' In Abhängigkeit der Konstante Traceausgabe schreiben
#if Main_testmodus
   Print ""
   Print ""
   Print "----------------------------------------"
#endif

' ----- Freigabe aller Interrupts ----
Enable Interrupts                                           ' Damit auch Empfang von Daten über Buffer

' ---------------------------------- Gosub's ----------------------------------

Gosub Lcd_kontrast_set                                      ' LCD Kontrast einstellen

Gosub Lcd_helligkeit_set                                    ' Displayhelligkeit einstellen
Lcd_beleuchtung_status = Lcd_beleuchtung_status_ein         ' Hintergrundbeleuchtung ist EIN

Gosub Adc_check_batterie                                    ' Batteriespannung überprüfen

Gosub Ee_init                                               ' Persistente Daten aus EEPROM auslesen

' #############################################################################
'
'                             Hauptprogramm Senso
'
' #############################################################################

' ----- Bypassmodus -----

' An dieser Stelle wird sofort der Status für den Bypassmodus abgefragt.
' Der Bypassmodus kann erreicht werden indem alle Tasten gleichzeitig betätigt
' und dann der Reihe nach 1-4 gedrückt werden

' Sind alle Tasten betätigt?
Temp_byte_1 = Pind And Key_all_key

If Temp_byte_1 = Key_all_key_pressed Then

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Bypass_testmodus
      Print "Bypass Step 1 erkannt"
   #endif

   Gosub Game_bypass_mode                                   ' Bypassmode

   Cls

   ' Nicht weitermachen bevor Taste losgelassen
   Do
      Temp_byte_1 = Key_check_all_key()

   Loop Until Temp_byte_1 = False

   ' So tun als wenn nichts gewesen wäre und weiter im Spiel

End If

' In Abhängigkeit der Konstante Traceausgabe schreiben
#if Main_testmodus
   Print "** OK, let's GO **"
#endif

' LED Testroutine
Gosub Led_test_routine

' Soundcheck
Sound Speaker , Sound_ton2 , Sound_dauer2
Sound Speaker , Sound_ton3 , Sound_dauer3
Sound Speaker , Sound_ton2 , Sound_dauer2

' Begrüßungstext ausgeben bis Taste betätigt wird
Cls
Locate 1 , 1 : Lcd "Willkommen zu *SENSO* - GC2ACC4"
Do
   Waitms Lcd_shift_speed
   Shiftlcd Left

   Temp_byte_2 = Key_check_all_key()

Loop Until Temp_byte_2 = True

' Achtung: shiftlcd lässt Cursor willkürlich im Speicher stehen.
'          Damit wieder geziel auf Position 1,1 gearbeitet werden kann ist
'          Initlcd notwendig. Danach muss aber nochmals Kontrast eingestellt
'          werden

Gosub Lcd_init                                              ' When the display is initialized, the display content is cleared also.
Gosub Lcd_kontrast_set                                      ' Kontrast nochmals einstellen, geht durch Initlcd verloren

' Bildschirm löschen und Start-Aufforderung auf Display ausgeben
Cls
Locate 1 , 1 : Lcd Chr(&B01111110) ; "  START"

' Spielablaufvariable wurde mit IDLE vorbelegt, damit geht Spiel in
' Warteposition und aktiviert ggf. auch Bildschirm-Schoner

' Logik für Abschaltung Hintergrundbeleuchtung "aufziehen"
Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

' ----------------------------------------------
' ----- Hier ist die Programmhauptschleife -----
' ----------------------------------------------

' Erklärung Spielstati - Game_ablaufstatus:
' 0 = Game_mode_idle
'     Spiel macht eigentlich nichts. Es wird ggf. die Hintergrundbeleuchtung
'     abgeschaltet und auf eine Tasteneingabe gewartet

' 1 = Game_mode_start
'     Spiel wurde neu gestartet oder nach erfolgreichem Spiel wiederholt.
'     Status 0 bedeutet es wurde die Start-Taste erkannt mit der das Spiel
'     gestartet werden kann. Es müssen alle Arbeitsvorbereitungen getroffen
'     werden und dann wird Spielstatus weitergeschaltet

' 2 = Game_mode_spiel

' 3 = Game_mode_aktion

Do                                                          ' Hauptschleife

   ' -------------------- Testaufgaben waehrend Entwicklung -------------------

   ' ------------------------------ Systemaufgaben ----------------------------

   ' --------------------------- Spielsteuerung -------------------------------

   ' -----
   ' ----- Spiel - Idle - Spiel idelt so vor sich hin und macht nichts ----
   ' -----

   If Game_ablaufstatus = Game_mode_idle Then

      ' Nur im Idle gibt es die Möglichkeit, dass das Spiel die Hintergrund-
      ' beleuchtung des Display abschalten kann, daher muss auch hier der
      ' entsprechende Ablauf erfolgen

      ' Prüfen ob Sekundencounter für Hintergrundbeleuchtung abgelaufen ist
      If Lcd_abschaltcounter = Sectick_counter Then

         ' JA -> Hintergrundbeleuchtung abschalten und Strom sparen
         Gosub Lcd_beleuchtung_aus
         Lcd_beleuchtung_status = Lcd_beleuchtung_status_aus       ' Hintergrundbeleuchtung ist AUS

         ' Durch Verringerung des Counters wird verhindert dass Funktion mehrfach angesprungen wird.
         Decr Lcd_abschaltcounter

      End If                                                ' LCD Abschaltzeitpunkt erreicht

      ' Prüfen ob der Bildschirm abgeschaltet ist und ggf. auf Taste überprüfen
      ' um Bildschirm wieder ein zu schalten
      If Lcd_beleuchtung_status = Lcd_beleuchtung_status_aus Then

         ' Ja, Bildschirm ist aus

         ' Überprüfung ob irgend eine Taste betätigt wurde
         Temp_byte_1 = Key_check_all_key()
         If Temp_byte_1 = True Then

            ' Ja, Bildschirm ist aus .,.. es darf nichts weiter passieren außer Bildschirm an
            Gosub Lcd_beleuchtung_ein                       ' Hintergrundbeleuchtung einschalten
            Lcd_beleuchtung_status = Lcd_beleuchtung_status_ein       ' Hintergrundbeleuchtung ist EIN

            ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen"
            Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

         End If                                             ' Tastenprüfung

      Else                                                  ' Bildschirmprüfung

         ' Nein, Bildschirm ist nicht aus und daher darf das Spiel erneut
         ' gestartet werden

         ' Überprüfung ob Spielstartbedingung "Blaue Taste betätigen" gegeben ist

         ' Tasten einlesen
         Temp_byte_1 = Key_check_any_key()

         'Prüfen ob irgend eine Taste gedrückt wurde damit abschaltcounter erhöht werden kann
         Temp_byte_2 = Temp_byte_1 And Key_all_key
         If Temp_byte_2 <> Key_all_key Then

            ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen"
            Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

            ' Überprüfen ob zufällig auch die blaue Taste betätigt wurde
            Temp_byte_2 = Temp_byte_1 And Key_bl__key
            If Temp_byte_2 <> Key_bl__key Then

               ' Ja, Blaue Taste wurde betätigt, damit kann Spiel gestartet werden
               Game_ablaufstatus = Game_mode_start

            End If                                          ' Blaue Taste

         End If                                             ' Tastenauswertung

      End If                                                ' Bildschimbeleuchtung aus ja/nein

   End If                                                   ' Idle Mode

   ' -----
   ' ----- Spiel - Start - Vorbereitungsarbeiten ----
   ' -----

   If Game_ablaufstatus = Game_mode_start Then

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Game_testmodus
         Print
         Print "-- Entering Game_mode_start"
         Print "Zufallszahlen laden"
      #endif

      Gosub Game_lade_sensowerte

      ' Sensolevel neu setzen da Spiel neu begonnen wird
      Game_sensolevel = 1

      ' Ablaufsteuerung Spiel weiterschalten
      Game_ablaufstatus = Game_mode_spiel

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Game_testmodus
         Print "Set Game Mode = 1 - Spiel"
      #endif

      Cls                                                   ' Bildschirm löschen

      ' Nachdem nun der Start des Spiel eingeleitet wurde wir noch ein Countdown
      ' 8-1 abgespielt
      For Temp_byte_1 = 1 To 8 Step 1
         Temp_byte_2 = 9 - Temp_byte_1
         Lcd Temp_byte_2;
         Waitms Lcd_countdown_speed
      Next Temp_byte_1

      Cls                                                   ' Bildschirm löschen

      ' Spielstart-Wartezeit
      Waitms Game_play_pause_delay

   End If                                                   ' Game_mode_start

   ' -----
   ' ----- Spiel - Request - Spiel gibt zu betätigende Tasten vor (komplette Serie) -----
   ' -----

   If Game_ablaufstatus = Game_mode_spiel Then

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Game_testmodus
         Print
         Print "Entering Game_mode_spiel"
         Print "Sensolevel ist " ; Game_sensolevel
      #endif

      Gosub Game_play_sensolevel

      ' Nun ist eine Benutzereingabe gefordert - Ablaufsteuerung Spiel weiterschalten
      Game_ablaufstatus = Game_mode_aktion

      ' Verzögerungs-Wartezeit bis Response
      Waitms Game_play_response_delay

   End If                                                   ' Game_mode_spiel

   ' -----
   ' ----- Spiel - Response - Spiel wartet auf Benutzereingabe und macht Auswertung -----
   ' -----

   If Game_ablaufstatus = Game_mode_aktion Then

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Game_testmodus
         Print
         Print "Entering Game_mode_aktion"
         Print "Sensolevel ist " ; Game_sensolevel
      #endif

      ' Falls Flag für Debuging gesetzt debugausgaben ausgeben
      #if Game_testmodus
         Print "Sensowerte sind: " ;
         For Temp_byte_1 = 1 To 10 Step 1
            Print Game_senso(temp_byte_1) ; " " ;
         Next Temp_byte_1
         Print " *"
      #endif

      ' In einer Gesamtschleife von 1-10 wird der Spieler nun aufgefordert die
      ' entsprechenden Tasten zu betätigen. Die EIngabe wir unmittelbar kontrolliert
      ' und die Zeit überwacht.

      For Temp_byte_3 = 1 To Game_sensolevel Step 1

         ' In einer Schleife wird geprüft, ob nun eine Taste betätigt wird.
         ' Die Schleife bildet gleichzeitig nach Ablauf den Timeout der zur
         ' Fehlerausgabe und zum Neustart des Spiels führt.

         ' Hier eventuell nochmals zur Sicherheit prüfen dass keine Taste betätigt ist
         ' Do
         '   Temp_byte_1 = Key_check_all_key()
         ' Loop Until Temp_byte_1 = False

         Temp_word_1 = 1                                    ' Timeoutcounter zurücksetzen
         Temp_byte_1 = False                                ' Verwendung al Error-Flag
         Temp_byte_2 = False                                ' Schleifenflag für Auswertung

         Do

            ' Auf Taste 1 prüfen
            If Key_taster1_pin = Key_pressed Then

               ' Ggf. Traceausgabe schreiben - abhängig von Compilerschalter
               #if Key_testmodus
                  Print "Key 1 BLAU pressed"
               #endif

               ' Auswertung der Eingabe aufrufen
               Call Game_eingabe(key_bl_num , Temp_byte_3 )

               ' Schleife kann verlassenwerden, es muss nicht auf Timeout gewartet werden da Taste betätigt
               Temp_byte_2 = True

            End If                                          ' Prüfung Taste 1

            ' Auf Taste 2 prüfen
            If Key_taster2_pin = Key_pressed Then

               ' Ggf. Traceausgabe schreiben - abhängig von Compilerschalter
               #if Key_testmodus
                  Print "Key 1 ROT pressed"
               #endif

               ' Auswertung der Eingabe aufrufen
               Call Game_eingabe(key_rt_num , Temp_byte_3 )

               ' Schleife kann verlassenwerden, es muss nicht auf Timeout gewartet werden da Taste betätigt
               Temp_byte_2 = True

            End If                                          ' Prüfung Taste 2

            ' Auf Taste 3 prüfen
            If Key_taster3_pin = Key_pressed Then

               ' Ggf. Traceausgabe schreiben - abhängig von Compilerschalter
               #if Key_testmodus
                  Print "Key 3 GRUEN pressed"
               #endif

               ' Auswertung der Eingabe aufrufen
               Call Game_eingabe(key_gn_num , Temp_byte_3 )

               ' Schleife kann verlassenwerden, es muss nicht auf Timeout gewartet werden da Taste betätigt
               Temp_byte_2 = True

            End If                                          ' Prüfung Taste 3

            ' Auf Taste 4 prüfen
            If Key_taster4_pin = Key_pressed Then

               ' Ggf. Traceausgabe schreiben - abhängig von Compilerschalter
               #if Key_testmodus
                  Print "Key 4 GELB pressed"
               #endif

               ' Auswertung der Eingabe aufrufen
               Call Game_eingabe(key_ge_num , Temp_byte_3 )

               ' Schleife kann verlassenwerden, es muss nicht auf Timeout gewartet werden da Taste betätigt
               Temp_byte_2 = True

            End If                                          ' Prüfung Taste 4

            Waitms Game_play_timeout_delay
            Incr Temp_word_1

         Loop Until Temp_word_1 > Game_play_loop_counter Or Temp_byte_2 = True

         ' Wenn Funktion hier ankommt gibt es mehrere Möglichkeiten ...
         ' - Es wurde eine Taste gedrückt und die war richtig .... alles OK
         ' - Es wurde eine Taste gedrückt und die war falsch ....
         ' - Es wurde keine Taste gedrückt .... Timeout => Schleifenflag = False

         ' Wurde keine Taste betätigt?
         If Temp_byte_2 = False Then

            ' Ja, es wurde keine Taste betätigt

            Temp_byte_1 = True                              ' Fehlerflag setzen

            ' Timeout-Melodie spiele und Spiel zurücksetzen
            Call Game_play_zu_langsam(temp_byte_3)

            ' Bildschirm löschen und Start-Aufforderung auf Display ausgeben
            Cls
            Locate 1 , 1 : Lcd Chr(&B01111110) ; "  START"

            Game_ablaufstatus = Game_mode_idle

            ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen"
            Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

            Exit For                                        ' FOR-Schleife fühzeitig verlassen

         End If                                             ' Taste betätigt

         ' Wurde falsche Taste betätigt?
         If Game_ablaufstatus = Game_mode_idle Then

               ' Ja es wurde eine falsche Taste betätigt.
               ' Behandlung ist aber bereits in Funktion erfolgt, hier muss nur
               ' noch FOR-Schleife abgebrochen werden

               Temp_byte_1 = True                           ' Fehlerflag setzen

               Exit For

          End If                                            ' Falsche Taste

      Next Temp_byte_3                                      ' Hauptschleife über Game_sensolevel 1-10

      ' Nun muss noch geprüft werden ob das Spiel bereits erfolgreich
      ' mit 10 Durchläufen abgeschlossen ist ... wenn kein Fehler aufgetreten ist.

      If Temp_byte_1 = False Then

         If Game_sensolevel < 10 Then

            Game_ablaufstatus = Game_mode_spiel             ' Zurück auf Ausgabe
            Incr Game_sensolevel                            ' Sensolevel erhöhen

            ' In Abhängigkeit der Konstante Traceausgabe schreiben
            #if Game_testmodus
               Print "Spielende noch nicht erreicht"
               Print "Incr Sensolevel ist " ; Game_sensolevel
            #endif

            Waitms Game_play_level_pause

         Else

            Gosub Game_play_winwin                          ' Gewinnersound spielen

            Waitms Game_play_pause_delay                    ' Wartezeit Übergang Playsound - Anszeige finale Koordinaten

            Gosub Lcd_show_final_koordinates                ' Finale Koordinaten ausgeben

            ' Bildschirm löschen und Start-Aufforderung auf Display ausgeben
            Cls

            ' Nicht weitermachen bevor Taste losgelassen
            Do
               Temp_byte_1 = Key_check_all_key()

            Loop Until Temp_byte_1 = False

            Locate 1 , 1 : Lcd Chr(&B01111110) ; "  START"

            Game_ablaufstatus = Game_mode_idle

            ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen"
            Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

         End If                                             ' Spielweiterschaltung

      End If                                                ' kein Fehler aufgetreten

   End If                                                   ' Game_mode_aktion

Loop                                                        ' Hauptschleife

'## End Hauptprogramm #########################################################

End

'******************************************************************************
' Interruptroutinen
'******************************************************************************

'------------------------------------------------------------------------------
' Interrupt-Service-Routine (Timer1): Sekunden_tick
'
' Routine zur Auswertung des Timer Interrupts
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' Sectick_counter = Variable für den Sekundencounter
'------------------------------------------------------------------------------
Sekunden_tick:

   ' ----- Programmcode -----

   Timer1 = Timervorgabe                                    ' Timer neu laden
   Toggle Alive_led                                         ' Alive-LED toggeln lassen

   ' Timervariable erhöhen
   Incr Sectick_counter

Return
'-- End Sekunden_tick  --------------------------------------------------------

'******************************************************************************
' Subroutinen
'******************************************************************************

' ***************
' * LCD-Display *
' ***************

'------------------------------------------------------------------------------
' LCD - Subroutine: Lcd_print_level
'
' Subroutine schreibt entsprechende Levelzahl auf das Display
'
' Parameter:    Value = Levelzahl
' Rückgabewert: keine
'
' Globale Variable:
' --
'------------------------------------------------------------------------------
Sub Lcd_print_level(byval Value As Byte)

   ' ----- Programmcode -----

   Cls
   Temp_string_1 = Str(value)
   Temp_string_1 = Format(temp_string_1 , "00")
   Locate 1 , 4 : Lcd Temp_string_1

End Sub
'-- End Lcd_print_level -------------------------------------------------------

' ********
' * GAME *
' ********

'------------------------------------------------------------------------------
' GAME - Subroutine: Game_eingabe
'
' Subroutine verarbeitet die übergebene Taste für den Spielablauf
'
' Parameter:    Value_key      = Nummer der betätigten Taste
'               Value_gameplay = Erreichstes Level
' Rückgabewert: keine
'
' Globale Variable:
' --
'------------------------------------------------------------------------------
Sub Game_eingabe(byval Value_key As Byte , Byval Value_gameplay As Byte )

   ' ----- lokale Variablen -----
   Local Temp_value As Byte
   Local Temp_senso_loop As Byte

   ' ----- Programmcode -----

   Temp_value = Game_senso(value_gameplay )

   ' Falls Flag für Debuging gesetzt debugausgaben ausgeben
   #if Game_testmodus
      Print "Auswertung: SOLL = " ; Temp_value ; " - IST = " ; Value_key
   #endif

   ' Prüfen ob betätigte Taste richtig war oder nicht
   If Value_key = Temp_value Then

      ' Ja, Eingabe war richtig

       Select Case Value_key
         Case 1:                                            ' LED und Taste 1 = BLAU
           Led_blau = Led_ein
           Sound Speaker , Sound_ton1 , Sound_dauer1
           Led_blau = Led_aus
         Case 2:                                            ' LED und Taste 1 = ROT
           Led_rot = Led_ein
           Sound Speaker , Sound_ton2 , Sound_dauer2
           Led_rot = Led_aus
         Case 3:                                            ' LED und Taste 1 = GRUEN
           Led_gruen = Led_ein
           Sound Speaker , Sound_ton3 , Sound_dauer3
           Led_gruen = Led_aus
         Case 4:                                            ' LED und Taste 1 = GELB
           Led_gelb = Led_ein
           Sound Speaker , Sound_ton4 , Sound_dauer4
           Led_gelb = Led_aus
       End Select

      #if Game_testmodus
         Print "++ Eingabe war richtig"
      #endif

   Else                                                     ' Tastenprüfung

      ' Nein, Eingabe war falsch

      ' Verlierersound spielen
      Gosub Game_play_lose_sound
      Wait 2

      ' Game-Spielestatus zurücksetzen
      Game_ablaufstatus = Game_mode_idle

      ' Bildschirm löschen und Start-Aufforderung auf Display ausgeben
      Cls
      Locate 1 , 1 : Lcd Chr(&B01111110) ; "  START"

      ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen"
      Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit

      #if Game_testmodus
         Print "++ Eingabe war falsch"
      #endif

   End If                                                   ' Tastenprüfung

End Sub
'-- End Lcd_print_level -------------------------------------------------------

'------------------------------------------------------------------------------
' GAME - Subroutine: Game_play_zu_langsam
'
' Subroutine gibt abhängig vom Sensolevel die zugehörige "Zu LANGSAM" Sequnz
' aus
'
' Parameter:    Value_gameplay = Erreichtes Level
' Rückgabewert: keine
'
' Globale Variable:
' --
'------------------------------------------------------------------------------
Sub Game_play_zu_langsam(byval Value_gameplay As Byte )

   ' ----- lokale Variablen -----
   Local Temp_value As Byte
   Local Temp_loop_count As Byte

   ' ----- Programmcode -----

   Temp_value = Game_senso(value_gameplay )

   ' Meldung auf Display ausgeben
   Cls
   '    12345678
   Lcd "Timeout "

   For Temp_loop_count = 1 To 6 Step 1

       Select Case Temp_value

         Case 1:                                            ' LED und Taste 1 = BLAU
           Led_blau = Led_ein
           Sound Speaker , Sound_ton1 , Sound_dauer1
           Led_blau = Led_aus

         Case 2:                                            ' LED und Taste 1 = ROT
           Led_rot = Led_ein
           Sound Speaker , Sound_ton2 , Sound_dauer2
           Led_rot = Led_aus

         Case 3:                                            ' LED und Taste 1 = GRUEN
           Led_gruen = Led_ein
           Sound Speaker , Sound_ton3 , Sound_dauer3
           Led_gruen = Led_aus

         Case 4:                                            ' LED und Taste 1 = GELB
           Led_gelb = Led_ein
           Sound Speaker , Sound_ton4 , Sound_dauer4
           Led_gelb = Led_aus

       End Select

       Waitms Game_play_sensolevel_speed

   Next Temp_loop_count                                     ' Schleife Anzahl Timeout-Signale

   Wait Game_timeout_delay                                  ' Wartezeit bis weiter

End Sub
'-- End Game_play_zu_langsam --------------------------------------------------

'******************************************************************************
' Functions
'******************************************************************************

' *********
' * KEY's *
' *********

'------------------------------------------------------------------------------
' KEY - Funktion: Key_check_all_key()
' Funktion prüft ob eine Taste betätigt wurde und liefert den boolschen Wert
' des Ereignis zurück. Wurde eine Taste betätigt wartet die Funktion eine
' definierte Zeit und prüft erneut ob die Taste bereits losgelassen wurde.
' So werden Mehrfachauslösungen einer Funktion verhindert
'
' Parameter:    keine
' Rückgabewert: Bytewert = TRUE  - es wurde eine Taste erkannt
'                          FALSE - es wurde keine Taste erkannt
' Globale Variablen: keine
'------------------------------------------------------------------------------
Function Key_check_all_key() As Byte

   ' ----- lokale Variablen -----
   Local Temp_value As Byte
   Local Temp_return_value As Byte

   ' ----- Programmcode -----

   ' Returnvariable vorbelegen
   Temp_return_value = False

   ' Tasten einlesen
   Temp_value = Pind And Key_all_key

   ' Prüfen ob Taste betätigt wurde
   If Temp_value <> Key_all_key Then

      ' Ja, Taste wurde betätigt, daher 20ms warten und auf Loslassen der Taste prüfen
      Waitms Key_entprellzeit

      Do
            Temp_value = Pind And Key_all_key
      Loop Until Temp_value = Key_all_key

      Temp_return_value = True

   End If                                                   ' Tastenprüfung

   ' Ergebnis an Rückgabewert übergeben
   Key_check_all_key = Temp_return_value

End Function
'-- End Key_check_all_key -----------------------------------------------------

'------------------------------------------------------------------------------
' KEY - Funktion: Key_check_any_key()
' Funktion prüft ob eine Taste betätigt wurde und liefert den Byte-Wert des
' kompletten eingelesenen Ports als Ereignis zurück.
' Wurde eine Taste betätigt wartet die Funktion eine
' definierte Zeit und prüft erneut ob die Taste bereits losgelassen wurde.
' So werden Mehrfachauslösungen einer Funktion verhindert
'
' Parameter:    keine
' Rückgabewert: Bytewert des gesamten Ports --> Auswertung muss außerhalb
'                                               der Funktion erfolgen.
' Globale Variablen: keine
'------------------------------------------------------------------------------
Function Key_check_any_key() As Byte

   ' ----- lokale Variablen -----
   Local Temp_value_1 As Byte
   Local Temp_value_2 As Byte

   ' ----- Programmcode -----

   ' Tasten einlesen
   Temp_value_1 = Pind And Key_all_key

   ' Prüfen ob Taste betätigt wurde
   If Temp_value_1 <> Key_all_key Then

      ' Ja, Taste wurde betätigt, daher 20ms warten und auf Loslassen der Taste prüfen
      Waitms Key_entprellzeit

      Do
            Temp_value_2 = Pind And Key_all_key
      Loop Until Temp_value_2 = Key_all_key

   End If                                                   ' Tastenprüfung

   ' Ergebnis an Rückgabewert übergeben
   Key_check_any_key = Temp_value_1

End Function
'-- End Key_check_any_key -----------------------------------------------------

'******************************************************************************
' GOSubroutinen
'******************************************************************************

' ********
' * GAME *
' ********

'------------------------------------------------------------------------------
' GAME - Gosub-Routine: Game_lade_sensowerte
'
' Routine ermittelt via Zufallszahl den im Spiel zu verwendenden Pattern für
' die Sensowerte. Diese wurden während der Entwicklung offline erzeugt.
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' Game_sensowert = Array 1 - 10 der jeweiligen Senso-Werte
'------------------------------------------------------------------------------
Game_lade_sensowerte:

   ' ----- Programmcode -----

   ' Zufallszahl ermitteln
   Temp_byte_1 = Rnd(game_anzahl_text )                     ' Random bei z.B. 40 = 0-39

   ' Falls Flag für Debuging gesetzt debugausgaben ausgeben
   #if Game_testmodus
      Print "Zufallszahl: " ; Temp_byte_1
   #endif

   Temp_byte_1 = Temp_byte_1 * 2                            ' Korrektur Zufallszahl auf Doppelpaare

   ' Sensowerte Doppelpaare laden
   Temp_word_1 = Lookup(temp_byte_1 , Spielkombinationen_data)
   Incr Temp_byte_1
   Temp_word_2 = Lookup(temp_byte_1 , Spielkombinationen_data)

   ' Falls Flag für Debuging gesetzt debugausgaben ausgeben
   #if Game_testmodus
      Print "Wert1: " ; Temp_word_1 ; "  -  Wert2: " ; Temp_word_2
   #endif

   ' Extrahieren von Einer-Zener-Hunderter-Tausender-Zehntausender und Übernahme
   ' in Senso-Zahlenarray
   For Temp_index = 5 To 1 Step -1

      ' Sensowerte Block 1 zerlegen
      Temp_word_3 = Temp_word_1 Mod 10
      Game_senso(temp_index) = Temp_word_3
      Temp_word_1 = Temp_word_1 - Temp_word_3
      Temp_word_1 = Temp_word_1 / 10

      ' Sensowerte Block 2 zerlegen
      Temp_word_3 = Temp_word_2 Mod 10
      Game_senso(temp_index + 5) = Temp_word_3
      Temp_word_2 = Temp_word_2 - Temp_word_3
      Temp_word_2 = Temp_word_2 / 10

   Next Temp_index                                          ' Indexschleife

   ' Falls Flag für Debuging gesetzt debugausgaben ausgeben
   #if Game_testmodus
      Print "Sensowerte sind: " ;
      For Temp_byte_1 = 1 To 10 Step 1
         Print Game_senso(temp_byte_1) ; " " ;
      Next Temp_byte_1
      Print " *"
   #endif

Return
'-- End Game_lade_sensowert ---------------------------------------------------

'------------------------------------------------------------------------------
' GAME - Gosub-Routine: Game_play_sensolevel
'
' Routine gibt abhängig vom erreichten Sensolevel die LED-Signale und Sound
' aus
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' Sensolevel     = erreichtes Spielelevel (1-10)
' Game_sensowert = Array 1 - 10 der jeweiligen Senso-Werte
'------------------------------------------------------------------------------
Game_play_sensolevel:

   ' ----- Programmcode -----

   ' In einer For-Schleife je nach erreichtem Senso-Spiellevel (1-10)
   ' LED einschalten -> Sound spielen -> LED ausschalten

   For Temp_index = 1 To Game_sensolevel
       Call Lcd_print_level(temp_index)
       Select Case Game_senso(temp_index)
         Case 1:                                            ' LED und Taste 1 = BLAU
           Led_blau = Led_ein
           Sound Speaker , Sound_ton1 , Sound_dauer1
           Led_blau = Led_aus
         Case 2:                                            ' LED und Taste 1 = ROT
           Led_rot = Led_ein
           Sound Speaker , Sound_ton2 , Sound_dauer2
           Led_rot = Led_aus
         Case 3:                                            ' LED und Taste 1 = GRUEN
           Led_gruen = Led_ein
           Sound Speaker , Sound_ton3 , Sound_dauer3
           Led_gruen = Led_aus
         Case 4:                                            ' LED und Taste 1 = GELB
           Led_gelb = Led_ein
           Sound Speaker , Sound_ton4 , Sound_dauer4
           Led_gelb = Led_aus
       End Select

       Waitms Game_play_sensolevel_speed                    ' Wartepause

     Next Temp_index                                        ' Schleife über erreichtes Sensolevel

Return
'-- End Game_play_sensolevel --------------------------------------------------

'------------------------------------------------------------------------------
' GAME - Gosub-Routine: Game_play_winwin
'
' Routine spielt Winsound ab und gibt Glückwunsch-Text auf Bildschirm aus
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
'------------------------------------------------------------------------------
Game_play_winwin:

   ' ----- Programmcode -----

   ' Displayausgabe
   Cls
   '                   12345678
   Locate 1 , 1 : Lcd Chr(0) ; " JUHU " ; Chr(0)

   ' Sound gefunden und verwendet von:
   ' http://www.mcselec.com/index.php?option=com_content&task=view&id=221&Itemid=57

   'Europe :: Final Countdown
   Gosub Led_all_on : Sound Speaker , 124 , 675 : Gosub Led_all_off       'H2(1/16)
   Gosub Led_all_on : Sound Speaker , 110 , 758 : Gosub Led_all_off       'A2(1/16)
   Gosub Led_all_on : Sound Speaker , 248 , 675 : Gosub Led_all_off       'H2(1/8)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 165 , 1011 : Gosub Led_all_off       'E2(1/8)
   Waitms 250                                               'P(1/8)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 131 , 637 : Gosub Led_all_off       'C3(1/16)
   Gosub Led_all_on : Sound Speaker , 124 , 675 : Gosub Led_all_off       'H2(1/16)
   Gosub Led_all_on : Sound Speaker , 131 , 637 : Gosub Led_all_off       'C3(1/16)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 124 , 675 : Gosub Led_all_off       'H2(1/16)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 220 , 758 : Gosub Led_all_off       'A2(1/8)
   Waitms 125                                               'P(1/16)
   Waitms 250                                               'P(1/8)
   Gosub Led_all_on : Sound Speaker , 131 , 637 : Gosub Led_all_off       'C3(1/16)
   Gosub Led_all_on : Sound Speaker , 124 , 675 : Gosub Led_all_off       'H2(1/16)
   Gosub Led_all_on : Sound Speaker , 262 , 637 : Gosub Led_all_off       'C3(1/8)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 165 , 1011 : Gosub Led_all_off       'E2(1/8)
   Waitms 250                                               'P(1/8)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 110 , 758 : Gosub Led_all_off       'A2(1/16)
   Gosub Led_all_on : Sound Speaker , 98 , 850 : Gosub Led_all_off       'G2(1/16)
   Gosub Led_all_on : Sound Speaker , 110 , 758 : Gosub Led_all_off       'A2(1/16)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 98 , 850 : Gosub Led_all_off       'G2(1/16)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 92 , 901 : Gosub Led_all_off       'Fis2(1/16)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 110 , 758 : Gosub Led_all_off       'A2(1/16)
   Waitms 125                                               'P(1/16)
   Gosub Led_all_on : Sound Speaker , 196 , 850 : Gosub Led_all_off       'G2(1/8)
   Wait 2

Return
'-- End Game_play_winwin ------------------------------------------------------

'------------------------------------------------------------------------------
' GAME - Gosub-Routine: Game_play_lose_sound
'
' Routine spielt Verlierer-Sound ab
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
'------------------------------------------------------------------------------
Game_play_lose_sound:

   ' ----- Programmcode -----

   ' Displayausgabe
   Cls
   '                   12345678
   Locate 1 , 1 : Lcd Chr(1) ; "SCHADE" ; Chr(1)

   'Note|Freqvency|Periods|Pulses 1/1|Pulses 1/2|Pulses 1/4|Pulses 1/8|Pulses 1/16|
   '===============================================================================
   ' C1 |  261,63 |  2548 |    523   |    262   |    131   |    65    |     33    |
   'Cis1|  277,18 |  2405 |    554   |    277   |    139   |    69    |     35    |
   ' D1 |  293,66 |  2270 |    587   |    294   |    147   |    73    |     37    |
   'Dis1|  311,13 |  2143 |    622   |    311   |    156   |    78    |     39    |
   ' E1 |  329,63 |  2022 |    659   |    330   |    165   |    82    |     41    |
   ' F1 |  349,23 |  1909 |    698   |    349   |    175   |    87    |     44    |
   'Fis1|  369,99 |  1802 |    740   |    370   |    185   |    92    |     46    |
   ' G1 |  392,00 |  1701 |    784   |    392   |    196   |    98    |     49    |
   'Gis1|  415,30 |  1605 |    831   |    415   |    208   |   104    |     52    |
   ' A1 |  440,00 |  1515 |    880   |    440   |    220   |   110    |     55    |
   'Ais1|  466,16 |  1430 |    932   |    466   |    233   |   117    |     58    |
   ' B1 |  493,88 |  1350 |    988   |    494   |    247   |   124    |     62    |

   Gosub Led_all_on : Sound Speaker , 062 , 1350 : Gosub Led_all_off       ' B1 (1/16)
   Gosub Led_all_on : Sound Speaker , 058 , 1430 : Gosub Led_all_off       ' Ais1 (1/16)
   Gosub Led_all_on : Sound Speaker , 055 , 1515 : Gosub Led_all_off       ' A1 (1/16)
   Gosub Led_all_on : Sound Speaker , 052 , 1605 : Gosub Led_all_off       ' Gis 1 (1/16)
   Gosub Led_all_on : Sound Speaker , 049 , 1701 : Gosub Led_all_off       ' G1 (1/16)
   Gosub Led_all_on : Sound Speaker , 046 , 1802 : Gosub Led_all_off       ' Fis1 (1/16)
   Gosub Led_all_on : Sound Speaker , 044 , 1909 : Gosub Led_all_off       ' F1 (1/16)
   Gosub Led_all_on : Sound Speaker , 041 , 2022 : Gosub Led_all_off       ' E1 (1/16)
   Gosub Led_all_on : Sound Speaker , 039 , 2143 : Gosub Led_all_off       ' Dis1 (1/16)
   Gosub Led_all_on : Sound Speaker , 037 , 2270 : Gosub Led_all_off       ' D1 (1/16)
   Gosub Led_all_on : Sound Speaker , 035 , 2405 : Gosub Led_all_off       ' Cis1 (1/16)
   Gosub Led_all_on : Sound Speaker , 131 , 2548 : Gosub Led_all_off       ' C1 (1/4)

Return
'-- End Game_play_lose_sound --------------------------------------------------

'------------------------------------------------------------------------------
' GAME - Gosub-Routine: Game_bypass_mode
'
' Routine gibt nach erfolgreichem Spiel die finalen Koordinaten auf dem
' Display aus
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
'------------------------------------------------------------------------------
Game_bypass_mode:

   ' ----- Programmcode -----

   Gosub Led_all_on                                         ' Alle LED's einschalten

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Bypass_testmodus
      Print "Eintritt in Bytepass-Sequenz"
   #endif

   ' Warten bis wieder alle Tasten losgelassen wurden
   Do
      Temp_byte_1 = Key_check_all_key()
   Loop Until Temp_byte_1 = False

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Bypass_testmodus
      Print "Alle Tasten losgelassen"
   #endif

   Waitms Key_entprellzeit

   ' Tasten einlesen und maskieren
   Do
      Temp_byte_1 = Key_check_any_key()
   Loop Until Temp_byte_1 <> Key_all_key
   Temp_byte_1 = Temp_byte_1 And Key_bl__key

   ' In Abhängigkeit der Konstante Traceausgabe schreiben
   #if Bypass_testmodus
      Print "Taste 1 erkannt - " ; Bin(temp_byte_1)
   #endif

   ' Taste BLAU abfragen
   If Temp_byte_1 = Key_masked_key_aktive Then

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Bypass_testmodus
         Print "Taste 1 ist BLAU"
      #endif

      Waitms Key_entprellzeit

      ' Tasten einlesen und maskieren
      Do
         Temp_byte_1 = Key_check_any_key()
      Loop Until Temp_byte_1 <> Key_all_key
      Temp_byte_1 = Temp_byte_1 And Key_rt__key

      ' In Abhängigkeit der Konstante Traceausgabe schreiben
      #if Bypass_testmodus
         Print "Taste 2 erkannt - " ; Bin(temp_byte_1)
      #endif

      ' Taste ROT abfragen
      If Temp_byte_1 = Key_masked_key_aktive Then

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Bypass_testmodus
            Print "Taste 2 ist ROT"
         #endif

         Waitms Key_entprellzeit

         ' Tasten einlesen und maskieren
         Do
            Temp_byte_1 = Key_check_any_key()
         Loop Until Temp_byte_1 <> Key_all_key
         Temp_byte_1 = Temp_byte_1 And Key_gn__key

         ' In Abhängigkeit der Konstante Traceausgabe schreiben
         #if Bypass_testmodus
            Print "Taste 3 erkannt - " ; Bin(temp_byte_1)
         #endif

         ' Taste GRÜN abfragen
         If Temp_byte_1 = Key_masked_key_aktive Then

            ' In Abhängigkeit der Konstante Traceausgabe schreiben
            #if Bypass_testmodus
               Print "Taste 3 ist GRUEN"
            #endif

            Waitms Key_entprellzeit

            ' Tasten einlesen und maskieren
            Do
               Temp_byte_1 = Key_check_any_key()
            Loop Until Temp_byte_1 <> Key_all_key
            Temp_byte_1 = Temp_byte_1 And Key_ge__key

            ' In Abhängigkeit der Konstante Traceausgabe schreiben
            #if Bypass_testmodus
               Print "Taste 4 erkannt - " ; Bin(temp_byte_1)
            #endif

            ' Taste GELB abfragen
            If Temp_byte_1 = Key_masked_key_aktive Then

               ' In Abhängigkeit der Konstante Traceausgabe schreiben
               #if Bypass_testmodus
                  Print "Taste 4 ist GELB"
               #endif

               ' Counter für Bypassmode erhöhen und in EEPROM speichern
               Incr Ee_bypass_counter
               Ee_data_bypass_counter = Ee_bypass_counter

               Temp_string_1 = Str(ee_bypass_counter)
               Temp_string_1 = Format(temp_string_1 , "000")
               Cls
               '    12345678
               Lcd "BPC: " ; Temp_string_1

               Wait 3

               ' Gewinnmelodie abspielen
               Gosub Game_play_winwin

               ' Bytepassmode auslösen und finale Koordinaten anzeigen
               Gosub Lcd_show_final_koordinates

            End If                                          ' Taste GELB

         End If                                             ' Taste GRÜN

      End If                                                ' Taste ROT

   End If                                                   ' Taste BLAU

   Gosub Led_all_off                                        ' Alle LED's ausschalten

Return
'-- End Game_bypass_mode ------------------------------------------------------

' *********
' * LED's *
' *********

'------------------------------------------------------------------------------
' LED - Gosub-Routine: Led_test_routine
'
' Routine dreht die 4 LED des 4 Farben 2x im Kreis als Test
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen: keine
'------------------------------------------------------------------------------
Led_test_routine:                                           ' LED Testroutine

   ' ----- Programmcode -----

   Led_blau = Led_ein
   Waitms Led_speed_testroutine
   Led_rot = Led_ein
   Waitms Led_speed_testroutine
   Led_gruen = Led_ein
   Waitms Led_speed_testroutine
   Led_gelb = Led_ein
   Waitms Led_speed_testroutine
   Led_blau = Led_aus
   Waitms Led_speed_testroutine
   Led_rot = Led_aus
   Waitms Led_speed_testroutine
   Led_gruen = Led_aus
   Waitms Led_speed_testroutine
   Led_gelb = Led_aus
   Waitms Led_speed_testroutine
   Led_blau = Led_ein
   Waitms Led_speed_testroutine
   Led_rot = Led_ein
   Waitms Led_speed_testroutine
   Led_gruen = Led_ein
   Waitms Led_speed_testroutine
   Led_gelb = Led_ein
   Waitms Led_speed_testroutine
   Led_blau = Led_aus
   Waitms Led_speed_testroutine
   Led_rot = Led_aus
   Waitms Led_speed_testroutine
   Led_gruen = Led_aus
   Waitms Led_speed_testroutine
   Led_gelb = Led_aus

Return
'-- End Led_test_routine ------------------------------------------------------

'------------------------------------------------------------------------------
' LED - Gosub-Routine: Led_all_on
'
' Routine schaltet alle LED's ein und wartet x ms
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen: keine
'------------------------------------------------------------------------------
Led_all_on:

   ' ----- Programmcode -----

   Led_blau = Led_ein
   Led_rot = Led_ein
   Led_gruen = Led_ein
   Led_gelb = Led_ein
   Waitms Game_play_winsound_speed

Return
'-- End Led_all_on ------------------------------------------------------------

'------------------------------------------------------------------------------
' LED - Gosub-Routine: Led_all_off
'
' Routine schaltet alle LED's aus und wartet x ms
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen: keine
'------------------------------------------------------------------------------
Led_all_off:

   ' ----- Programmcode -----

   Led_blau = Led_aus
   Led_rot = Led_aus
   Led_gruen = Led_aus
   Led_gelb = Led_aus
   Waitms Game_play_winsound_speed

Return
'-- End Led_all_on ------------------------------------------------------------

' ***************
' * LCD-Dsiplay *
' ***************

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_init
'
' Routine macht grundlegende LCD Initiualisierungen die im Programm dank
' Lauftext usw. immer wieder benötigt werden.
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
'------------------------------------------------------------------------------
Lcd_init:                                                   ' LCD Initialisierung

   ' ----- Programmcode -----

   Initlcd                                                  ' LCD initialisieren
   Waitms 100                                               ' 100ms nach Init warten
   Cursor Off Noblink                                       ' Blinkenden Cursor abschalten
   Cls                                                      ' Clear Screen

Return
'-- End Lcd_init --------------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_contrast_set
'
' Routine berechnen neue Kontrastwerte und steuert direkt den
' Kontroller des Display an.
' Aufgrund von 6 Bit sind nur Kontrastwerte zwischen 0 und 63 möglich!
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' Lcd_kontrastwert = Kontrastwert für Display
'------------------------------------------------------------------------------
Lcd_kontrast_set:                                           ' Kontrasteinstellung Display

   ' ----- Programmcode -----

   ' Verarbeitung des Kontrastwertes für High-Byte und Low-Byte
   Temp_byte_1 = Lcd_kontrastwert And &B00001111
   Temp_byte_1 = Temp_byte_1 + &B01110000

   Temp_byte_2 = Lcd_kontrastwert
   Shift Temp_byte_2 , Right , 4
   Temp_byte_2 = Temp_byte_2 And &B00000011
   Temp_byte_2 = Temp_byte_2 + &B01010100

   ' Instruction Table 1 einstellen [0,1]
   _temp1 = &B00101001
   !rCall _Lcd_control

   ' Tempvar_1 = &B0111xxxx für Kontrast Set Instruction Table 1 - Low Byte
   _temp1 = Temp_byte_1
   !rCall _Lcd_control

   ' Temovar_2 = &B010101xx für Kontrast Set Instruction Table 1 - High Byte
   _temp1 = Temp_byte_2
   !rCall _Lcd_control

   ' Zurückschalten auf Instruction Table 0 [0,0]
   _temp1 = &B00101000
   !rCall _Lcd_control

Return
'-- End Lcd_kontrast_set ------------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_helligkeit_set
'
' Routine setzt den Helligkeitswert aus der globalen Variable Lcd_helligkeit in
' das Controllregister
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' Lcd_helligkeit = Helligkeitswert für PWM
'------------------------------------------------------------------------------
Lcd_helligkeit_set:

   ' ----- Programmcode -----

   ' Variable in Timer-Count-Register laden
   Ocr2 = Lcd_helligkeit

Return
'-- End Ir_set_helligkeit -----------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_beleuchtung_aus
'
' Routine schaltet die LCD-Hintergrundbeleuchtung aus
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' --
'------------------------------------------------------------------------------
Lcd_beleuchtung_aus:

   ' ----- Programmcode -----

   Lcd_helligkeit = Lcd_helligkeit_aus
   Gosub Lcd_helligkeit_set

   #if Lcd_testmodus
      Print "Beleuchtung aus"
   #endif

Return
'-- End Lcd_beleuchtung_aus ---------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_beleuchtung_ein
'
' Routine schaltet die LCD-Hintergrundbeleuchtung ein
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' --
'------------------------------------------------------------------------------
Lcd_beleuchtung_ein:

   ' ----- Programmcode -----

   Lcd_helligkeit = Lcd_helligkeit_default
   Gosub Lcd_helligkeit_set

   #if Lcd_testmodus
      Print "Beleuchtung ein"
   #endif

Return
'-- End Lcd_beleuchtung_ein ---------------------------------------------------

'------------------------------------------------------------------------------
' LCD - Gosub-Routine: Lcd_show_final_koordinates
'
' Routine gibt wiederholend die finalen Koordinaten aus bis Taste benötigt ist
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' --
'------------------------------------------------------------------------------
Lcd_show_final_koordinates:

   ' ----- Programmcode -----

   ' Abbruchflag initialisieren
   Temp_byte_3 = False

   Do

      Cls
      '    12345678
      Lcd "Final "

      Wait Game_show_finaly_delay

      Cls
      '    12345678
      Lcd "ist bei"

      Wait Game_show_finaly_delay

      Cls
      '    12345678
      Lcd "N 26.704"

      Wait Game_show_finaly_delay

      Cls
      '    12345678
      Lcd "E 57.961"

      Wait Game_show_finaly_delay

      Cls
      '                      2345678
      Lcd Chr(&B01111110) ; "  Taste"

' Implementierung 1 führt aber zu ggf. unnötiger Wiederholung
'      Wait Game_show_finaly_delay
'      Temp_byte_2 = Pind And Key_all_key
'   Loop Until Temp_byte_2 <> Key_all_key

      ' Implementierung 2 - Tasten werden in FOR-Schleife abgefragt so dass
      ' eventueller Tastendruck sofort erkannt werden kann

      ' FOR-Schleife mit Delay aufziehen in der der Hinweise "Taste" angezeigt wird
      For Temp_byte_2 = 0 To 200 Step 1

         ' Tasten einlesen
         Temp_byte_1 = Pind And Key_all_key

         ' Prüfen ob Taste betätigt wurde / erkannt wurde
         If Temp_byte_1 <> Key_all_key Then

            ' JA, Taste wurde erkannt

            Temp_byte_3 = True                              ' Abbruchbedingung setzen
            Exit For                                        ' FOR-Schleife abbrechen

         End If                                             ' Tastenabfrage

         Waitms Game_play_timeout_delay                     ' Verzögerung für FOR-Schleife

      Next Temp_byte_2                                      ' Hinweisanzeige

   Loop Until Temp_byte_3 = True                            ' Hinweis repetierend anzeigen

Return
'-- End Lcd_show_final_koordinates --------------------------------------------

' **********
' * EEPROM *
' **********

'------------------------------------------------------------------------------
' EEPROM - Gosub-Routine: EE_init
'
' Routine prüft ob EEPROM schon initialisiert ist / war, holt ggf. dieses nach
' und liest aktuellen Bytepasscounter aus.
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
'    Ee_bypass_counter      = Arbeitsvariable für Bypasscounter
'    Ee_data_bypass_counter = Flash-variable für Bypasscounter
'    Ee_data_version_value  = Flash-Variable für Version
'    Ee_version_value       = Arbeitsvariable für Version
'------------------------------------------------------------------------------
Ee_init:

   ' ----- Programmcode -----

   ' Anmerkung:
   ' Es wird davon ausgegangen dass nicht initialisierte / neue EEPROMS
   ' bzw. gelöschte EEPROMS den Wert 0xFF enthalten.

   ' Version aus Speicher auslesen
   Ee_version_value = Ee_data_version_value

   ' Prüfen ob Eeprom schon initialisiert ist, wenn NEIN tue dies
   If Ee_version_value <> Ee_default_version_value Then

      ' NEIN, noch nicht initialisiert

      ' Arbeitsvariablen vorbelegen
      Ee_version_value = Ee_default_version_value
      Ee_bypass_counter = 0

      ' Arbeitsvariablen in EEPROM schreiben
      Ee_data_bypass_counter = Ee_bypass_counter
      Ee_data_version_value = Ee_version_value

      ' Ggf. Trace ausgeben
      #if Eeprom_testmodus
         Print "EEPROM und Arbeitsvariablen wurden neu initialisiert"
      #endif

   Else                                                     ' Eeprom schon Initialisiert

      ' JA, Speicher ist initialisiert

      ' Counter in Arbeitsvariable auslesen
      Ee_bypass_counter = Ee_data_bypass_counter

      ' Ggf. Trace ausgeben
      #if Eeprom_testmodus
         Print "EEPROM ist gueltig. Bypasscounter = " ; Ee_bypass_counter
      #endif

   End If                                                   ' Eeprom schon Initialisiert

Return
'-- End Ee_init ---------------------------------------------------------------

' **********************
' * ADC-Batteriestatus *
' **********************

'------------------------------------------------------------------------------
' ADC - Gosub-Routine: Adc_check_batterie
'
' Routine liest den Spannungswert aus dem AD-Wandler, prüft gegen eine
' voreingestellte Grenze und schaltet ggf. die Power-LED als Warnsignal ein.
'
' Parameter: keine
' Rückgabe:  keine
'
' Globale Variablen:
' Temp_word_1     = temporäre WORD Arbeitsvariable
' adc_channel     = Variable beinhaltet Kanalnummer des ADC
' Ubatt_grenzwert = Konstante für Grenzwert
'------------------------------------------------------------------------------
Adc_check_batterie:

   ' ----- Programmcode -----

   ' ADC-Wert lesen
   Temp_word_1 = Getadc(adc_channel)

   #if Batterie_testmodus
      Print "ADC-Wert Batteriespannung : " ; Temp_word_1
   #endif

   ' Hier findet keine Batterie-Spannungsüberwachung statt

   ' Zufallszahlengenerator "verdrehen" :-) Erklärung siehe ganz oben in der Einleitung!!
   ___rseed = Temp_word_1

Return
'-- End Adc_check_batterie ----------------------------------------------------

'------------------------------------------------------------------------------
' Devices schließend und ggf. "Terminate Programm execution"
'------------------------------------------------------------------------------

' System halt
End                                                         'end program

'------------------------------------------------------------------------------
' Definition von globalen Konstantenfeldern
'------------------------------------------------------------------------------

' Anmerkung:
' Eigentlich wird eine 10-stellige ganze Zahl benötigt die in ein Senso-Patter
' aufgelöst werden soll. Dazu würde sich der Wert DWord von BASCOM eignen.
' Wertebereich 0 to 4294967295
' Anscheinend gibt es aber einen Bug in BASCOM der dien verhindert und durch den
' nur Werte bis 2147483647 möglich sind. Das ist zu wendig
' Da Werte bis 4444444444 benötigt werden wird der Zahlenwert in 2 Word-Werte
' zerlegt die nacheinander gelesen und dann zusammengesetzt werden. Unschön!

Spielkombinationen_data:
Data 34212% , 31441%                                        ' #000
Data 43124% , 43432%                                        ' #001
Data 42244% , 42442%                                        ' #002
Data 32243% , 41112%                                        ' #003
Data 33234% , 14414%                                        ' #004
Data 12421% , 41344%                                        ' #005
Data 44221% , 31431%                                        ' #006
Data 33211% , 41234%                                        ' #007
Data 42141% , 42121%                                        ' #008
Data 43433% , 31414%                                        ' #009
Data 44224% , 31232%                                        ' #010
Data 34144% , 31342%                                        ' #011
Data 24214% , 22423%                                        ' #012
Data 42424% , 44421%                                        ' #013
Data 21341% , 21342%                                        ' #014
Data 11244% , 24442%                                        ' #015
Data 24123% , 41344%                                        ' #016
Data 42212% , 34221%                                        ' #017
Data 42433% , 23341%                                        ' #018
Data 23131% , 13444%                                        ' #019
Data 41343% , 43444%                                        ' #020
Data 44112% , 31221%                                        ' #021
Data 34243% , 23312%                                        ' #022
Data 42412% , 12112%                                        ' #023
Data 31324% , 23114%                                        ' #024
Data 44242% , 32441%                                        ' #025
Data 44413% , 23343%                                        ' #026
Data 41243% , 21243%                                        ' #027
Data 21332% , 24333%                                        ' #028
Data 13224% , 24413%                                        ' #029
Data 41333% , 11314%                                        ' #030
Data 33113% , 31143%                                        ' #031
Data 31244% , 33112%                                        ' #032
Data 33313% , 13124%                                        ' #033
Data 22423% , 33322%                                        ' #034
Data 23411% , 14243%                                        ' #035
Data 14312% , 23114%                                        ' #036
Data 24212% , 44324%                                        ' #037
Data 44333% , 43114%                                        ' #038
Data 34221% , 44311%                                        ' #039
Data 23441% , 31341%                                        ' #040
Data 43112% , 11334%                                        ' #041
Data 21312% , 12341%                                        ' #042
Data 23133% , 44334%                                        ' #043
Data 42231% , 32221%                                        ' #044
Data 24241% , 11113%                                        ' #045
Data 24142% , 13224%                                        ' #046
Data 13432% , 44443%                                        ' #047
Data 24212% , 14113%                                        ' #048
Data 44132% , 22443%                                        ' #049
Data 12423% , 24323%                                        ' #050
Data 33111% , 13432%                                        ' #051
Data 22112% , 44324%                                        ' #052
Data 23414% , 12243%                                        ' #053
Data 12133% , 42234%                                        ' #054
Data 34444% , 22324%                                        ' #055
Data 24312% , 34211%                                        ' #056
Data 31414% , 24242%                                        ' #057
Data 13323% , 31133%                                        ' #058
Data 41113% , 24333%                                        ' #059
Data 23313% , 43444%                                        ' #060
Data 43121% , 22214%                                        ' #061
Data 32431% , 33132%                                        ' #062
Data 24224% , 33432%                                        ' #063
Data 12223% , 34132%                                        ' #064
Data 42143% , 33213%                                        ' #065
Data 33111% , 21244%                                        ' #066
Data 14321% , 14222%                                        ' #067
Data 12123% , 12134%                                        ' #068
Data 32424% , 44443%                                        ' #069
Data 14112% , 13343%                                        ' #070
Data 21242% , 32331%                                        ' #071
Data 11212% , 44313%                                        ' #072
Data 34431% , 24222%                                        ' #073
Data 13431% , 21232%                                        ' #074
Data 34212% , 12224%                                        ' #075
Data 32212% , 22231%                                        ' #076
Data 13121% , 42124%                                        ' #077
Data 24132% , 41242%                                        ' #078
Data 31112% , 22331%                                        ' #079
Data 34311% , 21111%                                        ' #080
Data 32322% , 21112%                                        ' #081
Data 44231% , 31421%                                        ' #082
Data 24322% , 43344%                                        ' #083
Data 33233% , 13343%                                        ' #084
Data 34213% , 42321%                                        ' #085
Data 44443% , 41443%                                        ' #086
Data 41243% , 12413%                                        ' #087
Data 13314% , 22234%                                        ' #088
Data 41242% , 21412%                                        ' #089
Data 12342% , 32333%                                        ' #090
Data 34412% , 22121%                                        ' #091
Data 34421% , 33144%                                        ' #092
Data 13133% , 43213%                                        ' #093
Data 41412% , 22233%                                        ' #094
Data 12412% , 14311%                                        ' #095
Data 32244% , 42142%                                        ' #096
Data 41241% , 34441%                                        ' #097
Data 14423% , 21344%                                        ' #098
Data 13442% , 32421%                                        ' #099

' ----------------------------------------------------------------------------

'###################################### END ###################################

'################################### Historie #################################
'
' 25.12.2016 : Version x.x
'              Beginn der Implementierungen für DrMaFu_Senso
' -----------------------------------------------------------------------------
' 08.02.2017 : Version 1.0
'              Fertigstellung der Implementierung auf Basis STK500
' -----------------------------------------------------------------------------
' 19.03.2017 : Version 1.0
'              Umstellung GPIO auf Zielsystem und Programmierung Zielsystem
' -----------------------------------------------------------------------------
' 22.03.2017 : Version 1.1
'              - Delayzeit zwischen Eingabe und nächstem Level verkürzt
'              - WinWin-Melodie wird nun auch im Bypassmodus gespielt
'              - Bei Ausgabe der Koordinaten zyklische Tastenabfrage während
'                Hinweis Taste hinzugefügt wegen besserer Bedienbarkeit
'
'##############################################################################