/*
BITTE ERSTELLEN SIE SICH VORAB EINE PRIVATE KOPIE, DAZU
AUF "SAVE AS" GEHEN.
Aufgabenbeschreibung:
Es soll eine Steuerung aufgebaut werden, welche einen einfachen
Reaktionstester umsetzt.
Die Steuerung soll auf einem µC (AT-Mega 328, Arduino Uno)
realisiert werden.
Folgende Pin Belegung ist zu beachten
Port B
Bit 0/1/2/3/4/5/6/7
Bez Res/Res/Res/Res/Res/Res/Res/Res
Port D
Bit 0/1/2/3/4/5/6/7
Bez Res/Res/xTaster/Res/yBlue/Res/yYellow/Res
R1) Ein Taster ist angeschlossen und das Signal des Tasters
wird als xTaster in der Pin Belegung abgebildet.
R2) Es seien zwei LEDs angeschlossen, eine gelbe und eine blaue. Diese
sind durch über die Anschlüsse yBlue und yYellow in der Pin Belegung
abgebildet. Die beiden anderen LEDs dienen zur Überprüfung, ob Sie
reservierte Bits geändert haben.
R3) Der Reaktionstester soll fortwährend laufen, bis ein Fehler
in der HAS auftritt.
R4) Der Reaktionstester soll die Funktion void randomWait(void)
aufrufen, welche eine zufällige Zeit wartet. Sobald die Zeit abgelaufen
ist, soll die gelbe LED angeschaltet werden. Dies ist für den
Anwender das Zeichen, so schnell wie möglich auf den Taster zu drücken.
War die Reaktionszeit schneller als die bisherige Bestzeit des
Users, soll die blaue LED für eine Sekunde leuchten. Die gelbe LED
soll zeitgleich erlöschen.
Dies können Sie über die Funktion delay([Zeit in ms]) erreichen. War die
Zeit schlechter als die Bestzeit, soll die gelbe LED erlöschen, sobald
der User den Taster losgelassen hat. Die blaue LED soll in diesem
Fall nicht aufleuchten.
R5) Die Datenrichtungen sollen in einer InitIO() Funktion eingestellt werden.
R6) Alle Ihnen zur Verfügung stehenden Ausgänge sollen zu Beginn für
einen Zyklus auf 1 und dann auf 0 initialisiert werden. Dies soll in der initIO() geschehen.
R7) Nutzen Sie zum Lesen und Schreiben der digitalen Ein- und
Ausgänge die Funktionen InputByte und OutputByte der HAS.
R8) Wird beim Einlesen oder Ausgeben über die HAS ein Fehlerwert
zurückgegeben, sollen blaue und gelbe LED aufleuchten.
R9) Reservierte Bits dürfen nicht in Wert oder Datenrichtung geändert werden.
Ausgänge sind rücklesbar.
ACHTUNG:
Bitte nutzen Sie anstatt des bekannten int main(void) Aufbaus
eine void setup() + void loop() Struktur, wie folgend dargestellt.
Die Funktion setup() wird dabei bei der Abarbeitung einmal durchlaufen
und die Funktion loop() anschließend permanent.
*/
// typ bool ist bereits deklariert
typedef unsigned char uint8_t;
typedef unsigned char BYTE;
typedef enum {PB, PC, PD} PORT;
typedef enum {K0=0, K1, K2, K3, K4, K5, K6, K7} CHANNEL;
BYTE InitIO(){
// Kontrollvariablen
BYTE return_val = 1; //Rueckgabewert (mit 1 == Fehler initialisieren)
// Kontrolle Lesen, es kann kein Wert >255 gelesen werden also bekommt unsere Variable den Wert 256.
// Wenn das Lesen nicht Fuktioniert hat, kann so der Fehler festgestellt werden.
uint16_t val_inD = 256; // Bekommt Wert von gelesenen Port D
// Kontrolle schreiben. Mit der Maske, bei der nur Pin 2 als ,,Ausgang" festgelegt ist, wird kontrolliert,
// ob der Pin zwei von Port D als Ausgang definiert ist.
BYTE test_mask_D = ((1<<4)|(1<<6)); // Bit 4 und 6 auf 1
// Datenrichtung einstellen
// PORT D
DDRD|=((1<<4)|(1<<6)); // Pin 4 und 6 als Output festlegen alle anderen Bits bleiben gleich
DDRD &= ~(1<<2); // Pin 2 als Input festlegen (PB2=0) rest bleibt
// Einlesen
val_inD = PIND; // Lese Port Input Register von D ein und speichere in val_inD
// Kontrolle
if ((val_inD<256)&&((DDRD&test_mask_D)==test_mask_D)){ // Keine Fehler
return_val = 0; // Rueckgabewert 0 == Schreiben/ Lesen hat funktioniert
} // ende if
else { // Fehler erkannt
return_val = 1; // Rueckgabewert 1 == Schreiben/ Lesen hat nicht funktioniert
} // end else
} // end InitIO
uint8_t getTaste(uint8_t taste){
InputByte(PD, &taste);
taste &= (1 << 2);
taste = (taste >> 2);
return taste; // end getTaste
}
void preSetup(void){
// Pseudo-Funktion soll testen, ob reservierte Bits geändert wurden
BYTE PDval = 0b00000000;
BYTE PBval = 0b00100000;
DDRD = 0b00000010; // Output := 1, Input := 0
DDRB = 0b00100100; // Output := 1, Input := 0
OutputByte(PD, PDval);
OutputByte(PB, PBval);
}
BYTE InputByte (PORT PortName, BYTE* ReadValue){
// Hardwareabstraktionsschicht, Einlesen und Abspeichern an Adresse ReadValue
if (PortName == PB){
*ReadValue = PINB;
}
else if (PortName == PC){
*ReadValue = PINC;
}
else if (PortName == PD){
*ReadValue = PIND;
}
// Pseudo Error Code Generation
int returnVal = 0;
int randNumber = random(100); // Random number for error code
if (randNumber < 3) returnVal = randNumber; // Return Value depending on random number
return(returnVal);
}
BYTE OutputByte (PORT PortName, BYTE WriteValue){
// Hardwareabstraktionsschicht, Ausgabe des Bytes WriteValue am Port PortName
if (PortName == PB){
PORTB = WriteValue;
}
else if (PortName == PC){
PORTC = WriteValue;
}
else if (PortName == PD){
PORTD = WriteValue;
}
// Pseudo Error Code Generation
int returnVal = 0;
int randNumber = random(100); // Random number for error code
if (randNumber > 98) returnVal = randNumber; // Return Value depending on random number
return(returnVal);
}
void randomWait(void){
int randMilliSec = 3000 + random(20000); // Value between 3000 and 23000 ms
delay(randMilliSec);
}
void setup(){
// Code, der nur einmal ausgeführt wird
BYTE return_value = InitIO(); // Rueckgabewert von InitIO
if (return_value == 1){ // In / Output Definieren hat nicht funktioniert
return_value |= ((1<<4)|(1<<6)); // Stellen an denen die Leuchten sind 1 setzen
OutputByte (PD, return_value); // Leuchten einschalten
} // end if
} // end setup
void loop(){
// Pseudofunktion zum Testen, ob reservierte Bits geaendert wurden
// Rote LED darf nicht leuchten, Gruene muss leuchten
preSetup();
// Ab hier Ihr Code
int problem=0;
while(problem == 0){
uint8_t mask_gelb = 0x00;
uint8_t mask_LED = 0x00; //Maske für Gelb und Blau um Runde zu Starten
uint8_t mask_taste = 0x00;
bool taste = false;
static int reaktionsZeit = 0;
static int bestZeit = 10000;
//problem=InputByte(PD, &mask_LED); //Die Mask für LED und Gelb werden auf den PinD gesetzt
//problem=InputByte(PD, mask_gelb);
//Die LEDs leuchten für eine 0.5 sec auf
//um eine neue Runde Aufzuzählen
mask_LED |= (1 << 4) | (1 << 6);
problem=OutputByte(PD, mask_LED);
delay(500);
//Beide LED nicht mehr leuchten
mask_LED &= ~((1 << 4) | (1 << 6));
problem=OutputByte(PD, mask_LED);
//Wir warten nun für eine random Zeit und dann wird die Gelbe LED angemacht
randomWait();
mask_gelb |= (1 << 6); //Bit 6 setzten auf high
problem=OutputByte(PD, mask_gelb); //Gelbe Lampe leuchten lassen
//Hier wird die Zeit gemessen bis der Taster gedrückt wurde
do{
taste = getTaste(mask_taste);
delay(10); //Um die Tickzahl auf eine 1/100 sec genau zu messen und nicht auf die Tickzahl des Computers
reaktionsZeit++;
} while(taste==0);
//Wenn die reaktionsZeit kleiner der bestZeit
if(reaktionsZeit <= bestZeit){
//Serial.println("Bestzeit!!!!");
bestZeit = reaktionsZeit; //neue Bestzeit
reaktionsZeit = 0; //reaktionsZeit wird resettet
mask_LED |= (1 << 4) | (1 << 6); //Gelbe und Blaue LED wird angemacht
problem=OutputByte(PD, mask_LED);
delay(1000); //1 Sec warten
mask_LED &= ~((1 << 4) | (1 << 6)); //Beide LEDs werden ausgemacht
problem=OutputByte(PD, mask_LED);
}
else{
/* while(taste==true){
taste = getTaste(mask_taste);
}*/
reaktionsZeit = 0;
mask_gelb &= ~(1 << 6);
problem=OutputByte(PD, mask_gelb);
}
delay(2000);
}
// Do nothing more, wegen Umstrickung main() --> loop(), nach Fehler
// "Abbruch"
while(1) {
}
} // end loop