#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
#define F_CPU 16000000UL
#define LED_RED PA2
#define LED_GREEN PA1
#define BUTTON_SW1 PA0
#define RESPONSE_THRESHOLD 10000 // 1000 ms en décimas
volatile uint16_t response_time = 0;
volatile uint8_t counting = 0;
static long holdrand = 1L;
void srand(unsigned int seed) { holdrand = (long)seed; }
int rand(void) { return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff); }
void UART_putchar(uint8_t com, char data) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
void UART_puts(uint8_t com, char *str){
while(*str){
UART_putchar(com, *str);
str++;
}
}
void UART_print_time(uint16_t time) {
char buffer[20];
uint16_t ms = time / 10;
uint16_t dec = time % 10;
snprintf(buffer, sizeof(buffer), "%u.%u ms\r\n", ms, dec);
UART_puts(0, buffer);
}
#define frec 16000000
void UART_Ini(uint8_t com, uint32_t baudrate, uint8_t size, uint8_t parity, uint8_t stop)
{
uint8_t Velocidad = 0;
uint32_t closesmatchNormal, ubrrNormal, closesmatchDoble, ubrrDoble, errorNormal, errorDoble;
//--------------------------------------------------------------
ubrrNormal = (frec / (16 * baudrate)) - 1;
ubrrDoble = (frec / (8 * baudrate)) - 1;
//--------------------------------------------------------------
closesmatchNormal = frec / (16 * (ubrrNormal + 1));
closesmatchDoble = frec / (8 * (ubrrNormal + 1));
//--------------------------------------------------------------
errorNormal = ((closesmatchNormal / ubrrNormal)-1) * 100;
errorDoble = ((closesmatchDoble / ubrrDoble)-1) * 100;
//--------------------------------------------------------------
if (errorNormal> errorDoble)
Velocidad = 2;
if (parity == 1)
parity = 3;
switch (com)
{
case 0:
UCSR0A = Velocidad;
UCSR0B = (3<< TXEN0);
UCSR0C = ((size - 5) << UCSZ00) | ((stop - 1) << USBS0) | (parity << UPM00);
if (Velocidad==2)
UBRR0 = ubrrDoble;
else
UBRR0 = ubrrNormal;
break;
case 1:
UCSR1A = Velocidad;
UCSR1B = (3<< TXEN0);
UCSR1C = ((size - 5) << UCSZ10) | ((stop - 1) << USBS1) | (parity << UPM10);
if (Velocidad==2)
UBRR1 = ubrrDoble;
else
UBRR1 = ubrrNormal;
break;
case 2:
UCSR2A = Velocidad;
UCSR2B = (3<< TXEN0);
UCSR2C = ((size - 5) << UCSZ20) | ((stop - 1) << USBS2) | (parity << UPM20);
if (Velocidad==2)
UBRR2 = ubrrDoble;
else
UBRR2 = ubrrNormal;
break;
case 3:
UCSR3A = Velocidad;
UCSR3B = (3<< TXEN0);
UCSR3C = ((size - 5) << UCSZ30) | ((stop - 1) << USBS3) | (parity << UPM30);
if (Velocidad==2)
UBRR3 = ubrrDoble;
else
UBRR3 = ubrrNormal;
break;
}
}
void Timer2_Init() {
TCCR2A = 0;
TCCR2B = (1 << CS20); // sin prescaler
TIMSK2 = (1 << TOIE2);
TCNT2 = 131; // Desborde cada 25.5 us → acumulamos 4 veces = 102 us ≈ 0.1 ms
}
ISR(TIMER2_OVF_vect) {
static uint8_t count = 0;
TCNT2 = 131;
if (counting) {
count++;
if (count >= 4) { // 4 * 25.5 us ≈ 0.1 ms
response_time++;
count = 0;
}
}
}
void GPIO_Init() {
DDRA &= ~(1 << BUTTON_SW1); // entrada
DDRA |= (1 << LED_GREEN) | (1 << LED_RED); // salida
PORTA = 0x00; //&= ~((1 << LED_GREEN) | (1 << LED_RED)); // apaga LEDs
}
uint16_t get_random_delay() {
return (rand() % 9000 + 1000); // ms
}
int main(void) {
UART_Ini(0, 115200, 8, 0, 1);
UART_puts(0, "Presiona una tecla para iniciar.\r\n");
while (!(UCSR0A & (1 << RXC0)));
UDR0; // Limpiar buffer
GPIO_Init();
Timer2_Init();
sei();
srand(100);
while (1) {
//while (!(PINA & (1 << BUTTON_SW1)));
UART_puts(0, "Prepárate...\r\n");
// while ((PINA & (1 << BUTTON_SW1)));
uint16_t wait_time = get_random_delay();
for (uint16_t i = 0; i < wait_time; i++) _delay_ms(1);
PORTA |= (1 << LED_GREEN);
response_time = 0;
counting = 1;
while (!(PINA & (1 << BUTTON_SW1))); // espera presionar botón
counting = 0;
PORTA &= ~(1 << LED_GREEN);
if (response_time > RESPONSE_THRESHOLD) {
PORTA |= (1 << LED_RED);
UART_puts(0, "Tiempo de respuesta: ");
UART_print_time(response_time);
_delay_ms(2000);
PORTA &= ~(1 << LED_RED);
} else {
UART_puts(0, "¡Buena respuesta!\r\n");
}
}
}