Spielbeschreibung
Ein Leuchtpunkt wandert zwischen L0 und L8 hin und her. An den Endpunkten wird ein Ton ausgegeben.
Ein Treffer wird gelandet, wenn bei leuchtender L4 T1 gedrückt wird.
Dies wird durch einen höheren Ton signalisiert, dabei erhöht sich der Level, das Spiel wird schneller. Drückt man daneben geht es zurück auf Level 0. Es gibt auch einen "Cheat-Modus", finde raus wie er aktiviert wird.
Quellcode [zReaktionsspiel.ino ] // *** Zylon-Reaktions-Spiel V1.0 (c) Oliver Mezger 9.2.2020 ***
// Taktfrequenz auf 1MHz einstellen
#include <avr/io.h> // Definitionen laden
#include <util/delay.h> // Delay-Bibliothek laden
#include <avr/pgmspace.h> // Flashzugriffe laden
// C-Dur Frequenzen als Periodendauer F_CPU ist Systemtakt
const unsigned int PROGMEM ton[ ] = { F_CPU/ 264 , F_CPU/ 297 , F_CPU/ 330 , F_CPU/ 352 ,
F_CPU/ 396 , F_CPU/ 440 , F_CPU/ 495 } ;
unsigned char ledausgabe[ ] = { 0xe1 , 0xe2 , 0xe4 , 0xe8 , 0xd1 , 0xd2 ,
0xd4 , 0xd8 , 0xb1 , 0xb2 , 0xb4 , 0xb8 , 0x71 , 0x72 , 0x74 , 0x78 } ;
void piepen( unsigned char n) { // Ausgabe eines kurzen Tons
OCR1A = pgm_read_word( & ton[ n% 7 ] ) >> ( n/ 7 ) ; // pro Oktave halbe Periodendauer
OCR1B = OCR1A/ 2 ;
TCCR1A = 0b00100011 ; // Ausgang OC1B bei 0 setzen und bei OCR1B loeschen
_delay_ms( 70 ) ; // Tondauer
TCCR1A = 0b00000011 ; // Sound wieder aus
}
unsigned char buttonOld= 0 , buttonEnter= 0 ;
void checkButton( ) {
unsigned char bu= ~PIND>> 4 ; // Einlesen
buttonEnter = ~buttonOld & bu;
buttonOld= bu;
}
volatile unsigned char leuchtPunkt= 0 , piep= 0 ;
ISR( TIMER0_COMPA_vect) { // bewegt den Leuchtpunkt
static unsigned char up= 1 ;
if ( up) {
leuchtPunkt = leuchtPunkt + 1 ;
if ( leuchtPunkt >= 8 ) { // wenn oben angekommen
up= 0 ;
piep= 1 ; // einen tiefen Piep ausgeben
}
}
else {
leuchtPunkt = leuchtPunkt - 1 ;
if ( leuchtPunkt == 0 ) { // wenn unten angekommen
up = 1 ;
piep= 2 ; // einen hohen Piep ausgeben
}
}
PORTB = ledausgabe[ leuchtPunkt] ; //ausgeben Leuchtpunkt
}
int main( ) {
unsigned char level= 0 , cheat= 0 ;
DDRB = 0xff ; // PB0..7 als Ausgang
PORTD = 0x7f ; // Pullups an
TCCR1A= 0b00100011 ; // Ausgang OC1B bei 0 setzen und bei OCR1B loeschen
TCCR1B= 0b00011001 ; // Waveform Generation Mode: Fast PWM it OCR1A als Top, Timer mit CPU-CLK
TCCR0B= 5 ; // Phi / 1024
TCCR0A= 1 << WGM01; // CTC Mode mit OCR0A als TOP
TIMSK = 1 << OCIE0A; // Interrupt frei geben
OCR0A = 199 - level; // bei (199-level)*1024µs Interrupt
if ( ( PIND & 1 << PD4) == 0 ) cheat= 1 ;
sei( ) ;
while ( 1 ) { // Endlosschleife
checkButton( ) ; // Tastaturabfrage
if ( buttonEnter == 2 ) { // wurde Taste T1 gedrueckt?
if ( leuchtPunkt == 4 ) { //LED4
piepen( 12 ) ; piepen( 24 ) ; // Ton fuer getroffen
level++; // naechster Level
}
else {
piepen( 14 ) ; piepen( 8 ) ; piepen( 0 ) ; // Ton fuer daneben
level= 0 ; // zurueck auf unteren Level
}
OCR0A= 199 - ( level* 10 ) ; // Geschwindigkeit anpassen
}
if ( cheat && buttonEnter == 4 ) { // Taste T2
piepen( 12 ) ; piepen( 24 ) ;
level++;
OCR0A= 199 - ( level* 10 ) ;
}
if ( piep) { // wenn Eckpunkt erreicht Ton ausgeben
piepen( level+ ( piep- 1 ) * 8 ) ;
piep= 0 ;
}
}
}