import com.ajile.jem.rawJEM;
import com.ajile.drivers.irq.InterruptController;
import com.ajile.drivers.irq.InterruptEventListener;

/**
 * <p>
 * This Interrupt Service Routine utilizes the GPIO interrupt driver to parse
 * the GPIO interrupt and clear the interrupt before calling the
 * "interruptEvent" method defined in this class. 
 * <br>
 * The interruptEvent method notifies a waiting thread (mProcess) to process 
 * the interrupt. The objective is to minimize time spent in the interrupt handler 
 * where interrupts are disabled.
 * <br>
 * WARNING -- This file contains a hard coded GPIO port and bit (Port A, bit 0)
 * Be sure to change to the desired GPIO port and bit Alternatively, the
 * System.getProperty( string ) can be used.
 * <br>
 * WARNING -- The process thread is hard coded for priority 12 but not for any
 * particular reason 
 * </p>
 * <hr> 
 * Target: aJile only (JStamp, JStik,SaJe) 
 * <br> 
 * <p>
 * Copyright 2005 Systronix Inc. All Rights reserved. 
 * Systronix Inc 
 * 555 South 300 East Salt Lake City Utah USA 84111 
 * a href=http://www.systronix.com>www.systronix.com </a> 
 * </p>
 * CVS updates the following line with every commit. This helps us manage our repository. 
 * <br>
 * $Header: /home/cvsroot/PROJECTS/templates/eclipse/codetemplates.xml,v 1.2 2004/04/26 17:13:02 bab Exp $ 
 * <br> 
 * REVISION HISTORY 
 * <ul>
 * <li> 0.0 Jun 21, 2005 2:54:17 PM created by BAB 
 * </ul>
 * <hr>
 * @version 0.0 (Be sure to describe this in the revision history) 
 * @author aJileSupport, adapted by bboyes Systronix - use SystronixJava mail list
 * 	for support, please do not contact aJile support first. 
 * <br>
 */

public class CustomIsr implements InterruptEventListener, Runnable {

    /*
     * 
     * Constants
     *  
     */

    /**
     * Property Strings
     */
    private static final String GPIO_port_bit = "aj100_gpioa.0";

    /**
     * Process Thread priority (above Java threads)
     */
    public final static int PROCESS_PRIORITY = 12;

    /*
     * 
     * Instance Variables
     *  
     */

    /**
     * ISR Interrupt source
     */
    private int mISR_Source;

    /**
     * Object to wake up the process thread
     */
    private Object mWakeup;

    /**
     * Thread that's doing the processing
     */
    private Thread mProcess;

    /**
     * Constructor
     */
    public CustomIsr() {
        String tmp;

        // ISR gpio port
        // tmp = System.getProperty( string );

        tmp = GPIO_port_bit;

        // ISR interrupt (use tmp from above)
        mISR_Source = InterruptController.parseInterrupt(tmp);

        // setup the interrupt controller (IRQ is left disabled)
        // This example uses the rising edge to trigger the interrupt.
        // See the Java doc on setPinInterruptCondition for complete list
        // of interrupt triggering options.
        InterruptController.addInterruptListener(this, mISR_Source);
        InterruptController.setPinInterruptCondition(mISR_Source,
                InterruptController.FALLING_EDGE);

        // The Wakeup object must be set to interrupt priority (31)
        // so that the synchronized object can be accessed by both
        // an interrupt handler and a thread.
        mWakeup = new Object();
        rawJEM.setCeiling(mWakeup, 31);

        // setup the process thread
        mProcess = new Thread(this);
        rawJEM.setJEMPriority(mProcess, PROCESS_PRIORITY);
        mProcess.start();
    }

    /**
     * Interrupt Handler (Setup by addInterruptListener)
     */
    public void interruptEvent() {
        try {
            // notify the process thread
            synchronized (mWakeup) {
                mWakeup.notify();
            }
        } catch (Exception e) {
            System.out.println("IRQ: EX = " + e);
        }
    }

    /**
     * Thread to process the interrupt (since we don't want to do it at
     * interrupt time
     */
    public void run() {
        // First we need to enable the interrupt and wait the first time
        try {
            // get the wakeup flag (running at 31)
            synchronized (mWakeup) {
                // Interrupts will remain disabled until the wait is
                // executed since we are at interrupt level sync
                InterruptController.enableInterrupt(mISR_Source);

                // wait for the first interrupt notification
                mWakeup.wait();

            } // sync( mWakeup )

        } catch (Exception e) {
            System.out.println("Process thread exception: " + e);
        }

        /**
         * Setup an infinite loop waiting for the interrupt handler to notify
         * the processing to be done.
         */
        while (true) {
            try {
                /**
                 * Process the interrupt here!
                 */

                // get the wakeup flag (running at 31)
                synchronized (mWakeup) {
                    // We're done so wait for the next notification
                    mWakeup.wait();

                } // sync( mWakeup )

            } catch (Exception e) {
                System.out.println("Process thread exception: " + e);
            }
        }
    }
}