'############################################################################## ' ' HangingMan.BAS Stand 09.07.2014 ' -------------- (C) Markus Fulde ' ' Gesamtsoftware Steuerprogramm für das Geocaching-Spiel Hanging Man ' ' 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 2x16 EA DOG-M 162 von Electronic Assembly ' - Die Helligkeit des Display soll über PWM einstellbar sein ' - Bei Innaktivität soll das Display abgeschaltet werden können ' - Hauptschalter für Spannungsversorgung ' - Drück-Dreh-Geber (inkrementeller Drehgeber mit Tasterfunktion) ' - LED-Anzeigen für Betriebsanzeige und Low-Power Batterie-Überwachung ' - Gehäuse mit Batteriefach und Displayfenster ' - Akustisches Feedback über Piezo Schallwandler ' '############################################################################## '------------------------------------------------------------------------------ ' Allgemeines zum Spiel: '------------------------------------------------------------------------------ ' Galgenmännchen, Galgenraten, Galgenbaum oder auch Galgenmann, Hängemann, ' Hängemännchen oder ein-fach auch Galgen (englisch auch hangman) ist ein ' einfaches Buchstabenspiel. ' ' Spielverlauf ' Der Spieler spielt alleine mit Hilfe der Elektronik. Am Ende bei erfolgreichem ' Spiel wird eine Geokoordinaten für das Finale ausgegeben. ' Der Computer überlegt sich nun ein Wort 13 Buchstaben. Alle Buchstaben des ' ausgedachten Wortes werden durch Striche markiert. Der Geocacher hat nun die ' Aufgabe, die Buchstaben zu erraten. Hierzu wählt er in beliebiger Reihenfolge ' nacheinander einzelne Buchstaben des Alphabets mit dem DDS aus. Der Computer ' prüft die Eingabe und zeigt an, wie oft und an welcher Stelle des Lösungswortes ' der Buchstabe vorkommt. So ergibt sich nach und nach das gesuchte Wort. ' Kommt ein genannter Buchstabe darin jedoch nicht vor beginnt der Computer damit, ' einen Galgen mit einem Gehängten zu zeichnen. Dies geschieht in 5 Etappen ' (bei jeder Fehlfrage kommt ein Teilstrich dazu), so dass der Geocacher 5 ' Versuche hat das Wort zu erraten. Hat er dann das Wort noch nicht herausgefunden, ' so hat er verloren und hängt symbolisch am Galgen. ' ' Umlaute werden ae, oe oder ue geschrieben. ' Der Anfangsbuchstabe muss ebenfalls geraten werden. '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' 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] Bypassmodus ' Um das Spiel nicht spielen zu müssen wird quasi als Hintertür ein Bypassmodus ' implementiert der wie folgt erreicht werden kann: ' - Spiel ausschalten ' - DDS Drücken / gedrückt halten und Spiel einschalten ' - DDS loslassen ' - DDS 5x links drehen ' - DDS 5x rechts drehen ' - DDS erneut kurz betätigen ' Danach wird direkt die finale Geokoordinate an der sich der Cache befindet ' angezeigt. Abweichungen zur beschriebenen Bedienung führen zum sofortigen ' Abbruch der Bypasssequenz und es muss normal gespielt werden. ' Zur Kontrolle ob ein Cacher den Bypassmode findet und dies weiterkommuniziert ' wird ein Bypasscounter geführt der im EEPROM abgelegt wird. Dieser Couner ' wird kurz vor dem Anzeigen der finalen Koordinaten angezeigt. Somit hat man ' die Kontrolle darüber ob jemand dieses Hintertürchen gefunden hat. ' Das Hintertürchen ist als Telefonjoker für Cacher gedacht die erfolglos ' versucht haben das Spiel zu spielen und den Owner kontaktieren. '------------------------------------------------------------------------------ ' 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 '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' Definition von Ressourcen '------------------------------------------------------------------------------ ' ----- LED's ----- Alive_pin Alias PinB.0 ' GPIO für Alive-LED (für DDR oder Input) Alive Alias PortB.0 ' GPIO für Alive-LED (für Output oder Pullup) Pwrled_pin Alias PINB.1 ' GPIO für Power-LED (für DDR oder Input) Pwrled Alias PORTB.1 ' GPIO für Power-LED (für Output oder Pullup) ' ----- LCD-Display ----- ' LCD-Display Db4_pin Alias PortC.2 ' GPIO für LCD Pin4 Db5_pin Alias PortC.3 ' GPIO für LCD Pin5 Db6_pin Alias PortC.4 ' GPIO für LCD Pin6 Db7_pin Alias PortC.5 ' GPIO für LCD Pin7 E_pin Alias PortD.6 ' GPIO für LCD E Rs_pin Alias PortD.7 ' GPIO für LCD RS ' ----- SOUND ----- Piezosound_pin Alias Pinb.2 ' GPIO für Soundausgabesteuerung (Transistorstufe) Piezosound Alias Portb.2 ' GPIO für Sound (für Output oder Pullup) ' ----- DDS ----- A_signal_pin Alias Pind.2 ' GPIO für DDS Signal A (für DDR oder Input) A_signal Alias Portd.2 ' GPIO für DDS Signal A (für Output oder Pullup) B_signal_pin Alias Pind.4 ' GPIO für DDS Signal B (für DDR oder Input) B_signal Alias Portd.4 ' GPIO für DDS Signal B (für Output oder Pullup) Push_signal_pin Alias Pind.3 ' GPIO für DDS Push (für DDR oder Input) Push_signal Alias Portd.3 ' GPIO für DDS Push (für Output oder Pullup) '------------------------------------------------------------------------------ ' Definition von Konstaten '------------------------------------------------------------------------------ ' ----- Für Testumgebung bzw. Traceausgaben ----- Const Main_testmodus = 0 ' Flag für Testmodus Allgemeinsystem Const Lcd_testmodus = 0 ' Flag für Testmodus rund um das LCD-Display Const Game_testmodus = 0 ' Flag für Testmodus der Spielsteuerung Const Dds_testmodus = 0 ' Flag für Testmodus des Drückdrehstellers Const Bypass_testmodus = 0 ' Flag für Testmodus des Bypass-Modes Const Eeprom_testmodus = 0 ' Flag für Testmodus der Eeprom-Daten ' ----- Allgemeine Systemkonstanten ----- ' Tatsächliches Allgemeines Const Led_aus = 0 Const Led_ein = 1 ' Const Led_aus = 1 ' Achtung !! bei STK500 ist Logik gedreht!! ' Const Led_ein = 0 ' Achtung !! bei STK500 ist Logik gedreht!! Const False = 0 Const True = 1 Const Pullup_aus = 0 Const Pullup_ein = 1 ' Zeitvorgabe für Sekunden-Timer Const Timervorgabe = 34286 ' Timer von 1 Sekunden (SekundenTick) ' ----- 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 = 20 ' 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 ' ----- ADC: Batterieüberwachung ----- Const Ubatt_grenzwert = 700 ' Grenzwert für Batterieüberwachung ' ----- Sound ----- Const Sound_ein = 1 ' Wert für GPIO-Wert um Sound einzuschalten Const Sound_aus = 0 ' Wert für GPIO-Wert um Sound auszuschalten ' ----- DDS ----- Const Dds_none = 0 ' Keine Betätigung des DDS Const Dds_links = 1 ' DDS wurde nach links gedreht Const Dds_rechts = 2 ' DDS wurde nach rechts gedreht ' ----- GAME ----- Const Game_anzahl_text = 100 ' Anzahl der Text im DATA Bereich Const Game_textmaske = "_____________" ' 1 2 3 ' 12345678901234567890123456789012345678 Const Game_auswahltext_default = "uvwxyzabcdefghijklmnopqrstuvwxyzabcdef" ' 12345678901234567890123456 ' 1 2 Const Game_startposition_default = 1 ' Startposition für Buchstabenauswahl Const Game_fuellzeichen = 32 ' Leerzeichen ist Fuellzeichen ' Const Game_fuellzeichen = 95 ' Unterstrich ist Fuellzeichen Const Game_cursorzeichen = &B00101010 ' Zeichen aus Displayzeichentabelle für Cursorzeichen (Stern) Const Game_leftcount_max = 5 ' Anzahl von Linkstix für Bypassmode Const Game_rightcount_max = 5 ' Anzahl von Rechtstix für Bypassmode ' ----- EEPROM ----- Const Ee_default_version_value = 1 ' Version für persistente Daten '------------------------------------------------------------------------------ ' Definition von Variablen und Datentypen '------------------------------------------------------------------------------ ' ----- Temporäre Hilfsvariablen ----- Dim Temp_byte_1 As Byte ' Temporäre Byte Variable 1 Dim Temp_byte_2 As Byte ' Temporäre Byte Variable 2 Dim Temp_word_1 As Word ' Temporäre Word Variable 1 Dim Temp_word_2 As Word ' Temporäre Word Variable 2 ' ----- System ----- Dim ___rseed As Word ' Manipulation des Zufallszahlengenerators Dim Sectick_counter As Word ' Globaler Sekundenzähler ' ----- Arbeitsvariablen für Spieleablauf ----- Dim Game_hangman_status As Byte ' Arbeitsvariable für Hangman-Status Dim Game_ablaufstatus As Byte ' Arbeitsvariable für System-Status Dim Game_suchtext As String * 13 ' Stringvariable für den Suchtext Dim Game_suchtext_zeichen(14) As Byte At Game_suchtext Overlay Dim Game_scrolltext As String * 13 ' Stringvariable für Scrolltext in Zeile 1 Dim Game_scrolltext_zeichen(14) As Byte At Game_scrolltext Overlay ' Zeichenweise Zugriff auf Scrolltext Dim Game_raetseltext As String * 13 ' Stringvariable für zu suchenden Text in Zeile 2 Dim Game_raetseltext_zeichen(14) As Byte At Game_raetseltext Overlay ' Zeichenweise Zugriff auf Raetseltext Dim Game_auswahltext As String * 38 ' Stringvariable für scrollbaren Auswahltext Dim Game_auswahltext_zeichen(39) As Byte At Game_auswahltext Overlay ' Zeichenweise Zugriff auf Auswahltext Dim Game_buchstaben_index As Byte ' Arbeitsvariable für aktuelle Buchstabenauswahl Dim Game_bypassmode_flag As Byte ' Arbeitsvariable für Einstieg in Bypassmodus Dim Game_bypassmode_leftcounter As Byte ' Arbeitsvariable für Bypass Linkscounts Dim Game_bypassmode_rightcounter As Byte ' Arbeitsvariable für Rechtscount ' ----- 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 ' ----- ADC: Batteriespannungsueberwachung ----- Dim Adc_channel As Byte ' Arbeitsvariable für ADC-Kanalauswahl ' ----- DDS ----- Dim Dds_flag As Byte ' Arbeitsvariable zur Behandlung des DDS Dim Push_flag As Byte ' Arbeitsvariable zur Behandlung des Tasters ' ----- 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 '------------------------------------------------------------------------------ ' Prototyping '------------------------------------------------------------------------------ ' ----- LCD und Print ----- Declare Sub Lcd_print_hangingman(byval Value As Byte) ' Funktion zum schrittweisen Aufbau des Hanging Man '------------------------------------------------------------------------------ ' 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 = Db4_pin , Db5 = Db5_pin , Db6 = Db6_pin , Db7 = Db7_pin , E = E_pin , Rs = Rs_pin Config Lcd = 16 * 2 , Chipset = Dogm162v5 ' DOG-M Treiber laden Config Lcdbus = 4 ' LCD arbeitet über 4-Bit Initlcd ' LCD initialisieren Waitms 100 ' 100ms nach Init warten Cursor Off Noblink ' Blinkenden Cursor abschalten ' Definition benutzerdefinierter Zeichen Deflcdchar 0 , 16 , 16 , 16 , 16 , 16 , 16 , 30 , 30 ' LCD-Zeichen linker Sockel des Galgens Deflcdchar 1 , 15 , 9 , 10 , 12 , 8 , 8 , 8 , 8 ' LCD-Zeichen linke obere Ecke des Galgens Deflcdchar 2 , 28 , 4 , 32 , 32 , 32 , 32 , 32 , 32 ' LCD-Zeichen rechter Galgen ohne Männchen Deflcdchar 3 , 28 , 4 , 4 , 14 , 17 , 17 , 14 , 4 ' LCD-Zeichen rechter Galgen mit Kopf Deflcdchar 4 , 4 , 4 , 4 , 4 , 32 , 32 , 32 , 32 ' LCD-Zeichen Bauch Deflcdchar 5 , 4 , 4 , 4 , 4 , 8 , 16 , 16 , 32 ' LCD-Zeichen Bauch mit linkem Beine Deflcdchar 6 , 4 , 4 , 4 , 4 , 10 , 17 , 17 , 32 ' LCD-Zeichen Bauch mit beiden Beinen Deflcdchar 7 , 14 , 21 , 21 , 4 , 10 , 17 , 17 , 32 ' LCD-Zeichen kompletter Männchen-Körper Cls ' Clear Screen ' Anmerkung: CLS muss gemäß Datenblatt sein um selbstdefinierte Zeichen in den Controller zu übernehmen ...... ' ----- 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_pin = Output ' GPIO für Alive-LED ist Output Config Pwrled_pin = Output ' GPIO für Power-LED ist Output ' ----- Sound ------ Config Piezosound_pin = Output ' GPIO für Sound ist Output ' ----- DDS ------ Config A_signal_pin = Input ' GPIO für DDS-A ist Input, PullUp wird später geschaltet Config B_signal_pin = Input ' GPIO für DDS-B ist Input, PullUp wird später geschaltet Config Push_signal_pin = Input ' GPIO für Taster ist Input, PullUp wird später geschaltet ' ----- DDS ----- ' Int 0 für Signal A so konfigurieren dass Interrupt bei fallender Flanke angesprungen wird Config Int0 = Falling ' Schalter zieht PullUp-Spannung auf GND On Int0 Dds_interrupt ' Interrupt-Routine Enable Int0 ' Interrupt freigeben ' Int 1 für den Taster so konfigurieren, dass Interrupt bei fallender Flanke angesprungen wird ' Via Default ist Interrupt aber deaktiviert. Er wird nur zur Abfrage des Tasters bei der Anzeige ' der Geokoordinaten aktiviert. Config Int1 = Falling ' Schalter zieht PullUp-Spannung auf GND On Int1 Push_interrupt ' Interrupt-Routine Disable Int1 ' Interrupt freigeben ' ------------------------------ Variablen und Werte -------------------------- ' ----- System ----- Sectick_counter = 0 ' Globaler Sekundenzähler initialisieren ' ----- LED-Konfigurationen ----- Alive = Led_aus ' Alive-LED aus Pwrled = Led_aus ' LED für Spannungsüberwachung ' ----- Sound ----- Piezosound = Sound_aus ' Sound ausschalten ' ----- LCD-Display ----- Lcd_kontrastwert = Lcd_kontrast_default ' Kontrastwert Lcd_helligkeit = Lcd_helligkeit_default ' Displayhelligkleit ' ----- Spielesteuerung ----- Game_hangman_status = 0 ' Statusvariable für gezeichneten HangingMan Game_ablaufstatus = 0 ' Steuervariable für Spielablaufsteuerung Game_bypassmode_leftcounter = 0 ' Linkscounter initialisieren Game_bypassmode_rightcounter = 0 ' Rechtscounter initialisieren ' ----- ADC_ Batteriespannungsueberwachung ----- Adc_channel = 0 ' Spannungsteiler zur Batterispannungsmessung hängt an ADC0 ' ----- DDS - Konfiguration ----- ' Interne Pull-Ups für die Schalter aktivieren A_signal = Pullup_ein B_signal = Pullup_ein Push_signal = Pullup_ein ' ----- Bypassmodus ----- ' An dieser Stelle wird sofort der Status für den Bypassmodus abgefragt. ' Der Bypassmodus kann erreicht werden indem PTT direkt beim Einschalten betätigt wird ' Danach muss man 5x links drehen, 5x rechts drehen und erneut PTT betätigen ' Ggf Trace schreiben #if Bypass_testmodus Print "Pin-Pegel = " ; Push_signal_pin #endif ' Wurde bei Systemstart PTT als Triggersignal für den Einstieg in den Bypassmode erkannt? If Push_signal_pin = True Then ' PTT nicht betätigt -> Bypassmodus nicht schalten Game_bypassmode_flag = False ' Ggf Trace schreiben #if Bypass_testmodus Print "Bypassmode False" #endif Else ' Wurde Bypassmode getriggert? ' PTT betätigt -> Bypassmodus schalten Game_bypassmode_flag = True ' Ggf Trace schreiben #if Bypass_testmodus Print "Bypassmode True" #endif End If ' Wurde Bypassmode getriggert? ' Arbeitsvariable vorinitialisieren Dds_flag = Dds_none ' ... steuert DDS-Drehung erkannt Push_flag = False ' ... steuert Push-Taster erkannt '------------------------------------------------------------------------------ ' Und los gehts, hier noch die Restarbeiten '------------------------------------------------------------------------------ ' ----- 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 ConvCtrl ' ' ############################################################################# ' In Abhängigkeit der Konstante Traceausgabe schreiben #if Main_testmodus Print "** OK, let's GO **" #endif ' Begrüßungstext 1 ausgeben ' 1234567890123456 Locate 1 , 1 : Lcd " Willkommen zum" ' Text Zeile 1 Locate 2 , 1 : Lcd "Geocaching Spiel" ' Text Zeile 2 Gosub Sound_piep_400ms ' 400 ms Piepton ausgeben Wait 3 ' Wartezeit bis nächste Anzeige Cls ' Bildschirm löschen ' 1234567890123456 Locate 1 , 1 : Lcd " Galgenm" ; Chr(132) ; "nnchen" ' Text Zeile 1 Locate 2 , 1 : Lcd " GC585BM " ' Text Zeile 2 Gosub Sound_piep_400ms ' 400 ms Piepton ausgeben Wait 3 ' Wartezeit bis nächste Anzeige ' Logik für Abschaltung Hintergrundbeleuchtung "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit ' ---------------------------------------------- ' ----- Hier ist die Programmhauptschleife ----- ' ---------------------------------------------- ' Erklärung Spielstati - Game_ablaufstatus: ' 0 = Lösche Bildschirm, zeichne Basisgalgen, erzeuge Zufallstext, lade Auswahltext, ' lade Textinhalte in Arbeitsstring und zeige diese auf dem Display an ' 1 = Normales Spiels ' 2 = Verloren-Behandlung, Verlorentexte ausgeben, Spielstati zurücksetzen ' 3 = Jippi, gewonnen, Geokoordinate ausgeben ' ' Achtung: Status 1 ist normaler Status der im Wesentlichen den DDS auswertet ' Hier läuft die Do-While-Schleife die meiste Zeit!! ' Do ' Hauptschleife ' ------------------------------ Systemaufgaben ---------------------------- ' 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 der DDS betätigt wurden If Lcd_beleuchtung_status = Lcd_beleuchtung_status_aus Then ' JA -> wurde Drehung erkannt? If Dds_flag > Dds_none Then 'JA -> Beleuchtung einschalten und DDS ignorieren Gosub Lcd_beleuchtung_ein ' Hintergrundbeleuchtung einschalten Lcd_beleuchtung_status = Lcd_beleuchtung_status_ein ' Hintergrundbeleuchtung ist EIN Dds_flag = Dds_none ' Flag korrigieren ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit End If ' DDS betätigt End If ' Hintergrundbeleuchtung abgeschaltet ' --------------------------- Spielsteuerung ------------------------------- ' ==== Spiel Vorbereitung ==== ' Prüfen ob Spiel neu gestartet werden muss und Anzeige neu aufsetzt If Game_ablaufstatus = 0 Then ' JA -> Bildschirm löschen und Hanginman neu aufsetzen Cls Call Lcd_print_hangingman(game_hangman_status ) ' Maennchen gemaess Status zeichnen ' Zufallstext ermitteln Gosub Game_suchtext_select ' Auswahltext in Arbeitsvariable laden (gesamter Zeichenvorrat für Zeile 1) Game_auswahltext = Game_auswahltext_default ' Ratseltext zurücksetzen und Text auf Display anzeigen (Zeile 2) Game_raetseltext = Game_textmaske Gosub Lcd_print_raetseltext ' Scrollzeile für Buchstaben vorbereiten (Zeile 1) Game_buchstaben_index = Game_startposition_default Gosub Game_update_scrolltext Gosub Lcd_print_scrolltext ' Spielstatus weiterschalten Game_ablaufstatus = 1 End If ' Spiel Vorbereitung ' ==== normales Spiel => Auswertung des DDS ==== If Game_ablaufstatus = 1 Then ' ----- DDS auswerten ----- Select Case Dds_flag Case Dds_links : Gosub Dds_links_verarbeiten Case Dds_rechts : Gosub Dds_rechts_verarbeiten End Select End If ' normales Spiel ' ==== Leider verloren ==== If Game_ablaufstatus = 2 Then ' ----- Fehlerszenario ----- Wait 1 Gosub Sound_piep_1s Waitms 500 Gosub Sound_piep_1s Waitms 500 Gosub Sound_piep_1s Waitms 500 ' 1234567890123456 Locate 1 , 1 : Lcd "!!! Schade !!!" Locate 2 , 1 : Lcd "Leider verloren" Wait 3 ' 1234567890123456 Locate 1 , 1 : Lcd "Probiere es doch" Locate 2 , 1 : Lcd "einfach nochmals" Wait 3 Game_ablaufstatus = 0 ' Gameablaufsteuerung zurücksetzen Game_hangman_status = 0 ' Hangmanstatus zurücksetzen ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit End If ' Leider verloren ' ==== Jippi gewonnen ==== If Game_ablaufstatus = 3 Then Wait 1 Gosub Sound_piep_1s Waitms 500 Gosub Sound_piep_1s Waitms 500 Gosub Sound_piep_1s Waitms 500 ' 1234567890123456 Locate 1 , 1 : Lcd "!! Herzlichen !!" ' " Glückwunsch Locate 2 , 1 : Lcd "! Gl" ; Chr(129) ; "ckwunsch !" Wait 3 ' 1234567890123456 Locate 1 , 1 : Lcd "Du hast gewonnen" Locate 2 , 1 : Lcd "und findest den " Wait 3 ' 1234567890123456 Locate 1 , 1 : Lcd "Cache bei fol- " Locate 2 , 1 : Lcd "genden Koords.. " Temp_byte_1 = True ' Arbeitsvaraible für Schleifenabbruchkriterium Hinweistexte Wait 3 ' Ab hier auch Interrupt 1 für Taster zulassen. ' Interrupt wird wieder in der ISR disabled Push_flag = False ' Flag für Taster zurücksetzen Gifr.intf1 = 1 ' Anstehender Interrupt löschen Enable Int1 ' Interrupts freigeben Do ' 1234567890123456 Locate 1 , 1 : Lcd "N48" ; Chr(223) ; " 31.235 " Locate 2 , 1 : Lcd "E009" ; Chr(223) ; " 54.899 " Wait 3 ' 1234567890123456 Locate 1 , 1 : Lcd "Rohr unter Stein" Locate 2 , 1 : Lcd "und Weg von oben" Wait 3 ' Prüfe ob Schleife für Hinweistext verlassen werden kann If Dds_flag <> Dds_none Or Push_flag = True Then ' JA, alle Flags zurücksetzen Dds_flag = Dds_none Push_flag = False Temp_byte_1 = False End If ' Abbruchbedingung für Hinweistext Loop Until Temp_byte_1 = False ' Spielstatus weiterschalten, Hagmanstatus zurückschalten und nochmals kurz Piepsen Game_hangman_status = 0 Game_ablaufstatus = 4 Gosub Sound_piep_400ms ' 400 ms Piepton ausgeben ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit End If ' gewonnen ' ==== OK, Du magst nochmals spielen ==== If Game_ablaufstatus = 4 Then ' 1234567890123456 Locate 1 , 1 : Lcd "Ok Du magst also" Locate 2 , 1 : Lcd "nochmal spielen!" Gosub Sound_piep_400ms Waitms 2600 ' 1234567890123456 Locate 1 , 1 : Lcd "Na dann los und " Locate 2 , 1 : Lcd "viel Gl" ; Chr(129) ; "ck!!!!!!" Wait 3 ' Spielstatus zurückschalten Game_ablaufstatus = 0 ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit End If ' OK nochmals ' PTT-Taste des DDS auswerten Debounce Push_signal_pin , 0 , Dds_taste_erkannt , Sub 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 ' Alive-LED toggeln lassen ' Timervariable erhöhen Incr Sectick_counter Return '-- End Sekunden_tick -------------------------------------------------------- '------------------------------------------------------------------------------ ' Interrupt-Service-Routine (External Interrupt 0): Dds_interrupt ' ' Routine zur Auswertung des INT0 Interrupts für DDS-Bewegung ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Dds_flag = Variable für den Zustand (Drehrichtung) des DDS '------------------------------------------------------------------------------ Dds_interrupt: ' ----- Programmcode ----- ' Erkennung der Drehrichtung If A_signal_pin = B_signal_pin Then ' Links herum Dds_flag = Dds_links Else ' Erkennung der Drehrichtung ' Rechts herum Dds_flag = Dds_rechts End If ' Erkennung der Drehrichtung Return '-- End Dds_interrupt --------------------------------------------------------- '------------------------------------------------------------------------------ ' Interrupt-Service-Routine (External Interrupt 1): Push_interrupt ' Routine zur Auswertung des INT0 Interrupts für DDS-Bewegung '------------------------------------------------------------------------------ Push_interrupt: ' ----- Programmcode ----- Push_flag = True Disable Int1 Return '-- End Push_interrupt --------------------------------------------------------- '****************************************************************************** ' Subroutinen '****************************************************************************** ' *************** ' * LCD-Display * ' *************** '------------------------------------------------------------------------------ ' LCD - Subroutine: Lcd_print_hangingman ' ' Subroutine schreibt je nach uebergebenem Status den Zustand des Hanging Man ' auf das Display ' Status 0: Galgen ohne Maennchen ' Status 1: Galgen mit Kopf ' Status 2: Galgen mit Kopf und Rumpf ' Status 3: Galgen mit Kopf, Rumpf und linken Bein ' Status 4: Galgen mit Kopf, Rumpf, linken und rechten Bein ' Status 5: Galgen mit kompletten Körper ' ' Parameter: Value = Step n des Hanging-Man ' Rückgabewert: keine ' ' Globale Variable: ' -- '------------------------------------------------------------------------------ Sub Lcd_print_hangingman(byval Value As Byte) ' ----- Programmcode ----- ' Galgen zeichnen Locate 1 , 1 : Lcd Chr(1) Locate 2 , 1 : Lcd Chr(0) Select Case Value Case 0 : Locate 1 , 2 : Lcd Chr(2) Case 1 : Locate 1 , 2 : Lcd Chr(3) Case 2 : Locate 1 , 2 : Lcd Chr(3) Locate 2 , 2 : Lcd Chr(4) Case 3 : Locate 1 , 2 : Lcd Chr(3) Locate 2 , 2 : Lcd Chr(5) Case 4 : Locate 1 , 2 : Lcd Chr(3) Locate 2 , 2 : Lcd Chr(6) Case 5 : Locate 1 , 2 : Lcd Chr(3) Locate 2 , 2 : Lcd Chr(7) End Select ' Case Value End Sub '-- End Lcd_Print_hanginman --------------------------------------------------- '****************************************************************************** ' GOSubroutinen '****************************************************************************** ' *************** ' * LCD-Dsiplay * ' *************** '------------------------------------------------------------------------------ ' 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 ' Kurzes Piep ausgeben Gosub Sound_piep_100ms Return '-- End Lcd_beleuchtung_ein --------------------------------------------------- '------------------------------------------------------------------------------ ' LCD - Gosub-Routine: Lcd_print_raetseltext ' ' Routine gibt den bereits enträtselten Text in Zeile 2 mit 13 Zeichen aus ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Game_raetseltext = Textstring für Raetseltext '------------------------------------------------------------------------------ Lcd_print_raetseltext: ' ----- Programmcode ----- ' 1234567890123456 ' xxxxxxxxxxxxx Locate 2 , 4 : Lcd Game_raetseltext Return '-- End Lcd_print_raetseltext ------------------------------------------------- '------------------------------------------------------------------------------ ' LCD - Gosub-Routine: Lcd_print_scrolltext ' ' Routine gibt den Scroll-Text der Buchstaben in Zeile 1 mit 13 Zeichen aus ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Game_scrolltext = Textstring gescrollte Buchstaben '------------------------------------------------------------------------------ Lcd_print_scrolltext: ' ----- Programmcode ----- ' 1234567890123456 ' xxxxxxxxxxxxx Locate 1 , 4 : Lcd Game_scrolltext Return '-- End Lcd_print_raetseltext ------------------------------------------------- ' ********************** ' * 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) ' Prüfen auf Unterspannung If Temp_word_1 < Ubatt_grenzwert Then ' Wenn Unterspannung erkannt dann LED dauerhaft einschalten Pwrled = Led_ein End If ' Unterspannung? ' Zufallszahlengenerator "verdrehen" :-) Erklärung siehe ganz oben in der Einleitung!! ___rseed = Temp_word_1 Return '-- End Adc_check_batterie ---------------------------------------------------- ' *********************** ' DDS: Drückdrehsteller * ' *********************** '------------------------------------------------------------------------------ ' DDS - Gosub-Routine: Dds_links_verarbeiten ' ' Routine verarbeitet das Drehen des DDS nach links ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Viele ... (zu viele um hier einzeln beschrieben zu erden!) '------------------------------------------------------------------------------ Dds_links_verarbeiten: ' ----- Programmcode ----- ' Bearbeitungsflag zurücksetzen Dds_flag = Dds_none ' Buchstabenzeiger verringern und Grenzwerte überprüfen Decr Game_buchstaben_index If Game_buchstaben_index = 0 Then Game_buchstaben_index = 26 End If ' Grenzwert erreicht ' Scrollbaren Buchstabenasuwahltext auf LCD-Display aktualisieren Gosub Game_update_scrolltext Gosub Lcd_print_scrolltext ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit ' Ggf. Debugausgaben schreiben #if Dds_testmodus Print "DDS links - Index = " ; Game_buchstaben_index #endif ' Prüfung ob bypass aktiv, wenn ja verarbeiten If Game_bypassmode_flag = True Then ' JA, Bypassmode aktiv Incr Game_bypassmode_leftcounter ' Prüfen ob Linkscounter zu hoch, wenn ja Bypassmodus deaktivieren If Game_bypassmode_leftcounter > Game_leftcount_max Then ' Ja, Bypassmodus verlassen Game_bypassmode_leftcounter = 0 Game_bypassmode_flag = False ' ggf. Trace ausgeben #if Bypass_testmodus Print "Bypass zuruecksetzen" #endif End If ' Prüfung Linkscounter ' ggf. Trace ausgeben #if Bypass_testmodus Print "Linkscounter = " ; Game_bypassmode_leftcounter #endif End If ' Behandlung Bypassmode Return '-- End Dds_links_verarbeiten ------------------------------------------------- '------------------------------------------------------------------------------ ' DDS - Gosub-Routine: Dds_Dds_rechts_verarbeiten ' ' Routine verarbeitet das Drehen des DDS nach links ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Viele ... (zu viele um hier einzeln beschrieben zu erden!) '------------------------------------------------------------------------------ Dds_rechts_verarbeiten: ' ----- Programmcode ----- ' Bearbeitungsflag zurücksetzen Dds_flag = Dds_none ' Buchstabenzeiger erhöhen und Grenzwerte überprüfen Incr Game_buchstaben_index If Game_buchstaben_index = 27 Then Game_buchstaben_index = 1 End If ' Grenzwert erreicht? ' Scrollbaren Buchstabenasuwahltext auf LCD-Display aktualisieren Gosub Game_update_scrolltext Gosub Lcd_print_scrolltext ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit ' Ggf. Debugausgaben schreiben #if Dds_testmodus Print "DDS rechts - Index = " ; Game_buchstaben_index #endif ' Prüfung ob bypass aktiv UND Linkscounter auf Max-Value, wenn ja verarbeiten If Game_bypassmode_flag = True And Game_bypassmode_leftcounter = Game_leftcount_max Then ' JA, Bypassmode aktiv Incr Game_bypassmode_rightcounter ' Prüfen ob Rightcounter zu hoch, wenn ja Bypassmodus deaktivieren If Game_bypassmode_rightcounter > Game_rightcount_max Then ' Ja, Bypassmodus verlassen Game_bypassmode_rightcounter = 0 Game_bypassmode_flag = False ' ggf. Trace ausgeben #if Bypass_testmodus Print "Bypass zuruecksetzen" #endif End If ' Prüfung Linkscounter ' ggf. Trace ausgeben #if Bypass_testmodus Print "Rechtscounter = " ; Game_bypassmode_rightcounter #endif Else ' Behandlung Bypassmode ' Bypassmodus verlassen Game_bypassmode_rightcounter = 0 Game_bypassmode_flag = False ' ggf. Trace ausgeben #if Bypass_testmodus Print "Bypass zuruecksetzen" #endif End If ' Behandlung Bypassmode Return '-- End Dds_rechts_verarbeiten ------------------------------------------------ '------------------------------------------------------------------------------ ' DDS - Gosub-Routine: Dds_Taste_erkannt ' ' Routine gibt nur Traceausgabe aus, dass Taste erkannt wurde ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Viele ... (zu viele um hier einzeln beschrieben zu erden!) '------------------------------------------------------------------------------ Dds_taste_erkannt: ' ----- Programmcode ----- ' Ggf. Debugausgaben schreiben #if Dds_testmodus Print "DDS gedueckt" #endif ' Prüfen ob der Bildschirm abgeschaltet ist und der DDS betätigt wurden If Lcd_beleuchtung_status = Lcd_beleuchtung_status_aus Then 'JA -> Beleuchtung einschalten und DDS ignorieren Gosub Lcd_beleuchtung_ein ' Hintergrundbeleuchtung einschalten Lcd_beleuchtung_status = Lcd_beleuchtung_status_ein ' Hintergrundbeleuchtung ist EIN Else ' Bildschirm abgeschaltet? ' Prüfen ob Bypassmodus aktiv und Triggerbedingungen erfüllt If Game_bypassmode_flag = True Then ' Prüfen ob Bypassbedingungen erfüllt sind If Game_bypassmode_leftcounter = Game_leftcount_max And Game_bypassmode_rightcounter = Game_rightcount_max Then ' JA, Bedingungen erfüllt, nun können Koordinaten auch ohne Spiel angezeigt werden ' ggf. Trace ausgeben #if Bypass_testmodus Print "Bypass ausloesen, Koordinaten anzeigen" #endif ' Gamestatus setzen und fertig Game_ablaufstatus = 3 ' Counter für Bypassmode erhöhen und in EEPROM speichern Incr Ee_bypass_counter Ee_data_bypass_counter = Ee_bypass_counter ' Aktuelle Counter Value auf Display ausgeben ' 1234567890123456 Cls Locate 1 , 1 : Lcd "Bypasscounter:" Locate 2 , 1 : Lcd Ee_bypass_counter End If ' Bypassbedingungen erfüllt? ' In jedem Fall Counter und Flags wieder zurücksetzen Game_bypassmode_flag = False Game_bypassmode_leftcounter = 0 Game_bypassmode_rightcounter = 0 ' ggf. Trace ausgeben #if Bypass_testmodus Print "Bypassflags und Counter zuruecksetzen" #endif Else ' Bypassmode? ' NEIN -> Normale PTT Verarbeitung und Auswertung der Eingabe ' Ggf. Trace schreiben #if Game_testmodus Print "Auswertung PTT" #endif ' Prüfen ob Zeichen schon ausgewählt wurde und Buchstabe mit Unterstrich ausge-x-t ' If Game_scrolltext_zeichen(7) <> Game_fuellzeichen Then If Game_scrolltext_zeichen(7) <> Game_cursorzeichen Then ' JA -> Zeichen ist gültig #if Game_testmodus Print "Zeichen ist gueltig : " ; Chr(game_scrolltext_zeichen(7) ) Print "Game_suchtext : " ; Game_suchtext Print "Game_scrolltext : " ; Game_scrolltext #endif ' Nun im Rätseltext nach dem Buchstaben suchen und ggf. Buchstaben in Suchtext eintragen Temp_byte_2 = False For Temp_byte_1 = 1 To 13 Step 1 If Game_suchtext_zeichen(temp_byte_1) = Game_scrolltext_zeichen(7) Then ' Zeichen gefunden Temp_byte_2 = True Game_raetseltext_zeichen(temp_byte_1 ) = Game_scrolltext_zeichen(7) End If ' Suchtextzeichen = Scrolltextzeichen? Next ' Schleife über alle Zeichen ' Nun prüfen ob passende Zeichen gefunden wurden If Temp_byte_2 = True Then ' JA Gosub Lcd_print_raetseltext ' Kurzes Piep ausgeben Gosub Sound_piep_100ms Waitms 100 Gosub Sound_piep_100ms Else ' Zeichen gefunden ' nein Incr Game_hangman_status #if Game_testmodus Print "Fehler Hangman status : " ; Game_hangman_status #endif Call Lcd_print_hangingman(game_hangman_status ) ' Maennchen gemaess Status zeichnen ' Prüfen ob Spiel schon zuende If Game_hangman_status = 5 Then ' Spielstatus weiterschalten Game_ablaufstatus = 2 ' Rätseltext übernehmen und anzeigen da Spiel eh zuende Game_raetseltext = Game_suchtext Gosub Lcd_print_raetseltext End If ' Spiel zuende ' Piepston ausgeben und warten Gosub Sound_piep_1s ' Wait 1 End If ' Fehler gemacht ' Gesamten Auswahltext nach dem ausgewählten Zeichen durchsuchen und mit Füllzeichen besetzen ' ==> Zeichen kann nicht mehr ausgewählt werden. ' Gesuchtes Zeichen ist kleingeschrieben, daher muss scrolltext_zeichen angepasst werden Temp_byte_2 = Game_scrolltext_zeichen(7) + 32 ' Ggf. Debugausgaben schreiben #if Dds_testmodus Print "Rücksetzzeichen = " ; Chr(temp_byte_2) #endif For Temp_byte_1 = 1 To 38 Step 1 If Game_auswahltext_zeichen(temp_byte_1 ) = Temp_byte_2 Then ' Zeichen gefunden Game_auswahltext_zeichen(temp_byte_1 ) = Game_fuellzeichen ' Ggf. Debugausgaben schreiben #if Dds_testmodus Print "Zeichen gefunden" #endif End If ' Textposition entspricht Füllzeichen Next ' Schleife über alle Zeichen ' Scrolltext updaten !!! nicht vergessen Gosub Game_update_scrolltext Gosub Lcd_print_scrolltext #if Game_testmodus Print "Game_raetseltext : " ; Game_raetseltext #endif ' Nun prüfen ob bisheriger Text dem gesuchen Wort entspricht If Game_raetseltext = Game_suchtext And Game_hangman_status < 5 Then ' JA #if Game_testmodus Print "Jippi gewonnen" #endif ' Spielstatus weiterschalten Game_ablaufstatus = 3 End If ' Rätseltext=Suchtext & Status<5 End If ' Ungültiges Zeichen End If ' Bypassmode? ' Logik für Abschaltung Hintergrundbeleuchtung erneut "aufziehen" Lcd_abschaltcounter = Sectick_counter + Lcd_abschaltzeit End If ' Bypassmode=True & leftcounter=leftcount_max Return '-- End Dds_Taste_erkannt ----------------------------------------------------- ' ******** ' * GAME * ' ******** '------------------------------------------------------------------------------ ' GAME - Gosub-Routine: Game_suchtext_select ' ' Routine ermittelt via Zufallszahl den im Spiel zu suchenden Text aus dem ' DATA Bereich. ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Game_suchtext = Arbeitsvariable in dem Suchtext zur Verfügung gestellt wird. '------------------------------------------------------------------------------ Game_suchtext_select: ' ----- Programmcode ----- ' Zufallszahl ermitteln Temp_byte_1 = Rnd(game_anzahl_text ) ' Random bei z.B. 40 = 0-39 ' Suchtext auslesen Game_suchtext = Lookupstr(temp_byte_1 , Worte_data) ' Falls Flag für Debuging gesetzt debugausgaben ausgeben #if Game_testmodus Print "Index : " ; Temp_byte_1 Print "Text : " ; Game_suchtext #endif Return '-- End Game_suchtext_select -------------------------------------------------- '------------------------------------------------------------------------------ ' GAME - Gosub-Routine: Game_update_scrolltext ' ' Routine überträgt aus dem Gesamtstring game_auswahltext den für die Ausgabe ' auf dem Display relevanten Teil in die globale Variable game_scrolltext. ' Dabei der der mittlerste Buchstabe welche ausgewählt werden kann ggf. ' als Großbuchstabe dargestellt. ' Wurde der Buchstabe bereits ausgewählt und ist er als Leerzeichen gekenn- ' zeichnet wird der Buchstabe ignoriert. ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' Game_scrolltext = Teilstring für die Ausgabe auf dem Display ' Game_auswahltext = Gesamtstring auf dem gearbeitet wird ' Game_buchstaben_index = Index auf aktuelle A-Z Buchstabenposition '------------------------------------------------------------------------------ Game_update_scrolltext: ' ----- Programmcode ----- ' 1 2 3 ' 12345678901234567890123456789012345678 ' uvwxyzabcdefghijklmnopqrstuvwxyzabcdef ' abcdefghijklmnopqrstuvwxyz ' 12345678901234567890123456 ' 1 2 ' Zeile 1 ist Scrolltext ' Zeile 2 ist Raetseltext Game_scrolltext = Mid(game_auswahltext , Game_buchstaben_index , 13 ) ' Überprüfen ob Zeichen ein NULL-gesetztes Zeichen ist, also dass der Buchstabe ' schon mal ausgewählt wurde. Wenn NEIN Buchstaben GROSS setzen If Game_scrolltext_zeichen(7) <> Game_fuellzeichen Then ' NEIN -> Buchstaben GROSS schreiben Game_scrolltext_zeichen(7) = Game_scrolltext_zeichen(7) - 32 Else ' Null gesetztes Zeichen ? ' JA -> An nicht mehr gültiger Cursorstelle ein Cursorzeichen ausgeben Game_scrolltext_zeichen(7) = Game_cursorzeichen End If ' Null gesetztes Zeichen ? Return '-- End Game_update_scrolltext ------------------------------------------------ ' ********* ' * SOUND * ' ********* '------------------------------------------------------------------------------ ' SOUND - Gosub-Routine: Sound_piep_100ms ' ' Routine piepst für 100 ms ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' -- '------------------------------------------------------------------------------ Sound_piep_100ms: ' ----- Programmcode ----- Piezosound = Sound_ein Waitms 100 Piezosound = Sound_aus Return '-- End Sound_piep_100ms ------------------------------------------------------ '------------------------------------------------------------------------------ ' SOUND - Gosub-Routine: Sound_piep_400ms ' ' Routine piepst für 400 ms ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' -- '------------------------------------------------------------------------------ Sound_piep_400ms: ' ----- Programmcode ----- Piezosound = Sound_ein Waitms 400 Piezosound = Sound_aus Return '-- End Sound_piep_400ms ------------------------------------------------------ '------------------------------------------------------------------------------ ' SOUND - Gosub-Routine: Sound_piep_1s ' ' Routine piepst für 1s ' ' Parameter: keine ' Rückgabe: keine ' ' Globale Variablen: ' -- '------------------------------------------------------------------------------ Sound_piep_1s: ' ----- Programmcode ----- Piezosound = Sound_ein Wait 1 Piezosound = Sound_aus Return '-- End Sound_piep_1s --------------------------------------------------------- ' ********** ' * 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 --------------------------------------------------------------- '------------------------------------------------------------------------------ ' Devices schließend und ggf. "Terminate Programm execution" '------------------------------------------------------------------------------ ' System halt End 'end program '------------------------------------------------------------------------------ ' Definition von globalen Konstantenfeldern '------------------------------------------------------------------------------ Worte_data: Data "WELTRAUMFAHRT" ' 1 Data "ABENTEUERLICH" ' 2 Data "ABENTEUERLUST" ' 3 Data "ANLAGEOBJEKTE" ' 4 Data "ASTROGEOLOGIE" ' 5 Data "ASTROBIOLOGIE" ' 6 Data "BERGKRISTALLE" ' 7 Data "BERGSTATIONEN" ' 8 Data "BERGSTEIGEREI" ' 9 Data "BERGWANDERUNG" ' 10 Data "MYSTERYCACHES" ' 11 Data "HAUSAPOTHEKEN" ' 12 Data "HAUSVERWALTER" ' 13 Data "HAUSHALTSWARE" ' 14 Data "FESTSPIELHAUS" ' 15 Data "FALSCHAUSSAGE" ' 16 Data "WOCHENENDHAUS" ' 17 Data "HAUSBESETZUNG" ' 18 Data "WACKELKONTAKT" ' 19 Data "WACHTELSCHLAG" ' 20 Data "FAHRRADFAHREN" ' 21 Data "DURCHGELAUFEN" ' 22 Data "ASPHALTCOWBOY" ' 23 Data "ARBEITSZIMMER" ' 24 Data "FEUERWEHRAUTO" ' 25 Data "ABSCHIEDSKUSS" ' 26 Data "BUNDESKANZLER" ' 27 Data "ZWIEBELSCHALE" ' 28 Data "BANKGEHEIMNIS" ' 29 Data "ANSICHTSKARTE" ' 30 Data "ASTROPHYSIKER" ' 31 Data "FEUERWEHRMANN" ' 32 Data "KALENDERMONAT" ' 33 Data "HAFENARBEITER" ' 34 Data "COMPUTERFIRMA" ' 35 Data "KNOBLAUCHZEHE" ' 36 Data "LEUCHTREKLAME" ' 37 Data "MINUTENZEIGER" ' 38 Data "VERSTECKSPIEL" ' 39 Data "AMEISENHAUFEN" ' 40 Data "KAPITALANLAGE" ' 41 Data "GANGSCHALTUNG" ' 42 Data "MUTTERSPRACHE" ' 43 Data "BERUFSBERATER" ' 44 Data "NEBELSCHWADEN" ' 45 Data "OBERINSPEKTOR" ' 46 Data "WASCHMASCHINE" ' 47 Data "BLUMENSCHMUCK" ' 48 Data "ORIENTTEPPICH" ' 49 Data "DAMPFMASCHINE" ' 50 Data "PERSONENWAGEN" ' 51 Data "POLIZEISCHUTZ" ' 52 Data "FAMILIENNAMEN" ' 53 Data "RASIERAPPARAT" ' 54 Data "SATTELTASCHEN" ' 55 Data "ZAPPELPHILIPP" ' 56 Data "TASCHENMESSER" ' 57 Data "IDEENREICHTUM" ' 58 Data "TODESKANDIDAT" ' 59 Data "KANONENFUTTER" ' 60 Data "GEISTERSTUNDE" ' 61 Data "UMSTANDSKLEID" ' 62 Data "INNENMINISTER" ' 63 Data "RAUMFORSCHUNG" ' 64 Data "UNTEROFFIZIER" ' 65 Data "COMPUTERSPIEL" ' 66 Data "VANILLESCHOTE" ' 67 Data "POLTERGEISTER" ' 68 Data "VERSUCHSREIHE" ' 69 Data "ELEKTROMAGNET" ' 70 Data "WALNUSSKUCHEN" ' 71 Data "SCHATTENBOXEN" ' 72 Data "HAUPTSCHALTER" ' 73 Data "ZIMMERANTENNE" ' 74 Data "WASSERLEITUNG" ' 75 Data "ERDUMLAUFBAHN" ' 76 Data "ZUGVERBINDUNG" ' 77 Data "EINTRITTSGELD" ' 78 Data "WARTESCHLANGE" ' 79 Data "ZUCKERMELONEN" ' 80 Data "ENERGIEQUELLE" ' 81 Data "WASSERSPIEGEL" ' 82 Data "VERKEHRSCHAOS" ' 83 Data "ENERGIEBEDARF" ' 84 Data "SCHMERZMITTEL" ' 85 Data "VERBOTSSCHILD" ' 86 Data "NIEDRIGWASSER" ' 87 Data "FAHRRADREIFEN" ' 88 Data "TROMMELBREMSE" ' 89 Data "SCHAUKELSTUHL" ' 90 Data "INFRASTRUKTUR" ' 91 Data "RECHENAUFGABE" ' 92 Data "POLIZEIWACHEN" ' 93 Data "ZAHLENSCHLOSS" ' 94 Data "MODEINDUSTRIE" ' 95 Data "LICHTSCHALTER" ' 96 Data "BRIEFUMSCHLAG" ' 97 Data "KLASSENZIMMER" ' 98 Data "HAUTAUSSCHLAG" ' 99 Data "INSEKTENPLAGE" ' 100 ' ---------------------------------------------------------------------------- '###################################### END ################################### '################################### Historie ################################# ' ' 30.05.2014 : Version x.x ' Beginn der Implementierungen für Hanging Man. ' Fertigstellung Inbetriebnahme LCD-Display und wichtigster ' Funktionen. ' ----------------------------------------------------------------------------- ' 09.06.2014 : B_SIGNAL und PUSH_SIGNAL wegen Erfassung über Interrupt 1 ' getauscht. ' ----------------------------------------------------------------------------- ' 02.07.2014 : Restarbeiten und Begriffe auf 100 Stück ergänzt. ' ----------------------------------------------------------------------------- ' 04.07.2014 : Spiel-Bypass eingebaut um Koordinaten ohne Spiel anzeigen ' zu können :-) ' ----------------------------------------------------------------------------- ' 09.07.2014 : Bypasscounter implementiert und Ablage Counter in EEPROM ' ----------------------------------------------------------------------------- ' 09.07.2014 : Versions 1.0 - Fertigstellung erste Produktivversion ' '##############################################################################