#include <stdint.h>
#include <assert.h>
#include "t1001.h"
#include "omw_timer.h"


#ifdef OMW_TIMER
const struct gpio_cfg_tag pwm_pin_cfg[] = {
    {OMW_TIMER_PIN_PWM0_1, OMW_TIMER_FUN_CFG_PWM0},
    {OMW_TIMER_PIN_PWM1_1, OMW_TIMER_FUN_CFG_PWM1},
    {OMW_TIMER_PIN_PWM2_1, OMW_TIMER_FUN_CFG_PWM2},
    {OMW_TIMER_PIN_PWM3_1, OMW_TIMER_FUN_CFG_PWM3},
	{OMW_TIMER_PIN_PWM4_1, OMW_TIMER_FUN_CFG_PWM4},
	{OMW_TIMER_PIN_PWM5_1, OMW_TIMER_FUN_CFG_PWM5},
	{OMW_TIMER_PIN_PWM6_1, OMW_TIMER_FUN_CFG_PWM6},
	{OMW_TIMER_PIN_PWM7_1, OMW_TIMER_FUN_CFG_PWM7},
    {OMW_TIMER_PIN_PWM0_2, OMW_TIMER_FUN_CFG_PWM0},
    {OMW_TIMER_PIN_PWM1_2, OMW_TIMER_FUN_CFG_PWM1},
    {OMW_TIMER_PIN_PWM2_2, OMW_TIMER_FUN_CFG_PWM2},
    {OMW_TIMER_PIN_PWM3_2, OMW_TIMER_FUN_CFG_PWM3},
	{OMW_TIMER_PIN_PWM4_2, OMW_TIMER_FUN_CFG_PWM4},
	{OMW_TIMER_PIN_PWM5_2, OMW_TIMER_FUN_CFG_PWM5},
	{OMW_TIMER_PIN_PWM6_2, OMW_TIMER_FUN_CFG_PWM6},
	{OMW_TIMER_PIN_PWM7_2, OMW_TIMER_FUN_CFG_PWM7},
	{OMW_TIMER_PIN_PWM0_N, OMW_TIMER_FUN_CFG_PWM0},
	{OMW_TIMER_PIN_PWM1_N, OMW_TIMER_FUN_CFG_PWM1},
	{OMW_TIMER_PIN_PWM2_N, OMW_TIMER_FUN_CFG_PWM2},
	{OMW_TIMER_PIN_PWM3_N, OMW_TIMER_FUN_CFG_PWM3},
	{OMW_TIMER_PIN_PWM4_N, OMW_TIMER_FUN_CFG_PWM4},
	{OMW_TIMER_PIN_PWM5_N, OMW_TIMER_FUN_CFG_PWM5},
	{OMW_TIMER_PIN_PWM6_N, OMW_TIMER_FUN_CFG_PWM6},
    {OMW_TIMER_PIN_PWM7_N, OMW_TIMER_FUN_CFG_PWM7}
};




void omw_timer_init(OMW_ENUM_TIMER TIMERx,TIMER_InitTypeDef *timer_struct)
{
  omw_timer_en(TIMERx,DISABLE);
  uint16_t clk = *(volatile uint32_t*)(SYS_CTRL_BASE + 0x30) ;
  clk &= ~(0x3 << (TIMERx * 2));
  clk |= (timer_struct->timer_clk << (TIMERx * 2));
  *(volatile uint16_t*)(SYS_CTRL_BASE + 0x30) = clk;
  if(timer_struct->timer_clk == OMW_TIMER_CLK_SEL_PLL48M)
  {
	  *(volatile uint8_t*)(0x42002000) |= 2;
	  ;
      *(volatile uint32_t*)(SYS_CTRL_BASE + 0x24) &= ~(0X37 << 4);
      *(volatile uint32_t*)(SYS_CTRL_BASE + 0x24) |= (0X23 << 4);
  }

  uint32_t divide = *(volatile uint32_t*)(SYS_CTRL_BASE + 0x34) ;
  divide &= ~(0xf << (TIMERx * 4));
  divide |= (timer_struct->timer_clk_divide << (TIMERx * 4));
  *(volatile uint32_t*)(SYS_CTRL_BASE + 0x34) = divide;


  uint8_t tmpreg;
  tmpreg = timer_struct->timer_pwm_en | timer_struct->timer_pwm0n100_en | timer_struct->timer_mode;

  *(volatile uint8_t*) (TIMER_BASE + 0x08 + (TIMERx)* 0x14) |= tmpreg;
  *(volatile uint16_t*)(TIMER_BASE + 0x00 + (TIMERx)* 0x14) = timer_struct->timer_loadcount;
  if(timer_struct->timer_pwm_en == OMW_TIMER_PWM_ENABLE) 
      *(volatile uint16_t*)(TIMER_BASE + 0xB0 + (TIMERx) * 0x4) = timer_struct->timer_loadcount2;
  

}

void omw_timer_struct_init(TIMER_InitTypeDef *timer_struct)
{
  timer_struct->timer_pwm_en = OMW_TIMER_PWM_DISABLE;
  timer_struct->timer_pwm0n100_en = OMW_TIMER_PWM0N100_DISABLE;
  timer_struct->timer_mode = OMW_TIMER_MODE_FREE_RUNNING;
  timer_struct->timer_loadcount = 0xffff;
  timer_struct->timer_loadcount2= 0xffff;
  timer_struct->timer_clk = OMW_TIMER_CLK_SEL_XTAL24M;
  timer_struct->timer_clk_divide = OMW_TIMER_CLK_DIVIDE_2;
}
void omw_timer_gpio_init(OMW_ENUM_TIMER_GPIO TIMER_GPIOx)
{

  const struct gpio_cfg_tag  * pin_cfg = NULL;
  pin_cfg = pwm_pin_cfg;
  omw_gpio_set_func_ex(& pin_cfg[TIMER_GPIOx],1);
    
}


void omw_timer_en(OMW_ENUM_TIMER TIMERx,FunctionalState NEWSTATE)
{

	if (NEWSTATE != DISABLE)
  {
    *(volatile uint32_t*)(TIMER_BASE + 0x08 + (TIMERx) * 0x14)  |= ENABLE ;
  }
  else
  {
    *(volatile uint32_t*)(TIMER_BASE + 0x08 + (TIMERx) * 0x14)  &= ~ENABLE ;
  }
	
}


void omw_timer_it_en(OMW_ENUM_TIMER TIMERx,FunctionalState NEWSTATE)
{
    
  if (NEWSTATE != DISABLE)
  {
    *(volatile uint32_t*)(TIMER_BASE + 0x08 + (TIMERx * 0x14))  &= ~(OMW_TIMER_INTR_DISABLE);
  }
  else
  {
    *(volatile uint32_t*)(TIMER_BASE + 0x08 + (TIMERx * 0x14))  |= (OMW_TIMER_INTR_DISABLE) ;
  }
}

ITStatus omw_timer_get_it_status(OMW_ENUM_TIMER TIMERx)
{

  ITStatus bitstatus = RESET;
  uint8_t itpos = 0;

  itpos = (TIMER ->TIMERS_INT_STATUS & (0x01 << (TIMERx)));
 
  if (itpos != (uint8_t)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

void omw_timer_it_clr(void)
{
	*(volatile uint8_t*)(TIMER_BASE + 0xA4);
}

void omw_TimeX_it_clr(OMW_ENUM_TIMER TIMERx)
{
	*(volatile uint32_t*)(TIMER_BASE + 0x0C + (TIMERx * 0x14));
}

// void omw_timer_clock_sel (OMW_ENUM_TIMER TIMERx , OMW_ENUM_TIMER_CLK timer_clk)
// {
//   uint16_t tempreg = *(volatile uint32_t*)(SYS_CTRL_BASE + 0x30) ;
//   tempreg &= ~(0x3 << (TIMERx * 2));
//   tempreg |= (timer_clk << (TIMERx * 2));
//   *(volatile uint16_t*)(SYS_CTRL_BASE + 0x30) = tempreg;
//   if(timer_clk == OMW_TIMER_CLK_SEL_PLL48M)
//       *(volatile uint32_t*)(SYS_CTRL_BASE + 0x24) &= ~(7 << 4);
//       *(volatile uint32_t*)(SYS_CTRL_BASE + 0x24) |= (3 << 4);

// }

// void omw_timer_clock_divide (OMW_ENUM_TIMER TIMERx , OMW_ENUM_TIMER_CLK_DIVIDE timer_clk_divide)
// {
//   uint32_t tempreg = *(volatile uint32_t*)(SYS_CTRL_BASE + 0x34) ;
//   tempreg &= ~(0xf << (TIMERx * 4));
//   tempreg |= (timer_clk_divide << (TIMERx * 4));
//   *(volatile uint32_t*)(SYS_CTRL_BASE + 0x34) = tempreg;
// }



#endif
