#ifndef UART_H
#define UART_H

#include <stm32f4xx.h>
#include <stdint.h>
#include <stdbool.h>

typedef enum {
  USART_WORD_8_BITS = 0,
  USART_WORD_9_BITS = 1,
} usart_word_length_t;

typedef enum {
  USART_PARITY_EVEN = 0,
  USART_PARITY_ODD = 1,
} usart_parity_t;

typedef enum {
  USART_STOP_BIT_ONE = 0,
  USART_STOP_BIT_HALF = 1,
  USART_STOP_BIT_TWO = 2,
} usart_stop_bits_t;

typedef struct {
  USART_TypeDef* periph;
  uint8_t idx;
} uart_t;

void usart_init(uart_t* uart, USART_TypeDef* peripheral, uint8_t idx);

void usart_configure_speed(uart_t *uart,
                           uint32_t clock_speed_hz,
                           uint32_t baud);

void usart_configure_uart(uart_t* uart, bool enable,
                          usart_word_length_t length, bool parity_control,
                          usart_parity_t parity,
                          usart_stop_bits_t stop_bits);

void usart_configure_receiver(uart_t* uart, bool enable);
void usart_configure_transmitter(uart_t* uart, bool enable);

uint16_t usart_transmit(uart_t* uart, char* data, uint16_t size);
uint16_t usart_receive(uart_t* uart, char* buffer, uint16_t max_size);

bool usart_can_transmit(uart_t* uart);
uint16_t usart_can_receive(uart_t* uart);

void usart_enable_interrupt(uart_t* uart, bool tx, bool rx);

#endif // UART_H
