Initial commit
This commit is contained in:
53
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOListener.java
Normal file
53
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOListener.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* IOIOListener.java
|
||||
* @date Jan 24, 2012
|
||||
* @author ricky barrette
|
||||
* @author Twenty Codes, LLC
|
||||
*
|
||||
* Copyright 2012 Richard Barrette
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.TwentyCodes.android.ioio;
|
||||
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* This is a simple interface used to pass information from the IOIO thread to the manager
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public interface IOIOListener {
|
||||
|
||||
/**
|
||||
* Called when a IOIO is connected.
|
||||
* here is a good time to init ports
|
||||
* @param ioio
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void onConnected(IOIO ioio) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Called when the IOIO thread loops.
|
||||
* Here you want to update the ports
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void loop() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Called when the IOIO is disconnected.
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void onDisconnected();
|
||||
|
||||
}
|
||||
132
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOManager.java
Normal file
132
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOManager.java
Normal file
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* IOIOManager.java
|
||||
* @date Jan 21, 2012
|
||||
* @author ricky barrette
|
||||
* @author Twenty Codes, LLC
|
||||
*
|
||||
* Copyright 2012 Richard Barrette
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.TwentyCodes.android.ioio;
|
||||
|
||||
import ioio.lib.bluetooth.BluetoothIOIOConnectionDiscovery;
|
||||
import ioio.lib.util.IOIOConnectionDiscovery;
|
||||
import ioio.lib.util.SocketIOIOConnectionDiscovery;
|
||||
import ioio.lib.util.IOIOConnectionDiscovery.IOIOConnectionSpec;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class manages the IOIO connectivity threads. It is based on the AbstractIOIOActivity
|
||||
* Remember that onConnected(), loop(), and onDisconnected() are called from the one of the IOIO threads
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public abstract class IOIOManager implements IOIOListener{
|
||||
|
||||
private static final String TAG = "IOIOManager";
|
||||
private Collection<IOIOThread> mThreads = new LinkedList<IOIOThread>();
|
||||
|
||||
/**
|
||||
* Aborts the IOIO connectivity threads and joins them
|
||||
* @throws InterruptedException
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void abort() throws InterruptedException {
|
||||
for (IOIOThread thread : mThreads)
|
||||
thread.abort();
|
||||
joinAllThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins all the threads
|
||||
* @throws InterruptedException
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void joinAllThreads() throws InterruptedException {
|
||||
for (IOIOThread thread : mThreads)
|
||||
thread.join();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates all the required IOIO connectivity threads
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void createAllThreads() {
|
||||
mThreads.clear();
|
||||
Collection<IOIOConnectionSpec> specs = getConnectionSpecs();
|
||||
for (IOIOConnectionSpec spec : specs)
|
||||
mThreads.add(new IOIOThread(spec.className, spec.args, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts IOIO connectivity threads
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void start() {
|
||||
createAllThreads();
|
||||
for (IOIOThread thread : mThreads)
|
||||
thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @author Ytai Ben-Tsvi
|
||||
*/
|
||||
private Collection<IOIOConnectionSpec> getConnectionSpecs() {
|
||||
Collection<IOIOConnectionSpec> result = new LinkedList<IOIOConnectionSpec>();
|
||||
addConnectionSpecs(SocketIOIOConnectionDiscovery.class.getName(),result);
|
||||
addConnectionSpecs(BluetoothIOIOConnectionDiscovery.class.getName(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param discoveryClassName
|
||||
* @param result
|
||||
* @author Ytai Ben-Tsvi
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param isStatLedEnabled the isStatLedEnabled to set
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void setStatLedEnabled(boolean isStatLedEnabled) {
|
||||
for(IOIOThread thread : mThreads)
|
||||
thread.setStatLedEnabled(isStatLedEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the update interval of the IOIO thread
|
||||
* @param ms
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public void setUpdateInverval(long ms){
|
||||
for(IOIOThread thread : mThreads)
|
||||
thread.setUpdateInverval(ms);
|
||||
}
|
||||
|
||||
}
|
||||
161
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOThread.java
Normal file
161
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOThread.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* IOIOThread.java
|
||||
* @date Jan 11, 2012
|
||||
* @author ricky barrette
|
||||
* @author Ytai Ben-Tsvi
|
||||
* @author Twenty Codes, LLC
|
||||
*
|
||||
* Copyright 2012 Richard Barrette
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.TwentyCodes.android.ioio;
|
||||
|
||||
import ioio.lib.api.DigitalOutput;
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.IOIOFactory;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* This is the thread that maintains the IOIO interaction.
|
||||
*
|
||||
* It first creates a IOIO instance and wait for a connection to be
|
||||
* established.
|
||||
*
|
||||
* Whenever a connection drops, it tries to reconnect, unless this is a
|
||||
* result of abort().
|
||||
*
|
||||
* @author Ytai Ben-Tsvi
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class IOIOThread extends Thread{
|
||||
|
||||
private IOIO mIOIO;
|
||||
private boolean isAborted = false;
|
||||
private long mUpdateInterval = 10;
|
||||
private boolean isStatLedEnabled = false;
|
||||
private IOIOListener mListener;
|
||||
private String mClassName;
|
||||
private Object[] mArgs;
|
||||
|
||||
public IOIOThread(IOIOListener listener){
|
||||
super();
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public IOIOThread(String className, Object[] args, IOIOListener listener) {
|
||||
super();
|
||||
mListener = listener;
|
||||
mClassName = className;
|
||||
mArgs = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abort the connection.
|
||||
*
|
||||
* This is a little tricky synchronization-wise: we need to be handle
|
||||
* the case of abortion happening before the IOIO instance is created or
|
||||
* during its creation.
|
||||
*/
|
||||
synchronized public void abort() {
|
||||
isAborted = true;
|
||||
if (mIOIO != null) {
|
||||
mIOIO.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the isStatLedEnabled
|
||||
*/
|
||||
public boolean isStatLedEnabled() {
|
||||
return isStatLedEnabled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Thread Body
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Thread#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
synchronized (this) {
|
||||
if (isAborted) {
|
||||
break;
|
||||
}
|
||||
if(mClassName == null || mArgs == null)
|
||||
mIOIO = IOIOFactory.create();
|
||||
else
|
||||
try {
|
||||
mIOIO = IOIOFactory.create(mClassName, mArgs);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
/*
|
||||
* Here we will try to connect to the IOIO board.
|
||||
*
|
||||
* the waitForConnect() is blocking until it can connect
|
||||
*/
|
||||
mIOIO.waitForConnect();
|
||||
|
||||
/*
|
||||
* Here we register and initialize each port
|
||||
*/
|
||||
DigitalOutput statLed = mIOIO.openDigitalOutput(IOIOValues.STAT_LED_PORT, true);
|
||||
mListener.onConnected(mIOIO);
|
||||
|
||||
/*
|
||||
* Here we will update the ports every 10 ms (default)
|
||||
*/
|
||||
while (true) {
|
||||
mListener.loop();
|
||||
statLed.write(!isStatLedEnabled);
|
||||
sleep(mUpdateInterval );
|
||||
}
|
||||
} catch (ConnectionLostException e) {
|
||||
mListener.onDisconnected();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
mIOIO.disconnect();
|
||||
mListener.onDisconnected();
|
||||
break;
|
||||
} finally {
|
||||
try {
|
||||
mIOIO.waitForDisconnect();
|
||||
mListener.onDisconnected();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stat led on / off
|
||||
* @param isStatLedEnabled the isStatLedEnabled to set
|
||||
*/
|
||||
public synchronized void setStatLedEnabled(boolean isStatLedEnabled) {
|
||||
this.isStatLedEnabled = isStatLedEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the update interval of the IOIO thread
|
||||
* @param ms
|
||||
*/
|
||||
public synchronized void setUpdateInverval(long ms){
|
||||
mUpdateInterval = ms;
|
||||
}
|
||||
|
||||
}
|
||||
32
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOValues.java
Normal file
32
IOIOLib/src/com/TwentyCodes/android/ioio/IOIOValues.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* IOIOValues.java
|
||||
* @date Jan 24, 2012
|
||||
* @author ricky barrette
|
||||
* @author Twenty Codes, LLC
|
||||
*
|
||||
* Copyright 2012 Richard Barrette
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.TwentyCodes.android.ioio;
|
||||
|
||||
/**
|
||||
* This class contains values for the IOIO
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class IOIOValues {
|
||||
|
||||
public static final int STAT_LED_PORT = 0 ;
|
||||
|
||||
public static final int RC_PWM_FRQ = 50;
|
||||
}
|
||||
104
IOIOLib/src/ioio/lib/api/AnalogInput.java
Normal file
104
IOIOLib/src/ioio/lib/api/AnalogInput.java
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* A pin used for analog input.
|
||||
* <p>
|
||||
* An analog input pin can be used to measure voltage. AnalogInput instances are
|
||||
* obtained by calling {@link IOIO#openAnalogInput(int)}.
|
||||
* <p>
|
||||
* Floating-point values scaled from 0 to 1 can be obtained by calling
|
||||
* {@link #read()}. Absolute voltage levels can be obtained by calling
|
||||
* {@link #getVoltage()}.
|
||||
* <p>
|
||||
* The instance is alive since its creation. The first {@link #read()} call
|
||||
* block for a few milliseconds until the initial value is updated. If the
|
||||
* connection with the IOIO drops at any point, the instance transitions to a
|
||||
* disconnected state, in which every attempt to use the pin (except
|
||||
* {@link #close()}) will throw a {@link ConnectionLostException}. Whenever
|
||||
* {@link #close()} is invoked the instance may no longer be used. Any resources
|
||||
* associated with it are freed and can be reused.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* AnalogInput potentiometer = ioio.openAnalogInput(40);
|
||||
* float value = potentiometer.read();
|
||||
* ...
|
||||
* potentiometer.close(); // pin 40 can now be used for something else.
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIO#openAnalogInput(int)
|
||||
*/
|
||||
public interface AnalogInput extends Closeable {
|
||||
/**
|
||||
* Gets the analog input reading, as an absolute voltage in Volt units.
|
||||
* <p>
|
||||
* It typically takes a few milliseconds between when the instance is
|
||||
* created and until the first value can be read. In this case, the method
|
||||
* may block shortly. If this is a problem, the calling thread can be
|
||||
* interrupted.
|
||||
* <p>
|
||||
* 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.
|
||||
* @see #read()
|
||||
*/
|
||||
public float getVoltage() throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Gets the maximum value against which {@link #read()} values are scaled.
|
||||
* @return The voltage, in Volts.
|
||||
*/
|
||||
public float getReference();
|
||||
|
||||
/**
|
||||
* Gets the analog input reading, as a scaled real value between 0 and 1.
|
||||
* <p>
|
||||
* It typically takes a few milliseconds between when the instance is
|
||||
* created and until the first value can be read. In this case, the method
|
||||
* may block shortly. If this is a problem, the calling thread can be
|
||||
* interrupted.
|
||||
* <p>
|
||||
* 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.
|
||||
* @see #getVoltage()
|
||||
*/
|
||||
public float read() throws InterruptedException, ConnectionLostException;
|
||||
}
|
||||
5
IOIOLib/src/ioio/lib/api/Closeable.java
Normal file
5
IOIOLib/src/ioio/lib/api/Closeable.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package ioio.lib.api;
|
||||
|
||||
public interface Closeable {
|
||||
void close();
|
||||
}
|
||||
140
IOIOLib/src/ioio/lib/api/DigitalInput.java
Normal file
140
IOIOLib/src/ioio/lib/api/DigitalInput.java
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
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)}.
|
||||
* <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
|
||||
* {@link #waitForValue(boolean)}.
|
||||
* <p>
|
||||
* The instance is alive since its creation. The first {@link #read()} call
|
||||
* block for a few milliseconds until the initial value is updated. If the
|
||||
* connection with the IOIO drops at any point, the instance transitions to a
|
||||
* disconnected state, in which every attempt to use the pin (except
|
||||
* {@link #close()}) will throw a {@link ConnectionLostException}. Whenever
|
||||
* {@link #close()} is invoked the instance may no longer be used. Any resources
|
||||
* associated with it are freed and can be reused.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* DigitalInput button = ioio.openDigitalInput(10); // used an external pull-up
|
||||
* button.waitForValue(false); // wait for press
|
||||
* ...
|
||||
* button.close(); // pin 10 can now be used for something else.
|
||||
* </pre>
|
||||
*/
|
||||
public interface DigitalInput extends Closeable {
|
||||
/**
|
||||
* A digital input pin specification, used when opening digital inputs.
|
||||
*/
|
||||
static public class Spec {
|
||||
/** Input pin mode. */
|
||||
public enum Mode {
|
||||
/**
|
||||
* Pin is floating. When the pin is left disconnected the value
|
||||
* sensed is undefined. Use this mode when an external pull-up or
|
||||
* pull-down resistor is used or when interfacing push-pull type
|
||||
* logic circuits.
|
||||
*/
|
||||
FLOATING,
|
||||
/**
|
||||
* Internal pull-up resistor is used. When the pin is left
|
||||
* disconnected, a logical "HIGH" (true) will be sensed. This is
|
||||
* useful for interfacing with open drain circuits or for
|
||||
* interacting with a switch connected between the pin and ground.
|
||||
*/
|
||||
PULL_UP,
|
||||
/**
|
||||
* Internal pull-down resistor is used. When the pin is left
|
||||
* disconnected, a logical "LOW" (false) will be sensed. This is
|
||||
* useful for interacting with a switch connected between the pin
|
||||
* and Vdd.
|
||||
*/
|
||||
PULL_DOWN
|
||||
}
|
||||
|
||||
/** The pin number, as labeled on the board. */
|
||||
public int pin;
|
||||
/** The pin mode. */
|
||||
public Mode mode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param pin
|
||||
* Pin number, as labeled on the board.
|
||||
* @param mode
|
||||
* Pin mode.
|
||||
*/
|
||||
public Spec(int pin, Mode mode) {
|
||||
this.pin = pin;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/** Shorthand for Spec(pin, Mode.FLOATING). */
|
||||
public Spec(int pin) {
|
||||
this(pin, Mode.FLOATING);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value sensed on the pin. May block for a few milliseconds if
|
||||
* called right after creation of the instance. If this is a problem, the
|
||||
* calling thread may be interrupted.
|
||||
*
|
||||
* @return True for logical "HIGH", false for logical "LOW".
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO has been lost.
|
||||
*/
|
||||
public boolean read() throws InterruptedException, ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Block until a desired logical level is sensed. The calling thread can be
|
||||
* interrupted for aborting this operation.
|
||||
*
|
||||
* @param value
|
||||
* The desired logical level. true for "HIGH", false for "LOW".
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO has been lost.
|
||||
*/
|
||||
public void waitForValue(boolean value) throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
}
|
||||
120
IOIOLib/src/ioio/lib/api/DigitalOutput.java
Normal file
120
IOIOLib/src/ioio/lib/api/DigitalOutput.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* A pin used for digital output.
|
||||
* <p>
|
||||
* A digital input pin can be used to generate logic-level signals.
|
||||
* DigitalOutput instances are obtained by calling
|
||||
* {@link IOIO#openDigitalOutput(Spec, boolean)}.
|
||||
* <p>
|
||||
* The value of the pin is set by calling {@link #write(boolean)}.
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, in
|
||||
* which every attempt to use the pin (except {@link #close()}) will throw a
|
||||
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
|
||||
* instance may no longer be used. Any resources associated with it are freed
|
||||
* and can be reused.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* DigitalOutput led = ioio.openDigitalInput(2); // LED anode on pin 2.
|
||||
* led.write(true); // turn LED on.
|
||||
* ...
|
||||
* led.close(); // pin 2 can now be used for something else.
|
||||
* </pre>
|
||||
*/
|
||||
public interface DigitalOutput extends Closeable {
|
||||
/**
|
||||
* A digital output pin specification, used when opening digital outputs.
|
||||
*/
|
||||
public static class Spec {
|
||||
/** Output pin mode. */
|
||||
public enum Mode {
|
||||
/**
|
||||
* Pin operates in push-pull mode, i.e. a logical "HIGH" is
|
||||
* represented by a voltage of Vdd on the pin and a logical "LOW" by
|
||||
* a voltage of 0 (ground).
|
||||
*/
|
||||
NORMAL,
|
||||
/**
|
||||
* Pin operates in open-drain mode, i.e. a logical "HIGH" is
|
||||
* represented by a high impedance on the pin (as if it is
|
||||
* disconnected) and a logical "LOW" by a voltage of 0 (ground).
|
||||
* This mode is most commonly used for generating 5V logical signal
|
||||
* on a 3.3V pin: 5V tolerant pins must be used; a pull-up resistor
|
||||
* is connected between the pin and 5V, and the pin is used in open-
|
||||
* drain mode.
|
||||
*/
|
||||
OPEN_DRAIN,
|
||||
}
|
||||
|
||||
/** The pin number, as labeled on the board. */
|
||||
public int pin;
|
||||
/** The pin mode. */
|
||||
public Mode mode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param pin
|
||||
* Pin number, as labeled on the board.
|
||||
* @param mode
|
||||
* Pin mode.
|
||||
*/
|
||||
public Spec(int pin, Mode mode) {
|
||||
this.pin = pin;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand for Spec(pin, Mode.NORMAL).
|
||||
*
|
||||
* @see #Spec(int, Mode)
|
||||
*/
|
||||
public Spec(int pin) {
|
||||
this(pin, Mode.NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output of the pin.
|
||||
*
|
||||
* @param val
|
||||
* The output. true is logical "HIGH", false is logical "LOW".
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO has been lost.
|
||||
*/
|
||||
public void write(boolean val) throws ConnectionLostException;
|
||||
}
|
||||
638
IOIOLib/src/ioio/lib/api/IOIO.java
Normal file
638
IOIOLib/src/ioio/lib/api/IOIO.java
Normal file
@@ -0,0 +1,638 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.PulseInput.PulseMode;
|
||||
import ioio.lib.api.TwiMaster.Rate;
|
||||
import ioio.lib.api.Uart.Parity;
|
||||
import ioio.lib.api.Uart.StopBits;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.api.exception.IncompatibilityException;
|
||||
import ioio.lib.api.exception.OutOfResourceException;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
/**
|
||||
* This interface provides control over all the IOIO board functions.
|
||||
* <p>
|
||||
* An instance of this interface is typically obtained by using the
|
||||
* {@link IOIOFactory} class. Initially, a connection should be established, by
|
||||
* calling {@link #waitForConnect()}. This method will block until the board is
|
||||
* connected an a connection has been established.
|
||||
* <p>
|
||||
* During the connection process, this library verifies that the IOIO firmware
|
||||
* is compatible with the required version. If not, {@link #waitForConnect()}
|
||||
* will throw a {@link IncompatibilityException}, putting the {@link IOIO}
|
||||
* instance in a "zombie" state: nothing could be done with it except calling
|
||||
* {@link #disconnect()}, or waiting for the physical connection to drop via
|
||||
* {@link #waitForDisconnect()}.
|
||||
* <p>
|
||||
* As soon as a connection is established, the IOIO can be used, typically, by
|
||||
* calling the openXXX() functions to obtain additional interfaces for
|
||||
* controlling specific function of the board.
|
||||
* <p>
|
||||
* Whenever a connection is lost as a result of physically disconnecting the
|
||||
* board or as a result of calling {@link #disconnect()}, this instance and all
|
||||
* the interfaces obtained from it become invalid, and will throw a
|
||||
* {@link ConnectionLostException} on every operation. Once the connection is
|
||||
* lost, those instances cannot be recycled, but rather it is required to create
|
||||
* new ones and wait for a connection again.
|
||||
* <p>
|
||||
* Initially all pins are tri-stated (floating), and all functions are disabled.
|
||||
* Whenever a connection is lost or dropped, the board will immediately return
|
||||
* to the this initial state.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* IOIO ioio = IOIOFactory.create();
|
||||
* try {
|
||||
* ioio.waitForConnect();
|
||||
* DigitalOutput out = ioio.openDigitalOutput(10);
|
||||
* out.write(true);
|
||||
* ...
|
||||
* } catch (ConnectionLostException e) {
|
||||
* } catch (Exception e) {
|
||||
* ioio.disconnect();
|
||||
* } finally {
|
||||
* ioio.waitForDisconnect();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIOFactory#create()
|
||||
*/
|
||||
public interface IOIO {
|
||||
/** An invalid pin number. */
|
||||
public static final int INVALID_PIN = -1;
|
||||
/** The pin number used to designate the on-board 'stat' LED. */
|
||||
public static final int LED_PIN = 0;
|
||||
|
||||
/**
|
||||
* A versioned component in the system.
|
||||
*
|
||||
* @see IOIO#getImplVersion(VersionType)
|
||||
*/
|
||||
public enum VersionType {
|
||||
/** Hardware version. */
|
||||
HARDWARE_VER,
|
||||
/** Bootloader version. */
|
||||
BOOTLOADER_VER,
|
||||
/** Application layer firmware version. */
|
||||
APP_FIRMWARE_VER,
|
||||
/** IOIOLib version. */
|
||||
IOIOLIB_VER
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes connection with the IOIO board.
|
||||
* <p>
|
||||
* This method is blocking until connection is established. This method can
|
||||
* be aborted by calling {@link #disconnect()}. In this case, it will throw
|
||||
* a {@link ConnectionLostException}.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* An error occurred during connection or disconnect() has been
|
||||
* called during connection. The instance state is disconnected.
|
||||
* @throws IncompatibilityException
|
||||
* An incompatible board firmware of hardware has been detected.
|
||||
* The instance state is disconnected.
|
||||
* @see #disconnect()
|
||||
* @see #waitForDisconnect()
|
||||
*/
|
||||
public void waitForConnect() throws ConnectionLostException,
|
||||
IncompatibilityException;
|
||||
|
||||
/**
|
||||
* Closes the connection to the board, or aborts a connection process
|
||||
* started with waitForConnect().
|
||||
* <p>
|
||||
* Once this method is called, this IOIO instance and all the instances
|
||||
* obtain from it become invalid and will throw an exception on every
|
||||
* operation.
|
||||
* <p>
|
||||
* This method is asynchronous, i.e. it returns immediately, but it is not
|
||||
* guaranteed that all connection-related resources has already been freed
|
||||
* and can be reused upon return. In cases when this is important, client
|
||||
* can call {@link #waitForDisconnect()}, which will block until all
|
||||
* resources have been freed.
|
||||
*/
|
||||
public void disconnect();
|
||||
|
||||
/**
|
||||
* Blocks until IOIO has been disconnected and all connection-related
|
||||
* resources have been freed, so that a new connection can be attempted.
|
||||
*
|
||||
* @throws InterruptedException
|
||||
* When interrupt() has been called on this thread. This might
|
||||
* mean that an immediate attempt to create and connect a new
|
||||
* IOIO object might fail for resource contention.
|
||||
* @see #disconnect()
|
||||
* @see #waitForConnect()
|
||||
*/
|
||||
public void waitForDisconnect() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Resets the entire state (returning to initial state), without dropping
|
||||
* the connection.
|
||||
* <p>
|
||||
* It is equivalent to calling {@link Closeable#close()} on every interface
|
||||
* obtained from this instance. A connection must have been established
|
||||
* prior to calling this method, by invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @see #hardReset()
|
||||
*/
|
||||
public void softReset() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Equivalent to disconnecting and reconnecting the board power supply.
|
||||
* <p>
|
||||
* The connection will be dropped and not reestablished. Full boot sequence
|
||||
* will take place, so firmware upgrades can be performed. A connection must
|
||||
* have been established prior to calling this method, by invoking
|
||||
* {@link #waitForConnect()}.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @see #softReset()
|
||||
*/
|
||||
public void hardReset() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Query the implementation version of the system's components. The
|
||||
* implementation version uniquely identifies a hardware revision or a
|
||||
* software build. Returned version IDs are always 8-character long,
|
||||
* according to the IOIO versioning system: first 4 characters are the
|
||||
* version authority and last 4 characters are the revision.
|
||||
*
|
||||
* @param v
|
||||
* The component whose version we query.
|
||||
* @return An 8-character implementation version ID.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
*/
|
||||
public String getImplVersion(VersionType v) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a pin for digital input.
|
||||
* <p>
|
||||
* A digital input pin can be used to read logic-level signals. The pin will
|
||||
* operate in this mode until close() is invoked on the returned interface.
|
||||
* It is illegal to open a pin that has already been opened and has not been
|
||||
* closed. A connection must have been established prior to calling this
|
||||
* method, by invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param spec
|
||||
* Pin specification, consisting of the pin number, as labeled on
|
||||
* the board, and the mode, which determines whether the pin will
|
||||
* be floating, pull-up or pull-down. See
|
||||
* {@link DigitalInput.Spec.Mode} for more information.
|
||||
* @return Interface of the assigned pin.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @see DigitalInput
|
||||
*/
|
||||
public DigitalInput openDigitalInput(DigitalInput.Spec spec)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openDigitalInput(new DigitalInput.Spec(pin)).
|
||||
*
|
||||
* @see #openDigitalInput(ioio.lib.api.DigitalInput.Spec)
|
||||
*/
|
||||
public DigitalInput openDigitalInput(int pin)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openDigitalInput(new DigitalInput.Spec(pin, mode)).
|
||||
*
|
||||
* @see #openDigitalInput(ioio.lib.api.DigitalInput.Spec)
|
||||
*/
|
||||
public DigitalInput openDigitalInput(int pin, DigitalInput.Spec.Mode mode)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a pin for digital output.
|
||||
* <p>
|
||||
* A digital output pin can be used to generate logic-level signals. The pin
|
||||
* will operate in this mode until close() is invoked on the returned
|
||||
* interface. It is illegal to open a pin that has already been opened and
|
||||
* has not been closed. A connection must have been established prior to
|
||||
* calling this method, by invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param spec
|
||||
* Pin specification, consisting of the pin number, as labeled on
|
||||
* the board, and the mode, which determines whether the pin will
|
||||
* be normal or open-drain. See {@link DigitalOutput.Spec.Mode}
|
||||
* for more information.
|
||||
* @param startValue
|
||||
* The initial logic level this pin will generate as soon at it
|
||||
* is open.
|
||||
* @return Interface of the assigned pin.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @see DigitalOutput
|
||||
*/
|
||||
public DigitalOutput openDigitalOutput(DigitalOutput.Spec spec,
|
||||
boolean startValue) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin, mode),
|
||||
* startValue).
|
||||
*
|
||||
* @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean)
|
||||
*/
|
||||
public DigitalOutput openDigitalOutput(int pin,
|
||||
DigitalOutput.Spec.Mode mode, boolean startValue)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin), startValue).
|
||||
* Pin mode will be "normal" (as opposed to "open-drain".
|
||||
*
|
||||
* @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean)
|
||||
*/
|
||||
public DigitalOutput openDigitalOutput(int pin, boolean startValue)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openDigitalOutput(new DigitalOutput.Spec(pin), false). Pin
|
||||
* mode will be "normal" (as opposed to "open-drain".
|
||||
*
|
||||
* @see #openDigitalOutput(ioio.lib.api.DigitalOutput.Spec, boolean)
|
||||
*/
|
||||
public DigitalOutput openDigitalOutput(int pin)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a pin for analog input.
|
||||
* <p>
|
||||
* An analog input pin can be used to measure voltage. Note that not every
|
||||
* pin can be used as an analog input. See board documentation for the legal
|
||||
* pins and permitted voltage range.
|
||||
* <p>
|
||||
* The pin will operate in this mode until close() is invoked on the
|
||||
* returned interface. It is illegal to open a pin that has already been
|
||||
* opened and has not been closed. A connection must have been established
|
||||
* prior to calling this method, by invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param pin
|
||||
* Pin number, as labeled on the board.
|
||||
* @return Interface of the assigned pin.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @see AnalogInput
|
||||
*/
|
||||
public AnalogInput openAnalogInput(int pin) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a pin for PWM (Pulse-Width Modulation) output.
|
||||
* <p>
|
||||
* A PWM pin produces a logic-level PWM signal. These signals are typically
|
||||
* used for simulating analog outputs for controlling the intensity of LEDs,
|
||||
* the rotation speed of motors, etc. They are also frequently used for
|
||||
* controlling hobby servo motors.
|
||||
* <p>
|
||||
* Note that not every pin can be used as PWM output. In addition, the total
|
||||
* number of concurrent PWM modules in use is limited. See board
|
||||
* documentation for the legal pins and limit on concurrent usage.
|
||||
* <p>
|
||||
* The pin will operate in this mode until close() is invoked on the
|
||||
* returned interface. It is illegal to open a pin that has already been
|
||||
* opened and has not been closed. A connection must have been established
|
||||
* prior to calling this method, by invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param spec
|
||||
* Pin specification, consisting of the pin number, as labeled on
|
||||
* the board, and the mode, which determines whether the pin will
|
||||
* be normal or open-drain. See {@link DigitalOutput.Spec.Mode}
|
||||
* for more information.
|
||||
* @param freqHz
|
||||
* PWM frequency, in Hertz.
|
||||
* @return Interface of the assigned pin.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @throws OutOfResourceException
|
||||
* This is a runtime exception, so it is not necessary to catch
|
||||
* it if the client guarantees that the total number of
|
||||
* concurrent PWM resources is not exceeded.
|
||||
* @see PwmOutput
|
||||
*/
|
||||
public PwmOutput openPwmOutput(DigitalOutput.Spec spec, int freqHz)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openPwmOutput(new DigitalOutput.Spec(pin), freqHz).
|
||||
*
|
||||
* @see #openPwmOutput(ioio.lib.api.DigitalOutput.Spec, int)
|
||||
*/
|
||||
public PwmOutput openPwmOutput(int pin, int freqHz)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a pin for pulse input.
|
||||
* <p>
|
||||
* The pulse input module is quite flexible. It enables several kinds of
|
||||
* timing measurements on a digital signal: pulse width measurement
|
||||
* (positive or negative pulse), and frequency of a periodic signal.
|
||||
* <p>
|
||||
* Note that not every pin can be used as pulse input. In addition, the
|
||||
* total number of concurrent pulse input modules in use is limited. See
|
||||
* board documentation for the legal pins and limit on concurrent usage.
|
||||
* <p>
|
||||
* The pin will operate in this mode until close() is invoked on the
|
||||
* returned interface. It is illegal to open a pin that has already been
|
||||
* opened and has not been closed. A connection must have been established
|
||||
* prior to calling this method, by invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param spec
|
||||
* Pin specification, consisting of the pin number, as labeled on
|
||||
* the board, and the mode, which determines whether the pin will
|
||||
* be floating, pull-up or pull-down. See
|
||||
* {@link DigitalInput.Spec.Mode} for more information.
|
||||
* @param rate
|
||||
* The clock rate to use for timing the signal. A faster clock
|
||||
* rate will result in better precision but will only be able to
|
||||
* measure narrow pulses / high frequencies.
|
||||
* @param mode
|
||||
* The mode in which to operate. Determines whether the module
|
||||
* will measure pulse durations or frequency.
|
||||
* @param doublePrecision
|
||||
* Whether to open a double-precision pulse input module. Double-
|
||||
* precision modules enable reading of much longer pulses and
|
||||
* lower frequencies with high accuracy than single precision
|
||||
* modules. However, their number is limited, so when possible,
|
||||
* and if the resources are all needed, use single-precision. For
|
||||
* more details on the exact spec of single- vs. double-
|
||||
* precision, see {@link PulseInput}.
|
||||
* @return An instance of the {@link PulseInput}, which can be used to
|
||||
* obtain the data.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @throws OutOfResourceException
|
||||
* This is a runtime exception, so it is not necessary to catch
|
||||
* it if the client guarantees that the total number of
|
||||
* concurrent PWM resources is not exceeded.
|
||||
* @see PulseInput
|
||||
*/
|
||||
public PulseInput openPulseInput(DigitalInput.Spec spec,
|
||||
PulseInput.ClockRate rate, PulseInput.PulseMode mode,
|
||||
boolean doublePrecision) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for openPulseInput(new DigitalInput.Spec(pin), rate, mode,
|
||||
* true), i.e. opens a double-precision, 16MHz pulse input on the given pin
|
||||
* with the given mode.
|
||||
*
|
||||
* @see #openPulseInput(ioio.lib.api.DigitalInput.Spec,
|
||||
* ioio.lib.api.PulseInput.ClockRate, PulseMode, boolean)
|
||||
*/
|
||||
public PulseInput openPulseInput(int pin, PulseMode mode)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a UART module, enabling a bulk transfer of byte buffers.
|
||||
* <p>
|
||||
* UART is a very common hardware communication protocol, enabling full-
|
||||
* duplex, 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.
|
||||
* <p>
|
||||
* Note that not every pin can be used for UART RX or TX. In addition, the
|
||||
* total number of concurrent UART modules in use is limited. See board
|
||||
* documentation for the legal pins and limit on concurrent usage.
|
||||
* <p>
|
||||
* The UART module will operate, and the pins will work in their respective
|
||||
* modes until close() is invoked on the returned interface. It is illegal
|
||||
* to use pins that have already been opened and has not been closed. A
|
||||
* connection must have been established prior to calling this method, by
|
||||
* invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param rx
|
||||
* Pin specification for the RX pin, consisting of the pin
|
||||
* number, as labeled on the board, and the mode, which
|
||||
* determines whether the pin will be floating, pull-up or
|
||||
* pull-down. See {@link DigitalInput.Spec.Mode} for more
|
||||
* information. null can be passed to designate that we do not
|
||||
* want RX input to this module.
|
||||
* @param tx
|
||||
* Pin specification for the TX pin, consisting of the pin
|
||||
* number, as labeled on the board, and the mode, which
|
||||
* determines whether the pin will be normal or open-drain. See
|
||||
* {@link DigitalOutput.Spec.Mode} for more information. null can
|
||||
* be passed to designate that we do not want TX output to this
|
||||
* module.
|
||||
* @param baud
|
||||
* The clock frequency of the UART module in Hz.
|
||||
* @param parity
|
||||
* The parity mode, as in {@link Parity}.
|
||||
* @param stopbits
|
||||
* Number of stop bits, as in {@link StopBits}.
|
||||
* @return Interface of the assigned module.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @throws OutOfResourceException
|
||||
* This is a runtime exception, so it is not necessary to catch
|
||||
* it if the client guarantees that the total number of
|
||||
* concurrent UART resources is not exceeded.
|
||||
* @see Uart
|
||||
*/
|
||||
public Uart openUart(DigitalInput.Spec rx, DigitalOutput.Spec tx, int baud,
|
||||
Parity parity, StopBits stopbits) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Shorthand for
|
||||
* {@link #openUart(ioio.lib.api.DigitalInput.Spec, ioio.lib.api.DigitalOutput.Spec, int, Parity, 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)
|
||||
*/
|
||||
public Uart openUart(int rx, int tx, int baud, Parity parity,
|
||||
StopBits stopbits) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a SPI master module, enabling communication with multiple
|
||||
* SPI-enabled slave modules.
|
||||
* <p>
|
||||
* SPI is a common hardware communication protocol, enabling full-duplex,
|
||||
* synchronous point-to-multi-point data transfer. It requires MOSI, MISO
|
||||
* and CLK lines shared by all nodes, as well as a SS line per slave,
|
||||
* connected 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.
|
||||
* <p>
|
||||
* Note that not every pin can be used for SPI MISO, MOSI or CLK. In
|
||||
* addition, the total number of concurrent SPI modules in use is limited.
|
||||
* See board documentation for the legal pins and limit on concurrent usage.
|
||||
* <p>
|
||||
* The SPI module will operate, and the pins will work in their respective
|
||||
* modes until close() is invoked on the returned interface. It is illegal
|
||||
* to use pins that have already been opened and has not been closed. A
|
||||
* connection must have been established prior to calling this method, by
|
||||
* invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param miso
|
||||
* Pin specification for the MISO (Master In Slave Out) pin,
|
||||
* consisting of the pin number, as labeled on the board, and the
|
||||
* mode, which determines whether the pin will be floating,
|
||||
* pull-up or pull-down. See {@link DigitalInput.Spec.Mode} for
|
||||
* more information.
|
||||
* @param mosi
|
||||
* Pin specification for the MOSI (Master Out Slave In) pin,
|
||||
* consisting of the pin number, as labeled on the board, and the
|
||||
* mode, which determines whether the pin will be normal or
|
||||
* open-drain. See {@link DigitalOutput.Spec.Mode} for more
|
||||
* information.
|
||||
* @param clk
|
||||
* Pin specification for the CLK pin, consisting of the pin
|
||||
* number, as labeled on the board, and the mode, which
|
||||
* determines whether the pin will be normal or open-drain. See
|
||||
* {@link DigitalOutput.Spec.Mode} for more information.
|
||||
* @param slaveSelect
|
||||
* An array of pin specifications for each of the slaves' SS
|
||||
* (Slave Select) pin. The index of this array designates the
|
||||
* slave index, used later to refer to this slave. The spec is
|
||||
* consisting of the pin number, as labeled on the board, and the
|
||||
* mode, which determines whether the pin will be normal or
|
||||
* open-drain. See {@link DigitalOutput.Spec.Mode} for more
|
||||
* information.
|
||||
* @param config
|
||||
* The configuration of the SPI module. See
|
||||
* {@link SpiMaster.Config} for details.
|
||||
* @return Interface of the assigned module.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @throws OutOfResourceException
|
||||
* This is a runtime exception, so it is not necessary to catch
|
||||
* it if the client guarantees that the total number of
|
||||
* concurrent SPI resources is not exceeded.
|
||||
* @see SpiMaster
|
||||
*/
|
||||
public SpiMaster openSpiMaster(DigitalInput.Spec miso,
|
||||
DigitalOutput.Spec mosi, DigitalOutput.Spec clk,
|
||||
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.
|
||||
* @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)
|
||||
*/
|
||||
public SpiMaster openSpiMaster(int miso, int mosi, int clk,
|
||||
int[] slaveSelect, SpiMaster.Rate rate)
|
||||
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.
|
||||
* @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)
|
||||
*/
|
||||
public SpiMaster openSpiMaster(int miso, int mosi, int clk,
|
||||
int slaveSelect, SpiMaster.Rate rate)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open a TWI (Two-Wire Interface, such as I2C/SMBus) master module,
|
||||
* enabling communication with multiple TWI-enabled slave modules.
|
||||
* <p>
|
||||
* TWI is a common hardware communication protocol, enabling half-duplex,
|
||||
* synchronous point-to-multi-point data transfer. It 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.
|
||||
* <p>
|
||||
* Note that there is a fixed number of TWI modules, and the pins they use
|
||||
* are static. Client has to make sure these pins are not already opened
|
||||
* before calling this method. See board documentation for the number of
|
||||
* modules and the respective pins they use.
|
||||
* <p>
|
||||
* The TWI module will operate, and the pins will work in their respective
|
||||
* modes until close() is invoked on the returned interface. It is illegal
|
||||
* to use pins that have already been opened and has not been closed. A
|
||||
* connection must have been established prior to calling this method, by
|
||||
* invoking {@link #waitForConnect()}.
|
||||
*
|
||||
* @param twiNum
|
||||
* The TWI module index to use. Will also determine the pins
|
||||
* used.
|
||||
* @param rate
|
||||
* The clock rate. Can be 100KHz / 400KHz / 1MHz.
|
||||
* @param smbus
|
||||
* When true, will use SMBus voltage levels. When false, I2C
|
||||
* voltage levels.
|
||||
* @return Interface of the assigned module.
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
* @see TwiMaster
|
||||
*/
|
||||
public TwiMaster openTwiMaster(int twiNum, Rate rate, boolean smbus)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Open an ICSP channel, enabling Flash programming of an external PIC MCU,
|
||||
* and in particular, another IOIO board.
|
||||
* <p>
|
||||
* ICSP (In-Circuit Serial Programming) is a protocol intended for
|
||||
* programming of PIC MCUs. It is a serial protocol over three wires: PGC
|
||||
* (clock), PGD (data) and MCLR (reset), where PGC and MCLR are controlled
|
||||
* by the master and PGD is shared by the master and slave, depending on the
|
||||
* transaction state.
|
||||
* <p>
|
||||
* Note that there is only one ICSP modules, and the pins it uses are
|
||||
* static. Client has to make sure that the ICSP module is not already in
|
||||
* use, as well as those dedicated pins. See board documentation for the
|
||||
* actual pins used for ICSP.
|
||||
*
|
||||
* @return Interface of the ICSP module.
|
||||
* @see IcspMaster
|
||||
* @throws ConnectionLostException
|
||||
* Connection was lost before or during the execution of this
|
||||
* method.
|
||||
*/
|
||||
public IcspMaster openIcspMaster() throws ConnectionLostException;
|
||||
}
|
||||
44
IOIOLib/src/ioio/lib/api/IOIOConnection.java
Executable file
44
IOIOLib/src/ioio/lib/api/IOIOConnection.java
Executable file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
public interface IOIOConnection {
|
||||
void waitForConnect() throws ConnectionLostException;
|
||||
|
||||
void disconnect();
|
||||
|
||||
InputStream getInputStream() throws ConnectionLostException;
|
||||
|
||||
OutputStream getOutputStream() throws ConnectionLostException;
|
||||
}
|
||||
121
IOIOLib/src/ioio/lib/api/IOIOFactory.java
Normal file
121
IOIOLib/src/ioio/lib/api/IOIOFactory.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import ioio.lib.impl.IOIOImpl;
|
||||
import ioio.lib.impl.SocketIOIOConnection;
|
||||
|
||||
/**
|
||||
* Factory class for creating instances of the IOIO interface.
|
||||
* <p>
|
||||
* This class acts as the single entry-point to the IOIO API. It creates the
|
||||
* bootstrapping between a specific implementation of the IOIO interface and any
|
||||
* dependencies it might have, such as the underlying connection logic.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* IOIO ioio = IOIOFactory.create();
|
||||
* try {
|
||||
* ioio.waitForConnect();
|
||||
* ...
|
||||
* ioio.disconnect();
|
||||
* } catch (ConnectionLostException e) {
|
||||
* } finally {
|
||||
* ioio.waitForDisconnect();
|
||||
* }
|
||||
* </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
|
||||
* connection (typically over a wired USB connection).
|
||||
*
|
||||
* @return The IOIO instance.
|
||||
*/
|
||||
public static IOIO create() {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a IOIO instance with a user-provided underlying connection class.
|
||||
* 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.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
145
IOIOLib/src/ioio/lib/api/IcspMaster.java
Executable file
145
IOIOLib/src/ioio/lib/api/IcspMaster.java
Executable file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* An interface for controlling an ICSP channel, enabling Flash programming of
|
||||
* an external PIC MCU, and in particular, another IOIO board.
|
||||
* <p>
|
||||
* ICSP (In-Circuit Serial Programming) is a protocol intended for programming
|
||||
* of PIC MCUs. It is a serial protocol over three wires: PGC (clock), PGD
|
||||
* (data) and MCLR (reset), where PGC and MCLR are controlled by the master and
|
||||
* PGD is shared by the master and slave, depending on the transaction state.
|
||||
* IcspMaster instances are obtained by calling {@link IOIO#openIcspMaster()}.
|
||||
* <p>
|
||||
* This interface is very low level: it allows direct access to the atomic
|
||||
* operations of the ICSP protocol:
|
||||
* <ul>
|
||||
* <li>Enter / exit programming mode ( {@link #enterProgramming()} /
|
||||
* {@link #exitProgramming()}, respectively).</li>
|
||||
* <li>Executing a single instruction on the slave MCU (
|
||||
* {@link #executeInstruction(int)}).</li>
|
||||
* <li>Reading the value of the VISI register of the slave MCU into a read queue
|
||||
* ({@link #readVisi()}).</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* The ICSP module uses fixed pins for its lines. See the user guide for details
|
||||
* for your specific board. ICSP is a special feature, introduced for the
|
||||
* purpose of programming a IOIO board with another IOIO board. It does not
|
||||
* necessarily play nicely when used concurrently with other features, in the
|
||||
* sense that it may introduce latencies in other modules. It is thus
|
||||
* recommended not to use ICSP in conjunction with latency-sensitive features.
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, in
|
||||
* which every attempt to use it (except {@link #close()}) will throw a
|
||||
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
|
||||
* instance may no longer be used. Any resources associated with it are freed
|
||||
* and can be reused.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* IcspMaster icsp = ioio.openIcspMaster();
|
||||
* icsp.enterProgramming();
|
||||
* icsp.executeInstruction(0x212340); // mov #0x1234, w0
|
||||
* icsp.executeInstruction(0x883C20); // mov w0, 0x784 (VISI)
|
||||
* icsp.executeInstruction(0x000000); // nop
|
||||
* icsp.readVisi();
|
||||
* int visi = icsp.waitVisiResult(); // should read 0x1234
|
||||
* icsp.exitProgramming();
|
||||
* icsp.close(); // free ICSP module and pins
|
||||
* }</pre>
|
||||
*
|
||||
* @see IOIO#openIcspMaster()
|
||||
*/
|
||||
public interface IcspMaster extends Closeable {
|
||||
/**
|
||||
* Initiate a sequence that will put the slave device in programming mode.
|
||||
* This sequence is necessary for executing instructions and reading
|
||||
* register values.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
*/
|
||||
public void enterProgramming() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Initiate a sequence that will put the slave device out of programming
|
||||
* mode. It will be held in reset.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
*/
|
||||
public void exitProgramming() throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Execute a single instruction on the slave MCU.
|
||||
*
|
||||
* @param instruction
|
||||
* a 24-bit PIC instruction.
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
*/
|
||||
public void executeInstruction(int instruction)
|
||||
throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Request a read of the VISI register on the slave MCU. This is an
|
||||
* asynchronous call, in which the 16-bit result is obtained by
|
||||
* {@link #waitVisiResult()}.
|
||||
* This method may block if the read queue on the IOIO is full, but this
|
||||
* should be for short periods only.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* Interrupted while blocking.
|
||||
*/
|
||||
public void readVisi() throws ConnectionLostException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Wait and return a result of a call to {@link #readVisi()}.
|
||||
* Results will be returned in the same order as requested.
|
||||
*
|
||||
* The call will block until there is data, until interrupted, or until
|
||||
* connection to the IOIO has been lost.
|
||||
*
|
||||
* @return The result - an unsigned 16-bit number.
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* Interrupted while blocking.
|
||||
*/
|
||||
public int waitVisiResult() throws ConnectionLostException,
|
||||
InterruptedException;
|
||||
}
|
||||
322
IOIOLib/src/ioio/lib/api/PulseInput.java
Executable file
322
IOIOLib/src/ioio/lib/api/PulseInput.java
Executable file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* An interface for pulse width and frequency measurements of digital signals.
|
||||
* <p>
|
||||
* PulseInput (commonly known as "input capture") is a versatile module which
|
||||
* enables extraction of various timing information from a digital signal. There
|
||||
* are two main use cases: pulse duration measurement and frequency measurement.
|
||||
* In pulse width measurement we measure the duration of a positive ("high") or
|
||||
* negative ("low") pulse, i.e. the elapsed time between a rise and a fall or
|
||||
* vice versa. This mode is useful, for example, for decoding a PWM signal or
|
||||
* measuring the delay of a sonar return signal. In frequency measurement we
|
||||
* measure the duration between a rising edge to the following rising edge. This
|
||||
* gives us a momentary reading of a signal's frequency or period. This is
|
||||
* commonly used, for example, in conjunction with an optical or magnetic sensor
|
||||
* 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)}
|
||||
* . 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
|
||||
* positive pulse, {@link PulseMode#NEGATIVE} a negative pulse, and
|
||||
* {@link PulseMode#FREQ} / {@link PulseMode#FREQ_SCALE_4} /
|
||||
* {@link PulseMode#FREQ_SCALE_16} are used for measuring frequency. The
|
||||
* difference between the three scaling modes is that without scaling, the
|
||||
* frequency is determined by measurement of a single
|
||||
* (rising-edge-to-rising-edge) period. In x4 scaling, 4 consecutive periods are
|
||||
* measured and the time is divided by 4, providing some smoothing as well as
|
||||
* better resolution. Similarly for x16 scaling. Note that scaling affects the
|
||||
* range of signals to be measured, as discussed below.
|
||||
* <p>
|
||||
* The choice of single vs. double-precision is important to understand: IOIO
|
||||
* internally uses either 16-bit counters or 32-bit counters for the timing. 16-
|
||||
* counters force us to either limit the maximum duration (and the minimum
|
||||
* frequency) or compromise accuracy as compared to 32-bit counters. However, if
|
||||
* you need many concurrent pulse measurements in your application, you may have
|
||||
* no choice but to use single-precision.
|
||||
* <p>
|
||||
* The clock rate selection is important (and even critical when working in
|
||||
* single-precision) and requires the user to make some assumptions about the
|
||||
* nature of the measured signal. The higher the clock rate, the more precise
|
||||
* the measurement, but the longest pulse that can be measured decreases (or
|
||||
* lowest frequency that can be measured increases). Using the scaling option
|
||||
* when operating in frequency mode also affects these sizes. combinations. It
|
||||
* is always recommended to choose the most precise mode, which exceeds the
|
||||
* maximum expected pulse width (or inverse frequency). If a pulse is received
|
||||
* whom duration exceeds the longest allowed pulse, it will be "folded" into the
|
||||
* valid range and product garbage readings.
|
||||
* <p>
|
||||
* The following table (sorted by longest pulse) summarizes all possible clock /
|
||||
* mode combinations. The table applies for <b>single-precision</b> operation.
|
||||
* For double-precision, simply multiply the longest pulse by 65536 and divide
|
||||
* the lowest frequency by the same amount. Interestingly, the number written in
|
||||
* [ms] units in the longest pulse column, roughly corresponds to the same
|
||||
* number in minutes when working with double precsion, since 1[min] =
|
||||
* 60000[ms].
|
||||
* <table border="1">
|
||||
* <tr>
|
||||
* <th>Clock</th>
|
||||
* <th>Scaling</th>
|
||||
* <th>Resolution</th>
|
||||
* <th>Longest pulse</th>
|
||||
* <th>Lowest frequency</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>62.5KHz</td>
|
||||
* <td>1</td>
|
||||
* <td>16us</td>
|
||||
* <td>1.048s</td>
|
||||
* <td>0.95Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>250KHz</td>
|
||||
* <td>1</td>
|
||||
* <td>4us</td>
|
||||
* <td>262.1ms</td>
|
||||
* <td>3.81Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>62.5KHz</td>
|
||||
* <td>4</td>
|
||||
* <td>4us</td>
|
||||
* <td>262.1ms</td>
|
||||
* <td>3.81Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>250KHz</td>
|
||||
* <td>4</td>
|
||||
* <td>1us</td>
|
||||
* <td>65.54ms</td>
|
||||
* <td>15.26Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>62.5KHz</td>
|
||||
* <td>16</td>
|
||||
* <td>1us</td>
|
||||
* <td>65.54ms</td>
|
||||
* <td>15.26Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>2MHz</td>
|
||||
* <td>1</td>
|
||||
* <td>500ns</td>
|
||||
* <td>32.77ms</td>
|
||||
* <td>30.52Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>250KHz</td>
|
||||
* <td>16</td>
|
||||
* <td>250us</td>
|
||||
* <td>16.38ms</td>
|
||||
* <td>61.0Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>2MHz</td>
|
||||
* <td>4</td>
|
||||
* <td>125ns</td>
|
||||
* <td>8.192ms</td>
|
||||
* <td>122.1Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>16MHz</td>
|
||||
* <td>1</td>
|
||||
* <td>62.5ns</td>
|
||||
* <td>4.096ms</td>
|
||||
* <td>244.1Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>2MHz</td>
|
||||
* <td>16</td>
|
||||
* <td>31.25ns</td>
|
||||
* <td>2.048ms</td>
|
||||
* <td>488.3Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>16MHz</td>
|
||||
* <td>4</td>
|
||||
* <td>15.6ns</td>
|
||||
* <td>1.024ms</td>
|
||||
* <td>976.6Hz</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>16MHz</td>
|
||||
* <td>16</td>
|
||||
* <td>3.9ns</td>
|
||||
* <td>256us</td>
|
||||
* <td>3.906KHz</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>
|
||||
* In some applications it is desirable to measure every incoming pulse rather
|
||||
* than repetitively query the result of the last measurement. For that purpose
|
||||
* the {@link #waitPulseGetDuration()} method exists: every incoming pulse width
|
||||
* is pushed into a small internal queue from which it can be read. The client
|
||||
* waits for data to be available, then reads it and data that comes in in the
|
||||
* meanwhile is stored. The queue has limited size, so it is important to read
|
||||
* quickly if no pulses are to be lost. Note that once a pulse is detected, the
|
||||
* next one must have its leading edge at least 5ms after the leading edge of
|
||||
* the current one, or else it will be skipped. This throttling has been
|
||||
* introduced on purpose, in order to prevent saturation the communication
|
||||
* channel when the input signal is very high frequency. Effectively, this means
|
||||
* that the maximum sample rate is 200Hz. This rate has been chosen as it
|
||||
* enables measure R/C servo signals without missing pulses.
|
||||
*
|
||||
* <p>
|
||||
* Typical usage (servo signal pulse width measurement):
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* // Open pulse input at 16MHz, double-precision
|
||||
* PulseInput in = ioio.openPulseInput(3, PulseMode.POSITIVE);
|
||||
* ...
|
||||
* float widthSec = in.getDuration();
|
||||
* OR:
|
||||
* float widthSec = in.waitPulseGetDuration();
|
||||
* ...
|
||||
* in.close(); // pin 3 can now be used for something else.
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Typical usage (frequency measurement):
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* // Signal is known to be slightly over 150Hz. Single precision can be used.
|
||||
* PulseInput in = ioio.openPulseInput(3,
|
||||
* ClockRate.RATE_2MHz,
|
||||
* PulseMode.FREQ_SCALE_4,
|
||||
* false);
|
||||
* ...
|
||||
* float freqHz = in.getFrequency();
|
||||
* ...
|
||||
* in.close(); // pin 3 can now be used for something else.
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public interface PulseInput extends Closeable {
|
||||
/** An enumeration for describing the module's operating mode. */
|
||||
public enum PulseMode {
|
||||
/** Positive pulse measurement (rising-edge-to-falling-edge). */
|
||||
POSITIVE(1),
|
||||
/** Negative pulse measurement (falling-edge-to-rising-edge). */
|
||||
NEGATIVE(1),
|
||||
/** Frequency measurement (rising-edge-to-rising-edge). */
|
||||
FREQ(1),
|
||||
/** Frequency measurement (rising-edge-to-rising-edge) with 4x scaling. */
|
||||
FREQ_SCALE_4(4),
|
||||
/** Frequency measurement (rising-edge-to-rising-edge) with 16x scaling. */
|
||||
FREQ_SCALE_16(16);
|
||||
|
||||
/** The scaling factor as an integer. */
|
||||
public final int scaling;
|
||||
|
||||
private PulseMode(int s) {
|
||||
scaling = s;
|
||||
}
|
||||
}
|
||||
|
||||
/** Suported clock rate enum. */
|
||||
public enum ClockRate {
|
||||
/** 16MHz */
|
||||
RATE_16MHz(16000000),
|
||||
/** 2MHz */
|
||||
RATE_2MHz(2000000),
|
||||
/** 250KHz */
|
||||
RATE_250KHz(250000),
|
||||
/** 62.5KHz */
|
||||
RATE_62KHz(62500);
|
||||
|
||||
/** The value in Hertz units. */
|
||||
public final int hertz;
|
||||
|
||||
private ClockRate(int h) {
|
||||
hertz = h;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pulse duration in case of pulse measurement mode, or the period
|
||||
* in case of frequency mode. When scaling is used, this is compensated for
|
||||
* here, so the duration of a single cycle will be returned.
|
||||
* <p>
|
||||
* The first call to this method may block shortly until the first data
|
||||
* update arrives. The client may interrupt the calling thread.
|
||||
*
|
||||
* @return The duration, in seconds.
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO has been lost.
|
||||
*/
|
||||
public float getDuration() throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Reads a single measurement from the queue. If the queue is empty, will
|
||||
* block until more data arrives. The calling thread may be interrupted in
|
||||
* order to abort the call. See interface documentation for further
|
||||
* explanation regarding the read queue.
|
||||
* <p>
|
||||
* This method may not be used if the interface has was opened in frequency
|
||||
* mode.
|
||||
*
|
||||
* @return The duration, in seconds.
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO has been lost.
|
||||
*/
|
||||
public float waitPulseGetDuration() throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Gets the momentary frequency of the measured signal. When scaling is
|
||||
* used, this is compensated for here, so the true frequency of the signal
|
||||
* will be returned.
|
||||
* <p>
|
||||
* The first call to this method may block shortly until the first data
|
||||
* update arrives. The client may interrupt the calling thread.
|
||||
*
|
||||
* @return The frequency, in Hz.
|
||||
* @throws InterruptedException
|
||||
* The calling thread has been interrupted.
|
||||
* @throws ConnectionLostException
|
||||
* The connection with the IOIO has been lost.
|
||||
*/
|
||||
public float getFrequency() throws InterruptedException,
|
||||
ConnectionLostException;
|
||||
}
|
||||
126
IOIOLib/src/ioio/lib/api/PwmOutput.java
Normal file
126
IOIOLib/src/ioio/lib/api/PwmOutput.java
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* A pin used for PWM (Pulse-Width Modulation) output.
|
||||
* <p>
|
||||
* A PWM pin produces a logic-level PWM signal. These signals are typically used
|
||||
* for simulating analog outputs for controlling the intensity of LEDs, the
|
||||
* rotation speed of motors, etc. They are also frequently used for controlling
|
||||
* hobby servo motors. PwmOutput instances are obtained by calling
|
||||
* {@link IOIO#openPwmOutput(ioio.lib.api.DigitalOutput.Spec, int)}.
|
||||
* <p>
|
||||
* When used for motors and LEDs, a frequency of several KHz is typically used,
|
||||
* where there is a trade-off between switching power-loses and smoothness of
|
||||
* operation. The pulse width is typically set by specifying the duty cycle,
|
||||
* with the {@link #setDutyCycle(float)} method. A duty cycle of 0 is "off", a
|
||||
* duty cycle of 1 is "on", and every intermediate value produces an
|
||||
* intermediate intensity. Please note that any devices consuming more than 20mA
|
||||
* of current (e.g. motors) should not by directly connected the the IOIO pins,
|
||||
* but rather through an amplification circuit suited for the specific load.
|
||||
* <p>
|
||||
* When used for hobby servos, the PWM signal is rather used for encoding of the
|
||||
* desired angle the motor should go to. By standard, a 100Hz signal is used and
|
||||
* the pulse width is varied between 1ms and 2ms (corresponding to both extremes
|
||||
* of the shaft angle), using {@link #setPulseWidth(int)}.
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, in
|
||||
* which every attempt to use the pin (except {@link #close()}) will throw a
|
||||
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
|
||||
* instance may no longer be used. Any resources associated with it are freed
|
||||
* and can be reused.
|
||||
* <p>
|
||||
* Typical usage (fading LED):
|
||||
*
|
||||
* <pre>
|
||||
* PwmOutput servo = ioio.openPwmOutput(12, 1000); // LED anode on pin 12
|
||||
* ...
|
||||
* servo.setDutyCycle(0.0f); // LED off
|
||||
* ...
|
||||
* servo.setDutyCycle(0.5f); // 50% intensity
|
||||
* ...
|
||||
* servo.setDutyCycle(1.0f); // 100% intensity
|
||||
* ...
|
||||
* servo.close(); // pin 12 can now be used for something else.
|
||||
* </pre>
|
||||
* <p>
|
||||
* Typical usage (servo):
|
||||
*
|
||||
* <pre>
|
||||
* PwmOutput servo = ioio.openPwmOutput(12, 100);
|
||||
* ...
|
||||
* servo.setPulseWidth(1000); // 1000us = 1ms = one extreme
|
||||
* ...
|
||||
* servo.setPulseWidth(1500); // 1500us = 1.5ms = center
|
||||
* ...
|
||||
* servo.setPulseWidth(2000); // 2000us = 2ms = other extreme
|
||||
* ...
|
||||
* servo.close(); // pin 12 can now be used for something else.
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIO#openPwmOutput(ioio.lib.api.DigitalOutput.Spec, int)
|
||||
*/
|
||||
public interface PwmOutput extends Closeable {
|
||||
/**
|
||||
* Sets the duty cycle of the PWM output. The duty cycle is defined to be
|
||||
* the pulse width divided by the total cycle period. For absolute control
|
||||
* of the pulse with, consider using {@link #setPulseWidth(int)}.
|
||||
*
|
||||
* @param dutyCycle
|
||||
* The duty cycle, as a real value from 0.0 to 1.0.
|
||||
* @throws ConnectionLostException
|
||||
* The connection to the IOIO has been lost.
|
||||
* @see #setPulseWidth(int)
|
||||
*/
|
||||
public void setDutyCycle(float dutyCycle) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* Sets the pulse width of the PWM output. The pulse width is duration of
|
||||
* the high-time within a single period of the signal. For relative control
|
||||
* of the pulse with, consider using {@link #setDutyCycle(float)}.
|
||||
*
|
||||
* @param pulseWidthUs
|
||||
* The pulse width, in microsecond units.
|
||||
* @throws ConnectionLostException
|
||||
* The connection to the IOIO has been lost.
|
||||
* @see #setDutyCycle(float)
|
||||
*/
|
||||
public void setPulseWidth(int pulseWidthUs) throws ConnectionLostException;
|
||||
|
||||
/**
|
||||
* The same as {@link #setPulseWidth(int)}, but with sub-microsecond
|
||||
* precision.
|
||||
*/
|
||||
public void setPulseWidth(float pulseWidthUs)
|
||||
throws ConnectionLostException;
|
||||
}
|
||||
211
IOIOLib/src/ioio/lib/api/SpiMaster.java
Executable file
211
IOIOLib/src/ioio/lib/api/SpiMaster.java
Executable file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.DigitalInput.Spec;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* An interface for controlling an SPI module, in SPI bus-master mode, enabling
|
||||
* communication with multiple SPI-enabled slave modules.
|
||||
* <p>
|
||||
* SPI is a common hardware communication protocol, enabling full-duplex,
|
||||
* synchronous point-to-multi-point data transfer. It requires MOSI, MISO and
|
||||
* CLK lines shared by all nodes, as well as a SS line per slave, connected
|
||||
* 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)}.
|
||||
* <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
|
||||
* protocol, the amount of bytes sent is equal to the amount of bytes received.
|
||||
* However, by padding the sent data with garbage data, and by ignoring the
|
||||
* leading bytes of the received data arbitrarily-sized packets can be sent and
|
||||
* received.
|
||||
* <p>
|
||||
* A very common practice for SPI-based slave devices (although not always the
|
||||
* case), is to have a fixed request and response length and a fixed lag between
|
||||
* them, based on the request type. For example, an SPI-based sensor may define
|
||||
* the the protocol for obtaining its measured value is by sending a 2-byte
|
||||
* message, whereas the returned 3-byte value has its first byte overlapping the
|
||||
* second value of the response, as illustrated below:
|
||||
*
|
||||
* <pre>
|
||||
* Master: M1 M2 GG GG
|
||||
* Slave: GG S1 S2 S3
|
||||
* </pre>
|
||||
*
|
||||
* M1, M2: the master's request<br>
|
||||
* S1, S2, S3: the slave's response<br>
|
||||
* GG: garbage bytes used for padding.
|
||||
* <p>
|
||||
* The IOIO SPI interface supports such fixed length message protocols using a
|
||||
* single method, {@link #writeRead(int, byte[], int, int, byte[], int)}, which
|
||||
* gets the request data, and the lengths of the request, the response and the
|
||||
* total transaction bytes.
|
||||
*
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, in
|
||||
* which every attempt to use it (except {@link #close()}) will throw a
|
||||
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
|
||||
* instance may no longer be used. Any resources associated with it are freed
|
||||
* and can be reused.
|
||||
* <p>
|
||||
* Typical usage (single slave, as per the example above):
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* // MISO, MOSI, CLK, SS on pins 3, 4, 5, 6, respectively.
|
||||
* SpiMaster spi = ioio.openSpiMaster(3, 4, 5, 6, SpiMaster.Rate.RATE_125K);
|
||||
* final byte[] request = new byte[]{ 0x23, 0x45 };
|
||||
* final byte[] response = new byte[3];
|
||||
* spi.writeRead(request, 2, 4, response, 3);
|
||||
* ...
|
||||
* spi.close(); // free SPI module and pins
|
||||
* }</pre>
|
||||
*
|
||||
* @see IOIO#openSpiMaster(Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec, ioio.lib.api.DigitalOutput.Spec[], Config)
|
||||
*/
|
||||
public interface SpiMaster extends Closeable {
|
||||
/** Possible data rates for SPI, in Hz. */
|
||||
enum Rate {
|
||||
RATE_31K, RATE_35K, RATE_41K, RATE_50K, RATE_62K, RATE_83K, RATE_125K, RATE_142K, RATE_166K, RATE_200K, RATE_250K, RATE_333K, RATE_500K, RATE_571K, RATE_666K, RATE_800K, RATE_1M, RATE_1_3M, RATE_2M, RATE_2_2M, RATE_2_6M, RATE_3_2M, RATE_4M, RATE_5_3M, RATE_8M
|
||||
}
|
||||
|
||||
/** An object that can be waited on for asynchronous calls. */
|
||||
public interface Result {
|
||||
/**
|
||||
* Wait until the asynchronous call which returned this instance is
|
||||
* complete.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection with the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* This operation has been interrupted.
|
||||
*/
|
||||
public void waitReady() throws ConnectionLostException,
|
||||
InterruptedException;
|
||||
}
|
||||
|
||||
/** SPI configuration structure. */
|
||||
static class Config {
|
||||
/** Data rate. */
|
||||
public Rate rate;
|
||||
/** Whether to invert clock polarity. */
|
||||
public boolean invertClk;
|
||||
/**
|
||||
* Whether to do the input and output sampling on the trailing clock
|
||||
* edge.
|
||||
*/
|
||||
public boolean sampleOnTrailing;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param rate
|
||||
* Data rate.
|
||||
* @param invertClk
|
||||
* Whether to invert clock polarity.
|
||||
* @param sampleOnTrailing
|
||||
* Whether to do the input and output sampling on the
|
||||
* trailing clock edge.
|
||||
*/
|
||||
public Config(Rate rate, boolean invertClk, boolean sampleOnTrailing) {
|
||||
this.rate = rate;
|
||||
this.invertClk = invertClk;
|
||||
this.sampleOnTrailing = sampleOnTrailing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor with common defaults. Equivalent to Config(rate, false,
|
||||
* false)
|
||||
*
|
||||
* @see #Config(Rate, boolean, boolean)
|
||||
*/
|
||||
public Config(Rate rate) {
|
||||
this(rate, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a single SPI transaction which includes optional transmission and
|
||||
* optional reception of data to a single slave. This is a blocking
|
||||
* operation that can take a few milliseconds to a few tens of milliseconds.
|
||||
* To abort this operation, client can interrupt the blocked thread. If
|
||||
* readSize is 0, the call returns immediately.
|
||||
*
|
||||
* @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)}
|
||||
* .
|
||||
* @param writeData
|
||||
* A byte array of data to write. May be null if writeSize is 0.
|
||||
* @param writeSize
|
||||
* Number of bytes to write. Valid values are 0 to totalSize.
|
||||
* @param totalSize
|
||||
* Total transaction length, in bytes. Valid values are 1 to 64.
|
||||
* @param readData
|
||||
* An array where the response is to be stored. May be null if
|
||||
* readSize is 0.
|
||||
* @param readSize
|
||||
* The number of expected response bytes. Valid values are 0 to
|
||||
* totalSize.
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* Calling thread has been interrupted.
|
||||
*/
|
||||
public void writeRead(int slave, byte[] writeData, int writeSize,
|
||||
int totalSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Shorthand for {@link #writeRead(int, byte[], int, int, byte[], int)} for
|
||||
* the single-slave case.
|
||||
*
|
||||
* @see #writeRead(int, byte[], int, int, byte[], int)
|
||||
*/
|
||||
public void writeRead(byte[] writeData, int writeSize, int totalSize,
|
||||
byte[] readData, int readSize) throws ConnectionLostException,
|
||||
InterruptedException;
|
||||
|
||||
/**
|
||||
* The same as {@link #writeRead(int, byte[], int, int, byte[], int)}, but
|
||||
* returns immediately and returns a {@link Result} object that can be
|
||||
* waited on. If readSize is 0, the result object is ready immediately.
|
||||
*
|
||||
* @see #writeRead(int, byte[], int, int, byte[], int)
|
||||
*/
|
||||
public Result writeReadAsync(int slave, byte[] writeData, int writeSize,
|
||||
int totalSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException;
|
||||
}
|
||||
148
IOIOLib/src/ioio/lib/api/TwiMaster.java
Executable file
148
IOIOLib/src/ioio/lib/api/TwiMaster.java
Executable 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.api;
|
||||
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
/**
|
||||
* An interface for controlling a TWI module, in TWI bus-master mode, enabling
|
||||
* communication with multiple TWI-enabled slave modules.
|
||||
* <p>
|
||||
* TWI (Two-Wire Interface) is a common hardware communication protocol,
|
||||
* enabling half-duplex, synchronous point-to-multi-point data transfer. It
|
||||
* 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)}.
|
||||
* <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.
|
||||
* <p>
|
||||
* A TWI transaction is comprised of optional sending of a data buffer from the
|
||||
* master to a single slave, followed by an optional reception of a data buffer
|
||||
* from that slave. Slaves are designated by addresses, which may be 7-bit
|
||||
* (common) or 10-bit (less common). TWI transactions may fail, as a result of
|
||||
* the slave not responding or as result of the slave NACK'ing the request. Such
|
||||
* a transaction is executed using the
|
||||
* {@link #writeRead(int, boolean, byte[], int, byte[], int)} method.
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, in
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, in
|
||||
* which every attempt to use it (except {@link #close()}) will throw a
|
||||
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
|
||||
* instance may no longer be used. Any resources associated with it are freed
|
||||
* and can be reused.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
* // Uses the SDA1/SCL1 pins, I2C volatege levels at 100KHz.
|
||||
* TwiMaster twi = ioio.openTwiMaster(1, TwiMaster.RATE_100KHz, false);
|
||||
* final byte[] request = new byte[]{ 0x23, 0x45 };
|
||||
* final byte[] response = new byte[3];
|
||||
* if (twi.writeRead(0x19, false, request, 2, response, 3)) {
|
||||
* // response is valid
|
||||
* ...
|
||||
* } else {
|
||||
* // handle error
|
||||
* }
|
||||
* twi.close(); // free TWI module and pins
|
||||
* }</pre>
|
||||
*
|
||||
* @see IOIO#openTwiMaster(int, Rate, boolean)
|
||||
*/
|
||||
public interface TwiMaster extends Closeable {
|
||||
enum Rate {
|
||||
RATE_100KHz, RATE_400KHz, RATE_1MHz
|
||||
}
|
||||
|
||||
/** An object that can be waited on for asynchronous calls. */
|
||||
public interface Result {
|
||||
/**
|
||||
* Wait until the asynchronous call which returned this instance is
|
||||
* complete.
|
||||
*
|
||||
* @return true if TWI transaction succeeded.
|
||||
*
|
||||
* @throws ConnectionLostException
|
||||
* Connection with the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* This operation has been interrupted.
|
||||
*/
|
||||
public boolean waitReady() throws ConnectionLostException,
|
||||
InterruptedException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a single TWI transaction which includes optional transmission and
|
||||
* optional reception of data to a single slave. This is a blocking
|
||||
* operation that can take a few milliseconds to a few tens of milliseconds.
|
||||
* To abort this operation, client can interrupt the blocked thread.
|
||||
*
|
||||
* @param address
|
||||
* The slave address, either 7-bit or 10-bit. Note that in some
|
||||
* TWI device documentation the documented addresses are actually
|
||||
* 2x the address values used here, as they regard the trailing
|
||||
* 0-bit as part of the address.
|
||||
* @param tenBitAddr
|
||||
* Whether this is a 10-bit addressing mode.
|
||||
* @param writeData
|
||||
* The request data.
|
||||
* @param writeSize
|
||||
* The number of bytes to write. Valid value are 0-255.
|
||||
* @param readData
|
||||
* The array where the response should be stored.
|
||||
* @param readSize
|
||||
* The expected number of response bytes. Valid value are 0-255.
|
||||
* @return Whether operation succeeded.
|
||||
* @throws ConnectionLostException
|
||||
* Connection to the IOIO has been lost.
|
||||
* @throws InterruptedException
|
||||
* Calling thread has been interrupted.
|
||||
*/
|
||||
public boolean writeRead(int address, boolean tenBitAddr, byte[] writeData,
|
||||
int writeSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Asynchronous version of
|
||||
* {@link #writeRead(int, boolean, byte[], int, byte[], int)}. Returns
|
||||
* immediately and provides a {@link Result} object on which the client can
|
||||
* wait for the result.
|
||||
*
|
||||
* @see #writeRead(int, boolean, byte[], int, byte[], int)
|
||||
*/
|
||||
public Result writeReadAsync(int address, boolean tenBitAddr,
|
||||
byte[] writeData, int writeSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException;
|
||||
}
|
||||
108
IOIOLib/src/ioio/lib/api/Uart.java
Normal file
108
IOIOLib/src/ioio/lib/api/Uart.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import ioio.lib.api.DigitalInput.Spec;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* An interface for controlling a UART module.
|
||||
* <p>
|
||||
* UART is a very common hardware communication protocol, enabling full- duplex,
|
||||
* 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)}.
|
||||
* <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,
|
||||
* making it very useful for terminals and terminal-controllable devices.
|
||||
* <p>
|
||||
* Working with UART is very intuitive - it just provides a standard InputStream
|
||||
* and/or OutputStream. Optionally, one could create a read-only or write-only
|
||||
* UART instances, by passing null (or INVALID_PIN) for either TX or RX pins.
|
||||
* <p>
|
||||
* The instance is alive since its creation. If the connection with the IOIO
|
||||
* drops at any point, the instance transitions to a disconnected state, which
|
||||
* every attempt to use it (except {@link #close()}) will throw a
|
||||
* {@link ConnectionLostException}. Whenever {@link #close()} is invoked the
|
||||
* instance may no longer be used. Any resources associated with it are freed
|
||||
* and can be reused.
|
||||
* <p>
|
||||
* Typical usage:
|
||||
*
|
||||
* <pre>
|
||||
* Uart uart = ioio.openUart(3, 4, 19200, Parity.NONE, StopBits.ONE);
|
||||
* InputStream in = uart.getInputStream();
|
||||
* OutputStream out = uart.getOutputStream();
|
||||
* out.write(new String("Hello").getBytes());
|
||||
* int i = in.read(); // blocking
|
||||
* ...
|
||||
* uart.close(); // free UART module and pins
|
||||
* </pre>
|
||||
*
|
||||
* @see IOIO#openUart(Spec, ioio.lib.api.DigitalOutput.Spec, int, Parity,
|
||||
* StopBits)
|
||||
*/
|
||||
public interface Uart extends Closeable {
|
||||
/** Parity-bit mode. */
|
||||
enum Parity {
|
||||
/** No parity. */
|
||||
NONE,
|
||||
/** Even parity. */
|
||||
EVEN,
|
||||
/** Odd parity. */
|
||||
ODD
|
||||
}
|
||||
|
||||
/** Number of stop-bits. */
|
||||
enum StopBits {
|
||||
/** One stop bit. */
|
||||
ONE,
|
||||
/** Two stop bits. */
|
||||
TWO
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input stream.
|
||||
*
|
||||
* @return An input stream.
|
||||
*/
|
||||
public InputStream getInputStream();
|
||||
|
||||
/**
|
||||
* Gets the output stream.
|
||||
*
|
||||
* @return An output stream.
|
||||
*/
|
||||
public OutputStream getOutputStream();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.api.exception;
|
||||
|
||||
/**
|
||||
* Thrown when the connection between Android and IOIO has been lost or
|
||||
* disconnected.
|
||||
*/
|
||||
public class ConnectionLostException extends Exception {
|
||||
private static final long serialVersionUID = 7422862446246046772L;
|
||||
|
||||
public ConnectionLostException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public ConnectionLostException() {
|
||||
super("Connection lost");
|
||||
}
|
||||
}
|
||||
41
IOIOLib/src/ioio/lib/api/exception/IncompatibilityException.java
Executable file
41
IOIOLib/src/ioio/lib/api/exception/IncompatibilityException.java
Executable 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.api.exception;
|
||||
|
||||
/**
|
||||
* Thrown when an incompatibility of system components is detected, such as when
|
||||
* an unsupported board hardware or software version is encountered.
|
||||
*/
|
||||
public class IncompatibilityException extends Exception {
|
||||
private static final long serialVersionUID = -613939818063932627L;
|
||||
|
||||
public IncompatibilityException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ioio.lib.api.exception;
|
||||
|
||||
/**
|
||||
* The IOIO board does not have anymore of the requested resource. This
|
||||
* exceptions do not need to be handled if the client guarantees that the limits
|
||||
* on concurrent resource usage are never exceeded.
|
||||
*/
|
||||
public class OutOfResourceException extends RuntimeException {
|
||||
private static final long serialVersionUID = -4482605241361881899L;
|
||||
|
||||
public OutOfResourceException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
112
IOIOLib/src/ioio/lib/bluetooth/BluetoothIOIOConnection.java
Normal file
112
IOIOLib/src/ioio/lib/bluetooth/BluetoothIOIOConnection.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package ioio.lib.bluetooth;
|
||||
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.IOException;
|
||||
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.util.Log;
|
||||
|
||||
public class BluetoothIOIOConnection implements IOIOConnection {
|
||||
private static final String TAG = "BluetoothIOIOConnection";
|
||||
private BluetoothSocket socket_ = null;
|
||||
private boolean disconnect_ = false;
|
||||
private final String name_;
|
||||
private final String address_;
|
||||
|
||||
public BluetoothIOIOConnection(String name, String address) {
|
||||
name_ = name;
|
||||
address_ = address;
|
||||
}
|
||||
|
||||
@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.e(TAG, name_ + " Creating socket");
|
||||
try {
|
||||
socket_ = createSocket(ioioDevice);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
Log.e(TAG, name_ + " Created socket");
|
||||
}
|
||||
// keep trying to connect as long as we're not aborting
|
||||
while (true) {
|
||||
try {
|
||||
Log.e(TAG, name_ + "Connecting");
|
||||
socket_.connect();
|
||||
Log.e(TAG, "Established connection to device " + name_
|
||||
+ " address: " + address_);
|
||||
break; // if we got here, we're connected
|
||||
} catch (Exception e) {
|
||||
if (disconnect_) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public 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.
|
||||
return device.createInsecureRfcommSocketToServiceRecord(UUID
|
||||
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
|
||||
} catch (NoSuchMethodError e) {
|
||||
return device.createRfcommSocketToServiceRecord(UUID
|
||||
.fromString("00001101-0000-1000-8000-00805F9B34FB"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void disconnect() {
|
||||
if (disconnect_) {
|
||||
return;
|
||||
}
|
||||
Log.d(TAG, "Client initiated disconnect");
|
||||
disconnect_ = true;
|
||||
if (socket_ != null) {
|
||||
try {
|
||||
socket_.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws ConnectionLostException {
|
||||
try {
|
||||
return socket_.getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws ConnectionLostException {
|
||||
try {
|
||||
return socket_.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
45
IOIOLib/src/ioio/lib/impl/AbstractPin.java
Executable file
45
IOIOLib/src/ioio/lib/impl/AbstractPin.java
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.exception.ConnectionLostException;
|
||||
|
||||
public abstract class AbstractPin extends AbstractResource {
|
||||
protected final int pinNum_;
|
||||
|
||||
AbstractPin(IOIOImpl ioio, int pinNum) throws ConnectionLostException {
|
||||
super(ioio);
|
||||
pinNum_ = pinNum;
|
||||
}
|
||||
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
ioio_.closePin(pinNum_);
|
||||
}
|
||||
}
|
||||
74
IOIOLib/src/ioio/lib/impl/AbstractResource.java
Executable file
74
IOIOLib/src/ioio/lib/impl/AbstractResource.java
Executable file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IncomingState.DisconnectListener;
|
||||
import ioio.lib.api.Closeable;
|
||||
|
||||
public class AbstractResource implements Closeable, DisconnectListener {
|
||||
enum State {
|
||||
OPEN,
|
||||
CLOSED,
|
||||
DISCONNECTED
|
||||
}
|
||||
|
||||
protected State state_ = State.OPEN;
|
||||
protected final IOIOImpl ioio_;
|
||||
|
||||
public AbstractResource(IOIOImpl ioio) throws ConnectionLostException {
|
||||
ioio_ = ioio;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void disconnected() {
|
||||
if (state_ != State.CLOSED) {
|
||||
state_ = State.DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public void close() {
|
||||
if (state_ == State.CLOSED) {
|
||||
throw new IllegalStateException("Trying to use a closed resouce");
|
||||
} else if (state_ == State.DISCONNECTED) {
|
||||
state_ = State.CLOSED;
|
||||
return;
|
||||
}
|
||||
state_ = State.CLOSED;
|
||||
ioio_.removeDisconnectListener(this);
|
||||
}
|
||||
|
||||
protected synchronized void checkState() throws ConnectionLostException {
|
||||
if (state_ == State.CLOSED) {
|
||||
throw new IllegalStateException("Trying to use a closed resouce");
|
||||
} else if (state_ == State.DISCONNECTED) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
}
|
||||
}
|
||||
90
IOIOLib/src/ioio/lib/impl/AnalogInputImpl.java
Executable file
90
IOIOLib/src/ioio/lib/impl/AnalogInputImpl.java
Executable file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 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 {
|
||||
private int value_;
|
||||
private boolean valid_ = false;
|
||||
|
||||
AnalogInputImpl(IOIOImpl ioio, int pin) throws ConnectionLostException {
|
||||
super(ioio, pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVoltage() throws InterruptedException, ConnectionLostException {
|
||||
return read() * getReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getReference() {
|
||||
return 3.3f;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void setValue(int value) {
|
||||
// Log.v("AnalogInputImpl", "Pin " + pinNum_ + " value is " + value);
|
||||
assert(value >= 0 || value < 1024);
|
||||
value_ = value;
|
||||
if (!valid_) {
|
||||
valid_ = true;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public float read() throws InterruptedException, ConnectionLostException {
|
||||
checkState();
|
||||
while (!valid_ && state_ != State.DISCONNECTED) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
return (float) value_ / 1023.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void disconnected() {
|
||||
super.disconnected();
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
super.close();
|
||||
try {
|
||||
ioio_.protocol_.setAnalogInSampling(pinNum_, false);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
45
IOIOLib/src/ioio/lib/impl/Constants.java
Executable file
45
IOIOLib/src/ioio/lib/impl/Constants.java
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class Constants {
|
||||
static final int NUM_PINS = 49;
|
||||
static final int NUM_ANALOG_PINS = 16;
|
||||
static final int NUM_PWM_MODULES = 9;
|
||||
static final int NUM_UART_MODULES = 4;
|
||||
static final int NUM_SPI_MODULES = 3;
|
||||
static final int NUM_TWI_MODULES = 3;
|
||||
static final int[] INCAP_MODULES_DOUBLE = new int[] { 0, 2, 4};
|
||||
static final int[] INCAP_MODULES_SINGLE = new int[] { 6, 7, 8};
|
||||
static final int BUFFER_SIZE = 1024;
|
||||
static final int PACKET_BUFFER_SIZE = 256;
|
||||
|
||||
static final int[][] TWI_PINS = new int[][] {{ 4, 5 }, { 47, 48 }, { 26, 25 }};
|
||||
static final int[] ICSP_PINS = new int[] { 36, 37, 38 };
|
||||
}
|
||||
91
IOIOLib/src/ioio/lib/impl/DigitalInputImpl.java
Executable file
91
IOIOLib/src/ioio/lib/impl/DigitalInputImpl.java
Executable file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.DigitalInput;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IncomingState.InputPinListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DigitalInputImpl extends AbstractPin implements DigitalInput,
|
||||
InputPinListener {
|
||||
private boolean value_;
|
||||
private boolean valid_ = false;
|
||||
|
||||
DigitalInputImpl(IOIOImpl ioio, int pin) throws ConnectionLostException {
|
||||
super(ioio, pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void setValue(int value) {
|
||||
// Log.v("DigitalInputImpl", "Pin " + pinNum_ + " value is " + value);
|
||||
assert (value == 0 || value == 1);
|
||||
value_ = (value == 1);
|
||||
if (!valid_) {
|
||||
valid_ = true;
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized public void waitForValue(boolean value)
|
||||
throws InterruptedException, ConnectionLostException {
|
||||
checkState();
|
||||
while ((!valid_ || value_ != value) && state_ != State.DISCONNECTED) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
try {
|
||||
ioio_.protocol_.setChangeNotify(pinNum_, false);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public boolean read() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
checkState();
|
||||
while (!valid_ && state_ != State.DISCONNECTED) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
return value_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void disconnected() {
|
||||
super.disconnected();
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
50
IOIOLib/src/ioio/lib/impl/DigitalOutputImpl.java
Executable file
50
IOIOLib/src/ioio/lib/impl/DigitalOutputImpl.java
Executable file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.DigitalOutput;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class DigitalOutputImpl extends AbstractPin implements DigitalOutput {
|
||||
DigitalOutputImpl(IOIOImpl ioio, int pin) throws ConnectionLostException {
|
||||
super(ioio, pin);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void write(boolean val) throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
ioio_.protocol_.setDigitalOutLevel(pinNum_, val);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
128
IOIOLib/src/ioio/lib/impl/FlowControlledOutputStream.java
Executable file
128
IOIOLib/src/ioio/lib/impl/FlowControlledOutputStream.java
Executable file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class FlowControlledOutputStream extends OutputStream {
|
||||
interface Sender {
|
||||
void send(byte[] data, int size);
|
||||
}
|
||||
|
||||
private final Sender sender_;
|
||||
private final BlockingQueue<Byte> queue_ = new ArrayBlockingQueue<Byte>(
|
||||
Constants.BUFFER_SIZE);
|
||||
private final FlushThread thread_ = new FlushThread();
|
||||
private final int maxPacket_;
|
||||
private final byte[] packet_;
|
||||
|
||||
private int readyToSend_ = 0;
|
||||
private boolean closed_ = false;
|
||||
|
||||
public FlowControlledOutputStream(Sender sender, int maxPacket) {
|
||||
sender_ = sender;
|
||||
maxPacket_ = maxPacket;
|
||||
packet_ = new byte[maxPacket];
|
||||
thread_.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void flush() throws IOException {
|
||||
try {
|
||||
while (!closed_ && !queue_.isEmpty()) {
|
||||
wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Interrupted");
|
||||
}
|
||||
if (closed_) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void write(int oneByte) throws IOException {
|
||||
try {
|
||||
while (!closed_ && !queue_.offer((byte) oneByte)) {
|
||||
wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Interrupted");
|
||||
}
|
||||
if (closed_) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized public void readyToSend(int numBytes) {
|
||||
readyToSend_ += numBytes;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
closed_ = true;
|
||||
notifyAll();
|
||||
thread_.interrupt();
|
||||
}
|
||||
|
||||
synchronized public void kill() {
|
||||
thread_.interrupt();
|
||||
}
|
||||
|
||||
class FlushThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
try {
|
||||
while (true) {
|
||||
int toSend;
|
||||
synchronized (FlowControlledOutputStream.this) {
|
||||
while (readyToSend_ == 0 || queue_.isEmpty()) {
|
||||
FlowControlledOutputStream.this.wait();
|
||||
}
|
||||
toSend = Math.min(maxPacket_,
|
||||
Math.min(readyToSend_, queue_.size()));
|
||||
for (int i = 0; i < toSend; ++i) {
|
||||
packet_[i] = queue_.remove();
|
||||
}
|
||||
readyToSend_ -= toSend;
|
||||
FlowControlledOutputStream.this.notifyAll();
|
||||
}
|
||||
sender_.send(packet_, toSend);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
IOIOLib/src/ioio/lib/impl/FlowControlledPacketSender.java
Executable file
118
IOIOLib/src/ioio/lib/impl/FlowControlledPacketSender.java
Executable file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class FlowControlledPacketSender {
|
||||
interface Packet {
|
||||
int getSize();
|
||||
}
|
||||
|
||||
interface Sender {
|
||||
void send(Packet packet);
|
||||
}
|
||||
|
||||
private final Sender sender_;
|
||||
private final BlockingQueue<Packet> queue_ = new ArrayBlockingQueue<Packet>(
|
||||
Constants.PACKET_BUFFER_SIZE);
|
||||
private final FlushThread thread_ = new FlushThread();
|
||||
|
||||
private int readyToSend_ = 0;
|
||||
private boolean closed_ = false;
|
||||
|
||||
public FlowControlledPacketSender(Sender sender) {
|
||||
sender_ = sender;
|
||||
thread_.start();
|
||||
}
|
||||
|
||||
synchronized public void flush() throws IOException {
|
||||
try {
|
||||
while (!closed_ && !queue_.isEmpty()) {
|
||||
wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Interrupted");
|
||||
}
|
||||
if (closed_) {
|
||||
throw new IllegalStateException("Stream has been closed");
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public void write(Packet packet) throws IOException {
|
||||
try {
|
||||
while (!closed_ && !queue_.offer(packet)) {
|
||||
wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Interrupted");
|
||||
}
|
||||
if (closed_) {
|
||||
throw new IllegalStateException("Stream has been closed");
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized public void readyToSend(int numBytes) {
|
||||
readyToSend_ += numBytes;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
synchronized public void close() {
|
||||
closed_ = true;
|
||||
thread_.interrupt();
|
||||
}
|
||||
|
||||
synchronized public void kill() {
|
||||
thread_.interrupt();
|
||||
}
|
||||
|
||||
class FlushThread extends Thread {
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
try {
|
||||
while (true) {
|
||||
synchronized (FlowControlledPacketSender.this) {
|
||||
while (queue_.isEmpty()
|
||||
|| readyToSend_ < queue_.peek().getSize()) {
|
||||
FlowControlledPacketSender.this.wait();
|
||||
}
|
||||
FlowControlledPacketSender.this.notifyAll();
|
||||
readyToSend_ -= queue_.peek().getSize();
|
||||
}
|
||||
sender_.send(queue_.remove());
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
654
IOIOLib/src/ioio/lib/impl/IOIOImpl.java
Executable file
654
IOIOLib/src/ioio/lib/impl/IOIOImpl.java
Executable file
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* 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.AnalogInput;
|
||||
import ioio.lib.api.DigitalInput;
|
||||
import ioio.lib.api.DigitalInput.Spec;
|
||||
import ioio.lib.api.DigitalInput.Spec.Mode;
|
||||
import ioio.lib.api.DigitalOutput;
|
||||
import ioio.lib.api.IOIO;
|
||||
import ioio.lib.api.IOIOConnection;
|
||||
import ioio.lib.api.IcspMaster;
|
||||
import ioio.lib.api.PulseInput;
|
||||
import ioio.lib.api.PulseInput.ClockRate;
|
||||
import ioio.lib.api.PulseInput.PulseMode;
|
||||
import ioio.lib.api.PwmOutput;
|
||||
import ioio.lib.api.SpiMaster;
|
||||
import ioio.lib.api.TwiMaster;
|
||||
import ioio.lib.api.TwiMaster.Rate;
|
||||
import ioio.lib.api.Uart;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.api.exception.IncompatibilityException;
|
||||
import ioio.lib.impl.IOIOProtocol.PwmScale;
|
||||
import ioio.lib.impl.IncomingState.DisconnectListener;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class IOIOImpl implements IOIO, DisconnectListener {
|
||||
private static final String TAG = "IOIOImpl";
|
||||
|
||||
enum State {
|
||||
INIT, CONNECTED, INCOMPATIBLE, DEAD
|
||||
}
|
||||
|
||||
private static final byte[] REQUIRED_INTERFACE_ID = new byte[] { 'I', 'O',
|
||||
'I', 'O', '0', '0', '0', '3' };
|
||||
|
||||
private final IOIOConnection connection_;
|
||||
private final IncomingState incomingState_ = new IncomingState();
|
||||
private final boolean openPins_[] = new boolean[Constants.NUM_PINS];
|
||||
private final boolean openTwi_[] = new boolean[Constants.NUM_TWI_MODULES];
|
||||
private boolean openIcsp_ = false;
|
||||
private final ModuleAllocator pwmAllocator_ = new ModuleAllocator(
|
||||
Constants.NUM_PWM_MODULES, "PWM");
|
||||
private final ModuleAllocator uartAllocator_ = new ModuleAllocator(
|
||||
Constants.NUM_UART_MODULES, "UART");
|
||||
private final ModuleAllocator spiAllocator_ = new ModuleAllocator(
|
||||
Constants.NUM_SPI_MODULES, "SPI");
|
||||
private final ModuleAllocator incapAllocatorDouble_ = new ModuleAllocator(
|
||||
Constants.INCAP_MODULES_DOUBLE, "INCAP_DOUBLE");
|
||||
private final ModuleAllocator incapAllocatorSingle_ = new ModuleAllocator(
|
||||
Constants.INCAP_MODULES_SINGLE, "INCAP_SINGLE");
|
||||
IOIOProtocol protocol_;
|
||||
private State state_ = State.INIT;
|
||||
|
||||
public IOIOImpl(IOIOConnection con) {
|
||||
connection_ = con;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void waitForConnect() throws ConnectionLostException,
|
||||
IncompatibilityException {
|
||||
if (state_ == State.CONNECTED) {
|
||||
return;
|
||||
}
|
||||
if (state_ == State.DEAD) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
addDisconnectListener(this);
|
||||
Log.d(TAG, "Waiting for IOIO connection");
|
||||
try {
|
||||
try {
|
||||
Log.d(TAG, "Waiting for underlying connection");
|
||||
connection_.waitForConnect();
|
||||
protocol_ = new IOIOProtocol(connection_.getInputStream(),
|
||||
connection_.getOutputStream(), incomingState_);
|
||||
} catch (ConnectionLostException e) {
|
||||
incomingState_.handleConnectionLost();
|
||||
throw e;
|
||||
}
|
||||
Log.d(TAG, "Waiting for handshake");
|
||||
incomingState_.waitConnectionEstablished();
|
||||
Log.d(TAG, "Querying for required interface ID");
|
||||
checkInterfaceVersion();
|
||||
Log.d(TAG, "Required interface ID is supported");
|
||||
state_ = State.CONNECTED;
|
||||
Log.i(TAG, "IOIO connection established");
|
||||
} catch (ConnectionLostException e) {
|
||||
Log.d(TAG, "Connection lost / aborted");
|
||||
state_ = State.DEAD;
|
||||
throw e;
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, "Unexpected exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
connection_.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
state_ = State.DEAD;
|
||||
// The IOIOConnection doesn't necessarily know about the disconnect
|
||||
disconnect();
|
||||
}
|
||||
|
||||
public void waitForDisconnect() throws InterruptedException {
|
||||
incomingState_.waitDisconnect();
|
||||
}
|
||||
|
||||
private void checkInterfaceVersion() throws IncompatibilityException,
|
||||
ConnectionLostException, InterruptedException {
|
||||
try {
|
||||
protocol_.checkInterface(REQUIRED_INTERFACE_ID);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
if (!incomingState_.waitForInterfaceSupport()) {
|
||||
state_ = State.INCOMPATIBLE;
|
||||
Log.e(TAG, "Required interface ID is not supported");
|
||||
throw new IncompatibilityException(
|
||||
"IOIO firmware does not support required firmware: "
|
||||
+ new String(REQUIRED_INTERFACE_ID));
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void removeDisconnectListener(DisconnectListener listener) {
|
||||
incomingState_.removeDisconnectListener(listener);
|
||||
}
|
||||
|
||||
synchronized void addDisconnectListener(DisconnectListener listener)
|
||||
throws ConnectionLostException {
|
||||
incomingState_.addDisconnectListener(listener);
|
||||
}
|
||||
|
||||
synchronized void closePin(int pin) {
|
||||
try {
|
||||
checkState();
|
||||
if (!openPins_[pin]) {
|
||||
throw new IllegalStateException("Pin not open: " + pin);
|
||||
}
|
||||
protocol_.setPinDigitalIn(pin, DigitalInput.Spec.Mode.FLOATING);
|
||||
openPins_[pin] = false;
|
||||
} catch (IOException e) {
|
||||
} catch (ConnectionLostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void closePwm(int pwmNum) {
|
||||
try {
|
||||
checkState();
|
||||
pwmAllocator_.releaseModule(pwmNum);
|
||||
protocol_.setPwmPeriod(pwmNum, 0, IOIOProtocol.PwmScale.SCALE_1X);
|
||||
} catch (IOException e) {
|
||||
} catch (ConnectionLostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void closeUart(int uartNum) {
|
||||
try {
|
||||
checkState();
|
||||
uartAllocator_.releaseModule(uartNum);
|
||||
protocol_.uartClose(uartNum);
|
||||
} catch (IOException e) {
|
||||
} catch (ConnectionLostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void closeTwi(int twiNum) {
|
||||
try {
|
||||
checkState();
|
||||
if (!openTwi_[twiNum]) {
|
||||
throw new IllegalStateException("TWI not open: " + twiNum);
|
||||
}
|
||||
openTwi_[twiNum] = false;
|
||||
openPins_[Constants.TWI_PINS[twiNum][0]] = false;
|
||||
openPins_[Constants.TWI_PINS[twiNum][1]] = false;
|
||||
protocol_.i2cClose(twiNum);
|
||||
} catch (IOException e) {
|
||||
} catch (ConnectionLostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void closeIcsp() {
|
||||
try {
|
||||
checkState();
|
||||
if (!openIcsp_) {
|
||||
throw new IllegalStateException("ICSP not open");
|
||||
}
|
||||
openIcsp_ = false;
|
||||
openPins_[Constants.ICSP_PINS[0]] = false;
|
||||
openPins_[Constants.ICSP_PINS[1]] = false;
|
||||
protocol_.icspClose();
|
||||
} catch (ConnectionLostException e) {
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void closeSpi(int spiNum) {
|
||||
try {
|
||||
checkState();
|
||||
spiAllocator_.releaseModule(spiNum);
|
||||
protocol_.spiClose(spiNum);
|
||||
} catch (IOException e) {
|
||||
} catch (ConnectionLostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void closeIncap(int incapNum, boolean doublePrecision) {
|
||||
try {
|
||||
checkState();
|
||||
if (doublePrecision) {
|
||||
incapAllocatorDouble_.releaseModule(incapNum);
|
||||
} else {
|
||||
incapAllocatorSingle_.releaseModule(incapNum);
|
||||
}
|
||||
protocol_.incapClose(incapNum);
|
||||
} catch (IOException e) {
|
||||
} catch (ConnectionLostException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void softReset() throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
protocol_.softReset();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void hardReset() throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
protocol_.hardReset();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImplVersion(VersionType v) throws ConnectionLostException {
|
||||
checkState();
|
||||
switch (v) {
|
||||
case HARDWARE_VER:
|
||||
return incomingState_.hardwareId_;
|
||||
case BOOTLOADER_VER:
|
||||
return incomingState_.bootloaderId_;
|
||||
case APP_FIRMWARE_VER:
|
||||
return incomingState_.firmwareId_;
|
||||
case IOIOLIB_VER:
|
||||
return "IOIO0311";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DigitalInput openDigitalInput(int pin)
|
||||
throws ConnectionLostException {
|
||||
return openDigitalInput(new DigitalInput.Spec(pin));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DigitalInput openDigitalInput(int pin, Mode mode)
|
||||
throws ConnectionLostException {
|
||||
return openDigitalInput(new DigitalInput.Spec(pin, mode));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public DigitalInput openDigitalInput(DigitalInput.Spec spec)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
PinFunctionMap.checkValidPin(spec.pin);
|
||||
checkPinFree(spec.pin);
|
||||
DigitalInputImpl result = new DigitalInputImpl(this, spec.pin);
|
||||
addDisconnectListener(result);
|
||||
openPins_[spec.pin] = true;
|
||||
incomingState_.addInputPinListener(spec.pin, result);
|
||||
try {
|
||||
protocol_.setPinDigitalIn(spec.pin, spec.mode);
|
||||
protocol_.setChangeNotify(spec.pin, true);
|
||||
} catch (IOException e) {
|
||||
result.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DigitalOutput openDigitalOutput(int pin,
|
||||
ioio.lib.api.DigitalOutput.Spec.Mode mode, boolean startValue)
|
||||
throws ConnectionLostException {
|
||||
return openDigitalOutput(new DigitalOutput.Spec(pin, mode), startValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public DigitalOutput openDigitalOutput(
|
||||
DigitalOutput.Spec spec, boolean startValue)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
PinFunctionMap.checkValidPin(spec.pin);
|
||||
checkPinFree(spec.pin);
|
||||
DigitalOutputImpl result = new DigitalOutputImpl(this, spec.pin);
|
||||
addDisconnectListener(result);
|
||||
openPins_[spec.pin] = true;
|
||||
try {
|
||||
protocol_.setPinDigitalOut(spec.pin, startValue, spec.mode);
|
||||
} catch (IOException e) {
|
||||
result.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DigitalOutput openDigitalOutput(int pin, boolean startValue)
|
||||
throws ConnectionLostException {
|
||||
return openDigitalOutput(new DigitalOutput.Spec(pin), startValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DigitalOutput openDigitalOutput(int pin)
|
||||
throws ConnectionLostException {
|
||||
return openDigitalOutput(new DigitalOutput.Spec(pin), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public AnalogInput openAnalogInput(int pin)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
PinFunctionMap.checkSupportsAnalogInput(pin);
|
||||
checkPinFree(pin);
|
||||
AnalogInputImpl result = new AnalogInputImpl(this, pin);
|
||||
addDisconnectListener(result);
|
||||
openPins_[pin] = true;
|
||||
incomingState_.addInputPinListener(pin, result);
|
||||
try {
|
||||
protocol_.setPinAnalogIn(pin);
|
||||
protocol_.setAnalogInSampling(pin, true);
|
||||
} catch (IOException e) {
|
||||
result.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PwmOutput openPwmOutput(int pin, int freqHz)
|
||||
throws ConnectionLostException {
|
||||
return openPwmOutput(new DigitalOutput.Spec(pin), freqHz);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public PwmOutput openPwmOutput(DigitalOutput.Spec spec,
|
||||
int freqHz) throws ConnectionLostException {
|
||||
checkState();
|
||||
PinFunctionMap.checkSupportsPeripheralOutput(spec.pin);
|
||||
checkPinFree(spec.pin);
|
||||
int pwmNum = pwmAllocator_.allocateModule();
|
||||
|
||||
int scale = 0;
|
||||
float baseUs;
|
||||
int period;
|
||||
while (true) {
|
||||
final int clk = 16000000 / IOIOProtocol.PwmScale.values()[scale].scale;
|
||||
period = clk / freqHz;
|
||||
if (period <= 65536) {
|
||||
baseUs = 1000000.0f / clk;
|
||||
break;
|
||||
}
|
||||
if (++scale >= PwmScale.values().length) {
|
||||
throw new IllegalArgumentException("Frequency too low: "
|
||||
+ freqHz);
|
||||
}
|
||||
}
|
||||
|
||||
PwmImpl pwm = new PwmImpl(this, spec.pin, pwmNum, period, baseUs);
|
||||
addDisconnectListener(pwm);
|
||||
openPins_[spec.pin] = true;
|
||||
try {
|
||||
protocol_.setPinDigitalOut(spec.pin, false, spec.mode);
|
||||
protocol_.setPinPwm(spec.pin, pwmNum, true);
|
||||
protocol_.setPwmPeriod(pwmNum, period - 1,
|
||||
IOIOProtocol.PwmScale.values()[scale]);
|
||||
} catch (IOException e) {
|
||||
pwm.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return pwm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uart openUart(int rx, int tx, int baud, Uart.Parity parity,
|
||||
Uart.StopBits stopbits) throws ConnectionLostException {
|
||||
return openUart(rx == INVALID_PIN ? null : new DigitalInput.Spec(rx),
|
||||
tx == INVALID_PIN ? null : new DigitalOutput.Spec(tx), baud,
|
||||
parity, stopbits);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public Uart openUart(DigitalInput.Spec rx,
|
||||
DigitalOutput.Spec tx, int baud, Uart.Parity parity,
|
||||
Uart.StopBits stopbits) throws ConnectionLostException {
|
||||
checkState();
|
||||
if (rx != null) {
|
||||
PinFunctionMap.checkSupportsPeripheralInput(rx.pin);
|
||||
checkPinFree(rx.pin);
|
||||
}
|
||||
if (tx != null) {
|
||||
PinFunctionMap.checkSupportsPeripheralOutput(tx.pin);
|
||||
checkPinFree(tx.pin);
|
||||
}
|
||||
int rxPin = rx != null ? rx.pin : INVALID_PIN;
|
||||
int txPin = tx != null ? tx.pin : INVALID_PIN;
|
||||
int uartNum = uartAllocator_.allocateModule();
|
||||
UartImpl uart = new UartImpl(this, txPin, rxPin, uartNum);
|
||||
addDisconnectListener(uart);
|
||||
incomingState_.addUartListener(uartNum, uart);
|
||||
try {
|
||||
if (rx != null) {
|
||||
openPins_[rx.pin] = true;
|
||||
protocol_.setPinDigitalIn(rx.pin, rx.mode);
|
||||
protocol_.setPinUart(rx.pin, uartNum, false, true);
|
||||
}
|
||||
if (tx != null) {
|
||||
openPins_[tx.pin] = true;
|
||||
protocol_.setPinDigitalOut(tx.pin, true, tx.mode);
|
||||
protocol_.setPinUart(tx.pin, uartNum, true, true);
|
||||
}
|
||||
boolean speed4x = true;
|
||||
int rate = Math.round(4000000.0f / baud) - 1;
|
||||
if (rate > 65535) {
|
||||
speed4x = false;
|
||||
rate = Math.round(1000000.0f / baud) - 1;
|
||||
}
|
||||
protocol_.uartConfigure(uartNum, rate, speed4x, stopbits, parity);
|
||||
} catch (IOException e) {
|
||||
uart.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return uart;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public TwiMaster openTwiMaster(int twiNum, Rate rate,
|
||||
boolean smbus) throws ConnectionLostException {
|
||||
checkState();
|
||||
checkTwiFree(twiNum);
|
||||
checkPinFree(Constants.TWI_PINS[twiNum][0]);
|
||||
checkPinFree(Constants.TWI_PINS[twiNum][1]);
|
||||
openPins_[Constants.TWI_PINS[twiNum][0]] = true;
|
||||
openPins_[Constants.TWI_PINS[twiNum][1]] = true;
|
||||
openTwi_[twiNum] = true;
|
||||
TwiMasterImpl twi = new TwiMasterImpl(this, twiNum);
|
||||
addDisconnectListener(twi);
|
||||
incomingState_.addTwiListener(twiNum, twi);
|
||||
try {
|
||||
protocol_.i2cConfigureMaster(twiNum, rate, smbus);
|
||||
} catch (IOException e) {
|
||||
twi.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return twi;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public IcspMaster openIcspMaster()
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
checkIcspFree();
|
||||
checkPinFree(Constants.ICSP_PINS[0]);
|
||||
checkPinFree(Constants.ICSP_PINS[1]);
|
||||
checkPinFree(Constants.ICSP_PINS[2]);
|
||||
openPins_[Constants.ICSP_PINS[0]] = true;
|
||||
openPins_[Constants.ICSP_PINS[1]] = true;
|
||||
openPins_[Constants.ICSP_PINS[2]] = true;
|
||||
openIcsp_ = true;
|
||||
IcspMasterImpl icsp = new IcspMasterImpl(this);
|
||||
addDisconnectListener(icsp);
|
||||
incomingState_.addIcspListener(icsp);
|
||||
try {
|
||||
protocol_.icspOpen();
|
||||
} catch (IOException e) {
|
||||
icsp.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return icsp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiMaster openSpiMaster(int miso, int mosi, int clk,
|
||||
int slaveSelect, SpiMaster.Rate rate)
|
||||
throws ConnectionLostException {
|
||||
return openSpiMaster(miso, mosi, clk, new int[] { slaveSelect }, rate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiMaster openSpiMaster(int miso, int mosi, int clk,
|
||||
int[] slaveSelect, SpiMaster.Rate rate)
|
||||
throws ConnectionLostException {
|
||||
DigitalOutput.Spec[] slaveSpecs = new DigitalOutput.Spec[slaveSelect.length];
|
||||
for (int i = 0; i < slaveSelect.length; ++i) {
|
||||
slaveSpecs[i] = new DigitalOutput.Spec(slaveSelect[i]);
|
||||
}
|
||||
return openSpiMaster(new DigitalInput.Spec(miso, Mode.PULL_UP),
|
||||
new DigitalOutput.Spec(mosi), new DigitalOutput.Spec(clk),
|
||||
slaveSpecs, new SpiMaster.Config(rate));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public SpiMaster openSpiMaster(DigitalInput.Spec miso,
|
||||
DigitalOutput.Spec mosi, DigitalOutput.Spec clk,
|
||||
DigitalOutput.Spec[] slaveSelect, SpiMaster.Config config)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
int ssPins[] = new int[slaveSelect.length];
|
||||
checkPinFree(miso.pin);
|
||||
PinFunctionMap.checkSupportsPeripheralInput(miso.pin);
|
||||
checkPinFree(mosi.pin);
|
||||
PinFunctionMap.checkSupportsPeripheralOutput(mosi.pin);
|
||||
checkPinFree(clk.pin);
|
||||
PinFunctionMap.checkSupportsPeripheralOutput(clk.pin);
|
||||
for (int i = 0; i < slaveSelect.length; ++i) {
|
||||
checkPinFree(slaveSelect[i].pin);
|
||||
ssPins[i] = slaveSelect[i].pin;
|
||||
}
|
||||
|
||||
int spiNum = spiAllocator_.allocateModule();
|
||||
SpiMasterImpl spi = new SpiMasterImpl(this, spiNum, mosi.pin, miso.pin,
|
||||
clk.pin, ssPins);
|
||||
addDisconnectListener(spi);
|
||||
|
||||
openPins_[miso.pin] = true;
|
||||
openPins_[mosi.pin] = true;
|
||||
openPins_[clk.pin] = true;
|
||||
for (int i = 0; i < slaveSelect.length; ++i) {
|
||||
openPins_[slaveSelect[i].pin] = true;
|
||||
}
|
||||
|
||||
incomingState_.addSpiListener(spiNum, spi);
|
||||
try {
|
||||
protocol_.setPinDigitalIn(miso.pin, miso.mode);
|
||||
protocol_.setPinSpi(miso.pin, 1, true, spiNum);
|
||||
protocol_.setPinDigitalOut(mosi.pin, true, mosi.mode);
|
||||
protocol_.setPinSpi(mosi.pin, 0, true, spiNum);
|
||||
protocol_.setPinDigitalOut(clk.pin, config.invertClk, clk.mode);
|
||||
protocol_.setPinSpi(clk.pin, 2, true, spiNum);
|
||||
for (DigitalOutput.Spec spec : slaveSelect) {
|
||||
protocol_.setPinDigitalOut(spec.pin, true, spec.mode);
|
||||
}
|
||||
protocol_.spiConfigureMaster(spiNum, config);
|
||||
} catch (IOException e) {
|
||||
spi.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return spi;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PulseInput openPulseInput(Spec spec, ClockRate rate, PulseMode mode,
|
||||
boolean doublePrecision) throws ConnectionLostException {
|
||||
checkState();
|
||||
checkPinFree(spec.pin);
|
||||
PinFunctionMap.checkSupportsPeripheralInput(spec.pin);
|
||||
int incapNum = doublePrecision ? incapAllocatorDouble_.allocateModule()
|
||||
: incapAllocatorSingle_.allocateModule();
|
||||
IncapImpl incap = new IncapImpl(this, mode, incapNum, spec.pin,
|
||||
rate.hertz, mode.scaling, doublePrecision);
|
||||
addDisconnectListener(incap);
|
||||
incomingState_.addIncapListener(incapNum, incap);
|
||||
openPins_[spec.pin] = true;
|
||||
try {
|
||||
protocol_.setPinDigitalIn(spec.pin, spec.mode);
|
||||
protocol_.setPinIncap(spec.pin, incapNum, true);
|
||||
protocol_.incapConfigure(incapNum, doublePrecision,
|
||||
mode.ordinal() + 1, rate.ordinal());
|
||||
} catch (IOException e) {
|
||||
incap.close();
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
return incap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PulseInput openPulseInput(int pin, PulseMode mode)
|
||||
throws ConnectionLostException {
|
||||
return openPulseInput(new DigitalInput.Spec(pin), ClockRate.RATE_16MHz,
|
||||
mode, true);
|
||||
}
|
||||
|
||||
private void checkPinFree(int pin) {
|
||||
if (openPins_[pin]) {
|
||||
throw new IllegalArgumentException("Pin already open: " + pin);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkTwiFree(int twi) {
|
||||
if (openTwi_[twi]) {
|
||||
throw new IllegalArgumentException("TWI already open: " + twi);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkIcspFree() {
|
||||
if (openIcsp_) {
|
||||
throw new IllegalArgumentException("ICSP already open");
|
||||
}
|
||||
}
|
||||
|
||||
private void checkState() throws ConnectionLostException {
|
||||
if (state_ == State.DEAD) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
if (state_ == State.INCOMPATIBLE) {
|
||||
throw new IllegalStateException(
|
||||
"Incompatibility has been reported - IOIO cannot be used");
|
||||
}
|
||||
if (state_ != State.CONNECTED) {
|
||||
throw new IllegalStateException(
|
||||
"Connection has not yet been established");
|
||||
}
|
||||
}
|
||||
}
|
||||
798
IOIOLib/src/ioio/lib/impl/IOIOProtocol.java
Executable file
798
IOIOLib/src/ioio/lib/impl/IOIOProtocol.java
Executable file
@@ -0,0 +1,798 @@
|
||||
/*
|
||||
* 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.DigitalInput;
|
||||
import ioio.lib.api.DigitalOutput;
|
||||
import ioio.lib.api.SpiMaster;
|
||||
import ioio.lib.api.TwiMaster.Rate;
|
||||
import ioio.lib.api.Uart;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class IOIOProtocol {
|
||||
static final int HARD_RESET = 0x00;
|
||||
static final int ESTABLISH_CONNECTION = 0x00;
|
||||
static final int SOFT_RESET = 0x01;
|
||||
static final int CHECK_INTERFACE = 0x02;
|
||||
static final int CHECK_INTERFACE_RESPONSE = 0x02;
|
||||
static final int SET_PIN_DIGITAL_OUT = 0x03;
|
||||
static final int SET_DIGITAL_OUT_LEVEL = 0x04;
|
||||
static final int REPORT_DIGITAL_IN_STATUS = 0x04;
|
||||
static final int SET_PIN_DIGITAL_IN = 0x05;
|
||||
static final int REPORT_PERIODIC_DIGITAL_IN_STATUS = 0x05;
|
||||
static final int SET_CHANGE_NOTIFY = 0x06;
|
||||
static final int REGISTER_PERIODIC_DIGITAL_SAMPLING = 0x07;
|
||||
static final int SET_PIN_PWM = 0x08;
|
||||
static final int SET_PWM_DUTY_CYCLE = 0x09;
|
||||
static final int SET_PWM_PERIOD = 0x0A;
|
||||
static final int SET_PIN_ANALOG_IN = 0x0B;
|
||||
static final int REPORT_ANALOG_IN_STATUS = 0x0B;
|
||||
static final int SET_ANALOG_IN_SAMPLING = 0x0C;
|
||||
static final int REPORT_ANALOG_IN_FORMAT = 0x0C;
|
||||
static final int UART_CONFIG = 0x0D;
|
||||
static final int UART_STATUS = 0x0D;
|
||||
static final int UART_DATA = 0x0E;
|
||||
static final int SET_PIN_UART = 0x0F;
|
||||
static final int UART_REPORT_TX_STATUS = 0x0F;
|
||||
static final int SPI_CONFIGURE_MASTER = 0x10;
|
||||
static final int SPI_STATUS = 0x10;
|
||||
static final int SPI_MASTER_REQUEST = 0x11;
|
||||
static final int SPI_DATA = 0x11;
|
||||
static final int SET_PIN_SPI = 0x12;
|
||||
static final int SPI_REPORT_TX_STATUS = 0x12;
|
||||
static final int I2C_CONFIGURE_MASTER = 0x13;
|
||||
static final int I2C_STATUS = 0x13;
|
||||
static final int I2C_WRITE_READ = 0x14;
|
||||
static final int I2C_RESULT = 0x14;
|
||||
static final int I2C_REPORT_TX_STATUS = 0x15;
|
||||
static final int ICSP_SIX = 0x16;
|
||||
static final int ICSP_REPORT_RX_STATUS = 0x16;
|
||||
static final int ICSP_REGOUT = 0x17;
|
||||
static final int ICSP_RESULT = 0x17;
|
||||
static final int ICSP_PROG_ENTER = 0x18;
|
||||
static final int ICSP_PROG_EXIT = 0x19;
|
||||
static final int ICSP_CONFIG = 0x1A;
|
||||
static final int INCAP_CONFIGURE = 0x1B;
|
||||
static final int INCAP_STATUS = 0x1B;
|
||||
static final int SET_PIN_INCAP = 0x1C;
|
||||
static final int INCAP_REPORT = 0x1C;
|
||||
|
||||
static final int[] SCALE_DIV = new int[] {
|
||||
0x1F, // 31.25
|
||||
0x1E, // 35.714
|
||||
0x1D, // 41.667
|
||||
0x1C, // 50
|
||||
0x1B, // 62.5
|
||||
0x1A, // 83.333
|
||||
0x17, // 125
|
||||
0x16, // 142.857
|
||||
0x15, // 166.667
|
||||
0x14, // 200
|
||||
0x13, // 250
|
||||
0x12, // 333.333
|
||||
0x0F, // 500
|
||||
0x0E, // 571.429
|
||||
0x0D, // 666.667
|
||||
0x0C, // 800
|
||||
0x0B, // 1000
|
||||
0x0A, // 1333.333
|
||||
0x07, // 2000
|
||||
0x06, // 2285.714
|
||||
0x05, // 2666.667
|
||||
0x04, // 3200
|
||||
0x03, // 4000
|
||||
0x02, // 5333.333
|
||||
0x01 // 8000
|
||||
};
|
||||
|
||||
private static final String TAG = "IOIOProtocol";
|
||||
|
||||
enum PwmScale {
|
||||
SCALE_1X(1, 0), SCALE_8X(8, 3), SCALE_64X(64, 2), SCALE_256X(256, 1);
|
||||
|
||||
public final int scale;
|
||||
private final int encoding;
|
||||
|
||||
PwmScale(int scale, int encoding) {
|
||||
this.scale = scale;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] outbuf_ = new byte[128];
|
||||
private int pos_ = 0;
|
||||
|
||||
private void writeByte(int b) {
|
||||
assert (b >= 0 && b < 256);
|
||||
//Log.v(TAG, "sending: 0x" + Integer.toHexString(b));
|
||||
outbuf_[pos_++] = (byte) b;
|
||||
}
|
||||
|
||||
private void flush() throws IOException {
|
||||
try {
|
||||
out_.write(outbuf_, 0, pos_);
|
||||
} finally {
|
||||
pos_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeTwoBytes(int i) throws IOException {
|
||||
writeByte(i & 0xFF);
|
||||
writeByte(i >> 8);
|
||||
}
|
||||
|
||||
private void writeThreeBytes(int i) throws IOException {
|
||||
writeByte(i & 0xFF);
|
||||
writeByte((i >> 8) & 0xFF);
|
||||
writeByte((i >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
synchronized public void hardReset() throws IOException {
|
||||
writeByte(HARD_RESET);
|
||||
writeByte('I');
|
||||
writeByte('O');
|
||||
writeByte('I');
|
||||
writeByte('O');
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void softReset() throws IOException {
|
||||
writeByte(SOFT_RESET);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void checkInterface(byte[] interfaceId)
|
||||
throws IOException {
|
||||
if (interfaceId.length != 8) {
|
||||
throw new IllegalArgumentException(
|
||||
"interface ID must be exactly 8 bytes long");
|
||||
}
|
||||
writeByte(CHECK_INTERFACE);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
writeByte(interfaceId[i]);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setDigitalOutLevel(int pin, boolean level)
|
||||
throws IOException {
|
||||
writeByte(SET_DIGITAL_OUT_LEVEL);
|
||||
writeByte(pin << 2 | (level ? 1 : 0));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPinPwm(int pin, int pwmNum, boolean enable)
|
||||
throws IOException {
|
||||
writeByte(SET_PIN_PWM);
|
||||
writeByte(pin & 0x3F);
|
||||
writeByte((enable ? 0x80 : 0x00) | (pwmNum & 0x0F));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPwmDutyCycle(int pwmNum, int dutyCycle,
|
||||
int fraction) throws IOException {
|
||||
writeByte(SET_PWM_DUTY_CYCLE);
|
||||
writeByte(pwmNum << 2 | fraction);
|
||||
writeTwoBytes(dutyCycle);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPwmPeriod(int pwmNum, int period, PwmScale scale)
|
||||
throws IOException {
|
||||
writeByte(SET_PWM_PERIOD);
|
||||
writeByte(((scale.encoding & 0x02) << 6) | (pwmNum << 1)
|
||||
| (scale.encoding & 0x01));
|
||||
writeTwoBytes(period);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPinIncap(int pin, int incapNum, boolean enable)
|
||||
throws IOException {
|
||||
writeByte(SET_PIN_INCAP);
|
||||
writeByte(pin);
|
||||
writeByte(incapNum | (enable ? 0x80 : 0x00));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void incapClose(int incapNum) throws IOException {
|
||||
writeByte(INCAP_CONFIGURE);
|
||||
writeByte(incapNum);
|
||||
writeByte(0x00);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void incapConfigure(int incapNum, boolean double_prec,
|
||||
int mode, int clock) throws IOException {
|
||||
writeByte(INCAP_CONFIGURE);
|
||||
writeByte(incapNum);
|
||||
writeByte((double_prec ? 0x80 : 0x00) | (mode << 3) | clock);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void i2cWriteRead(int i2cNum, boolean tenBitAddr,
|
||||
int address, int writeSize, int readSize, byte[] writeData)
|
||||
throws IOException {
|
||||
writeByte(I2C_WRITE_READ);
|
||||
writeByte(((address >> 8) << 6) | (tenBitAddr ? 0x20 : 0x00) | i2cNum);
|
||||
writeByte(address & 0xFF);
|
||||
writeByte(writeSize);
|
||||
writeByte(readSize);
|
||||
for (int i = 0; i < writeSize; ++i) {
|
||||
writeByte(((int) writeData[i]) & 0xFF);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPinDigitalOut(int pin, boolean value,
|
||||
DigitalOutput.Spec.Mode mode) throws IOException {
|
||||
writeByte(SET_PIN_DIGITAL_OUT);
|
||||
writeByte((pin << 2)
|
||||
| (mode == DigitalOutput.Spec.Mode.OPEN_DRAIN ? 0x01 : 0x00)
|
||||
| (value ? 0x02 : 0x00));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPinDigitalIn(int pin,
|
||||
DigitalInput.Spec.Mode mode) throws IOException {
|
||||
int pull = 0;
|
||||
if (mode == DigitalInput.Spec.Mode.PULL_UP) {
|
||||
pull = 1;
|
||||
} else if (mode == DigitalInput.Spec.Mode.PULL_DOWN) {
|
||||
pull = 2;
|
||||
}
|
||||
writeByte(SET_PIN_DIGITAL_IN);
|
||||
writeByte((pin << 2) | pull);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setChangeNotify(int pin, boolean changeNotify)
|
||||
throws IOException {
|
||||
writeByte(SET_CHANGE_NOTIFY);
|
||||
writeByte((pin << 2) | (changeNotify ? 0x01 : 0x00));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void registerPeriodicDigitalSampling(int pin,
|
||||
int freqScale) throws IOException {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
synchronized public void setPinAnalogIn(int pin) throws IOException {
|
||||
writeByte(SET_PIN_ANALOG_IN);
|
||||
writeByte(pin);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setAnalogInSampling(int pin, boolean enable)
|
||||
throws IOException {
|
||||
writeByte(SET_ANALOG_IN_SAMPLING);
|
||||
writeByte((enable ? 0x80 : 0x00) | (pin & 0x3F));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void uartData(int uartNum, int numBytes, byte data[])
|
||||
throws IOException {
|
||||
if (numBytes > 64) {
|
||||
throw new IllegalArgumentException(
|
||||
"A maximum of 64 bytes can be sent in one uartData message. Got: "
|
||||
+ numBytes);
|
||||
}
|
||||
writeByte(UART_DATA);
|
||||
writeByte((numBytes - 1) | uartNum << 6);
|
||||
for (int i = 0; i < numBytes; ++i) {
|
||||
writeByte(((int) data[i]) & 0xFF);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void uartConfigure(int uartNum, int rate,
|
||||
boolean speed4x, Uart.StopBits stopbits, Uart.Parity parity)
|
||||
throws IOException {
|
||||
int parbits = parity == Uart.Parity.EVEN ? 1
|
||||
: (parity == Uart.Parity.ODD ? 2 : 0);
|
||||
writeByte(UART_CONFIG);
|
||||
writeByte((uartNum << 6) | (speed4x ? 0x08 : 0x00)
|
||||
| (stopbits == Uart.StopBits.TWO ? 0x04 : 0x00) | parbits);
|
||||
writeTwoBytes(rate);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void uartClose(int uartNum) throws IOException {
|
||||
writeByte(UART_CONFIG);
|
||||
writeByte(uartNum << 6);
|
||||
writeTwoBytes(0);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPinUart(int pin, int uartNum, boolean tx,
|
||||
boolean enable) throws IOException {
|
||||
writeByte(SET_PIN_UART);
|
||||
writeByte(pin);
|
||||
writeByte((enable ? 0x80 : 0x00) | (tx ? 0x40 : 0x00) | uartNum);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void spiConfigureMaster(int spiNum,
|
||||
SpiMaster.Config config) throws IOException {
|
||||
writeByte(SPI_CONFIGURE_MASTER);
|
||||
writeByte((spiNum << 5) | SCALE_DIV[config.rate.ordinal()]);
|
||||
writeByte((config.sampleOnTrailing ? 0x00 : 0x02)
|
||||
| (config.invertClk ? 0x01 : 0x00));
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void spiClose(int spiNum) throws IOException {
|
||||
writeByte(SPI_CONFIGURE_MASTER);
|
||||
writeByte(spiNum << 5);
|
||||
writeByte(0x00);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void setPinSpi(int pin, int mode, boolean enable,
|
||||
int spiNum) throws IOException {
|
||||
writeByte(SET_PIN_SPI);
|
||||
writeByte(pin);
|
||||
writeByte((1 << 4) | (mode << 2) | spiNum);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void spiMasterRequest(int spiNum, int ssPin,
|
||||
byte data[], int dataBytes, int totalBytes, int responseBytes)
|
||||
throws IOException {
|
||||
final boolean dataNeqTotal = (dataBytes != totalBytes);
|
||||
final boolean resNeqTotal = (responseBytes != totalBytes);
|
||||
writeByte(SPI_MASTER_REQUEST);
|
||||
writeByte((spiNum << 6) | ssPin);
|
||||
writeByte((dataNeqTotal ? 0x80 : 0x00) | (resNeqTotal ? 0x40 : 0x00)
|
||||
| totalBytes - 1);
|
||||
if (dataNeqTotal) {
|
||||
writeByte(dataBytes);
|
||||
}
|
||||
if (resNeqTotal) {
|
||||
writeByte(responseBytes);
|
||||
}
|
||||
for (int i = 0; i < dataBytes; ++i) {
|
||||
writeByte(((int) data[i]) & 0xFF);
|
||||
}
|
||||
flush();
|
||||
}
|
||||
|
||||
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));
|
||||
writeByte(I2C_CONFIGURE_MASTER);
|
||||
writeByte((smbusLevels ? 0x80 : 0) | (rateBits << 5) | i2cNum);
|
||||
flush();
|
||||
}
|
||||
|
||||
synchronized public void i2cClose(int i2cNum) throws IOException {
|
||||
writeByte(I2C_CONFIGURE_MASTER);
|
||||
writeByte(i2cNum);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void icspOpen() throws IOException {
|
||||
writeByte(ICSP_CONFIG);
|
||||
writeByte(0x01);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void icspClose() throws IOException {
|
||||
writeByte(ICSP_CONFIG);
|
||||
writeByte(0x00);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void icspEnter() throws IOException {
|
||||
writeByte(ICSP_PROG_ENTER);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void icspExit() throws IOException {
|
||||
writeByte(ICSP_PROG_EXIT);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void icspSix(int instruction) throws IOException {
|
||||
writeByte(ICSP_SIX);
|
||||
writeThreeBytes(instruction);
|
||||
flush();
|
||||
}
|
||||
|
||||
public void icspRegout() throws IOException {
|
||||
writeByte(ICSP_REGOUT);
|
||||
flush();
|
||||
}
|
||||
|
||||
public interface IncomingHandler {
|
||||
public void handleEstablishConnection(byte[] hardwareId,
|
||||
byte[] bootloaderId, byte[] firmwareId);
|
||||
|
||||
public void handleConnectionLost();
|
||||
|
||||
public void handleSoftReset();
|
||||
|
||||
public void handleCheckInterfaceResponse(boolean supported);
|
||||
|
||||
public void handleSetChangeNotify(int pin, boolean changeNotify);
|
||||
|
||||
public void handleReportDigitalInStatus(int pin, boolean level);
|
||||
|
||||
public void handleRegisterPeriodicDigitalSampling(int pin, int freqScale);
|
||||
|
||||
public void handleReportPeriodicDigitalInStatus(int frameNum,
|
||||
boolean values[]);
|
||||
|
||||
public void handleAnalogPinStatus(int pin, boolean open);
|
||||
|
||||
public void handleReportAnalogInStatus(int pins[], int values[]);
|
||||
|
||||
public void handleUartOpen(int uartNum);
|
||||
|
||||
public void handleUartClose(int uartNum);
|
||||
|
||||
public void handleUartData(int uartNum, int numBytes, byte data[]);
|
||||
|
||||
public void handleUartReportTxStatus(int uartNum, int bytesRemaining);
|
||||
|
||||
public void handleSpiOpen(int spiNum);
|
||||
|
||||
public void handleSpiClose(int spiNum);
|
||||
|
||||
public void handleSpiData(int spiNum, int ssPin, byte data[],
|
||||
int dataBytes);
|
||||
|
||||
public void handleSpiReportTxStatus(int spiNum, int bytesRemaining);
|
||||
|
||||
public void handleI2cOpen(int i2cNum);
|
||||
|
||||
public void handleI2cClose(int i2cNum);
|
||||
|
||||
public void handleI2cResult(int i2cNum, int size, byte[] data);
|
||||
|
||||
public void handleI2cReportTxStatus(int spiNum, int bytesRemaining);
|
||||
|
||||
void handleIcspOpen();
|
||||
|
||||
void handleIcspClose();
|
||||
|
||||
void handleIcspReportRxStatus(int bytesRemaining);
|
||||
|
||||
void handleIcspResult(int size, byte[] data);
|
||||
|
||||
public void handleIncapReport(int incapNum, int size, byte[] data);
|
||||
|
||||
public void handleIncapClose(int incapNum);
|
||||
|
||||
public void handleIncapOpen(int incapNum);
|
||||
}
|
||||
|
||||
class IncomingThread extends Thread {
|
||||
private int readOffset_ = 0;
|
||||
private int validBytes_ = 0;
|
||||
private byte[] inbuf_ = new byte[64];
|
||||
|
||||
private int[] analogFramePins_ = new int[0];
|
||||
private Set<Integer> removedPins_ = new HashSet<Integer>(
|
||||
Constants.NUM_ANALOG_PINS);
|
||||
private Set<Integer> addedPins_ = new HashSet<Integer>(
|
||||
Constants.NUM_ANALOG_PINS);
|
||||
|
||||
private void findDelta(int[] newPins) {
|
||||
removedPins_.clear();
|
||||
addedPins_.clear();
|
||||
for (int i : analogFramePins_) {
|
||||
removedPins_.add(i);
|
||||
}
|
||||
for (int i : newPins) {
|
||||
addedPins_.add(i);
|
||||
}
|
||||
for (Iterator<Integer> it = removedPins_.iterator(); it.hasNext();) {
|
||||
Integer current = it.next();
|
||||
if (addedPins_.contains(current)) {
|
||||
it.remove();
|
||||
addedPins_.remove(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void fillBuf() throws IOException {
|
||||
try {
|
||||
validBytes_ = in_.read(inbuf_, 0, inbuf_.length);
|
||||
if (validBytes_ <= 0) {
|
||||
throw new IOException("Unexpected stream closure");
|
||||
}
|
||||
//Log.v(TAG, "received " + validBytes_ + " bytes");
|
||||
readOffset_ = 0;
|
||||
} catch (IOException e) {
|
||||
Log.i(TAG, "IOIO disconnected");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private int readByte() throws IOException {
|
||||
if (readOffset_ == validBytes_) {
|
||||
fillBuf();
|
||||
}
|
||||
int b = inbuf_[readOffset_++];
|
||||
b &= 0xFF; // make unsigned
|
||||
//Log.v(TAG, "received: 0x" + Integer.toHexString(b));
|
||||
return b;
|
||||
}
|
||||
|
||||
private void readBytes(int size, byte[] buffer) throws IOException {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
buffer[i] = (byte) readByte();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.run();
|
||||
setPriority(MAX_PRIORITY);
|
||||
int arg1;
|
||||
int arg2;
|
||||
int numPins;
|
||||
int size;
|
||||
byte[] data = new byte[256];
|
||||
try {
|
||||
while (true) {
|
||||
switch (arg1 = readByte()) {
|
||||
case ESTABLISH_CONNECTION:
|
||||
if (readByte() != 'I' || readByte() != 'O'
|
||||
|| readByte() != 'I' || readByte() != 'O') {
|
||||
throw new IOException(
|
||||
"Bad establish connection magic");
|
||||
}
|
||||
byte[] hardwareId = new byte[8];
|
||||
byte[] bootloaderId = new byte[8];
|
||||
byte[] firmwareId = new byte[8];
|
||||
readBytes(8, hardwareId);
|
||||
readBytes(8, bootloaderId);
|
||||
readBytes(8, firmwareId);
|
||||
|
||||
handler_.handleEstablishConnection(hardwareId,
|
||||
bootloaderId, firmwareId);
|
||||
break;
|
||||
|
||||
case SOFT_RESET:
|
||||
handler_.handleSoftReset();
|
||||
break;
|
||||
|
||||
case REPORT_DIGITAL_IN_STATUS:
|
||||
arg1 = readByte();
|
||||
handler_.handleReportDigitalInStatus(arg1 >> 2,
|
||||
(arg1 & 0x01) == 1);
|
||||
break;
|
||||
|
||||
case SET_CHANGE_NOTIFY:
|
||||
arg1 = readByte();
|
||||
handler_.handleSetChangeNotify(arg1 >> 2,
|
||||
(arg1 & 0x01) == 1);
|
||||
break;
|
||||
|
||||
case REGISTER_PERIODIC_DIGITAL_SAMPLING:
|
||||
// TODO: implement
|
||||
break;
|
||||
|
||||
case REPORT_PERIODIC_DIGITAL_IN_STATUS:
|
||||
// TODO: implement
|
||||
break;
|
||||
|
||||
case REPORT_ANALOG_IN_FORMAT:
|
||||
numPins = readByte();
|
||||
int[] newFormat = new int[numPins];
|
||||
for (int i = 0; i < numPins; ++i) {
|
||||
newFormat[i] = readByte();
|
||||
}
|
||||
findDelta(newFormat);
|
||||
for (Integer i : removedPins_) {
|
||||
handler_.handleAnalogPinStatus(i, false);
|
||||
}
|
||||
for (Integer i : addedPins_) {
|
||||
handler_.handleAnalogPinStatus(i, true);
|
||||
}
|
||||
analogFramePins_ = newFormat;
|
||||
break;
|
||||
|
||||
case REPORT_ANALOG_IN_STATUS:
|
||||
numPins = analogFramePins_.length;
|
||||
int header = 0;
|
||||
int[] values = new int[numPins];
|
||||
for (int i = 0; i < numPins; ++i) {
|
||||
if (i % 4 == 0) {
|
||||
header = readByte();
|
||||
}
|
||||
values[i] = (readByte() << 2) | (header & 0x03);
|
||||
header >>= 2;
|
||||
}
|
||||
handler_.handleReportAnalogInStatus(analogFramePins_,
|
||||
values);
|
||||
break;
|
||||
|
||||
case UART_REPORT_TX_STATUS:
|
||||
arg1 = readByte();
|
||||
arg2 = readByte();
|
||||
handler_.handleUartReportTxStatus(arg1 & 0x03,
|
||||
(arg1 >> 2) | (arg2 << 6));
|
||||
break;
|
||||
|
||||
case UART_DATA:
|
||||
arg1 = readByte();
|
||||
for (int i = 0; i < (arg1 & 0x3F) + 1; ++i) {
|
||||
data[i] = (byte) readByte();
|
||||
}
|
||||
handler_.handleUartData(arg1 >> 6, (arg1 & 0x3F) + 1,
|
||||
data);
|
||||
break;
|
||||
|
||||
case UART_STATUS:
|
||||
arg1 = readByte();
|
||||
if ((arg1 & 0x80) != 0) {
|
||||
handler_.handleUartOpen(arg1 & 0x03);
|
||||
} else {
|
||||
handler_.handleUartClose(arg1 & 0x03);
|
||||
}
|
||||
break;
|
||||
|
||||
case SPI_DATA:
|
||||
arg1 = readByte();
|
||||
arg2 = readByte();
|
||||
for (int i = 0; i < (arg1 & 0x3F) + 1; ++i) {
|
||||
data[i] = (byte) readByte();
|
||||
}
|
||||
handler_.handleSpiData(arg1 >> 6, arg2 & 0x3F, data,
|
||||
(arg1 & 0x3F) + 1);
|
||||
break;
|
||||
|
||||
case SPI_REPORT_TX_STATUS:
|
||||
arg1 = readByte();
|
||||
arg2 = readByte();
|
||||
handler_.handleSpiReportTxStatus(arg1 & 0x03,
|
||||
(arg1 >> 2) | (arg2 << 6));
|
||||
break;
|
||||
|
||||
case SPI_STATUS:
|
||||
arg1 = readByte();
|
||||
if ((arg1 & 0x80) != 0) {
|
||||
handler_.handleSpiOpen(arg1 & 0x03);
|
||||
} else {
|
||||
handler_.handleSpiClose(arg1 & 0x03);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_STATUS:
|
||||
arg1 = readByte();
|
||||
if ((arg1 & 0x80) != 0) {
|
||||
handler_.handleI2cOpen(arg1 & 0x03);
|
||||
} else {
|
||||
handler_.handleI2cClose(arg1 & 0x03);
|
||||
}
|
||||
break;
|
||||
|
||||
case I2C_RESULT:
|
||||
arg1 = readByte();
|
||||
arg2 = readByte();
|
||||
if (arg2 != 0xFF) {
|
||||
for (int i = 0; i < arg2; ++i) {
|
||||
data[i] = (byte) readByte();
|
||||
}
|
||||
}
|
||||
handler_.handleI2cResult(arg1 & 0x03, arg2, data);
|
||||
break;
|
||||
|
||||
case I2C_REPORT_TX_STATUS:
|
||||
arg1 = readByte();
|
||||
arg2 = readByte();
|
||||
handler_.handleI2cReportTxStatus(arg1 & 0x03,
|
||||
(arg1 >> 2) | (arg2 << 6));
|
||||
break;
|
||||
|
||||
case CHECK_INTERFACE_RESPONSE:
|
||||
arg1 = readByte();
|
||||
handler_.handleCheckInterfaceResponse((arg1 & 0x01) == 1);
|
||||
break;
|
||||
|
||||
case ICSP_REPORT_RX_STATUS:
|
||||
arg1 = readByte();
|
||||
arg2 = readByte();
|
||||
handler_.handleIcspReportRxStatus(arg1 | (arg2 << 8));
|
||||
break;
|
||||
|
||||
case ICSP_RESULT:
|
||||
data[0] = (byte) readByte();
|
||||
data[1] = (byte) readByte();
|
||||
handler_.handleIcspResult(2, data);
|
||||
break;
|
||||
|
||||
case ICSP_CONFIG:
|
||||
arg1 = readByte();
|
||||
if ((arg1 & 0x01) == 1) {
|
||||
handler_.handleIcspOpen();
|
||||
} else {
|
||||
handler_.handleIcspClose();
|
||||
}
|
||||
break;
|
||||
|
||||
case INCAP_STATUS:
|
||||
arg1 = readByte();
|
||||
if ((arg1 & 0x80) != 0) {
|
||||
handler_.handleIncapOpen(arg1 & 0x0F);
|
||||
} else {
|
||||
handler_.handleIncapClose(arg1 & 0x0F);
|
||||
}
|
||||
break;
|
||||
|
||||
case INCAP_REPORT:
|
||||
arg1 = readByte();
|
||||
size = arg1 >> 6;
|
||||
if (size == 0) {
|
||||
size = 4;
|
||||
}
|
||||
readBytes(size, data);
|
||||
handler_.handleIncapReport(arg1 & 0x0F, size, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
in_.close();
|
||||
IOException e = new IOException(
|
||||
"Received unexpected command: 0x"
|
||||
+ Integer.toHexString(arg1));
|
||||
Log.e("IOIOProtocol", "Protocol error", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
handler_.handleConnectionLost();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final InputStream in_;
|
||||
private final OutputStream out_;
|
||||
private final IncomingHandler handler_;
|
||||
private final IncomingThread thread_ = new IncomingThread();
|
||||
|
||||
public IOIOProtocol(InputStream in, OutputStream out,
|
||||
IncomingHandler handler) {
|
||||
in_ = in;
|
||||
out_ = out;
|
||||
handler_ = handler;
|
||||
thread_.start();
|
||||
}
|
||||
}
|
||||
135
IOIOLib/src/ioio/lib/impl/IcspMasterImpl.java
Executable file
135
IOIOLib/src/ioio/lib/impl/IcspMasterImpl.java
Executable file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.IcspMaster;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IncomingState.DataModuleListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class IcspMasterImpl extends AbstractResource implements IcspMaster,
|
||||
DataModuleListener {
|
||||
private Queue<Integer> resultQueue_ = new LinkedList<Integer>();
|
||||
private int rxRemaining_ = 0;
|
||||
|
||||
public IcspMasterImpl(IOIOImpl ioio) throws ConnectionLostException {
|
||||
super(ioio);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void dataReceived(byte[] data, int size) {
|
||||
assert (size == 2);
|
||||
int result = (byteToInt(data[1]) << 8) | byteToInt(data[0]);
|
||||
resultQueue_.add(result);
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void reportAdditionalBuffer(int bytesToAdd) {
|
||||
rxRemaining_ += bytesToAdd;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void enterProgramming() throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
ioio_.protocol_.icspEnter();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void exitProgramming() throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
ioio_.protocol_.icspExit();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void executeInstruction(int instruction)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
try {
|
||||
ioio_.protocol_.icspSix(instruction);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void readVisi() throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
checkState();
|
||||
while (rxRemaining_ < 2 && state_ == State.OPEN) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
rxRemaining_ -= 2;
|
||||
try {
|
||||
ioio_.protocol_.icspRegout();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
ioio_.closeIcsp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void disconnected() {
|
||||
super.disconnected();
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
private static int byteToInt(byte b) {
|
||||
return ((int) b) & 0xFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int waitVisiResult() throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
checkState();
|
||||
while (resultQueue_.isEmpty() && state_ == State.OPEN) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
return resultQueue_.remove();
|
||||
}
|
||||
}
|
||||
109
IOIOLib/src/ioio/lib/impl/IncapImpl.java
Executable file
109
IOIOLib/src/ioio/lib/impl/IncapImpl.java
Executable file
@@ -0,0 +1,109 @@
|
||||
package ioio.lib.impl;
|
||||
|
||||
import ioio.lib.api.PulseInput;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IncomingState.DataModuleListener;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class IncapImpl extends AbstractPin implements DataModuleListener,
|
||||
PulseInput {
|
||||
private static final int MAX_QUEUE_LEN = 32;
|
||||
private final PulseMode mode_;
|
||||
private final int incapNum_;
|
||||
private long lastDuration_;
|
||||
private final float timeBase_;
|
||||
private final boolean doublePrecision_;
|
||||
private boolean valid_ = false;
|
||||
// TODO: a fixed-size array would have been much better than a linked list.
|
||||
private Queue<Long> pulseQueue_ = new LinkedList<Long>();
|
||||
|
||||
public IncapImpl(IOIOImpl ioio, PulseMode mode, int incapNum, int pin,
|
||||
int clockRate, int scale, boolean doublePrecision)
|
||||
throws ConnectionLostException {
|
||||
super(ioio, pin);
|
||||
mode_ = mode;
|
||||
incapNum_ = incapNum;
|
||||
timeBase_ = 1.0f / (scale * clockRate);
|
||||
doublePrecision_ = doublePrecision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFrequency() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
if (mode_ != PulseMode.FREQ && mode_ != PulseMode.FREQ_SCALE_4
|
||||
&& mode_ != PulseMode.FREQ_SCALE_16) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot query frequency when module was not opened in frequency mode.");
|
||||
}
|
||||
return 1.0f / getDuration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized float getDuration() throws InterruptedException,
|
||||
ConnectionLostException {
|
||||
checkState();
|
||||
while (!valid_) {
|
||||
wait();
|
||||
checkState();
|
||||
}
|
||||
return timeBase_ * lastDuration_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized float waitPulseGetDuration()
|
||||
throws InterruptedException, ConnectionLostException {
|
||||
if (mode_ != PulseMode.POSITIVE && mode_ != PulseMode.NEGATIVE) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot wait for pulse when module was not opened in pulse mode.");
|
||||
}
|
||||
checkState();
|
||||
while (pulseQueue_.isEmpty() && state_ == State.OPEN) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
return timeBase_ * pulseQueue_.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void dataReceived(byte[] data, int size) {
|
||||
lastDuration_ = ByteArrayToLong(data, size);
|
||||
if (pulseQueue_.size() == MAX_QUEUE_LEN) {
|
||||
pulseQueue_.remove();
|
||||
}
|
||||
pulseQueue_.add(lastDuration_);
|
||||
valid_ = true;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
private static long ByteArrayToLong(byte[] data, int size) {
|
||||
long result = 0;
|
||||
int i = size;
|
||||
while (i-- > 0) {
|
||||
result <<= 8;
|
||||
result |= ((int) data[i]) & 0xFF;
|
||||
}
|
||||
if (result == 0) {
|
||||
result = 1 << (size * 8);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reportAdditionalBuffer(int bytesToAdd) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
ioio_.closeIncap(incapNum_, doublePrecision_);
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void disconnected() {
|
||||
notifyAll();
|
||||
super.disconnected();
|
||||
}
|
||||
|
||||
}
|
||||
460
IOIOLib/src/ioio/lib/impl/IncomingState.java
Executable file
460
IOIOLib/src/ioio/lib/impl/IncomingState.java
Executable file
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
* 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.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.IOIOProtocol.IncomingHandler;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class IncomingState implements IncomingHandler {
|
||||
enum ConnectionState {
|
||||
INIT, ESTABLISHED, CONNECTED, DISCONNECTED, UNSUPPORTED_IID
|
||||
}
|
||||
|
||||
interface InputPinListener {
|
||||
void setValue(int value);
|
||||
}
|
||||
|
||||
interface DisconnectListener {
|
||||
void disconnected();
|
||||
}
|
||||
|
||||
interface DataModuleListener {
|
||||
void dataReceived(byte[] data, int size);
|
||||
|
||||
void reportAdditionalBuffer(int bytesToAdd);
|
||||
}
|
||||
|
||||
class InputPinState {
|
||||
private Queue<InputPinListener> listeners_ = new ConcurrentLinkedQueue<InputPinListener>();
|
||||
private boolean currentOpen_ = false;
|
||||
|
||||
void pushListener(InputPinListener listener) {
|
||||
listeners_.add(listener);
|
||||
}
|
||||
|
||||
void closeCurrentListener() {
|
||||
if (currentOpen_) {
|
||||
currentOpen_ = false;
|
||||
listeners_.remove();
|
||||
}
|
||||
}
|
||||
|
||||
void openNextListener() {
|
||||
assert (!listeners_.isEmpty());
|
||||
if (!currentOpen_) {
|
||||
currentOpen_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void setValue(int v) {
|
||||
assert (currentOpen_);
|
||||
listeners_.peek().setValue(v);
|
||||
}
|
||||
}
|
||||
|
||||
class DataModuleState {
|
||||
private Queue<DataModuleListener> listeners_ = new ConcurrentLinkedQueue<IncomingState.DataModuleListener>();
|
||||
private boolean currentOpen_ = false;
|
||||
|
||||
void pushListener(DataModuleListener listener) {
|
||||
listeners_.add(listener);
|
||||
}
|
||||
|
||||
void closeCurrentListener() {
|
||||
if (currentOpen_) {
|
||||
currentOpen_ = false;
|
||||
listeners_.remove();
|
||||
}
|
||||
}
|
||||
|
||||
void openNextListener() {
|
||||
assert (!listeners_.isEmpty());
|
||||
if (!currentOpen_) {
|
||||
currentOpen_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void dataReceived(byte[] data, int size) {
|
||||
assert (currentOpen_);
|
||||
listeners_.peek().dataReceived(data, size);
|
||||
}
|
||||
|
||||
public void reportAdditionalBuffer(int bytesRemaining) {
|
||||
assert (currentOpen_);
|
||||
listeners_.peek().reportAdditionalBuffer(bytesRemaining);
|
||||
}
|
||||
}
|
||||
|
||||
private final InputPinState[] intputPinStates_ = new InputPinState[Constants.NUM_PINS];
|
||||
private final DataModuleState[] uartStates_ = new DataModuleState[Constants.NUM_UART_MODULES];
|
||||
private final DataModuleState[] twiStates_ = new DataModuleState[Constants.NUM_TWI_MODULES];
|
||||
private final DataModuleState[] spiStates_ = new DataModuleState[Constants.NUM_SPI_MODULES];
|
||||
private final DataModuleState[] incapStates_ = new DataModuleState[2
|
||||
* Constants.INCAP_MODULES_DOUBLE.length
|
||||
+ Constants.INCAP_MODULES_SINGLE.length];
|
||||
private final DataModuleState icspState_ = new DataModuleState();
|
||||
private final Set<DisconnectListener> disconnectListeners_ = new HashSet<IncomingState.DisconnectListener>();
|
||||
private ConnectionState connection_ = ConnectionState.INIT;
|
||||
public String hardwareId_;
|
||||
public String bootloaderId_;
|
||||
public String firmwareId_;
|
||||
|
||||
public IncomingState() {
|
||||
for (int i = 0; i < intputPinStates_.length; ++i) {
|
||||
intputPinStates_[i] = new InputPinState();
|
||||
}
|
||||
for (int i = 0; i < uartStates_.length; ++i) {
|
||||
uartStates_[i] = new DataModuleState();
|
||||
}
|
||||
for (int i = 0; i < twiStates_.length; ++i) {
|
||||
twiStates_[i] = new DataModuleState();
|
||||
}
|
||||
for (int i = 0; i < spiStates_.length; ++i) {
|
||||
spiStates_[i] = new DataModuleState();
|
||||
}
|
||||
for (int i = 0; i < incapStates_.length; ++i) {
|
||||
incapStates_[i] = new DataModuleState();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public void waitConnectionEstablished()
|
||||
throws InterruptedException, ConnectionLostException {
|
||||
while (connection_ == ConnectionState.INIT) {
|
||||
wait();
|
||||
}
|
||||
if (connection_ == ConnectionState.DISCONNECTED) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
}
|
||||
|
||||
synchronized public boolean waitForInterfaceSupport()
|
||||
throws InterruptedException, ConnectionLostException {
|
||||
if (connection_ == ConnectionState.INIT) {
|
||||
throw new IllegalStateException(
|
||||
"Have to connect before waiting for interface support");
|
||||
}
|
||||
while (connection_ == ConnectionState.ESTABLISHED) {
|
||||
wait();
|
||||
}
|
||||
if (connection_ == ConnectionState.DISCONNECTED) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
return connection_ == ConnectionState.CONNECTED;
|
||||
}
|
||||
|
||||
synchronized public void waitDisconnect() throws InterruptedException {
|
||||
while (connection_ != ConnectionState.DISCONNECTED) {
|
||||
wait();
|
||||
}
|
||||
}
|
||||
|
||||
public void addInputPinListener(int pin, InputPinListener listener) {
|
||||
intputPinStates_[pin].pushListener(listener);
|
||||
}
|
||||
|
||||
public void addUartListener(int uartNum, DataModuleListener listener) {
|
||||
uartStates_[uartNum].pushListener(listener);
|
||||
}
|
||||
|
||||
public void addTwiListener(int twiNum, DataModuleListener listener) {
|
||||
twiStates_[twiNum].pushListener(listener);
|
||||
}
|
||||
|
||||
public void addIncapListener(int incapNum, DataModuleListener listener) {
|
||||
incapStates_[incapNum].pushListener(listener);
|
||||
}
|
||||
|
||||
public void addIcspListener(DataModuleListener listener) {
|
||||
icspState_.pushListener(listener);
|
||||
}
|
||||
|
||||
public void addSpiListener(int spiNum, DataModuleListener listener) {
|
||||
spiStates_[spiNum].pushListener(listener);
|
||||
}
|
||||
|
||||
synchronized public void addDisconnectListener(DisconnectListener listener)
|
||||
throws ConnectionLostException {
|
||||
checkNotDisconnected();
|
||||
disconnectListeners_.add(listener);
|
||||
}
|
||||
|
||||
synchronized public void removeDisconnectListener(
|
||||
DisconnectListener listener) {
|
||||
if (connection_ != ConnectionState.DISCONNECTED) {
|
||||
disconnectListeners_.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleConnectionLost() {
|
||||
// logMethod("handleConnectionLost");
|
||||
synchronized (this) {
|
||||
connection_ = ConnectionState.DISCONNECTED;
|
||||
}
|
||||
for (DisconnectListener listener : disconnectListeners_) {
|
||||
listener.disconnected();
|
||||
}
|
||||
disconnectListeners_.clear();
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSoftReset() {
|
||||
// logMethod("handleSoftReset");
|
||||
for (InputPinState pinState : intputPinStates_) {
|
||||
pinState.closeCurrentListener();
|
||||
}
|
||||
for (DataModuleState uartState : uartStates_) {
|
||||
uartState.closeCurrentListener();
|
||||
}
|
||||
for (DataModuleState twiState : twiStates_) {
|
||||
twiState.closeCurrentListener();
|
||||
}
|
||||
for (DataModuleState spiState : spiStates_) {
|
||||
spiState.closeCurrentListener();
|
||||
}
|
||||
for (DataModuleState incapState : incapStates_) {
|
||||
incapState.closeCurrentListener();
|
||||
}
|
||||
icspState_.closeCurrentListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void handleCheckInterfaceResponse(boolean supported) {
|
||||
// logMethod("handleCheckInterfaceResponse", supported);
|
||||
connection_ = supported ? ConnectionState.CONNECTED
|
||||
: ConnectionState.UNSUPPORTED_IID;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSetChangeNotify(int pin, boolean changeNotify) {
|
||||
// logMethod("handleSetChangeNotify", pin, changeNotify);
|
||||
if (changeNotify) {
|
||||
intputPinStates_[pin].openNextListener();
|
||||
} else {
|
||||
intputPinStates_[pin].closeCurrentListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRegisterPeriodicDigitalSampling(int pin, int freqScale) {
|
||||
// logMethod("handleRegisterPeriodicDigitalSampling", pin, freqScale);
|
||||
assert (false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleAnalogPinStatus(int pin, boolean open) {
|
||||
// logMethod("handleAnalogPinStatus", pin, open);
|
||||
if (open) {
|
||||
intputPinStates_[pin].openNextListener();
|
||||
} else {
|
||||
intputPinStates_[pin].closeCurrentListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUartData(int uartNum, int numBytes, byte[] data) {
|
||||
// logMethod("handleUartData", uartNum, numBytes, data);
|
||||
uartStates_[uartNum].dataReceived(data, numBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUartOpen(int uartNum) {
|
||||
// logMethod("handleUartOpen", uartNum);
|
||||
uartStates_[uartNum].openNextListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUartClose(int uartNum) {
|
||||
// logMethod("handleUartClose", uartNum);
|
||||
uartStates_[uartNum].closeCurrentListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSpiOpen(int spiNum) {
|
||||
// logMethod("handleSpiOpen", spiNum);
|
||||
spiStates_[spiNum].openNextListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSpiClose(int spiNum) {
|
||||
// logMethod("handleSpiClose", spiNum);
|
||||
spiStates_[spiNum].closeCurrentListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleI2cOpen(int i2cNum) {
|
||||
// logMethod("handleI2cOpen", i2cNum);
|
||||
twiStates_[i2cNum].openNextListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleI2cClose(int i2cNum) {
|
||||
// logMethod("handleI2cClose", i2cNum);
|
||||
twiStates_[i2cNum].closeCurrentListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIcspOpen() {
|
||||
// logMethod("handleIcspOpen");
|
||||
icspState_.openNextListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIcspClose() {
|
||||
// logMethod("handleIcspClose");
|
||||
icspState_.closeCurrentListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEstablishConnection(byte[] hardwareId,
|
||||
byte[] bootloaderId, byte[] firmwareId) {
|
||||
hardwareId_ = new String(hardwareId);
|
||||
bootloaderId_ = new String(bootloaderId);
|
||||
firmwareId_ = new String(firmwareId);
|
||||
|
||||
Log.i("IncomingState", "IOIO Connection established. Hardware ID: "
|
||||
+ hardwareId_ + " Bootloader ID: " + bootloaderId_
|
||||
+ " Firmware ID: " + firmwareId_);
|
||||
synchronized (this) {
|
||||
connection_ = ConnectionState.ESTABLISHED;
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleUartReportTxStatus(int uartNum, int bytesRemaining) {
|
||||
// logMethod("handleUartReportTxStatus", uartNum, bytesRemaining);
|
||||
uartStates_[uartNum].reportAdditionalBuffer(bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleI2cReportTxStatus(int i2cNum, int bytesRemaining) {
|
||||
// logMethod("handleI2cReportTxStatus", i2cNum, bytesRemaining);
|
||||
twiStates_[i2cNum].reportAdditionalBuffer(bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSpiData(int spiNum, int ssPin, byte[] data, int dataBytes) {
|
||||
// logMethod("handleSpiData", spiNum, ssPin, data, dataBytes);
|
||||
spiStates_[spiNum].dataReceived(data, dataBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIcspReportRxStatus(int bytesRemaining) {
|
||||
// logMethod("handleIcspReportRxStatus", bytesRemaining);
|
||||
icspState_.reportAdditionalBuffer(bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleReportDigitalInStatus(int pin, boolean level) {
|
||||
// logMethod("handleReportDigitalInStatus", pin, level);
|
||||
intputPinStates_[pin].setValue(level ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleReportPeriodicDigitalInStatus(int frameNum,
|
||||
boolean[] values) {
|
||||
// logMethod("handleReportPeriodicDigitalInStatus", frameNum, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleReportAnalogInStatus(int pins[], int values[]) {
|
||||
// logMethod("handleReportAnalogInStatus", pins, values);
|
||||
for (int i = 0; i < pins.length; ++i) {
|
||||
intputPinStates_[pins[i]].setValue(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSpiReportTxStatus(int spiNum, int bytesRemaining) {
|
||||
// logMethod("handleSpiReportTxStatus", spiNum, bytesRemaining);
|
||||
spiStates_[spiNum].reportAdditionalBuffer(bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleI2cResult(int i2cNum, int size, byte[] data) {
|
||||
// logMethod("handleI2cResult", i2cNum, size, data);
|
||||
twiStates_[i2cNum].dataReceived(data, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIncapReport(int incapNum, int size, byte[] data) {
|
||||
// logMethod("handleIncapReport", incapNum, size, data);
|
||||
incapStates_[incapNum].dataReceived(data, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIncapClose(int incapNum) {
|
||||
// logMethod("handleIncapClose", incapNum);
|
||||
incapStates_[incapNum].closeCurrentListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIncapOpen(int incapNum) {
|
||||
// logMethod("handleIncapOpen", incapNum);
|
||||
incapStates_[incapNum].openNextListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleIcspResult(int size, byte[] data) {
|
||||
// logMethod("handleIcspResult", size, data);
|
||||
icspState_.dataReceived(data, size);
|
||||
}
|
||||
|
||||
private void checkNotDisconnected() throws ConnectionLostException {
|
||||
if (connection_ == ConnectionState.DISCONNECTED) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
}
|
||||
|
||||
// private void logMethod(String name, Object... args) {
|
||||
// StringBuffer msg = new StringBuffer(name);
|
||||
// msg.append('(');
|
||||
// for (int i = 0; i < args.length; ++i) {
|
||||
// if (i != 0) {
|
||||
// msg.append(", ");
|
||||
// }
|
||||
// msg.append(args[i]);
|
||||
// }
|
||||
// msg.append(')');
|
||||
//
|
||||
// Log.v("IncomingState", msg.toString());
|
||||
// }
|
||||
}
|
||||
106
IOIOLib/src/ioio/lib/impl/ModuleAllocator.java
Executable file
106
IOIOLib/src/ioio/lib/impl/ModuleAllocator.java
Executable file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.exception.OutOfResourceException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Utility to allocate and assign unique module ids.
|
||||
* A module id is requested via {@link #allocateModule()}
|
||||
* and released via {@link #releaseModule(int)}.
|
||||
*
|
||||
* @author birmiwal
|
||||
*/
|
||||
public class ModuleAllocator {
|
||||
private final Set<Integer> availableModuleIds_;
|
||||
private final Set<Integer> allocatedModuleIds_;
|
||||
private final String name_;
|
||||
|
||||
public ModuleAllocator(Collection<Integer> availableModuleIds, String name) {
|
||||
this.availableModuleIds_ = new TreeSet<Integer>(availableModuleIds);
|
||||
allocatedModuleIds_ = new HashSet<Integer>();
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
public ModuleAllocator(int[] availableModuleIds, String name) {
|
||||
this(getList(availableModuleIds), name);
|
||||
}
|
||||
|
||||
public ModuleAllocator(int maxModules, String name) {
|
||||
this(getList(maxModules), name);
|
||||
}
|
||||
|
||||
private static Collection<Integer> getList(int maxModules) {
|
||||
List<Integer> availableModuleIds = new ArrayList<Integer>();
|
||||
for (int i = 0; i < maxModules; i++) {
|
||||
availableModuleIds.add(i);
|
||||
}
|
||||
return availableModuleIds;
|
||||
}
|
||||
|
||||
private static Collection<Integer> getList(int[] array) {
|
||||
List<Integer> availableModuleIds = new ArrayList<Integer>(array.length);
|
||||
for (int i : array) {
|
||||
availableModuleIds.add(i);
|
||||
}
|
||||
return availableModuleIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a module id that was allocated, or {@code null} if nothing was available
|
||||
*/
|
||||
public synchronized Integer allocateModule() {
|
||||
if (availableModuleIds_.isEmpty()) {
|
||||
throw new OutOfResourceException("No more resources of the requested type: " + name_);
|
||||
}
|
||||
Integer moduleId = availableModuleIds_.iterator().next();
|
||||
availableModuleIds_.remove(moduleId);
|
||||
allocatedModuleIds_.add(moduleId);
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param moduleId the moduleId to be released; throws {@link IllegalArgumentException} if
|
||||
* a moduleId is re-returned, or an invalid moduleId is provided
|
||||
*/
|
||||
public synchronized void releaseModule(int moduleId) {
|
||||
if (!allocatedModuleIds_.contains(moduleId)) {
|
||||
throw new IllegalArgumentException("moduleId: " + moduleId+ "; not yet allocated");
|
||||
}
|
||||
availableModuleIds_.add(moduleId);
|
||||
allocatedModuleIds_.remove(moduleId);
|
||||
}
|
||||
}
|
||||
76
IOIOLib/src/ioio/lib/impl/PinFunctionMap.java
Executable file
76
IOIOLib/src/ioio/lib/impl/PinFunctionMap.java
Executable file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
public 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,
|
||||
false, false, false, false, false, false, true, true, true, true,
|
||||
true, true, false, true, true, true, true, true, true, true, false,
|
||||
false, false, false, true, true, true, true };
|
||||
|
||||
private static final boolean[] PERIPHERAL_IN = new boolean[] { true,
|
||||
false, false, true, true, true, true, true, false, true, true,
|
||||
true, true, true, true, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, true, true, true, true,
|
||||
true, true, false, true, true, true, true, true, true, true, false,
|
||||
false, false, false, true, true, true, true };
|
||||
|
||||
static void checkSupportsAnalogInput(int pin) {
|
||||
checkValidPin(pin);
|
||||
if (pin < 31 || pin > 46) {
|
||||
throw new IllegalArgumentException("Pin " + pin
|
||||
+ " does not support analog input");
|
||||
}
|
||||
}
|
||||
|
||||
static void checkSupportsPeripheralInput(int pin) {
|
||||
checkValidPin(pin);
|
||||
if (!PERIPHERAL_IN[pin]) {
|
||||
throw new IllegalArgumentException("Pin " + pin
|
||||
+ " does not support peripheral input");
|
||||
}
|
||||
}
|
||||
|
||||
static void checkSupportsPeripheralOutput(int pin) {
|
||||
checkValidPin(pin);
|
||||
if (!PERIPHERAL_OUT[pin]) {
|
||||
throw new IllegalArgumentException("Pin " + pin
|
||||
+ " does not support peripheral output");
|
||||
}
|
||||
}
|
||||
|
||||
static void checkValidPin(int pin) {
|
||||
if (pin < 0 || pin > 48) {
|
||||
throw new IllegalArgumentException("Illegal pin: " + pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
101
IOIOLib/src/ioio/lib/impl/PwmImpl.java
Executable file
101
IOIOLib/src/ioio/lib/impl/PwmImpl.java
Executable file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.PwmOutput;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class PwmImpl extends AbstractResource implements PwmOutput {
|
||||
private final int pwmNum_;
|
||||
private final int pinNum_;
|
||||
private final float baseUs_;
|
||||
private final int period_;
|
||||
|
||||
public PwmImpl(IOIOImpl ioio, int pinNum, int pwmNum, int period,
|
||||
float baseUs) throws ConnectionLostException {
|
||||
super(ioio);
|
||||
pwmNum_ = pwmNum;
|
||||
pinNum_ = pinNum;
|
||||
baseUs_ = baseUs;
|
||||
period_ = period;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
super.close();
|
||||
ioio_.closePwm(pwmNum_);
|
||||
ioio_.closePin(pinNum_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDutyCycle(float dutyCycle) throws ConnectionLostException {
|
||||
assert (dutyCycle <= 1 && dutyCycle >= 0);
|
||||
setPulseWidthInClocks(period_ * dutyCycle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPulseWidth(int pulseWidthUs) throws ConnectionLostException {
|
||||
setPulseWidth((float) pulseWidthUs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPulseWidth(float pulseWidthUs)
|
||||
throws ConnectionLostException {
|
||||
assert (pulseWidthUs >= 0);
|
||||
float p = pulseWidthUs / baseUs_;
|
||||
setPulseWidthInClocks(p);
|
||||
}
|
||||
|
||||
synchronized private void setPulseWidthInClocks(float p)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
if (p > period_) {
|
||||
p = period_;
|
||||
}
|
||||
int pw;
|
||||
int fraction;
|
||||
p -= 1; // period parameter is one less than the actual period length
|
||||
// yes, there is 0 and then 2 (no 1) - this is not a bug, that
|
||||
// is how the hardware PWM module works.
|
||||
if (p < 1) {
|
||||
pw = 0;
|
||||
fraction = 0;
|
||||
} else {
|
||||
pw = (int) p;
|
||||
fraction = ((int) p * 4) & 0x03;
|
||||
}
|
||||
try {
|
||||
ioio_.protocol_.setPwmDutyCycle(pwmNum_, pw, fraction);
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
79
IOIOLib/src/ioio/lib/impl/QueueInputStream.java
Executable file
79
IOIOLib/src/ioio/lib/impl/QueueInputStream.java
Executable file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class QueueInputStream extends InputStream {
|
||||
private final Queue<Byte> queue_ = new ArrayBlockingQueue<Byte>(
|
||||
Constants.BUFFER_SIZE);
|
||||
private boolean closed_ = false;
|
||||
|
||||
@Override
|
||||
synchronized public int read() throws IOException {
|
||||
try {
|
||||
while (!closed_ && queue_.isEmpty()) {
|
||||
wait();
|
||||
}
|
||||
if (closed_) {
|
||||
throw new IOException("Stream has been closed");
|
||||
}
|
||||
return ((int) queue_.remove()) & 0xFF;
|
||||
} 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) {
|
||||
Log.e("QueueInputStream", "Buffer overflow, discarding data");
|
||||
break;
|
||||
}
|
||||
queue_.add(data[i]);
|
||||
}
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public int available() throws IOException {
|
||||
return queue_.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
closed_ = true;
|
||||
}
|
||||
|
||||
}
|
||||
140
IOIOLib/src/ioio/lib/impl/SocketIOIOConnection.java
Executable file
140
IOIOLib/src/ioio/lib/impl/SocketIOIOConnection.java
Executable file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.api.exception.ConnectionLostException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class SocketIOIOConnection implements IOIOConnection {
|
||||
private final int port_;
|
||||
private ServerSocket server_ = null;
|
||||
private Socket socket_ = null;
|
||||
private boolean disconnect_ = false;
|
||||
private boolean server_owned_by_connect_ = true;
|
||||
private boolean socket_owned_by_connect_ = true;
|
||||
|
||||
public SocketIOIOConnection(Integer port) {
|
||||
port_ = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForConnect() throws ConnectionLostException {
|
||||
try {
|
||||
synchronized (this) {
|
||||
if (disconnect_) {
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
Log.d("SocketIOIOConnection", "Creating server socket");
|
||||
server_ = new ServerSocket(port_);
|
||||
server_owned_by_connect_ = false;
|
||||
}
|
||||
Log.d("SocketIOIOConnection", "Waiting for TCP connection");
|
||||
socket_ = server_.accept();
|
||||
Log.d("SocketIOIOConnection", "TCP connected");
|
||||
synchronized (this) {
|
||||
if (disconnect_) {
|
||||
socket_.close();
|
||||
throw new ConnectionLostException();
|
||||
}
|
||||
socket_owned_by_connect_ = false;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
synchronized (this) {
|
||||
disconnect_ = true;
|
||||
if (server_owned_by_connect_ && server_ != null) {
|
||||
try {
|
||||
server_.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("SocketIOIOConnection", "Unexpected exception", e1);
|
||||
}
|
||||
}
|
||||
if (socket_owned_by_connect_ && socket_ != null) {
|
||||
try {
|
||||
socket_.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("SocketIOIOConnection", "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?");
|
||||
}
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void disconnect() {
|
||||
if (disconnect_) {
|
||||
return;
|
||||
}
|
||||
Log.d("SocketIOIOConnection", "Client initiated disconnect");
|
||||
disconnect_ = true;
|
||||
if (!server_owned_by_connect_) {
|
||||
try {
|
||||
server_.close();
|
||||
} catch (IOException e1) {
|
||||
Log.e("SocketIOIOConnection", "Unexpected exception", e1);
|
||||
}
|
||||
}
|
||||
if (!socket_owned_by_connect_) {
|
||||
try {
|
||||
socket_.shutdownOutput();
|
||||
} catch (IOException e1) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws ConnectionLostException {
|
||||
try {
|
||||
return socket_.getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws ConnectionLostException {
|
||||
try {
|
||||
return socket_.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
throw new ConnectionLostException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
198
IOIOLib/src/ioio/lib/impl/SpiMasterImpl.java
Executable file
198
IOIOLib/src/ioio/lib/impl/SpiMasterImpl.java
Executable file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 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.SpiMaster;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.FlowControlledPacketSender.Packet;
|
||||
import ioio.lib.impl.FlowControlledPacketSender.Sender;
|
||||
import ioio.lib.impl.IncomingState.DataModuleListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class SpiMasterImpl extends AbstractResource implements SpiMaster,
|
||||
DataModuleListener, Sender {
|
||||
public class SpiResult implements Result {
|
||||
boolean ready_;
|
||||
final byte[] data_;
|
||||
|
||||
SpiResult(byte[] data) {
|
||||
data_ = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void waitReady() throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
while (!ready_ && state_ != State.DISCONNECTED) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
}
|
||||
}
|
||||
|
||||
class OutgoingPacket implements Packet {
|
||||
int writeSize_;
|
||||
byte[] writeData_;
|
||||
int ssPin_;
|
||||
int readSize_;
|
||||
int totalSize_;
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return writeSize_ + 4;
|
||||
}
|
||||
}
|
||||
|
||||
private final Queue<SpiResult> pendingRequests_ = new ConcurrentLinkedQueue<SpiMasterImpl.SpiResult>();
|
||||
private final FlowControlledPacketSender outgoing_ = new FlowControlledPacketSender(
|
||||
this);
|
||||
|
||||
private final int spiNum_;
|
||||
private final Map<Integer, Integer> ssPinToIndex_;
|
||||
private final int[] indexToSsPin_;
|
||||
private final int mosiPinNum_;
|
||||
private final int misoPinNum_;
|
||||
private final int clkPinNum_;
|
||||
|
||||
SpiMasterImpl(IOIOImpl ioio, int spiNum, int mosiPinNum, int misoPinNum,
|
||||
int clkPinNum, int[] ssPins) throws ConnectionLostException {
|
||||
super(ioio);
|
||||
spiNum_ = spiNum;
|
||||
mosiPinNum_ = mosiPinNum;
|
||||
misoPinNum_ = misoPinNum;
|
||||
clkPinNum_ = clkPinNum;
|
||||
indexToSsPin_ = ssPins.clone();
|
||||
ssPinToIndex_ = new HashMap<Integer, Integer>(ssPins.length);
|
||||
for (int i = 0; i < ssPins.length; ++i) {
|
||||
ssPinToIndex_.put(ssPins[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void disconnected() {
|
||||
super.disconnected();
|
||||
outgoing_.kill();
|
||||
for (SpiResult tr : pendingRequests_) {
|
||||
synchronized (tr) {
|
||||
tr.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeRead(int slave, byte[] writeData, int writeSize,
|
||||
int totalSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException, InterruptedException {
|
||||
Result result = writeReadAsync(slave, writeData, writeSize,
|
||||
totalSize, readData, readSize);
|
||||
result.waitReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiResult writeReadAsync(int slave, byte[] writeData,
|
||||
int writeSize, int totalSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
SpiResult result = new SpiResult(readData);
|
||||
|
||||
OutgoingPacket p = new OutgoingPacket();
|
||||
p.writeSize_ = writeSize;
|
||||
p.writeData_ = writeData;
|
||||
p.readSize_ = readSize;
|
||||
p.ssPin_ = indexToSsPin_[slave];
|
||||
p.totalSize_ = totalSize;
|
||||
|
||||
if (p.readSize_ > 0) {
|
||||
synchronized (this) {
|
||||
pendingRequests_.add(result);
|
||||
}
|
||||
} else {
|
||||
result.ready_ = true;
|
||||
}
|
||||
try {
|
||||
outgoing_.write(p);
|
||||
} catch (IOException e) {
|
||||
Log.e("SpiMasterImpl", "Exception caught", e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeRead(byte[] writeData, int writeSize, int totalSize,
|
||||
byte[] readData, int readSize) throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
writeRead(0, writeData, writeSize, totalSize, readData, readSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataReceived(byte[] data, int size) {
|
||||
SpiResult result = pendingRequests_.remove();
|
||||
synchronized (result) {
|
||||
result.ready_ = true;
|
||||
System.arraycopy(data, 0, result.data_, 0, size);
|
||||
result.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportAdditionalBuffer(int bytesRemaining) {
|
||||
outgoing_.readyToSend(bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
outgoing_.close();
|
||||
ioio_.closeSpi(spiNum_);
|
||||
ioio_.closePin(mosiPinNum_);
|
||||
ioio_.closePin(misoPinNum_);
|
||||
ioio_.closePin(clkPinNum_);
|
||||
for (int pin : indexToSsPin_) {
|
||||
ioio_.closePin(pin);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Packet packet) {
|
||||
OutgoingPacket p = (OutgoingPacket) packet;
|
||||
try {
|
||||
ioio_.protocol_.spiMasterRequest(spiNum_, p.ssPin_, p.writeData_,
|
||||
p.writeSize_, p.totalSize_, p.readSize_);
|
||||
} catch (IOException e) {
|
||||
Log.e("SpiImpl", "Caught exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
169
IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java
Executable file
169
IOIOLib/src/ioio/lib/impl/TwiMasterImpl.java
Executable file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.TwiMaster;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.FlowControlledPacketSender.Packet;
|
||||
import ioio.lib.impl.FlowControlledPacketSender.Sender;
|
||||
import ioio.lib.impl.IncomingState.DataModuleListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class TwiMasterImpl extends AbstractResource implements TwiMaster,
|
||||
DataModuleListener, Sender {
|
||||
class TwiResult implements Result {
|
||||
boolean ready_ = false;
|
||||
boolean success_;
|
||||
final byte[] data_;
|
||||
|
||||
public TwiResult(byte[] data) {
|
||||
data_ = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean waitReady() throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
while (!ready_ && state_ != State.DISCONNECTED) {
|
||||
wait();
|
||||
}
|
||||
checkState();
|
||||
return success_;
|
||||
}
|
||||
}
|
||||
|
||||
class OutgoingPacket implements Packet {
|
||||
int writeSize_;
|
||||
byte[] writeData_;
|
||||
boolean tenBitAddr_;
|
||||
int addr_;
|
||||
int readSize_;
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return writeSize_ + 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final Queue<TwiResult> pendingRequests_ = new ConcurrentLinkedQueue<TwiMasterImpl.TwiResult>();
|
||||
private final FlowControlledPacketSender outgoing_ = new FlowControlledPacketSender(
|
||||
this);
|
||||
private final int twiNum_;
|
||||
|
||||
TwiMasterImpl(IOIOImpl ioio, int twiNum) throws ConnectionLostException {
|
||||
super(ioio);
|
||||
twiNum_ = twiNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void disconnected() {
|
||||
super.disconnected();
|
||||
outgoing_.kill();
|
||||
for (TwiResult tr : pendingRequests_) {
|
||||
synchronized (tr) {
|
||||
tr.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeRead(int address, boolean tenBitAddr, byte[] writeData,
|
||||
int writeSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException, InterruptedException {
|
||||
Result result = writeReadAsync(address, tenBitAddr, writeData,
|
||||
writeSize, readData, readSize);
|
||||
return result.waitReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result writeReadAsync(int address, boolean tenBitAddr,
|
||||
byte[] writeData, int writeSize, byte[] readData, int readSize)
|
||||
throws ConnectionLostException {
|
||||
checkState();
|
||||
TwiResult result = new TwiResult(readData);
|
||||
|
||||
OutgoingPacket p = new OutgoingPacket();
|
||||
p.writeSize_ = writeSize;
|
||||
p.writeData_ = writeData;
|
||||
p.tenBitAddr_ = tenBitAddr;
|
||||
p.readSize_ = readSize;
|
||||
p.addr_ = address;
|
||||
|
||||
synchronized (this) {
|
||||
pendingRequests_.add(result);
|
||||
try {
|
||||
outgoing_.write(p);
|
||||
} catch (IOException e) {
|
||||
Log.e("SpiMasterImpl", "Exception caught", e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataReceived(byte[] data, int size) {
|
||||
TwiResult result = pendingRequests_.remove();
|
||||
synchronized (result) {
|
||||
result.ready_ = true;
|
||||
result.success_ = (size != 0xFF);
|
||||
if (result.success_) {
|
||||
System.arraycopy(data, 0, result.data_, 0, size);
|
||||
}
|
||||
result.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportAdditionalBuffer(int bytesRemaining) {
|
||||
outgoing_.readyToSend(bytesRemaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
outgoing_.close();
|
||||
ioio_.closeTwi(twiNum_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Packet packet) {
|
||||
OutgoingPacket p = (OutgoingPacket) packet;
|
||||
try {
|
||||
ioio_.protocol_.i2cWriteRead(twiNum_, p.tenBitAddr_, p.addr_,
|
||||
p.writeSize_, p.readSize_, p.writeData_);
|
||||
} catch (IOException e) {
|
||||
Log.e("TwiImpl", "Caught exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
IOIOLib/src/ioio/lib/impl/UartImpl.java
Executable file
107
IOIOLib/src/ioio/lib/impl/UartImpl.java
Executable file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.IOIO;
|
||||
import ioio.lib.api.Uart;
|
||||
import ioio.lib.api.exception.ConnectionLostException;
|
||||
import ioio.lib.impl.FlowControlledOutputStream.Sender;
|
||||
import ioio.lib.impl.IncomingState.DataModuleListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class UartImpl extends AbstractResource implements DataModuleListener, Sender, Uart {
|
||||
private static final int MAX_PACKET = 64;
|
||||
|
||||
private final int uartNum_;
|
||||
private final int rxPinNum_;
|
||||
private final int txPinNum_;
|
||||
private final FlowControlledOutputStream outgoing_ = new FlowControlledOutputStream(this, MAX_PACKET);
|
||||
private final QueueInputStream incoming_ = new QueueInputStream();
|
||||
|
||||
public UartImpl(IOIOImpl ioio, int txPin, int rxPin, int uartNum) throws ConnectionLostException {
|
||||
super(ioio);
|
||||
uartNum_ = uartNum;
|
||||
rxPinNum_ = rxPin;
|
||||
txPinNum_ = txPin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dataReceived(byte[] data, int size) {
|
||||
incoming_.write(data, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(byte[] data, int size) {
|
||||
try {
|
||||
ioio_.protocol_.uartData(uartNum_, size, data);
|
||||
} catch (IOException e) {
|
||||
Log.e("UartImpl", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void close() {
|
||||
super.close();
|
||||
incoming_.close();
|
||||
outgoing_.close();
|
||||
ioio_.closeUart(uartNum_);
|
||||
if (rxPinNum_ != IOIO.INVALID_PIN) {
|
||||
ioio_.closePin(rxPinNum_);
|
||||
}
|
||||
if (txPinNum_ != IOIO.INVALID_PIN) {
|
||||
ioio_.closePin(txPinNum_);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized public void disconnected() {
|
||||
super.disconnected();
|
||||
outgoing_.kill();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() {
|
||||
return incoming_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() {
|
||||
return outgoing_;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportAdditionalBuffer(int bytesRemaining) {
|
||||
outgoing_.readyToSend(bytesRemaining);
|
||||
}
|
||||
}
|
||||
295
IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java
Executable file
295
IOIOLib/src/ioio/lib/util/AbstractIOIOActivity.java
Executable file
@@ -0,0 +1,295 @@
|
||||
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 java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* A convenience class for easy creation of IOIO-based applications.
|
||||
*
|
||||
* It is used by creating a concrete 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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 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
|
||||
* {@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.
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractIOIOActivity extends Activity {
|
||||
private static final String TAG = "AbstractIOIOActivity";
|
||||
private IOIOConnectionSpec currentSpec_;
|
||||
private Collection<IOIOThread> threads_ = new LinkedList<IOIOThread>();
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onResume() if
|
||||
* overloaded. It takes care of connecting with the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
createAllThreads();
|
||||
startAllThreads();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should call this method from their own onPause() if
|
||||
* overloaded. It takes care of disconnecting from the IOIO.
|
||||
*/
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
abortAllThreads();
|
||||
try {
|
||||
joinAllThreads();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return An implementation of {@link IOIOThread}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
protected IOIOThread createIOIOThread() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should implement this method by returning a concrete subclass
|
||||
* of {@link IOIOThread}. This overload is useful in multi-IOIO scenarios,
|
||||
* where you want to identify which IOIO the thread is for. The provided
|
||||
* arguments should provide enough information to be unique per connection.
|
||||
* <code>null</code> may be returned if the client is not interested to
|
||||
* connect 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 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.
|
||||
*
|
||||
* @return An implementation of {@link IOIOThread}, or <code>null</code> to
|
||||
* skip.
|
||||
*/
|
||||
protected IOIOThread createIOIOThread(String connectionClass,
|
||||
Object[] connectionArgs) {
|
||||
return createIOIOThread();
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract class, which facilitates a thread dedicated for communication
|
||||
* with a single physical IOIO device.
|
||||
*/
|
||||
protected abstract class IOIOThread extends Thread {
|
||||
/** Subclasses should use this field for controlling the IOIO. */
|
||||
protected IOIO ioio_;
|
||||
private boolean abort_ = false;
|
||||
private boolean connected_ = true;
|
||||
private final IOIOConnectionSpec spec_ = currentSpec_;
|
||||
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to
|
||||
* be done once as soon as IOIO communication is established. Typically,
|
||||
* this will include opening pins and modules using the openXXX()
|
||||
* methods of the {@link #ioio_} field.
|
||||
*/
|
||||
protected void setup() 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.
|
||||
*/
|
||||
protected void loop() throws ConnectionLostException,
|
||||
InterruptedException {
|
||||
sleep(100000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* {@link #ioio_} member must not be used from within this method.
|
||||
*/
|
||||
protected void disconnected() throws InterruptedException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should override this method for performing operations to
|
||||
* be done if an incompatible IOIO firmware is detected. The
|
||||
* {@link #ioio_} member must not be used from within this method. This
|
||||
* method will only be called once, until a compatible IOIO is connected
|
||||
* (i.e. {@link #setup()} gets called).
|
||||
*/
|
||||
protected void incompatible() {
|
||||
}
|
||||
|
||||
/** Not relevant to subclasses. */
|
||||
@Override
|
||||
public final void run() {
|
||||
super.run();
|
||||
Looper.prepare();
|
||||
while (true) {
|
||||
try {
|
||||
synchronized (this) {
|
||||
if (abort_) {
|
||||
break;
|
||||
}
|
||||
ioio_ = IOIOFactory.create(spec_.className, spec_.args);
|
||||
}
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Not relevant to subclasses. */
|
||||
public synchronized final void abort() {
|
||||
abort_ = true;
|
||||
if (ioio_ != null) {
|
||||
ioio_.disconnect();
|
||||
}
|
||||
if (connected_) {
|
||||
interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void abortAllThreads() {
|
||||
for (IOIOThread thread : threads_) {
|
||||
thread.abort();
|
||||
}
|
||||
}
|
||||
|
||||
private void joinAllThreads() throws InterruptedException {
|
||||
for (IOIOThread thread : threads_) {
|
||||
thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
private void createAllThreads() {
|
||||
threads_.clear();
|
||||
Collection<IOIOConnectionSpec> specs = getConnectionSpecs();
|
||||
for (IOIOConnectionSpec spec : specs) {
|
||||
currentSpec_ = spec;
|
||||
IOIOThread thread = createIOIOThread(spec.className, spec.args);
|
||||
if (thread != null) {
|
||||
threads_.add(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startAllThreads() {
|
||||
for (IOIOThread thread : threads_) {
|
||||
thread.start();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
IOIOLib/src/ioio/lib/util/IOIOConnectionDiscovery.java
Normal file
17
IOIOLib/src/ioio/lib/util/IOIOConnectionDiscovery.java
Normal file
@@ -0,0 +1,17 @@
|
||||
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);
|
||||
}
|
||||
15
IOIOLib/src/ioio/lib/util/SocketIOIOConnectionDiscovery.java
Normal file
15
IOIOLib/src/ioio/lib/util/SocketIOIOConnectionDiscovery.java
Normal file
@@ -0,0 +1,15 @@
|
||||
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) }));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user