#ifndef __USART_H__
#define __USART_H__

#include "types.h"
#include "base_addresses.h"

class USART
{
	public:
		void SetBaudRate(uint32_t baudRate);
		void Send(char ch);
		void Send(const char* string);
		uint8_t Receive(void);
		bool Readable(void);

	private:
		  __IO uint16_t SR;         // USART Status register,                   Address offset: 0x00
		  __IO uint16_t RESERVED0;  // Reserved, 0x02
		  __IO uint16_t DR;         // USART Data register,                     Address offset: 0x04
		  __IO uint16_t RESERVED1;  // Reserved, 0x06
		  __IO uint16_t BRR;        // USART Baud rate register,                Address offset: 0x08
		  __IO uint16_t RESERVED2;  // Reserved, 0x0A
		  __IO uint16_t CR1;        // USART Control register 1,                Address offset: 0x0C
		  __IO uint16_t RESERVED3;  // Reserved, 0x0E
		  __IO uint16_t CR2;        // USART Control register 2,                Address offset: 0x10
		  __IO uint16_t RESERVED4;  // Reserved, 0x12
		  __IO uint16_t CR3;        // USART Control register 3,                Address offset: 0x14
		  __IO uint16_t RESERVED5;  // Reserved, 0x16
		  __IO uint16_t GTPR;       // USART Guard time and prescaler register, Address offset: 0x18
		  __IO uint16_t RESERVED6;  // Reserved, 0x1A
};

class USART_1 : public USART
{
	public:
		enum {address = USART1_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }
};

class USART_2 : public USART
{
	public:
		enum { address = USART2_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }
};

class USART_3 : public USART
{
	public:
		enum {address = USART3_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }
};

class UART_4 : public USART
{
	public:
		enum { address = UART4_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }
};

class UART_5 : public USART
{
	public:
		enum { address = UART5_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }
};

#if 0
class USART_6 : public USART
{
	public:
		enum {address = USART6_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }
		void Reset(void);
		void Enable(void);
		void Disable(void);
		static void InterruptHandler(void);
};
#endif

#endif // __USART_H__
