/** @file usart.h
 * Module handling Universal Synchronous/Asynchronous Receiver/Transmitter
 *
 * The module provides functions to configure the usarts and read/write from/to
 * it
 */

#ifndef _USART_H_
#define _USART_H_

//--includes--------------------------------------------------------------------

#include "dma.h"

#include "stdint.h"


//--type definitions------------------------------------------------------------

/**
 * Available USART peripherals. Note that some of these peripherals may not be
 * available on all chips
 */
enum UsartPeriph {
	USART_PERIPH_1,
	USART_PERIPH_2,
	USART_PERIPH_3,
};

/**
 * Available configuration options
 */
enum UsartConfig {
	USART_CONFIG_7E1,
	USART_CONFIG_7E2,
	USART_CONFIG_7O1,
	USART_CONFIG_7O2,
	USART_CONFIG_8N1,
	USART_CONFIG_8N2,
	USART_CONFIG_8E1,
	USART_CONFIG_8E2,
	USART_CONFIG_8O1,
	USART_CONFIG_8O2,
};


//--functions-------------------------------------------------------------------

/**
 * Configures the given USART peripheral using the provided condiguration
 * options and baudrate. The baudrate may be any value supported by the
 * peripheral, though some may not be exact due to precision errors (see
 * table 192 in documentation). The baudrate is dependant on the peripheral's
 * clock and changes to the later after this function has been called will cause
 * the effective baudrate to change
 *
 * This function doesn't configure the required ports. This should be done using
 * the gpio driver:
 * - Tx port should be using GPIO_CONFIG_OUT_ALT_PUSH_PULL with
 * the appropriate output speed based on the baurate (see GpioMode)
 * - Rx port should be using GPIO_CONFIG_IN_FLOATING in input mode
 * Both ports do not need to be configured if not used (e.g. if only using Tx,
 * the Rx port can be left unconfigured)
 */
void usart_configure(enum UsartPeriph periph, enum UsartConfig config,
		uint32_t baudrate);

/**
 * Resets the given USART peripheral, applying the default configuration and
 * disabling it
 */
void usart_reset(enum UsartPeriph periph);

/**
 * Reads a single byte to the given USART peripheral, returning 0 if
 * successfull, 1 otherwise.
 *
 * The Rx port must be configured for this function to ever return successfully
 */
uint32_t usart_read_byte(enum UsartPeriph periph, uint8_t* byte);

/**
 * Writes a single byte to the given USART peripheral, returning 0 if
 * successfull, 1 otherwise.
 *
 * The Tx port must be configured for this function to do anything, though the
 * function would still return 0
 */
uint32_t usart_write_byte(enum UsartPeriph periph, uint8_t byte);

/**
 * Configures the given USART peripheral for DMA Rx operations, returning the
 * corresponding DMA parameters to be used.
 *
 * The DMA must be configured separately using the DMA driver or an existing
 * service
 */
const struct DmaParam* usart_configure_rx_dma(enum UsartPeriph periph);

/**
 * Configures the given USART peripheral for DMA Rx operations, returning the
 * corresponding DMA parameters to be used.
 *
 * The DMA must be configured separately using the DMA driver or an existing
 * service
 */
const struct DmaParam* usart_configure_tx_dma(enum UsartPeriph periph);


#endif //_USART_H_

