#ifndef __SCB_H__
#define __SCB_H__

#include "types.h"
#include "base_addresses.h"

// ARM Cortex M4 System Control Block
// This is not defined by ST but by ARM

class SCB
{
	public:

		typedef enum SystemHandlerIRQn {
			// Cortex-M4 Processor Exceptions Numbers
			NonMaskableInt_IRQn			= -14,      // Non Maskable Interrupt
			MemoryManagement_IRQn		= -12,      // Cortex-M4 Memory Management Interrupt
			BusFault_IRQn				= -11,      // Cortex-M4 Bus Fault Interrupt
			UsageFault_IRQn				= -10,      // Cortex-M4 Usage Fault Interrupt
			SVCall_IRQn					= -5,       // Cortex-M4 SV Call Interrupt
			DebugMonitor_IRQn			= -4,       // Cortex-M4 Debug Monitor Interrupt
			PendSV_IRQn					= -2,       // 14 Cortex-M4 Pend SV Interrupt
			SysTick_IRQn				= -1        // 15 Cortex-M4 System Tick Interrupt
		} SystemHandlerIRQn_Type;

		enum CPUID {
			ImplementerMask				= (0xFFUL   << 24),
			VariantMask					= (0xFUL    << 20),
			PartNumber					= (0xFFFUL  << 4),
			CPU_Revision				= (0xFUL    << 0)
		};

		// SCB Interrupt Control State Register Definitions
		enum ICSR {
			NMI_PendingMask				=	(1UL << 31),
			VectorTableBaseMask			=	(1UL << 29),
			Pending_SVC_SetMask         =	(1UL << 28),
			Pending_SVC_Clearmask		=	(1UL << 27),
			Pending_ST_SetMask			=	(1UL << 26),
			Pending_ST_ClearMask		=	(1UL << 25),
			ISR_PreemptedMask			=	(1UL << 23),
			ISR_PendingMask				=	(1UL << 22),
			VectorPendingMask			=	(0x1FFUL << 12),
			ReturnToBaseMask            =	(1UL << 11),
			VectorTableOffsetMask		=	(0x3FFFFFUL << 7),
			VectorActiveMask			=	(0x1FFUL << 0)
		};

		// SCB Application Interrupt and Reset Control Register Definitions
		enum AIRCR {
			VectorKeyMask				=	(0xFFFFUL << 16),  // On Write
			VectorStatusMask			=	(0xFFFFUL << 16),  // On read
			EndianessMask				=	(1UL << 15),
			PriorityGroupMask			=	(7UL << 8),
			SystemResetRequestMask		=	(1UL << 2),
			VectorClearActiveMask		=	(1UL << 1),
			VectorResetMask				=	(1UL << 0)
		};

		// SCB System Control Register Definitions
		enum SCR {
			SCB_SCR_SEVONPEND_Mask		=	(1UL << 4),
			DeepSleepMask				=	(1UL << 2),
			SleepOnExitMask				=   (1UL << 1)
		};

		// SCB Configuration Control Register Definitions
		enum CCR {
			StackAlignmentTrapMask		=	(1UL << 9),
			SCB_CCR_BFHFNMIGN_Msk       =   (1UL << 8),
			DivisionByZeroTrapMask		=	(1UL << 4),
			UnalignAccessTrapMask		=	(1UL << 3),
			SCB_CCR_USERSETMPEND_Mask	=	(1UL << 1),
			SCB_CCR_NONBASETHRDENA_Mask	=	(1UL << 0)
		};

		//  SCB System Handler Control and State Register Definitions
		enum SHCSR {
			UsageFaultEnabledMask		=	(1UL << 18),
			BusFaultEnabledMask			=	(1UL << 17),
			MemoryFaultEnabledMask		=	(1UL << 16),
			SVC_PendingMask				=	(1UL << 15),
			BusFaultPendingMask			=	(1UL << 14),
			MemoryFaultPendingMask		=	(1UL << 13),
			UsageFaultPendingMask		=	(1UL << 12),
			SystemTickActiveMask		=	(1UL << 11),
			Penidng_SVC_ActiveMask		=	(1UL << 10),
			MonitorActiveMask			=	(1UL << 8),
			SVC_ActiveMask				=	(1UL << 7),
			UsageFaultActivemask		=	(1UL << 3),
			BusFaultActiveMask			=	(1UL << 1),
			MemoryFaultActiveMask		=	(1UL << 0)
		};

		// SCB Configurable Fault Status Registers Definitions
		enum CFSR {
			UserFaultStatusMask			=	(0xFFFFUL << 16),
			BusFaultStatusMask			=	(0xFFUL << 8),
			MemoryFaultStatusMask		=	(0xFFUL << 0)
		};

		// SCB Hard Fault Status Registers Definitions
		enum HFSR {
			DebugEventMask				=	(1UL << 31),
			ForcedMask					=	(1UL << 30),
			VectorTableMask				=	(1UL <<  1)
		};

		// SCB Debug Fault Status Register Definitions
		enum DFSR {
			ExternalMask				=	(1UL << 4),
			VectorCatchMask				=	(1UL << 3),
			TrapMask					=	(1UL << 2),
			BreakpointMask				=	(1UL << 1),
			HaltedMask					=	(1UL << 0)
		};

		enum {address = SCB_BASE};
		void *operator new(size_t) { return reinterpret_cast<void *> (address); }

		void SetPriorityGrouping(uint32_t priorityGroup);
		uint32_t GetPriorityGrouping(void);

		void SetSystemHandlerPriority(SystemHandlerIRQn_Type IRQn, uint32_t priority);
		uint32_t GetSystemHandlerPriority(SystemHandlerIRQn_Type IRQn);

	private:
		__I  uint32_t CPUID;		// CPU ID Base Register
		__IO uint32_t ICSR;			// Interrupt Control State Register
		__IO uint32_t VTOR;			// Vector Table Offset Register
		__IO uint32_t AIRCR;		// Application Interrupt / Reset Control Register
		__IO uint32_t SCR;			// System Control Register
		__IO uint32_t CCR;			// Configuration Control Register
		__IO uint8_t  SHP[12];		// System Handlers Priority Registers (4-7, 8-11, 12-15)
		__IO uint32_t SHCSR;		// System Handler Control and State Register
		__IO uint32_t CFSR;			// Configurable Fault Status Register
		__IO uint32_t HFSR;			// Hard Fault Status Register
		__IO uint32_t DFSR;			// Debug Fault Status Register
		__IO uint32_t MMFAR;		// Mem Manage Address Register
		__IO uint32_t BFAR;			// Bus Fault Address Register
		__IO uint32_t AFSR;			// Auxiliary Fault Status Register
		__I  uint32_t PFR[2];		// Processor Feature Register
		__I  uint32_t DFR;          // Debug Feature Register
		__I  uint32_t ADR;          // Auxiliary Feature Register
		__I  uint32_t MMFR[4];      // Memory Model Feature Register
		__I  uint32_t ISAR[5];      // ISA Feature Register/
};

#endif // __SCB_H__
