#include <avr/io.h>
#include <avr/interrupt.h>
//#include <stdio.h>
//#include <stdlib.h>
static volatile uint32_t mSecCnt = 0;
static volatile uint32_t timer_overflow = 0;
char time[20];
#define LED_GRN PA1
#define LED_RED PA2
#define SW1 PA0
void PORT_INI(void) // Inicializa el puerto según el diagrama
{
// LEDs
DDRA |= (1 << PA1) | (1 << PA2) | (1 << PA3); // Habilito PA1 y PA2 como salida
PORTA |= 1 << PA2; // PA2 pull up
// Boton
DDRA &= ~(1 << PA0); // PA0 como entrada
PORTA |= 1 << PA0; // Pull-Up para PA0
}
static long holdrand = 1L;
void srand(unsigned int seed)
{
holdrand = (long)seed;
}
int rand(void)
{
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
int random_time(void)
{
return rand() % 10 + 1; // Generar un número aleatorio entre 1 y 10
}
void Timer0_Ini(void)
{
OCR0A = 249; // El tope para 1 milisegundo (16MHz / (64 * 1000) - 1)
TCCR0A = (1 << WGM01); // Configuro a modo CTC
TCCR0B = (1 << CS01) | (1 << CS00); // Configuro prescalador a 64
TIMSK0 = (1 << OCIE0A); // Habilito la interrupcion
sei(); // Habilito las interrupciones globales
}
ISR(TIMER0_COMPA_vect)
{
mSecCnt++; /* Incrementa contador de milisegundos */
}
void Timer1_Ini()
{
// Configurar Timer1 en modo de cuenta con prescaler de 8
OCR1A = 249; // El tope para 1 milisegundo (16MHz / (64 * 1000) - 1)
TCCR1A = (1 << WGM11); // Configuro a modo CTC
TCCR1B = (1 << CS11) | (1 << CS10); // Configuro prescalador a 64
TIMSK1 = (1 << OCIE1A); // Habilito la interrupcion
}
ISR(TIMER1_COMPA_vect)
{
timer_overflow++;
}
void delayS(uint8_t s)
{
// Reiniciar el contador y el indicador de desbordamiento
TCNT1 = 0;
timer_overflow = 0;
while (timer_overflow < s * 500)
;
}
void UART0_INI()
{
UCSR0A = 0; //U2X = 0 (Double speed)
UCSR0B = (0<<UCSZ02)| (1<<RXEN0) | (1<<TXEN0); // 9bits-data?| Recieve Enable | Transmit Enable
UCSR0C = (0<<UPM00) | (0<<USBS0) | (3<<UCSZ00); //Parity disabled | 1bit-stop | 8bit-Size
UBRR0 = 8; //115200K e=-3.5%
}
void UART0_PUTCHAR(char data)
{
while(!(UCSR0A & (1<<UDRE0)))
;
UDR0 = data;
}
void UART0_PUTS(char *str)
{
while(*str)
{
UART0_PUTCHAR(*str); //Toma el dato
str++; //Aumenta el apuntador
}
}
void itoa(uint16_t number, char* str)
{
uint8_t base = 10;
uint16_t residue;
uint16_t i = 0, j = 0;
uint8_t temp_stack[16];
while(number >= base && j < 16)
{
residue = number % base;
temp_stack[j] = residue;
number = number / base;
j++;
}
temp_stack[j] = number;
while(j > 0)
{
number = temp_stack[j];
if(number >= 10)
str[i] = number + '7';
else
str[i] = number + '0';
j--;
i++;
}
number = temp_stack[j];
if(number >= 10)
str[i] = number + '7';
else
str[i] = number + '0';
i++;
str[i] = '\x0';
}
/* Convierte numero a cadena con libreria: intToString(mSecCnt,time);
void intToString(int numero, char *cadena) {
// Utilizar sprintf para formatear el número como una cadena
sprintf(cadena, "%d", numero);
}
Convierte cadena a numero con librerias: int numero = stringToInt(cadena);
int stringToInt(const char *cadena) {
// Utilizar la función atoi para convertir la cadena a un número entero
return atoi(cadena);
}
*/
int main(void)
{
UART0_INI();
PORT_INI();
Timer0_Ini();
Timer1_Ini();
UART0_PUTS("Presione el boton para iniciar\n");
while (PINA & (1 << SW1))
;
UART0_PUTS("Juego iniciado\n");
while (1)
{
delayS(random_time()); // Esperar un tiempo aleatorio
PORTA |= 1 << LED_GRN; // Encender LED verde
TCNT0 = 0; // Comenzar a contar el tiempo
mSecCnt = 0;
while (PINA & (1 << SW1))
; // Esperar a que el usuario presione el botón
PORTA &= ~(1 << LED_GRN); // Apagar LED verde
itoa(mSecCnt,time);
UART0_PUTS(time);
UART0_PUTS("ms\n");
if (mSecCnt > 1000)
{ // Si el tiempo de respuesta es mayor a un segundo
PORTA &= ~(1 << LED_RED); // Encender LED rojo
delayS(2); // Esperar 2 segundos
PORTA |= 1 << LED_RED; // Apagar LED rojo
}
}
return 0;
}