Thomas E.
07.10.2012, 12:17
Um mich etwas in ein KS0108-GLCD einzuarbeiten entstand aus einer "Drauf-los-Programmiererei" ein kleines Pong-Spiel.
Der Hintergrund dazu: Eigentlich wird aus der ganzen Sache mal ein Datenlogger mit USB-Stick, da ich aber bisher nur T6963C-Displays verwendet habe und dieses Projekt erstmal ein KS0108-GLCD verwendet habe ich mich mal in der Ansteuerung versucht. Grundsätzlich besitzt dieses Display einige Tücken. So muss zum Beispiel ein Grafik-Befehl in einem Rutsch ausgeführt werden und darf keinesfalls unterbrochen werden (z. B. durch einen Interrupt). Während das T6963C-Display bei Unterbrechung gemütlich gewartet hat, bis der Befehl vollständig übertragen wurde, führt das KS0108 den angebrochenen Befehl sofort aus - mit interessanten Folgen. Anschließend stimmt nichts mehr und jeder darauffolgende Befehl wird völlig falsch ausgeführt. Ebenfalls tödlich ist das Beschreiben außerhalb der Display-Position: Das T6963C-Display hat den Befehl dann einfach ignoriert während das KS0108-Display quasi überläuft und eine exestierende Position nimmt, ähnlich wie wenn man einer Bytevariable mit dem Wert null den Wert eins abzieht, was den Wert 255 als Ergebnis liefert.
Zum Programm: Es ist eine Quick'n'Dirty-Lösung, die rein aus dem Bauch heraus entstand. Wenn ich mich dazu motivieren kann werde ich den Code vielleicht noch umschreiben und erweitern, damit was schönes dabei rauskommt. Trotzdem funktioniert die Sache bereits tadellos.
Wird der Ball mit dem Schläger getroffen gibt es einen Punkt, verfehlt man den Ball wird ein Punkt abgezogen. Weniger wie null Punkte gibts nicht.
Vielleicht hat ja jemand Spaß daran und entwickelt es weiter oder spielt einfach nur ein paar Runden. :)
'#########
'## EDT ##
'#########
'---------
'KS0108-Ansteuerung
'V1.0
'07.10.2012
'BASCOM 2.0.7.5
'---------
'schaltplan_ks0108ans_v1_0.dsn
'---------
'DEMO- und Testprogramm zur Ansteuerung eines GLCDs mit KS0108-Controller.
'Mit optional angeschlossenen Tastern an Pind.0 und Pind.1 kann das Spiel gespielt werden.
'---------
$regfile = "m32def.dat" 'AtMega32
$crystal = 1000000 '1Mhz
$hwstack = 32 'nicht optimiert
$swstack = 8 'nicht optimiert
$framesize = 32 'nicht optimiert
Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
Portd.0 = 1
Portd.1 = 1
Portd.2 = 1
Portd.3 = 1
'KONFIGURATION TIMER0
Config Timer0 = Timer , Prescale = 256 '65,5ms
On Timer0 Isr_timer0
Enable Timer0
Start Timer0
'VARIABLEN
Dim X As Byte 'X-Pos. des Balls
Dim Y As Byte 'Y-Pos. des Balls
Dim X_dir As Bit 'Horizontale Laufrichtung 1=rechts, 0=links
Dim Y_dir As Bit 'Vertikale Laufrichtung 1=unten, 0=oben
Dim X_bar As Byte 'X-Position des Schlägers (linkes Ende)
Dim X_bar_offset As Byte 'X-Position des Schlägers (rechtes Ende)
Dim X_bar_temp As Byte 'Schlägerposition zum Rechnen
Dim Y_bar As Byte 'Y-Postion des Schlägers
Dim Point As Byte 'Punktestand
Dim Timer_flag As Bit 'Timer Flag
Dim I As Byte 'Indexvariable für For-Schleife
'INITIALISIEREN DER VARIABLEN
X = 20 'X-Pos. des Balls am Start
Y = 20 'Y-Pos. des Balls am Start
Y_bar = 60 'X-Pos. des Schlägers am Start
X_bar = 20 'Y_Pos. des Schlägers
$lib "glcdKS108.lbx" 'Lib für das Display
Config Graphlcd = 128 * 64sed , Dataport = Portc , Controlport = Porta , Ce = 4 , Ce2 = 3 , Cd = 0 , Rd = 1 , Reset = 5 , Enable = 2
Cls 'LCD-löschen
Setfont My6_8
Lcdat 1 , 1 , "GLCD-DEMO" , 0
Lcdat 2 , 1 , "----------" , 0
Lcdat 4 , 1 , "KS0108-GLCD 128x64" , 0
Lcdat 5 , 1 , "AtMega32 @1Mhz" , 0
Lcdat 6 , 1 , "EDT 2012" , 0
Wait 1
Cls
Enable Interrupts
'### HAUPTSCHLEIFE ###
Do
If Timer_flag = 1 Then
Pset X , Y , 0 'Ball löschen
If X_dir = 1 Then Incr X Else Decr X 'Ballbewegung X-Ache
If Y_dir = 1 Then Incr Y Else Decr Y 'Ballbewegung Y-Achse
If X = 127 Then X_dir = 0 'Richtungswechsel X-Achse
If Y = 63 Then 'Verzweigung wenn Ball am unteren Spielrand
Y_dir = 0 'Richtungswechsel Y-Achse
If Point > 0 Then Decr Point 'Punktestand dekrementieren
End If
If X = 1 Then X_dir = 1 'Richtungswechsel X-Achse
If Y = 1 Then Y_dir = 1 'Richtungswechsel Y-Achse
X_bar_temp = X_bar 'Temporäre Variable zum Rechnen mit der aktuellen Schlägerpos. füllen
For I = 1 To 10 'For-Schleife mit 10 Durchläufen
If Y = 60 And X = X_bar_temp And Y_dir = 1 Then 'Abfrage ob Ball die Schlägerposition erreicht hat
Incr Point 'wenn ja, Punktestand inkrementieren
Toggle Y_dir 'und Richtungswechsel Y-Achse
End If
Incr X_bar_temp 'Temporäre Variable mit Schlägerposition um eins erhöhen
Next
Pset X , Y , 1 'Ball zeichnen
If Pind.0 = 0 Then
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 0 'Schläger löschen
If X_bar > 10 Then Decr X_bar 'Schlägerposition dekrementieren
X_bar_offset = X_bar + 10 'Rechtes Schlägerende neu berechnen
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 1 'Schläger zeichnen
End If
If Pind.1 = 0 Then
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 0
If X_bar < 100 Then Incr X_bar
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 1
End If
Lcdat 1 , 1 , Point , 0 'Punktestand zeichnen
Reset Timer_flag
End If
Loop
'### ISR ###
Isr_timer0:
Set Timer_flag
Return
End
$include "my6_8.font"
Der Hintergrund dazu: Eigentlich wird aus der ganzen Sache mal ein Datenlogger mit USB-Stick, da ich aber bisher nur T6963C-Displays verwendet habe und dieses Projekt erstmal ein KS0108-GLCD verwendet habe ich mich mal in der Ansteuerung versucht. Grundsätzlich besitzt dieses Display einige Tücken. So muss zum Beispiel ein Grafik-Befehl in einem Rutsch ausgeführt werden und darf keinesfalls unterbrochen werden (z. B. durch einen Interrupt). Während das T6963C-Display bei Unterbrechung gemütlich gewartet hat, bis der Befehl vollständig übertragen wurde, führt das KS0108 den angebrochenen Befehl sofort aus - mit interessanten Folgen. Anschließend stimmt nichts mehr und jeder darauffolgende Befehl wird völlig falsch ausgeführt. Ebenfalls tödlich ist das Beschreiben außerhalb der Display-Position: Das T6963C-Display hat den Befehl dann einfach ignoriert während das KS0108-Display quasi überläuft und eine exestierende Position nimmt, ähnlich wie wenn man einer Bytevariable mit dem Wert null den Wert eins abzieht, was den Wert 255 als Ergebnis liefert.
Zum Programm: Es ist eine Quick'n'Dirty-Lösung, die rein aus dem Bauch heraus entstand. Wenn ich mich dazu motivieren kann werde ich den Code vielleicht noch umschreiben und erweitern, damit was schönes dabei rauskommt. Trotzdem funktioniert die Sache bereits tadellos.
Wird der Ball mit dem Schläger getroffen gibt es einen Punkt, verfehlt man den Ball wird ein Punkt abgezogen. Weniger wie null Punkte gibts nicht.
Vielleicht hat ja jemand Spaß daran und entwickelt es weiter oder spielt einfach nur ein paar Runden. :)
'#########
'## EDT ##
'#########
'---------
'KS0108-Ansteuerung
'V1.0
'07.10.2012
'BASCOM 2.0.7.5
'---------
'schaltplan_ks0108ans_v1_0.dsn
'---------
'DEMO- und Testprogramm zur Ansteuerung eines GLCDs mit KS0108-Controller.
'Mit optional angeschlossenen Tastern an Pind.0 und Pind.1 kann das Spiel gespielt werden.
'---------
$regfile = "m32def.dat" 'AtMega32
$crystal = 1000000 '1Mhz
$hwstack = 32 'nicht optimiert
$swstack = 8 'nicht optimiert
$framesize = 32 'nicht optimiert
Config Pind.0 = Input
Config Pind.1 = Input
Config Pind.2 = Input
Config Pind.3 = Input
Portd.0 = 1
Portd.1 = 1
Portd.2 = 1
Portd.3 = 1
'KONFIGURATION TIMER0
Config Timer0 = Timer , Prescale = 256 '65,5ms
On Timer0 Isr_timer0
Enable Timer0
Start Timer0
'VARIABLEN
Dim X As Byte 'X-Pos. des Balls
Dim Y As Byte 'Y-Pos. des Balls
Dim X_dir As Bit 'Horizontale Laufrichtung 1=rechts, 0=links
Dim Y_dir As Bit 'Vertikale Laufrichtung 1=unten, 0=oben
Dim X_bar As Byte 'X-Position des Schlägers (linkes Ende)
Dim X_bar_offset As Byte 'X-Position des Schlägers (rechtes Ende)
Dim X_bar_temp As Byte 'Schlägerposition zum Rechnen
Dim Y_bar As Byte 'Y-Postion des Schlägers
Dim Point As Byte 'Punktestand
Dim Timer_flag As Bit 'Timer Flag
Dim I As Byte 'Indexvariable für For-Schleife
'INITIALISIEREN DER VARIABLEN
X = 20 'X-Pos. des Balls am Start
Y = 20 'Y-Pos. des Balls am Start
Y_bar = 60 'X-Pos. des Schlägers am Start
X_bar = 20 'Y_Pos. des Schlägers
$lib "glcdKS108.lbx" 'Lib für das Display
Config Graphlcd = 128 * 64sed , Dataport = Portc , Controlport = Porta , Ce = 4 , Ce2 = 3 , Cd = 0 , Rd = 1 , Reset = 5 , Enable = 2
Cls 'LCD-löschen
Setfont My6_8
Lcdat 1 , 1 , "GLCD-DEMO" , 0
Lcdat 2 , 1 , "----------" , 0
Lcdat 4 , 1 , "KS0108-GLCD 128x64" , 0
Lcdat 5 , 1 , "AtMega32 @1Mhz" , 0
Lcdat 6 , 1 , "EDT 2012" , 0
Wait 1
Cls
Enable Interrupts
'### HAUPTSCHLEIFE ###
Do
If Timer_flag = 1 Then
Pset X , Y , 0 'Ball löschen
If X_dir = 1 Then Incr X Else Decr X 'Ballbewegung X-Ache
If Y_dir = 1 Then Incr Y Else Decr Y 'Ballbewegung Y-Achse
If X = 127 Then X_dir = 0 'Richtungswechsel X-Achse
If Y = 63 Then 'Verzweigung wenn Ball am unteren Spielrand
Y_dir = 0 'Richtungswechsel Y-Achse
If Point > 0 Then Decr Point 'Punktestand dekrementieren
End If
If X = 1 Then X_dir = 1 'Richtungswechsel X-Achse
If Y = 1 Then Y_dir = 1 'Richtungswechsel Y-Achse
X_bar_temp = X_bar 'Temporäre Variable zum Rechnen mit der aktuellen Schlägerpos. füllen
For I = 1 To 10 'For-Schleife mit 10 Durchläufen
If Y = 60 And X = X_bar_temp And Y_dir = 1 Then 'Abfrage ob Ball die Schlägerposition erreicht hat
Incr Point 'wenn ja, Punktestand inkrementieren
Toggle Y_dir 'und Richtungswechsel Y-Achse
End If
Incr X_bar_temp 'Temporäre Variable mit Schlägerposition um eins erhöhen
Next
Pset X , Y , 1 'Ball zeichnen
If Pind.0 = 0 Then
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 0 'Schläger löschen
If X_bar > 10 Then Decr X_bar 'Schlägerposition dekrementieren
X_bar_offset = X_bar + 10 'Rechtes Schlägerende neu berechnen
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 1 'Schläger zeichnen
End If
If Pind.1 = 0 Then
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 0
If X_bar < 100 Then Incr X_bar
X_bar_offset = X_bar + 10
Line(x_bar , Y_bar) -(x_bar_offset , Y_bar) , 1
End If
Lcdat 1 , 1 , Point , 0 'Punktestand zeichnen
Reset Timer_flag
End If
Loop
'### ISR ###
Isr_timer0:
Set Timer_flag
Return
End
$include "my6_8.font"