/*!
 * @file    	misc.c
 * @brief	 
 *
 * @details	
 *
 * @version		V1.0.0
 * @author  	
 * @date    	2019-8-13
 *
 */

#include "misc.h"

#define AIRCR_VECTKEY_MASK    ((uint32_t)0x05FA0000)


/*!
 * @brief		Configures the priority grouping: pre-emption priority and subpriority.
 *
 * @param		priorityGroup	specifies the priority grouping bits length.
 *
 * @see 
 *
 * @note 
 */
void NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_T priorityGroup)
{
	SCB->AIRCR = AIRCR_VECTKEY_MASK | priorityGroup;
}


/*!
 * @brief		Enable NVIC request
 *
 * @param		irq: the NVIC interrupt request, detailed in IRQn_Type
 *				For the complete APM32 Devices IRQ Channels list,please refer to apm32f10x.h file
 *
 * @param		preemptionPriority: the pre-emption priority needed to set	
 *				
 * @param		subPriority: the subpriority needed to set	
 *
 * @see 
 *
 * @note 
 */
void NVIC_EnableIRQRequest(IRQn_Type irq, uint8_t preemptionPriority, uint8_t subPriority)
{
	uint32_t tempPriority, tempPrePri, tempSubPri;
	uint32_t priorityGrp;
	
	/** Get priority group */
	priorityGrp = (SCB->AIRCR) & (uint32_t)0x700U;

	/** get pre-emption priority and subpriority */
	switch(priorityGrp)
	{
		case NVIC_PRIORITY_GROUP_0:
			tempPrePri = 0;
			tempSubPri = 4;
			break;

		case NVIC_PRIORITY_GROUP_1:
			tempPrePri = 1;
			tempSubPri = 3;
			break;

		case NVIC_PRIORITY_GROUP_2:
			tempPrePri = 2;
			tempSubPri = 2;
			break;

		case NVIC_PRIORITY_GROUP_3:
			tempPrePri = 3;
			tempSubPri = 1;
			break;	

		case NVIC_PRIORITY_GROUP_4:
			tempPrePri = 4;
			tempSubPri = 0;
			break;	

		default:
			NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_0);
			tempPrePri = 0;
			tempSubPri = 4;
			break;
	}

	tempPrePri = 4 - tempPrePri;
	tempSubPri = 4 - tempSubPri;
	tempPriority = preemptionPriority << tempPrePri;
	tempPriority |= subPriority & (0x0f >> tempSubPri);
	tempPriority <<= 4;
	NVIC->IP[irq] = (uint8_t)tempPriority;
	
    /* enable the selected IRQ */
    NVIC->ISER[irq >> 0x05U] = (uint32_t)0x01U << (irq & (uint8_t)0x1FU);	
}

/*!
 * @brief		Disable NVIC request 
 *
 * @param		irq: the NVIC interrupt request, detailed in IRQn_Type
 *
 * @see 
 *
 * @note 
 */
void NVIC_DisableIRQRequest(IRQn_Type irq)
{
    /* disable the selected IRQ.*/
    NVIC->ICER[irq >> 0x05U] = (uint32_t)0x01U << (irq & (uint8_t)0x1FU);
}

/*!
 * @brief		Sets the vector table location and Offset.
 *
 * @param		vectTab	specifies if the vector table is in RAM or FLASH memory
 *
 * @param		Offset	Vector Table base offset field. This value must be a multiple of 0x200
 *
 * @see 
 *
 * @note 
 */
void NVIC_SetVectorTable(NVIC_VECT_T vectTab, uint32_t offset)
{ 
 	SCB->VTOR = vectTab | (offset & (uint32_t)0x1FFFFF80);
}

/*!
 * @brief		set the state of the low power mode
 *
 * @param		lowPowerMode: the low power mode state
 *
 * @see 
 *
 * @note 
 */
void NVIC_SetSystemLowPower(NVIC_LP_T lowPowerMode)
{
	SCB->SCR |= lowPowerMode;
}


/*!
 * @brief		reset the state of the low power mode
 *
 * @param		lowPowerMode: the low power mode state
 *
 * @see 
 *
 * @note 
 */
void NVIC_ResetystemLowPower(NVIC_LP_T lowPowerMode)
{
	SCB->SCR &= (uint32_t)(~(uint32_t)lowPowerMode);
}

/*!
 * @brief		Configures the SysTick clock source
 *
 * @param		clkSource: specifies the SysTick clock source
 *
 * @see 
 *
 * @note 
 */
void SysTick_ConfigCLKSource(SYSTICK_CLK_SOURCE_T clkSource)
{
	if (clkSource == SYSTICK_CLK_SOURCE_HCLK)
	{
		SysTick->CTRL |= SYSTICK_CLK_SOURCE_HCLK;
	}
	else
	{
		SysTick->CTRL &= SYSTICK_CLK_SOURCE_HCLK_DIV8;
	}
}

