001package com.pi4j.wiringpi;
002
003/*
004 * #%L
005 * **********************************************************************
006 * ORGANIZATION  :  Pi4J
007 * PROJECT       :  Pi4J :: Java Library (Core)
008 * FILENAME      :  GpioInterrupt.java  
009 * 
010 * This file is part of the Pi4J project. More information about 
011 * this project can be found here:  http://www.pi4j.com/
012 * **********************************************************************
013 * %%
014 * Copyright (C) 2012 - 2013 Pi4J
015 * %%
016 * Licensed under the Apache License, Version 2.0 (the "License");
017 * you may not use this file except in compliance with the License.
018 * You may obtain a copy of the License at
019 * 
020 *      http://www.apache.org/licenses/LICENSE-2.0
021 * 
022 * Unless required by applicable law or agreed to in writing, software
023 * distributed under the License is distributed on an "AS IS" BASIS,
024 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
025 * See the License for the specific language governing permissions and
026 * limitations under the License.
027 * #L%
028 */
029
030
031import java.util.Vector;
032
033import com.pi4j.util.NativeLibraryLoader;
034
035/**
036 * <p>
037 * This class provides static methods to configure the native Pi4J library to listen to GPIO
038 * interrupts and invoke callbacks into this class. Additionally, this class provides a listener
039 * registration allowing Java consumers to subscribe to GPIO pin state changes.
040 * </p>
041 * 
042 * <p>
043 * Before using the Pi4J library, you need to ensure that the Java VM in configured with access to
044 * the following system libraries:
045 * <ul>
046 * <li>pi4j</li>
047 * <li>wiringPi</li>
048 * </ul>
049 * <blockquote> This library depends on the wiringPi native system library.</br> (developed by
050 * Gordon Henderson @ <a href="https://projects.drogon.net/">https://projects.drogon.net/</a>)
051 * </blockquote>
052 * </p>
053 * 
054 * @see <a href="http://www.pi4j.com/">http://www.pi4j.com/</a>
055 * @author Robert Savage (<a
056 *         href="http://www.savagehomeautomation.com">http://www.savagehomeautomation.com</a>)
057 */
058public class GpioInterrupt {
059
060    private static Vector<GpioInterruptListener> listeners = new Vector<GpioInterruptListener>();
061    private Object lock;
062
063    // private constructor 
064    private GpioInterrupt()  {
065        // forbid object construction 
066    }
067    
068    static {
069        // Load the platform library
070        NativeLibraryLoader.load("pi4j", "libpi4j.so");
071    }
072
073    /**
074     * <p>
075     * This method is used to instruct the native code to setup a monitoring thread to monitor
076     * interrupts that represent changes to the selected GPIO pin.
077     * </p>
078     * 
079     * <p>
080     * <b>The GPIO pin must first be exported before it can be monitored.</b>
081     * </p>
082     * 
083     * @param pin GPIO pin number (not header pin number; not wiringPi pin number)
084     * @return A return value of a negative number represents an error. A return value of '0'
085     *         represents success and that the GPIO pin is already being monitored. A return value
086     *         of '1' represents success and that a new monitoring thread was created to handle the
087     *         requested GPIO pin number.
088     */
089    public static native int enablePinStateChangeCallback(int pin);
090
091    /**
092     * <p>
093     * This method is used to instruct the native code to stop the monitoring thread monitoring
094     * interrupts on the selected GPIO pin.
095     * </p>
096     * 
097     * @param pin GPIO pin number (not header pin number; not wiringPi pin number)
098
099     * @return A return value of a negative number represents an error. A return value of '0'
100     *         represents success and that no existing monitor was previously running. A return
101     *         value of '1' represents success and that an existing monitoring thread was stopped
102     *         for the requested GPIO pin number.
103     */
104    public static native int disablePinStateChangeCallback(int pin);
105
106    /**
107     * <p>
108     * This method is provided as the callback handler for the Pi4J native library to invoke when a
109     * GPIO interrupt is detected. This method should not be called from any Java consumers. (Thus
110     * is is marked as a private method.)
111     * </p>
112     * 
113     * @param pin GPIO pin number (not header pin number; not wiringPi pin number)
114     * @param state New GPIO pin state.
115     */
116    @SuppressWarnings("unchecked")
117    private static void pinStateChangeCallback(int pin, boolean state) {
118
119        Vector<GpioInterruptListener> dataCopy;
120        dataCopy = (Vector<GpioInterruptListener>) listeners.clone();
121
122        for (int i = 0; i < dataCopy.size(); i++) {
123            GpioInterruptEvent event = new GpioInterruptEvent(listeners, pin, state);
124            ((GpioInterruptListener) dataCopy.elementAt(i)).pinStateChange(event);
125        }
126
127        // System.out.println("GPIO PIN [" + pin + "] = " + state);
128    }
129
130    /**
131     * <p>
132     * Java consumer code can all this method to register itself as a listener for pin state
133     * changes.
134     * </p>
135     * 
136     * @see #com.pi4j.wiringpi.GpioInterruptListener
137     * @see #com.pi4j.wiringpi.GpioInterruptEvent
138     * 
139     * @param listener A class instance that implements the GpioInterruptListener interface.
140     */
141    public static synchronized void addListener(GpioInterruptListener listener) {
142        if (!listeners.contains(listener)) {
143            listeners.addElement(listener);
144        }
145    }
146
147    /**
148     * <p>
149     * Java consumer code can all this method to unregister itself as a listener for pin state
150     * changes.
151     * </p>
152     * 
153     * @see #com.pi4j.wiringpi.GpioInterruptListener
154     * @see #com.pi4j.wiringpi.GpioInterruptEvent
155     * 
156     * @param listener A class instance that implements the GpioInterruptListener interface.
157     */
158    public static synchronized void removeListener(GpioInterruptListener listener) {
159        if (listeners.contains(listener)) {
160            listeners.removeElement(listener);
161        }
162    }
163    
164    
165    /**
166     * <p>
167     * Returns true if the listener is already registered for event callbacks.
168     * </p>
169     * 
170     * @see #com.pi4j.wiringpi.GpioInterruptListener
171     * @see #com.pi4j.wiringpi.GpioInterruptEvent
172     * 
173     * @param listener A class instance that implements the GpioInterruptListener interface.
174     */
175    public static synchronized boolean hasListener(GpioInterruptListener listener) {
176        return listeners.contains(listener);
177    }    
178}