/*
 *  Copyright (c) 1996-2007 Digi International Inc., All Rights Reserved
 *
 *  This software contains proprietary and confidential information of Digi
 *  International Inc.  By accepting transfer of this copy, Recipient agrees
 *  to retain this software in confidence, to prevent disclosure to others,
 *  and to make no use of this software other than that for which it was
 *  delivered.  This is an unpublished copyrighted work of Digi International
 *  Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 *  prohibited.
 *
 *  Restricted Rights Legend
 *
 *  Use, duplication, or disclosure by the Government is subject to
 *  restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 *  Technical Data and Computer Software clause at DFARS 252.227-7031 or
 *  subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 *  Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 *  Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
 * Description.
 * =======================================================================
 * applicationStart() is the entry point for user applications.  This
 * This function will be called after the kernel has started and the
 * TCP/IP stack has loaded.  applicationTcpDown() is called periodically
 * after the kernel has started while the system is waiting for the
 * TCP/IP stack to start.  
 *                                                                        
 *                                                                        
 * Edit Date/Ver   Edit Description
 * ==============  ===================================================
 *
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include "appconf.h"
#include "tx_api.h"
#include "gpiomux_def.h"
#include "reg_def.h"
#include "NA_ISR.h"
#include "mc_isr.h"
#include "gpio.h"


/* set this to the number of times you want to run the test */
#define NUMBEROFITERATIONS 1000000

#ifdef NS9750
#define APP_OUTPUT_PIN  0
#define APP_INPUT_PIN   1
#elif NS9360
#define APP_OUTPUT_PIN  0
#define APP_INPUT_PIN   1
#endif

static unsigned int isr_int_count = 0;

void external_irq0_isr(void * param);

/*
 *
 *  Function: void applicationTcpDown (void)
 *
 *  Description:
 *
 *      This routine will be called by the NET+OS root thread once every 
 *      clock tick while it is waiting for the TCP/IP stack to come up.  
 *      This function can increment a counter everytime it's called to 
 *      keep track of how long we've been waiting for the stack to start.
 *      If we've been waiting too long, then this function can do something
 *      to handle the error.  
 *
 *      This function will not be called once the stack has started.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

void applicationTcpDown (void)

{
    static int ticksPassed = 0;

    ticksPassed++;
/*
 * Code to handle error condition if the stack doesn't come up goes here.
 */
}


/*
 *
 *  Function: void applicationStart (void)
 *
 *  Description:
 *
 *      This routine is responsible for starting the user application.  It should 
 *      create any threads or other resources the application needs.
 *
 *      ThreadX, the NET+OS device drivers, and the TCP/IP stack will be running
 *      when this function is called.
 *
 *  Parameters:
 *
 *      none
 *
 *  Return Values:
 *
 *      none
 *
 */

void applicationStart (void)

{
     
/*
 * Code to start the user application goes here.
 */
    int result = 0, LoopIndex = 0;
    unsigned int NextBit = 0, NumberOfIntTriggers = 0;

    printf ("Beginning %s.\n", APP_DIALOG_APP_NAME);

    /* Set the logic level of the interrupt trigger GPIO line to deactivate interrupts on the external IRQ */
#if (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_ACTIVE_HIGH) || (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_RISING_EDGE)
    NextBit = 1;
    result = NAconfigureGPIOpin(APP_OUTPUT_PIN, NA_GPIO_OUTPUT_STATE, 0);
#elif (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_ACTIVE_LOW) || (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_FALLING_EDGE)
    NextBit = 0;
    result = NAconfigureGPIOpin(APP_OUTPUT_PIN, NA_GPIO_OUTPUT_STATE, 1);
#endif

    if (result != 0)
    {
        printf ("NAconfigureGPIOpin failure[%d]\n", result);
    }

    result = naIsrInstall(EXTERNAL0_INTERRUPT, (MC_ISR_HANDLER)external_irq0_isr, NULL);
    if (result != 0)
    {
        printf ("NAconfigureGPIOpin failure[%d]\n", result);
    }

    /*
     * For level triggered interrupts, each iteration will trigger an interrupt
     * which is deactivated in the ISR by setting the interrupt trigger GPIO to
     * deactivate interrupts.
     * For edge triggered interrupts, every other iteration of the loop will
     * trigger an interrupt which is cleared in the ISR by writing to the CLR
     * bit of the external IRQ register.
     *
     */
    for (LoopIndex = 0; LoopIndex < NUMBEROFITERATIONS; LoopIndex++)
    {
        result = NAsetGPIOpin(APP_OUTPUT_PIN, NextBit);
        if (result != 0)
        {
            printf ("NAsetGPIOpin failure[%d]\n", result);
        }
#if (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_RISING_EDGE) || (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_FALLING_EDGE)
        NextBit++;
	NextBit %= 2;
#endif
    }

    printf("%s completed.\n", APP_DIALOG_APP_NAME);

#if (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_RISING_EDGE) || (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_FALLING_EDGE)
    NumberOfIntTriggers = NUMBEROFITERATIONS / 2; /* every other iteration triggers an interrupt */
#else
    NumberOfIntTriggers = NUMBEROFITERATIONS;
#endif

    if (isr_int_count != NumberOfIntTriggers)
    {
        printf("Your test experienced interrupt count mismatches.\n");
    }
    else
    {
        printf("Your test was completely successfully.\n");
    }

    printf("The number of interrupts triggered is %d.\n", NumberOfIntTriggers);
    printf("The number of interrupts counted is %d.\n", isr_int_count);
}

/*
 * Interrupt service routine to handle external IRQ interrupts.
 * For edge triggered interrupts, write to the clr bit of the
 * respective external IRQ register.  For level triggered
 * interrupts, set the interrupt trigger GPIO output signal
 * to the logic level that deactive interrupts.
 */
void external_irq0_isr(void * param)
{
#if (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_RISING_EDGE) || (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_FALLING_EDGE)
    /* set the clr bit high in the external IRQ0 register to clear register */
    narm_write_reg(NA_SCM_EXTIRQ0_REG, NA_SCM_EXTIRQ0_REG_ADDR, clr, 1);

    /* set the clr bit low in the external IRQ0 register */
    narm_write_reg(NA_SCM_EXTIRQ0_REG, NA_SCM_EXTIRQ0_REG_ADDR, clr, 0);
#elif (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_ACTIVE_HIGH) || (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_ACTIVE_LOW)
    int result = 0;
#if (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_ACTIVE_HIGH)
    result = NAsetGPIOpin(APP_OUTPUT_PIN, 0);
#else /*if (BSP_GPIO_MUX_IRQ_0_CONFIG == BSP_GPIO_MUX_IRQ_ACTIVE_LOW)*/
    result = NAsetGPIOpin(APP_OUTPUT_PIN, 1);
#endif
    if (result != 0)
    {
        //printf ("external_irq0_isr: NAsetGPIOpin failure[%d]\n", result);
    }
#endif
    isr_int_count++; /* keep track of interrupts fired */
}
