IOIO Over OpenAccessory Beta

ytai edited this page Feb 27, 2012 · 4 revisions

IOIO Over OpenAccessory Beta

As of IOIO firmware V3.21, OpenAccessory is no longer in Beta and is officially supported! The usage is slightly different (and simpler!) than the description below. This page is only kept here for backward reference. Please refer to the updated page.

OpenAccessory (commonly known as ADK) is a new (as of May 2011) protocol developed by Google, which enables a hack-free connection of peripherals to Android devices. The protocol is supported in Android 2.3.4 and higher. Naturally, it makes sense for IOIO to communicate with the Android device using this protocol now that it is available, avoiding the need for running the Android device with USB debugging enabled. In addition, the ADK connection also has some performance gains over ADB.

This is a first Beta release of IOIO over ADK. It is fully functional, but with some caveats you should be aware of. This release is intended for advances users, wishing to use this cool new functionality while willing to invest some more time in setting things up as early adopters. Installing this version will require a PIC programmer capable of programming PIC24FJ128DA206 (such as PICKit3). This Beta release will not be distributed as a bootloader-installed upgrade.

If you are one of the brave ones, your feedback will be highly appreciated. Please send it to the ioio-users list.

Caveats & Merits

Please understand the following caveats and limitations before jumping to re-programming your board:

  • Only Android 2.3.4 and higher supports OpenAccessory. Don't bother with older versions.
  • Only version 2.3.4 on Nexus S has been verified. Other versions may or may not work (your feedback welcome if you give it a try).
  • Due to problems with the accessory library implementation (i.e. the Android OS code supporting the protocol) - the IOIO connection will not be properly closed when pausing (and exiting) your IOIO app. When the app is resumed (restarted) it will hang. The current workaround is to physically disconnect and reconnect the IOIO (or power-cycle it).
  • When IOIO detects that a device supports ADK it will try to establish the app connection over ADK. Your existing apps will not detect the IOIO anymore. However, converting your existing apps to work with ADK is super-simple if you've written them based on AbstractIOIOActivity (information below).
  • Unlike the official IOIOLib, where extendingAbstractIOIOActivity is optional, in ADK mode extending the equivalent AbstractIOIOAdkActivity is the only way to go.
  • No efforts to maintain backward of forward compatibility with this Beta release will be made. Apps you write for this mode might need to be modified when the official release comes. However, such modifications are expected to be small, if any.

Having said all that, in practice, this mode works very well and give some nice improvements over ADB:

  • One-way average latency has improved from ~4ms to ~1ms.
  • Jitter (i.e. variance in latency) is much smaller.
  • Effective throughput has increased from ~300KB/s to ~600KB/s.
  • You can have the connecting of the IOIO automatically trigger your app of choice.
  • IOIO is not using ADB. So you can leave it off, and you should be able to use ADB over WiFi and debug your app while it is connected to the IOIO (not verified yet).

Downloading the Required Software

A zip file containing all the required software is here: https://github.com/ytai/ioio/raw/adk/release/ADK_Beta.zip
If you're interested in the source code, it is all on the adk branch of the repository.
If you want to return to the original firmware / software, download the latest version from the Downloads page.

Installing The Firmware

For this you will need a programmer, such as the PICKit3. A PICKit2 can be easily hacked to support the required chip. If anyone's interested, drop a note on the ioio-users list. You'll also need a programming software on your PC, such as this one (Windows only).

You need to connect 5 wires from the programmer to the IOIO board:

  • Programmer mclr to the mclr pin on the IOIO (the single pin in the area of pins 28, 29, 33, 34).
  • Programmer Vdd to the IOIO 3.3V.
  • Programmer Vss (GND) to the IOIO GND.
  • Programmer PGD to IOIO pin 38.
  • Programmer PGC to IOIO pin 37.

You you're using a PICKit, the pins on the 6-wire connector or the programmer are exactly in the order above, starting at the pin marked with an arrow and leaving the last pin unconnected.

Use the programming software to flash the file SPRK0015.hex or SPRK0016.hex' (depending on your board version), found in thefirmware` directory of the zip you downloaded earlier.

To go back to the stock firmware, download the latest version from the Downloads page.

If at this point you power the IOIO and connect it to your Android, you'll get a message about the IOIO being connected and be sent to a link on this Wiki site. This message will go away as soon as you install an application which advertises itself to be working with IOIO, and replaced with a message asking you which app you want to start.

Running HelloIOIO

In your zip file, under the software/applications directory is the HelloIOIO application, adapted for ADK. For your convenience, under the bin directory is a pre-built .apk file. You can install it using the command adb install HelloIOIO.apk from a command line. The adb application is typically under <android-sdk>/platform-tools. Alternately, you can import the source code to Eclipse and build it yourself, then install it using "Run as... > Android Application".

Writing an App from Scratch

Since converting an application written with the official IOIOLib to an ADK-compatible app, the recommended process is to write the app as you normally would, while extending AbstractIOIOActivity and then follow the conversion steps below. After you do it once or twice, you'll be able to write the app as ADK-compatible without this intermediate step. For more information on writing a IOIO app, see the User Guide.

Another simple approach is to copy HelloIOIO and modify it.

Converting an Existing App to Use ADK

The conversion process is very technical and simple. Once you have an app ready and extending AbstractIOIOActivity, follow these steps:

  • Import the IOIOLibAdk project from the zip file into your Eclipse workspace.
  • Right click your app's project > properties > Android tab:
    • Choose the "Google APIs" target API level 10 if using OS 2.3.4, or higher according to the device you are using.
    • In the library pane, click "Add..." and choose IOIOLibAdk.
  • Change your activity to extend AbstractIOIOAdkActivity instead of AbstractIOIOActivity.
  • Edit the AndroidManifest.xml file:
    • If you prefer manually editing the xml file, see an example file below.
    • In the Manifest tab, "Manifest Extras" pane: if you don't have a "Uses Sdk" node, add one. Set "Min SDK Version" on the right to 10 or later.
    • In the application tab, "application nodes" pane: "Add..." > "Create a new element..." > Users Library > Enter com.android.future.usb.accessory in the "name" box on the right.
    • In the application tab, "application nodes" pane: select the intent filter under your activity > "Add..." > Action > Enter android.hardware.usb.action.USB_ACCESSORY_ATTACHED in the "name" box on the right.
    • In the application tab, "application nodes" pane: select your activity > on the right, find the "Launch mode" setting (might need to scroll down) and set it to singleInstance.
    • In the application tab, "application nodes" pane: select your activity > "Add..." > Meta Data > set Name to android.hardware.usb.action.USB_ACCESSORY_ATTACHED and Resource to @xml/accessory_filter.
  • Under the res directory of your project, create a directory called xml. Create a file called accessory_filter.xml in this directory. Edit it to include the contents below.

The accessory_filter.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <usb-accessory model="IOIO" />
 </resources>

An example AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:a="http://schemas.android.com/apk/res/android"
      package="ioio.examples.hello"
      a:versionCode="1"
      a:versionName="1.0">
    <uses-sdk a:minSdkVersion="10" />
    <application a:icon="@drawable/icon" a:label="@string/app_name">
        <uses-library a:name="com.android.future.usb.accessory" />
        <activity a:name="MainActivity"
                  a:label="@string/app_name" a:launchMode="singleInstance">
            <intent-filter>
                <action a:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
                <action a:name="android.intent.action.MAIN" />
                <category a:name="android.intent.category.LAUNCHER" />
            </intent-filter>
                <meta-data a:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
                                  a:resource="@xml/accessory_filter" />
        </activity>
    </application>
</manifest>

Try it! Install the app on your Android device, connect a powered IOIO. If all goes well, you should get a dialog asking you which app to launch and your app should be there. Select it. It should now start using the IOIO.

Remember, if you exit the app and start it again it will hang. This is because of a problem in the Android OpenAccessory library preventing the app from gracefully closing the ADK connection. To work around this problem, detach and re-attach the IOIO when that happens (or power-cycle it). Another option is to force-close the app.