//! \file stm32_sys_tick.c
//! \author tkl
//! \date Feb 15, 2012
//! \brief Source file of the stm32f10x architecture dependent sys tick timer implementation.
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>

#include "stm32f4xx.h"

#include "timer.h"
#include "stm32_sys_tick.h"
#include "stm32f4xx_isr.h"

struct stm32_sys_tick_obj {
	stm32_sys_tick_cb_t sys_tick_cb;
	void *sys_tick_cb_param;
};

static struct stm32_sys_tick_obj stm32_sys_tick_obj;

int stm32_sys_tick_open(const void *sys_tick) {
	if(sys_tick == NULL)
		return -1;

	struct stm32_sys_tick *this = (struct stm32_sys_tick *)sys_tick;
	uint32_t div = 1000;
	switch(*this->tick_time_base) {
	case STM32_SYS_TICK_TIME_BASE_US:
		div = 1000000;
		break;

	case STM32_SYS_TICK_TIME_BASE_MS:
		div = 1000;
		break;

	default:
		return -1;
	}
	if(SysTick_Config(SystemCoreClock / div))
		return -1;

	return 0;
}

int stm32_sys_tick_close(const void *sys_tick)
{
	if(sys_tick == NULL)
		return -1;

	SysTick->CTRL = 0;

	return 0;
}

int stm32_sys_tick_set_cb(const void *sys_tick, const void *callback, const void *param)
{
	if((sys_tick == NULL) || (callback == NULL))
		return -1;

	stm32_sys_tick_obj.sys_tick_cb = (stm32_sys_tick_cb_t)callback;
	stm32_sys_tick_obj.sys_tick_cb_param = (void*)param;

	return 0;
}

void SysTick_Handler(void)
{
	enter_isr();

	#if defined(USE_HAL_DRIVER)
	  HAL_IncTick();
	#endif
	if(stm32_sys_tick_obj.sys_tick_cb != NULL) {
		stm32_sys_tick_cb_t cb = stm32_sys_tick_obj.sys_tick_cb;
		void *param = stm32_sys_tick_obj.sys_tick_cb_param;
		cb(param);
	}

	exit_isr();
}

HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)
{
	return HAL_OK;
}