Started to update the library to API 3.22 RC
Change-Id: I8eaf3151b1d405799eb582564f0e1e8fbcb7744c Signed-off-by: Ricky Barrette <rickbarrette@gmail.com>
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -52,10 +52,42 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* AnalogInput potentiometer = ioio.openAnalogInput(40);
|
||||
* float value = potentiometer.read();
|
||||
* ...
|
||||
* potentiometer.close(); // pin 40 can now be used for something else.
|
||||
* }
|
||||
* </pre>
|
||||
* <p>
|
||||
* An alternate usage allows reading periodically sampled data without missing
|
||||
* samples. The {@link #setBuffer(int)} method must first be called, for setting
|
||||
* up an internal buffer for queuing samples. Then, samples can be obtained by
|
||||
* calling {@link #readBuffered()} or {@link #getVoltageBuffered()}. These
|
||||
* methods will block until a sample is available. If this is undesirable, the
|
||||
* {@link #available()} method can be called first to check how many samples are
|
||||
* ready in the buffer. In case the buffer overflows, as result of the client
|
||||
* not reading fast enough, old samples will be dropped, and the client can
|
||||
* check {@link #getOverflowCount()} to determine how many samples have been
|
||||
* lost. The sample rate used for capturing samples can be obtained by calling
|
||||
* {@link #getSampleRate()}.
|
||||
* <p>
|
||||
* The non-buffered versions of the read methods will still behave normally when
|
||||
* buffering is enabled. The {@link #read()} and {@link #getVoltage()} methods
|
||||
* will always return the most recent value, regardless of the buffer state.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* AnalogInput potentiometer = ioio.openAnalogInput(40);
|
||||
* potentiometer.setBuffer(256);
|
||||
* for (int i = 0; i < 1024; ++i) {
|
||||
* // next line will block until at least one sample is available
|
||||
* float sample = potentiometer.readBuffered();
|
||||
* ...
|
||||
* }
|
||||
* ...
|
||||
* potentiometer.close(); // pin 40 can now be used for something else.
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIO#openAnalogInput(int)
|
||||
@@ -72,8 +104,10 @@ public interface AnalogInput extends Closeable {
|
||||
* If a scaled value is desired, consider using {@link #read()}.
|
||||
*
|
||||
* @return The voltage, in Volt units.
|
||||
* @throws InterruptedException The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException The connection with the IOIO is lost.
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
* @see #read()
|
||||
*/
|
||||
public float getVoltage() throws InterruptedException,
|
||||
@@ -81,6 +115,7 @@ public interface AnalogInput extends Closeable {
|
||||
|
||||
/**
|
||||
* Gets the maximum value against which {@link #read()} values are scaled.
|
||||
*
|
||||
* @return The voltage, in Volts.
|
||||
*/
|
||||
public float getReference();
|
||||
@@ -96,9 +131,95 @@ public interface AnalogInput extends Closeable {
|
||||
* If an absolute value is desired, consider using {@link #getVoltage()}.
|
||||
*
|
||||
* @return The voltage, in scaled units.
|
||||
* @throws InterruptedException The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException The connection with the IOIO is lost.
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
* @see #getVoltage()
|
||||
*/
|
||||
public float read() throws InterruptedException, ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Initializes or destroys an internal buffer, used for queuing sampled
|
||||
* data. When called with a positive argument, an internal buffer will be
|
||||
* created, and start storing sampled data. The client can then call
|
||||
* {@link #readBuffered()} or {@link #getVoltageBuffered()} for obtaining
|
||||
* buffered samples.
|
||||
* <p>
|
||||
* When called with argument of 0, the internal buffer is destroyed.
|
||||
*
|
||||
* @param capacity
|
||||
* The maximum number of unread samples that can be buffered
|
||||
* before overflow occurs.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
*/
|
||||
public void setBuffer(int capacity) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Gets the number of samples that have been dropped as result of overflow,
|
||||
* since {@link #setBuffer(int)} has been called.
|
||||
*
|
||||
* @return The number of dropped samples.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
*/
|
||||
public int getOverflowCount() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Gets the number of samples currently in the buffer. Reading that many
|
||||
* samples is guaranteed not to block.
|
||||
*
|
||||
* @return The number of samples available in the buffer.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
*/
|
||||
public int available() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Read a sample from the internal buffer. This method will block until at
|
||||
* least one sample is available, the instance is closed (via
|
||||
* {@link #close()}), the thread is interrupted (via
|
||||
* {@link Thread#interrupt()} or connection is lost. {@link #setBuffer(int)}
|
||||
* must be called prior to this method for setting up an internal buffer for
|
||||
* storing samples.
|
||||
*
|
||||
* @see #getVoltageBuffered()
|
||||
* @return The earliest (oldest) sample available in the buffer, scaled to
|
||||
* the range [0,1].
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
*/
|
||||
public float readBuffered() throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Read a sample from the internal buffer. This method will block until at
|
||||
* least one sample is available, the instance is closed (via
|
||||
* {@link #close()}), the thread is interrupted (via
|
||||
* {@link Thread#interrupt()} or connection is lost. {@link #setBuffer(int)}
|
||||
* must be called prior to this method for setting up an internal buffer for
|
||||
* storing samples.
|
||||
*
|
||||
* @see #readBuffered()
|
||||
* @return The earliest (oldest) sample available in the buffer, in Volt
|
||||
* units.
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
*/
|
||||
public float getVoltageBuffered() throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Gets the sample rate used for obtaining buffered samples.
|
||||
*
|
||||
* @return The sample rate, in Hz units.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO is lost.
|
||||
*/
|
||||
public float getSampleRate() throws ConnectionLostException;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* A pin used for digital input.
|
||||
* <p>
|
||||
* A digital input pin can be used to read logic-level signals. DigitalInput
|
||||
* instances are obtained by calling {@link IOIO#openDigitalInput(Spec)}.
|
||||
* instances are obtained by calling {@link IOIO#openDigitalInput(DigitalInput.Spec)}.
|
||||
* <p>
|
||||
* The value of the pin is obtained by calling {@link #read()}. It is also
|
||||
* possible for the client to block until a certain level is sensed, by using
|
||||
|
||||
@@ -35,7 +35,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* <p>
|
||||
* A digital input pin can be used to generate logic-level signals.
|
||||
* DigitalOutput instances are obtained by calling
|
||||
* {@link IOIO#openDigitalOutput(Spec, boolean)}.
|
||||
* {@link IOIO#openDigitalOutput(DigitalOutput.Spec, boolean)}.
|
||||
* <p>
|
||||
* The value of the pin is set by calling {@link #write(boolean)}.
|
||||
* <p>
|
||||
@@ -101,7 +101,7 @@ public interface DigitalOutput extends Closeable {
|
||||
/**
|
||||
* Shorthand for Spec(pin, Mode.NORMAL).
|
||||
*
|
||||
* @see #Spec(int, Mode)
|
||||
* @see DigitalOutput.Spec#Spec(int, DigitalOutput.Spec.Mode)
|
||||
*/
|
||||
public Spec(int pin) {
|
||||
this(pin, Mode.NORMAL);
|
||||
|
||||
@@ -109,6 +109,20 @@ public interface IOIO {
|
||||
IOIOLIB_VER
|
||||
}
|
||||
|
||||
/**
|
||||
* A state of a IOIO instance.
|
||||
*/
|
||||
public enum State {
|
||||
/** Connection not yet established. */
|
||||
INIT,
|
||||
/** Connected. */
|
||||
CONNECTED,
|
||||
/** Connection established, incompatible firmware detected. */
|
||||
INCOMPATIBLE,
|
||||
/** Disconnected. Instance is useless. */
|
||||
DEAD
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes connection with the IOIO board.
|
||||
* <p>
|
||||
@@ -157,6 +171,13 @@ public interface IOIO {
|
||||
*/
|
||||
public void waitForDisconnect() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Gets the connections state.
|
||||
*
|
||||
* @return The connection state.
|
||||
*/
|
||||
public State getState();
|
||||
|
||||
/**
|
||||
* Resets the entire state (returning to initial state), without dropping
|
||||
* the connection.
|
||||
@@ -420,7 +441,8 @@ public interface IOIO {
|
||||
* with the given mode.
|
||||
*
|
||||
* @see #openPulseInput(ioio.lib.api.DigitalInput.Spec,
|
||||
* ioio.lib.api.PulseInput.ClockRate, PulseMode, boolean)
|
||||
* ioio.lib.api.PulseInput.ClockRate,
|
||||
* ioio.lib.api.PulseInput.PulseMode, boolean)
|
||||
*/
|
||||
public PulseInput openPulseInput(int pin, PulseMode mode)
|
||||
throws ConnectionLostException;
|
||||
@@ -478,12 +500,12 @@ public interface IOIO {
|
||||
|
||||
/**
|
||||
* Shorthand for
|
||||
* {@link #openUart(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, int, Parity, StopBits)}
|
||||
* {@link #openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, Uart.StopBits)}
|
||||
* , where the input pins use their default specs. {@link #INVALID_PIN} can
|
||||
* be used on either pin if a TX- or RX-only UART is needed.
|
||||
*
|
||||
* @see #openUart(ioio.lib.api.DigitalInput.Spec,
|
||||
* ioio.lib.api.DigitalOutput.Spec, int, Parity, StopBits)
|
||||
* @see #openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity,
|
||||
* Uart.StopBits)
|
||||
*/
|
||||
public Uart openUart(int rx, int tx, int baud, Parity parity,
|
||||
StopBits stopbits) throws ConnectionLostException;
|
||||
@@ -552,9 +574,12 @@ public interface IOIO {
|
||||
DigitalOutput.Spec[] slaveSelect, SpiMaster.Config config)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config),
|
||||
* where the pins are all open with the default modes and default configuration values are used.
|
||||
/**
|
||||
* Shorthand for
|
||||
* {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)}
|
||||
* , where the pins are all open with the default modes and default
|
||||
* configuration values are used.
|
||||
*
|
||||
* @see #openSpiMaster(ioio.lib.api.DigitalInput.Spec,
|
||||
* ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec,
|
||||
* ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)
|
||||
@@ -564,10 +589,12 @@ public interface IOIO {
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config),
|
||||
* where the MISO pins is opened with pull up, and the other pins are open
|
||||
* with the default modes and default configuration values are used.
|
||||
* In this version, a single slave is used.
|
||||
* Shorthand for
|
||||
* {@link #openSpiMaster(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)}
|
||||
* , where the MISO pins is opened with pull up, and the other pins are open
|
||||
* with the default modes and default configuration values are used. In this
|
||||
* version, a single slave is used.
|
||||
*
|
||||
* @see #openSpiMaster(ioio.lib.api.DigitalInput.Spec,
|
||||
* ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec,
|
||||
* ioio.lib.api.DigitalOutput.Spec[], ioio.lib.api.SpiMaster.Config)
|
||||
@@ -635,4 +662,35 @@ public interface IOIO {
|
||||
* method.
|
||||
*/
|
||||
public IcspMaster openIcspMaster() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Start a batch of operations. This is strictly an optimization and will
|
||||
* not change functionality: if the client knows that a sequence of several
|
||||
* IOIO operations are going to be performed immediately following each
|
||||
* other, a call to {@link #beginBatch()} before the sequence and
|
||||
* {@link #endBatch()} after the sequence will cause the operations to be
|
||||
* grouped into one transfer to the IOIO, thus reducing latency. A matching
|
||||
* {@link #endBatch()} operation must always follow, or otherwise no
|
||||
* operation will ever be actually executed. {@link #beginBatch()} /
|
||||
* {@link #endBatch()} blocks may be nested - the transfer will occur when
|
||||
* the outermost {@link #endBatch()} is invoked. Note that it is not
|
||||
* guaranteed that no transfers will happen while inside a batch - it should
|
||||
* be treated as a hint. Code running inside the block must be quick as it
|
||||
* blocks <b>all</b> transfers to the IOIO, including those performed from
|
||||
* other threads.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
*/
|
||||
public void beginBatch() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* End a batch of operations. For explanation, see {@link #beginBatch()}.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
*/
|
||||
public void endBatch() throws ConnectionLostException;
|
||||
}
|
||||
0
IOIOLib/src/ioio/lib/api/IOIOConnection.java
Executable file → Normal file
0
IOIOLib/src/ioio/lib/api/IOIOConnection.java
Executable file → Normal file
@@ -28,10 +28,14 @@
|
||||
*/
|
||||
package ioio.lib.api;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import ioio.lib.impl.IOIOImpl;
|
||||
import ioio.lib.impl.SocketIOIOConnection;
|
||||
import ioio.lib.spi.IOIOConnectionFactory;
|
||||
import ioio.lib.util.IOIOConnectionRegistry;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Factory class for creating instances of the IOIO interface.
|
||||
@@ -55,9 +59,6 @@ import ioio.lib.impl.SocketIOIOConnection;
|
||||
* </pre>
|
||||
*/
|
||||
public class IOIOFactory {
|
||||
/** The TCP port used for communicating with the IOIO board. */
|
||||
public static final int IOIO_PORT = 4545;
|
||||
|
||||
/**
|
||||
* Create a IOIO instance. This specific implementation creates a IOIO
|
||||
* instance which works with the actual IOIO board connected via a TCP
|
||||
@@ -66,11 +67,13 @@ public class IOIOFactory {
|
||||
* @return The IOIO instance.
|
||||
*/
|
||||
public static IOIO create() {
|
||||
Collection<IOIOConnectionFactory> factories = IOIOConnectionRegistry
|
||||
.getConnectionFactories();
|
||||
try {
|
||||
return create(SocketIOIOConnection.class.getName(), IOIO_PORT);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// we shouldn't get here - this class must always exist.
|
||||
throw new RuntimeException("Something is very wrong here");
|
||||
return create(factories.iterator().next().createConnection());
|
||||
} catch (NoSuchElementException e) {
|
||||
Log.e(TAG, "No connection is available. This shouldn't happen.");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,43 +82,14 @@ public class IOIOFactory {
|
||||
* This method should be used for establishing a non-standard connection to
|
||||
* the IOIO board.
|
||||
*
|
||||
* @param connectionClassName
|
||||
* The name of the connection class. Must have a public default
|
||||
* constructor.
|
||||
* @param connection
|
||||
* An instance of a IOIO connection.
|
||||
*
|
||||
* @return The IOIO instance.
|
||||
* @throws ClassNotFoundException The given class name was not found.
|
||||
*/
|
||||
public static IOIO create(String connectionClassName, Object... args) throws ClassNotFoundException {
|
||||
IOIOConnection connection = createConnectionDynamically(connectionClassName, args);
|
||||
return create(connection);
|
||||
}
|
||||
|
||||
public static IOIO create(IOIOConnection connection) {
|
||||
return new IOIOImpl(connection);
|
||||
}
|
||||
|
||||
public static IOIOConnection createConnectionDynamically(
|
||||
String connectionClassName, Object... args)
|
||||
throws ClassNotFoundException {
|
||||
Class<?> cls;
|
||||
cls = Class.forName(connectionClassName);
|
||||
Object instance;
|
||||
try {
|
||||
Class<?>[] argTypes = new Class<?>[args.length];
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
argTypes[i] = args[i].getClass();
|
||||
}
|
||||
Constructor<?> constructor = cls.getConstructor(argTypes);
|
||||
instance = constructor.newInstance(args);
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(
|
||||
"Provided class does not have a public ctor with the right signature", e);
|
||||
}
|
||||
if (!(instance instanceof IOIOConnection)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Provided class does not implement IOIOConnection");
|
||||
}
|
||||
return (IOIOConnection) instance;
|
||||
}
|
||||
private static final String TAG = "IOIOFactory";
|
||||
}
|
||||
|
||||
0
IOIOLib/src/ioio/lib/api/IcspMaster.java
Executable file → Normal file
0
IOIOLib/src/ioio/lib/api/IcspMaster.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/api/PulseInput.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/api/PulseInput.java
Executable file → Normal file
@@ -46,7 +46,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* for measuring a turning shaft's speed.
|
||||
* <p>
|
||||
* {@link PulseInput} instances are obtained by calling
|
||||
* {@link IOIO#openPulseInput(ioio.lib.api.DigitalInput.Spec, ClockRate, PulseMode, boolean)}
|
||||
* {@link IOIO#openPulseInput(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.PulseInput.ClockRate, ioio.lib.api.PulseInput.PulseMode, boolean)}
|
||||
* . When created, some important configuration decisions have to be made: the
|
||||
* precision (single or double), the clock rate and the mode of operation. Modes
|
||||
* are straightforward: {@link PulseMode#POSITIVE} is used for measuring a
|
||||
|
||||
13
IOIOLib/src/ioio/lib/api/SpiMaster.java
Executable file → Normal file
13
IOIOLib/src/ioio/lib/api/SpiMaster.java
Executable file → Normal file
@@ -28,7 +28,6 @@
|
||||
*/
|
||||
package ioio.lib.api;
|
||||
|
||||
import ioio.lib.api.DigitalInput.Spec;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
@@ -41,7 +40,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* between this slave and a respective pin on the master. The MISO line should
|
||||
* operate in pull-up mode, using either the internal pull-up or an external
|
||||
* resistor. SpiMaster instances are obtained by calling
|
||||
* {@link IOIO#openSpiMaster(Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], Config)}.
|
||||
* {@link IOIO#openSpiMaster(DigitalInput.Spec, DigitalOutput.Spec, DigitalOutput.Spec, DigitalOutput.Spec[], SpiMaster.Config)}.
|
||||
* <p>
|
||||
* The SPI protocol is comprised of simultaneous sending and receiving of data
|
||||
* between the bus master and a single slave. By the very nature of this
|
||||
@@ -90,9 +89,11 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* spi.writeRead(request, 2, 4, response, 3);
|
||||
* ...
|
||||
* spi.close(); // free SPI module and pins
|
||||
* }</pre>
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIO#openSpiMaster(Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], Config)
|
||||
* @see IOIO#openSpiMaster(DigitalInput.Spec, DigitalOutput.Spec,
|
||||
* DigitalOutput.Spec, DigitalOutput.Spec[], SpiMaster.Config)
|
||||
*/
|
||||
public interface SpiMaster extends Closeable {
|
||||
/** Possible data rates for SPI, in Hz. */
|
||||
@@ -148,7 +149,7 @@ public interface SpiMaster extends Closeable {
|
||||
* Constructor with common defaults. Equivalent to Config(rate, false,
|
||||
* false)
|
||||
*
|
||||
* @see #Config(Rate, boolean, boolean)
|
||||
* @see SpiMaster.Config#Config(SpiMaster.Config.Rate, boolean, boolean)
|
||||
*/
|
||||
public Config(Rate rate) {
|
||||
this(rate, false, false);
|
||||
@@ -165,7 +166,7 @@ public interface SpiMaster extends Closeable {
|
||||
* @param slave
|
||||
* The slave index. It is determined by the index of its
|
||||
* slave-select pin, as per the array passed to
|
||||
* {@link IOIO#openSpiMaster(Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], Config)}
|
||||
* {@link IOIO#openSpiMaster(DigitalInput.Spec, DigitalOutput.Spec, DigitalOutput.Spec, DigitalOutput.Spec[], SpiMaster.Config)}
|
||||
* .
|
||||
* @param writeData
|
||||
* A byte array of data to write. May be null if writeSize is 0.
|
||||
|
||||
4
IOIOLib/src/ioio/lib/api/TwiMaster.java
Executable file → Normal file
4
IOIOLib/src/ioio/lib/api/TwiMaster.java
Executable file → Normal file
@@ -39,7 +39,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* requires a physical connection of two lines (SDA, SCL) shared by all the bus
|
||||
* nodes, where the SDA is open-drain and externally pulled-up. TwiMaster
|
||||
* instances are obtained by calling
|
||||
* {@link IOIO#openTwiMaster(int, Rate, boolean)}.
|
||||
* {@link IOIO#openTwiMaster(int, ioio.lib.api.TwiMaster.Rate, boolean)}.
|
||||
* <p>
|
||||
* TWI is the generic name for the specific I2C and SMBus protocols, differing
|
||||
* mostly by the voltage levels they require. This module supports both.
|
||||
@@ -79,7 +79,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
* twi.close(); // free TWI module and pins
|
||||
* }</pre>
|
||||
*
|
||||
* @see IOIO#openTwiMaster(int, Rate, boolean)
|
||||
* @see IOIO#openTwiMaster(int, ioio.lib.api.TwiMaster.Rate, boolean)
|
||||
*/
|
||||
public interface TwiMaster extends Closeable {
|
||||
enum Rate {
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
*/
|
||||
package ioio.lib.api;
|
||||
|
||||
import ioio.lib.api.DigitalInput.Spec;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.InputStream;
|
||||
@@ -41,7 +40,7 @@ import java.io.OutputStream;
|
||||
* asynchronous point-to-point data transfer. It typically serves for opening
|
||||
* consoles or as a basis for higher-level protocols, such as MIDI, RS-232 and
|
||||
* RS-485. Uart instances are obtained by calling
|
||||
* {@link IOIO#openUart(Spec, ioio.lib.api.DigitalOutput.Spec, int, Parity, StopBits)}.
|
||||
* {@link IOIO#openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity, Uart.StopBits)}.
|
||||
* <p>
|
||||
* The UART protocol is completely symmetric - there is no "master" and "slave"
|
||||
* at this layer. Each end may send any number of bytes at arbitrary times,
|
||||
@@ -70,8 +69,8 @@ import java.io.OutputStream;
|
||||
* uart.close(); // free UART module and pins
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIO#openUart(Spec, ioio.lib.api.DigitalOutput.Spec, int, Parity,
|
||||
* StopBits)
|
||||
* @see IOIO#openUart(DigitalInput.Spec, DigitalOutput.Spec, int, Uart.Parity,
|
||||
* Uart.StopBits)
|
||||
*/
|
||||
public interface Uart extends Closeable {
|
||||
/** Parity-bit mode. */
|
||||
|
||||
0
IOIOLib/src/ioio/lib/api/exception/IncompatibilityException.java
Executable file → Normal file
0
IOIOLib/src/ioio/lib/api/exception/IncompatibilityException.java
Executable file → Normal file
@@ -1,3 +1,32 @@
|
||||
/*
|
||||
* Copyright 2011 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.bluetooth;
|
||||
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
@@ -8,43 +37,41 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.UUID;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
public class BluetoothIOIOConnection implements IOIOConnection {
|
||||
private static final String TAG = "BluetoothIOIOConnection";
|
||||
private BluetoothSocket socket_ = null;
|
||||
private boolean disconnect_ = false;
|
||||
private final BluetoothDevice device_;
|
||||
private final String name_;
|
||||
private final String address_;
|
||||
|
||||
public BluetoothIOIOConnection(String name, String address) {
|
||||
name_ = name;
|
||||
address_ = address;
|
||||
public BluetoothIOIOConnection(BluetoothDevice device) {
|
||||
device_ = device;
|
||||
name_ = device.getName();
|
||||
address_ = device.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForConnect() throws ConnectionLostException {
|
||||
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
final BluetoothDevice ioioDevice = adapter.getRemoteDevice(address_);
|
||||
synchronized (this) {
|
||||
if (disconnect_) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
Log.v(TAG, name_ + " Creating socket");
|
||||
try {
|
||||
socket_ = createSocket(ioioDevice);
|
||||
socket_ = createSocket(device_);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
Log.v(TAG, name_ + " Created socket");
|
||||
}
|
||||
// keep trying to connect as long as we're not aborting
|
||||
while (true) {
|
||||
try {
|
||||
Log.v(TAG, name_ + "Connecting");
|
||||
Log.v(TAG, "Attempting to connect to Bluetooth device: " + name_);
|
||||
socket_.connect();
|
||||
Log.v(TAG, "Established connection to device " + name_
|
||||
+ " address: " + address_);
|
||||
@@ -61,17 +88,15 @@ public class BluetoothIOIOConnection implements IOIOConnection {
|
||||
}
|
||||
}
|
||||
|
||||
public BluetoothSocket createSocket(final BluetoothDevice device)
|
||||
public static BluetoothSocket createSocket(final BluetoothDevice device)
|
||||
throws IOException {
|
||||
try {
|
||||
// We're trying to create an insecure socket, which is
|
||||
// only supported
|
||||
// in API 10 and up. If we fail, we try a secure socket
|
||||
// with is in API
|
||||
// 7 and up.
|
||||
if (Build.VERSION.SDK_INT >= 10 ) {
|
||||
// We're trying to create an insecure socket, which is only
|
||||
// supported in API 10 and up. Otherwise, we try a secure socket
|
||||
// which is in API 7 and up.
|
||||
return device.createInsecureRfcommSocketToServiceRecord(UUID
|
||||
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
|
||||
} catch (NoSuchMethodError e) {
|
||||
} else {
|
||||
return device.createRfcommSocketToServiceRecord(UUID
|
||||
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
|
||||
}
|
||||
@@ -82,7 +107,7 @@ public class BluetoothIOIOConnection implements IOIOConnection {
|
||||
if (disconnect_) {
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Client initiated disconnect");
|
||||
Log.v(TAG, "Client initiated disconnect");
|
||||
disconnect_ = true;
|
||||
if (socket_ != null) {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2011 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.bluetooth;
|
||||
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
import ioio.lib.spi.IOIOConnectionBootstrap;
|
||||
import ioio.lib.spi.IOIOConnectionFactory;
|
||||
import ioio.lib.spi.NoRuntimeSupportException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.util.Log;
|
||||
|
||||
public class BluetoothIOIOConnectionBootstrap implements
|
||||
IOIOConnectionBootstrap {
|
||||
|
||||
private static final String TAG = "BluetoothIOIOConnectionDiscovery";
|
||||
private final BluetoothAdapter adapter_;
|
||||
|
||||
public BluetoothIOIOConnectionBootstrap() throws NoRuntimeSupportException {
|
||||
try {
|
||||
adapter_ = BluetoothAdapter.getDefaultAdapter();
|
||||
} catch (NoClassDefFoundError e) {
|
||||
throw new NoRuntimeSupportException(
|
||||
"Bluetooth is not supported on this device.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getFactories(Collection<IOIOConnectionFactory> result) {
|
||||
try {
|
||||
Set<BluetoothDevice> bondedDevices = adapter_.getBondedDevices();
|
||||
for (final BluetoothDevice device : bondedDevices) {
|
||||
if (device.getName().startsWith("IOIO")) {
|
||||
result.add(new IOIOConnectionFactory() {
|
||||
@Override
|
||||
public String getType() {
|
||||
return BluetoothIOIOConnection.class
|
||||
.getCanonicalName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getExtra() {
|
||||
return new Object[] { device.getName(),
|
||||
device.getAddress() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public IOIOConnection createConnection() {
|
||||
return new BluetoothIOIOConnection(device);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG,
|
||||
"Did you forget to declare uses-permission of android.permission.BLUETOOTH?");
|
||||
throw e;
|
||||
} catch (NoClassDefFoundError e) {
|
||||
Log.w(TAG, "Bluetooth is not supported on this device.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package ioio.lib.bluetooth;
|
||||
|
||||
import ioio.lib.util.IOIOConnectionDiscovery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.util.Log;
|
||||
|
||||
public class BluetoothIOIOConnectionDiscovery implements
|
||||
IOIOConnectionDiscovery {
|
||||
|
||||
private static final String TAG = "BluetoothIOIOConnectionDiscovery";
|
||||
|
||||
@Override
|
||||
public void getSpecs(Collection<IOIOConnectionSpec> result) {
|
||||
try {
|
||||
final BluetoothAdapter adapter = BluetoothAdapter
|
||||
.getDefaultAdapter();
|
||||
Set<BluetoothDevice> bondedDevices = adapter.getBondedDevices();
|
||||
for (BluetoothDevice device : bondedDevices) {
|
||||
if (device.getName().startsWith("IOIO")) {
|
||||
result.add(new IOIOConnectionSpec(
|
||||
BluetoothIOIOConnection.class.getName(),
|
||||
new Object[] { device.getName(),
|
||||
device.getAddress() }));
|
||||
}
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG,
|
||||
"Did you forget to declare uses-permission of android.permission.BLUETOOTH?");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
IOIOLib/src/ioio/lib/impl/AbstractPin.java
Executable file → Normal file
3
IOIOLib/src/ioio/lib/impl/AbstractPin.java
Executable file → Normal file
@@ -30,7 +30,7 @@ package ioio.lib.impl;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
public abstract class AbstractPin extends AbstractResource {
|
||||
abstract class AbstractPin extends AbstractResource {
|
||||
protected final int pinNum_;
|
||||
|
||||
AbstractPin(IOIOImpl ioio, int pinNum) throws ConnectionLostException {
|
||||
@@ -38,6 +38,7 @@ public abstract class AbstractPin extends AbstractResource {
|
||||
pinNum_ = pinNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
ioio_.closePin(pinNum_);
|
||||
|
||||
3
IOIOLib/src/ioio/lib/impl/AbstractResource.java
Executable file → Normal file
3
IOIOLib/src/ioio/lib/impl/AbstractResource.java
Executable file → Normal file
@@ -32,7 +32,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IncomingState.DisconnectListener;
|
||||
import ioio.lib.api.Closeable;
|
||||
|
||||
public class AbstractResource implements Closeable, DisconnectListener {
|
||||
class AbstractResource implements Closeable, DisconnectListener {
|
||||
enum State {
|
||||
OPEN,
|
||||
CLOSED,
|
||||
@@ -53,6 +53,7 @@ public class AbstractResource implements Closeable, DisconnectListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
if (state_ == State.CLOSED) {
|
||||
throw new IllegalStateException("Trying to use a closed resouce");
|
||||
|
||||
103
IOIOLib/src/ioio/lib/impl/AnalogInputImpl.java
Executable file → Normal file
103
IOIOLib/src/ioio/lib/impl/AnalogInputImpl.java
Executable file → Normal file
@@ -28,22 +28,31 @@
|
||||
*/
|
||||
package ioio.lib.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ioio.lib.api.AnalogInput;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IncomingState.InputPinListener;
|
||||
|
||||
public class AnalogInputImpl extends AbstractPin implements AnalogInput, InputPinListener {
|
||||
import java.io.IOException;
|
||||
|
||||
class AnalogInputImpl extends AbstractPin implements AnalogInput,
|
||||
InputPinListener {
|
||||
private int value_;
|
||||
private boolean valid_ = false;
|
||||
|
||||
short[] buffer_;
|
||||
int bufferSize_;
|
||||
int bufferCapacity_;
|
||||
int bufferReadCursor_;
|
||||
int bufferWriteCursor_;
|
||||
int bufferOverflowCount_ = 0;
|
||||
|
||||
AnalogInputImpl(IOIOImpl ioio, int pin) throws ConnectionLostException {
|
||||
super(ioio, pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVoltage() throws InterruptedException, ConnectionLostException {
|
||||
public float getVoltage() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
return read() * getReference();
|
||||
}
|
||||
|
||||
@@ -55,18 +64,20 @@ public class AnalogInputImpl extends AbstractPin implements AnalogInput, InputPi
|
||||
@Override
|
||||
synchronized public void setValue(int value) {
|
||||
// Log.v("AnalogInputImpl", "Pin " + pinNum_ + " value is " + value);
|
||||
assert(value >= 0 || value < 1024);
|
||||
assert (value >= 0 && value < 1024);
|
||||
value_ = value;
|
||||
if (!valid_) {
|
||||
valid_ = true;
|
||||
notifyAll();
|
||||
}
|
||||
bufferPush((short) value);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public float read() throws InterruptedException, ConnectionLostException {
|
||||
synchronized public float read() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
checkState();
|
||||
while (!valid_ && state_ != State.DISCONNECTED) {
|
||||
while (!valid_ && state_ == State.OPEN) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
@@ -87,4 +98,82 @@ public class AnalogInputImpl extends AbstractPin implements AnalogInput, InputPi
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setBuffer(int capacity)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
if (capacity <= 0) {
|
||||
buffer_ = null;
|
||||
} else {
|
||||
buffer_ = new short[capacity];
|
||||
}
|
||||
bufferCapacity_ = capacity;
|
||||
bufferSize_ = 0;
|
||||
bufferReadCursor_ = 0;
|
||||
bufferWriteCursor_ = 0;
|
||||
bufferOverflowCount_ = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readBuffered() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
checkState();
|
||||
return (float) bufferPull() / 1023.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVoltageBuffered() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
return readBuffered() * getReference();
|
||||
}
|
||||
|
||||
private void bufferPush(short value) {
|
||||
if (buffer_ == null) {
|
||||
return;
|
||||
}
|
||||
if (bufferSize_ == bufferCapacity_) {
|
||||
++bufferOverflowCount_;
|
||||
} else {
|
||||
++bufferSize_;
|
||||
}
|
||||
buffer_[bufferWriteCursor_++] = value;
|
||||
if (bufferWriteCursor_ == bufferCapacity_) {
|
||||
bufferWriteCursor_ = 0;
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
private synchronized short bufferPull() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
if (buffer_ == null) {
|
||||
throw new IllegalStateException(
|
||||
"Need to call setBuffer() before reading buffered values.");
|
||||
}
|
||||
while (bufferSize_ == 0 && state_ == State.OPEN) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
short result = buffer_[bufferReadCursor_++];
|
||||
if (bufferReadCursor_ == bufferCapacity_) {
|
||||
bufferReadCursor_ = 0;
|
||||
}
|
||||
--bufferSize_;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOverflowCount() throws ConnectionLostException {
|
||||
return bufferOverflowCount_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSampleRate() throws ConnectionLostException {
|
||||
return 1000.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws ConnectionLostException {
|
||||
return bufferSize_;
|
||||
}
|
||||
}
|
||||
|
||||
0
IOIOLib/src/ioio/lib/impl/Constants.java
Executable file → Normal file
0
IOIOLib/src/ioio/lib/impl/Constants.java
Executable file → Normal file
3
IOIOLib/src/ioio/lib/impl/DigitalInputImpl.java
Executable file → Normal file
3
IOIOLib/src/ioio/lib/impl/DigitalInputImpl.java
Executable file → Normal file
@@ -34,7 +34,7 @@ import ioio.lib.impl.IncomingState.InputPinListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DigitalInputImpl extends AbstractPin implements DigitalInput,
|
||||
class DigitalInputImpl extends AbstractPin implements DigitalInput,
|
||||
InputPinListener {
|
||||
private boolean value_;
|
||||
private boolean valid_ = false;
|
||||
@@ -54,6 +54,7 @@ public class DigitalInputImpl extends AbstractPin implements DigitalInput,
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void waitForValue(boolean value)
|
||||
throws InterruptedException, ConnectionLostException {
|
||||
checkState();
|
||||
|
||||
18
IOIOLib/src/ioio/lib/impl/DigitalOutputImpl.java
Executable file → Normal file
18
IOIOLib/src/ioio/lib/impl/DigitalOutputImpl.java
Executable file → Normal file
@@ -33,18 +33,24 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DigitalOutputImpl extends AbstractPin implements DigitalOutput {
|
||||
DigitalOutputImpl(IOIOImpl ioio, int pin) throws ConnectionLostException {
|
||||
class DigitalOutputImpl extends AbstractPin implements DigitalOutput {
|
||||
boolean value_;
|
||||
|
||||
DigitalOutputImpl(IOIOImpl ioio, int pin, boolean startValue) throws ConnectionLostException {
|
||||
super(ioio, pin);
|
||||
value_ = startValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void write(boolean val) throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
ioio_.protocol_.setDigitalOutLevel(pinNum_, val);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
if (val != value_) {
|
||||
try {
|
||||
ioio_.protocol_.setDigitalOutLevel(pinNum_, val);
|
||||
value_ = val;
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
IOIOLib/src/ioio/lib/impl/FlowControlledOutputStream.java
Executable file → Normal file
9
IOIOLib/src/ioio/lib/impl/FlowControlledOutputStream.java
Executable file → Normal file
@@ -33,7 +33,7 @@ import java.io.OutputStream;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class FlowControlledOutputStream extends OutputStream {
|
||||
class FlowControlledOutputStream extends OutputStream {
|
||||
interface Sender {
|
||||
void send(byte[] data, int size);
|
||||
}
|
||||
@@ -91,15 +91,14 @@ public class FlowControlledOutputStream extends OutputStream {
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
if (closed_) {
|
||||
return;
|
||||
}
|
||||
closed_ = true;
|
||||
notifyAll();
|
||||
thread_.interrupt();
|
||||
}
|
||||
|
||||
synchronized public void kill() {
|
||||
thread_.interrupt();
|
||||
}
|
||||
|
||||
class FlushThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/FlowControlledPacketSender.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/FlowControlledPacketSender.java
Executable file → Normal file
@@ -32,7 +32,7 @@ import java.io.IOException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class FlowControlledPacketSender {
|
||||
class FlowControlledPacketSender {
|
||||
interface Packet {
|
||||
int getSize();
|
||||
}
|
||||
|
||||
80
IOIOLib/src/ioio/lib/impl/IOIOImpl.java
Executable file → Normal file
80
IOIOLib/src/ioio/lib/impl/IOIOImpl.java
Executable file → Normal file
@@ -55,10 +55,7 @@ import android.util.Log;
|
||||
|
||||
public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
private static final String TAG = "IOIOImpl";
|
||||
|
||||
enum State {
|
||||
INIT, CONNECTED, INCOMPATIBLE, DEAD
|
||||
}
|
||||
private boolean disconnect_ = false;
|
||||
|
||||
private static final byte[] REQUIRED_INTERFACE_ID = new byte[] { 'I', 'O',
|
||||
'I', 'O', '0', '0', '0', '3' };
|
||||
@@ -86,7 +83,7 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void waitForConnect() throws ConnectionLostException,
|
||||
public void waitForConnect() throws ConnectionLostException,
|
||||
IncompatibilityException {
|
||||
if (state_ == State.CONNECTED) {
|
||||
return;
|
||||
@@ -98,19 +95,26 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
Log.d(TAG, "Waiting for IOIO connection");
|
||||
try {
|
||||
try {
|
||||
Log.d(TAG, "Waiting for underlying connection");
|
||||
Log.v(TAG, "Waiting for underlying connection");
|
||||
connection_.waitForConnect();
|
||||
protocol_ = new IOIOProtocol(connection_.getInputStream(),
|
||||
connection_.getOutputStream(), incomingState_);
|
||||
synchronized (this) {
|
||||
if (disconnect_) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
protocol_ = new IOIOProtocol(connection_.getInputStream(),
|
||||
connection_.getOutputStream(), incomingState_);
|
||||
// Once this block exits, a disconnect will also involve
|
||||
// softClose().
|
||||
}
|
||||
} catch (ConnectionLostException e) {
|
||||
incomingState_.handleConnectionLost();
|
||||
throw e;
|
||||
}
|
||||
Log.d(TAG, "Waiting for handshake");
|
||||
Log.v(TAG, "Waiting for handshake");
|
||||
incomingState_.waitConnectionEstablished();
|
||||
Log.d(TAG, "Querying for required interface ID");
|
||||
Log.v(TAG, "Querying for required interface ID");
|
||||
checkInterfaceVersion();
|
||||
Log.d(TAG, "Required interface ID is supported");
|
||||
Log.v(TAG, "Required interface ID is supported");
|
||||
state_ = State.CONNECTED;
|
||||
Log.i(TAG, "IOIO connection established");
|
||||
} catch (ConnectionLostException e) {
|
||||
@@ -123,21 +127,44 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
public synchronized void disconnect() {
|
||||
Log.d(TAG, "Client requested disconnect.");
|
||||
if (disconnect_) {
|
||||
return;
|
||||
}
|
||||
disconnect_ = true;
|
||||
try {
|
||||
if (protocol_ != null) {
|
||||
protocol_.softClose();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Soft close failed", e);
|
||||
}
|
||||
connection_.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
public synchronized void disconnected() {
|
||||
state_ = State.DEAD;
|
||||
if (disconnect_) {
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Physical disconnect.");
|
||||
disconnect_ = true;
|
||||
// The IOIOConnection doesn't necessarily know about the disconnect
|
||||
disconnect();
|
||||
connection_.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForDisconnect() throws InterruptedException {
|
||||
incomingState_.waitDisconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public State getState() {
|
||||
return state_;
|
||||
}
|
||||
|
||||
private void checkInterfaceVersion() throws IncompatibilityException,
|
||||
ConnectionLostException, InterruptedException {
|
||||
try {
|
||||
@@ -272,7 +299,10 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
|
||||
@Override
|
||||
public String getImplVersion(VersionType v) throws ConnectionLostException {
|
||||
checkState();
|
||||
if (state_ == State.INIT) {
|
||||
throw new IllegalStateException(
|
||||
"Connection has not yet been established");
|
||||
}
|
||||
switch (v) {
|
||||
case HARDWARE_VER:
|
||||
return incomingState_.hardwareId_;
|
||||
@@ -281,7 +311,7 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
case APP_FIRMWARE_VER:
|
||||
return incomingState_.firmwareId_;
|
||||
case IOIOLIB_VER:
|
||||
return "IOIO0311";
|
||||
return "IOIO0322";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -332,7 +362,7 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
checkState();
|
||||
PinFunctionMap.checkValidPin(spec.pin);
|
||||
checkPinFree(spec.pin);
|
||||
DigitalOutputImpl result = new DigitalOutputImpl(this, spec.pin);
|
||||
DigitalOutputImpl result = new DigitalOutputImpl(this, spec.pin, startValue);
|
||||
addDisconnectListener(result);
|
||||
openPins_[spec.pin] = true;
|
||||
try {
|
||||
@@ -651,4 +681,20 @@ public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
"Connection has not yet been established");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void beginBatch() throws ConnectionLostException {
|
||||
checkState();
|
||||
protocol_.beginBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void endBatch() throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
protocol_.endBatch();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
129
IOIOLib/src/ioio/lib/impl/IOIOProtocol.java
Executable file → Normal file
129
IOIOLib/src/ioio/lib/impl/IOIOProtocol.java
Executable file → Normal file
@@ -43,7 +43,7 @@ import java.util.Set;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class IOIOProtocol {
|
||||
class IOIOProtocol {
|
||||
static final int HARD_RESET = 0x00;
|
||||
static final int ESTABLISH_CONNECTION = 0x00;
|
||||
static final int SOFT_RESET = 0x01;
|
||||
@@ -90,6 +90,7 @@ public class IOIOProtocol {
|
||||
static final int INCAP_STATUS = 0x1B;
|
||||
static final int SET_PIN_INCAP = 0x1C;
|
||||
static final int INCAP_REPORT = 0x1C;
|
||||
static final int SOFT_CLOSE = 0x1D;
|
||||
|
||||
static final int[] SCALE_DIV = new int[] {
|
||||
0x1F, // 31.25
|
||||
@@ -133,15 +134,30 @@ public class IOIOProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] outbuf_ = new byte[128];
|
||||
private byte[] outbuf_ = new byte[256];
|
||||
private int pos_ = 0;
|
||||
private int batchCounter_ = 0;
|
||||
|
||||
private void writeByte(int b) {
|
||||
private void writeByte(int b) throws IOException {
|
||||
assert (b >= 0 && b < 256);
|
||||
if (pos_ == outbuf_.length) {
|
||||
// buffer is full
|
||||
flush();
|
||||
}
|
||||
//Log.v(TAG, "sending: 0x" + Integer.toHexString(b));
|
||||
outbuf_[pos_++] = (byte) b;
|
||||
}
|
||||
|
||||
public synchronized void beginBatch() {
|
||||
++batchCounter_;
|
||||
}
|
||||
|
||||
public synchronized void endBatch() throws IOException {
|
||||
if (--batchCounter_ == 0) {
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void flush() throws IOException {
|
||||
try {
|
||||
out_.write(outbuf_, 0, pos_);
|
||||
@@ -162,17 +178,25 @@ public class IOIOProtocol {
|
||||
}
|
||||
|
||||
synchronized public void hardReset() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(HARD_RESET);
|
||||
writeByte('I');
|
||||
writeByte('O');
|
||||
writeByte('I');
|
||||
writeByte('O');
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void softReset() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SOFT_RESET);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void softClose() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SOFT_CLOSE);
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void checkInterface(byte[] interfaceId)
|
||||
@@ -181,71 +205,80 @@ public class IOIOProtocol {
|
||||
throw new IllegalArgumentException(
|
||||
"interface ID must be exactly 8 bytes long");
|
||||
}
|
||||
beginBatch();
|
||||
writeByte(CHECK_INTERFACE);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
writeByte(interfaceId[i]);
|
||||
}
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setDigitalOutLevel(int pin, boolean level)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_DIGITAL_OUT_LEVEL);
|
||||
writeByte(pin << 2 | (level ? 1 : 0));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPinPwm(int pin, int pwmNum, boolean enable)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_PWM);
|
||||
writeByte(pin & 0x3F);
|
||||
writeByte((enable ? 0x80 : 0x00) | (pwmNum & 0x0F));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPwmDutyCycle(int pwmNum, int dutyCycle,
|
||||
int fraction) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PWM_DUTY_CYCLE);
|
||||
writeByte(pwmNum << 2 | fraction);
|
||||
writeTwoBytes(dutyCycle);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPwmPeriod(int pwmNum, int period, PwmScale scale)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PWM_PERIOD);
|
||||
writeByte(((scale.encoding & 0x02) << 6) | (pwmNum << 1)
|
||||
| (scale.encoding & 0x01));
|
||||
writeTwoBytes(period);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPinIncap(int pin, int incapNum, boolean enable)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_INCAP);
|
||||
writeByte(pin);
|
||||
writeByte(incapNum | (enable ? 0x80 : 0x00));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void incapClose(int incapNum) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(INCAP_CONFIGURE);
|
||||
writeByte(incapNum);
|
||||
writeByte(0x00);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void incapConfigure(int incapNum, boolean double_prec,
|
||||
int mode, int clock) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(INCAP_CONFIGURE);
|
||||
writeByte(incapNum);
|
||||
writeByte((double_prec ? 0x80 : 0x00) | (mode << 3) | clock);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void i2cWriteRead(int i2cNum, boolean tenBitAddr,
|
||||
int address, int writeSize, int readSize, byte[] writeData)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(I2C_WRITE_READ);
|
||||
writeByte(((address >> 8) << 6) | (tenBitAddr ? 0x20 : 0x00) | i2cNum);
|
||||
writeByte(address & 0xFF);
|
||||
@@ -254,16 +287,17 @@ public class IOIOProtocol {
|
||||
for (int i = 0; i < writeSize; ++i) {
|
||||
writeByte(((int) writeData[i]) & 0xFF);
|
||||
}
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPinDigitalOut(int pin, boolean value,
|
||||
DigitalOutput.Spec.Mode mode) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_DIGITAL_OUT);
|
||||
writeByte((pin << 2)
|
||||
| (mode == DigitalOutput.Spec.Mode.OPEN_DRAIN ? 0x01 : 0x00)
|
||||
| (value ? 0x02 : 0x00));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPinDigitalIn(int pin,
|
||||
@@ -274,16 +308,18 @@ public class IOIOProtocol {
|
||||
} else if (mode == DigitalInput.Spec.Mode.PULL_DOWN) {
|
||||
pull = 2;
|
||||
}
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_DIGITAL_IN);
|
||||
writeByte((pin << 2) | pull);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setChangeNotify(int pin, boolean changeNotify)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_CHANGE_NOTIFY);
|
||||
writeByte((pin << 2) | (changeNotify ? 0x01 : 0x00));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void registerPeriodicDigitalSampling(int pin,
|
||||
@@ -292,16 +328,18 @@ public class IOIOProtocol {
|
||||
}
|
||||
|
||||
synchronized public void setPinAnalogIn(int pin) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_ANALOG_IN);
|
||||
writeByte(pin);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setAnalogInSampling(int pin, boolean enable)
|
||||
throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_ANALOG_IN_SAMPLING);
|
||||
writeByte((enable ? 0x80 : 0x00) | (pin & 0x3F));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void uartData(int uartNum, int numBytes, byte data[])
|
||||
@@ -311,12 +349,13 @@ public class IOIOProtocol {
|
||||
"A maximum of 64 bytes can be sent in one uartData message. Got: "
|
||||
+ numBytes);
|
||||
}
|
||||
beginBatch();
|
||||
writeByte(UART_DATA);
|
||||
writeByte((numBytes - 1) | uartNum << 6);
|
||||
for (int i = 0; i < numBytes; ++i) {
|
||||
writeByte(((int) data[i]) & 0xFF);
|
||||
}
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void uartConfigure(int uartNum, int rate,
|
||||
@@ -324,50 +363,56 @@ public class IOIOProtocol {
|
||||
throws IOException {
|
||||
int parbits = parity == Uart.Parity.EVEN ? 1
|
||||
: (parity == Uart.Parity.ODD ? 2 : 0);
|
||||
beginBatch();
|
||||
writeByte(UART_CONFIG);
|
||||
writeByte((uartNum << 6) | (speed4x ? 0x08 : 0x00)
|
||||
| (stopbits == Uart.StopBits.TWO ? 0x04 : 0x00) | parbits);
|
||||
writeTwoBytes(rate);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void uartClose(int uartNum) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(UART_CONFIG);
|
||||
writeByte(uartNum << 6);
|
||||
writeTwoBytes(0);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPinUart(int pin, int uartNum, boolean tx,
|
||||
boolean enable) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_UART);
|
||||
writeByte(pin);
|
||||
writeByte((enable ? 0x80 : 0x00) | (tx ? 0x40 : 0x00) | uartNum);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void spiConfigureMaster(int spiNum,
|
||||
SpiMaster.Config config) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SPI_CONFIGURE_MASTER);
|
||||
writeByte((spiNum << 5) | SCALE_DIV[config.rate.ordinal()]);
|
||||
writeByte((config.sampleOnTrailing ? 0x00 : 0x02)
|
||||
| (config.invertClk ? 0x01 : 0x00));
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void spiClose(int spiNum) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SPI_CONFIGURE_MASTER);
|
||||
writeByte(spiNum << 5);
|
||||
writeByte(0x00);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void setPinSpi(int pin, int mode, boolean enable,
|
||||
int spiNum) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(SET_PIN_SPI);
|
||||
writeByte(pin);
|
||||
writeByte((1 << 4) | (mode << 2) | spiNum);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void spiMasterRequest(int spiNum, int ssPin,
|
||||
@@ -375,6 +420,7 @@ public class IOIOProtocol {
|
||||
throws IOException {
|
||||
final boolean dataNeqTotal = (dataBytes != totalBytes);
|
||||
final boolean resNeqTotal = (responseBytes != totalBytes);
|
||||
beginBatch();
|
||||
writeByte(SPI_MASTER_REQUEST);
|
||||
writeByte((spiNum << 6) | ssPin);
|
||||
writeByte((dataNeqTotal ? 0x80 : 0x00) | (resNeqTotal ? 0x40 : 0x00)
|
||||
@@ -388,55 +434,63 @@ public class IOIOProtocol {
|
||||
for (int i = 0; i < dataBytes; ++i) {
|
||||
writeByte(((int) data[i]) & 0xFF);
|
||||
}
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void i2cConfigureMaster(int i2cNum, Rate rate,
|
||||
boolean smbusLevels) throws IOException {
|
||||
int rateBits = (rate == Rate.RATE_1MHz ? 3
|
||||
: (rate == Rate.RATE_400KHz ? 2 : 1));
|
||||
beginBatch();
|
||||
writeByte(I2C_CONFIGURE_MASTER);
|
||||
writeByte((smbusLevels ? 0x80 : 0) | (rateBits << 5) | i2cNum);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
synchronized public void i2cClose(int i2cNum) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(I2C_CONFIGURE_MASTER);
|
||||
writeByte(i2cNum);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public void icspOpen() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(ICSP_CONFIG);
|
||||
writeByte(0x01);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public void icspClose() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(ICSP_CONFIG);
|
||||
writeByte(0x00);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public void icspEnter() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(ICSP_PROG_ENTER);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public void icspExit() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(ICSP_PROG_EXIT);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public void icspSix(int instruction) throws IOException {
|
||||
beginBatch();
|
||||
writeByte(ICSP_SIX);
|
||||
writeThreeBytes(instruction);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public void icspRegout() throws IOException {
|
||||
beginBatch();
|
||||
writeByte(ICSP_REGOUT);
|
||||
flush();
|
||||
endBatch();
|
||||
}
|
||||
|
||||
public interface IncomingHandler {
|
||||
@@ -768,6 +822,11 @@ public class IOIOProtocol {
|
||||
handler_.handleIncapReport(arg1 & 0x0F, size, data);
|
||||
break;
|
||||
|
||||
case SOFT_CLOSE:
|
||||
Log.d(TAG, "Received soft close.");
|
||||
throw new IOException("Soft close");
|
||||
|
||||
|
||||
default:
|
||||
in_.close();
|
||||
IOException e = new IOException(
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/IcspMasterImpl.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/IcspMasterImpl.java
Executable file → Normal file
@@ -36,7 +36,7 @@ import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class IcspMasterImpl extends AbstractResource implements IcspMaster,
|
||||
class IcspMasterImpl extends AbstractResource implements IcspMaster,
|
||||
DataModuleListener {
|
||||
private Queue<Integer> resultQueue_ = new LinkedList<Integer>();
|
||||
private int rxRemaining_ = 0;
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/IncapImpl.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/IncapImpl.java
Executable file → Normal file
@@ -7,7 +7,7 @@ import ioio.lib.impl.IncomingState.DataModuleListener;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class IncapImpl extends AbstractPin implements DataModuleListener,
|
||||
class IncapImpl extends AbstractPin implements DataModuleListener,
|
||||
PulseInput {
|
||||
private static final int MAX_QUEUE_LEN = 32;
|
||||
private final PulseMode mode_;
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/IncomingState.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/IncomingState.java
Executable file → Normal file
@@ -38,7 +38,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class IncomingState implements IncomingHandler {
|
||||
class IncomingState implements IncomingHandler {
|
||||
enum ConnectionState {
|
||||
INIT, ESTABLISHED, CONNECTED, DISCONNECTED, UNSUPPORTED_IID
|
||||
}
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/ModuleAllocator.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/ModuleAllocator.java
Executable file → Normal file
@@ -44,7 +44,7 @@ import java.util.TreeSet;
|
||||
*
|
||||
* @author birmiwal
|
||||
*/
|
||||
public class ModuleAllocator {
|
||||
class ModuleAllocator {
|
||||
private final Set<Integer> availableModuleIds_;
|
||||
private final Set<Integer> allocatedModuleIds_;
|
||||
private final String name_;
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/PinFunctionMap.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/PinFunctionMap.java
Executable file → Normal file
@@ -29,7 +29,7 @@
|
||||
package ioio.lib.impl;
|
||||
|
||||
|
||||
public class PinFunctionMap {
|
||||
class PinFunctionMap {
|
||||
private static final boolean[] PERIPHERAL_OUT = new boolean[] { true,
|
||||
false, false, true, true, true, true, true, false, false, true,
|
||||
true, true, true, true, false, false, false, false, false, false,
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/PwmImpl.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/PwmImpl.java
Executable file → Normal file
@@ -33,7 +33,7 @@ import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PwmImpl extends AbstractResource implements PwmOutput {
|
||||
class PwmImpl extends AbstractResource implements PwmOutput {
|
||||
private final int pwmNum_;
|
||||
private final int pinNum_;
|
||||
private final float baseUs_;
|
||||
|
||||
56
IOIOLib/src/ioio/lib/impl/QueueInputStream.java
Executable file → Normal file
56
IOIOLib/src/ioio/lib/impl/QueueInputStream.java
Executable file → Normal file
@@ -35,26 +35,60 @@ import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class QueueInputStream extends InputStream {
|
||||
class QueueInputStream extends InputStream {
|
||||
private enum State {
|
||||
OPEN, CLOSED, KILLED
|
||||
};
|
||||
|
||||
private final Queue<Byte> queue_ = new ArrayBlockingQueue<Byte>(
|
||||
Constants.BUFFER_SIZE);
|
||||
private boolean closed_ = false;
|
||||
private State state_ = State.OPEN;
|
||||
|
||||
@Override
|
||||
synchronized public int read() throws IOException {
|
||||
try {
|
||||
while (!closed_ && queue_.isEmpty()) {
|
||||
while (state_ == State.OPEN && queue_.isEmpty()) {
|
||||
wait();
|
||||
}
|
||||
if (closed_) {
|
||||
if (state_ == State.KILLED) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
if (state_ == State.CLOSED && queue_.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
return ((int) queue_.remove()) & 0xFF;
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int read(byte[] b, int off, int len) throws IOException {
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
try {
|
||||
while (state_ == State.OPEN && queue_.isEmpty()) {
|
||||
wait();
|
||||
}
|
||||
if (state_ == State.KILLED) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
if (state_ == State.CLOSED && queue_.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
if (len > queue_.size()) {
|
||||
len = queue_.size();
|
||||
}
|
||||
for (int i = 0; i < len; ++i) {
|
||||
b[off++] = queue_.remove();
|
||||
}
|
||||
return len;
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public void write(byte[] data, int size) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (queue_.size() == Constants.BUFFER_SIZE) {
|
||||
@@ -73,7 +107,19 @@ public class QueueInputStream extends InputStream {
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
closed_ = true;
|
||||
if (state_ != State.OPEN) {
|
||||
return;
|
||||
}
|
||||
state_ = State.CLOSED;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized public void kill() {
|
||||
if (state_ != State.OPEN) {
|
||||
return;
|
||||
}
|
||||
state_ = State.KILLED;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
19
IOIOLib/src/ioio/lib/impl/SocketIOIOConnection.java
Executable file → Normal file
19
IOIOLib/src/ioio/lib/impl/SocketIOIOConnection.java
Executable file → Normal file
@@ -41,6 +41,7 @@ import java.net.SocketException;
|
||||
import android.util.Log;
|
||||
|
||||
public class SocketIOIOConnection implements IOIOConnection {
|
||||
private static final String TAG = "SocketIOIOConnection";
|
||||
private final int port_;
|
||||
private ServerSocket server_ = null;
|
||||
private Socket socket_ = null;
|
||||
@@ -48,7 +49,7 @@ public class SocketIOIOConnection implements IOIOConnection {
|
||||
private boolean server_owned_by_connect_ = true;
|
||||
private boolean socket_owned_by_connect_ = true;
|
||||
|
||||
public SocketIOIOConnection(Integer port) {
|
||||
public SocketIOIOConnection(int port) {
|
||||
port_ = port;
|
||||
}
|
||||
|
||||
@@ -59,13 +60,13 @@ public class SocketIOIOConnection implements IOIOConnection {
|
||||
if (disconnect_) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
Log.d("SocketIOIOConnection", "Creating server socket");
|
||||
Log.v(TAG, "Creating server socket");
|
||||
server_ = new ServerSocket(port_);
|
||||
server_owned_by_connect_ = false;
|
||||
}
|
||||
Log.d("SocketIOIOConnection", "Waiting for TCP connection");
|
||||
Log.v(TAG, "Waiting for TCP connection");
|
||||
socket_ = server_.accept();
|
||||
Log.d("SocketIOIOConnection", "TCP connected");
|
||||
Log.v(TAG, "TCP connected");
|
||||
synchronized (this) {
|
||||
if (disconnect_) {
|
||||
socket_.close();
|
||||
@@ -80,18 +81,18 @@ public class SocketIOIOConnection implements IOIOConnection {
|
||||
try {
|
||||
server_.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("SocketIOIOConnection", "Unexpected exception", e1);
|
||||
Log.e(TAG, "Unexpected exception", e1);
|
||||
}
|
||||
}
|
||||
if (socket_owned_by_connect_ && socket_ != null) {
|
||||
try {
|
||||
socket_.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("SocketIOIOConnection", "Unexpected exception", e1);
|
||||
Log.e(TAG, "Unexpected exception", e1);
|
||||
}
|
||||
}
|
||||
if (e instanceof SocketException && e.getMessage().equals("Permission denied")) {
|
||||
Log.e("SocketIOIOConnection", "Did you forget to declare uses-permission of android.permission.INTERNET?");
|
||||
Log.e(TAG, "Did you forget to declare uses-permission of android.permission.INTERNET?");
|
||||
}
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
@@ -103,13 +104,13 @@ public class SocketIOIOConnection implements IOIOConnection {
|
||||
if (disconnect_) {
|
||||
return;
|
||||
}
|
||||
Log.d("SocketIOIOConnection", "Client initiated disconnect");
|
||||
Log.v(TAG, "Client initiated disconnect");
|
||||
disconnect_ = true;
|
||||
if (!server_owned_by_connect_) {
|
||||
try {
|
||||
server_.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("SocketIOIOConnection", "Unexpected exception", e1);
|
||||
Log.e(TAG, "Unexpected exception", e1);
|
||||
}
|
||||
}
|
||||
if (!socket_owned_by_connect_) {
|
||||
|
||||
63
IOIOLib/src/ioio/lib/impl/SocketIOIOConnectionBootstrap.java
Normal file
63
IOIOLib/src/ioio/lib/impl/SocketIOIOConnectionBootstrap.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2011 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.impl;
|
||||
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
import ioio.lib.spi.IOIOConnectionBootstrap;
|
||||
import ioio.lib.spi.IOIOConnectionFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SocketIOIOConnectionBootstrap implements IOIOConnectionBootstrap {
|
||||
/** The TCP port used for communicating with the IOIO board. */
|
||||
public static final int IOIO_PORT = 4545;
|
||||
|
||||
@Override
|
||||
public void getFactories(Collection<IOIOConnectionFactory> result) {
|
||||
result.add(new IOIOConnectionFactory() {
|
||||
private Integer port_ = new Integer(IOIO_PORT);
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return SocketIOIOConnection.class.getCanonicalName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getExtra() {
|
||||
return port_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IOIOConnection createConnection() {
|
||||
return new SocketIOIOConnection(IOIO_PORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
2
IOIOLib/src/ioio/lib/impl/SpiMasterImpl.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/SpiMasterImpl.java
Executable file → Normal file
@@ -42,7 +42,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class SpiMasterImpl extends AbstractResource implements SpiMaster,
|
||||
class SpiMasterImpl extends AbstractResource implements SpiMaster,
|
||||
DataModuleListener, Sender {
|
||||
public class SpiResult implements Result {
|
||||
boolean ready_;
|
||||
|
||||
2
IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java
Executable file → Normal file
2
IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java
Executable file → Normal file
@@ -40,7 +40,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class TwiMasterImpl extends AbstractResource implements TwiMaster,
|
||||
class TwiMasterImpl extends AbstractResource implements TwiMaster,
|
||||
DataModuleListener, Sender {
|
||||
class TwiResult implements Result {
|
||||
boolean ready_ = false;
|
||||
|
||||
5
IOIOLib/src/ioio/lib/impl/UartImpl.java
Executable file → Normal file
5
IOIOLib/src/ioio/lib/impl/UartImpl.java
Executable file → Normal file
@@ -40,7 +40,7 @@ import java.io.OutputStream;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class UartImpl extends AbstractResource implements DataModuleListener, Sender, Uart {
|
||||
class UartImpl extends AbstractResource implements DataModuleListener, Sender, Uart {
|
||||
private static final int MAX_PACKET = 64;
|
||||
|
||||
private final int uartNum_;
|
||||
@@ -87,7 +87,8 @@ public class UartImpl extends AbstractResource implements DataModuleListener, Se
|
||||
@Override
|
||||
synchronized public void disconnected() {
|
||||
super.disconnected();
|
||||
outgoing_.kill();
|
||||
incoming_.kill();
|
||||
outgoing_.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
41
IOIOLib/src/ioio/lib/spi/IOIOConnectionBootstrap.java
Normal file
41
IOIOLib/src/ioio/lib/spi/IOIOConnectionBootstrap.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2011 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.spi;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Implementing class must have a default constructor. The default constructor
|
||||
* must throw a NoRuntimeSupportException in case the required libraries for
|
||||
* implementing the connections are not available in run-time.
|
||||
*/
|
||||
public interface IOIOConnectionBootstrap {
|
||||
public void getFactories(Collection<IOIOConnectionFactory> result);
|
||||
}
|
||||
21
IOIOLib/src/ioio/lib/spi/IOIOConnectionFactory.java
Normal file
21
IOIOLib/src/ioio/lib/spi/IOIOConnectionFactory.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package ioio.lib.spi;
|
||||
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
|
||||
public interface IOIOConnectionFactory {
|
||||
/**
|
||||
* A unique name of the connection type. Typically a fully-qualified
|
||||
* name of the connection class.
|
||||
*/
|
||||
public String getType();
|
||||
|
||||
/**
|
||||
* Extra information on the connection. This is specific to the
|
||||
* connection type. For example, for a Bluetooth connection, this is an
|
||||
* array containing the name and the Bluetooth address of the remote
|
||||
* IOIO.
|
||||
*/
|
||||
public Object getExtra();
|
||||
|
||||
public IOIOConnection createConnection();
|
||||
}
|
||||
9
IOIOLib/src/ioio/lib/spi/NoRuntimeSupportException.java
Normal file
9
IOIOLib/src/ioio/lib/spi/NoRuntimeSupportException.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package ioio.lib.spi;
|
||||
|
||||
public class NoRuntimeSupportException extends Exception {
|
||||
private static final long serialVersionUID = -6559208663699429514L;
|
||||
|
||||
public NoRuntimeSupportException(String desc) {
|
||||
super(desc);
|
||||
}
|
||||
}
|
||||
258
IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java
Executable file → Normal file
258
IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java
Executable file → Normal file
@@ -1,16 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 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.util;
|
||||
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.IOIOFactory;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.api.exception.IncompatibilityException;
|
||||
import ioio.lib.util.IOIOConnectionDiscovery.IOIOConnectionSpec;
|
||||
import ioio.lib.spi.IOIOConnectionBootstrap;
|
||||
import ioio.lib.spi.IOIOConnectionFactory;
|
||||
import ioio.lib.util.android.ContextWrapperDependent;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Looper;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
@@ -22,73 +54,137 @@ import android.util.Log;
|
||||
*
|
||||
* In the basic usage the client should extend this class and implement
|
||||
* {@link #createIOIOThread()}, which should return an implementation of the
|
||||
* {@link IOIOThread} abstract class. In this implementation, the client
|
||||
* implements the {@link IOIOThread#setup()} method, which gets called as soon
|
||||
* as communication with the IOIO is established, and the {@link IOIOThread
|
||||
* #loop()} method, which gets called repetitively as long as the IOIO is
|
||||
* connected. Both methods should access the {@link IOIOThread#ioio_} field for
|
||||
* controlling the IOIO.
|
||||
* {@link AbstractIOIOActivity.IOIOThread} abstract class. In this
|
||||
* implementation, the client implements the
|
||||
* {@link AbstractIOIOActivity.IOIOThread#setup()} method, which gets called as
|
||||
* soon as communication with the IOIO is established, and the
|
||||
* {@link AbstractIOIOActivity.IOIOThread#loop()} method, which gets called
|
||||
* repetitively as long as the IOIO is connected. Both methods should access the
|
||||
* {@link AbstractIOIOActivity.IOIOThread#ioio_} field for controlling the IOIO.
|
||||
*
|
||||
* In addition, the {@link IOIOThread#disconnected()} method may be overridden
|
||||
* in order to execute logic as soon as a disconnection occurs for whichever
|
||||
* reason. The {@link IOIOThread#incompatible()} method may be overridden in
|
||||
* order to take action in case where a IOIO whose firmware is incompatible with
|
||||
* the IOIOLib version that application is built with.
|
||||
* In addition, the {@link AbstractIOIOActivity.IOIOThread#disconnected()}
|
||||
* method may be overridden in order to execute logic as soon as a disconnection
|
||||
* occurs for whichever reason. The
|
||||
* {@link AbstractIOIOActivity.IOIOThread#incompatible()} method may be
|
||||
* overridden in order to take action in case where a IOIO whose firmware is
|
||||
* incompatible with the IOIOLib version that application is built with.
|
||||
*
|
||||
* In a more advanced use case, more than one IOIO is available. In this case, a
|
||||
* thread will be created for each IOIO, whose semantics are as defined above.
|
||||
* If the client needs to be able to distinguish between them, it is possible to
|
||||
* override {@link #createIOIOThread(String, Object[])} instead of
|
||||
* override {@link #createIOIOThread(String, Object)} instead of
|
||||
* {@link #createIOIOThread()}. The first argument provided will contain the
|
||||
* connection class name, such as ioio.lib.impl.SocketIOIOConnection for a
|
||||
* connection established over a TCP socket (which is used over ADB). The second
|
||||
* argument will contain information specific to the connection type. For
|
||||
* example, in the case of SocketIOIOConnection, the array will contain an
|
||||
* {@link Integer} representing the local port number.
|
||||
* example, in the case of SocketIOIOConnection, the second argument will
|
||||
* contain an {@link Integer} representing the local port number.
|
||||
*
|
||||
* @deprecated Please use {@link ioio.lib.util.android.IOIOActivity} instead.
|
||||
*/
|
||||
public abstract class AbstractIOIOActivity extends Activity {
|
||||
private static final String TAG = "AbstractIOIOActivity";
|
||||
private IOIOConnectionSpec currentSpec_;
|
||||
|
||||
static {
|
||||
IOIOConnectionRegistry
|
||||
.addBootstraps(new String[] {
|
||||
"ioio.lib.android.accessory.AccessoryConnectionBootstrap",
|
||||
"ioio.lib.android.bluetooth.BluetoothIOIOConnectionBootstrap" });
|
||||
}
|
||||
|
||||
private Collection<IOIOThread> threads_ = new LinkedList<IOIOThread>();
|
||||
private Collection<IOIOConnectionBootstrap> bootstraps_ = IOIOConnectionRegistry
|
||||
.getBootstraps();
|
||||
private IOIOConnectionFactory currentConnectionFactory_;
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onResume() if
|
||||
* Subclasses should call this method from their own onCreate() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).onCreate(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onDestroy() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).onDestroy();
|
||||
}
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onStart() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).open();
|
||||
}
|
||||
}
|
||||
createAllThreads();
|
||||
startAllThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onPause() if
|
||||
* overloaded. It takes care of disconnecting from the IOIO.
|
||||
* Subclasses should call this method from their own onStop() if overloaded.
|
||||
* It takes care of disconnecting from the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
protected void onStop() {
|
||||
abortAllThreads();
|
||||
try {
|
||||
joinAllThreads();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).close();
|
||||
}
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method by returning a concrete subclass
|
||||
* of {@link IOIOThread}. <code>null</code> may be returned if the client
|
||||
* is not interested to connect a thread for this IOIO. In multi-IOIO
|
||||
* scenarios, where you want to identify which IOIO the thread is for,
|
||||
* consider using {@link #createIOIOThread()} instead.
|
||||
* Subclasses must either implement this method or its other overload by
|
||||
* returning a concrete subclass of {@link IOIOThread}. <code>null</code>
|
||||
* may be returned if the client is not interested to create a thread for
|
||||
* this IOIO. In multi-IOIO scenarios, where you want to identify which IOIO
|
||||
* the thread is for, consider using {@link #createIOIOThread()} instead.
|
||||
*
|
||||
* @return An implementation of {@link IOIOThread}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
protected IOIOThread createIOIOThread() {
|
||||
return null;
|
||||
throw new RuntimeException(
|
||||
"Client must override on of the createIOIOThread overloads!");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,20 +198,21 @@ public abstract class AbstractIOIOActivity extends Activity {
|
||||
* wireless connection, any wired connection attempts may be rejected, thus
|
||||
* saving resources used for listening for incoming wired connections.
|
||||
*
|
||||
* @param connectionClass
|
||||
* The fully-qualified name of the connection class used to
|
||||
* connect to the IOIO.
|
||||
* @param connectionArgs
|
||||
* A list of arguments passed to the constructor of the
|
||||
* connection class. Should provide information that enables
|
||||
* distinguishing between different IOIO instances using the same
|
||||
* connection class.
|
||||
* @param connectionType
|
||||
* A unique name of the connection type. Typically, the
|
||||
* fully-qualified name of the connection class used to connect
|
||||
* to the IOIO.
|
||||
* @param extra
|
||||
* A connection-type-specific object with extra information on
|
||||
* the specific connection. Should provide information that
|
||||
* enables distinguishing between different IOIO instances using
|
||||
* the same connection class. For example, a Bluetooth connection
|
||||
* type, might have the remote IOIO's Bluetooth name as extra.
|
||||
*
|
||||
* @return An implementation of {@link IOIOThread}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
protected IOIOThread createIOIOThread(String connectionClass,
|
||||
Object[] connectionArgs) {
|
||||
protected IOIOThread createIOIOThread(String connectionType, Object extra) {
|
||||
return createIOIOThread();
|
||||
}
|
||||
|
||||
@@ -128,7 +225,7 @@ public abstract class AbstractIOIOActivity extends Activity {
|
||||
protected IOIO ioio_;
|
||||
private boolean abort_ = false;
|
||||
private boolean connected_ = true;
|
||||
private final IOIOConnectionSpec spec_ = currentSpec_;
|
||||
private final IOIOConnectionFactory connectionFactory_ = currentConnectionFactory_;
|
||||
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to
|
||||
@@ -156,9 +253,10 @@ public abstract class AbstractIOIOActivity extends Activity {
|
||||
* be done once as soon as IOIO communication is lost or closed.
|
||||
* Typically, this will include GUI changes corresponding to the change.
|
||||
* This method will only be called if setup() has been called. The
|
||||
* {@link #ioio_} member must not be used from within this method.
|
||||
* {@link #ioio_} member must not be used from within this method. This
|
||||
* method should not block for long, since it may cause an ANR.
|
||||
*/
|
||||
protected void disconnected() throws InterruptedException {
|
||||
protected void disconnected() {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,54 +273,53 @@ public abstract class AbstractIOIOActivity extends Activity {
|
||||
@Override
|
||||
public final void run() {
|
||||
super.run();
|
||||
Looper.prepare();
|
||||
while (true) {
|
||||
while (!abort_) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
if (abort_) {
|
||||
break;
|
||||
}
|
||||
ioio_ = IOIOFactory.create(spec_.className, spec_.args);
|
||||
ioio_ = IOIOFactory.create(connectionFactory_
|
||||
.createConnection());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to create IOIO, aborting IOIOThread!");
|
||||
return;
|
||||
}
|
||||
// if we got here, we have a ioio_!
|
||||
try {
|
||||
ioio_.waitForConnect();
|
||||
connected_ = true;
|
||||
setup();
|
||||
while (!abort_) {
|
||||
loop();
|
||||
}
|
||||
ioio_.disconnect();
|
||||
} catch (ConnectionLostException e) {
|
||||
if (abort_) {
|
||||
break;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
ioio_.disconnect();
|
||||
break;
|
||||
} catch (IncompatibilityException e) {
|
||||
Log.e(TAG, "Incompatible IOIO firmware", e);
|
||||
incompatible();
|
||||
// nothing to do - just wait until physical disconnection
|
||||
try {
|
||||
ioio_.waitForDisconnect();
|
||||
} catch (InterruptedException e1) {
|
||||
ioio_.disconnect();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unexpected exception caught", e);
|
||||
ioio_.disconnect();
|
||||
break;
|
||||
} finally {
|
||||
try {
|
||||
if (ioio_ != null) {
|
||||
ioio_.waitForDisconnect();
|
||||
if (connected_) {
|
||||
disconnected();
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
ioio_.waitForDisconnect();
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
synchronized (this) {
|
||||
ioio_ = null;
|
||||
}
|
||||
if (connected_) {
|
||||
disconnected();
|
||||
connected_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "IOIOThread is exiting");
|
||||
}
|
||||
|
||||
/** Not relevant to subclasses. */
|
||||
@@ -251,10 +348,12 @@ public abstract class AbstractIOIOActivity extends Activity {
|
||||
|
||||
private void createAllThreads() {
|
||||
threads_.clear();
|
||||
Collection<IOIOConnectionSpec> specs = getConnectionSpecs();
|
||||
for (IOIOConnectionSpec spec : specs) {
|
||||
currentSpec_ = spec;
|
||||
IOIOThread thread = createIOIOThread(spec.className, spec.args);
|
||||
Collection<IOIOConnectionFactory> factories = IOIOConnectionRegistry
|
||||
.getConnectionFactories();
|
||||
for (IOIOConnectionFactory factory : factories) {
|
||||
currentConnectionFactory_ = factory;
|
||||
IOIOThread thread = createIOIOThread(factory.getType(),
|
||||
factory.getExtra());
|
||||
if (thread != null) {
|
||||
threads_.add(thread);
|
||||
}
|
||||
@@ -267,29 +366,4 @@ public abstract class AbstractIOIOActivity extends Activity {
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<IOIOConnectionSpec> getConnectionSpecs() {
|
||||
Collection<IOIOConnectionSpec> result = new LinkedList<IOIOConnectionSpec>();
|
||||
addConnectionSpecs("ioio.lib.util.SocketIOIOConnectionDiscovery",
|
||||
result);
|
||||
addConnectionSpecs(
|
||||
"ioio.lib.bluetooth.BluetoothIOIOConnectionDiscovery", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addConnectionSpecs(String discoveryClassName,
|
||||
Collection<IOIOConnectionSpec> result) {
|
||||
try {
|
||||
Class<?> cls = Class.forName(discoveryClassName);
|
||||
IOIOConnectionDiscovery discovery = (IOIOConnectionDiscovery) cls
|
||||
.newInstance();
|
||||
discovery.getSpecs(result);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.d(TAG, "Discovery class not found: " + discoveryClassName
|
||||
+ ". Not adding.");
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG,
|
||||
"Exception caught while discovering connections - not adding connections of class "
|
||||
+ discoveryClassName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
IOIOLib/src/ioio/lib/util/BaseIOIOLooper.java
Normal file
48
IOIOLib/src/ioio/lib/util/BaseIOIOLooper.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package ioio.lib.util;
|
||||
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* A convenience implementation of {@link IOIOLooper}.
|
||||
*
|
||||
* This base class provides no-op implementations for all methods and provides
|
||||
* the {@link #ioio_} field for subclasses.
|
||||
*
|
||||
*/
|
||||
public class BaseIOIOLooper implements IOIOLooper {
|
||||
protected IOIO ioio_;
|
||||
|
||||
@Override
|
||||
public final void setup(IOIO ioio) throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
ioio_ = ioio;
|
||||
setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called as soon as connection to the IOIO has been
|
||||
* established. Typically, this will include opening pins and modules using
|
||||
* the openXXX() methods of the {@link #ioio_} field.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* The connection to the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* The thread has been interrupted.
|
||||
*/
|
||||
protected void setup() throws ConnectionLostException, InterruptedException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loop() throws ConnectionLostException, InterruptedException {
|
||||
Thread.sleep(20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incompatible() {
|
||||
}
|
||||
}
|
||||
166
IOIOLib/src/ioio/lib/util/IOIOApplicationHelper.java
Normal file
166
IOIOLib/src/ioio/lib/util/IOIOApplicationHelper.java
Normal file
@@ -0,0 +1,166 @@
|
||||
package ioio.lib.util;
|
||||
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.IOIOFactory;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.api.exception.IncompatibilityException;
|
||||
import ioio.lib.spi.IOIOConnectionBootstrap;
|
||||
import ioio.lib.spi.IOIOConnectionFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A helper class for creating different kinds of IOIO based applications.
|
||||
*
|
||||
* This class implements a common life-cycle for applications interacting with
|
||||
* IOIO devices.
|
||||
* <p>
|
||||
* When the application starts, call {@link #start()}, which will in turn
|
||||
* attempt to create a thread for each possible IOIO connection channel. Each
|
||||
* thread will have a respective {@link IOIOLooper}, which the client provides,
|
||||
* through which the client gets context for working with the IOIO.
|
||||
* <p>
|
||||
* When the application exits, call {@link #stop()}, which will disconnect all
|
||||
* open connections and will abort and join all the threads.
|
||||
*
|
||||
*/
|
||||
public class IOIOApplicationHelper {
|
||||
/**
|
||||
* An abstract class, which facilitates a thread dedicated for communication
|
||||
* with a single physical IOIO device.
|
||||
*/
|
||||
static private class IOIOThread extends Thread {
|
||||
protected IOIO ioio_;
|
||||
private boolean abort_ = false;
|
||||
private boolean connected_ = true;
|
||||
private final IOIOLooper looper_;
|
||||
private final IOIOConnectionFactory connectionFactory_;
|
||||
|
||||
IOIOThread(IOIOLooper looper, IOIOConnectionFactory factory) {
|
||||
looper_ = looper;
|
||||
connectionFactory_ = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
super.run();
|
||||
while (!abort_) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
if (abort_) {
|
||||
break;
|
||||
}
|
||||
ioio_ = IOIOFactory.create(connectionFactory_
|
||||
.createConnection());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to create IOIO, aborting IOIOThread!");
|
||||
return;
|
||||
}
|
||||
// if we got here, we have a ioio_!
|
||||
try {
|
||||
ioio_.waitForConnect();
|
||||
connected_ = true;
|
||||
looper_.setup(ioio_);
|
||||
while (!abort_ && ioio_.getState() == IOIO.State.CONNECTED) {
|
||||
looper_.loop();
|
||||
}
|
||||
} catch (ConnectionLostException e) {
|
||||
} catch (InterruptedException e) {
|
||||
ioio_.disconnect();
|
||||
} catch (IncompatibilityException e) {
|
||||
Log.e(TAG, "Incompatible IOIO firmware", e);
|
||||
looper_.incompatible();
|
||||
// nothing to do - just wait until physical
|
||||
// disconnection
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unexpected exception caught", e);
|
||||
ioio_.disconnect();
|
||||
break;
|
||||
} finally {
|
||||
try {
|
||||
ioio_.waitForDisconnect();
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
synchronized (this) {
|
||||
ioio_ = null;
|
||||
}
|
||||
if (connected_) {
|
||||
looper_.disconnected();
|
||||
connected_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "IOIOThread is exiting");
|
||||
}
|
||||
|
||||
/** Not relevant to subclasses. */
|
||||
public synchronized final void abort() {
|
||||
abort_ = true;
|
||||
if (ioio_ != null) {
|
||||
ioio_.disconnect();
|
||||
}
|
||||
if (connected_) {
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static final String TAG = "IOIOAndroidApplicationHelper";
|
||||
protected final IOIOLooperProvider looperProvider_;
|
||||
private Collection<IOIOThread> threads_ = new LinkedList<IOIOThread>();
|
||||
protected Collection<IOIOConnectionBootstrap> bootstraps_ = IOIOConnectionRegistry
|
||||
.getBootstraps();
|
||||
|
||||
public IOIOApplicationHelper(IOIOLooperProvider provider) {
|
||||
looperProvider_ = provider;
|
||||
}
|
||||
|
||||
protected void abortAllThreads() {
|
||||
for (IOIOThread thread : threads_) {
|
||||
thread.abort();
|
||||
}
|
||||
}
|
||||
|
||||
protected void joinAllThreads() throws InterruptedException {
|
||||
for (IOIOThread thread : threads_) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
protected void createAllThreads() {
|
||||
threads_.clear();
|
||||
Collection<IOIOConnectionFactory> factories = IOIOConnectionRegistry
|
||||
.getConnectionFactories();
|
||||
for (IOIOConnectionFactory factory : factories) {
|
||||
IOIOLooper looper = looperProvider_.createIOIOLooper(
|
||||
factory.getType(), factory.getExtra());
|
||||
if (looper != null) {
|
||||
threads_.add(new IOIOThread(looper, factory));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void startAllThreads() {
|
||||
for (IOIOThread thread : threads_) {
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
createAllThreads();
|
||||
startAllThreads();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
abortAllThreads();
|
||||
try {
|
||||
joinAllThreads();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package ioio.lib.util;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface IOIOConnectionDiscovery {
|
||||
public static class IOIOConnectionSpec {
|
||||
public final String className;
|
||||
public final Object[] args;
|
||||
|
||||
public IOIOConnectionSpec(String c, Object[] a) {
|
||||
className = c;
|
||||
args = a;
|
||||
}
|
||||
}
|
||||
|
||||
public void getSpecs(Collection<IOIOConnectionSpec> result);
|
||||
}
|
||||
133
IOIOLib/src/ioio/lib/util/IOIOConnectionRegistry.java
Normal file
133
IOIOLib/src/ioio/lib/util/IOIOConnectionRegistry.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2011 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.util;
|
||||
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
import ioio.lib.api.IOIOFactory;
|
||||
import ioio.lib.spi.IOIOConnectionBootstrap;
|
||||
import ioio.lib.spi.IOIOConnectionFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A utility class for managing available connection types to IOIO.
|
||||
* <p>
|
||||
* <b>For advanced usage only!</b>
|
||||
* <p>
|
||||
* This class facilitates dynamic linkage and instantiation of different IOIO
|
||||
* connection types. {@link IOIOConnectionBootstrap} classes enable creation of
|
||||
* {@link IOIOConnectionFactory} instances, from which concrete
|
||||
* {@link IOIOConnection}s are created. The binding to
|
||||
* {@link IOIOConnectionBootstrap} is dynamic, thus enabling linkage to succeed
|
||||
* with or without those bootstraps. Likewise, during runtime, the absence of
|
||||
* bootstraps is handled gracefully.
|
||||
*
|
||||
* A typical usage will call {@link #addBootstraps(String[])} with a list of
|
||||
* class names to be sought from a static initializer block. It may then call
|
||||
* {@link #getBootstraps()} to obtain any bootstrap classes that are available
|
||||
* in runtime, in case the bootstrap classes themselves need some runtime
|
||||
* handling. Last, the {@link #getConnectionFactories()} will return a
|
||||
* collection of {@link IOIOConnectionFactory}, each representing one possible
|
||||
* communication channel to a IOIO.
|
||||
*
|
||||
*/
|
||||
public class IOIOConnectionRegistry {
|
||||
/**
|
||||
* Get all available connection specifications. This is a list of all
|
||||
* currently available communication channels in which a IOIO may be
|
||||
* available. The client typically passes elements of this collection to
|
||||
* {@link IOIOFactory#create(IOIOConnection)}, possibly after filtering based on the
|
||||
* specification's properties.
|
||||
*
|
||||
* @return A collection of specifications.
|
||||
*/
|
||||
public static Collection<IOIOConnectionFactory> getConnectionFactories() {
|
||||
Collection<IOIOConnectionFactory> result = new LinkedList<IOIOConnectionFactory>();
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
bootstrap.getFactories(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* For advanced usage only! Used for special runtime handling of bootstrap
|
||||
* classes.
|
||||
*
|
||||
* @return The bootstraps.
|
||||
*/
|
||||
public static Collection<IOIOConnectionBootstrap> getBootstraps() {
|
||||
return bootstraps_;
|
||||
}
|
||||
|
||||
/**
|
||||
* For advanced usage only! Add platform-specific connection bootstrap
|
||||
* classes. Call before calling {@link #getConnectionFactories()}.
|
||||
*/
|
||||
public static void addBootstraps(String[] classNames) {
|
||||
for (String className : classNames) {
|
||||
addBootstrap(className);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "IOIOConnectionRegistry";
|
||||
|
||||
private static Collection<IOIOConnectionBootstrap> bootstraps_;
|
||||
|
||||
static {
|
||||
bootstraps_ = new LinkedList<IOIOConnectionBootstrap>();
|
||||
String[] classNames = new String[] { "ioio.lib.impl.SocketIOIOConnectionBootstrap" };
|
||||
addBootstraps(classNames);
|
||||
}
|
||||
|
||||
private static void addBootstrap(String className) {
|
||||
try {
|
||||
Class<? extends IOIOConnectionBootstrap> bootstrapClass = Class
|
||||
.forName(className).asSubclass(
|
||||
IOIOConnectionBootstrap.class);
|
||||
bootstraps_.add(bootstrapClass.newInstance());
|
||||
Log.d(TAG, "Successfully added bootstrap class: " + className);
|
||||
} catch (ClassNotFoundException e) {
|
||||
Log.d(TAG, "Bootstrap class not found: " + className
|
||||
+ ". Not adding.");
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG,
|
||||
"Runtime exception caught while attempting to initialize accessory connection factory",
|
||||
e);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG,
|
||||
"Exception caught while attempting to initialize accessory connection factory",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
56
IOIOLib/src/ioio/lib/util/IOIOLooper.java
Normal file
56
IOIOLib/src/ioio/lib/util/IOIOLooper.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package ioio.lib.util;
|
||||
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* A handler implementing interaction with a single IOIO over a single
|
||||
* connection period. The interface utilizes a basic workflow for working with a
|
||||
* IOIO instance: as soon as a connection is established, {@link #setup(IOIO)}
|
||||
* will be called. Then, the {@link #loop()} method will be called repeatedly as
|
||||
* long as the connection is alive. Last, the {@link #disconnected()} method
|
||||
* will be called upon losing the connection (as result of physical
|
||||
* disconnection, closing the application, etc). In case a IOIO with an
|
||||
* incompatible firmware is encountered, {@link #incompatible()} will be called
|
||||
* instead of {@link #setup(IOIO)}, and the IOIO instance is entirely useless,
|
||||
* until eventually {@link #disconnected()} gets called.
|
||||
*
|
||||
*/
|
||||
public interface IOIOLooper {
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to be
|
||||
* done once as soon as IOIO communication is established.
|
||||
*/
|
||||
public abstract void setup(IOIO ioio) throws ConnectionLostException,
|
||||
InterruptedException;
|
||||
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to be
|
||||
* done repetitively as long as IOIO communication persists. Typically, this
|
||||
* will be the main logic of the application, processing inputs and
|
||||
* producing outputs.
|
||||
*/
|
||||
public abstract void loop() throws ConnectionLostException,
|
||||
InterruptedException;
|
||||
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to be
|
||||
* done once as soon as IOIO communication is lost or closed. Typically,
|
||||
* this will include GUI changes corresponding to the change. This method
|
||||
* will only be called if setup() has been called. The ioio argument passed
|
||||
* to {@link #setup(IOIO)} must not be used from within this method - it is
|
||||
* invalid. This method should not block for long, since it may cause an
|
||||
* ANR.
|
||||
*/
|
||||
public abstract void disconnected();
|
||||
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to be
|
||||
* done if an incompatible IOIO firmware is detected. The ioio argument
|
||||
* passed to {@link #setup(IOIO)} must not be used from within this method -
|
||||
* it is invalid. This method will only be called once, until a compatible
|
||||
* IOIO is connected (i.e. {@link #setup(IOIO)} gets called).
|
||||
*/
|
||||
public abstract void incompatible();
|
||||
|
||||
}
|
||||
36
IOIOLib/src/ioio/lib/util/IOIOLooperProvider.java
Normal file
36
IOIOLib/src/ioio/lib/util/IOIOLooperProvider.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package ioio.lib.util;
|
||||
|
||||
/**
|
||||
* An entity that provides {@link IOIOLooper} instances on demand, per
|
||||
* connection specifications.
|
||||
*/
|
||||
public interface IOIOLooperProvider {
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method by returning an implementation of
|
||||
* {@link IOIOLooper}. The caller provide enough information to uniquely
|
||||
* identify the connection, through the parameters. <code>null</code> may be
|
||||
* returned if the client is not interested to create a thread for this
|
||||
* IOIO. This can be used in order to filter out unwanted connections, for
|
||||
* example if the application is only intended for wireless connection, any
|
||||
* wired connection attempts may be rejected, thus saving resources used for
|
||||
* listening for incoming wired connections.
|
||||
*
|
||||
* @param connectionType
|
||||
* A unique name of the connection type. Typically, the
|
||||
* fully-qualified name of the connection class used to connect
|
||||
* to the IOIO.
|
||||
* @param extra
|
||||
* A connection-type-specific object with extra information on
|
||||
* the specific connection. Should provide information that
|
||||
* enables distinguishing between different IOIO instances using
|
||||
* the same connection class. For example, a Bluetooth connection
|
||||
* type, might have the remote IOIO's Bluetooth name as extra.
|
||||
*
|
||||
* @return An implementation of {@link IOIOLooper}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
public abstract IOIOLooper createIOIOLooper(String connectionType,
|
||||
Object extra);
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package ioio.lib.util;
|
||||
|
||||
import ioio.lib.api.IOIOFactory;
|
||||
import ioio.lib.impl.SocketIOIOConnection;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SocketIOIOConnectionDiscovery implements IOIOConnectionDiscovery {
|
||||
|
||||
@Override
|
||||
public void getSpecs(Collection<IOIOConnectionSpec> result) {
|
||||
result.add(new IOIOConnectionSpec(SocketIOIOConnection.class.getName(),
|
||||
new Object[] { new Integer(IOIOFactory.IOIO_PORT) }));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2011 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.util.android;
|
||||
|
||||
import android.content.ContextWrapper;
|
||||
|
||||
|
||||
public interface ContextWrapperDependent {
|
||||
public void onCreate(ContextWrapper wrapper);
|
||||
public void onDestroy();
|
||||
public void open();
|
||||
public void reopen();
|
||||
public void close();
|
||||
}
|
||||
148
IOIOLib/src/ioio/lib/util/android/IOIOActivity.java
Normal file
148
IOIOLib/src/ioio/lib/util/android/IOIOActivity.java
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright 2011 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.util.android;
|
||||
|
||||
import ioio.lib.impl.SocketIOIOConnection;
|
||||
import ioio.lib.util.IOIOLooper;
|
||||
import ioio.lib.util.IOIOLooperProvider;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
/**
|
||||
* A convenience class for easy creation of IOIO-based activities.
|
||||
*
|
||||
* It is used by creating a concrete {@link Activity} in your application, which
|
||||
* extends this class. This class then takes care of proper creation and
|
||||
* abortion of the IOIO connection and of a dedicated thread for IOIO
|
||||
* communication.
|
||||
* <p>
|
||||
* In the basic usage the client should extend this class and implement
|
||||
* {@link #createIOIOLooper()}, which should return an implementation of the
|
||||
* {@link IOIOLooper} interface. In this implementation, the client implements
|
||||
* the {@link IOIOLooper#setup(ioio.lib.api.IOIO)} method, which gets called as
|
||||
* soon as communication with the IOIO is established, and the
|
||||
* {@link IOIOLooper#loop()} method, which gets called repetitively as long as
|
||||
* the IOIO is connected.
|
||||
* <p>
|
||||
* In addition, the {@link IOIOLooper#disconnected()} method may be overridden
|
||||
* in order to execute logic as soon as a disconnection occurs for whichever
|
||||
* reason. The {@link IOIOLooper#incompatible()} method may be overridden in
|
||||
* order to take action in case where a IOIO whose firmware is incompatible with
|
||||
* the IOIOLib version that application is built with.
|
||||
* <p>
|
||||
* In a more advanced use case, more than one IOIO is available. In this case, a
|
||||
* thread will be created for each IOIO, whose semantics are as defined above.
|
||||
* If the client needs to be able to distinguish between them, it is possible to
|
||||
* override {@link #createIOIOLooper(String, Object)} instead of
|
||||
* {@link #createIOIOLooper()}. The first argument provided will contain the
|
||||
* connection class name, such as ioio.lib.impl.SocketIOIOConnection for a
|
||||
* connection established over a TCP socket (which is used over ADB). The second
|
||||
* argument will contain information specific to the connection type. For
|
||||
* example, in the case of {@link SocketIOIOConnection}, the second argument
|
||||
* will contain an {@link Integer} representing the local port number.
|
||||
*/
|
||||
public abstract class IOIOActivity extends Activity implements
|
||||
IOIOLooperProvider {
|
||||
private final IOIOAndroidApplicationHelper helper_ = new IOIOAndroidApplicationHelper(
|
||||
this, this);
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onCreate() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
helper_.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onDestroy() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
helper_.destroy();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onStart() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
helper_.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onStop() if overloaded.
|
||||
* It takes care of disconnecting from the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onStop() {
|
||||
helper_.stop();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
|
||||
helper_.restart();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must either implement this method or its other overload by
|
||||
* returning an implementation of {@link IOIOLooper}. A dedicated thread
|
||||
* will be created for each available IOIO, from which the
|
||||
* {@link IOIOLooper}'s methods will be invoked. <code>null</code> may be
|
||||
* returned if the client is not interested to create a thread for this
|
||||
* IOIO. In multi-IOIO scenarios, where you want to identify which IOIO the
|
||||
* thread is for, consider overriding
|
||||
* {@link #createIOIOLooper(String, Object)} instead.
|
||||
*
|
||||
* @return An implementation of {@link IOIOLooper}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
protected IOIOLooper createIOIOLooper() {
|
||||
throw new RuntimeException(
|
||||
"Client must override one of the createIOIOLooper overloads!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IOIOLooper createIOIOLooper(String connectionType, Object extra) {
|
||||
return createIOIOLooper();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package ioio.lib.util.android;
|
||||
|
||||
import ioio.lib.spi.IOIOConnectionBootstrap;
|
||||
import ioio.lib.util.IOIOApplicationHelper;
|
||||
import ioio.lib.util.IOIOConnectionRegistry;
|
||||
import ioio.lib.util.IOIOLooperProvider;
|
||||
|
||||
import android.content.ContextWrapper;
|
||||
|
||||
public class IOIOAndroidApplicationHelper extends IOIOApplicationHelper {
|
||||
private final ContextWrapper contextWrapper_;
|
||||
|
||||
public IOIOAndroidApplicationHelper(ContextWrapper wrapper,
|
||||
IOIOLooperProvider provider) {
|
||||
super(provider);
|
||||
contextWrapper_ = wrapper;
|
||||
}
|
||||
|
||||
static {
|
||||
IOIOConnectionRegistry
|
||||
.addBootstraps(new String[] {
|
||||
"ioio.lib.android.accessory.AccessoryConnectionBootstrap",
|
||||
"ioio.lib.android.bluetooth.BluetoothIOIOConnectionBootstrap" });
|
||||
}
|
||||
|
||||
public void create() {
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).onCreate(contextWrapper_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).onDestroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).open();
|
||||
}
|
||||
}
|
||||
super.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
super.stop();
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void restart() {
|
||||
for (IOIOConnectionBootstrap bootstrap : bootstraps_) {
|
||||
if (bootstrap instanceof ContextWrapperDependent) {
|
||||
((ContextWrapperDependent) bootstrap).reopen();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
149
IOIOLib/src/ioio/lib/util/android/IOIOService.java
Normal file
149
IOIOLib/src/ioio/lib/util/android/IOIOService.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2011 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.util.android;
|
||||
|
||||
import ioio.lib.impl.SocketIOIOConnection;
|
||||
import ioio.lib.util.IOIOLooper;
|
||||
import ioio.lib.util.IOIOLooperProvider;
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* A convenience class for easy creation of IOIO-based services.
|
||||
*
|
||||
* It is used by creating a concrete {@link Service} in your application, which
|
||||
* extends this class. This class then takes care of proper creation and
|
||||
* abortion of the IOIO connection and of a dedicated thread for IOIO
|
||||
* communication.
|
||||
* <p>
|
||||
* In the basic usage the client should extend this class and implement
|
||||
* {@link #createIOIOLooper()}, which should return an implementation of the
|
||||
* {@link IOIOLooper} interface. In this implementation, the client implements
|
||||
* the {@link IOIOLooper#setup(ioio.lib.api.IOIO)} method, which gets called as
|
||||
* soon as communication with the IOIO is established, and the
|
||||
* {@link IOIOLooper#loop()} method, which gets called repetitively as long as
|
||||
* the IOIO is connected.
|
||||
* <p>
|
||||
* In addition, the {@link IOIOLooper#disconnected()} method may be overridden
|
||||
* in order to execute logic as soon as a disconnection occurs for whichever
|
||||
* reason. The {@link IOIOLooper#incompatible()} method may be overridden in
|
||||
* order to take action in case where a IOIO whose firmware is incompatible with
|
||||
* the IOIOLib version that application is built with.
|
||||
* <p>
|
||||
* In a more advanced use case, more than one IOIO is available. In this case, a
|
||||
* thread will be created for each IOIO, whose semantics are as defined above.
|
||||
* If the client needs to be able to distinguish between them, it is possible to
|
||||
* override {@link #createIOIOLooper(String, Object)} instead of
|
||||
* {@link #createIOIOLooper()}. The first argument provided will contain the
|
||||
* connection class name, such as ioio.lib.impl.SocketIOIOConnection for a
|
||||
* connection established over a TCP socket (which is used over ADB). The second
|
||||
* argument will contain information specific to the connection type. For
|
||||
* example, in the case of {@link SocketIOIOConnection}, the second argument
|
||||
* will contain an {@link Integer} representing the local port number.
|
||||
*/
|
||||
public abstract class IOIOService extends Service implements
|
||||
IOIOLooperProvider {
|
||||
private final IOIOAndroidApplicationHelper helper_ = new IOIOAndroidApplicationHelper(
|
||||
this, this);
|
||||
private boolean started_ = false;
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onCreate() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
helper_.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onDestroy() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stop();
|
||||
helper_.destroy();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onStart() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
super.onStart(intent, startId);
|
||||
if (!started_) {
|
||||
helper_.start();
|
||||
started_ = true;
|
||||
} else {
|
||||
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
|
||||
helper_.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method if they wish to disconnect from the
|
||||
* IOIO(s) until the next onStart().
|
||||
*/
|
||||
protected void stop() {
|
||||
if (started_) {
|
||||
helper_.stop();
|
||||
started_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must either implement this method or its other overload by
|
||||
* returning an implementation of {@link IOIOLooper}. A dedicated thread
|
||||
* will be created for each available IOIO, from which the
|
||||
* {@link IOIOLooper}'s methods will be invoked. <code>null</code> may be
|
||||
* returned if the client is not interested to create a thread for this
|
||||
* IOIO. In multi-IOIO scenarios, where you want to identify which IOIO the
|
||||
* thread is for, consider overriding
|
||||
* {@link #createIOIOLooper(String, Object)} instead.
|
||||
*
|
||||
* @return An implementation of {@link IOIOLooper}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
protected IOIOLooper createIOIOLooper() {
|
||||
throw new RuntimeException(
|
||||
"Client must override one of the createIOIOLooper overloads!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IOIOLooper createIOIOLooper(String connectionType, Object extra) {
|
||||
return createIOIOLooper();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user