#include <avr/io.h>
#include <avr/interrupt.h>
#define FOSC 16000000 // Clock Speed
#define BAUD 9600
#define MYUBRR (FOSC/16/BAUD-1)
static long holdrand = 1L;
static volatile uint8_t MilisFlag;
static uint32_t milis;
static uint8_t UCounter;
static uint32_t globalMilis;
int main(void) {
uint8_t randomSec;
char str[10];
// Initializations
UCounter = 0;
milis = 0;
gpio_ini();
uart_ini(MYUBRR);
Timer2_Ini();
uart_puts("Ingrese una tecla para iniciar\n");
uart_getchar();
srand(globalMilis);
while (1) {
uart_puts("Advertencia\n");
uart_puts("Iniciando programa...");
// Generate random delay
randomSec = getRandomNumber();
uart_itoa(randomSec, str, 10);
uart_puts(str);
uart_putchar('\n');
for (uint8_t counter = 0; counter < randomSec; counter++) {
secondDelay();
uart_itoa(counter + 1, str, 10);
uart_puts(str);
uart_putchar('\n');
milis = 0;
}
globalMilis = 0;
led_On_Off(1);
while ((PINA >> PA3) & 1)
;
uart_itoa(globalMilis, str, 10);
uart_puts(str);
uart_putchar('.');
uart_itoa(UCounter, str, 10);
uart_puts(str);
uart_puts(" ms");
uart_putchar('\n');
randomSec = 2;
for (uint8_t counter = 0; counter < randomSec; counter++)
{
if (globalMilis > 1000)
{
led_On_Off(2);
secondDelay();
uart_itoa(counter + 1, str, 10);
uart_puts(str);
uart_putchar('\n');
milis = 0;
led_On_Off(3);
}
}
Msdelay();
milis++;
}
return 0;
}
// Function implementations
void srand(unsigned int seed) {
holdrand = (long)seed;
}
int rand(void) {
return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
uint16_t getRandomNumber(void) {
uint16_t number = rand() & 0xf;
if (number > 10) {
number = 10;
} else if (number < 1) {
number = 1;
}
return number;
}
void uart_ini(int ubrr) {
UBRR0L = ubrr;
UBRR0H = (ubrr >> 8);
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (3 << UCSZ00);
}
void uart_putchar(unsigned char data) {
while (!(UCSR0A & (1 << UDRE0)))
;
UDR0 = data;
}
void uart_puts(char *str) {
while (*str != '\0') {
uart_putchar(*str++);
}
}
unsigned char uart_getchar(void) {
while (!(UCSR0A & (1 << RXC0)))
;
return UDR0;
}
void uart_itoa(uint32_t num, char* str, uint8_t base) {
uint8_t i = 0;
uint8_t is_negative = 0;
if (num == 0) {
str[i++] = '0';
str[i] = '\0';
return;
}
if (num < 0 && base == 10) {
is_negative = 1;
num = -num;
}
while (num != 0) {
int rem = num % base;
str[i++] = (rem > 9) ? (rem - 10) + 'A' : rem + '0';
num = num / base;
}
if (is_negative) {
str[i++] = '-';
}
uint16_t start = 0;
uint16_t end = i - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
start++;
end--;
}
str[i] = '\0';
}
void gpio_ini(void) {
DDRA = (1 << PA0) | (1 << PA1) | (1 << PA2);
PORTA = 0;
PORTA |= (1 << PA3);
}
void Timer2_Ini(void) {
TCNT2 = 0;
TCCR2A = 2 << WGM20;
OCR2A = 25 - 1;
TCCR2B = 0x04;
TIMSK2 = 1 << OCIE2A;
sei();
}
uint8_t Timer2_MilisFlag(void) {
if (MilisFlag) {
MilisFlag = 0;
return 1;
} else {
return 0;
}
}
ISR(TIMER2_COMPA_vect) {
TCNT2 = 0;
UCounter++;
if (UCounter == 10) {
globalMilis++;
UCounter = 0;
MilisFlag = 1;
}
}
void Msdelay(void) {
while (!Timer2_MilisFlag())
;
}
void secondDelay(void) {
while (milis < 1000) {
Msdelay();
milis++;
}
milis = 0;
}
void led_On_Off(uint8_t state) {
if (state == 1) {
PORTA |= (1 << PA1);
PORTA &= ~(1 << PA2);
} else if (state == 2) {
PORTA |= (1 << PA2);
PORTA &= ~(1 << PA1);
} else if (state == 3) {
PORTA &= ~(1 << PA1);
PORTA &= ~(1 << PA2);
}
}