#ifndef __IOMUX_REGISTERS_H__
#define __IOMUX_REGISTERS_H__

// MS Didn't even supply stdint.h! Ugh...
#include "stdint.h"  
#include "register_bitops.h"

#define IOMUXBaseAddress 0x43FAC000

PVOID MapPhysicalAddr(PVOID dwPhysicalAddress, DWORD dwSize);

namespace IOMUX
{
	//GM static volatile uint32_t virtualAddress = (uint32_t) MapPhysicalAddr((PVOID) 0x43FAC000, 0x7FFF); 
	//GM change size to 0xCFFF to span entire IOMUXC address space
	static volatile uint32_t virtualAddress = (uint32_t) MapPhysicalAddr((PVOID) IOMUXBaseAddress, 0xCFFF); 
	
	enum Registers
	{
		//IOMUXC Register
		GPR												= 0x0008,	//GM add GPR register

		//CSPI1 Registers
		CSPI_1mux_SS2_SCLK_SRDY_CSPI_2_MOSI				= 0x0088,	//GM CSPI1_SCLK mux register
		CSPI_1mux_MOSI_MISO_SS_SS1						= 0x008C,	//GM CSPI1_MOSI mux register
		CSPI_1pad_SCLK_SRDY_CSPI_2_MOSI					= 0x01FC,	//GM add CSPI1_SCLK pad config register
		CSPI_1pad_SFS6_MOSI_MISO						= 0x0204,	//GM add CSPI1_MOSI pad config register
	
		//GPIO registers
		GPIO1Mux_gpio1_0_gpio1_1_gpio1_2_gpio1_3		= 0X014C,	//GM add GPIO_3 mux register
		GPIO1Mux_usb_pwr_usb_oc_usb_byp_usbotg_clk		= 0X0054,	//GM add GPIO_3 mux register
		GPIO1Pad_pwmo_gpio1_0_gpio1_1					= 0X0304,
		GPIO1Pad_gpio1_2_gpio1_3_gpio1_4				= 0X0300,	//GM add GPIO_3 pad register
		GPIO1Pad_usb_pwr_usb_oc_usb_byp					= 0X01B8,	//GM add GPIO_3 pad register
		GPIO1Pad_capture_compare_watchdog_rst			= 0X0308
	};

	enum MUX_OUTPUT_SELECT
	{
		GPIO							= 0, 
		FUNCTIONAL_OUTPUT				= 1,
		ALTERNATE_MODE_1_OUTPUT			= 2
	};

	enum MUX_INPUT_SELECT
	{
		NO_INPUTS_SELECTED				= 0,
		GPIO_PSR_ISR_INPUT				= 1,
		FUNCTIONAL_INPUT				= 2,
//GM	ALTERNATE_MODE_1_INPUT			= 3
		ALTERNATE_MODE_1_INPUT			= 4	//GM according to ref manual
	};


	// Bits 25 and 24 of the control register
	enum IOMUX_REGISTER_BIT_FIELDS
	{
		SIGNAL_3_OUTPUT					= REGISTER_BIT_DEFINITION(30, 28),
		SIGNAL_3_INPUT					= REGISTER_BIT_DEFINITION(27, 24),
		SIGNAL_2_OUTPUT					= REGISTER_BIT_DEFINITION(22, 20),
		SIGNAL_2_INPUT					= REGISTER_BIT_DEFINITION(19, 16),
		SIGNAL_1_OUTPUT					= REGISTER_BIT_DEFINITION(14, 12),
		SIGNAL_1_INPUT					= REGISTER_BIT_DEFINITION(11,  8),
		SIGNAL_0_OUTPUT					= REGISTER_BIT_DEFINITION( 6,  4),
		SIGNAL_0_INPUT					= REGISTER_BIT_DEFINITION( 3,  0)
	};
	
	inline volatile uint32_t *regAddress(Registers reg)
	{
		return reinterpret_cast<volatile uint32_t*>(virtualAddress + reg);
	}
	
	inline uint32_t regRead(Registers reg)
	{
		return *regAddress(reg);
	}
	
	inline void regWrite(Registers reg, uint32_t value)
	{
		*regAddress(reg) = value;
	}
}

#endif // __IOMUX_REGISTERS_H__
