#include <stdint.h>
#include <stdio.h>

// Definições de registradores
#define RCC_BASE    0x40021000
#define GPIOC_BASE  0x40011000
#define USART1_BASE 0x40013800

#define RCC_APB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x18))
#define GPIOC_CRH   (*(volatile uint32_t *)(GPIOC_BASE + 0x04))
#define GPIOC_BSRR  (*(volatile uint32_t *)(GPIOC_BASE + 0x10))
#define USART1_SR   (*(volatile uint32_t *)(USART1_BASE + 0x00))
#define USART1_DR   (*(volatile uint32_t *)(USART1_BASE + 0x04))
#define USART1_BRR  (*(volatile uint32_t *)(USART1_BASE + 0x08))
#define USART1_CR1  (*(volatile uint32_t *)(USART1_BASE + 0x0C))

// Definições de bit para os registradores
#define RCC_APB2ENR_IOPCEN   (1 << 4)
#define RCC_APB2ENR_USART1EN (1 << 14)
#define GPIOC_CRH_MODE13     (1 << 20)
#define GPIOC_CRH_CNF13_0    (1 << 22)
#define GPIOC_CRH_CNF13_1    (1 << 23)
#define USART1_CR1_UE        (1 << 13)
#define USART1_CR1_TE        (1 << 3)
#define USART1_SR_TXE        (1 << 7)

void delay(volatile uint32_t count)
{
    while (count--)
        ;
}

void usart1_send(char ch)
{
    while (!(USART1_SR & USART1_SR_TXE))
        ;           // Espera até o buffer estar vazio
    USART1_DR = ch; // Envia o caractere
}

void usart1_send_string(const char *str)
{
    while (*str) {
        usart1_send(*str++);
    }
}

int main(void)
{
    // Habilita o clock para GPIOC e USART1
    RCC_APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_USART1EN;

    // Configura PC13 como saída push-pull, máxima velocidade 2 MHz
    GPIOC_CRH &= ~(0xF << 20);
    GPIOC_CRH |= (GPIOC_CRH_MODE13 | GPIOC_CRH_CNF13_0);

    // Configura USART1: Baud rate 9600, 8N1
    USART1_BRR = 0x1D4C; // Configuração para 72 MHz
    USART1_CR1 |= (USART1_CR1_UE | USART1_CR1_TE);

    while (1) {
        // Liga o LED (PC13 é ativo baixo)
        GPIOC_BSRR = (1 << 13) << 16;
        usart1_send_string("LED ON\r\n");
        delay(1000);

        // Desliga o LED
        GPIOC_BSRR = (1 << 13);
        usart1_send_string("LED OFF\r\n");
        delay(1000);
    }
}