#include "stm32f4xx.h"

void delay(uint32_t count) {
    while (count--) {
        __asm("nop"); // Prevent compiler optimization
    }
}

void USART2_Init() {
    // Enable clock for GPIOA and USART2
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    RCC->APB1ENR |= RCC_APB1ENR_USART2EN;

    // Configure PA2 as USART2_TX (Alternate Function)
    GPIOA->MODER &= ~(0x3 << (2 * 2)); // Clear mode bits for PA2
    GPIOA->MODER |= (0x2 << (2 * 2));  // Set PA2 to alternate function

    GPIOA->AFR[0] &= ~(0xF << (2 * 4)); // Clear bits
    GPIOA->AFR[0] |= (0x7 << (2 * 4));  // Set Alternate Function to USART2 (AF7)

    // Configure USART2
    USART2->BRR = 0x8B; // Assuming 16 MHz clock, set baud rate to 115200
    USART2->CR1 |= USART_CR1_TE; // Enable transmitter
    USART2->CR1 |= USART_CR1_UE;  // Enable USART
}

void USART2_Write(char* str) {
    while (*str) {
        while (!(USART2->SR & USART_SR_TXE)); // Wait until TX buffer is empty
        USART2->DR = (uint8_t)(*str++); // Send character
    }
}

int main() {
    // Initialize USART
    USART2_Init();
    
    // Enable GPIOA clock (already done in USART2_Init, can be omitted)
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

    // Configure PA5 as output
    GPIOA->MODER &= ~(0x3 << (5 * 2)); // Clear mode bits for PA5
    GPIOA->MODER |= (0x1 << (5 * 2));  // Set PA5 as output (01)

    USART2_Write("Starting LED Blink...\n");

    while (1) {
        GPIOA->ODR |= (1 << 5);  // Turn on LED
        USART2_Write("LED ON\n");
        delay(1000000);          // Delay
        GPIOA->ODR &= ~(1 << 5); // Turn off LED
        USART2_Write("LED OFF\n");
        delay(1000000);          // Delay
    }
}