--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>AKBrobotADB</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.ammlab.android.akbrobotadb"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="4" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".AKBrobotADBActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+ <uses-permission android:name="android.permission.INTERNET"/>
+</manifest>
\ No newline at end of file
--- /dev/null
+/** Automatically generated file. DO NOT MODIFY */
+package org.ammlab.android.akbrobotadb;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = true;
+}
\ No newline at end of file
--- /dev/null
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package org.ammlab.android.akbrobotadb;
+
+public final class R {
+ public static final class array {
+ public static final int command1=0x7f050000;
+ public static final int portlist=0x7f050001;
+ }
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class id {
+ public static final int buttonain=0x7f06001b;
+ public static final int buttonaout=0x7f060021;
+ public static final int buttonconfig=0x7f060015;
+ public static final int buttondin=0x7f06001a;
+ public static final int buttondout=0x7f060020;
+ public static final int editOutput=0x7f06001f;
+ public static final int label1=0x7f060001;
+ public static final int label2=0x7f060005;
+ public static final int label3=0x7f060009;
+ public static final int label4=0x7f06000c;
+ public static final int label5=0x7f06000e;
+ public static final int label6=0x7f060012;
+ public static final int label7=0x7f060017;
+ public static final int label8=0x7f06001d;
+ public static final int label9=0x7f060010;
+ public static final int labelinvalue=0x7f060019;
+ public static final int seekBar1=0x7f060002;
+ public static final int seekBar2=0x7f060006;
+ public static final int seekBar3=0x7f06000a;
+ public static final int spinner1=0x7f060013;
+ public static final int spinner2=0x7f060014;
+ public static final int spinner3=0x7f060018;
+ public static final int spinner4=0x7f06001e;
+ public static final int tableRow01=0x7f060000;
+ public static final int tableRow02=0x7f060004;
+ public static final int tableRow03=0x7f060008;
+ public static final int tableRow11=0x7f060011;
+ public static final int tableRow12=0x7f060016;
+ public static final int tableRow13=0x7f06001c;
+ public static final int textView1=0x7f060003;
+ public static final int textView2=0x7f060007;
+ public static final int textView3=0x7f06000b;
+ public static final int toggleButton1=0x7f06000d;
+ public static final int toggleButton2=0x7f06000f;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040000;
+ public static final int labelmotor1=0x7f040003;
+ public static final int labelmotor2=0x7f040004;
+ public static final int labelrelay1=0x7f040001;
+ public static final int labelrelay2=0x7f040002;
+ public static final int labelservo1=0x7f040005;
+ }
+}
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-4
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+ android:layout_width="fill_parent" android:layout_height="fill_parent"\r
+ android:orientation="vertical">\r\r <TableLayout android:layout_width="fill_parent"\r android:layout_height="wrap_content" android:stretchColumns="1">\r
+\r
+ <TableRow android:id="@+id/tableRow01" android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label1" android:text="@string/labelmotor1" />\r
+ <SeekBar android:id="@+id/seekBar1" />\r
+ <TextView android:id="@+id/textView1" android:text="000" />\r
+ </TableRow>\r
+\r
+\r
+ <TableRow android:id="@+id/tableRow02" android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label2" android:text="@string/labelmotor2" />\r
+ <SeekBar android:id="@+id/seekBar2" />\r
+ <TextView android:id="@+id/textView2" android:text="000" />\r
+ </TableRow>\r
+\r
+\r
+ <TableRow android:id="@+id/tableRow03" android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label3" android:text="@string/labelservo1" />\r
+ <SeekBar android:id="@+id/seekBar3" />\r
+ <TextView android:id="@+id/textView3" android:text="090" />\r
+ </TableRow>\r
+\r
+\r
+ </TableLayout>\r
+\r
+ <LinearLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label4" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="@string/labelrelay1" />\r
+ <ToggleButton android:id="@+id/toggleButton1"\r
+ android:layout_width="wrap_content" android:layout_height="wrap_content" />\r
+ </LinearLayout>\r
+ <LinearLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label5" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="@string/labelrelay2" />\r
+ <ToggleButton android:id="@+id/toggleButton2"\r
+ android:layout_width="wrap_content" android:layout_height="wrap_content" />\r
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="20dp" />\r
+\r
+ <LinearLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content">\r
+\r
+ <TextView android:id="@+id/label9" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Primitive Operation" />\r
+ </LinearLayout>\r
+ <TableLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:stretchColumns="*">\r
+\r
+ <TableRow android:id="@+id/tableRow11" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:gravity="center_vertical">\r
+ <TextView android:id="@+id/label6" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Config" />\r
+ <Spinner android:id="@+id/spinner1" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/portlist" />\r
+ <Spinner android:id="@+id/spinner2" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/command1" />\r
+ <Button android:id="@+id/buttonconfig" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="Set" />\r
+ </TableRow>\r
+\r
+ <TableRow android:id="@+id/tableRow12" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:gravity="center_vertical">\r
+\r
+ <TextView android:id="@+id/label7" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Input" />\r
+ <Spinner android:id="@+id/spinner3" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/portlist" />\r
+ <TextView android:id="@+id/labelinvalue"\r
+ android:layout_width="wrap_content" android:layout_height="wrap_content" \r
+ android:text=" "/>\r
+ <Button android:id="@+id/buttondin" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="D In" />\r
+ <Button android:id="@+id/buttonain" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="A In" />\r
+ </TableRow>\r
+\r
+ <TableRow android:id="@+id/tableRow13" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:gravity="center_vertical">\r
+\r
+ <TextView android:id="@+id/label8" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Output" />\r
+ <Spinner android:id="@+id/spinner4" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/portlist" />\r
+ <EditText android:id="@+id/editOutput" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:inputType="number"\r
+ android:singleLine="true" />\r
+\r
+ <Button android:id="@+id/buttondout" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="D Out" />\r
+ <Button android:id="@+id/buttonaout" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="A Out" />\r
+ </TableRow>\r
+ </TableLayout>\r
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">AKBrobotADB</string>
+ <string name="labelrelay1">Relay1</string>
+ <string name="labelrelay2">Relay2</string>
+ <string name="labelmotor1">Motor1</string>
+ <string name="labelmotor2">Motor2</string>
+ <string name="labelservo1">Servo1</string>
+ <string-array name="command1">
+ <item>D Out</item>
+ <item>A Out</item>
+ <item>D In</item>
+ <item>A In</item>
+ </string-array>
+ <string-array name="portlist">
+ <item>D0</item>
+ <item>D1</item>
+ <item>D2</item>
+ <item>D3</item>
+ <item>D4</item>
+ <item>D5</item>
+ <item>D6</item>
+ <item>A0</item>
+ <item>A1</item>
+ <item>A2</item>
+ <item>A3</item>
+ <item>A4</item>
+ <item>A5</item>
+ </string-array>
+</resources>
\ No newline at end of file
--- /dev/null
+/*
+ Copyright 2012 JAG-AKIBA
+
+ 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 org.ammlab.android.akbrobotadb;
+
+import java.io.IOException;
+
+import android.app.Activity;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+import org.microbridge.server.AbstractServerListener;
+import org.microbridge.server.Client;
+import org.microbridge.server.Server;
+
+
+public class AKBrobotADBActivity extends Activity implements OnClickListener {
+ private static final String TAG = "AKBrobotADB";
+ private Server server = null;
+
+ private ToggleButton mToggleButton1;
+ private ToggleButton mToggleButton2;
+ private SeekBar mSeekBar1;
+ private SeekBar mSeekBar2;
+ private SeekBar mSeekBar3;
+ private TextView mText1;
+ private TextView mText2;
+ private TextView mText3;
+ private TextView mInValue;
+ private EditText mEditOutput;
+ private Spinner mSpinner1;
+ private Spinner mSpinner2;
+ private Spinner mSpinner3;
+ private Spinner mSpinner4;
+ private Button mButtonConfig;
+ private Button mButtonDin;
+ private Button mButtonAin;
+ private Button mButtonDout;
+ private Button mButtonAout;
+
+ private byte[] mRecvBuff = new byte[4];
+
+ private static final int MESSAGE_INPUTVAL = 1;
+ private static final int MESSAGE_CONNECT = 2;
+ private static final int MESSAGE_DISCONNECT = 3;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ mToggleButton1 = (ToggleButton) findViewById(R.id.toggleButton1);
+ mToggleButton2 = (ToggleButton) findViewById(R.id.toggleButton2);
+ mSeekBar1 = (SeekBar) findViewById(R.id.seekBar1);
+ mSeekBar2 = (SeekBar) findViewById(R.id.seekBar2);
+ mSeekBar3 = (SeekBar) findViewById(R.id.seekBar3);
+ mSeekBar1.setProgress(50);
+ mSeekBar2.setProgress(50);
+ mSeekBar3.setProgress(50);
+
+ mText1 = (TextView) findViewById(R.id.textView1);
+ mText2 = (TextView) findViewById(R.id.textView2);
+ mText3 = (TextView) findViewById(R.id.textView3);
+ mInValue = (TextView) findViewById(R.id.labelinvalue);
+
+ mEditOutput = (EditText) findViewById(R.id.editOutput);
+
+ mSpinner1 = (Spinner) findViewById(R.id.spinner1);
+ mSpinner2 = (Spinner) findViewById(R.id.spinner2);
+ mSpinner3 = (Spinner) findViewById(R.id.spinner3);
+ mSpinner4 = (Spinner) findViewById(R.id.spinner4);
+
+ mButtonConfig = (Button)findViewById(R.id.buttonconfig);
+ mButtonDin = (Button)findViewById(R.id.buttondin);
+ mButtonAin = (Button)findViewById(R.id.buttonain);
+ mButtonDout = (Button)findViewById(R.id.buttondout);
+ mButtonAout = (Button)findViewById(R.id.buttonaout);
+
+ mButtonConfig.setOnClickListener(this);
+ mButtonDin.setOnClickListener(this);
+ mButtonAin.setOnClickListener(this);
+ mButtonDout.setOnClickListener(this);
+ mButtonAout.setOnClickListener(this);
+
+ //\83V\81[\83N\83o\81[\82ð\95Ï\8dX\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89
+ //for motor#0
+ mSeekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = 0;
+ byte direction = 0;
+ if( progress > 45 && progress < 55){
+ value = 0;
+ }else if(progress > 50){
+ value = ((progress - 50) * 255 / 50);
+ direction = 0;
+ }else{ //progress < 50
+ value = ((50 - progress) * 255 / 50);
+ direction = 1;
+ }
+ mText1.setText(String.format("%d", value));
+ sendCommand((byte)3,(byte)0,direction,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83j\83\85\81[\83g\83\89\83\8b
+ mSeekBar1.setProgress(50);
+ //motor#1\92â\8e~
+ sendCommand((byte)3,(byte)0,(byte)0,(byte)0);
+ }
+ });
+ //for motor#1
+ mSeekBar2.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = 0;
+ byte direction = 0;
+ if( progress > 45 && progress < 55){
+ value = 0;
+ }else if(progress > 50){
+ value = ((progress - 50) * 255 / 50);
+ direction = 0;
+ }else{ //progress < 50
+ value = ((50 - progress) * 255 / 50);
+ direction = 1;
+ }
+ mText2.setText(String.format("%d", value));
+ sendCommand((byte)3,(byte)1,direction,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83j\83\85\81[\83g\83\89\83\8b
+ mSeekBar2.setProgress(50);
+ //motor#1\92â\8e~
+ sendCommand((byte)3,(byte)1,(byte)0,(byte)0);
+ }
+ });
+
+ //for servo#0
+ mSeekBar3.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = (180*progress/100);
+ mText3.setText(String.format("%d", value));
+ Log.d(TAG, "Servo0:"+value+","+(byte)value);
+ sendCommand((byte)5,(byte)0,(byte)0,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83Z\83\93\83^\81[\82É
+ mSeekBar3.setProgress(50);
+ sendCommand((byte)5,(byte)0,(byte)0,(byte)90);
+ }
+ });
+ //\83{\83^\83\93\82ð\89\9f\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89(\83{\83^\83\931)
+ mToggleButton1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ sendCommand((byte)4,(byte)0,(byte)0,(byte)(isChecked ? 0x1 : 0x0));
+ }
+ });
+ //\83{\83^\83\93\82ð\89\9f\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89(\83{\83^\83\932)
+ mToggleButton2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ sendCommand((byte)4,(byte)1,(byte)0,(byte)(isChecked ? 0x1 : 0x0));
+ }
+ });
+
+ // Create TCP server
+ try
+ {
+ server = new Server(4567);
+ server.start();
+ } catch (IOException e)
+ {
+ Log.e(TAG, "Unable to start TCP server", e);
+ System.exit(-1);
+ }
+
+ server.addListener(new AbstractServerListener() {
+ @Override
+ public void onReceive(org.microbridge.server.Client client, byte[] data)
+ {
+ Log.d(TAG, "data received:"+data.length);
+ if (data.length<4) return;
+ Message m = Message.obtain(mHandler, MESSAGE_INPUTVAL);
+ synchronized (this) {
+ mRecvBuff[0] = data[0];
+ mRecvBuff[1] = data[1];
+ mRecvBuff[2] = data[2];
+ mRecvBuff[3] = data[3];
+ }
+ Log.d(TAG, "data received:"+data[0]+","+data[1]+","+data[2]+","+data[3]);
+ mHandler.sendMessage(m);
+ };
+ @Override
+ public void onClientConnect(Server server, Client client)
+ {
+ Message m = Message.obtain(mHandler, MESSAGE_CONNECT);
+ mHandler.sendMessage(m);
+ }
+ @Override
+ public void onClientDisconnect(Server server, Client client)
+ {
+ Message m = Message.obtain(mHandler, MESSAGE_DISCONNECT);
+ mHandler.sendMessage(m);
+ }
+ });
+
+ enableControls(false);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if(! server.isRunning()){
+ try
+ {
+ server.start();
+ } catch (IOException e)
+ {
+ Log.e(TAG, "Unable to start TCP server", e);
+ }
+ }
+ }
+
+ @Override
+ protected void onPause()
+ {
+ super.onPause();
+ if(server.isRunning())
+ {
+ server.stop();
+ }
+ }
+
+ public void sendCommand(byte command1, byte command2, byte value1, byte value2) {
+ byte[] buffer = new byte[4];
+ buffer[0] = command1;
+ buffer[1] = command2;
+ buffer[2] = value1;
+ buffer[3] = value2;
+ try
+ {
+ server.send(buffer);
+ } catch (IOException e)
+ {
+ Log.e(TAG, "problem sending TCP message", e);
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if( view == mButtonConfig ){
+ long port = mSpinner1.getSelectedItemId();
+ long mode = mSpinner2.getSelectedItemId();
+ byte p = getPort(port, 256);
+ Log.d(TAG, "Primitive:"+port+","+p+","+mode);
+ sendCommand((byte)0, p, (byte)0, (byte)mode);
+ }else if( view == mButtonDout){
+ long port = mSpinner4.getSelectedItemId();
+ String value = mEditOutput.getText().toString();
+ byte p = getPort(port, 0);
+ if( value != null && value.length() > 0){
+ byte v = (byte)(int)Integer.valueOf(value);
+ Log.d(TAG, "DigitalOut:"+port+","+p+","+v);
+ sendCommand((byte)1, p, (byte)0, (byte)v);
+ }
+ }else if( view == mButtonAout){
+ long port = mSpinner4.getSelectedItemId();
+ String value = mEditOutput.getText().toString();
+ byte p = getPort(port, 1);
+ if( value != null && value.length() > 0){
+ byte v = (byte)(int)Integer.valueOf(value);
+ Log.d(TAG, "AnalogOut:"+port+","+p+","+v);
+ sendCommand((byte)1, p, (byte)0, (byte)v);
+ }
+ }else if( view == mButtonDin){
+ long port = mSpinner3.getSelectedItemId();
+ byte p = getPort(port, 2);
+ sendCommand((byte)2, p, (byte)0, (byte)0);
+ Log.d(TAG, "DigitalIn:"+port+","+p);
+ }else if( view == mButtonAin){
+ long port = mSpinner3.getSelectedItemId();
+ byte p = getPort(port, 3);
+ sendCommand((byte)2, p, (byte)0, (byte)0);
+ Log.d(TAG, "AnalogIn:"+port+","+p);
+ }else{
+ Log.d(TAG, "Ignore click:"+view.toString());
+ }
+ }
+
+ private byte getPort(long port, long type){//type(0:DigitalOut, 1:AnalogOut, 2:DigitalIn, 3:AnalogIn, 256:config)
+ byte ConfigPort=-1;
+ long limitDigtal = 6;
+ if(type == 0 || type == 2 || type == 256){ //Digital Port
+ if(port > limitDigtal){ //Analog Port
+ ConfigPort = (byte) (port - limitDigtal -1 + 0x40);
+ }else{
+ ConfigPort = (byte) port;
+ }
+ }else if( type == 1 ){//Analog Out Port
+ ConfigPort = (byte)(port + 0x80);
+ }else{ //AnalogIn Port
+ if( port > limitDigtal){
+ ConfigPort = (byte)(port - limitDigtal -1 + 0x80);
+ }
+ }
+ return ConfigPort;
+ }
+ // UI \83X\83\8c\83b\83h\82Å\89æ\96Ê\8fã\82Ì\95\\8e¦\82ð\95Ï\8dX
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_INPUTVAL:
+ int val=0;
+ synchronized (this) {
+ val = mRecvBuff[2] & 0xff;
+ val = val * 256 + (mRecvBuff[3] & 0xff);
+ }
+ mInValue.setText(String.valueOf(val));
+ break;
+ case MESSAGE_CONNECT:
+ enableControls(true);
+ break;
+ case MESSAGE_DISCONNECT:
+ enableControls(false);
+ break;
+ }
+ }
+ };
+
+ // \90Ú\91±\8fó\91Ô\95\\8e¦(\83^\83C\83g\83\8b\83o\81[)
+ private void enableControls(boolean enable) {
+ Resources res = getResources();
+ String titleString = res.getString(R.string.app_name);
+
+ if (enable) {
+ setTitle(titleString + " - connected");
+ } else {
+ setTitle(titleString + " - not connected");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.microbridge.server;
+
+/**
+ *
+ * Base class for implementing a ServerListener. Extend this class to capture a subset of the server events.
+ *
+ * @author Niels Brouwers
+ *
+ */
+public class AbstractServerListener implements ServerListener
+{
+
+ public void onServerStarted(Server server)
+ {
+ }
+
+ public void onServerStopped(Server server)
+ {
+ }
+
+ public void onClientConnect(Server server, Client client)
+ {
+ }
+
+ public void onClientDisconnect(Server server, Client client)
+ {
+ }
+
+ public void onReceive(Client client, byte[] data)
+ {
+ }
+
+}
--- /dev/null
+package org.microbridge.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.SocketException;
+
+import android.util.Log;
+
+public class Client
+{
+
+ private Socket socket;
+
+ private final Server server;
+
+ private final InputStream input;
+ private final OutputStream output;
+
+ private boolean keepAlive = true;
+
+ public Client(Server server, Socket socket) throws IOException
+ {
+ this.server = server;
+ this.socket = socket;
+ socket.setKeepAlive(true);
+
+ this.input = this.socket.getInputStream();
+ this.output = this.socket.getOutputStream();
+
+ startCommunicationThread();
+ }
+
+ public void startCommunicationThread()
+ {
+ (new Thread() {
+ public void run()
+ {
+ while (keepAlive)
+ {
+ try
+ {
+
+ // Check for input
+ if (input.available()>0)
+ {
+
+ int bytesRead;
+ byte buf[] = new byte[input.available()];
+ bytesRead = input.read(buf);
+
+ if (bytesRead==-1)
+ keepAlive = false;
+ else
+ server.receive(Client.this, buf);
+ }
+
+ } catch (IOException e)
+ {
+ keepAlive = false;
+ Log.d("microbridge", "IOException: " + e);
+ }
+ }
+
+ // Client exited, notify parent server
+ server.disconnectClient(Client.this);
+ }
+ }).start();
+ }
+
+ public void close()
+ {
+ keepAlive = false;
+
+ // Close the socket, will throw an IOException in the listener thread.
+ try
+ {
+ socket.close();
+ } catch (IOException e)
+ {
+ Log.e("microbridge", "error while closing socket", e);
+ }
+ }
+
+ public void send(byte[] data) throws IOException
+ {
+ try {
+ output.write(data);
+ output.flush();
+ } catch (SocketException ex)
+ {
+ // Broken socket, disconnect
+ close();
+ server.disconnectClient(this);
+ }
+ }
+
+ public void send(String command) throws IOException
+ {
+ send(command.getBytes());
+ }
+
+}
--- /dev/null
+package org.microbridge.server;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.util.HashSet;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Lightweight TCP server that supports multiple clients connecting on a given port.
+ *
+ * @author Niels Brouwers
+ *
+ */
+public class Server
+{
+
+ // Server socket for the TCP connection
+ private ServerSocket serverSocket = null;
+
+ // TCP port to use
+ private final int port;
+
+ // List of connected clients. Concurrency-safe arraylist because Clients can join/leave at any point,
+ // which means inserts/removes can occur at any time from different threads.
+ private CopyOnWriteArrayList<Client> clients = new CopyOnWriteArrayList<Client>();
+
+ // Set of event listeners for this server
+ private HashSet<ServerListener> listeners = new HashSet<ServerListener>();
+
+ // Indicates that the main server loop should keep running.
+ private boolean keepAlive = true;
+
+ // Main thread.
+ private Thread listenThread;
+
+ /**
+ * Constructs a new server instance on port 4567.
+ */
+ public Server()
+ {
+ this(4567);
+ }
+
+ /**
+ * Constructs a new server instance.
+ * @param port TCP port to use.
+ */
+ public Server(int port)
+ {
+ this.port = port;
+ }
+
+ /**
+ * @return TCP port this server accepts connections on.
+ */
+ public int getPort()
+ {
+ return port;
+ }
+
+ /**
+ * @return true iff the server is running.
+ */
+ public boolean isRunning()
+ {
+ return listenThread!=null && listenThread.isAlive();
+ }
+
+ /**
+ * @return the number of currently connected clients
+ */
+ public int getClientCount()
+ {
+ return clients.size();
+ }
+
+ /**
+ * Starts the server.
+ * @throws IOException
+ */
+ public void start() throws IOException
+ {
+ keepAlive = true;
+ serverSocket = new ServerSocket(port);
+
+ (listenThread = new Thread(){
+ public void run()
+ {
+ Socket socket;
+ try
+ {
+ while (keepAlive)
+ {
+
+ try {
+
+ socket = serverSocket.accept();
+
+ // Create Client object.
+ Client client = new Client(Server.this, socket);
+ clients.add(client);
+
+ // Notify listeners.
+ for (ServerListener listener : listeners)
+ listener.onClientConnect(Server.this, client);
+
+ } catch (SocketException ex)
+ {
+ // A SocketException is thrown when the stop method calls 'close' on the
+ // serverSocket object. This means we should break out of the connection
+ // accept loop.
+ keepAlive = false;
+ }
+
+ }
+
+ } catch (IOException e)
+ {
+ // TODO
+ }
+ }
+ }).start();
+
+ // Notify listeners.
+ for (ServerListener listener : listeners)
+ listener.onServerStarted(this);
+
+ }
+
+ /**
+ * Stops the server
+ */
+ public void stop()
+ {
+ // Stop listening in the TCP port.
+ if (serverSocket!=null)
+ try
+ {
+ serverSocket.close();
+ } catch (IOException e)
+ {
+ // TODO
+ }
+
+ // Close all clients.
+ for (Client client : clients)
+ client.close();
+
+ // Notify listeners.
+ for (ServerListener listener : listeners)
+ listener.onServerStopped(this);
+
+ }
+
+ /**
+ * Called by the Client class to remove itself from the server.
+ *
+ * @param client Client to disconnect
+ */
+ protected void disconnectClient(Client client)
+ {
+ this.clients.remove(client);
+
+ for (ServerListener listener : listeners)
+ listener.onClientDisconnect(Server.this, client);
+ }
+
+ /**
+ * Fires the receive event. Called by the client when it has new data to offer.
+ *
+ * @param client source client
+ * @param data data
+ */
+ protected void receive(Client client, byte data[])
+ {
+ // Notify listeners.
+ for (ServerListener listener : listeners)
+ listener.onReceive(client, data);
+ }
+
+ /**
+ * Adds a server listener to the server
+ * @param listener a ServerListener instance
+ */
+ public void addListener(ServerListener listener)
+ {
+ this.listeners.add(listener);
+ }
+
+ /**
+ * Removes a server listener from the server
+ * @param listener a ServerListener instance
+ */
+ public void removeListener(ServerListener listener)
+ {
+ this.listeners.remove(listener);
+ }
+
+ /**
+ * Send bytes to all connected clients.
+ *
+ * @param data data to send
+ * @throws IOException
+ */
+ public void send(byte[] data) throws IOException
+ {
+ for (Client client : clients)
+ client.send(data);
+ }
+
+ /**
+ * Send a string to all connected clients
+ * @param str string to send
+ * @throws IOException
+ */
+ public void send(String str) throws IOException
+ {
+ for (Client client : clients)
+ client.send(str);
+ }
+
+}
--- /dev/null
+package org.microbridge.server;
+
+/**
+ *
+ * Server listener interface.
+ *
+ * @author Niels Brouwers
+ *
+ */
+public interface ServerListener
+{
+
+ /**
+ * Called when the server is started.
+ * @param server the server that is started
+ */
+ public void onServerStarted(Server server);
+
+ /**
+ * Called when the server is stopped.
+ * @param server the server that is stopped
+ */
+ public void onServerStopped(Server server);
+
+ /**
+ * Called when a new client (device) connects to the server.
+ * @param server the server that is started
+ * @param client the Client object representing the newly connected client
+ */
+ public void onClientConnect(Server server, Client client);
+
+ /**
+ * Called when a new client (device) disconnects from the server.
+ * @param server the server that is started
+ * @param client the Client that disconnected
+ */
+ public void onClientDisconnect(Server server, Client client);
+
+ /**
+ * Called when data is received from the client.
+ * @param client source client
+ * @param data data
+ */
+ public void onReceive(Client client, byte data[]);
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>AKBrobotADK</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.ammlab.android.akbrobotadk"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="10" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <uses-library android:name="com.android.future.usb.accessory" />
+ <activity
+ android:name="org.ammlab.android.akbrobotadk.AKBrobotADKActivity"
+ android:label="@string/app_name" android:screenOrientation="portrait">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter >
+ <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
+ android:resource="@xml/accessory_filter" />
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+/** Automatically generated file. DO NOT MODIFY */
+package org.ammlab.android.akbrobotadk;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = true;
+}
\ No newline at end of file
--- /dev/null
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package org.ammlab.android.akbrobotadk;
+
+public final class R {
+ public static final class array {
+ public static final int command1=0x7f060000;
+ public static final int portlist=0x7f060001;
+ }
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class id {
+ public static final int buttonain=0x7f07001b;
+ public static final int buttonaout=0x7f070021;
+ public static final int buttonconfig=0x7f070015;
+ public static final int buttondin=0x7f07001a;
+ public static final int buttondout=0x7f070020;
+ public static final int editOutput=0x7f07001f;
+ public static final int label1=0x7f070001;
+ public static final int label2=0x7f070005;
+ public static final int label3=0x7f070009;
+ public static final int label4=0x7f07000c;
+ public static final int label5=0x7f07000e;
+ public static final int label6=0x7f070012;
+ public static final int label7=0x7f070017;
+ public static final int label8=0x7f07001d;
+ public static final int label9=0x7f070010;
+ public static final int labelinvalue=0x7f070019;
+ public static final int seekBar1=0x7f070002;
+ public static final int seekBar2=0x7f070006;
+ public static final int seekBar3=0x7f07000a;
+ public static final int spinner1=0x7f070013;
+ public static final int spinner2=0x7f070014;
+ public static final int spinner3=0x7f070018;
+ public static final int spinner4=0x7f07001e;
+ public static final int tableRow01=0x7f070000;
+ public static final int tableRow02=0x7f070004;
+ public static final int tableRow03=0x7f070008;
+ public static final int tableRow11=0x7f070011;
+ public static final int tableRow12=0x7f070016;
+ public static final int tableRow13=0x7f07001c;
+ public static final int textView1=0x7f070003;
+ public static final int textView2=0x7f070007;
+ public static final int textView3=0x7f07000b;
+ public static final int toggleButton1=0x7f07000d;
+ public static final int toggleButton2=0x7f07000f;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f050000;
+ public static final int labelmotor1=0x7f050003;
+ public static final int labelmotor2=0x7f050004;
+ public static final int labelrelay1=0x7f050001;
+ public static final int labelrelay2=0x7f050002;
+ public static final int labelservo1=0x7f050005;
+ }
+ public static final class xml {
+ public static final int accessory_filter=0x7f040000;
+ }
+}
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=Google Inc.:Google APIs:10
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\r
+ android:layout_width="fill_parent" android:layout_height="fill_parent"\r
+ android:orientation="vertical">\r\r <TableLayout android:layout_width="fill_parent"\r android:layout_height="wrap_content" android:stretchColumns="1">\r
+\r
+ <TableRow android:id="@+id/tableRow01" android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label1" android:text="@string/labelmotor1" />\r
+ <SeekBar android:id="@+id/seekBar1" />\r
+ <TextView android:id="@+id/textView1" android:text="000" />\r
+ </TableRow>\r
+\r
+\r
+ <TableRow android:id="@+id/tableRow02" android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label2" android:text="@string/labelmotor2" />\r
+ <SeekBar android:id="@+id/seekBar2" />\r
+ <TextView android:id="@+id/textView2" android:text="000" />\r
+ </TableRow>\r
+\r
+\r
+ <TableRow android:id="@+id/tableRow03" android:layout_width="fill_parent"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label3" android:text="@string/labelservo1" />\r
+ <SeekBar android:id="@+id/seekBar3" />\r
+ <TextView android:id="@+id/textView3" android:text="090" />\r
+ </TableRow>\r
+\r
+\r
+ </TableLayout>\r
+\r
+ <LinearLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label4" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="@string/labelrelay1" />\r
+ <ToggleButton android:id="@+id/toggleButton1"\r
+ android:layout_width="wrap_content" android:layout_height="wrap_content" />\r
+ </LinearLayout>\r
+ <LinearLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content">\r
+ <TextView android:id="@+id/label5" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="@string/labelrelay2" />\r
+ <ToggleButton android:id="@+id/toggleButton2"\r
+ android:layout_width="wrap_content" android:layout_height="wrap_content" />\r
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="20dp" />\r
+\r
+ <LinearLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content">\r
+\r
+ <TextView android:id="@+id/label9" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Primitive Operation" />\r
+ </LinearLayout>\r
+ <TableLayout android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:stretchColumns="*">\r
+\r
+ <TableRow android:id="@+id/tableRow11" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:gravity="center_vertical">\r
+ <TextView android:id="@+id/label6" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Config" />\r
+ <Spinner android:id="@+id/spinner1" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/portlist" />\r
+ <Spinner android:id="@+id/spinner2" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/command1" />\r
+ <Button android:id="@+id/buttonconfig" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="Set" />\r
+ </TableRow>\r
+\r
+ <TableRow android:id="@+id/tableRow12" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:gravity="center_vertical">\r
+\r
+ <TextView android:id="@+id/label7" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Input" />\r
+ <Spinner android:id="@+id/spinner3" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/portlist" />\r
+ <TextView android:id="@+id/labelinvalue"\r
+ android:layout_width="wrap_content" android:layout_height="wrap_content" \r
+ android:text=" "/>\r
+ <Button android:id="@+id/buttondin" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="D In" />\r
+ <Button android:id="@+id/buttonain" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="A In" />\r
+ </TableRow>\r
+\r
+ <TableRow android:id="@+id/tableRow13" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:gravity="center_vertical">\r
+\r
+ <TextView android:id="@+id/label8" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:text="Output" />\r
+ <Spinner android:id="@+id/spinner4" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:entries="@array/portlist" />\r
+ <EditText android:id="@+id/editOutput" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" android:inputType="number"\r
+ android:singleLine="true" />\r
+\r
+ <Button android:id="@+id/buttondout" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="D Out" />\r
+ <Button android:id="@+id/buttonaout" android:layout_width="wrap_content"\r
+ android:layout_height="wrap_content" style="?android:attr/buttonStyleSmall"\r
+ android:text="A Out" />\r
+ </TableRow>\r
+ </TableLayout>\r
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">AKBrobotADK</string>
+ <string name="labelrelay1">Relay1</string>
+ <string name="labelrelay2">Relay2</string>
+ <string name="labelmotor1">Motor1</string>
+ <string name="labelmotor2">Motor2</string>
+ <string name="labelservo1">Servo1</string>
+ <string-array name="command1">
+ <item>D Out</item>
+ <item>A Out</item>
+ <item>D In</item>
+ <item>A In</item>
+ </string-array>
+ <string-array name="portlist">
+ <item>D0</item>
+ <item>D1</item>
+ <item>D2</item>
+ <item>D3</item>
+ <item>D4</item>
+ <item>D5</item>
+ <item>D6</item>
+ <item>A0</item>
+ <item>A1</item>
+ <item>A2</item>
+ <item>A3</item>
+ <item>A4</item>
+ <item>A5</item>
+ </string-array>
+</resources>
\ No newline at end of file
--- /dev/null
+<!--?xml version="1.0" encoding="utf-8"?-->
+<resources>
+ <usb-accessory manufacturer="JAG-AKIBA" model="CoreModule01" version="1.0" />
+</resources>
--- /dev/null
+/*
+ Copyright 2012 JAG-AKIBA
+
+ 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 org.ammlab.android.akbrobotadk;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import com.android.future.usb.UsbAccessory;
+import com.android.future.usb.UsbManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.CompoundButton;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+
+public class AKBrobotADKActivity extends Activity implements OnClickListener, Runnable {
+ private static final String TAG = "AKBrobotADK";
+ private static final String ACTION_USB_PERMISSION = "org.ammlab.android.app.akbrobotadk.action.USB_PERMISSION";
+ private PendingIntent mPermissionIntent;
+ private boolean mPermissionRequestPending;
+
+ private UsbManager mUsbManager;
+ private UsbAccessory mAccessory;
+
+ ParcelFileDescriptor mFileDescriptor = null;
+
+ FileInputStream mInputStream = null;
+ FileOutputStream mOutputStream = null;
+ private ToggleButton mToggleButton1;
+ private ToggleButton mToggleButton2;
+ private SeekBar mSeekBar1;
+ private SeekBar mSeekBar2;
+ private SeekBar mSeekBar3;
+ private TextView mText1;
+ private TextView mText2;
+ private TextView mText3;
+ private TextView mInValue;
+ private EditText mEditOutput;
+ private Spinner mSpinner1;
+ private Spinner mSpinner2;
+ private Spinner mSpinner3;
+ private Spinner mSpinner4;
+ private Button mButtonConfig;
+ private Button mButtonDin;
+ private Button mButtonAin;
+ private Button mButtonDout;
+ private Button mButtonAout;
+
+ private byte[] mRecvBuff = new byte[4];
+
+ private static final int MESSAGE_INPUTVAL = 1;
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // UsbManager \82Ì\83C\83\93\83X\83^\83\93\83X\82ð\8eæ\93¾
+ mUsbManager = UsbManager.getInstance(this);
+
+ // \83I\83\8c\83I\83\8c\83p\81[\83~\83b\83V\83\87\83\93\97p Broadcast Intent
+ mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
+
+ // \83I\83\8c\83I\83\8c\83p\81[\83~\83b\83V\83\87\83\93 Intent \82Æ\83A\83N\83Z\83T\83\8a\82ª\8eæ\82è\8aO\82³\82ê\82½\82Æ\82«\82Ì Intent \82ð\93o\98^
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_USB_PERMISSION);
+ filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
+ registerReceiver(mUsbReceiver, filter);
+
+ //re-creation?
+ if (getLastNonConfigurationInstance() != null) {
+ mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
+ openAccessory(mAccessory);
+ }
+
+ setContentView(R.layout.main);
+
+ mToggleButton1 = (ToggleButton) findViewById(R.id.toggleButton1);
+ mToggleButton2 = (ToggleButton) findViewById(R.id.toggleButton2);
+ mSeekBar1 = (SeekBar) findViewById(R.id.seekBar1);
+ mSeekBar2 = (SeekBar) findViewById(R.id.seekBar2);
+ mSeekBar3 = (SeekBar) findViewById(R.id.seekBar3);
+ mSeekBar1.setProgress(50);
+ mSeekBar2.setProgress(50);
+ mSeekBar3.setProgress(50);
+
+ mText1 = (TextView) findViewById(R.id.textView1);
+ mText2 = (TextView) findViewById(R.id.textView2);
+ mText3 = (TextView) findViewById(R.id.textView3);
+ mInValue = (TextView) findViewById(R.id.labelinvalue);
+
+ mEditOutput = (EditText) findViewById(R.id.editOutput);
+
+ mSpinner1 = (Spinner) findViewById(R.id.spinner1);
+ mSpinner2 = (Spinner) findViewById(R.id.spinner2);
+ mSpinner3 = (Spinner) findViewById(R.id.spinner3);
+ mSpinner4 = (Spinner) findViewById(R.id.spinner4);
+
+ mButtonConfig = (Button)findViewById(R.id.buttonconfig);
+ mButtonDin = (Button)findViewById(R.id.buttondin);
+ mButtonAin = (Button)findViewById(R.id.buttonain);
+ mButtonDout = (Button)findViewById(R.id.buttondout);
+ mButtonAout = (Button)findViewById(R.id.buttonaout);
+
+ mButtonConfig.setOnClickListener(this);
+ mButtonDin.setOnClickListener(this);
+ mButtonAin.setOnClickListener(this);
+ mButtonDout.setOnClickListener(this);
+ mButtonAout.setOnClickListener(this);
+
+ //\83V\81[\83N\83o\81[\82ð\95Ï\8dX\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89
+ //for motor#0
+ mSeekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = 0;
+ byte direction = 0;
+ if( progress > 45 && progress < 55){
+ value = 0;
+ }else if(progress > 50){
+ value = ((progress - 50) * 255 / 50);
+ direction = 0;
+ }else{ //progress < 50
+ value = ((50 - progress) * 255 / 50);
+ direction = 1;
+ }
+ mText1.setText(String.format("%d", value));
+ sendCommand((byte)3,(byte)0,direction,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83j\83\85\81[\83g\83\89\83\8b
+ mSeekBar1.setProgress(50);
+ //motor#1\92â\8e~
+ sendCommand((byte)3,(byte)0,(byte)0,(byte)0);
+ }
+ });
+ //for motor#1
+ mSeekBar2.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = 0;
+ byte direction = 0;
+ if( progress > 45 && progress < 55){
+ value = 0;
+ }else if(progress > 50){
+ value = ((progress - 50) * 255 / 50);
+ direction = 0;
+ }else{ //progress < 50
+ value = ((50 - progress) * 255 / 50);
+ direction = 1;
+ }
+ mText2.setText(String.format("%d", value));
+ sendCommand((byte)3,(byte)1,direction,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83j\83\85\81[\83g\83\89\83\8b
+ mSeekBar2.setProgress(50);
+ //motor#1\92â\8e~
+ sendCommand((byte)3,(byte)1,(byte)0,(byte)0);
+ }
+ });
+
+ //for servo#0
+ mSeekBar3.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = (180*progress/100);
+ mText3.setText(String.format("%d", value));
+ Log.d(TAG, "Servo0:"+value+","+(byte)value);
+ sendCommand((byte)5,(byte)0,(byte)0,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83Z\83\93\83^\81[\82É
+ mSeekBar3.setProgress(50);
+ sendCommand((byte)5,(byte)0,(byte)0,(byte)90);
+ }
+ });
+ //\83{\83^\83\93\82ð\89\9f\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89(\83{\83^\83\931)
+ mToggleButton1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ sendCommand((byte)4,(byte)0,(byte)0,(byte)(isChecked ? 0x1 : 0x0));
+ }
+ });
+ //\83{\83^\83\93\82ð\89\9f\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89(\83{\83^\83\932)
+ mToggleButton2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ sendCommand((byte)4,(byte)1,(byte)0,(byte)(isChecked ? 0x1 : 0x0));
+ }
+ });
+
+ enableControls(false);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ if (mInputStream != null && mOutputStream != null) {
+ return;
+ }
+
+ // USB Accessory \82Ì\88ê\97\97\82ð\8eæ\93¾
+ UsbAccessory[] accessories = mUsbManager.getAccessoryList();
+ UsbAccessory accessory = (accessories == null ? null : accessories[0]);
+ if (accessory != null) {
+ // Accessory \82É\83A\83N\83Z\83X\82·\82é\8c \8cÀ\82ª\82 \82é\82©\83`\83F\83b\83N
+ if (mUsbManager.hasPermission(accessory)) {
+ // \90Ú\91±\82ð\8aJ\82
+ openAccessory(accessory);
+ } else {
+ synchronized (mUsbReceiver) {
+ if (!mPermissionRequestPending) {
+ // \83p\81[\83~\83b\83V\83\87\83\93\82ð\88Ë\97\8a
+ mUsbManager.requestPermission(accessory, mPermissionIntent);
+ mPermissionRequestPending = true;
+ }
+ }
+ }
+ } else {
+ Log.d(TAG, "mAccessory is null");
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ closeAccessory();
+ }
+
+ @Override
+ public void onDestroy() {
+ unregisterReceiver(mUsbReceiver);
+ super.onDestroy();
+ }
+
+ private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+
+ if (ACTION_USB_PERMISSION.equals(action)) {
+ synchronized (this) {
+ // Intent \82©\82ç\83A\83N\83Z\83T\83\8a\82ð\8eæ\93¾
+ UsbAccessory accessory = UsbManager.getAccessory(intent);
+
+ // \83p\81[\83~\83b\83V\83\87\83\93\82ª\82 \82é\82©\83`\83F\83b\83N
+ if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
+ // \90Ú\91±\82ð\8aJ\82
+ openAccessory(accessory);
+ } else {
+ Log.d(TAG, "permission denied for accessory " + accessory);
+ }
+ mPermissionRequestPending = false;
+ }
+ } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
+ // Intent \82©\82ç\83A\83N\83Z\83T\83\8a\82ð\8eæ\93¾
+ UsbAccessory accessory = UsbManager.getAccessory(intent);
+ if (accessory != null && accessory.equals(mAccessory)) {
+ // \90Ú\91±\82ð\95Â\82¶\82é
+ closeAccessory();
+ }
+ }
+ }
+ };
+
+ private void openAccessory(UsbAccessory accessory) {
+ // \83A\83N\83Z\83T\83\8a\82É\83A\83N\83Z\83X\82·\82é\82½\82ß\82Ì\83t\83@\83C\83\8b\83f\83B\83X\83N\83\8a\83v\83^\82ð\8eæ\93¾
+ mFileDescriptor = mUsbManager.openAccessory(accessory);
+
+ if (mFileDescriptor != null) {
+ mAccessory = accessory;
+ FileDescriptor fd = mFileDescriptor.getFileDescriptor();
+
+ // \93ü\8fo\97Í\97p\82Ì\83X\83g\83\8a\81[\83\80\82ð\8am\95Û
+ mInputStream = new FileInputStream(fd);
+ mOutputStream = new FileOutputStream(fd);
+
+ // \82±\82Ì\92\86\82Å\83A\83N\83Z\83T\83\8a\82Æ\82â\82è\82Æ\82è\82·\82é
+ Thread thread = new Thread(null, this, "DemoKit");
+ thread.start();
+ enableControls(true);
+ Log.d(TAG, "accessory opened");
+ } else {
+ Log.d(TAG, "accessory open fail");
+ }
+ }
+
+ private void closeAccessory() {
+ enableControls(false);
+ try {
+ if (mFileDescriptor != null) {
+ mInputStream.close();
+ mOutputStream.close();
+ mFileDescriptor.close();
+ }
+ } catch (IOException e) {
+ } finally {
+ mFileDescriptor = null;
+ mAccessory = null;
+ mInputStream = null;
+ mOutputStream = null;
+ Log.d(TAG, "accessory closed");
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if( view == mButtonConfig ){
+ long port = mSpinner1.getSelectedItemId();
+ long mode = mSpinner2.getSelectedItemId();
+ byte p = getPort(port, 256);
+ Log.d(TAG, "Primitive:"+port+","+p+","+mode);
+ sendCommand((byte)0, p, (byte)0, (byte)mode);
+ }else if( view == mButtonDout){
+ long port = mSpinner4.getSelectedItemId();
+ String value = mEditOutput.getText().toString();
+ byte p = getPort(port, 0);
+ if( value != null && value.length() > 0){
+ byte v = (byte)(int)Integer.valueOf(value);
+ Log.d(TAG, "DigitalOut:"+port+","+p+","+v);
+ sendCommand((byte)1, p, (byte)0, (byte)v);
+ }
+ }else if( view == mButtonAout){
+ long port = mSpinner4.getSelectedItemId();
+ String value = mEditOutput.getText().toString();
+ byte p = getPort(port, 1);
+ if( value != null && value.length() > 0){
+ byte v = (byte)(int)Integer.valueOf(value);
+ Log.d(TAG, "AnalogOut:"+port+","+p+","+v);
+ sendCommand((byte)1, p, (byte)0, (byte)v);
+ }
+ }else if( view == mButtonDin){
+ long port = mSpinner3.getSelectedItemId();
+ byte p = getPort(port, 2);
+ sendCommand((byte)2, p, (byte)0, (byte)0);
+ Log.d(TAG, "DigitalIn:"+port+","+p);
+ }else if( view == mButtonAin){
+ long port = mSpinner3.getSelectedItemId();
+ byte p = getPort(port, 3);
+ sendCommand((byte)2, p, (byte)0, (byte)0);
+ Log.d(TAG, "AnalogIn:"+port+","+p);
+ }else{
+ Log.d(TAG, "Ignore click:"+view.toString());
+ }
+ }
+
+ private byte getPort(long port, long type){//type(0:DigitalOut, 1:AnalogOut, 2:DigitalIn, 3:AnalogIn, 256:config)
+ byte ConfigPort=-1;
+ long limitDigtal = 6;
+ if(type == 0 || type == 2 || type == 256){ //Digital Port
+ if(port > limitDigtal){ //Analog Port
+ ConfigPort = (byte) (port - limitDigtal -1 + 0x40);
+ }else{
+ ConfigPort = (byte) port;
+ }
+ }else if( type == 1 ){//Analog Out Port
+ ConfigPort = (byte)(port + 0x80);
+ }else{ //AnalogIn Port
+ if( port > limitDigtal){
+ ConfigPort = (byte)(port - limitDigtal -1 + 0x80);
+ }
+ }
+ return ConfigPort;
+ }
+ // \82±\82±\82Å\83A\83N\83Z\83T\83\8a\82Æ\92Ê\90M\82·\82é
+ @Override
+ public void run() {
+ int ret = 0;
+ byte[] buffer = new byte[16384];
+ int i;
+
+ Log.d(TAG, "Thread started.");
+ // \83A\83N\83Z\83T\83\8a -> \83A\83v\83\8a
+ while (mInputStream != null) {
+// while (ret >= 0) {
+ try {
+ ret = mInputStream.read(buffer);
+ } catch (IOException e) {
+ break;
+ }
+
+ if( ret > 0 ){
+ Log.d(TAG, ret + " bytes message received.");
+ }
+ i = 0;
+ while (i < ret) {
+ int len = ret - i;
+
+ switch (buffer[i]) {
+ case 0x2:
+ if (len >= 4) {
+ Message m = Message.obtain(mHandler, MESSAGE_INPUTVAL);
+ synchronized (this) {
+ mRecvBuff[0] = buffer[0];
+ mRecvBuff[1] = buffer[1];
+ mRecvBuff[2] = buffer[2];
+ mRecvBuff[3] = buffer[3];
+ }
+ Log.d(TAG, "data received:"+buffer[0]+","+buffer[1]+","+buffer[2]+","+buffer[3]);
+ mHandler.sendMessage(m);
+ i += 4;
+ }
+ break;
+
+ default:
+ Log.d(TAG, "unknown msg: " + buffer[i]);
+ i = len;
+ break;
+ }
+ }
+
+ }
+ Log.d(TAG, "Thread end.");
+ }
+ // \83A\83v\83\8a -> \83A\83N\83Z\83T\83\8a
+ public void sendCommand(byte command1, byte command2, byte value1, byte value2) {
+ byte[] buffer = new byte[4];
+ buffer[0] = command1;
+ buffer[1] = command2;
+ buffer[2] = value1;
+ buffer[3] = value2;
+
+ if (mOutputStream != null) {
+ try {
+ mOutputStream.write(buffer);
+ } catch (IOException e) {
+ Log.e(TAG, "write failed", e);
+ }
+ }
+ }
+ // UI \83X\83\8c\83b\83h\82Å\89æ\96Ê\8fã\82Ì\95\\8e¦\82ð\95Ï\8dX
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_INPUTVAL:
+ int val=0;
+ synchronized (this) {
+ val = mRecvBuff[2] & 0xff;
+ val = val * 256 + (mRecvBuff[3] & 0xff);
+ }
+ mInValue.setText(String.valueOf(val));
+ break;
+ }
+ }
+ };
+
+ // \90Ú\91±\8fó\91Ô\95\\8e¦(\83^\83C\83g\83\8b\83o\81[)
+ private void enableControls(boolean enable) {
+ Resources res = getResources();
+ String titleString = res.getString(R.string.app_name);
+
+ if (enable) {
+ setTitle(titleString + " - connected");
+ } else {
+ setTitle(titleString + " - not connected");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>AKBrobotUART</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.ammlab.android.akbrobotuart"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk android:minSdkVersion="12" />
+
+ <application
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name="org.ammlab.android.akbrobotuart.AKBrobotUARTActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ <intent-filter>
+ <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
+ </intent-filter>
+ <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
+ android:resource="@xml/device_filter" />
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+/** Automatically generated file. DO NOT MODIFY */
+package org.ammlab.android.akbrobotuart;
+
+public final class BuildConfig {
+ public final static boolean DEBUG = true;
+}
\ No newline at end of file
--- /dev/null
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package org.ammlab.android.akbrobotuart;
+
+public final class R {
+ public static final class array {
+ public static final int command1=0x7f060000;
+ public static final int portlist=0x7f060001;
+ }
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int ic_launcher=0x7f020000;
+ }
+ public static final class id {
+ public static final int buttonain=0x7f070015;
+ public static final int buttonaout=0x7f07001a;
+ public static final int buttonconfig=0x7f070010;
+ public static final int buttondin=0x7f070014;
+ public static final int buttondout=0x7f070019;
+ public static final int editOutput=0x7f070018;
+ public static final int label1=0x7f070000;
+ public static final int label2=0x7f070003;
+ public static final int label3=0x7f070006;
+ public static final int label4=0x7f070009;
+ public static final int label5=0x7f07000b;
+ public static final int label6=0x7f07000d;
+ public static final int label7=0x7f070011;
+ public static final int label8=0x7f070016;
+ public static final int labelinvalue=0x7f070013;
+ public static final int seekBar1=0x7f070001;
+ public static final int seekBar2=0x7f070004;
+ public static final int seekBar3=0x7f070007;
+ public static final int spinner1=0x7f07000e;
+ public static final int spinner2=0x7f07000f;
+ public static final int spinner3=0x7f070012;
+ public static final int spinner4=0x7f070017;
+ public static final int textView1=0x7f070002;
+ public static final int textView2=0x7f070005;
+ public static final int textView3=0x7f070008;
+ public static final int toggleButton1=0x7f07000a;
+ public static final int toggleButton2=0x7f07000c;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f050000;
+ public static final int labelmotor1=0x7f050003;
+ public static final int labelmotor2=0x7f050004;
+ public static final int labelrelay1=0x7f050001;
+ public static final int labelrelay2=0x7f050002;
+ public static final int labelservo1=0x7f050005;
+ }
+ public static final class xml {
+ public static final int device_filter=0x7f040000;
+ }
+}
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-12
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent" android:layout_height="fill_parent"
+ android:orientation="vertical">
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/label1" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:text="@string/labelmotor1" />
+ <SeekBar android:id="@+id/seekBar1" android:layout_width="500dp"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/textView1" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content" android:layout_height="20dp" />
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/label2" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:text="@string/labelmotor2" />
+ <SeekBar android:id="@+id/seekBar2" android:layout_width="500dp"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/textView2" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content" android:layout_height="20dp" />
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/label3" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:text="@string/labelservo1" />
+ <SeekBar android:id="@+id/seekBar3" android:layout_width="500dp"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/textView3" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content" android:layout_height="20dp" />
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/label4" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:text="@string/labelrelay1" />
+ <ToggleButton android:id="@+id/toggleButton1"
+ android:layout_width="wrap_content" android:layout_height="wrap_content" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/label5" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" android:text="@string/labelrelay2" />
+ <ToggleButton android:id="@+id/toggleButton2"
+ android:layout_width="wrap_content" android:layout_height="wrap_content" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content" android:layout_height="50dp" />
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/label6"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Primitive Configuration" />
+ <Spinner
+ android:id="@+id/spinner1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:entries="@array/portlist" />
+ <Spinner
+ android:id="@+id/spinner2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:entries="@array/command1" />
+ <Button
+ android:id="@+id/buttonconfig"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Set" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/label7"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Primitive In" />
+ <Spinner
+ android:id="@+id/spinner3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:entries="@array/portlist" />
+ <TextView
+ android:id="@+id/labelinvalue"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <Button
+ android:id="@+id/buttondin"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="DigitalIn" />
+ <Button
+ android:id="@+id/buttonain"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="AnalogIn" />
+ </LinearLayout>
+ <LinearLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/label8"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Primitive Out" />
+ <Spinner
+ android:id="@+id/spinner4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:entries="@array/portlist" />
+ <EditText
+ android:id="@+id/editOutput"
+ android:layout_width="79dp"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="number"
+ android:singleLine="true" >
+ </EditText>
+ <Button
+ android:id="@+id/buttondout"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="DigitalOut" />
+ <Button
+ android:id="@+id/buttonaout"
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="AnalogOut" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">AKBrobotUART</string>
+ <string name="labelrelay1">Relay1</string>
+ <string name="labelrelay2">Relay2</string>
+ <string name="labelmotor1">Motor1</string>
+ <string name="labelmotor2">Motor2</string>
+ <string name="labelservo1">Servo1</string>
+ <string-array name="command1">
+ <item>Digital Out</item>
+ <item>Analog Out</item>
+ <item>Digital In</item>
+ <item>Analog In</item>
+ </string-array>
+ <string-array name="portlist">
+ <item>D0</item>
+ <item>D1</item>
+ <item>D2</item>
+ <item>D3</item>
+ <item>D4</item>
+ <item>D5</item>
+ <item>D6</item>
+ <item>A0</item>
+ <item>A1</item>
+ <item>A2</item>
+ <item>A3</item>
+ <item>A4</item>
+ <item>A5</item>
+ </string-array>
+</resources>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ 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.
+-->
+<resources>
+ <usb-device vendor-id="1027" product-id="24577" />
+ <usb-device vendor-id="1118" product-id="688" />
+ <usb-device vendor-id="1027" product-id="24592" />
+ <usb-device vendor-id="1027" product-id="24596" />
+</resources>
--- /dev/null
+package jp.ksksue.driver.serial;
+/*
+ * FTDI Driver Class
+ *
+ * Copyright (C) 2011 @ksksue
+ * Licensed under the Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * thanks to @titoi2 @darkukll @yakagawa @yishii @hyokota555
+ */
+
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbDeviceConnection;
+import android.hardware.usb.UsbEndpoint;
+import android.hardware.usb.UsbInterface;
+import android.hardware.usb.UsbManager;
+import android.hardware.usb.UsbConstants;
+import android.util.Log;
+
+enum FTDICHIPTYPE {FT232RL, FT2232C, FT232H, FT2232D, FT2232HL, FT4232HL, FT230X ; }
+class UsbId {
+ int mVid;
+ int mPid;
+ int mBcdDevice;
+ int mNumOfChannels;
+ FTDICHIPTYPE mType;
+ UsbId(int vid, int pid, int bcdDevice, int numOfChannels, FTDICHIPTYPE type){ mVid = vid; mPid = pid; mBcdDevice = bcdDevice; mNumOfChannels = numOfChannels; mType = type;}
+}
+
+public class FTDriver {
+
+ /*
+ * USB read packet loss checker
+ *
+ * If true then checking USB read packet loss
+ * and displaying messages to Logcat
+ *
+ * requirement : microcomputer send 01234567890123456789012... to Android
+ */
+ private boolean mReadPakcetChecker = false;
+
+ private static final UsbId[] IDS = {
+ new UsbId(0x0403, 0x6001, 6, 1, FTDICHIPTYPE.FT232RL), // FT232RL
+ new UsbId(0x0403, 0x6014, 9, 1, FTDICHIPTYPE.FT232H), // FT232H
+ new UsbId(0x0403, 0x6010, 5, 2, FTDICHIPTYPE.FT2232C), // FT2232C
+ new UsbId(0x0403, 0x6010, 5, 2, FTDICHIPTYPE.FT2232D), // FT2232D
+ new UsbId(0x0403, 0x6010, 7, 2, FTDICHIPTYPE.FT2232HL), // FT2232HL
+ new UsbId(0x0403, 0x6011, 8, 4, FTDICHIPTYPE.FT4232HL), // FT4232HL
+ new UsbId(0x0403, 0x6015, 10, 1, FTDICHIPTYPE.FT230X), // FT230X
+ new UsbId(0x0584, 0xB020, 4, 1, FTDICHIPTYPE.FT232RL), // REX-USB60F thanks to @hyokota555
+ };
+ private UsbId mSelectedDeviceInfo;
+
+ public static final int CH_A = 1;
+ public static final int CH_B = 2;
+ public static final int CH_C = 3;
+ public static final int CH_D = 4;
+
+ public static final int BAUD300 = 300;
+ public static final int BAUD600 = 600;
+ public static final int BAUD1200 = 1200;
+ public static final int BAUD2400 = 2400;
+ public static final int BAUD4800 = 4800;
+ public static final int BAUD9600 = 9600;
+ public static final int BAUD14400 = 14400;
+ public static final int BAUD19200 = 19200;
+ public static final int BAUD38400 = 38400;
+ public static final int BAUD57600 = 57600;
+ public static final int BAUD115200 = 115200;
+ public static final int BAUD230400 = 230400;
+
+ public static final int FTDI_SET_DATA_BITS_7 = 7;
+ public static final int FTDI_SET_DATA_BITS_8 = 8;
+ public static final int FTDI_SET_DATA_PARITY_NONE = (0x0 << 8);
+ public static final int FTDI_SET_DATA_PARITY_ODD = (0x1 << 8);
+ public static final int FTDI_SET_DATA_PARITY_EVEN = (0x2 << 8);
+ public static final int FTDI_SET_DATA_PARITY_MARK = (0x3 << 8);
+ public static final int FTDI_SET_DATA_PARITY_SPACE = (0x4 << 8);
+ public static final int FTDI_SET_DATA_STOP_BITS_1 = (0x0 << 11);
+ public static final int FTDI_SET_DATA_STOP_BITS_15 = (0x1 << 11);
+ public static final int FTDI_SET_DATA_STOP_BITS_2 = (0x2 << 11);
+ public static final int FTDI_SET_NOBREAK = (0x0 << 14);
+ public static final int FTDI_SET_BREAK = (0x1 << 14);
+ public static final int FTDI_SET_FLOW_CTRL_NONE = 0x0;
+ public static final int FTDI_SET_FLOW_RTS_CTS_HS = (0x1 << 8);
+ public static final int FTDI_SET_FLOW_DTR_DSR_HS = (0x2 << 8);
+ public static final int FTDI_SET_FLOW_XON_XOFF_HS = (0x4 << 8);
+
+
+ private int[] mSerialProperty = new int[4];
+
+ public static final int FTDI_MPSSE_BITMODE_RESET = 0x00; /**< switch off bitbang mode, back to regular serial/FIFO */
+ public static final int FTDI_MPSSE_BITMODE_BITBANG= 0x01; /**< classical asynchronous bitbang mode, introduced with B-type chips */
+ public static final int FTDI_MPSSE_BITMODE_MPSSE = 0x02; /**< MPSSE mode, available on 2232x chips */
+ public static final int FTDI_MPSSE_BITMODE_SYNCBB = 0x04; /**< synchronous bitbang mode, available on 2232x and R-type chips */
+ public static final int FTDI_MPSSE_BITMODE_MCU = 0x08; /**< MCU Host Bus Emulation mode, available on 2232x chips */
+ public static final int FTDI_MPSSE_BITMODE_OPTO = 0x10; /**< Fast Opto-Isolated Serial Interface Mode, available on 2232x chips */
+ public static final int FTDI_MPSSE_BITMODE_CBUS = 0x20; /**< Bitbang on CBUS pins of R-type chips, configure in EEPROM before */
+ public static final int FTDI_MPSSE_BITMODE_SYNCFF = 0x40; /**< Single Channel Synchronous FIFO mode, available on 2232H chips */
+ public static final int FTDI_MPSSE_BITMODE_FT1284 = 0x80; /**< FT1284 mode, available on 232H chips */
+
+ final static int FTDI_SIO_SET_BITMODE_REQUEST = 0x0B;
+ final static int FTDI_SIO_READ_PINS_REQUEST = 0x0C;
+
+
+ public static final int FTDI_MAX_INTERFACE_NUM = 4;
+
+ private static final String TAG = "FTDriver";
+ private final int mPacketSize = 64;
+
+ private UsbManager mManager;
+ private UsbDevice mDevice;
+ private UsbDeviceConnection mDeviceConnection;
+ private UsbInterface[] mInterface = new UsbInterface[FTDI_MAX_INTERFACE_NUM];
+
+ private UsbEndpoint[] mFTDIEndpointIN;
+ private UsbEndpoint[] mFTDIEndpointOUT;
+
+ public static final int READBUF_SIZE = 4096;
+ private int mReadbufOffset;
+ private int mReadbufRemain;
+ private byte[] mReadbuf = new byte[READBUF_SIZE];
+ //private int mBitbangMode = FTDI_MPSSE_BITMODE_RESET;
+
+ public static final int WRITEBUF_SIZE = 4096;
+
+ /* for USB read packet loss checker */
+ private int incReadCount=0;
+ private int totalReadCount=0;
+ private boolean updateReadCount = false;
+
+ public FTDriver(UsbManager manager) {
+ mManager = manager;
+ mReadbufOffset = 0;
+ mReadbufRemain = 0;
+ for(int i=0;i<4;++i) {
+ // Default Serial Property : Data bit : 8, Parity : none, Stop bit : 1, Tx : off
+ mSerialProperty[i] = FTDI_SET_DATA_PARITY_NONE | FTDI_SET_DATA_STOP_BITS_1 | 8;
+ }
+ }
+
+ // Open an FTDI USB Device
+ public boolean begin(int baudrate) {
+ for (UsbDevice device : mManager.getDeviceList().values()) {
+ Log.i(TAG,"Devices : "+device.toString());
+
+ getPermission(device);
+ if(!mManager.hasPermission(device)) {
+ return false;
+ }
+
+ // TODO: support any connections(current version find a first device)
+ if(getUsbInterfaces(device)) {
+ break;
+ }
+ }
+
+ if(mSelectedDeviceInfo == null) {
+ return false;
+ }
+
+ mFTDIEndpointIN = new UsbEndpoint[mSelectedDeviceInfo.mNumOfChannels];
+ mFTDIEndpointOUT = new UsbEndpoint[mSelectedDeviceInfo.mNumOfChannels];
+
+ if(!setFTDIEndpoints(mInterface,mSelectedDeviceInfo.mNumOfChannels)){
+ return false;
+ }
+ initFTDIChip(mDeviceConnection,baudrate);
+
+ Log.i(TAG,"Device Serial : "+mDeviceConnection.getSerial());
+
+ return true;
+ }
+
+ // Close the device
+ public void end() {
+ if(mSelectedDeviceInfo!=null) {
+ for(int i=0; i<mSelectedDeviceInfo.mNumOfChannels; ++i) {
+ setUSBInterface(null,null,i);
+ }
+ }
+ }
+
+ // Read Binary Data
+ public int read(byte[] buf) {
+ return read(buf,0);
+ }
+
+ public int read(byte[] buf, int channel) {
+
+ if(channel >= mSelectedDeviceInfo.mNumOfChannels) {
+ return -1;
+ }
+ if (buf.length <= mReadbufRemain) {
+ if(!mReadPakcetChecker) {
+ System.arraycopy(mReadbuf, mReadbufOffset, buf, 0, buf.length);
+ } else {
+ /*
+ * USB read packet loss checker
+ *
+ * check: read byte is 01234567890123456789012...
+ * requirement : microcomputer send 01234567890123456789012... to Android
+ */
+ for (int i = 0; i < buf.length; i++) {
+ buf[i] = mReadbuf[mReadbufOffset++];
+ ++incReadCount;
+ // check count number == read number
+ while ((incReadCount - 1) % 10 != (Byte.valueOf(buf[i]) - '0')) {
+ Log.d(TAG, "!!! Lost Data !!! count : "
+ + (incReadCount - 1) + ", data : " + buf[i]);
+ ++incReadCount;
+ }
+ }
+ Log.d(TAG, "read buf length 1 : " + Integer.toString(buf.length));
+ totalReadCount += buf.length;
+ updateReadCount = true;
+ /* end of USB read packet loss checker*/
+ }
+ mReadbufRemain -= buf.length;
+ return buf.length;
+ }
+ int ofst = 0;
+ int needlen = buf.length;
+ if (mReadbufRemain>0) {
+ needlen -= mReadbufRemain;
+ System.arraycopy(mReadbuf, mReadbufOffset, buf, ofst, mReadbufRemain);
+// for (; mReadbufRemain>0 ; mReadbufRemain-- ) {
+// buf[ofst++] = mReadbuf[mReadbufOffset++];
+// }
+ }
+ int len = mDeviceConnection.bulkTransfer(mFTDIEndpointIN[channel], mReadbuf, mReadbuf.length,
+ 0); // RX
+ int blocks = len / mPacketSize;
+ int remain = len % mPacketSize;
+ if (remain>0) {
+ blocks++;
+ }
+ mReadbufRemain = len - (2*blocks);
+ int rbufindex = 0;
+ for (int block=0; block<blocks; block++) {
+ int blockofst = block*mPacketSize;
+// System.arraycopy(mReadbuf, blockofst+2, mReadbuf, rbufindex+1, mPacketSize-2);
+ for (int i=2; i<mPacketSize ; i++ ) {
+ mReadbuf[rbufindex++] = mReadbuf[blockofst+i];
+ }
+ }
+
+ mReadbufOffset = 0;
+
+ for (;(mReadbufRemain>0) && (needlen>0);mReadbufRemain--,needlen--) {
+ buf[ofst++] = mReadbuf[mReadbufOffset++];
+ if (mReadPakcetChecker) {
+ /*
+ * USB read packet loss checker
+ */
+ ++incReadCount;
+ while ((incReadCount - 1) % 10 != (Byte.valueOf(buf[ofst - 1]) - '0')) {
+ Log.d(TAG,
+ "!!! Lost Data !!! count : " + (incReadCount - 1)
+ + ", data : "
+ + Byte.toString(buf[ofst - 1]));
+ ++incReadCount;
+ }
+ /* End of packet loss checker */
+ }
+ }
+
+ /*
+ * USB read packet loss checker
+ *
+ * Display a total of read count
+ */
+ if (mReadPakcetChecker) {
+ if (ofst > 0) {
+ Log.d(TAG, "read buf length 2 : " + Integer.toString(ofst));
+ totalReadCount += ofst;
+ updateReadCount = true;
+ }
+ if (updateReadCount) {
+ Log.d(TAG, "Total of Read Count : " + totalReadCount);
+ Log.d(TAG, "Increment Read Count : " + incReadCount);
+ updateReadCount = false;
+ }
+ }
+ /* End of packet loss checker */
+
+ return ofst;
+ }
+
+ /** Writes 1byte Binary Data
+ *
+ * @param buf : write buffer
+ * @return written length
+ */
+ public int write(byte[] buf) {
+ return write(buf,buf.length,0);
+ }
+
+ /** Writes n byte Binary Data
+ *
+ * @param buf : write buffer
+ * @param length : write length
+ * @return wrriten length
+ */
+ public int write(byte[] buf,int length) {
+ return write(buf,length,0);
+ }
+
+ /** Writes n byte Binary Data to n channel
+ *
+ * @param buf : write buffer
+ * @param length : write length
+ * @param channel : write channel
+ * @return written length
+ */
+ public int write(byte[] buf, int length, int channel) {
+ if(channel >= mSelectedDeviceInfo.mNumOfChannels) {
+ return -1;
+ }
+ int offset = 0;
+ int actual_length;
+ byte[] write_buf = new byte[WRITEBUF_SIZE];
+// byte[] tmp_buf=new byte[WRITEBUF_SIZE];
+
+ while(offset < length) {
+ int write_size = WRITEBUF_SIZE;
+
+ if(offset+write_size > length) {
+ write_size = length-offset;
+ }
+ System.arraycopy(buf, offset, write_buf, 0, write_size);
+// ByteArrayInputStream write_buf = new ByteArrayInputStream(buf);
+// write_buf.read(tmp_buf, offset, write_size);
+
+ actual_length = mDeviceConnection.bulkTransfer(mFTDIEndpointOUT[channel], write_buf, write_size, 0);
+
+ if(actual_length<0) {
+ return -1;
+ }
+ offset += actual_length;
+ }
+
+ return offset;
+ }
+
+ // TODO Implement these methods
+/* public void available() {
+
+ }
+
+ public void peek() {
+
+ }
+
+ public void flush() {
+
+ }
+
+ public void print() {
+
+ }
+
+ public void println() {
+
+ }
+ */
+
+ public boolean isConnected() {
+ if(mDevice != null && mFTDIEndpointIN != null && mFTDIEndpointOUT != null) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ public byte getPinState()
+ {
+ int index = 0;
+ byte [] buffer;
+ buffer = new byte [1];
+
+ mDeviceConnection.controlTransfer(
+ UsbConstants.USB_TYPE_VENDOR | UsbConstants.USB_DIR_IN,
+ FTDI_SIO_READ_PINS_REQUEST, 0, index, buffer, 1, 0);
+
+ return buffer[0];
+ }
+
+ public boolean setBitmode(boolean enable,int bitmask,int mode)
+ {
+ short val = 0;
+ int result;
+ boolean ret = false;
+ int index = 0; // for devices that have multiple IFs,need to modify.
+
+ if(enable){
+ val = (short)bitmask;
+ val |= (mode << 8);
+ }
+
+ result = mDeviceConnection.controlTransfer(
+ UsbConstants.USB_TYPE_VENDOR | UsbConstants.USB_DIR_OUT,
+ FTDI_SIO_SET_BITMODE_REQUEST,val,index,null,0,0);
+
+ if(result >= 0){
+ ret = true;
+ //mBitbangMode = mode;
+ }
+
+ return ret;
+ }
+
+ public boolean setBaudrate(int baudrate, int channel) {
+ if(mDeviceConnection == null) {
+ return false;
+ }
+ int baud = calcFTDIBaudrate(baudrate, mSelectedDeviceInfo.mType);
+ int index = 0;
+
+/* if(mSelectedDeviceInfo.mType == FTDICHIPTYPE.FT232H) {
+ index = 0x0200;
+ }*/
+ if (mSelectedDeviceInfo.mType == FTDICHIPTYPE.FT2232HL ||
+ mSelectedDeviceInfo.mType == FTDICHIPTYPE.FT4232HL ||
+ mSelectedDeviceInfo.mType == FTDICHIPTYPE.FT232H ) {
+ index = baud >> 8;
+ index &= 0xFF00;
+ } else{
+ index = baud >> 16;
+ }
+
+ index |= channel; // Ch.A=1, Ch.B=2, ...
+
+ mDeviceConnection.controlTransfer(0x40, 0x03, baud, index, null, 0, 0); //set baudrate
+
+ // TODO: check error
+ return true;
+ }
+ // Initial control transfer
+ private void initFTDIChip(UsbDeviceConnection conn,int baudrate) {
+
+ for(int i=0;i < mSelectedDeviceInfo.mNumOfChannels; ++i) {
+ int index = i+1;
+ conn.controlTransfer(0x40, 0, 0, index, null, 0, 0); //reset
+ conn.controlTransfer(0x40, 0, 1, index, null, 0, 0); //clear Rx
+ conn.controlTransfer(0x40, 0, 2, index, null, 0, 0); //clear Tx
+ conn.controlTransfer(0x40, 0x02, 0x0000, index, null, 0, 0); //flow control none
+ setBaudrate(baudrate, index);
+ conn.controlTransfer(0x40, 0x04, 0x0008, index, null, 0, 0); //data bit 8, parity none, stop bit 1, tx off
+ }
+ }
+
+ /**
+ * Sets flow control to an FTDI chip register
+ *
+ * @param channel
+ * CH_A
+ * CH_B
+ * CH_C
+ * CH_D
+ * @param flowControl
+ * FTDI_SET_FLOW_CTRL_NONE
+ * FTDI_SET_FLOW_RTS_CTS_HS
+ * FTDI_SET_FLOW_DTR_DSR_HS
+ * FTDI_SET_FLOW_XON_XOFF_HS
+ * @return true : succeed, false : not succeed
+ */
+ public boolean setFlowControl(int channel, int flowControl) {
+ if(mDeviceConnection == null) {
+ return false;
+ }
+
+ if(CH_A > channel || channel > CH_D) {
+ return false;
+ }
+
+ if( flowControl == FTDI_SET_FLOW_CTRL_NONE ||
+ flowControl == FTDI_SET_FLOW_RTS_CTS_HS ||
+ flowControl == FTDI_SET_FLOW_DTR_DSR_HS ||
+ flowControl == FTDI_SET_FLOW_XON_XOFF_HS
+ ) {
+ if(mDeviceConnection.controlTransfer(0x40, 0x02, 0x0000, channel, null, 0, 0)<0) {
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets the serial properties to an FTDI chip register
+ *
+ * @param channel
+ * CH_A
+ * CH_B
+ * CH_C
+ * CH_D
+ * @return true : succeed, false : not succeed
+ */
+ public boolean setSerialPropertyToChip(int channel) {
+ // TODO : test this method
+ if(mDeviceConnection == null) {
+ return false;
+ }
+
+ if(CH_A > channel || channel > CH_D) {
+ return false;
+ }
+
+ if(mDeviceConnection.controlTransfer(0x40, 0x04, mSerialProperty[channel-1], channel, null, 0, 0)<0) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Sets the serial property of data bit
+ *
+ * @param numOfDataBit : number of data bit(8 or 7)
+ * @param channel
+ * CH_A
+ * CH_B
+ * CH_C
+ * CH_D
+ * @return true : succeed, false : not succeed
+ */
+ public boolean setSerialPropertyDataBit(int numOfDataBit, int channel) {
+ // TODO : test this method
+ if((0 < numOfDataBit) || (numOfDataBit <= 8)) {
+ mSerialProperty[channel-1] = (mSerialProperty[channel-1] & 0xFFF0) | (numOfDataBit & 0x000F);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets the serial property of parity bit
+ *
+ * @param parity
+ * none : FTDI_SET_DATA_PARITY_NONE
+ * odd : FTDI_SET_DATA_PARITY_ODD
+ * even : FTDI_SET_DATA_PARITY_EVEN
+ * mark : FTDI_SET_DATA_PARITY_MARK
+ * space : FTDI_SET_DATA_PARITY_SPACE
+ * @param channel
+ * CH_A
+ * CH_B
+ * CH_C
+ * CH_D
+ * @return true : succeed, false : not succeed
+ */
+ public boolean setSerialPropertyParity(int parity, int channel) {
+ // TODO : test this method
+ if( parity == FTDI_SET_DATA_PARITY_NONE ||
+ parity == FTDI_SET_DATA_PARITY_ODD ||
+ parity == FTDI_SET_DATA_PARITY_EVEN ||
+ parity == FTDI_SET_DATA_PARITY_MARK ||
+ parity == FTDI_SET_DATA_PARITY_SPACE
+ ) {
+ mSerialProperty[channel-1] = (mSerialProperty[channel-1] & 0xFF8F) | (parity & 0x0070);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets the serial property of stop bits
+ *
+ * @param stopBits
+ * 1 : FTDI_SET_DATA_STOP_BITS_1
+ * 1.5 : FTDI_SET_DATA_STOP_BITS_15
+ * 2 : FTDI_SET_DATA_STOP_BITS_2
+ * @param channel
+ * CH_A
+ * CH_B
+ * CH_C
+ * CH_D
+ * @return true : succeed, false : not succeed
+ */
+ public boolean setSerialPropertyStopBits(int stopBits, int channel) {
+ // TODO : test this method
+ if( stopBits == FTDI_SET_DATA_STOP_BITS_1 ||
+ stopBits == FTDI_SET_DATA_STOP_BITS_15 ||
+ stopBits == FTDI_SET_DATA_STOP_BITS_2
+ ) {
+ mSerialProperty[channel-1] = (mSerialProperty[channel-1] & 0xFC7F) | (stopBits & 0x0380);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Sets the serial property of TX ON/OFF
+ *
+ * @param tx
+ * TX OFF : FTDI_SET_NOBREAK
+ * TX ON : FTDI_SET_BREAK
+ * @param channel
+ * CH_A
+ * CH_B
+ * CH_C
+ * CH_D
+ * @return true : succeed, false : not succeed
+ */
+ public boolean setSerialPropertyBreak(int tx, int channel) {
+ // TODO : test this method
+ if( tx == FTDI_SET_NOBREAK ||
+ tx == FTDI_SET_BREAK
+ ) {
+ mSerialProperty[channel-1] = (mSerialProperty[channel-1] & 0xFBFF) | (tx & 0x0400);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /* Calculate a Divisor at 48MHz
+ * 9600 : 0x4138
+ * 11400 : 0xc107
+ * 19200 : 0x809c
+ * 38400 : 0xc04e
+ * 57600 : 0x0034
+ * 115200 : 0x001a
+ * 230400 : 0x000d
+ */
+ private int calcFTDIBaudrate(int baud, FTDICHIPTYPE chiptype) {
+ int divisor = 0;
+ if( chiptype == FTDICHIPTYPE.FT232RL || chiptype == FTDICHIPTYPE.FT2232C || chiptype == FTDICHIPTYPE.FT230X ){
+ if(baud <= 3000000) {
+ divisor = calcFT232bmBaudBaseToDiv(baud, 48000000);
+ } else {
+ Log.e(TAG,"Cannot set baud rate : " + baud + ", because too high." );
+ Log.e(TAG,"Set baud rate : 9600" );
+ divisor = calcFT232bmBaudBaseToDiv(9600, 48000000);
+ }
+ }else if (chiptype == FTDICHIPTYPE.FT232H){
+ if(baud <= 12000000 && baud >= 1200) {
+ divisor = calcFT232hBaudBaseToDiv(baud, 120000000);
+ } else {
+ Log.e(TAG,"Cannot set baud rate : " + baud + ", because too high." );
+ Log.e(TAG,"Set baud rate : 9600" );
+ divisor = calcFT232hBaudBaseToDiv(9600, 120000000);
+ }
+ }
+ return divisor;
+ }
+
+ // Calculate a divisor from baud rate and base clock for FT232BM, FT2232C and FT232LR
+ // thanks to @titoi2
+ private int calcFT232bmBaudBaseToDiv(int baud, int base) {
+ int divisor;
+ divisor = (base / 16 / baud)
+ | (((base / 2 / baud) & 4) != 0 ? 0x4000 // 0.5
+ : ((base / 2 / baud) & 2) != 0 ? 0x8000 // 0.25
+ : ((base / 2 / baud) & 1) != 0 ? 0xc000 // 0.125
+ : 0);
+ return divisor;
+ }
+ // Calculate a divisor from baud rate and base clock for FT2232H and FT232H
+ // thanks to @yakagawa
+ private int calcFT232hBaudBaseToDiv(int baud, int base) {
+ int divisor3, divisor;
+ divisor = (base / 10 / baud);
+ divisor3 = divisor * 8;
+ divisor |= ((divisor3 & 4) != 0 ? 0x4000 // 0.5
+ : (divisor3 & 2) != 0 ? 0x8000 // 0.25
+ : (divisor3 & 1) != 0 ? 0xc000 // 0.125
+ : 0);
+
+// divisor |= 0x00020000;
+ divisor &= 0xffff;
+ return divisor;
+ }
+
+ private boolean setFTDIEndpoints(UsbInterface[] intf, int portNum) {
+ UsbEndpoint epIn;
+ UsbEndpoint epOut;
+
+ if(intf[0] == null) {
+ return false;
+ }
+
+ for(int i=0; i<portNum; ++i) {
+ epIn = intf[i].getEndpoint(0);
+ epOut = intf[i].getEndpoint(1);
+
+ if(epIn != null && epOut != null) {
+ mFTDIEndpointIN[i] = epIn;
+ mFTDIEndpointOUT[i] = epOut;
+ } else {
+ return false;
+ }
+ }
+ return true;
+
+ }
+
+ // Sets the current USB device and interface
+ private boolean setUSBInterface(UsbDevice device, UsbInterface intf, int intfNum) {
+ if (mDeviceConnection != null) {
+ if (mInterface[intfNum] != null) {
+ mDeviceConnection.releaseInterface(mInterface[intfNum]);
+ mInterface[intfNum] = null;
+ }
+ mDeviceConnection.close();
+ mDevice = null;
+ mDeviceConnection = null;
+ }
+
+ if (device != null && intf != null) {
+ UsbDeviceConnection connection = mManager.openDevice(device);
+ if (connection != null) {
+ Log.d(TAG,"open succeeded");
+ if (connection.claimInterface(intf, false)) {
+ Log.d(TAG,"claim interface succeeded");
+
+ // TODO: support any connections(current version find a first device)
+ for(UsbId usbids : IDS) {
+ if(device.getVendorId() == usbids.mVid && device.getProductId() == usbids.mPid) {
+ Log.d(TAG,"Vendor ID : "+device.getVendorId());
+ Log.d(TAG,"Product ID : "+device.getProductId());
+ mDevice = device;
+ mDeviceConnection = connection;
+ mInterface[intfNum] = intf;
+ return true;
+ }
+ }
+ } else {
+ Log.d(TAG,"claim interface failed");
+ connection.close();
+ }
+ } else {
+ Log.d(TAG,"open failed");
+ }
+ }
+
+ return false;
+ }
+
+ // find any interfaces and set mInterface
+ private boolean getUsbInterfaces(UsbDevice device){
+ UsbInterface[] intf = new UsbInterface[FTDI_MAX_INTERFACE_NUM];
+ for(UsbId usbids : IDS){
+ intf = findUSBInterfaceByVIDPID(device, usbids.mVid, usbids.mPid);
+ if (intf[0] != null) {
+ for(int i=0; i<usbids.mNumOfChannels; ++i) {
+ Log.d(TAG, "Found USB interface " + intf[i]);
+ setUSBInterface(device, intf[i], i);
+ mSelectedDeviceInfo = usbids;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // searches for an interface on the given USB device by VID and PID
+ private UsbInterface[] findUSBInterfaceByVIDPID(UsbDevice device,int vid, int pid) {
+ Log.d(TAG, "findUSBInterface " + device);
+ UsbInterface[] retIntf = new UsbInterface[FTDI_MAX_INTERFACE_NUM];
+ int j=0;
+ int count = device.getInterfaceCount();
+ for (int i = 0; i < count; i++) {
+ UsbInterface intf = device.getInterface(i);
+ if (device.getVendorId() == vid && device.getProductId() == pid) {
+ retIntf[j]=intf;
+ ++j;
+ }
+ }
+ return retIntf;
+ }
+
+ // get a device descriptor : bcdDevice
+ // need Android API Level 13
+/* private int getDescriptorBcdDevice() {
+ byte[] rowDesc = mDeviceConnection.getRawDescriptors();
+ return rowDesc[13] << 8 + rowDesc[12];
+ }
+*/
+ private PendingIntent mPermissionIntent;
+
+ /**
+ * Sets PendingIntent for requestPermission
+ *
+ * @param pi
+ * @see getPermission
+ */
+ public void setPermissionIntent(PendingIntent pi) {
+ mPermissionIntent = pi;
+ }
+
+ /**
+ * Gets an USB permission if no permission
+ *
+ * @param device
+ * @see setPermissionIntent
+ */
+ public void getPermission(UsbDevice device) {
+ if(device !=null && mPermissionIntent!=null) {
+ if(!mManager.hasPermission(device)) {
+ mManager.requestPermission(device, mPermissionIntent);
+ }
+ }
+ }
+
+ /**
+ * Gets number of channels
+ *
+ * @return Number of channels
+ */
+ public int getNumberOfChannels() {
+ if(mSelectedDeviceInfo!=null) {
+ return mSelectedDeviceInfo.mNumOfChannels;
+ } else {
+ return 0;
+ }
+ }
+
+ // when insert the device USB plug into a USB port
+ public boolean usbAttached(Intent intent) {
+ UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ return getUsbInterfaces(device);
+ }
+
+ // when remove the device USB plug from a USB port
+ public void usbDetached(Intent intent) {
+ UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ String deviceName = device.getDeviceName();
+ if (mDevice != null && mDevice.equals(deviceName)) {
+ Log.d(TAG, "USB interface removed");
+ setUSBInterface(null, null, 0);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright 2012 JAG-AKIBA
+
+ 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.
+*/
+
+/*
+ * Work with ksksue's FTDriver
+ * https://github.com/ksksue/FTDriver
+ *
+ */
+package org.ammlab.android.akbrobotuart;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.usb.UsbManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.SeekBar;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.CompoundButton;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.ToggleButton;
+import jp.ksksue.driver.serial.*;
+
+public class AKBrobotUARTActivity extends Activity implements OnClickListener {
+ private static final String TAG = "AKBroboUART";
+ private ToggleButton mToggleButton1;
+ private ToggleButton mToggleButton2;
+ private SeekBar mSeekBar1;
+ private SeekBar mSeekBar2;
+ private SeekBar mSeekBar3;
+ private TextView mText1;
+ private TextView mText2;
+ private TextView mText3;
+ private TextView mInValue;
+ private EditText mEditOutput;
+ private Spinner mSpinner1;
+ private Spinner mSpinner2;
+ private Spinner mSpinner3;
+ private Spinner mSpinner4;
+ private Button mButtonConfig;
+ private Button mButtonDin;
+ private Button mButtonAin;
+ private Button mButtonDout;
+ private Button mButtonAout;
+
+
+ FTDriver mSerial;
+ private boolean mStop=false;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ // get FTDI service
+ mSerial = new FTDriver((UsbManager)getSystemService(Context.USB_SERVICE));
+ // listen for new devices
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
+ filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
+ registerReceiver(mUsbReceiver, filter);
+
+ //\8f\89\8aú\89»\8e¸\94s
+ if(! mSerial.begin(FTDriver.BAUD115200)) {
+ unregisterReceiver(mUsbReceiver);
+ this.finish();
+ }
+
+ mToggleButton1 = (ToggleButton) findViewById(R.id.toggleButton1);
+ mToggleButton2 = (ToggleButton) findViewById(R.id.toggleButton2);
+ mSeekBar1 = (SeekBar) findViewById(R.id.seekBar1);
+ mSeekBar2 = (SeekBar) findViewById(R.id.seekBar2);
+ mSeekBar3 = (SeekBar) findViewById(R.id.seekBar3);
+ mSeekBar1.setProgress(50);
+ mSeekBar2.setProgress(50);
+ mSeekBar3.setProgress(50);
+
+ mText1 = (TextView) findViewById(R.id.textView1);
+ mText2 = (TextView) findViewById(R.id.textView2);
+ mText3 = (TextView) findViewById(R.id.textView3);
+ mInValue = (TextView) findViewById(R.id.labelinvalue);
+
+ mEditOutput = (EditText) findViewById(R.id.editOutput);
+
+ mSpinner1 = (Spinner) findViewById(R.id.spinner1);
+ mSpinner2 = (Spinner) findViewById(R.id.spinner2);
+ mSpinner3 = (Spinner) findViewById(R.id.spinner3);
+ mSpinner4 = (Spinner) findViewById(R.id.spinner4);
+
+ mButtonConfig = (Button)findViewById(R.id.buttonconfig);
+ mButtonDin = (Button)findViewById(R.id.buttondin);
+ mButtonAin = (Button)findViewById(R.id.buttonain);
+ mButtonDout = (Button)findViewById(R.id.buttondout);
+ mButtonAout = (Button)findViewById(R.id.buttonaout);
+
+ mButtonConfig.setOnClickListener(this);
+ mButtonDin.setOnClickListener(this);
+ mButtonAin.setOnClickListener(this);
+ mButtonDout.setOnClickListener(this);
+ mButtonAout.setOnClickListener(this);
+
+ //\83V\81[\83N\83o\81[\82ð\95Ï\8dX\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89
+ //for motor#0
+ mSeekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = 0;
+ byte direction = 0;
+ if( progress > 45 && progress < 55){
+ value = 0;
+ }else if(progress > 50){
+ value = ((progress - 50) * 255 / 50);
+ direction = 0;
+ }else{ //progress < 50
+ value = ((50 - progress) * 255 / 50);
+ direction = 1;
+ }
+ mText1.setText(String.format("%d", value));
+ sendCommand((byte)3,(byte)0,direction,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83j\83\85\81[\83g\83\89\83\8b
+ mSeekBar1.setProgress(50);
+ //motor#1\92â\8e~
+ sendCommand((byte)3,(byte)0,(byte)0,(byte)0);
+ }
+ });
+ //for motor#1
+ mSeekBar2.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = 0;
+ byte direction = 0;
+ if( progress > 45 && progress < 55){
+ value = 0;
+ }else if(progress > 50){
+ value = ((progress - 50) * 255 / 50);
+ direction = 0;
+ }else{ //progress < 50
+ value = ((50 - progress) * 255 / 50);
+ direction = 1;
+ }
+ mText2.setText(String.format("%d", value));
+ sendCommand((byte)3,(byte)1,direction,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83j\83\85\81[\83g\83\89\83\8b
+ mSeekBar2.setProgress(50);
+ //motor#1\92â\8e~
+ sendCommand((byte)3,(byte)1,(byte)0,(byte)0);
+ }
+ });
+
+ //for servo#0
+ mSeekBar3.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ // \83c\83}\83~\82ð\83h\83\89\83b\83O\82µ\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ int value = (180*progress/100);
+ mText3.setText(String.format("%d", value));
+ Log.d(TAG, "Servo0:"+value+","+(byte)value);
+ sendCommand((byte)5,(byte)0,(byte)0,(byte)value);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // \83c\83}\83~\82É\90G\82ê\82½\82Æ\82«\82É\8cÄ\82Î\82ê\82é
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // \97£\82µ\82½\82ç\83Z\83\93\83^\81[\82É
+ mSeekBar3.setProgress(50);
+ sendCommand((byte)5,(byte)0,(byte)0,(byte)90);
+ }
+ });
+ //\83{\83^\83\93\82ð\89\9f\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89(\83{\83^\83\931)
+ mToggleButton1.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ sendCommand((byte)4,(byte)0,(byte)0,(byte)(isChecked ? 0x1 : 0x0));
+ }
+ });
+ //\83{\83^\83\93\82ð\89\9f\82µ\82½\82Æ\82«\82Ì\83n\83\93\83h\83\89(\83{\83^\83\932)
+ mToggleButton2.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ sendCommand((byte)4,(byte)1,(byte)0,(byte)(isChecked ? 0x1 : 0x0));
+ }
+ });
+
+ }
+
+ // BroadcastReceiver when insert/remove the device USB plug into/from a USB port
+ BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG,"BroadcastReceiver.onReceive()");
+ String action = intent.getAction();
+ if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
+ mSerial.usbAttached(intent);
+ mSerial.begin(FTDriver.BAUD115200);
+ } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
+ mSerial.usbDetached(intent);
+ mSerial.end();
+ mStop=true;
+ }
+ }
+ };
+
+ public void sendCommand(byte command1, byte command2, byte value1, byte value2) {
+ //\83f\83o\83C\83X\82ª\92â\8e~\92\86\82Ì\8fê\8d\87\82Í\89½\82à\82µ\82È\82¢\82Å\83\8a\83^\81[\83\93
+ if( mStop == true){
+ return;
+ }
+ byte[] buffer = new byte[4];
+ buffer[0] = command1;
+ buffer[1] = command2;
+ buffer[2] = value1;
+ buffer[3] = value2;
+ mSerial.write(buffer,4);
+ }
+ public int recvData(byte command1, byte command2) {
+ //\83f\83o\83C\83X\82ª\92â\8e~\92\86\82Ì\8fê\8d\87\82Í\89½\82à\82µ\82È\82¢\82Å\83\8a\83^\81[\83\93
+ if( mStop == true){
+ return 0;
+ }
+ byte[] buffer = new byte[4];
+ //flush receive buffer
+ while(mSerial.read(buffer) > 0){
+ ;
+ }
+ buffer[0] = command1;
+ buffer[1] = command2;
+ buffer[2] = 0;
+ buffer[3] = 0;
+ mSerial.write(buffer,4);
+ int rbytes = 0;
+ do{
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ rbytes = mSerial.read(buffer);
+ }while( rbytes == 0);
+ int val = buffer[2] & 0xff;
+ val = val * 256 + (buffer[3] & 0xff);
+ Log.d(TAG, "data received:"+rbytes+","+buffer[0]+","+buffer[1]+","+buffer[2]+","+buffer[3]+","+val);
+ return val;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if( view == mButtonConfig ){
+ long port = mSpinner1.getSelectedItemId();
+ long mode = mSpinner2.getSelectedItemId();
+ byte p = getPort(port, 256);
+ Log.d(TAG, "Primitive:"+port+","+p+","+mode);
+ sendCommand((byte)0, p, (byte)0, (byte)mode);
+ }else if( view == mButtonDout){
+ long port = mSpinner4.getSelectedItemId();
+ String value = mEditOutput.getText().toString();
+ byte p = getPort(port, 0);
+ if( value != null && value.length() > 0){
+ byte v = (byte)(int)Integer.valueOf(value);
+ Log.d(TAG, "DigitalOut:"+port+","+p+","+v);
+ sendCommand((byte)1, p, (byte)0, (byte)v);
+ }
+ }else if( view == mButtonAout){
+ long port = mSpinner4.getSelectedItemId();
+ String value = mEditOutput.getText().toString();
+ byte p = getPort(port, 1);
+ if( value != null && value.length() > 0){
+ byte v = (byte)(int)Integer.valueOf(value);
+ Log.d(TAG, "AnalogOut:"+port+","+p+","+v);
+ sendCommand((byte)1, p, (byte)0, (byte)v);
+ }
+ }else if( view == mButtonDin){
+ long port = mSpinner3.getSelectedItemId();
+ byte p = getPort(port, 2);
+ int val = recvData((byte)2, p);
+ Log.d(TAG, "DigitalIn:"+port+","+p+":"+val);
+ mInValue.setText(String.valueOf(val));
+ }else if( view == mButtonAin){
+ long port = mSpinner3.getSelectedItemId();
+ byte p = getPort(port, 3);
+ int val = recvData((byte)2, p);
+ Log.d(TAG, "AnalogIn:"+port+","+p+":"+val);
+ mInValue.setText(String.valueOf(val));
+ }else{
+ Log.d(TAG, "Ignore click:"+view.toString());
+ }
+ }
+
+ private byte getPort(long port, long type){//type(0:DigitalOut, 1:AnalogOut, 2:DigitalIn, 3:AnalogIn, 256:config)
+ byte ConfigPort=-1;
+ long limitDigtal = 6;
+ if(type == 0 || type == 2 || type == 256){ //Digital Port
+ if(port > limitDigtal){ //Analog Port
+ ConfigPort = (byte) (port - limitDigtal -1 + 0x40);
+ }else{
+ ConfigPort = (byte) port;
+ }
+ }else if( type == 1 ){//Analog Out Port
+ ConfigPort = (byte)(port + 0x80);
+ }else{ //AnalogIn Port
+ if( port > limitDigtal){
+ ConfigPort = (byte)(port - limitDigtal -1 + 0x80);
+ }
+ }
+ return ConfigPort;
+ }
+}
\ No newline at end of file
--- /dev/null
+日本Androidの会 秋葉原支部 ロボット部
+コアモジュール(モータドライバー)
+・Android - 操作用Androidアプリ
+ 必要なアプリソースをimport->ExistingProjects into Workspaceで取り込む