#ifndef __FLASH_H__
#define __FLASH_H__

#include "types.h"
#include "base_addresses.h"
#include "bit_access.h"
#include "bitwise_enums.h"

class FLASH
{
	public:
		~FLASH(void) { ACR = 0; };
		enum { address = FLASH_R_BASE };
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }

	private:
		__IO uint32_t ACR;      // Access control register, Address offset: 0x00
		__IO uint32_t KEYR;     // Key register,            Address offset: 0x04
		__IO uint32_t OPTKEYR;  // Option key register,     Address offset: 0x08
		__IO uint32_t SR;       // Status register,         Address offset: 0x0C
		__IO uint32_t CR;       // Option control register, Address offset: 0x14

		enum FLASH_ACR_Bits {
			LATENCY			= REG_BIT_DEFN(  0,  2),
			PRFTEN			= REG_BIT_DEFN(  8,  8),
			ICEN			= REG_BIT_DEFN(  9,  9),
			DCEN			= REG_BIT_DEFN( 10, 10),
			ICRST			= REG_BIT_DEFN( 11, 11),
			DCRST			= REG_BIT_DEFN( 12, 12)
		};

		enum FLASH_SR_Bits {
			EOP             = REG_BIT_DEFN(  0,  0),
			OPERR			= REG_BIT_DEFN(  1,  1),
			WRPERR			= REG_BIT_DEFN(  4,  4),
			PGAERR			= REG_BIT_DEFN(  5,  5),
			PGPERR			= REG_BIT_DEFN(  6,  6),
			PGSERR			= REG_BIT_DEFN(  7,  7),
			BSY             = REG_BIT_DEFN( 16, 16)
		};

		enum FLASH_CR_Bits {
			PG				= REG_BIT_DEFN(  0,  0),
			SER				= REG_BIT_DEFN(  1,  1),
			MER				= REG_BIT_DEFN(  2,  2),
			SNB				= REG_BIT_DEFN(  3,  6),
			PSIZE			= REG_BIT_DEFN(  8,  9),
			STRT			= REG_BIT_DEFN( 16, 16),
			EOPIE			= REG_BIT_DEFN( 24, 24),
			ERRIE			= REG_BIT_DEFN( 25, 25),
			LOCK			= REG_BIT_DEFN( 31, 31)
		};

		enum FLASH_OPTCR_Bits {
			OPTLOCK			= REG_BIT_DEFN(  0,  0),
			OPTSTART		= REG_BIT_DEFN(  1,  1),
			BOR_LEV			= REG_BIT_DEFN(  2,  3),
			WDG_SW			= REG_BIT_DEFN(  5,  5),
			NRST_STOP		= REG_BIT_DEFN(  6,  6),
			NRST_STDBY		= REG_BIT_DEFN(  7,  7),
			RDP				= REG_BIT_DEFN(  8, 15),
			NWRP			= REG_BIT_DEFN( 16, 27)
		};

	public:
		void SetLatency(uint32_t waitStates) { bitWrite(ACR, LATENCY, waitStates); }

};

#endif // __FLASH_H__
