/*
 * File:		uart_isr.c
 * Purpose:		interrupt handler routines for the Kinetis uart tests
 *
 */

#include "common.h"
#include "uart.h"

/* Globals from tests.c */
int framing_err_done = 0;
int noise_err_done = 0;
int parity_err_done = 0;
int rx_or_err_done = 0;
int rxuf_err_done = 0;
int txof_err_done = 0;

int break_detect_intr_done = 0;
int rx_actv_edge_intr_done = 0;
int idle_line_intr_done = 0;
int tx_comp_intr_done = 0;
int tdre_intr_done = 0;
int rdrf_intr_done = 0;

/* Local function prototypes for ISR */
void uart_isr(UART_MemMapPtr channel);
void uart_7816_isr(UART_MemMapPtr channel);

/********************************************************************/  
/* UART0 interrupt handler.
 * Display message stating handler has been entered, then jumps to generic
 * UART interrupt handler.
 */
interrupt void UART0_ISR(void)
{
   print_str("\n****UART0 Interrupt Handler*****\n");
   if(!(UART0_C7816 & UART_C7816_ISO_7816E_MASK)) 
   {
     uart_isr(UART0_BASE_PTR);
   }
   else
   {
     uart_7816_isr(UART0_BASE_PTR);
   }
}

/********************************************************************/  
/* UART1 interrupt handler.
 * Display message stating handler has been entered, then jumps to generic
 * UART interrupt handler.
 */
interrupt void UART1_ISR(void)
{
   print_str("\n****UART1 Interrupt Handler*****\n");
   if(!(UART0_C7816 & UART_C7816_ISO_7816E_MASK)) 
   {
     uart_isr(UART1_BASE_PTR);
   }
   else
   {
     uart_7816_isr(UART1_BASE_PTR);
   }
}

/********************************************************************/
/* Generic UART status interrupt handler.
 * This function is called by the specific UART interupt handler routines,
 * so it isn't technically an interrupt handler. The individual interrupt
 * handlers will call this function immediately, so this function contains
 * most of the code. This function will check all possible interrupt sources,
 * so if there are multiple interrupt flags they will all be handled.
 * 
 * NOTE: Since the handler doesn't have access to any transmit or recieve 
 * buffers from an application layer, the transmit and receive interrupts
 * are not really serviced by this routine (don't know what data the application
 * would want to transmit and don't know where the application wants receive
 * data to be stored).
 *
 * Parameters: 
 * channel      UART channel that triggered the interrupt
 * 
 */
void uart_isr(UART_MemMapPtr channel)
{
    uint8 status, temp;
    
    /* Determine the source of the interrupt */

    /* Check to see if the transmit data register empty flag is set */
    if (UART_S1_REG(channel) & UART_S1_TDRE_MASK)
    {
        print_str("\nUART transmit data register empty.\n");
        tdre_intr_done++;

        /* Disable the tx interrupt in the module */
        /* Without having data to load in the buffer, this is the only way
         * to prevent the interrupt from occurring continuously.
         */
        UART_C2_REG(channel) &= ~UART_C2_TIE_MASK;
    }
  
    /* Check to see if the transmit complete flag is set */
    if (UART_S1_REG(channel) & UART_S1_TC_MASK)
    {
        print_str("\nUART transmit complete.\n");
        tx_comp_intr_done++;

        /* Disable the tx complete interrupt in the module */
        /* Without having data to load in the buffer, this is the only way
         * to prevent the interrupt from occurring continuously.
         */
        UART_C2_REG(channel) &= ~UART_C2_TCIE_MASK;
    }
  
    /* Check to see if the rx full flag is set */
    if (UART_S1_REG(channel) & UART_S1_RDRF_MASK)
    {
        print_str("\nUART receive data register full.\n");
        rdrf_intr_done++;

        /* Read data register to clear the flag */
        temp = UART_D_REG(channel);
    }

    /* Check to see if the idle line flag is set */
    if (UART_S1_REG(channel) & UART_S1_IDLE_MASK)
    {
        print_str("\nUART idle line detected.\n");
        idle_line_intr_done++;

        /* Read data register to clear the flag */
        temp = UART_D_REG(channel);
    }

    /* Check to see if the LIN break detect flag is set */
    if (UART_S2_REG(channel) & UART_S2_LBKDIF_MASK)
    {
        print_str("\nUART LIN break detected.\n");
        break_detect_intr_done++;

        /* Write 1 to flag to clear the flag */
        UART_S2_REG(channel) |= UART_S2_LBKDIF_MASK;
    }
    
    /* Check to see if the RxD active edge flag is set */
    if (UART_S2_REG(channel) & UART_S2_RXEDGIF_MASK)
    {
        print_str("\nUART RXD active edge detected.\n");
        rx_actv_edge_intr_done++;

        /* Write 1 to flag to clear the flag */
        UART_S2_REG(channel) |= UART_S2_RXEDGIF_MASK;
    }
  
    /* Since the flag clearing mechanism will clear any flags in a register
     * that are set, we have to save off the value of the status register
     * and then check against the saved value to be able to detect all of
     * the flags that were set (if you read the status register over and 
     * over again, then you'll only capture the first one that was set.
     */
    
    /* Read and save the S1 value */
    status = UART_S1_REG(channel);
  
    /* Check to see if a receiver overrun has been detected */
    if (status & UART_S1_OR_MASK)
    {
        print_str("\nUART receiver overrun detected.\n");
        rx_or_err_done++;
        
        /* Read data register to clear the flag */
        temp = UART_D_REG(channel);
    }
    
    /* Check to see if the noise flag is set */
    if (status & UART_S1_NF_MASK)
    {
        print_str("\nUART noise error detected.\n");
        noise_err_done++;
        
        /* Read data register to clear the flag */
        temp = UART_D_REG(channel);
    }
    
    /* Check to see if a framing error was detected */
    if (status & UART_S1_FE_MASK)
    {
        print_str("\nUART framing error detected.\n");
        framing_err_done++;
     
        /* Read data register to clear the flag */
        temp = UART_D_REG(channel);
    }
    
    /* Check to see if a parity error was detected */
    if (status & UART_S1_PF_MASK)
    {
        print_str("\nUART parity error detected.\n");
        parity_err_done++;

        /* Read data register to clear the flag */
        temp = UART_D_REG(channel);
    }

    /* Check to see if a transmit buffer overflow was detected */
    if (UART_SFIFO_REG(channel) & UART_SFIFO_TXOF_MASK)
    {
        print_str("\nUART transmit buffer overflow detected.\n");
        txof_err_done++;

        /* Write 1 to flag to clear the flag */
        UART_SFIFO_REG(channel) |= UART_SFIFO_TXOF_MASK;
    }

    /* Check to see if a receiver underflow was detected */
    if (UART_SFIFO_REG(channel) & UART_SFIFO_RXUF_MASK)
    {
        print_str("\nUART receiver buffer underflow detected.\n");
        rxuf_err_done++;

        /* Write 1 to flag to clear the flag */
        UART_SFIFO_REG(channel) |= UART_SFIFO_RXUF_MASK;
    }
}    

/********************************************************************/
/* UART0 IS0-7816 interrupt handler.
 * When using 7816 mode this interrupt handler should be used instead
 * of the regular uart_isr.
 */
void uart_7816_isr(UART_MemMapPtr channel)
{
     print_str("\n****UART ISO-7816 Interrupt Handler*****\n");

    /* Check to see if a 7816 transmit threshold exceeded error detected */
    if (UART_IS7816_REG(channel) & UART_IS7816_TXT_MASK)
    {
        print_str("\nUART ISO-7816 transmit threshold exceeded limit.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel) |= UART_IS7816_TXT_MASK;
    }

    /* Check to see if a 7816 receive threshold exceeded error detected */
    if (UART_IS7816_REG(channel) & UART_IS7816_RXT_MASK)
    {
        print_str("\nUART ISO-7816 receive threshold exceeded limit.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel) |= UART_IS7816_RXT_MASK;
    }

    /* Check to see if a 7816 wait timer interrupt was detected */
    if (UART_IS7816_REG(channel) & UART_IS7816_WT_MASK)
    {
        print_str("\nUART ISO-7816 wait timer interrupt.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel)|= UART_IS7816_WT_MASK;
    }

    /* Check to see if a 7816 character wait timer interrupt was detected */
    if (UART_IS7816_REG(channel) & UART_IS7816_CWT_MASK)
    {
        print_str("\nUART ISO-7816 character wait timer interrupt.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel) |= UART_IS7816_CWT_MASK;
    }
    
    /* Check to see if a 7816 block wait timer interrupt was detected */
    if (UART_IS7816_REG(channel) & UART_IS7816_BWT_MASK)
    {
        print_str("\nUART ISO-7816 block wait timer interrupt.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel) |= UART_IS7816_BWT_MASK;
    }

    /* Check to see if a 7816 character guard timer interrupt was detected */
    if (UART_IS7816_REG(channel) & UART_IS7816_GTV_MASK)
    {
        print_str("\nUART ISO-7816 guard timer interrupt.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel) |= UART_IS7816_GTV_MASK;
    }   
    /* Check to see if the 7816 initial character detect flag is set */
    if (UART_IS7816_REG(channel) & UART_IS7816_INITD_MASK)
    {
        print_str("\nUART ISO-7816 initial character detected.\n");

        /* Write 1 to flag to clear the flag */
        UART_IS7816_REG(channel) |= UART_IS7816_INITD_MASK;
    }
}
/********************************************************************/   

