/*
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;
// Debug konstante
const bool ENABLE_ERROR = true;
// Deklaration konstanter hilfs-bytes
const BYTE BLUE = 0x10;
const BYTE YELLOW = 0x40;
const BYTE CLEAR_OUTPUT = ~BLUE & ~YELLOW;
const BYTE BTN = 0x04;
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 && ENABLE_ERROR) returnVal = randNumber; // Return Value depending on random number
return(returnVal);
}
// Wrapper on InputByte to accomodate for errors
void errInputByte(PORT portName, BYTE* readValue){
if(InputByte(portName, readValue)){
OutputByte(PD, *readValue | YELLOW | BLUE);
}
}
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 && ENABLE_ERROR) returnVal = randNumber; // Return Value depending on random number
return(returnVal);
}
// Wrapper on OutputByte to accomodate for errors
void errOutputByte(PORT portName, BYTE writeValue){
if(OutputByte(portName, writeValue)){
BYTE pdVal;
InputByte(portName, &pdVal);
OutputByte(PD, pdVal | YELLOW | BLUE);
}
}
void randomWait(void){
int randMilliSec = 3000 + random(1000); // Value between 3000 and 23000 ms
delay(randMilliSec);
}
void setup(){
// Code, der nur einmal ausgef�hrt wird
//Serial.begin(9600);
initIO();
}
void loop(){
// Pseudofunktion zum Testen, ob reservierte Bits geaendert wurden
// Rote LED darf nicht leuchten, Gruene muss leuchten
preSetup();
// BYTEs zum speichern des Tasterzustands
BYTE btnByte = ~BTN;
BYTE pdBuffer = 0x00;
//Variablen zum errechnen der reaktionszeit
unsigned long t0 = 0;
unsigned long deltaT = 0;
//static damit es �ber loops hinweg erhalten bleibt
static unsigned long fastestTime = 999999999;
// being "game" logic
randomWait();
// take start time
t0 = millis();
// while "button not pressed"
while(btnByte != 0xFF){
// shine yellow
errOutputByte(PD, (pdBuffer | YELLOW) & ~BLUE);
// check if button is pressed
errInputByte(PD, &pdBuffer);
btnByte |= pdBuffer;
}
// how long did it take to press the button
deltaT = millis()-t0;
// Clear Output
errInputByte(PD, &pdBuffer);
errOutputByte(PD, pdBuffer & CLEAR_OUTPUT);
delay(1000);
// Show win?
if(deltaT < fastestTime){
fastestTime = deltaT;
errInputByte(PD, &pdBuffer);
errOutputByte(PD, (pdBuffer | BLUE) & ~YELLOW);
delay(1000);
}
// Clear Output
errInputByte(PD, &pdBuffer);
errOutputByte(PD, pdBuffer & CLEAR_OUTPUT);
}
// initialisierung der Datenrichtungen und erstmaliges an- und ausschalten der LEDs
void initIO(){
BYTE pdBuffer;
//Initialisierung der gebrauchten Ausg�nge unter beibehaltung der reservierten Bits
DDRD |= BLUE | YELLOW;
DDRD &= ~BTN;
// LEDs an schalten
errInputByte(PD, &pdBuffer);
errOutputByte(PD, pdBuffer | BLUE | YELLOW);
//warte um nachzuvollziehen, dass die Output gesetzt wurden.
delay(1000);
// LEDs aus schalten
errInputByte(PD, &pdBuffer);
errOutputByte(PD, pdBuffer & CLEAR_OUTPUT);
}