#ifndef __BASE_ADDRESSES_H__
#define __BASE_ADDRESSES_H__

#include "types.h"

enum Address_Spaces {
	FLASH_BASE			= ((uint32_t) 0x08000000),				// FLASH(up to 1 MB), base address in the alias region
	CCMDATARAM_BASE     = ((uint32_t) 0x10000000),				// CCM(core coupled memory), data RAM(64 KB), base address
	SRAM1_BASE          = ((uint32_t) 0x20000000),				// SRAM1(112 KB), base address in the alias region
	SRAM2_BASE          = ((uint32_t) 0x2001C000),				// SRAM2(16 KB), base address in the alias region
	PERIPH_BASE         = ((uint32_t) 0x40000000),				// Peripheral base address in the alias region
	BKPSRAM_BASE        = ((uint32_t) 0x40024000),				// Backup SRAM(4 KB), base address in the alias region
	FSMC_R_BASE         = ((uint32_t) 0xA0000000)				// FSMC registers base address
};


// System Control
enum System_Control {
	SCS_BASE			= ((uint32_t) (0xE000E000)),			// System Control Space Base Address
	ITM_BASE            = ((uint32_t) (0xE0000000)),			// ITM Base Address
	CORE_DEBUG_BASE     = ((uint32_t) (0xE000EDF0)),			// Core Debug Base Address
	SYSTICK_BASE        = ((uint32_t) (SCS_BASE + 0x0010)),	 	// SysTick Base Address
	NVIC_BASE           = ((uint32_t) (SCS_BASE + 0x0100)),  	// NVIC Base Address
	SCB_BASE            = ((uint32_t) (SCS_BASE + 0x0D00UL))	// System Control Block Base Address
};

// Peripheral Memory Map
enum Peripheral_Memory_Map {
	APB1_PERIPH_BASE	= ((uint32_t) (PERIPH_BASE)),
	APB2_PERIPH_BASE    = ((uint32_t) (PERIPH_BASE + 0x00010000)),
	AHB1_PERIPH_BASE    = ((uint32_t) (PERIPH_BASE + 0x00020000)),
	AHB2_PERIPH_BASE    = ((uint32_t) (PERIPH_BASE + 0x10000000))
};

// APB1 peripherals
enum APB1_Peripherals {
	TIM2_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x0000)),
	TIM3_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x0400)),
	TIM4_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x0800)),
	TIM5_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x0C00)),
	TIM6_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x1000)),
	TIM7_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x1400)),
	TIM12_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x1800)),
	TIM13_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x1C00)),
	TIM14_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x2000)),
	RTC_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x2800)),
	WWDG_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x2C00)),
	IWDG_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x3000)),
	I2S2ext_BASE		= ((uint32_t) (APB1_PERIPH_BASE + 0x3400)),
	SPI2_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x3800)),
	SPI3_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x3C00)),
	I2S3ext_BASE		= ((uint32_t) (APB1_PERIPH_BASE + 0x4000)),
	USART2_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x4400)),
	USART3_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x4800)),
	UART4_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x4C00)),
	UART5_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x5000)),
	I2C1_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x5400)),
	I2C2_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x5800)),
	I2C3_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x5C00)),
	CAN1_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x6400)),
	CAN2_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x6800)),
	PWR_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x7000)),
	DAC_BASE			= ((uint32_t) (APB1_PERIPH_BASE + 0x7400))
};

// APB2 Peripherals
enum APB2_Peripherals {
	TIM1_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x0000)),
	TIM8_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x0400)),
	USART1_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x1000)),
	USART6_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x1400)),
	ADC1_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x2000)),
	ADC2_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x2100)),
	ADC3_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x2200)),
	ADC_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x2300)),
	SDIO_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x2C00)),
	SPI1_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x3000)),
	SYSCFG_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x3800)),
	EXTI_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x3C00)),
	TIM9_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x4000)),
	TIM10_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x4400)),
	TIM11_BASE			= ((uint32_t) (APB2_PERIPH_BASE + 0x4800))
};

// AHB1 Peripherals
enum AHB1_Peripherals {
	GPIOA_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x0000)),
	GPIOB_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x0400)),
	GPIOC_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x0800)),
	GPIOD_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x0C00)),
	GPIOE_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x1000)),
	GPIOF_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x1400)),
	GPIOG_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x1800)),
	GPIOH_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x1C00)),
	GPIOI_BASE            = ((uint32_t) (AHB1_PERIPH_BASE + 0x2000)),
	CRC_BASE              = ((uint32_t) (AHB1_PERIPH_BASE + 0x3000)),
	RCC_BASE              = ((uint32_t) (AHB1_PERIPH_BASE + 0x3800)),
	FLASH_R_BASE          = ((uint32_t) (AHB1_PERIPH_BASE + 0x3C00)),
	DMA1_BASE             = ((uint32_t) (AHB1_PERIPH_BASE + 0x6000)),
	DMA1_Stream0_BASE     = ((uint32_t) (DMA1_BASE + 0x010)),
	DMA1_Stream1_BASE     = ((uint32_t) (DMA1_BASE + 0x028)),
	DMA1_Stream2_BASE     = ((uint32_t) (DMA1_BASE + 0x040)),
	DMA1_Stream3_BASE     = ((uint32_t) (DMA1_BASE + 0x058)),
	DMA1_Stream4_BASE     = ((uint32_t) (DMA1_BASE + 0x070)),
	DMA1_Stream5_BASE     = ((uint32_t) (DMA1_BASE + 0x088)),
	DMA1_Stream6_BASE     = ((uint32_t) (DMA1_BASE + 0x0A0)),
	DMA1_Stream7_BASE     = ((uint32_t) (DMA1_BASE + 0x0B8)),
	DMA2_BASE             = ((uint32_t) (AHB1_PERIPH_BASE + 0x6400)),
	DMA2_Stream0_BASE     = ((uint32_t) (DMA2_BASE + 0x010)),
	DMA2_Stream1_BASE     = ((uint32_t) (DMA2_BASE + 0x028)),
	DMA2_Stream2_BASE     = ((uint32_t) (DMA2_BASE + 0x040)),
	DMA2_Stream3_BASE     = ((uint32_t) (DMA2_BASE + 0x058)),
	DMA2_Stream4_BASE     = ((uint32_t) (DMA2_BASE + 0x070)),
	DMA2_Stream5_BASE     = ((uint32_t) (DMA2_BASE + 0x088)),
	DMA2_Stream6_BASE     = ((uint32_t) (DMA2_BASE + 0x0A0)),
	DMA2_Stream7_BASE     = ((uint32_t) (DMA2_BASE + 0x0B8)),
	ETH_BASE              = ((uint32_t) (AHB1_PERIPH_BASE + 0x8000)),
	ETH_MAC_BASE          = ((uint32_t) (ETH_BASE)),
	ETH_MMC_BASE          = ((uint32_t) (ETH_BASE + 0x0100)),
	ETH_PTP_BASE          = ((uint32_t) (ETH_BASE + 0x0700)),
	ETH_DMA_BASE          = ((uint32_t) (ETH_BASE + 0x1000))
};


// AHB2 Peripherals
enum AHB2_Peripherals {
	DCMI_BASE             = ((uint32_t) (AHB2_PERIPH_BASE + 0x50000)),
	CRYP_BASE             = ((uint32_t) (AHB2_PERIPH_BASE + 0x60000)),
	HASH_BASE             = ((uint32_t) (AHB2_PERIPH_BASE + 0x60400)),
	RNG_BASE              = ((uint32_t) (AHB2_PERIPH_BASE + 0x60800))
};

// FSMC Bankx Registers Base Address
enum FSMC_R {
	FSMC_Bank1_R_BASE     = ((uint32_t) (FSMC_R_BASE + 0x0000)),
	FSMC_Bank1E_R_BASE    = ((uint32_t) (FSMC_R_BASE + 0x0104)),
	FSMC_Bank2_R_BASE     = ((uint32_t) (FSMC_R_BASE + 0x0060)),
	FSMC_Bank3_R_BASE     = ((uint32_t) (FSMC_R_BASE + 0x0080)),
	FSMC_Bank4_R_BASE     = ((uint32_t) (FSMC_R_BASE + 0x00A0))
};

// Debug MCU Registers Base Address
enum DEBUG_R {
	DBGMCU_BASE           = ((uint32_t) (0xE0042000))
};

#endif // of __BASE_ADDRESSES_H__
