/*
* Copyright 2013 Ytai Ben-Tsvi. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied.
*/
package ioio.lib.api;
import ioio.lib.api.exception.ConnectionLostException;
/**
* A pin used for capacitive sensing.
* <p/>
* A cap-sense input pin can be used to measure capacitance, most frequently for touch sensing.
* CapSense instances are obtained by calling {@link IOIO#openCapSense(int)}.
* <p/>
* Capacitance is measured by pushing a known amount of charge into the circuit, and measuring the
* increase in voltage. As capacitance gets bigger, this increase becomes smaller, and thus less
* accurate. As capacitance gets smaller, the increase may become fast enough so it can saturate,
* i.e. reach the maximum voltage. The system has been tuned to effectively sense capacitance values
* typical of the human body, for touch sensors. The lowest possible capacitance is about 27pF, and
* at about 2700pF the precision will be around 10% (with high noise level unless filtered). The
* internal capacitance of the system with some parasitic capacitance will normally be 30pF or more.
* Human-body capacitance will typically be about 150pF without grounding, and greater with
* grounding or when touching a large metallic surface.
* <p/>
* Floating-point values in pico-Farade units can be obtained by calling {@link #read()}.
* <p/>
* For better noise immunity, some low-pass filtering is recommended. This module provides a simple,
* single-pole IIR filtering, with configurable time- constant. There is a trade-off when selecting
* the time-constant: a longer time constant will provide better noise filtering, but at the cost of
* a slower response. In other words, it will take more time for the measured value to reach the
* actual. The default value of {@link #DEFAULT_COEF}( {@value #DEFAULT_COEF}pF) is a reasonable one
* in many cases. To change it, call {@link #setFilterCoef(float)}, or use the overload the open
* method, which gets a filter coefficient argument: {@link IOIO#openCapSense(int, float)}.
* <p/>
* The instance is alive since its creation. The first {@link #read()} call block for a few
* milliseconds until the initial value is updated. If the connection with the IOIO drops at any
* point, the instance transitions to a disconnected state, in which every attempt to use the pin
* (except {@link #close()}) will throw a {@link ConnectionLostException}. Whenever {@link #close()}
* is invoked the instance may no longer be used. Any resources associated with it are freed and can
* be reused.
* <p/>
* Typical usage:
* <p/>
* <pre>
* CapSense touchSensor = ioio.openCapSense(40);
* if (touchSensor.read() > 50) {
* // Clicked!
* ...
* }
*
* ...
* touchSensor.close(); // optional. pin 40 can now be used for something else.
* </pre>
*
* @see IOIO#openCapSense(int)
* @see IOIO#openCapSense(int, float)
*/
public interface CapSense extends Closeable {
public static final float DEFAULT_COEF = 25.f;
/**
* Gets the capacitance reading.
* <p/>
* It typically takes a few milliseconds between when the instance is created and until the
* first value can be read. In this case, the method may block shortly. If this is a problem,
* the calling thread can be interrupted.
* <p/>
* This value is computed using a filtered signal, which is configured via
* {@link #setFilterCoef(float)}
*
* @return The capacitance, in pico-Farade units.
* @throws InterruptedException The calling thread has been interrupted.
* @throws ConnectionLostException The connection with the IOIO is lost.
*/
public float read() throws InterruptedException, ConnectionLostException;
/**
* This is very similar to {@link #read()}, but will wait for a new sample to arrive before
* returning. This is useful in conjunction with {@link IOIO#sync()}, in cases when we want to
* guarantee the we are looking at a sample that has been captured strictly after certain other
* commands have been executed.
*
* @return The capacitance, in pico-Farade units.
* @throws InterruptedException The calling thread has been interrupted.
* @throws ConnectionLostException The connection with the IOIO is lost.
* @see #read()
*/
public float readSync() throws InterruptedException, ConnectionLostException;
/**
* Sets the low-pass filter coefficient.
* <p/>
* This coefficient is the typical time constant of the system, which gives us an order of
* magnitude of its response time. Slower response time typically provides better noise immunity
* at the expense of higher latency.
*
* @param t The time constant, in milliseconds.
* @throws ConnectionLostException The connection with the IOIO is lost.
*/
public void setFilterCoef(float t) throws ConnectionLostException;
/**
* Block until sensed capacitance becomes greater than a given threshold.
* <p/>
* For using a touch surface as a digital button, a threshold of 50pF is normally useful, with
* some hysteresis recommended.
*
* @param threshold The threshold value, in pF units.
* @throws ConnectionLostException The connection with the IOIO is lost.
* @throws InterruptedException The calling thread has been interrupted.
*/
public void waitOver(float threshold) throws ConnectionLostException, InterruptedException;
/**
* This is very similar to {@link #waitOver()}, but will wait for a new sample to arrive before
* returning. This is useful in conjunction with {@link IOIO#sync()}, in cases when we want to
* guarantee the we are looking at a sample that has been captured strictly after certain other
* commands have been executed.
*
* @return The capacitance, in pico-Farade units.
* @throws InterruptedException The calling thread has been interrupted.
* @throws ConnectionLostException The connection with the IOIO is lost.
* @see #waitOver()
*/
public void waitOverSync(float threshold) throws ConnectionLostException, InterruptedException;
/**
* Block until sensed capacitance becomes less than a given threshold.
* <p/>
* For using a touch surface as a digital button, a threshold of 50pF is normally useful, with
* some hysteresis recommended.
*
* @param threshold The threshold value, in pF units.
* @throws ConnectionLostException The connection with the IOIO is lost.
* @throws InterruptedException The calling thread has been interrupted.
*/
public void waitUnder(float threshold) throws ConnectionLostException, InterruptedException;
/**
* This is very similar to {@link #waitUnder()}, but will wait for a new sample to arrive before
* returning. This is useful in conjunction with {@link IOIO#sync()}, in cases when we want to
* guarantee the we are looking at a sample that has been captured strictly after certain other
* commands have been executed.
*
* @return The capacitance, in pico-Farade units.
* @throws InterruptedException The calling thread has been interrupted.
* @throws ConnectionLostException The connection with the IOIO is lost.
* @see #waitUnder()
*/
public void waitUnderSync(float threshold) throws ConnectionLostException, InterruptedException;
}