/******************************************************************************
* File:    vectors.c
*
* Purpose: Configure interrupt vector table for Kinetis.
******************************************************************************/

#include "vectors_a5.h"
#include "common.h"
#include "macros.h"
#include "sysinit.h"

/* Globals for interrupt vectors */
int  pdb_int_flag = 0;
int  pdb_seq0_err_flag = 0;
int  pdb_seq1_err_flag = 0;
int  adc0_int_flag = 0;
int  adc1_int_flag = 0;
int  dac0_int_flag = 0;
int  dac1_int_flag = 0;
int  dma0_int_flag = 0;
int  dma1_int_flag = 0;
int  dma0_err_flag = 0;
int  dma1_err_flag = 0;
int  adc0_result[2];
int  adc1_result[2];
int  srtc_int_flag = 0;
int  dly_val[10];
int  dly_val_ftm[10];
int	 pit_int_occurred;
int  cpu_to_cpu_int_occurred;
int  LPTMR_INTERRUPT;


/* Vector table is defined in sysinit.c
 * extern int_hdlr_t interrupt_handlers[144];
 *
 * Installed using enable_interrupt() function
 */

#ifdef LOW_POWER_DDR_TEST
	/* If LOW_POWER_DDR_TEST is defined then we are compiling code to DDR memory space (0x8000_0000 area)
	/* So, in this scenario, we compile interrupt vectors to internal SRAM so we can service them if DDR is in self-refresh state */
#ifdef ARMCC_A5
	/* DS-5 */
	#pragma arm section code=".sram_exe_section"
#else
	/* IAR */
	#pragma location = ".sram_exe_section"

#endif /* ARMCC_A5 */

#endif /* LOW_POWER_DDR_TEST */

/******************************************************************************
* default_isr(void)
*
* Default ISR definition.
*
* In:  n/a
* Out: n/a
******************************************************************************/
void default_isr(void)
{
   //#define VECTORNUM                     (*(volatile uint8_t*)(0xE000ED04))		//M4 core

   //printf("\n****default_isr entered for A5 Core on vector %d*****\r\n\n",VECTORNUM);
	printf("\n****default_isr entered for A5 Core *****\r\n\n");
   ;return;
   while(1);
}

void dac0_isr_routine(void)
{
  dac0_int_flag++;

  //Write 0 to clear flags
  if (DAC0->STATCTRL1 & DAC_STATCTRL1_DACBFRPBF_MASK)
  {
	  DAC0->STATCTRL1 &= ~DAC_STATCTRL1_DACBFRPBF_MASK;
  }
  else if (DAC0->STATCTRL1 & DAC_STATCTRL1_DACBFRPTF_MASK)
  {
	  DAC0->STATCTRL1 &= ~DAC_STATCTRL1_DACBFRPTF_MASK;
  }
  //else if (DAC0.SR.B.BFWMF)
  else if (DAC0->STATCTRL1 & DAC_STATCTRL1_DACBFWMF_MASK)
  {
	  DAC0->STATCTRL1 &= ~DAC_STATCTRL1_DACBFWMF_MASK;
  }
}

void dac1_isr_routine(void)
{
  dac1_int_flag++;

  //Write 0 to clear flags
  if (DAC1->STATCTRL1 & DAC_STATCTRL1_DACBFRPBF_MASK)
  {
	  DAC1->STATCTRL1 &= ~DAC_STATCTRL1_DACBFRPBF_MASK;
  }
  else if (DAC1->STATCTRL1 & DAC_STATCTRL1_DACBFRPTF_MASK)
  {
	  DAC1->STATCTRL1 &= ~DAC_STATCTRL1_DACBFRPTF_MASK;
  }
  else if (DAC1->STATCTRL1 & DAC_STATCTRL1_DACBFWMF_MASK)
  {
	  DAC1->STATCTRL1 &= ~DAC_STATCTRL1_DACBFWMF_MASK;
  }
}

void adc0_isr_routine(void)
{
  adc0_int_flag++;

  /* read result  */
  if (ADC0->HS & ADC_HS_COCO0_MASK)
  {
	  adc0_result[0] = ADC0->R[0];
  }

  /* read result */
  if (ADC0->HS & ADC_HS_COCO1_MASK)
  {
	  adc0_result[1] = ADC0->R[1];
  }
}

void adc1_isr_routine(void)
{
  adc1_int_flag++;

  /* read result  */
  if (ADC1->HS & ADC_HS_COCO0_MASK)
  {
	  adc1_result[0] = ADC1->R[0];
  }

  /* read result */
  if (ADC1->HS & ADC_HS_COCO1_MASK)
  {
	  adc1_result[1] = ADC1->R[1];
  }
}

void dma0_isr_routine(void)
{
  dma0_int_flag++;

  /* Global DMA INT flag clear */
  if (DMA0->INT)
  {
	  DMA0->CINT = 0x40;
  }

  /* Check for errors */
  if (DMA0->ES)
  {
    dma0_err_flag = DMA0->ES;
    printf("\nDMA0 Error! DMA0.ES.R = %x, DMA Interrupt #: %d", dma0_err_flag, dma0_int_flag);
  }

  /* we are running dma test with pdb and loading new IDLY registers so this will load them after dma writes them to the buffer */
  if ((PDB->SC & PDB_SC_LDMOD_MASK) == 1)
  {
	PDB->SC |= PDB_SC_LDOK_MASK;
  }
}

void dma1_isr_routine(void)
{
  dma1_int_flag++;

  /* Global DMA INT flag clear */
  if (DMA1->INT)
  {
	  DMA1->CINT = 0x40;
  }

  /* Check for errors */
  if (DMA1->ES)
  {
    dma1_err_flag = DMA1->ES;
    printf("\nDMA1 Error! DMA1.ES.R = %x, DMA Interrupt #: %d", dma1_err_flag, dma1_int_flag);
  }

  /* we are running dma test with pdb and loading new IDLY registers so this will load them after dma writes them to the buffer */
  if ((PDB->SC & PDB_SC_LDMOD_MASK) == 1)
  {
	PDB->SC |= PDB_SC_LDOK_MASK;
  }
}

void PIT_INTR_ROUTINE_71(void)
{
  //Clear PIT flag
  pit_int_occurred++;
  PIT->MCR = 0x02;     //  Disable PIT module
  PIT->CHANNEL[0].TCTRL = 0x00;    //  Disable PIT Channel
  PIT->CHANNEL[0].TFLG = 0x1;		//Clear PIT
}

void srtc_isr_routine(void)
{
  uint32_t snvs_lpsr;

  srtc_int_flag++;

  /* read full register before we start to clear flags, as backup for debug */
  snvs_lpsr = SNVS->LPSR;

  /* Check time alarm interrupt - need to be enabled for this to trigger */
  if (snvs_lpsr & 0x1 /*SNVS.LPSR.B.LPTA */)
  {
	  SNVS->LPSR |= (snvs_lpsr & 0x1);   //w1c
  }

  /* Has SRTC rolled over? */
  if (snvs_lpsr & 0x2 /* SNVS.LPSR.B.SRTCR */)
  {
	  SNVS->LPSR |= (snvs_lpsr & 0x2);   //w1c
  }

  /* Check power supply glitch */
  if (snvs_lpsr & 0x8 /* SNVS.LPSR.B.PGD */)
  {
	SNVS->LPSR |= (snvs_lpsr & SNVS_LPSR_PGD_MASK);	//w1c
    printf("\nPower supply glitch detected!!! SRTC ISR serviced!\n");
  }

  /* Check clock tampering flag */
  if (SNVS->LPSR & SNVS_LPSR_CTD_MASK)
  {
    //not w1c bit
    printf("\nClock Tamper flag detected!!! SRTC ISR serviced!\n");
  }
}

/* Example function to test the PIT interrupt */
void PIT_INTR_TEST (void)
{
  int i;
  pit_int_occurred = 0;

  // Load Interrupt Handler
  //interrupt_handlers[71]= PIT_INTR_ROUTINE_71;
  enable_interrupt(PIT_IRQn, PIT_INTR_ROUTINE_71);

  /* PIT */
  PIT->MCR = 0x00;       //Enable PIT module
  PIT->CHANNEL[0].LDVAL = 0x10D40;   //Load value corrrssponds to 4 ms (using 50 MHz)
  PIT->CHANNEL[0].TCTRL = 0x03;    // Start PIT

  for(i=0;i<10000;i++);

  if(pit_int_occurred==1)
    while (1);
  else
    while(1);
}

void pdb_isr_routine(void)
{
  /* Capture PDB count based on isr sequence but make sure it's in range */
  /* Also capture FTM counter in the event we are using FTM to compare PDB count */
  if (pdb_int_flag < 10)
  {
    dly_val[pdb_int_flag] = PDB->CNT;	//PDB0_CNT;

    /* make sure flextimer0 clock is enabled or bad things happen here */
    /* this is use to track flextimer counter */
    if (CCM->CCGR1 & CCM_CCGR1_CG8_MASK)
    {
      dly_val_ftm[pdb_int_flag] = FTM0->CNT;
    }
  }

  /* increment global flag */
  pdb_int_flag++;

  /* Clear interrupt flag by writing 0*/
  PDB->SC &= (uint32_t)~PDB_SC_PDBIF_MASK;

  /* Clear ERR bits if they exist */
  if (PDB->CH[0].S & PDB_S_ERR_MASK)
  {
	  PDB->CH[0].S &= ~PDB_S_ERR_MASK;
    pdb_seq0_err_flag++;
  }

  /* Clear ERR bits if they exist */
  if (PDB->CH[1].S & PDB_S_ERR_MASK)
  {
	  PDB->CH[1].S &= ~PDB_S_ERR_MASK;
    pdb_seq1_err_flag++;
  }
}

void lptmr_isr_example(void)
{
  LPTMR_INTERRUPT=1;
  LPTMR0->CSR=0;   //Clear LPT Compare flag

  //Set global variable
  printf("\n\nIn LPT ISR!\n\n");
}

void cpu_to_cpu_isr(void)
{
	/*debug*/
	//printf("\nA5 cpu isr...\n");

	/* Timestamp #4*/
	mem32_write(SHARED_DATA_TIMESTAMP_LOCATION_4, TIMER_COUNTER);

	cpu_to_cpu_int_occurred++;

	if(A5_CORE_CHECK)
	{
		/* clear the flag in the MSCM_IRCP0IR register */
		// MSCM_IRCP0IR = MSCM_IRCP0IR_INT0_MASK;
		// *(unsigned int *)(void*)(0x40001800) = (1 << 0);	//MQX
		MSCM->IRCP0IR = 1;	//w1c
	}
	else
	{
		/* clear the flag in the MSCM_IRCP1IR register */
		// MSCM_IRCP1IR = MSCM_IRCP1IR_INT0_MASK;
		//*(unsigned int *)(void*)(0x40001804) = (1 << 0);	//MQX
		MSCM->IRCP1IR = 1;	//w1c
	}

	/* Debug/Demo */
	printf("\nA5: CPU isr\n");
}

void ptb_isr(void)
{
	uint32_t data;

	data = PORT1->ISFR;
	if (data)
	{
		/* clear */
		PORT1->ISFR = data;
	}

	/* debug only */
	printf("\nPort B ISR!\n");
}

void wkup_isr(void)
{
	uint32_t data;

	data = WKPU->WISR;
	if (data)
	{
		/* clear */
		WKPU->WISR = data;
	}

	/* debug - stay here */
	//led_blink_tower();
}


/******************************************************************************/
/* End of "vectors_a5.c" */
