diff --git a/SensorLib/app/src/main/java/de/fau/sensorlibtest/RxMainActivity.java b/SensorLib/app/src/main/java/de/fau/sensorlibtest/RxMainActivity.java new file mode 100644 index 00000000..3160a4e9 --- /dev/null +++ b/SensorLib/app/src/main/java/de/fau/sensorlibtest/RxMainActivity.java @@ -0,0 +1,184 @@ +/** + * Copyright (C) 2015-2016 Digital Sports Group, Friedrich-Alexander University Erlangen-Nuremberg (FAU). + *

+ * This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. If you reuse + * this code you have to keep or cite this comment. + */ +package de.fau.sensorlibtest; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.graphics.Color; +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import android.util.Log; + +import com.androidplot.xy.LineAndPointFormatter; +import com.androidplot.xy.PointLabelFormatter; +import com.androidplot.xy.SimpleXYSeries; +import com.androidplot.xy.XYPlot; + +import java.util.List; + +import de.fau.sensorlib.BleSensorManager; +import de.fau.sensorlib.SensorDataProcessor; +import de.fau.sensorlib.SensorFoundCallback; +import de.fau.sensorlib.SensorInfo; +import de.fau.sensorlib.dataframe.AccelDataFrame; +import de.fau.sensorlib.dataframe.AmbientDataFrame; +import de.fau.sensorlib.dataframe.SensorDataFrame; +import de.fau.sensorlib.enums.HardwareSensor; +import de.fau.sensorlib.enums.KnownSensor; +import de.fau.sensorlib.rx.RxSensorDataProcessor; +import de.fau.sensorlib.sensors.GenericBleSensor; +import de.fau.sensorlib.sensors.TekSensor; +import io.reactivex.functions.Consumer; + +/** + * A simple example application to demonstrate the use of the SensorLib. + */ +public class RxMainActivity extends AppCompatActivity +{ + + private static final String TAG = "SensorLib::TestApp"; + + GenericBleSensor mSensor; + + XYPlot mPlot; + SimpleXYSeries mPlotData; + + @SuppressLint("CheckResult") + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + try + { + BleSensorManager.checkBtLePermissions(this, true); + } catch (Exception e) + { + // TODO Really handle exception + e.printStackTrace(); + } + + mPlot = (XYPlot) findViewById(R.id.plotViewA); + mPlotData = new SimpleXYSeries("Sensor Values"); + mPlotData.useImplicitXVals(); + mPlot.addSeries(mPlotData, new LineAndPointFormatter(Color.rgb(100, 100, 200), null, null, new PointLabelFormatter(Color.DKGRAY))); + mPlot.setDomainLabel("Sample Index"); + mPlot.setRangeLabel("Value"); + mDataHandler.getNewDataObservable().forEach( + new Consumer() + { + @Override + public void accept(SensorDataFrame data) + { + + if (mPlotData.size() > 99) + { + mPlotData.removeFirst(); + } + + if (data instanceof AccelDataFrame) + { + AccelDataFrame adf = (AccelDataFrame) data; + mPlotData.addLast(null, adf.getAccelX()); + } + if (data instanceof AmbientDataFrame) + { + AmbientDataFrame adf = (AmbientDataFrame) data; + mPlotData.addLast(null, adf.getLight()); + } + + TekSensor.TekDataFrame df = (TekSensor.TekDataFrame) data; + Log.d(TAG, "DataFrame (" + df.getCounter() + "): " + df.toString()); + + // redraw the Plots: + mPlot.redraw(); + } + } + ); + } + + RxSensorDataProcessor mDataHandler = new RxSensorDataProcessor(); + + Activity getThis() + { + return this; + } + + @Override + protected void onResume() + { + super.onResume(); + + /*String tekMac = "52:4D:4B:5F:01:55"; + mSensor = new TekSensor(this, tekMac, mDataHandler); + mSensor.useHardwareSensor(HardwareSensor.ACCELEROMETER); + mSensor.useHardwareSensor(HardwareSensor.LIGHT); + try { + mSensor.connect(); + mSensor.startStreaming(); + } catch (Exception e) { + e.printStackTrace(); + }*/ + + + List list = BleSensorManager.getConnectableSensors(); + for (SensorInfo s : list) + { + Log.d(TAG, "Sensor found: " + s.getName()); + } + + try + { + BleSensorManager.searchBleDevices(new SensorFoundCallback() + { + public boolean onKnownSensorFound(SensorInfo sensor) + { + Log.d(TAG, "BLE Sensor found: " + sensor.getName()); + + // we check what kind of sensor we found + if (sensor.getDeviceClass() == KnownSensor.GENERIC_BLE) + { + // ignore default/unknown BLE sensors + //if (sensor.getDeviceName().contains("miCoach")) { + + } else if (sensor.getDeviceClass() == KnownSensor.TEK) + { + // this is a TEK sensor, create and connect it. + mSensor = new TekSensor(getThis(), sensor, mDataHandler); + mSensor.useHardwareSensor(HardwareSensor.ACCELEROMETER); + mSensor.useHardwareSensor(HardwareSensor.LIGHT); + try + { + mSensor.connect(); + mSensor.startStreaming(); + } catch (Exception e) + { + e.printStackTrace(); + } + return false; + } + return true; + } + }); + } catch (Exception e) + { + e.printStackTrace(); + } + } + + @Override + protected void onPause() + { + if (mSensor != null) + { + mSensor.disconnect(); + } + super.onPause(); + } +} diff --git a/SensorLib/build.gradle b/SensorLib/build.gradle index 7f4d55e7..179c1744 100644 --- a/SensorLib/build.gradle +++ b/SensorLib/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.android.tools.build:gradle:3.3.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/SensorLib/rxsensorlib/.gitignore b/SensorLib/rxsensorlib/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/SensorLib/rxsensorlib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/SensorLib/rxsensorlib/build.gradle b/SensorLib/rxsensorlib/build.gradle new file mode 100644 index 00000000..5667010f --- /dev/null +++ b/SensorLib/rxsensorlib/build.gradle @@ -0,0 +1,41 @@ +apply plugin: 'com.android.library' +apply plugin: 'com.github.dcendents.android-maven' + +group='com.github.gradlman.SensorLib' +version = '1.0' + +android { + compileSdkVersion 27 + + + + defaultConfig { + minSdkVersion 21 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + api 'io.reactivex.rxjava2:rxandroid:2.1.0' + api 'io.reactivex.rxjava2:rxjava:2.2.6' + implementation 'androidx.appcompat:appcompat:1.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + api project(path: ':sensorlib') +} diff --git a/SensorLib/rxsensorlib/proguard-rules.pro b/SensorLib/rxsensorlib/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/SensorLib/rxsensorlib/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/SensorLib/rxsensorlib/src/androidTest/java/de/fau/sensorlib/rx/ExampleInstrumentedTest.java b/SensorLib/rxsensorlib/src/androidTest/java/de/fau/sensorlib/rx/ExampleInstrumentedTest.java new file mode 100644 index 00000000..840d227c --- /dev/null +++ b/SensorLib/rxsensorlib/src/androidTest/java/de/fau/sensorlib/rx/ExampleInstrumentedTest.java @@ -0,0 +1,28 @@ +package de.fau.sensorlib.rx; + +import android.content.Context; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest +{ + @Test + public void useAppContext() + { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("de.fau.sensorlib.rx.test", appContext.getPackageName()); + } +} diff --git a/SensorLib/rxsensorlib/src/main/AndroidManifest.xml b/SensorLib/rxsensorlib/src/main/AndroidManifest.xml new file mode 100644 index 00000000..b805ad33 --- /dev/null +++ b/SensorLib/rxsensorlib/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/SensorLib/rxsensorlib/src/main/java/de/fau/sensorlib/rx/RxSensorDataProcessor.java b/SensorLib/rxsensorlib/src/main/java/de/fau/sensorlib/rx/RxSensorDataProcessor.java new file mode 100644 index 00000000..e3ca9df4 --- /dev/null +++ b/SensorLib/rxsensorlib/src/main/java/de/fau/sensorlib/rx/RxSensorDataProcessor.java @@ -0,0 +1,123 @@ +package de.fau.sensorlib.rx; + +import de.fau.sensorlib.SensorDataProcessor; +import de.fau.sensorlib.dataframe.SensorDataFrame; +import de.fau.sensorlib.sensors.AbstractSensor; +import io.reactivex.Observable; +import io.reactivex.subjects.PublishSubject; + +public class RxSensorDataProcessor extends SensorDataProcessor +{ + + public enum SensorState + { + CREATED, CONNECTING, CONNECTED, DISCONNECTED, CONNECTION_LOST, STREAMING_STARTED, STREAMING_STOPPED + } + + public static class SensorNotification + { + private final AbstractSensor sensor; + private final T notification; + + public SensorNotification(AbstractSensor sensor, T notification) + { + this.sensor = sensor; + this.notification = notification; + } + + public AbstractSensor getSensor() + { + return sensor; + } + + public T getNotification() + { + return notification; + } + } + + private PublishSubject> sensorStateSubject = PublishSubject.create(); + private PublishSubject> sensorSamplingRateSubject = PublishSubject.create(); + private PublishSubject> sensorNotificationSubject = PublishSubject.create(); + private PublishSubject newDataSubject = PublishSubject.create(); + + + @Override + public void onSensorCreated(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.CREATED)); + } + + @Override + public void onConnected(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.CONNECTED)); + } + + @Override + public void onConnecting(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.CONNECTING)); + } + + @Override + public void onDisconnected(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.DISCONNECTED)); + } + + @Override + public void onConnectionLost(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.CONNECTION_LOST)); + } + + @Override + public void onStartStreaming(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.STREAMING_STARTED)); + } + + @Override + public void onStopStreaming(AbstractSensor sensor) + { + sensorStateSubject.onNext(new SensorNotification(sensor, SensorState.STREAMING_STOPPED)); + } + + @Override + public void onSamplingRateChanged(AbstractSensor sensor, double newSamplingRate) + { + sensorSamplingRateSubject.onNext(new SensorNotification(sensor, newSamplingRate)); + } + + @Override + public void onNotify(AbstractSensor sensor, Object notification) + { + sensorNotificationSubject.onNext(new SensorNotification(sensor, notification)); + } + + @Override + public void onNewData(SensorDataFrame data) + { + newDataSubject.onNext(data); + } + + public Observable> getSensorStateObservable() + { + return sensorStateSubject; + } + + public Observable> getSensorSamplingRateObservable() + { + return sensorSamplingRateSubject; + } + + public Observable> getSensorNotificationObservable() + { + return sensorNotificationSubject; + } + + public Observable getNewDataObservable() { + return (Observable) newDataSubject; + } +} diff --git a/SensorLib/rxsensorlib/src/main/res/values/strings.xml b/SensorLib/rxsensorlib/src/main/res/values/strings.xml new file mode 100644 index 00000000..1e7011e0 --- /dev/null +++ b/SensorLib/rxsensorlib/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + RxSensorLib + diff --git a/SensorLib/rxsensorlib/src/test/java/de/fau/sensorlib/rx/ExampleUnitTest.java b/SensorLib/rxsensorlib/src/test/java/de/fau/sensorlib/rx/ExampleUnitTest.java new file mode 100644 index 00000000..bc138e39 --- /dev/null +++ b/SensorLib/rxsensorlib/src/test/java/de/fau/sensorlib/rx/ExampleUnitTest.java @@ -0,0 +1,19 @@ +package de.fau.sensorlib.rx; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest +{ + @Test + public void addition_isCorrect() + { + assertEquals(4, 2 + 2); + } +} diff --git a/SensorLib/sensorlib/build.gradle b/SensorLib/sensorlib/build.gradle index 62e28904..100c99ca 100644 --- a/SensorLib/sensorlib/build.gradle +++ b/SensorLib/sensorlib/build.gradle @@ -82,10 +82,10 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'org.apache.commons:commons-lang3:3.0' - api 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support:recyclerview-v7:27.1.1' - implementation 'com.android.support:cardview-v7:27.1.1' - implementation 'com.android.support:design:27.1.1' + api 'androidx.appcompat:appcompat:1.0.0' + implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'androidx.cardview:cardview:1.0.0' + implementation 'com.google.android.material:material:1.0.0' implementation 'com.github.hannesa2:MPAndroidChart:3.0.6' } diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleScanCallback.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleScanCallback.java index f8362e3d..6cf61041 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleScanCallback.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleScanCallback.java @@ -9,7 +9,7 @@ import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanResult; -import android.support.annotation.CallSuper; +import androidx.annotation.CallSuper; import android.util.Log; import android.util.SparseArray; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleSensorManager.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleSensorManager.java index e731a82f..5449362f 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleSensorManager.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/BleSensorManager.java @@ -20,8 +20,8 @@ import android.os.Build; import android.os.Handler; import android.os.ParcelUuid; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import java.util.ArrayList; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/SensorDataRecorder.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/SensorDataRecorder.java index 92b84a14..8e904b97 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/SensorDataRecorder.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/SensorDataRecorder.java @@ -4,7 +4,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.Environment; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import android.widget.Toast; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/sensors/AbstractSensor.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/sensors/AbstractSensor.java index 161e9709..592324a9 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/sensors/AbstractSensor.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/sensors/AbstractSensor.java @@ -10,7 +10,7 @@ import android.content.Context; import android.os.Handler; import android.os.Message; -import android.support.annotation.CallSuper; +import androidx.annotation.CallSuper; import android.util.Log; import java.util.ArrayList; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/GenericFileProvider.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/GenericFileProvider.java index 91ed754c..f64bdb0b 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/GenericFileProvider.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/GenericFileProvider.java @@ -8,7 +8,7 @@ package de.fau.sensorlib.widgets; -import android.support.v4.content.FileProvider; +import androidx.core.content.FileProvider; public class GenericFileProvider extends FileProvider { diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/RecorderShareDialog.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/RecorderShareDialog.java index 9b3a9176..0f6489f7 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/RecorderShareDialog.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/RecorderShareDialog.java @@ -12,8 +12,8 @@ import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; -import android.support.annotation.NonNull; -import android.support.v7.app.AlertDialog; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; import java.io.File; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorActionDialog.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorActionDialog.java index ac32a052..705f9020 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorActionDialog.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorActionDialog.java @@ -9,11 +9,11 @@ package de.fau.sensorlib.widgets; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; import android.util.Log; import android.view.LayoutInflater; import android.view.View; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoBar.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoBar.java index 0d92e564..727b892a 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoBar.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoBar.java @@ -11,12 +11,12 @@ import android.content.ContextWrapper; import android.graphics.Rect; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.v4.app.FragmentManager; -import android.support.v4.widget.TextViewCompat; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentManager; +import androidx.core.widget.TextViewCompat; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -250,4 +250,4 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State s outRect.set(spacing, spacing, spacing, spacing); } } -} \ No newline at end of file +} diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoDialog.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoDialog.java index 6fd43dab..058574ee 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoDialog.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorInfoDialog.java @@ -1,8 +1,8 @@ package de.fau.sensorlib.widgets; import android.os.Bundle; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; import android.text.Html; import android.view.LayoutInflater; import android.view.View; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPickerDialog.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPickerDialog.java index 2995c19d..cbd8253b 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPickerDialog.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPickerDialog.java @@ -14,16 +14,16 @@ import android.graphics.Typeface; import android.os.Bundle; import android.os.Handler; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v4.content.ContextCompat; -import android.support.v4.util.ArraySet; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.RecyclerView.Adapter; -import android.support.v7.widget.RecyclerView.ViewHolder; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.core.content.ContextCompat; +import androidx.collection.ArraySet; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.Adapter; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPlotter.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPlotter.java index a71624d3..2a0fbb52 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPlotter.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SensorPlotter.java @@ -11,14 +11,14 @@ import android.content.res.TypedArray; import android.graphics.Color; import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.content.ContextCompat; -import android.support.v4.graphics.ColorUtils; -import android.support.v7.widget.CardView; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.RecyclerView.ViewHolder; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView.ViewHolder; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SimulationPickerFragment.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SimulationPickerFragment.java index 5737f592..84f835ed 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SimulationPickerFragment.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/SimulationPickerFragment.java @@ -5,10 +5,10 @@ import android.content.DialogInterface; import android.os.Bundle; import android.os.Environment; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AppCompatActivity; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.appcompat.app.AppCompatActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -31,7 +31,7 @@ import de.fau.sensorlib.enums.KnownSensor; /** - * {@link android.support.v4.app.DialogFragment} that lists files for simulation. + * {@link DialogFragment} that lists files for simulation. */ public class SimulationPickerFragment extends DialogFragment implements View.OnClickListener { diff --git a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/StatusBar.java b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/StatusBar.java index 956a7472..2ea3c190 100644 --- a/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/StatusBar.java +++ b/SensorLib/sensorlib/src/main/java/de/fau/sensorlib/widgets/StatusBar.java @@ -9,7 +9,7 @@ import android.content.Context; import android.content.res.TypedArray; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.AttributeSet; import android.widget.RelativeLayout; import android.widget.TextView; diff --git a/SensorLib/sensorlib/src/main/res/layout/item_sensor_info_bar.xml b/SensorLib/sensorlib/src/main/res/layout/item_sensor_info_bar.xml index 21dc55bc..730979a5 100644 --- a/SensorLib/sensorlib/src/main/res/layout/item_sensor_info_bar.xml +++ b/SensorLib/sensorlib/src/main/res/layout/item_sensor_info_bar.xml @@ -1,11 +1,11 @@ - + - \ No newline at end of file + diff --git a/SensorLib/sensorlib/src/main/res/layout/item_sensor_picker.xml b/SensorLib/sensorlib/src/main/res/layout/item_sensor_picker.xml index 1a9153f5..970cf249 100644 --- a/SensorLib/sensorlib/src/main/res/layout/item_sensor_picker.xml +++ b/SensorLib/sensorlib/src/main/res/layout/item_sensor_picker.xml @@ -1,11 +1,11 @@ - + - \ No newline at end of file + diff --git a/SensorLib/sensorlib/src/main/res/layout/widget_sensor_picker.xml b/SensorLib/sensorlib/src/main/res/layout/widget_sensor_picker.xml index 0c4e075d..70371979 100644 --- a/SensorLib/sensorlib/src/main/res/layout/widget_sensor_picker.xml +++ b/SensorLib/sensorlib/src/main/res/layout/widget_sensor_picker.xml @@ -30,7 +30,7 @@ - - \ No newline at end of file + diff --git a/SensorLib/sensorlib/src/main/res/layout/widget_sensor_plotter.xml b/SensorLib/sensorlib/src/main/res/layout/widget_sensor_plotter.xml index b934a7b3..74a95dfd 100644 --- a/SensorLib/sensorlib/src/main/res/layout/widget_sensor_plotter.xml +++ b/SensorLib/sensorlib/src/main/res/layout/widget_sensor_plotter.xml @@ -1,11 +1,11 @@ - + - - \ No newline at end of file + diff --git a/SensorLib/sensorlib/src/main/res/layout/widget_streaming_footer.xml b/SensorLib/sensorlib/src/main/res/layout/widget_streaming_footer.xml index 4f605b75..211fec5e 100644 --- a/SensorLib/sensorlib/src/main/res/layout/widget_streaming_footer.xml +++ b/SensorLib/sensorlib/src/main/res/layout/widget_streaming_footer.xml @@ -38,7 +38,7 @@ tools:ignore="ButtonStyle" /> - - \ No newline at end of file + diff --git a/SensorLib/sensorlibutils/build.gradle b/SensorLib/sensorlibutils/build.gradle index fea25474..5b38ff40 100644 --- a/SensorLib/sensorlibutils/build.gradle +++ b/SensorLib/sensorlibutils/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' version = '1.0' android { @@ -23,7 +23,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' } tasks.create(name: 'copyApk', type: Copy) { diff --git a/SensorLib/settings.gradle b/SensorLib/settings.gradle index 7d3bf12b..e8f1e9ba 100644 --- a/SensorLib/settings.gradle +++ b/SensorLib/settings.gradle @@ -1,4 +1,4 @@ -include ':sensorlibutils', ':sensorlib', ':sls-tek', ':sls-fitnessshirt', ':sls-shimmer', ':sls-smartwatch', ':sls-simblee', ':sls-smartband2', ':sls-bitalino', ':sls-portabiles' +include ':sensorlibutils', ':sensorlib', ':sls-tek', ':sls-fitnessshirt', ':sls-shimmer', ':sls-smartwatch', ':sls-simblee', ':sls-smartband2', ':sls-bitalino', ':sls-portabiles', ':rxsensorlib' if (!fileTree(dir: 'sls-empatica/libs', include: 'empalink*.aar').isEmpty()) { include ':sls-empatica' } diff --git a/SensorLib/sls-empatica/build.gradle b/SensorLib/sls-empatica/build.gradle index a13d334d..b17e2e0f 100644 --- a/SensorLib/sls-empatica/build.gradle +++ b/SensorLib/sls-empatica/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { compileSdkVersion 27 diff --git a/SensorLib/sls-fitnessshirt/build.gradle b/SensorLib/sls-fitnessshirt/build.gradle index e274e4b0..47b40fd4 100644 --- a/SensorLib/sls-fitnessshirt/build.gradle +++ b/SensorLib/sls-fitnessshirt/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { compileSdkVersion 27 @@ -23,7 +23,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' } tasks.create(name: 'copyApk', type: Copy) { diff --git a/SensorLib/sls-muse/build.gradle b/SensorLib/sls-muse/build.gradle index 541f74ce..be2c77bf 100644 --- a/SensorLib/sls-muse/build.gradle +++ b/SensorLib/sls-muse/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { compileSdkVersion 27 diff --git a/SensorLib/sls-myo/build.gradle b/SensorLib/sls-myo/build.gradle index e7106410..f03bd39f 100644 --- a/SensorLib/sls-myo/build.gradle +++ b/SensorLib/sls-myo/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { compileSdkVersion 27 diff --git a/SensorLib/sls-portabiles/build.gradle b/SensorLib/sls-portabiles/build.gradle index eeaf5b41..344ec236 100644 --- a/SensorLib/sls-portabiles/build.gradle +++ b/SensorLib/sls-portabiles/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { compileSdkVersion 27 @@ -22,7 +22,7 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'com.google.code.gson:gson:2.8.5' } diff --git a/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionByteWriter.java b/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionByteWriter.java index d5a5cb7c..24a8e431 100644 --- a/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionByteWriter.java +++ b/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionByteWriter.java @@ -12,7 +12,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.Environment; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import android.widget.Toast; diff --git a/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionDownloadChecker.java b/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionDownloadChecker.java index 81dfd0de..65b7cf63 100644 --- a/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionDownloadChecker.java +++ b/SensorLib/sls-portabiles/src/main/java/de/fau/sensorlib/sensors/logging/SessionDownloadChecker.java @@ -12,7 +12,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.Environment; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import android.widget.Toast; diff --git a/SensorLib/sls-shimmer/build.gradle b/SensorLib/sls-shimmer/build.gradle index d80b0647..55ae02e8 100644 --- a/SensorLib/sls-shimmer/build.gradle +++ b/SensorLib/sls-shimmer/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { compileSdkVersion 27 @@ -23,8 +23,10 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'com.google.guava:guava:22.0' + implementation 'org.apache.commons:commons-math:2.2' + } tasks.create(name: 'copyApk', type: Copy) { diff --git a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/algorithms/GradDes3DOrientation.java b/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/algorithms/GradDes3DOrientation.java deleted file mode 100644 index e2a9e176..00000000 --- a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/algorithms/GradDes3DOrientation.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.shimmerresearch.algorithms; -/* - * Madgwick, Sebastian OH, Andrew JL Harrison, and Ravi Vaidyanathan. "Estimation of imu and marg orientation using a gradient descent algorithm." Rehabilitation Robotics (ICORR), 2011 IEEE International Conference on. IEEE, 2011. - * - * 3D orientation code modified from https://code.google.com/p/labview-quaternion-ahrs/ which is licensed under GNU_Lesser_GPL - */ - - -public class GradDes3DOrientation { - - double mBeta = 1; - double mSamplingPeriod = 1; - double q1, q2, q3, q4; - - public GradDes3DOrientation(double beta, double samplingPeriod, double q1, double q2, double q3, double q4) { - mBeta = beta; - this.q1 = q1; - this.q2 = q2; - this.q3 = q3; - this.q4 = q4; - mSamplingPeriod = samplingPeriod; - } - - - public Quaternion update(double ax, double ay, double az, double gx, double gy, double gz, double mx, double my, double mz) { - - - double norm; - double hx, hy, _2bx, _2bz; - double s1, s2, s3, s4; - double qDot1, qDot2, qDot3, qDot4; - - double _4bx, _4bz; - double q1q1, q1q2, q1q3, q1q4, q2q2, q2q3, q2q4, q3q3, q3q4, q4q4, _2q1q3, _2q3q4; - - _2q1q3 = 2.0 * q1 * q3; - _2q3q4 = 2.0 * q3 * q4; - q1q1 = q1 * q1; - q1q2 = q1 * q2; - q1q3 = q1 * q3; - q1q4 = q1 * q4; - q2q2 = q2 * q2; - q2q3 = q2 * q3; - q2q4 = q2 * q4; - q3q3 = q3 * q3; - q3q4 = q3 * q4; - q4q4 = q4 * q4; - - // Normalise accelerometer measurement - norm = Math.sqrt(ax * ax + ay * ay + az * az); - if (norm > 0.0) { - norm = 1.0 / norm; - ax *= norm; - ay *= norm; - az *= norm; - } else { - - } - - // Normalise magnetometer measurement - norm = Math.sqrt(mx * mx + my * my + mz * mz); - if (norm > 0.0) { - norm = 1.0 / norm; - mx *= norm; - my *= norm; - mz *= norm; - } else { - - } - - - hx = mx * q1q1 - (2 * q1 * my) * q4 + (2 * q1 * mz) * q3 + mx * q2q2 + (2.0 * q2) * my * q3 + (2.0 * q2) * mz * q4 - mx * q3q3 - mx * q4q4; - hy = (2 * q1 * mx) * q4 + my * q1q1 - (2 * q1 * mz) * q2 + (2 * q2 * mx) * q3 - my * q2q2 + my * q3q3 + (2.0 * q3) * mz * q4 - my * q4q4; - _2bx = Math.sqrt(hx * hx + hy * hy); - _2bz = -(2 * q1 * mx) * q3 + (2 * q1 * my) * q2 + mz * q1q1 + (2 * q2 * mx) * q4 - mz * q2q2 + (2.0 * q3) * my * q4 - mz * q3q3 + mz * q4q4; - _4bx = 2 * _2bx; - _4bz = 2 * _2bz; - - // Corrective step - s1 = -(2.0 * q3) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q2) * (2.0 * q1q2 + _2q3q4 - ay) - _2bz * q3 * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q4 + _2bz * q2) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q3 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); - s2 = (2.0 * q4) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q1) * (2.0 * q1q2 + _2q3q4 - ay) - 4.0 * q2 * (1.0 - 2.0 * q2q2 - 2.0 * q3q3 - az) + _2bz * q4 * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q3 + _2bz * q1) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q4 - _4bz * q2) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); - s3 = -(2.0 * q1) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q4) * (2.0 * q1q2 + _2q3q4 - ay) - 4.0 * q3 * (1.0 - 2.0 * q2q2 - 2.0 * q3q3 - az) + (-_4bx * q3 - _2bz * q1) * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q2 + _2bz * q4) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q1 - _4bz * q3) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); - s4 = (2.0 * q2) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q3) * (2.0 * q1q2 + _2q3q4 - ay) + (-_4bx * q4 + _2bz * q2) * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q1 + _2bz * q3) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q2 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); - - norm = 1.0 / Math.sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4); // normalise - s1 *= norm; - s2 *= norm; - s3 *= norm; - s4 *= norm; - - // Compute rate of change of quaternion - qDot1 = 0.5 * (-q2 * gx - q3 * gy - q4 * gz) - mBeta * s1; - qDot2 = 0.5 * (q1 * gx + q3 * gz - q4 * gy) - mBeta * s2; - qDot3 = 0.5 * (q1 * gy - q2 * gz + q4 * gx) - mBeta * s3; - qDot4 = 0.5 * (q1 * gz + q2 * gy - q3 * gx) - mBeta * s4; - - // Integrate to yield quaternion - q1 += qDot1 * mSamplingPeriod; - q2 += qDot2 * mSamplingPeriod; - q3 += qDot3 * mSamplingPeriod; - q4 += qDot4 * mSamplingPeriod; - norm = 1.0 / Math.sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4); // normalise quaternion - - q1 = q1 * norm; - q2 = q2 * norm; - q3 = q3 * norm; - q4 = q4 * norm; - - - return new Quaternion(q1, q2, q3, q4); - } - - - public class Quaternion { - - public double q1, q2, q3, q4; - - public Quaternion(double q1, double q2, double q3, double q4) { - this.q1 = q1; - this.q2 = q2; - this.q3 = q3; - this.q4 = q4; - } - } - - -} diff --git a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/Configuration.java b/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/Configuration.java deleted file mode 100644 index 051620cc..00000000 --- a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/Configuration.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.shimmerresearch.driver; - -public class Configuration { - //Channel Contents - public static class Shimmer3 { - public class Channel { - public final static int XAAccel = 0x00; - public final static int YAAccel = 0x01; - public final static int ZAAccel = 0x02; - public final static int VBatt = 0x03; - public final static int XDAccel = 0x04; - public final static int YDAccel = 0x05; - public final static int ZDAccel = 0x06; - public final static int XMag = 0x07; - public final static int YMag = 0x08; - public final static int ZMag = 0x09; - public final static int XGyro = 0x0A; - public final static int YGyro = 0x0B; - public final static int ZGyro = 0x0C; - public final static int ExtAdc7 = 0x0D; - public final static int ExtAdc6 = 0x0E; - public final static int ExtAdc15 = 0x0F; - public final static int IntAdc1 = 0x10; - public final static int IntAdc12 = 0x11; - public final static int IntAdc13 = 0x12; - public final static int IntAdc14 = 0x13; - } - - public class SensorBitmap { - //Sensor Bitmap for Shimmer 3 - public static final int SENSOR_A_ACCEL_S3 = 0x80; - public static final int SENSOR_GYRO_S3 = 0x40; - public static final int SENSOR_VBATT_S3 = 0x2000; - public static final int SENSOR_MAG_S3 = 0x20; - public static final int SENSOR_D_ACCEL_S3 = 0x1000; - public static final int SENSOR_EXT_A7 = 0x02; - public static final int SENSOR_EXT_A6 = 0x01; - public static final int SENSOR_EXT_A15 = 0x0800; - public static final int SENSOR_INT_A1 = 0x0400; - public static final int SENSOR_INT_A12 = 0x0200; - public static final int SENSOR_INT_A13 = 0x0100; - public static final int SENSOR_INT_A14 = 0x800000; - } - - protected final static String[] ListofCompatibleSensors = {"Accelerometer", "Gyroscope", "Magnetometer", "Battery Voltage", "External ADC A7", "External ADC A6", "External ADC A15", "Internal ADC A1", "Internal ADC A12", "Internal ADC A13", "Internal ADC A14"}; - protected final static String[] ListofCompatibleSensorsAccelDualMode = {"Low Noise Accelerometer", "Wide Range Accelerometer", "Gyroscope", "Magnetometer", "Battery Voltage", "External ADC A7", "External ADC A6", "External ADC A15", "Internal ADC A1", "Internal ADC A12", "Internal ADC A13", "Internal ADC A14"}; - public final static String[] ListofAccelRange = {"+/- 2g", "+/- 4g", "+/- 8g", "+/- 16g"}; - public final static String[] ListofGyroRange = {"250dps", "500dps", "1000dps", "2000dps"}; - public final static String[] ListofMagRange = {"+/- 1.3Ga", "+/- 1.9Ga", "+/- 2.5Ga", "+/- 4.0Ga", "+/- 4.7Ga", "+/- 5.6Ga", "+/- 8.1Ga"}; - } - - public static class Shimmer2 { - public class Channel { - public final static int XAccel = 0x00; - public final static int YAccel = 0x01; - public final static int ZAccel = 0x02; - public final static int XGyro = 0x03; - public final static int YGyro = 0x04; - public final static int ZGyro = 0x05; - public final static int XMag = 0x06; - public final static int YMag = 0x07; - public final static int ZMag = 0x08; - public final static int EcgRaLl = 0x09; - public final static int EcgLaLl = 0x0A; - public final static int GsrRaw = 0x0B; - public final static int GsrRes = 0x0C; - public final static int Emg = 0x0D; - public final static int AnExA0 = 0x0E; - public final static int AnExA7 = 0x0F; - public final static int StrainHigh = 0x10; - public final static int StrainLow = 0x11; - public final static int HeartRate = 0x12; - } - - public class SensorBitmap { - public static final int SENSOR_ACCEL = 0x80; - public static final int SENSOR_GYRO = 0x40; - public static final int SENSOR_MAG = 0x20; - public static final int SENSOR_ECG = 0x10; - public static final int SENSOR_EMG = 0x08; - public static final int SENSOR_GSR = 0x04; - public static final int SENSOR_EXP_BOARD_A7 = 0x02; - public static final int SENSOR_EXP_BOARD_A0 = 0x01; - public static final int SENSOR_STRAIN = 0x8000; - public static final int SENSOR_HEART = 0x4000; - - } - - protected final static String[] ListofCompatibleSensors = {"Accelerometer", "Gyroscope", "Magnetometer", "Battery Voltage", "ECG", "EMG", "GSR", "Exp Board", "Strain Gauge", "Heart Rate"}; - public final static String[] ListofAccelRange = {"+/- 1.5g", "+/- 6g"}; - public final static String[] ListofMagRange = {"+/- 0.8Ga", "+/- 1.3Ga", "+/- 1.9Ga", "+/- 2.5Ga", "+/- 4.0Ga", "+/- 4.7Ga", "+/- 5.6Ga", "+/- 8.1Ga"}; - } - - -} - - diff --git a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/FormatCluster.java b/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/FormatCluster.java deleted file mode 100644 index 26c96759..00000000 --- a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/FormatCluster.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.shimmerresearch.driver; - - -public class FormatCluster { - public String mFormat; - public String mUnits; - public double mData; - - public FormatCluster(String format, String units, double data) { - mFormat = format; - mUnits = units; - mData = data; - } - - public FormatCluster(String format, String units) { - mFormat = format; - mUnits = units; - } - - -} diff --git a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/ObjectCluster.java b/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/ObjectCluster.java deleted file mode 100644 index a76b358c..00000000 --- a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/ObjectCluster.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.shimmerresearch.driver; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - -import java.util.Collection; -import java.util.Iterator; - -public class ObjectCluster { - public Multimap mPropertyCluster = HashMultimap.create(); - public String mMyName; - public String mBluetoothAddress; - - public ObjectCluster(String myName) { - mMyName = myName; - } - - public ObjectCluster(String myName, String myBlueAdd) { - mMyName = myName; - mBluetoothAddress = myBlueAdd; - } - - /** - * Takes in a collection of Format Clusters and returns the Format Cluster specified by the string format - * - * @param collectionFormatCluster - * @param format - * @return FormatCluster - */ - public static FormatCluster returnFormatCluster(Collection collectionFormatCluster, String format) { - Iterator iFormatCluster = collectionFormatCluster.iterator(); - FormatCluster formatCluster; - FormatCluster returnFormatCluster = null; - - while (iFormatCluster.hasNext()) { - formatCluster = (FormatCluster) iFormatCluster.next(); - if (formatCluster.mFormat.equals(format)) { - returnFormatCluster = formatCluster; - } - } - return returnFormatCluster; - } - - -} diff --git a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/Shimmer.java b/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/Shimmer.java deleted file mode 100644 index c6b51f5f..00000000 --- a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/driver/Shimmer.java +++ /dev/null @@ -1,5105 +0,0 @@ -//1.1.3 - -/*Changes since beta 0.9 (1 January 2013) - * - * - Packet Reception Rate is now provided, whenever a packet loss detected a message is sent via handler, see MESSAGE_PACKET_LOSS_DETECTED - * - Changed Accel cal parameters - * - Added default cal parameters for the other accel ranges, if default accel range is being used, changing the accel range will change the defaults automatically as well - * - Revised the GSR calibration method, now uses a linear fit - * - Batt Voltage Monitoring - * - Sensor Conflict checks, have to wire the handler in order to see the msgs - * - Bug fix, timer wasnt triggering when waiting for response which was not received, causing the driver to get stuck in a loop - * - Added retrieve all,ecg & emg calibration parameters, only works with Boilerplate >= 1.0 - * - Rearranged the data reception section, to accommodate for in streaming ack detection - * - Added uncalibrated heart rate, which is a pulse now, with the value being the time difference between the last pulse and the current one - * - Updated the name of the formats, units and property names, so as to stay consistent with the rest of the instrument drivers - * - Low Battery Voltage warning at 3.4V where LED turns yellow - * - Added Packet Reception Rate monitoring - * - Added MESSAGE_NOT_SYNC for MSS support - * - Updated the initialization process, if a connection fails during the initialization process, disconnect is done immediately - * - Update Toggle LED - * - Switched to the use of createInsecureRfcommSocketToServiceRecord - * - ECG and EMG units have a * (mVolts*) as an indicator when default parameters are used - * - SR 30 support - * - Orientation - * - Support for low and high power Mag (high power == high sampling rate Mag) - * - Support for different mag range - * - Updated the execution model when transmitting commands, now uses a thread, and will improve Main UI thread latency - * - * Changes since beta 1.0 (21 May 2013) - * - Added support for on the fly gyro offset calibration - * - Added quartenions - * - Convert to an instruction stack format, no longer supports Boilerplate - * - * Changes since beta 1.0.1 (20 June 2013) - * - Fix the no response bug, through the use of the function dummyreadSamplingRate() - * - Updates to allow operation with Boilerplate - * - add get functions for lower power mag and gyro cal on the fly - * - * Changes since beta 1.0.2 (17 July 2013) - * - started integration with Shimmer 3, major changes include the use of i16* now. This indicates array of bytes where MSB is on the far left/smallest index number of the array. - * - minor fix to the stop streaming command, causing it to block the inputstream, and not being able to clear the bytes from minstream - * - added default calibration parameters for Shimmer 3 - * - added functionality for internal and external adc - * - added new constructor to support setup device on connect (Shimmer 3) - * - * Changes since beta 1.1.1 (17 July 2013) - * - - * - added support for dual accelerometer mode for Shimmer 3 - * - updated wide range accel from i12> to i16 and updated default calibration values - * - * Changes since beta 1.1.2 (1 Oct 2013) - * - mag gain command implemented for Shimmer2 - * */ - - -package com.shimmerresearch.driver; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothSocket; -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.util.Log; - -import com.google.common.collect.BiMap; -import com.google.common.collect.ImmutableBiMap; -import com.shimmerresearch.algorithms.GradDes3DOrientation; -import com.shimmerresearch.algorithms.GradDes3DOrientation.Quaternion; - -import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Stack; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; - -import javax.vecmath.Quat4d; -import javax.vecmath.Vector3d; - -import it.gerdavax.easybluetooth.BtSocket; -import it.gerdavax.easybluetooth.LocalDevice; -import it.gerdavax.easybluetooth.RemoteDevice; -//import java.io.FileOutputStream; - - -public class Shimmer { - //generic UUID for serial port protocol - private UUID mSPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - // Message types sent from the Shimmer Handler - public static final int MESSAGE_STATE_CHANGE = 1; - public static final int MESSAGE_READ = 2; - public static final int MESSAGE_WRITE = 3; - public static final int MESSAGE_ACK_RECEIVED = 4; - public static final int MESSAGE_DEVICE_NAME = 5; - public static final int MESSAGE_TOAST = 6; - public static final int MESSAGE_SAMPLING_RATE_RECEIVED = 7; - public static final int MESSAGE_INQUIRY_RESPONSE = 8; - public static final int MESSAGE_STOP_STREAMING_COMPLETE = 9; - public static final int MESSAGE_PACKET_LOSS_DETECTED = 11; - public static final int MESSAGE_NOT_SYNC = 12; - public static final int SHIMMER_1 = 0; - public static final int SHIMMER_2 = 1; - public static final int SHIMMER_2R = 2; - public static final int SHIMMER_3 = 3; - public static final int SHIMMER_SR30 = 4; - //Dual mode accelerometer options for Shimmer3 - public static final int ACCEL_SMART_MODE = 0; // this picks the best accelerometer depending on the accelerometer range selected - public static final int ACCEL_DUAL_MODE = 1; // this outputs 'Wide Range Accelerometer X' and 'Low Noise Accelerometer X' - public static final int ACCEL_DUAL_SMART_MODE = 2; // this picks the best accelerometer depending on the accelerometer range selected (as e.g. 'Accelerometer X') while also outputting both accelerometer data as (e.g 'Wide Range Accelerometer'), this is to keep backward compatibility with applications which rely on 'Accelerometer X' signal names - - // Key names received from the Shimmer Handler - public static final String TOAST = "toast"; - private boolean mInitialized = false; - private final BluetoothAdapter mAdapter; - public final Handler mHandler; - - private ConnectThread mConnectThread; - private ConnectedThread mConnectedThread; - private int mState; - private boolean mDummy = false; - //Arduino - private LocalDevice localDevice; - - // Constants that indicate the current connection state - public static final int STATE_NONE = 0; // The class is doing nothing - public static final int STATE_CONNECTING = 1; // The class is now initiating an outgoing connection - public static final int STATE_CONNECTED = 2; // The class is now connected to a remote device - public static final int MSG_STATE_FULLY_INITIALIZED = 3; // This is the connected state, indicating the device has establish a connection + tx/rx commands and reponses (Initialized) - public static final int MSG_STATE_STREAMING = 4; - public static final int MSG_STATE_STOP_STREAMING = 5; - //Sensor Bitmap for ID ; for the purpose of forward compatibility the sensor bitmap and the ID and the sensor bitmap for the Shimmer firmware has been kept separate, - public static final int SENSOR_ACCEL = 0x80; - public static final int SENSOR_DACCEL = 0x1000; //only - public static final int SENSOR_GYRO = 0x40; - public static final int SENSOR_MAG = 0x20; - public static final int SENSOR_ECG = 0x10; - public static final int SENSOR_EMG = 0x08; - public static final int SENSOR_GSR = 0x04; - public static final int SENSOR_EXP_BOARD_A7 = 0x02; - public static final int SENSOR_EXP_BOARD_A0 = 0x01; - public static final int SENSOR_EXP_BOARD = SENSOR_EXP_BOARD_A7 + SENSOR_EXP_BOARD_A0; - public static final int SENSOR_STRAIN = 0x8000; - public static final int SENSOR_HEART = 0x4000; - public static final int SENSOR_BATT = 0x2000; //THIS IS A DUMMY VALUE - public static final int SENSOR_EXT_ADC_A7 = 0x02; - public static final int SENSOR_EXT_ADC_A6 = 0x01; - public static final int SENSOR_EXT_ADC_A15 = 0x0800; - public static final int SENSOR_INT_ADC_A1 = 0x0400; - public static final int SENSOR_INT_ADC_A12 = 0x0200; - public static final int SENSOR_INT_ADC_A13 = 0x0100; - public static final int SENSOR_INT_ADC_A14 = 0x800000; - public BiMap mSensorBitmaptoName; - - { - final Map tempSensorBMtoName = new HashMap(); - tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); - tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); - tempSensorBMtoName.put(Integer.toString(SENSOR_STRAIN), "Strain Gauge"); - tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); - tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); - mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } - - - //Constants describing the packet type - private static final byte DATA_PACKET = (byte) 0x00; - private static final byte INQUIRY_COMMAND = (byte) 0x01; - private static final byte INQUIRY_RESPONSE = (byte) 0x02; - private static final byte GET_SAMPLING_RATE_COMMAND = (byte) 0x03; - private static final byte SAMPLING_RATE_RESPONSE = (byte) 0x04; - private static final byte SET_SAMPLING_RATE_COMMAND = (byte) 0x05; - private static final byte TOGGLE_LED_COMMAND = (byte) 0x06; - private static final byte START_STREAMING_COMMAND = (byte) 0x07; - private static final byte SET_SENSORS_COMMAND = (byte) 0x08; - private static final byte SET_ACCEL_SENSITIVITY_COMMAND = (byte) 0x09; - private static final byte ACCEL_SENSITIVITY_RESPONSE = (byte) 0x0A; - private static final byte GET_ACCEL_SENSITIVITY_COMMAND = (byte) 0x0B; - private static final byte SET_5V_REGULATOR_COMMAND = (byte) 0x0C; // only Shimmer 2 - private static final byte SET_PMUX_COMMAND = (byte) 0x0D; // only Shimmer 2 - private static final byte SET_CONFIG_BYTE0_COMMAND = (byte) 0x0E; - private static final byte CONFIG_BYTE0_RESPONSE = (byte) 0x0F; - private static final byte GET_CONFIG_BYTE0_COMMAND = (byte) 0x10; - private static final byte STOP_STREAMING_COMMAND = (byte) 0x20; - private static final byte ACCEL_CALIBRATION_RESPONSE = (byte) 0x12; - private static final byte LSM303DLHC_ACCEL_CALIBRATION_RESPONSE = (byte) 0x1B; - private static final byte GET_ACCEL_CALIBRATION_COMMAND = (byte) 0x13; - private static final byte GYRO_CALIBRATION_RESPONSE = (byte) 0x15; - private static final byte GET_GYRO_CALIBRATION_COMMAND = (byte) 0x16; - private static final byte MAG_CALIBRATION_RESPONSE = (byte) 0x18; - private static final byte GET_MAG_CALIBRATION_COMMAND = (byte) 0x19; - private static final byte SET_GSR_RANGE_COMMAND = (byte) 0x21; - private static final byte GSR_RANGE_RESPONSE = (byte) 0x22; - private static final byte GET_GSR_RANGE_COMMAND = (byte) 0x23; - private static final byte GET_SHIMMER_VERSION_COMMAND = (byte) 0x24; - private static final byte GET_SHIMMER_VERSION_COMMAND_NEW = (byte) 0x3F; //this is to avoid the $ char which is used by rn42 - private static final byte GET_SHIMMER_VERSION_RESPONSE = (byte) 0x25; - private static final byte SET_EMG_CALIBRATION_COMMAND = (byte) 0x26; - private static final byte EMG_CALIBRATION_RESPONSE = (byte) 0x27; - private static final byte GET_EMG_CALIBRATION_COMMAND = (byte) 0x28; - private static final byte SET_ECG_CALIBRATION_COMMAND = (byte) 0x29; - private static final byte ECG_CALIBRATION_RESPONSE = (byte) 0x2A; - private static final byte GET_ECG_CALIBRATION_COMMAND = (byte) 0x2B; - private static final byte GET_ALL_CALIBRATION_COMMAND = (byte) 0x2C; - private static final byte ALL_CALIBRATION_RESPONSE = (byte) 0x2D; - private static final byte GET_FW_VERSION_COMMAND = (byte) 0x2E; - private static final byte FW_VERSION_RESPONSE = (byte) 0x2F; - private static final byte SET_BLINK_LED = (byte) 0x30; - private static final byte BLINK_LED_RESPONSE = (byte) 0x31; - private static final byte GET_BLINK_LED = (byte) 0x32; - private static final byte SET_GYRO_TEMP_VREF_COMMAND = (byte) 0x33; - private static final byte SET_BUFFER_SIZE_COMMAND = (byte) 0x34; - private static final byte BUFFER_SIZE_RESPONSE = (byte) 0x35; - private static final byte GET_BUFFER_SIZE_COMMAND = (byte) 0x36; - private static final byte SET_MAG_GAIN_COMMAND = (byte) 0x37; - private static final byte MAG_GAIN_RESPONSE = (byte) 0x38; - private static final byte GET_MAG_GAIN_COMMAND = (byte) 0x39; - private static final byte SET_MAG_SAMPLING_RATE_COMMAND = (byte) 0x3A; - private static final byte MAG_SAMPLING_RATE_RESPONSE = (byte) 0x3B; - private static final byte GET_MAG_SAMPLING_RATE_COMMAND = (byte) 0x3C; - private static final byte SET_ACCEL_SAMPLING_RATE_COMMAND = (byte) 0x40; - private static final byte ACCEL_SAMPLING_RATE_RESPONSE = (byte) 0x41; - private static final byte GET_ACCEL_SAMPLING_RATE_COMMAND = (byte) 0x42; - private static final byte SET_LSM303DLHC_ACCEL_LPMODE_COMMAND = (byte) 0x43; - private static final byte LSM303DLHC_ACCEL_LPMODE_RESPONSE = (byte) 0x44; - private static final byte GET_LSM303DLHC_ACCEL_LPMODE_COMMAND = (byte) 0x45; - private static final byte SET_LSM303DLHC_ACCEL_HRMODE_COMMAND = (byte) 0x46; - private static final byte LSM303DLHC_ACCEL_HRMODE_RESPONSE = (byte) 0x47; - private static final byte GET_LSM303DLHC_ACCEL_HRMODE_COMMAND = (byte) 0x48; - private static final byte SET_MPU9150_GYRO_RANGE_COMMAND = (byte) 0x49; - private static final byte MPU9150_GYRO_RANGE_RESPONSE = (byte) 0x4A; - private static final byte GET_MPU9150_GYRO_RANGE_COMMAND = (byte) 0x4B; - private static final byte SET_MPU9150_SAMPLING_RATE_COMMAND = (byte) 0x4C; - - private static final byte ACK_COMMAND_PROCESSED = (byte) 0xff; - - public static final int MAX_NUMBER_OF_SIGNALS = 30; //used to be 11 but now 13 because of the SR30 + 8 for 3d orientation - private double mFWVersion; - private int mFWInternal; - private String mFWVersionFullName; - private final int ACK_TIMER_DURATION = 2; // Duration to wait for an ack packet (seconds) - - private double mLastReceivedTimeStamp = 0; - private double mCurrentTimeStampCycle = 0; - private boolean mStreaming = false; // This is used to monitor whether the device is in streaming mode - private double mSamplingRate; // 51.2Hz is the default sampling rate - protected int mEnabledSensors; // This stores the enabled sensors - private int tempEnabledSensors; // This stores the enabled sensors - private int mSetEnabledSensors = SENSOR_ACCEL; // Only used during the initialization process, see initialize(); - protected String mMyName; // This stores the user assigned name - private byte mCurrentCommand; // This variable is used to keep track of the current command being executed while waiting for an Acknowledge Packet. This allows the appropriate action to be taken once an Acknowledge Packet is received. - private byte mTempByteValue; // A temporary variable used to store Byte value - private int mTempIntValue; // A temporary variable used to store Integer value, used mainly to store a value while waiting for an acknowledge packet (e.g. when writeGRange() is called, the range is stored temporarily and used to update GSRRange when the acknowledge packet is received. - private boolean mWaitForAck = false; // This indicates whether the device is waiting for an acknowledge packet from the Shimmer Device - private boolean mWaitForResponse = false; // This indicates whether the device is waiting for a response packet from the Shimmer Device - private int mPacketSize = 0; // Default 2 bytes for time stamp and 6 bytes for accelerometer - private int mAccelRange = 0; // This stores the current accelerometer range being used. The accelerometer range is stored during two instances, once an ack packet is received after a writeAccelRange(), and after a response packet has been received after readAccelRange() - private int mMagSamplingRate = 4; // This stores the current Mag Sampling rate, it is a value between 0 and 6; 0 = 0.5 Hz; 1 = 1.0 Hz; 2 = 2.0 Hz; 3 = 5.0 Hz; 4 = 10.0 Hz; 5 = 20.0 Hz; 6 = 50.0 Hz - private int mAccelSamplingRate = 0; - private int mMPU9150SamplingRate = 0; - private int mMagGain = 1; // Currently not supported on Shimmer2. This stores the current Mag Range, it is a value between 0 and 6; 0 = 0.7 Ga; 1 = 1.0 Ga; 2 = 1.5 Ga; 3 = 2.0 Ga; 4 = 3.2 Ga; 5 = 3.8 Ga; 6 = 4.5 Ga - private int mGyroRange = 1; // This stores the current Mag Range, it is a value between 0 and 6; 0 = 0.7 Ga; 1 = 1.0 Ga; 2 = 1.5 Ga; 3 = 2.0 Ga; 4 = 3.2 Ga; 5 = 3.8 Ga; 6 = 4.5 Ga - protected int mGSRRange = 4; // This stores the current GSR range being used. - private int mConfigByte0; - protected int mNChannels = 0; // Default number of sensor channels set to three because of the on board accelerometer - protected int mBufferSize; - protected int mShimmerVersion = -1; - private String mMyBluetoothAddress = ""; - private String[] mSignalNameArray = new String[19]; // 19 is the maximum number of signal thus far - protected String[] mSignalDataTypeArray = new String[19]; // 19 is the maximum number of signal thus far - private String[] mGetDataInstruction = {"a"}; // This is the default value to return all data in both calibrated and uncalibrated format for now only 'a' is supported - protected boolean mDefaultCalibrationParametersECG = true; - protected boolean mDefaultCalibrationParametersEMG = true; - protected boolean mDefaultCalibrationParametersAccel = true; - protected boolean mDefaultCalibrationParametersDigitalAccel = true; - // - protected double[][] AlignmentMatrixAccel = {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}}; - protected double[][] SensitivityMatrixAccel = {{38, 0, 0}, {0, 38, 0}, {0, 0, 38}}; - protected double[][] OffsetVectorAccel = {{2048}, {2048}, {2048}}; - - protected double[][] AlignmentMatrixAccel2 = {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}; - protected double[][] SensitivityMatrixAccel2 = {{1631, 0, 0}, {0, 1631, 0}, {0, 0, 1631}}; - protected double[][] OffsetVectorAccel2 = {{0}, {0}, {0}}; - - //Default values Shimmer2 - protected static double[][] SensitivityMatrixAccel1p5gShimmer2 = {{101, 0, 0}, {0, 101, 0}, {0, 0, 101}}; - protected static double[][] SensitivityMatrixAccel2gShimmer2 = {{76, 0, 0}, {0, 76, 0}, {0, 0, 76}}; - protected static double[][] SensitivityMatrixAccel4gShimmer2 = {{38, 0, 0}, {0, 38, 0}, {0, 0, 38}}; - protected static double[][] SensitivityMatrixAccel6gShimmer2 = {{25, 0, 0}, {0, 25, 0}, {0, 0, 25}}; - protected static double[][] AlignmentMatrixAccelShimmer2 = {{-1, 0, 0}, {0, -1, 0}, {0, 0, 1}}; - protected static double[][] OffsetVectorAccelShimmer2 = {{2048}, {2048}, {2048}}; - //Shimmer3 - protected static double[][] SensitivityMatrixLowNoiseAccel2gShimmer3 = {{83, 0, 0}, {0, 83, 0}, {0, 0, 83}}; - protected static double[][] SensitivityMatrixWideRangeAccel2gShimmer3 = {{1631, 0, 0}, {0, 1631, 0}, {0, 0, 1631}}; - protected static double[][] SensitivityMatrixWideRangeAccel4gShimmer3 = {{815, 0, 0}, {0, 815, 0}, {0, 0, 815}}; - protected static double[][] SensitivityMatrixWideRangeAccel8gShimmer3 = {{408, 0, 0}, {0, 408, 0}, {0, 0, 408}}; - protected static double[][] SensitivityMatrixWideRangeAccel16gShimmer3 = {{135, 0, 0}, {0, 135, 0}, {0, 0, 135}}; - protected static double[][] AlignmentMatrixLowNoiseAccelShimmer3 = {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}; - - protected static double[][] AlignmentMatrixWideRangeAccelShimmer3 = {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}; - protected static double[][] AlignmentMatrixAccelShimmer3 = {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}; - protected static double[][] OffsetVectorLowNoiseAccelShimmer3 = {{2047}, {2047}, {2047}}; - protected static double[][] OffsetVectorWideRangeAccelShimmer3 = {{0}, {0}, {0}}; - - protected List mListofInstructions = new ArrayList(); - protected boolean mInstructionStackLock = false; - protected double OffsetECGRALL = 2060; - protected double GainECGRALL = 175; - protected double OffsetECGLALL = 2060; - protected double GainECGLALL = 175; - protected double OffsetEMG = 2060; - protected double GainEMG = 750; - - protected boolean mDefaultCalibrationParametersGyro = true; - protected double[][] AlignmentMatrixGyro = {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}; - protected double[][] SensitivityMatrixGyro = {{2.73, 0, 0}, {0, 2.73, 0}, {0, 0, 2.73}}; - protected double[][] OffsetVectorGyro = {{1843}, {1843}, {1843}}; - - //Default values Shimmer2 - protected static double[][] AlignmentMatrixGyroShimmer2 = {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}; - protected static double[][] SensitivityMatrixGyroShimmer2 = {{2.73, 0, 0}, {0, 2.73, 0}, {0, 0, 2.73}}; - protected static double[][] OffsetVectorGyroShimmer2 = {{1843}, {1843}, {1843}}; - //Shimmer3 - protected static double[][] SensitivityMatrixGyro250dpsShimmer3 = {{131, 0, 0}, {0, 131, 0}, {0, 0, 131}}; - protected static double[][] SensitivityMatrixGyro500dpsShimmer3 = {{65.5, 0, 0}, {0, 65.5, 0}, {0, 0, 65.5}}; - protected static double[][] SensitivityMatrixGyro1000dpsShimmer3 = {{32.8, 0, 0}, {0, 32.8, 0}, {0, 0, 32.8}}; - protected static double[][] SensitivityMatrixGyro2000dpsShimmer3 = {{16.4, 0, 0}, {0, 16.4, 0}, {0, 0, 16.4}}; - protected static double[][] AlignmentMatrixGyroShimmer3 = {{0, -1, 0}, {-1, 0, 0}, {0, 0, -1}}; - protected static double[][] OffsetVectorGyroShimmer3 = {{0}, {0}, {0}}; - - - protected boolean mDefaultCalibrationParametersMag = true; - protected double[][] AlignmentMatrixMag = {{1, 0, 0}, {0, 1, 0}, {0, 0, -1}}; - protected double[][] SensitivityMatrixMag = {{580, 0, 0}, {0, 580, 0}, {0, 0, 580}}; - protected double[][] OffsetVectorMag = {{0}, {0}, {0}}; - - //Default values Shimmer2 and Shimmer3 - protected static double[][] AlignmentMatrixMagShimmer2 = {{1, 0, 0}, {0, 1, 0}, {0, 0, -1}}; - protected static double[][] SensitivityMatrixMagShimmer2 = {{580, 0, 0}, {0, 580, 0}, {0, 0, 580}}; - protected static double[][] OffsetVectorMagShimmer2 = {{0}, {0}, {0}}; - //Shimmer3 - protected static double[][] AlignmentMatrixMagShimmer3 = {{1, 0, 0}, {0, -1, 0}, {0, 0, 1}}; - protected static double[][] SensitivityMatrixMagShimmer3 = {{1100, 0, 0}, {0, 1100, 0}, {0, 0, 980}}; - protected static double[][] OffsetVectorMagShimmer3 = {{0}, {0}, {0}}; - - protected static double[][] SensitivityMatrixMag1p3GaShimmer3 = {{1100, 0, 0}, {0, 1100, 0}, {0, 0, 980}}; - protected static double[][] SensitivityMatrixMag1p9GaShimmer3 = {{855, 0, 0}, {0, 855, 0}, {0, 0, 760}}; - protected static double[][] SensitivityMatrixMag2p5GaShimmer3 = {{670, 0, 0}, {0, 670, 0}, {0, 0, 600}}; - protected static double[][] SensitivityMatrixMag4GaShimmer3 = {{450, 0, 0}, {0, 450, 0}, {0, 0, 400}}; - protected static double[][] SensitivityMatrixMag4p7GaShimmer3 = {{355, 0, 0}, {0, 355, 0}, {0, 0, 300}}; - protected static double[][] SensitivityMatrixMag5p6GaShimmer3 = {{330, 0, 0}, {0, 330, 0}, {0, 0, 295}}; - protected static double[][] SensitivityMatrixMag8p1GaShimmer3 = {{230, 0, 0}, {0, 230, 0}, {0, 0, 205}}; - - - private boolean mTransactionCompleted = true; // Variable is used to ensure a command has finished execution prior to executing the next command (see initialize()) - private boolean mSync = true; // Variable to keep track of sync - private boolean mContinousSync = false; // This is to select whether to continuously check the data packets - private boolean mSetupDevice = false; // Used by the constructor when the user intends to write new settings to the Shimmer device after connection - private boolean mLowPowerMag = false; - private boolean mLowPowerAccel = false; - private boolean mLowPowerGyro = false; - private Timer mTimer; // Timer variable used when waiting for an ack or response packet - private int mBluetoothLib = 0; // 0 = default lib, 1 = arduino lib - private BluetoothAdapter mBluetoothAdapter = null; - private long mPacketLossCount = 0; - private double mPacketReceptionRate = 100; - private double mLastReceivedCalibratedTimeStamp = -1; - private boolean mFirstTimeCalTime = true; - private double mCalTimeStart; - private int mCurrentLEDStatus = 0; - private double mLowBattLimit = 3.4; - private double mLastKnownHeartRate = 0; - DescriptiveStatistics mVSenseBattMA = new DescriptiveStatistics(1024); - private int mTempPacketCountforBatt = 0; //reason for this is if the Shimmer has low battery, and the data is trying to be sync, the ack packet of the batt may be deleted - Quat4d mQ = new Quat4d(); - GradDes3DOrientation mOrientationAlgo; - private boolean mOrientationEnabled = false; - private boolean mEnableOntheFlyGyroOVCal = false; - private double mGyroOVCalThreshold = 1.2; - DescriptiveStatistics mGyroX; - DescriptiveStatistics mGyroY; - DescriptiveStatistics mGyroZ; - DescriptiveStatistics mGyroXRaw; - DescriptiveStatistics mGyroYRaw; - DescriptiveStatistics mGyroZRaw; - private boolean mFirstTime = true; - private int mAccelSmartSetting = ACCEL_SMART_MODE; - - /** - * Constructor. Prepares a new BluetoothChat session. - * - * @param context The UI Activity Context - * @param handler A Handler to send messages back to the UI Activity - * @param myName To allow the user to set a unique identifier for each Shimmer device - * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. - */ - public Shimmer(Context context, Handler handler, String myName, Boolean continousSync) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mState = STATE_NONE; - mHandler = handler; - mMyName = myName; - mContinousSync = continousSync; - mSetupDevice = false; - } - - /** - * Constructor. Prepares a new BluetoothChat session. Additional fields allows the device to be set up immediately. - * - * @param context The UI Activity Context - * @param handler A Handler to send messages back to the UI Activity - * @param myName To allow the user to set a unique identifier for each Shimmer device - * @param samplingRate Defines the sampling rate - * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). - * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). - * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) - * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. - */ - public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, boolean continousSync) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mState = STATE_NONE; - mHandler = handler; - mSamplingRate = samplingRate; - mAccelRange = accelRange; - mGSRRange = gsrRange; - mSetEnabledSensors = setEnabledSensors; - mMyName = myName; - mSetupDevice = true; - mContinousSync = continousSync; - } - - /** - * Constructor. Prepares a new BluetoothChat session. Additional fields allows the device to be set up immediately. - * - * @param context The UI Activity Context - * @param handler A Handler to send messages back to the UI Activity - * @param myName To allow the user to set a unique identifier for each Shimmer device - * @param samplingRate Defines the sampling rate - * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). - * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). - * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) - * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. - */ - public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, boolean continousSync, int magGain) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mState = STATE_NONE; - mHandler = handler; - mSamplingRate = samplingRate; - mAccelRange = accelRange; - mMagGain = magGain; - mGSRRange = gsrRange; - mSetEnabledSensors = setEnabledSensors; - mMyName = myName; - mSetupDevice = true; - mContinousSync = continousSync; - } - - /** - * Constructor. Prepares a new BluetoothChat session. Additional fields allows the device to be set up immediately. - * - * @param context The UI Activity Context - * @param handler A Handler to send messages back to the UI Activity - * @param myName To allow the user to set a unique identifier for each Shimmer device - * @param samplingRate Defines the sampling rate - * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). - * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). - * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) - * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. - */ - public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, boolean continousSync, boolean enableLowPowerAccel, boolean enableLowPowerGyro, boolean enableLowPowerMag, int gyroRange, int magRange) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mState = STATE_NONE; - mHandler = handler; - mSamplingRate = samplingRate; - mAccelRange = accelRange; - mGSRRange = gsrRange; - mSetEnabledSensors = setEnabledSensors; - mMyName = myName; - mSetupDevice = true; - mContinousSync = continousSync; - mLowPowerMag = enableLowPowerMag; - mLowPowerAccel = enableLowPowerAccel; - mLowPowerGyro = enableLowPowerGyro; - mGyroRange = gyroRange; - mMagGain = magRange; - } - - /** - * Constructor. Prepares a new BluetoothChat session. Additional fields allows the device to be set up immediately. - * - * @param context The UI Activity Context - * @param handler A Handler to send messages back to the UI Activity - * @param myName To allow the user to set a unique identifier for each Shimmer device - * @param samplingRate Defines the sampling rate - * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). - * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). - * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) - * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. - */ - public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, boolean continousSync, boolean enableLowPowerAccel, boolean enableLowPowerGyro, boolean enableLowPowerMag, int gyroRange, int magRange, int accelSmartSetting) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mState = STATE_NONE; - mHandler = handler; - mSamplingRate = samplingRate; - mAccelRange = accelRange; - mGSRRange = gsrRange; - mSetEnabledSensors = setEnabledSensors; - mMyName = myName; - mSetupDevice = true; - mContinousSync = continousSync; - mLowPowerMag = enableLowPowerMag; - mLowPowerAccel = enableLowPowerAccel; - mLowPowerGyro = enableLowPowerGyro; - mGyroRange = gyroRange; - mMagGain = magRange; - mAccelSmartSetting = accelSmartSetting; - } - - - /** - * Set the current state of the chat connection - * - * @param state An integer defining the current connection state - */ - private synchronized void setState(int state) { - mState = state; - // Give the new state to the Handler so the UI Activity can update - mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, state, -1, new ObjectCluster(mMyName, getBluetoothAddress())).sendToTarget(); - } - - /** - * Return the current connection state. - */ - public synchronized int getShimmerState() { - return mState; - } - - /** - * Start the ConnectThread to initiate a connection to a remote device. The purpose of having two libraries is because some Stock firmware do not implement the full Bluetooth Stack. In such cases use 'gerdavax'. If problems persist consider installing an aftermarket firmware, with a mature Bluetooth stack. - * - * @param address Bluetooth Address of Device to connect too - * @param bluetoothLibrary Supported libraries are 'default' and 'gerdavax' - */ - public synchronized void connect(final String address, String bluetoothLibrary) { - mListofInstructions.clear(); - mFirstTime = true; - if (bluetoothLibrary == "default") { - mMyBluetoothAddress = address; - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); - - // Cancel any thread attempting to make a connection - if (mState == STATE_CONNECTING) { - if (mConnectThread != null) { - mConnectThread.cancel(); - mConnectThread = null; - } - } - // Cancel any thread currently running a connection - if (mConnectedThread != null) { - mConnectedThread.cancel(); - mConnectedThread = null; - } - - // Start the thread to connect with the given device - mConnectThread = new ConnectThread(device); - mConnectThread.start(); - setState(STATE_CONNECTING); - } else if (bluetoothLibrary == "gerdavax") { - mMyBluetoothAddress = address; - // Cancel any thread attempting to make a connection - if (mState == STATE_CONNECTING) { - if (mConnectThread != null) { - mConnectThread.cancel(); - mConnectThread = null; - } - } - // Cancel any thread currently running a connection - if (mConnectedThread != null) { - mConnectedThread.cancel(); - mConnectedThread = null; - } - - if (address == null) return; - Log.d("ConnectionStatus", "Get Local Device " + address); - - localDevice = LocalDevice.getInstance(); - RemoteDevice device = localDevice.getRemoteForAddr(address); - new ConnectThreadArduino(device).start(); - setState(STATE_CONNECTING); - /*localDevice.init(this, new ReadyListener() { - @Override - public synchronized void ready() { - - - //localDevice.destroy(); - - - } - });*/ - - - } - } - - /** - * Start the ConnectedThread to begin managing a Bluetooth connection - * - * @param socket The BluetoothSocket on which the connection was made - * @param device The BluetoothDevice that has been connected - */ - public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { - // Cancel the thread that completed the connection - if (mConnectThread != null) { - mConnectThread.cancel(); - mConnectThread = null; - } - // Cancel any thread currently running a connection - if (mConnectedThread != null) { - mConnectedThread.cancel(); - mConnectedThread = null; - } - // Start the thread to manage the connection and perform transmissions - mConnectedThread = new ConnectedThread(socket); - mConnectedThread.start(); - mMyBluetoothAddress = device.getAddress(); - // Send the name of the connected device back to the UI Activity - Message msg = mHandler.obtainMessage(Shimmer.MESSAGE_DEVICE_NAME); - mHandler.sendMessage(msg); - while (!mConnectedThread.isAlive()) { - } - ; - setState(STATE_CONNECTED); - initialize(); - } - - /** - * Stop all threads - */ - public synchronized void stop() { - setState(STATE_NONE); - SystemClock.sleep(500);//HACK: avoid seg fault in libc library on Nexus devices - mStreaming = false; - mInitialized = false; - if (mConnectThread != null) { - mConnectThread.cancel(); - mConnectThread = null; - } - if (mConnectedThread != null) { - mConnectedThread.cancel(); - mConnectedThread = null; - } - - } - - /** - * Write to the ConnectedThread in an unsynchronized manner - * - * @param out The bytes to write - * @see ConnectedThread write(byte[]) - */ - public void write(byte[] out) { - // Create temporary object - ConnectedThread r; - // Synchronize a copy of the ConnectedThread - synchronized (this) { - if (mState != STATE_CONNECTED) return; - r = mConnectedThread; - } - // Perform the write unsynchronized - r.write(out); - } - - /** - * Indicate that the connection attempt failed and notify the UI Activity. - */ - private void connectionFailed() { - setState(STATE_NONE); - mInitialized = false; - // Send a failure message back to the Activity - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Unable to connect device"); - msg.setData(bundle); - mHandler.sendMessage(msg); - } - - /** - * Indicate that the connection was lost and notify the UI Activity. - */ - private void connectionLost() { - setState(STATE_NONE); - mInitialized = false; - // Send a failure message back to the Activity - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Device connection was lost"); - msg.setData(bundle); - mHandler.sendMessage(msg); - } - - /** - * This thread runs while attempting to make an outgoing connection - * with a device. It runs straight through; the connection either - * succeeds or fails. - */ - private class ConnectThread extends Thread { - private final BluetoothSocket mmSocket; - private final BluetoothDevice mmDevice; - - public ConnectThread(BluetoothDevice device) { - mmDevice = device; - BluetoothSocket tmp = null; - Log.d("Shimmer", "Start of Default ConnectThread"); - // Get a BluetoothSocket for a connection with the - // given BluetoothDevice - try { - tmp = device.createInsecureRfcommSocketToServiceRecord(mSPP_UUID); // If your device fails to pair try: device.createInsecureRfcommSocketToServiceRecord(mSPP_UUID) - } catch (IOException e) { - } - mmSocket = tmp; - } - - public void run() { - setName("ConnectThread"); - - // Always cancel discovery because it will slow down a connection - mAdapter.cancelDiscovery(); - - try { - // Connect the device through the socket. This will block - // until it succeeds or throws an exception - mmSocket.connect(); - } catch (IOException connectException) { - connectionFailed(); - // Unable to connect; close the socket and get out - try { - mmSocket.close(); - } catch (IOException closeException) { - } - return; - } - // Reset the ConnectThread because we're done - synchronized (Shimmer.this) { - mConnectThread = null; - } - // Start the connected thread - connected(mmSocket, mmDevice); - } - - public void cancel() { - try { - mmSocket.close(); - } catch (IOException e) { - } - } - } - - //arduino - private class ConnectThreadArduino extends Thread { - - //private static final String TAG = "ConnectThread"; - private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - - private final RemoteDevice mDevice; - private BtSocket mSocket; - - public ConnectThreadArduino(RemoteDevice device) { - mDevice = device; - Log.d("Shimmer", " Start of ArduinoConnectThread"); - } - - public void run() { - try { - boolean isPaired = false; - - try { - isPaired = mDevice.ensurePaired(); - - - } catch (RuntimeException re) { - re.printStackTrace(); - } - - //add a timer to wait for the user to pair the device otherwise quit - if (!isPaired) { - Thread.sleep(10000); - isPaired = mDevice.ensurePaired(); - } - - if (!isPaired) { - Log.d("Shimmer", "not paired!"); - connectionFailed(); - - - } else { - Log.d("Shimmer", "is paired!"); - // Let main thread do some stuff to render UI immediately - //Thread.yield(); - // Get a BluetoothSocket to connect with the given BluetoothDevice - try { - mSocket = mDevice.openSocket(SPP_UUID); - } catch (Exception e) { - Log.d("Shimmer", "Connection via SDP unsuccessful, try to connect via port directly"); - // 1.x Android devices only work this way since SDP was not part of their firmware then - mSocket = mDevice.openSocket(1); - //connectionFailed(); - Log.d("Shimmer", "I am here"); - } - - // Do work to manage the connection (in a separate thread) - Log.d("Shimmer", "Going to Manage Socket"); - if (getShimmerState() != STATE_NONE) { - Log.d("Shimmer", "ManagingSocket"); - manageConnectedSocket(mSocket); - } - } - } catch (Exception e) { - Log.d("Shimmer", "Connection Failed"); - //sendConnectionFailed(mDevice.getAddress()); - connectionFailed(); - e.printStackTrace(); - if (mSocket != null) - try { - mSocket.close(); - Log.d("Shimmer", "Arduinothreadclose"); - } catch (IOException e1) { - } - - return; - } - } - - /** - * Will cancel an in-progress connection, and close the socket - */ - @SuppressWarnings("unused") - public void cancel() { - try { - if (mSocket != null) mSocket.close(); - //sendConnectionDisconnected(mDevice.getAddress()); - } catch (IOException e) { - Log.e("Shimmer", "cannot close socket to " + mDevice.getAddress()); - } - } - - private void manageConnectedSocket(BtSocket socket) { - // Logger.d(TAG, "connection established."); - // pass the socket to a worker thread - String address = mDevice.getAddress(); - mConnectedThread = new ConnectedThread(socket, address); - Log.d("Shimmer", "ConnectedThread is about to start"); - mConnectedThread.start(); - // Send the name of the connected device back to the UI Activity - mMyBluetoothAddress = mDevice.getAddress(); - Message msg = mHandler.obtainMessage(Shimmer.MESSAGE_DEVICE_NAME); - mHandler.sendMessage(msg); - // Send the name of the connected device back to the UI Activity - while (!mConnectedThread.isAlive()) { - } - ; - Log.d("Shimmer", "alive!!"); - setState(STATE_CONNECTED); - //startStreaming(); - initialize(); - } - } - - - /** - * This thread runs during a connection with a remote device. - * It handles all incoming and outgoing transmissions. - */ - private class ConnectedThread extends Thread { - private BluetoothSocket mmSocket = null; - private final InputStream mInStream; - private final OutputStream mmOutStream; - private BtSocket mSocket = null; - byte[] tb = {0}; - Stack byteStack = new Stack(); - byte[] newPacket = new byte[mPacketSize + 1]; - - public ConnectedThread(BluetoothSocket socket) { - - mmSocket = socket; - InputStream tmpIn = null; - OutputStream tmpOut = null; - - // Get the BluetoothSocket input and output streams - try { - tmpIn = socket.getInputStream(); - tmpOut = socket.getOutputStream(); - } catch (IOException e) { - } - - mInStream = tmpIn; - mmOutStream = tmpOut; - } - - public ConnectedThread(BtSocket socket, String address) { - mSocket = socket; - //this.mAddress = address; - InputStream tmpIn = null; - OutputStream tmpOut = null; - - // Get the input and output streams, using temp objects because - // member streams are final - try { - tmpIn = socket.getInputStream(); - tmpOut = socket.getOutputStream(); - } catch (Exception e) { - Log.d("Shimmer", "Connected Thread Error"); - } - - mInStream = tmpIn; - mmOutStream = tmpOut; - - } - - /** - * The received packets are processed here - */ - public synchronized void run() { - // Keep listening to the InputStream while connected - while (true) { - - ///////////////////////// - // is an instruction running ? if not proceed - if (mInstructionStackLock == false) { - // check instruction stack, are there any other instructions left to be executed? - if (!mListofInstructions.isEmpty()) { - mInstructionStackLock = true; - byte[] insBytes = (byte[]) mListofInstructions.get(0); - mCurrentCommand = insBytes[0]; - mWaitForAck = true; - write(insBytes); - if (mCurrentCommand == STOP_STREAMING_COMMAND) { - mStreaming = false; - } else { - if (mCurrentCommand == GET_FW_VERSION_COMMAND) { - responseTimer(ACK_TIMER_DURATION); - } else if (mCurrentCommand == GET_SAMPLING_RATE_COMMAND) { - responseTimer(ACK_TIMER_DURATION); - } else { - responseTimer(ACK_TIMER_DURATION + 10); - } - } - mTransactionCompleted = false; - } - - } - - try { - - //Log.d("Shimmer","byte " + Byte.toString(tb[0]) + " " + Boolean.toString(mWaitForAck) + " " + Boolean.toString(mWaitForResponse) ); - //Is the device waiting for an Ack/Response if so look out for the appropriate command - - if (mWaitForAck == true && mStreaming == false) { - if (mInStream.available() != 0) { - mInStream.read(tb, 0, 1); - Log.d("ShimmerREAD", mMyBluetoothAddress + " :: " + Byte.toString(tb[0])); - - - if (mCurrentCommand == STOP_STREAMING_COMMAND) { //due to not receiving the ack from stop streaming command we will skip looking for it. - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "ACK Received for Device: " + mMyBluetoothAddress + "; Command Issued: " + mCurrentCommand); - mStreaming = false; - mTransactionCompleted = true; - mWaitForAck = false; - try { - Thread.sleep(200); // Wait to ensure that we dont missed any bytes which need to be cleared - } catch (InterruptedException e) { - e.printStackTrace(); - } - byteStack.clear(); - mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_STOP_STREAMING, -1, new ObjectCluster(mMyName, getBluetoothAddress())).sendToTarget(); - Message msg = mHandler.obtainMessage(MESSAGE_STOP_STREAMING_COMPLETE); - Bundle bundle = new Bundle(); - bundle.putBoolean("Stop Streaming", true); - bundle.putString("Bluetooth Address", mMyBluetoothAddress); - msg.setData(bundle); - mHandler.sendMessage(msg); - while (mInStream.available() > 0) { //this is to clear the buffer - byte[] tbtemp = new byte[mInStream.available()]; - mInStream.read(tbtemp, 0, mInStream.available()); - Log.d("ShimmerClear", "Streaming Stop Done " + "Bytes still available:" + Integer.toString(mInStream.available())); - } - Log.d("Shimmer", "Streaming Stop Done - clear readbuffer loop completed " + "Bytes still available:" + Integer.toString(mInStream.available())); - mListofInstructions.remove(0); - mInstructionStackLock = false; - } - - if ((byte) tb[0] == ACK_COMMAND_PROCESSED) { - - Log.d("Shimmer", "ACK Received for Device: " + mMyBluetoothAddress + "; Command Issued: " + mCurrentCommand); - if (mCurrentCommand == START_STREAMING_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mStreaming = true; - mTransactionCompleted = true; - byteStack.clear(); - isNowStreaming(); - mWaitForAck = false; - mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_STREAMING, -1, new ObjectCluster(mMyName, getBluetoothAddress())).sendToTarget(); - mListofInstructions.remove(0); - mInstructionStackLock = false; - } - /*else if (mCurrentCommand==STOP_STREAMING_COMMAND) { - - mStreaming=false; - mTransactionCompleted=true; - mWaitForAck=false; - packetStack.clear(); - if(mInStream.available()>0){ //this is to clear the buffer - byte[] tbtemp =new byte[mInStream.available()]; - mInStream.read(tbtemp,0,mInStream.available()); - } - mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_STOP_STREAMING, -1, new ObjectCluster(mMyName,getBluetoothAddress())).sendToTarget(); - Message msg = mHandler.obtainMessage(MESSAGE_STOP_STREAMING_COMPLETE); - Bundle bundle = new Bundle(); - bundle.putBoolean("Stop Streaming", true); - bundle.putString("Bluetooth Address", mMyBluetoothAddress); - msg.setData(bundle); - mHandler.sendMessage(msg); - - - Log.d("Shimmer","Streaming Stop Done" + "Bytes still available:" + Integer.toString(mInStream.available())); - - }*/ - else if (mCurrentCommand == SET_SAMPLING_RATE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mWaitForAck = false; - byte[] instruction = mListofInstructions.get(0); - double tempdouble = 0; - if (mShimmerVersion == Shimmer.SHIMMER_2 || mShimmerVersion == Shimmer.SHIMMER_2R) { - tempdouble = (double) 1024 / instruction[1]; - } else { - tempdouble = 32768 / (double) ((int) (instruction[1] & 0xFF) + ((int) (instruction[2] & 0xFF) << 8)); - } - String x = new DecimalFormat("#.#").format(tempdouble); - String a = x.replace(",", "."); - double y = Double.parseDouble(a); - mSamplingRate = y; - Log.d("Shimmer", "SR rx" + Double.toString(mSamplingRate)); - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_BUFFER_SIZE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mWaitForAck = false; - mBufferSize = (int) ((byte[]) mListofInstructions.get(0))[1]; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == INQUIRY_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_LSM303DLHC_ACCEL_LPMODE_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_LSM303DLHC_ACCEL_HRMODE_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_BUFFER_SIZE_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_BLINK_LED) { - mWaitForAck = false; - mWaitForResponse = true; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_MAG_SAMPLING_RATE_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_MAG_GAIN_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_ACCEL_SENSITIVITY_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - } else if (mCurrentCommand == GET_MPU9150_GYRO_RANGE_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - } else if (mCurrentCommand == GET_GSR_RANGE_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_FW_VERSION_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - } else if (mCurrentCommand == GET_ECG_CALIBRATION_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_EMG_CALIBRATION_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == SET_BLINK_LED) { - mCurrentLEDStatus = (int) ((byte[]) mListofInstructions.get(0))[1]; - mTransactionCompleted = true; - //mWaitForAck=false; - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_GSR_RANGE_COMMAND) { - - mTransactionCompleted = true; - mWaitForAck = false; - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mGSRRange = (int) ((byte[]) mListofInstructions.get(0))[1]; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == GET_SAMPLING_RATE_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - - } else if (mCurrentCommand == GET_CONFIG_BYTE0_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == SET_CONFIG_BYTE0_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mConfigByte0 = (int) ((byte[]) mListofInstructions.get(0))[1]; - ; - mWaitForAck = false; - mTransactionCompleted = true; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_LSM303DLHC_ACCEL_LPMODE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mWaitForAck = false; - mTransactionCompleted = true; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_LSM303DLHC_ACCEL_HRMODE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mWaitForAck = false; - mTransactionCompleted = true; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_PMUX_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - if (((byte[]) mListofInstructions.get(0))[1] == 1) { - mConfigByte0 = (byte) ((byte) (mConfigByte0 | 64) & (0xFF)); - } else if (((byte[]) mListofInstructions.get(0))[1] == 0) { - mConfigByte0 = (byte) ((byte) (mConfigByte0 & 191) & (0xFF)); - } - mTransactionCompleted = true; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_GYRO_TEMP_VREF_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mConfigByte0 = mTempByteValue; - mWaitForAck = false; - } else if (mCurrentCommand == SET_5V_REGULATOR_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - if (((byte[]) mListofInstructions.get(0))[1] == 1) { - mConfigByte0 = (byte) (mConfigByte0 | 128); - } else if (((byte[]) mListofInstructions.get(0))[1] == 0) { - mConfigByte0 = (byte) (mConfigByte0 & 127); - } - mTransactionCompleted = true; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_ACCEL_SENSITIVITY_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mAccelRange = (int) (((byte[]) mListofInstructions.get(0))[1]); - if (mDefaultCalibrationParametersAccel == true) { - if (mShimmerVersion != SHIMMER_3) { - if (getAccelRange() == 0) { - SensitivityMatrixAccel = SensitivityMatrixAccel1p5gShimmer2; - } else if (getAccelRange() == 1) { - SensitivityMatrixAccel = SensitivityMatrixAccel2gShimmer2; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel = SensitivityMatrixAccel4gShimmer2; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel = SensitivityMatrixAccel6gShimmer2; - } - } else if (mShimmerVersion == SHIMMER_3) { - SensitivityMatrixAccel = SensitivityMatrixLowNoiseAccel2gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixLowNoiseAccelShimmer3; - OffsetVectorAccel = OffsetVectorLowNoiseAccelShimmer3; - } - } - - if (mDefaultCalibrationParametersDigitalAccel) { - if (mShimmerVersion == SHIMMER_3) { - if (getAccelRange() == 1) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel4gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel8gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel16gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 0) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel2gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } - } - } - mTransactionCompleted = true; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - - } else if (mCurrentCommand == SET_MPU9150_GYRO_RANGE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mGyroRange = (int) (((byte[]) mListofInstructions.get(0))[1]); - if (mDefaultCalibrationParametersGyro == true) { - if (mShimmerVersion == SHIMMER_3) { - AlignmentMatrixGyro = AlignmentMatrixGyroShimmer3; - OffsetVectorGyro = OffsetVectorGyroShimmer3; - if (mGyroRange == 0) { - SensitivityMatrixGyro = SensitivityMatrixGyro250dpsShimmer3; - - } else if (mGyroRange == 1) { - SensitivityMatrixGyro = SensitivityMatrixGyro500dpsShimmer3; - - } else if (mGyroRange == 2) { - SensitivityMatrixGyro = SensitivityMatrixGyro1000dpsShimmer3; - - } else if (mGyroRange == 3) { - SensitivityMatrixGyro = SensitivityMatrixGyro2000dpsShimmer3; - - } - } - } - mTransactionCompleted = true; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_MAG_SAMPLING_RATE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mMagSamplingRate = mTempIntValue; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == GET_ACCEL_SAMPLING_RATE_COMMAND) { - mWaitForAck = false; - mWaitForResponse = true; - mListofInstructions.remove(0); - } else if (mCurrentCommand == SET_ACCEL_SAMPLING_RATE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mAccelSamplingRate = mTempIntValue; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_MPU9150_SAMPLING_RATE_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mMPU9150SamplingRate = mTempIntValue; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_SENSORS_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mWaitForAck = false; - mEnabledSensors = tempEnabledSensors; - byteStack.clear(); // Always clear the packetStack after setting the sensors, this is to ensure a fresh start - mTransactionCompleted = true; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_MAG_GAIN_COMMAND) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mWaitForAck = false; - mMagGain = (int) ((byte[]) mListofInstructions.get(0))[1]; - if (mDefaultCalibrationParametersMag == true) { - if (mShimmerVersion == SHIMMER_3) { - AlignmentMatrixMag = AlignmentMatrixMagShimmer3; - OffsetVectorMag = OffsetVectorMagShimmer3; - if (mMagGain == 1) { - SensitivityMatrixMag = SensitivityMatrixMag1p3GaShimmer3; - } else if (mMagGain == 2) { - SensitivityMatrixMag = SensitivityMatrixMag1p9GaShimmer3; - } else if (mMagGain == 3) { - SensitivityMatrixMag = SensitivityMatrixMag2p5GaShimmer3; - } else if (mMagGain == 4) { - SensitivityMatrixMag = SensitivityMatrixMag4GaShimmer3; - } else if (mMagGain == 5) { - SensitivityMatrixMag = SensitivityMatrixMag4p7GaShimmer3; - } else if (mMagGain == 6) { - SensitivityMatrixMag = SensitivityMatrixMag5p6GaShimmer3; - } else if (mMagGain == 7) { - SensitivityMatrixMag = SensitivityMatrixMag8p1GaShimmer3; - } - } - } - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == GET_ACCEL_CALIBRATION_COMMAND || mCurrentCommand == GET_GYRO_CALIBRATION_COMMAND || mCurrentCommand == GET_MAG_CALIBRATION_COMMAND || mCurrentCommand == GET_ALL_CALIBRATION_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_SHIMMER_VERSION_COMMAND_NEW) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == GET_SHIMMER_VERSION_COMMAND) { - mWaitForResponse = true; - mWaitForAck = false; - mListofInstructions.remove(0); - } else if (mCurrentCommand == SET_ECG_CALIBRATION_COMMAND) { - //mGSRRange=mTempIntValue; - mDefaultCalibrationParametersECG = false; - OffsetECGLALL = (double) ((((byte[]) mListofInstructions.get(0))[0] & 0xFF) << 8) + (((byte[]) mListofInstructions.get(0))[1] & 0xFF); - GainECGLALL = (double) ((((byte[]) mListofInstructions.get(0))[2] & 0xFF) << 8) + (((byte[]) mListofInstructions.get(0))[3] & 0xFF); - OffsetECGRALL = (double) ((((byte[]) mListofInstructions.get(0))[4] & 0xFF) << 8) + (((byte[]) mListofInstructions.get(0))[5] & 0xFF); - GainECGRALL = (double) ((((byte[]) mListofInstructions.get(0))[6] & 0xFF) << 8) + (((byte[]) mListofInstructions.get(0))[7] & 0xFF); - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mTransactionCompleted = true; - mWaitForAck = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == SET_EMG_CALIBRATION_COMMAND) { - //mGSRRange=mTempIntValue; - mDefaultCalibrationParametersEMG = false; - OffsetEMG = (double) ((((byte[]) mListofInstructions.get(0))[0] & 0xFF) << 8) + (((byte[]) mListofInstructions.get(0))[1] & 0xFF); - GainEMG = (double) ((((byte[]) mListofInstructions.get(0))[2] & 0xFF) << 8) + (((byte[]) mListofInstructions.get(0))[3] & 0xFF); - mTransactionCompleted = true; - mWaitForAck = false; - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (mCurrentCommand == TOGGLE_LED_COMMAND) { - //mGSRRange=mTempIntValue; - mTransactionCompleted = true; - mWaitForAck = false; - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mListofInstructions.remove(0); - mInstructionStackLock = false; - } - - } - } - } else if (mWaitForResponse == true) { - if (mFirstTime) { - while (mInStream.available() != 0) { - mInStream.skip(mInStream.available()); - } - mFirstTime = false; - } else if (mInStream.available() != 0) { - - mInStream.read(tb, 0, 1); - - if (tb[0] == FW_VERSION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - - try { - Thread.sleep(200); // Wait to ensure the packet has been fully received - } catch (InterruptedException e) { - e.printStackTrace(); - } - byte[] bufferInquiry = new byte[6]; - mInStream.read(bufferInquiry, 0, 6); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mFWVersion = (double) ((bufferInquiry[3] & 0xFF) << 8) + (double) (bufferInquiry[2] & 0xFF) + ((double) ((bufferInquiry[4] & 0xFF)) / 10); - mFWInternal = (int) (bufferInquiry[5] & 0xFF); - if (((double) ((bufferInquiry[4] & 0xFF)) / 10) == 0) { - mFWVersionFullName = "BtStream " + Double.toString(mFWVersion) + "." + Integer.toString(mFWInternal); - } else { - mFWVersionFullName = "BtStream " + Double.toString(mFWVersion) + "." + Integer.toString(mFWInternal); - } - Log.d("Shimmer", "Version:" + mFWVersionFullName); - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Firmware Version: " + mFWVersionFullName); - msg.setData(bundle); - if (!mDummy) { - mHandler.sendMessage(msg); - } - mListofInstructions.remove(0); - mInstructionStackLock = false; - mTransactionCompleted = true; - readShimmerVersion(); - } else if (tb[0] == INQUIRY_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - try { - Thread.sleep(200); // Wait to ensure the packet has been fully received - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (mShimmerVersion == SHIMMER_2 || mShimmerVersion == SHIMMER_2R) { - byte[] bufferInquiry = new byte[30]; - mInStream.read(bufferInquiry, 0, 30); - mPacketSize = 2 + bufferInquiry[3] * 2; - mSamplingRate = (double) 1024 / bufferInquiry[0]; - if (mMagSamplingRate == 3 && mSamplingRate > 10) { - mLowPowerMag = true; - } - mAccelRange = bufferInquiry[1]; - mConfigByte0 = bufferInquiry[2] & 0xFF; //convert the byte to unsigned integer - mNChannels = bufferInquiry[3]; - mBufferSize = bufferInquiry[4]; - byte[] signalIdArray = new byte[mNChannels]; - System.arraycopy(bufferInquiry, 5, signalIdArray, 0, mNChannels); - updateEnabledSensorsFromChannels(signalIdArray); - interpretdatapacketformat(mNChannels, signalIdArray); - Log.d("Shimmer", "Inquiry Response Received for Device-> " + mMyBluetoothAddress + " " + bufferInquiry[0] + " " + bufferInquiry[1] + " " + bufferInquiry[2] + " " + bufferInquiry[3] + " " + bufferInquiry[4] + " " + bufferInquiry[5] + " " + bufferInquiry[6] + " " + bufferInquiry[7] + " " + bufferInquiry[8] + " " + bufferInquiry[9] + " " + bufferInquiry[10] + " " + bufferInquiry[11] + " " + bufferInquiry[12] + " " + bufferInquiry[13] + " " + bufferInquiry[14] + " " + bufferInquiry[15] + " " + bufferInquiry[16] + " " + bufferInquiry[17] + " " + bufferInquiry[18]); - } else if (mShimmerVersion == SHIMMER_3) { - byte[] bufferInquiry = new byte[30]; - mInStream.read(bufferInquiry, 0, 30); - mPacketSize = 2 + bufferInquiry[6] * 2; - String x = new DecimalFormat("#.#").format(32768 / (double) ((int) (bufferInquiry[0] & 0xFF) + ((int) (bufferInquiry[1] & 0xFF) << 8))); - String a = x.replace(",", "."); - double y = Double.parseDouble(a); - mSamplingRate = y; - mNChannels = bufferInquiry[6]; - mBufferSize = bufferInquiry[7]; - mConfigByte0 = ((int) (bufferInquiry[2] & 0xFF) + ((int) (bufferInquiry[3] & 0xFF) << 8) + ((int) (bufferInquiry[4] & 0xFF) << 16) + ((int) (bufferInquiry[5] & 0xFF) << 24)); - mAccelRange = ((int) (mConfigByte0 & 0xC)) >> 2; - mGyroRange = ((int) (mConfigByte0 & 196608)) >> 16; - mMagGain = ((int) (mConfigByte0 & 14680064)) >> 21; - mAccelSamplingRate = ((int) (mConfigByte0 & 0xF0)) >> 4; - mMPU9150SamplingRate = ((int) (mConfigByte0 & 65280)) >> 8; - mMagSamplingRate = ((int) (mConfigByte0 & 1835008)) >> 18; - if ((mAccelSamplingRate == 2 && mSamplingRate > 10)) { - mLowPowerAccel = true; - } - if ((mMPU9150SamplingRate == 0xFF && mSamplingRate > 10)) { - mLowPowerGyro = true; - } - if ((mMagSamplingRate == 4 && mSamplingRate > 10)) { - mLowPowerMag = true; - } - byte[] signalIdArray = new byte[mNChannels]; - System.arraycopy(bufferInquiry, 8, signalIdArray, 0, mNChannels); - updateEnabledSensorsFromChannels(signalIdArray); - interpretdatapacketformat(mNChannels, signalIdArray); - Log.d("Shimmer", "Inquiry Response Received for Device-> " + mMyBluetoothAddress + " " + bufferInquiry[0] + " " + bufferInquiry[1] + " " + bufferInquiry[2] + " " + bufferInquiry[3] + " " + bufferInquiry[4] + " " + bufferInquiry[5] + " " + bufferInquiry[6] + " " + bufferInquiry[7] + " " + bufferInquiry[8] + " " + bufferInquiry[9] + " " + bufferInquiry[10] + " " + bufferInquiry[11] + " " + bufferInquiry[12] + " " + bufferInquiry[13] + " " + bufferInquiry[14] + " " + bufferInquiry[15] + " " + bufferInquiry[16] + " " + bufferInquiry[17] + " " + bufferInquiry[18]); - } else if (mShimmerVersion == SHIMMER_SR30) { //no config byte so adjust accordingly - byte[] bufferInquiry = new byte[30]; - mInStream.read(bufferInquiry, 0, 30); - mPacketSize = 2 + bufferInquiry[2] * 2; - mSamplingRate = (double) 1024 / bufferInquiry[0]; - mAccelRange = bufferInquiry[1]; - mNChannels = bufferInquiry[2]; - mBufferSize = bufferInquiry[3]; - byte[] signalIdArray = new byte[mNChannels]; - System.arraycopy(bufferInquiry, 4, signalIdArray, 0, mNChannels); // this is 4 because there is no config byte - interpretdatapacketformat(mNChannels, signalIdArray); - Log.d("Shimmer", "Inquiry Response Received for Device-> " + mMyBluetoothAddress + " " + bufferInquiry[0] + " " + bufferInquiry[1] + " " + bufferInquiry[2] + " " + bufferInquiry[3] + " " + bufferInquiry[4] + " " + bufferInquiry[5] + " " + bufferInquiry[6] + " " + bufferInquiry[7] + " " + bufferInquiry[8] + " " + bufferInquiry[9] + " " + bufferInquiry[10] + " " + bufferInquiry[11] + " " + bufferInquiry[12] + " " + bufferInquiry[13] + " " + bufferInquiry[14] + " " + bufferInquiry[15] + " " + bufferInquiry[16] + " " + bufferInquiry[17] + " " + bufferInquiry[18]); - } - inquiryDone(); - mWaitForResponse = false; - mTransactionCompleted = true; - mInstructionStackLock = false; - } else if (tb[0] == GSR_RANGE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferGSRRange = new byte[1]; - mInStream.read(bufferGSRRange, 0, 1); - mGSRRange = bufferGSRRange[0]; - mInstructionStackLock = false; - } else if (tb[0] == MAG_SAMPLING_RATE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferAns = new byte[1]; - mInStream.read(bufferAns, 0, 1); - mMagSamplingRate = bufferAns[0]; - mInstructionStackLock = false; - } else if (tb[0] == ACCEL_SAMPLING_RATE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferAns = new byte[1]; - mAccelSamplingRate = bufferAns[0]; - mInstructionStackLock = false; - } else if (tb[0] == MAG_GAIN_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferAns = new byte[1]; - mInStream.read(bufferAns, 0, 1); - mMagGain = bufferAns[0]; - mInstructionStackLock = false; - } else if (tb[0] == LSM303DLHC_ACCEL_HRMODE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferAns = new byte[1]; - mInStream.read(bufferAns, 0, 1); - mInstructionStackLock = false; - } else if (tb[0] == LSM303DLHC_ACCEL_LPMODE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferAns = new byte[1]; - mInStream.read(bufferAns, 0, 1); - mInstructionStackLock = false; - } else if (tb[0] == BUFFER_SIZE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] byteled = new byte[1]; - mInStream.read(byteled, 0, 1); - mBufferSize = byteled[0] & 0xFF; - mInstructionStackLock = false; - } else if (tb[0] == BLINK_LED_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] byteled = new byte[1]; - mInStream.read(byteled, 0, 1); - mCurrentLEDStatus = byteled[0] & 0xFF; - mInstructionStackLock = false; - } else if (tb[0] == ACCEL_SENSITIVITY_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferAccelSensitivity = new byte[1]; - mInStream.read(bufferAccelSensitivity, 0, 1); - mAccelRange = bufferAccelSensitivity[0]; - if (mDefaultCalibrationParametersAccel == true) { - if (mShimmerVersion != SHIMMER_3) { - if (getAccelRange() == 0) { - SensitivityMatrixAccel = SensitivityMatrixAccel1p5gShimmer2; - } else if (getAccelRange() == 1) { - SensitivityMatrixAccel = SensitivityMatrixAccel2gShimmer2; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel = SensitivityMatrixAccel4gShimmer2; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel = SensitivityMatrixAccel6gShimmer2; - } - } else if (mShimmerVersion == SHIMMER_3) { - if (getAccelRange() == 0) { - SensitivityMatrixAccel = SensitivityMatrixLowNoiseAccel2gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixLowNoiseAccelShimmer3; - OffsetVectorAccel = OffsetVectorLowNoiseAccelShimmer3; - } else if (getAccelRange() == 1) { - SensitivityMatrixAccel = SensitivityMatrixWideRangeAccel4gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel = SensitivityMatrixWideRangeAccel8gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel = SensitivityMatrixWideRangeAccel16gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel = OffsetVectorWideRangeAccelShimmer3; - } - } - } - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (tb[0] == MPU9150_GYRO_RANGE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - mTransactionCompleted = true; - byte[] bufferGyroSensitivity = new byte[1]; - mInStream.read(bufferGyroSensitivity, 0, 1); - mGyroRange = bufferGyroSensitivity[0]; - if (mDefaultCalibrationParametersGyro == true) { - if (mShimmerVersion == SHIMMER_3) { - AlignmentMatrixGyro = AlignmentMatrixGyroShimmer3; - OffsetVectorGyro = OffsetVectorGyroShimmer3; - if (mGyroRange == 0) { - SensitivityMatrixGyro = SensitivityMatrixGyro250dpsShimmer3; - - } else if (mGyroRange == 1) { - SensitivityMatrixGyro = SensitivityMatrixGyro500dpsShimmer3; - - } else if (mGyroRange == 2) { - SensitivityMatrixGyro = SensitivityMatrixGyro1000dpsShimmer3; - - } else if (mGyroRange == 3) { - SensitivityMatrixGyro = SensitivityMatrixGyro2000dpsShimmer3; - } - } - } - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (tb[0] == SAMPLING_RATE_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - if (mStreaming == false) { - if (mShimmerVersion == Shimmer.SHIMMER_2R && mShimmerVersion == Shimmer.SHIMMER_2) { - byte[] bufferSR = new byte[1]; - mInStream.read(bufferSR, 0, 1); //read the sampling rate - if (mCurrentCommand == GET_SAMPLING_RATE_COMMAND) { // this is a double check, not necessary - double val = (double) (bufferSR[0] & (byte) ACK_COMMAND_PROCESSED); - mSamplingRate = 1024 / val; - } - } else if (mShimmerVersion == Shimmer.SHIMMER_3) { - byte[] bufferSR = new byte[2]; - mInStream.read(bufferSR, 0, 2); //read the sampling rate - mSamplingRate = 32768 / (double) ((int) (bufferSR[0] & 0xFF) + ((int) (bufferSR[1] & 0xFF) << 8)); - } - } - - mTransactionCompleted = true; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else if (tb[0] == ACCEL_CALIBRATION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - mWaitForResponse = false; - byte[] bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - int packetType = tb[0]; - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, packetType); - mTransactionCompleted = true; - mInstructionStackLock = false; - } else if (tb[0] == ALL_CALIBRATION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mWaitForResponse = false; - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - if (mShimmerVersion != Shimmer.SHIMMER_3) { - byte[] bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, ACCEL_CALIBRATION_RESPONSE); - - //get gyro - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, GYRO_CALIBRATION_RESPONSE); - - //get mag - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, MAG_CALIBRATION_RESPONSE); - - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - bufferCalibrationParameters = new byte[12]; - mInStream.read(bufferCalibrationParameters, 0, 12); //just read the EMG and ECG values for now. - - if (bufferCalibrationParameters[0] == -1 && bufferCalibrationParameters[1] == -1 && bufferCalibrationParameters[2] == -1 && bufferCalibrationParameters[3] == -1) { - mDefaultCalibrationParametersEMG = true; - } else { - mDefaultCalibrationParametersEMG = false; - OffsetEMG = (double) ((bufferCalibrationParameters[0] & 0xFF) << 8) + (bufferCalibrationParameters[1] & 0xFF); - GainEMG = (double) ((bufferCalibrationParameters[2] & 0xFF) << 8) + (bufferCalibrationParameters[3] & 0xFF); - } - if (bufferCalibrationParameters[4] == -1 && bufferCalibrationParameters[5] == -1 && bufferCalibrationParameters[6] == -1 && bufferCalibrationParameters[7] == -1) { - mDefaultCalibrationParametersECG = true; - } else { - mDefaultCalibrationParametersECG = false; - OffsetECGLALL = (double) ((bufferCalibrationParameters[4] & 0xFF) << 8) + (bufferCalibrationParameters[5] & 0xFF); - GainECGLALL = (double) ((bufferCalibrationParameters[6] & 0xFF) << 8) + (bufferCalibrationParameters[7] & 0xFF); - OffsetECGRALL = (double) ((bufferCalibrationParameters[8] & 0xFF) << 8) + (bufferCalibrationParameters[9] & 0xFF); - GainECGRALL = (double) ((bufferCalibrationParameters[10] & 0xFF) << 8) + (bufferCalibrationParameters[11] & 0xFF); - } - - mTransactionCompleted = true; - mInstructionStackLock = false; - - } else { - - - byte[] bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, ACCEL_CALIBRATION_RESPONSE); - - //get gyro - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, GYRO_CALIBRATION_RESPONSE); - - //get mag - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, MAG_CALIBRATION_RESPONSE); - - //second accel cal params - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, LSM303DLHC_ACCEL_CALIBRATION_RESPONSE); - mTransactionCompleted = true; - mInstructionStackLock = false; - - } - } else if (tb[0] == GYRO_CALIBRATION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - mWaitForResponse = false; - byte[] bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - int packetType = tb[0]; - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, packetType); - mTransactionCompleted = true; - mInstructionStackLock = false; - } else if (tb[0] == MAG_CALIBRATION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - mWaitForResponse = false; - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - byte[] bufferCalibrationParameters = new byte[21]; - mInStream.read(bufferCalibrationParameters, 0, 21); - int packetType = tb[0]; - retrievecalibrationparametersfrompacket(bufferCalibrationParameters, packetType); - mTransactionCompleted = true; - mInstructionStackLock = false; - } else if (tb[0] == CONFIG_BYTE0_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - byte[] bufferConfigByte0 = new byte[1]; - mInStream.read(bufferConfigByte0, 0, 1); - mConfigByte0 = bufferConfigByte0[0] & 0xFF; - mTransactionCompleted = true; - mInstructionStackLock = false; - } else if (tb[0] == GET_SHIMMER_VERSION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - byte[] bufferShimmerVersion = new byte[1]; - mInStream.read(bufferShimmerVersion, 0, 1); - mShimmerVersion = (int) bufferShimmerVersion[0]; - generateBiMapSensorIDtoSensorName(); - mTransactionCompleted = true; - mInstructionStackLock = false; - if (mShimmerVersion == SHIMMER_2R) { - initializeShimmer2R(); - } else if (mShimmerVersion == SHIMMER_3) { - initializeShimmer3(); - } - } else if (tb[0] == ECG_CALIBRATION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - byte[] bufferCalibrationParameters = new byte[8]; - mInStream.read(bufferCalibrationParameters, 0, 4); //just read the EMCG and ECG values for now. - //get ecg - if (bufferCalibrationParameters[0] == -1 && bufferCalibrationParameters[1] == -1 && bufferCalibrationParameters[2] == -1 && bufferCalibrationParameters[3] == -1) { - mDefaultCalibrationParametersECG = true; - } else { - mDefaultCalibrationParametersECG = false; - OffsetECGLALL = (double) ((bufferCalibrationParameters[0] & 0xFF) << 8) + (bufferCalibrationParameters[1] & 0xFF); - GainECGLALL = (double) ((bufferCalibrationParameters[2] & 0xFF) << 8) + (bufferCalibrationParameters[3] & 0xFF); - OffsetECGRALL = (double) ((bufferCalibrationParameters[4] & 0xFF) << 8) + (bufferCalibrationParameters[5] & 0xFF); - GainECGRALL = (double) ((bufferCalibrationParameters[6] & 0xFF) << 8) + (bufferCalibrationParameters[7] & 0xFF); - } - mTransactionCompleted = true; - mInstructionStackLock = false; - } else if (tb[0] == EMG_CALIBRATION_RESPONSE) { - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - Log.d("Shimmer", "Response received: " + Integer.toString(mCurrentCommand)); - try { - Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read - } catch (InterruptedException e) { - e.printStackTrace(); - } - byte[] bufferCalibrationParameters = new byte[4]; - mInStream.read(bufferCalibrationParameters, 0, 4); //just read the EMCG and ECG values for now. - //get ecg - if (bufferCalibrationParameters[0] == -1 && bufferCalibrationParameters[1] == -1 && bufferCalibrationParameters[2] == -1 && bufferCalibrationParameters[3] == -1) { - mDefaultCalibrationParametersEMG = true; - } else { - mDefaultCalibrationParametersEMG = false; - OffsetEMG = (double) ((bufferCalibrationParameters[0] & 0xFF) << 8) + (bufferCalibrationParameters[1] & 0xFF); - GainEMG = (double) ((bufferCalibrationParameters[2] & 0xFF) << 8) + (bufferCalibrationParameters[3] & 0xFF); - } - mTransactionCompleted = true; - mInstructionStackLock = false; - } - } - } - if (mStreaming == true) { - mInStream.read(tb, 0, 1); - - - //Log.d("Shimmer","Incoming Byte: " + Byte.toString(tb[0])); // can be commented out to watch the incoming bytes - if (mSync == true) { //if the stack is full - if (mWaitForAck == true && (byte) tb[0] == ACK_COMMAND_PROCESSED && byteStack.size() == mPacketSize + 1) { //this is to handle acks during mid stream, acks only are received between packets. - if (mCurrentCommand == SET_BLINK_LED) { - Log.d("ShimmerCMD", "LED_BLINK_ACK_DETECTED"); - mWaitForAck = false; - mTransactionCompleted = true; - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mCurrentLEDStatus = (int) ((byte[]) mListofInstructions.get(0))[1]; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } - } else { // the first time you start streaming it will go through this piece of code to make sure the data streaming is alligned/sync - if (byteStack.size() == mPacketSize + 1) { - if (tb[0] == DATA_PACKET && byteStack.firstElement() == DATA_PACKET) { //check for the starting zero of the packet, and the starting zero of the subsequent packet, this causes a delay equivalent to the transmission duration between two packets - newPacket = convertstacktobytearray(byteStack, mPacketSize); - ObjectCluster objectCluster = (ObjectCluster) buildMsg(newPacket, mGetDataInstruction); - //printtofile(newmsg.UncalibratedData); - mHandler.obtainMessage(MESSAGE_READ, objectCluster) - .sendToTarget(); - byteStack.clear(); - if (mContinousSync == false) { //disable continuous synchronizing - mSync = false; - } - } - } - /*if (mStreaming==true && mWaitForAck==true && (byte)tb[0]==ACK_COMMAND_PROCESSED && (packetStack.size()==0)){ //this is to handle acks during mid stream, acks only are received between packets. - Log.d("ShimmerCMD","LED_BLINK_ACK_DETECTED"); - mWaitForAck=false; - mCurrentLEDStatus=mTempIntValue; - mTransactionCompleted = true; - } */ - byteStack.push((tb[0])); //push new sensor data into the stack - if (byteStack.size() > mPacketSize + 1) { //if the stack has reached the packet size remove an element from the stack - byteStack.removeElementAt(0); - Log.d("ShimmerCMD", "Throwing Data"); - } - } - } else if (mSync == false) { - if (mWaitForAck == true && (byte) tb[0] == ACK_COMMAND_PROCESSED && byteStack.size() == 0) { //this is to handle acks during mid stream, acks only are received between packets. - if (mCurrentCommand == SET_BLINK_LED) { - Log.d("ShimmerCMD", "LED_BLINK_ACK_DETECTED"); - mWaitForAck = false; - mTransactionCompleted = true; - mTimer.cancel(); //cancel the ack timer - mTimer.purge(); - mCurrentLEDStatus = (int) ((byte[]) mListofInstructions.get(0))[1]; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } - } else { - byteStack.push((tb[0])); //push new sensor data into the stack - if (byteStack.firstElement() == DATA_PACKET && (byteStack.size() == mPacketSize + 1)) { //only used when continous sync is disabled - newPacket = convertstacktobytearray(byteStack, mPacketSize); - ObjectCluster objectCluster = (ObjectCluster) buildMsg(newPacket, mGetDataInstruction); //the packet which is an array of bytes is converted to the data structure - mHandler.obtainMessage(MESSAGE_READ, objectCluster) - .sendToTarget(); - byteStack.clear(); - } - - if (byteStack.size() > mPacketSize) { //if the stack has reached the packet size remove an element from the stack - byteStack.removeElementAt(0); - Log.d("ShimmerCMD", "Throwing Data"); - } - } - } - - - } - - - } catch (IOException e) { - Log.d("Shimmer", e.toString()); - connectionLost(); - break; - } - - - } - } - - - /** - * Write to the connected OutStream. - * - * @param buffer The bytes to write - */ - private void write(byte[] buffer) { - try { - mmOutStream.write(buffer); - Log.d("Shimmer", "Command transmitted: " + mMyBluetoothAddress + "; Command Issued: " + mCurrentCommand); - - } catch (IOException e) { - Log.d("Shimmer", "Command NOT transmitted: " + mMyBluetoothAddress + "; Command Issued: " + mCurrentCommand); - } - } - - public void cancel() { - if (mInStream != null) { - try { - mInStream.close(); - } catch (IOException e) { - } - } - if (mmOutStream != null) { - try { - mmOutStream.close(); - } catch (IOException e) { - } - } - if (mmSocket != null) { - try { - if (mBluetoothLib == 0) { - mmSocket.close(); - } else { - mSocket.close(); - } - } catch (IOException e) { - } - } - } - } - - - public synchronized void responseTimer(int seconds) { - if (mTimer != null) { - mTimer.cancel(); - mTimer.purge(); - } - Log.d("ShimmerTimer", Integer.toString(mCurrentCommand)); - mTimer = new Timer(); - mTimer.schedule(new responseTask(), seconds * 1000); - } - - class responseTask extends TimerTask { - public void run() { - { - if (mCurrentCommand == GET_FW_VERSION_COMMAND) { - Log.d("ShimmerFW", "FW Response Timeout"); - mFWVersion = 0.1; - mFWInternal = 0; - mFWVersionFullName = "BoilerPlate 0.1.0"; - /*Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Firmware Version: " +mFWVersionFullName); - msg.setData(bundle);*/ - if (!mDummy) { - //mHandler.sendMessage(msg); - } - mWaitForAck = false; - mTransactionCompleted = true; //should be false, so the driver will know that the command has to be executed again, this is not supported at the moment - mTimer.cancel(); //Terminate the timer thread - mTimer.purge(); - mFirstTime = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - initializeBoilerPlate(); - } else if (mCurrentCommand == GET_SAMPLING_RATE_COMMAND && mInitialized == false) { - Log.d("ShimmerFW", "FW Response Timeout"); - mWaitForAck = false; - mTransactionCompleted = true; //should be false, so the driver will know that the command has to be executed again, this is not supported at the moment - mTimer.cancel(); //Terminate the timer thread - mTimer.purge(); - mFirstTime = false; - mListofInstructions.remove(0); - mInstructionStackLock = false; - } else { - Log.d("Shimmer", "Command " + Integer.toString(mCurrentCommand) + " failed; Killing Connection " + Double.toString(mSamplingRate)); - if (mWaitForResponse) { - Log.d("Shimmer", "Response not received"); - - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Response not received, please reset Shimmer Device." + mMyBluetoothAddress); - msg.setData(bundle); - mHandler.sendMessage(msg); - } - mWaitForAck = false; - mTransactionCompleted = true; //should be false, so the driver will know that the command has to be executed again, this is not supported at the moment - stop(); //If command fail exit device - - } - } - } - } - - - private synchronized void initialize() { //See two constructors for Shimmer - Log.d("Shimmer", "Get FW Version"); // no ack means it boilerplate version 0.0 - //InstructionsThread instructionsThread = new InstructionsThread(); - //instructionsThread.start(); - dummyreadSamplingRate(); // it actually acts to clear the write buffer - readFWVersion(); - //mShimmerVersion=4; - - } - - public void initializeBoilerPlate() { - readSamplingRate(); - readConfigByte0(); - readCalibrationParameters("Accelerometer"); - readCalibrationParameters("Magnetometer"); - readCalibrationParameters("Gyroscope"); - if (mSetupDevice == true && mShimmerVersion != 4) { - writeAccelRange(mAccelRange); - writeGSRRange(mGSRRange); - writeSamplingRate(mSamplingRate); - writeEnabledSensors(mSetEnabledSensors); - setContinuousSync(mContinousSync); - } else { - inquiry(); - } - } - - /** - * By default once connected no low power modes will be enabled. Low power modes should be enabled post connection once the MSG_STATE_FULLY_INITIALIZED is sent - */ - private void initializeShimmer2R() { - mAccelSmartSetting = ACCEL_SMART_MODE; // this setting does nothing for Shimmer2R and should always be kept to this setting when using Shimmer2R - readSamplingRate(); - Log.d("Shimmer", "Device " + mMyBluetoothAddress + " initializing"); - readMagSamplingRate(); - writeBufferSize(1); - readBlinkLED(); - readConfigByte0(); - readCalibrationParameters("All"); - if (mSetupDevice == true) { - writeMagRange(mMagGain); //set to default Shimmer mag gain - writeAccelRange(mAccelRange); - writeGSRRange(mGSRRange); - writeSamplingRate(mSamplingRate); - writeEnabledSensors(mSetEnabledSensors); - setContinuousSync(mContinousSync); - } else { - inquiry(); - } - } - - - private void initializeShimmer3() { - readSamplingRate(); - Log.d("Shimmer", "Device " + mMyBluetoothAddress + " initializing"); - readMagRange(); - readAccelRange(); - readGyroRange(); - readAccelSamplingRate(); - readCalibrationParameters("All"); - //enableLowPowerMag(mLowPowerMag); - if (mSetupDevice == true) { - //writeAccelRange(mAccelRange); - writeAccelRange(mAccelRange); - writeGyroRange(mGyroRange); - writeMagRange(mMagGain); - writeSamplingRate(mSamplingRate); - setContinuousSync(mContinousSync); - writeEnabledSensors(mSetEnabledSensors); //this should always be the last command - } else { - inquiry(); - } - } - - private void inquiryDone() { - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Inquiry done for device-> " + mMyBluetoothAddress); - msg.setData(bundle); - mHandler.sendMessage(msg); - isReadyForStreaming(); - } - - private void isReadyForStreaming() { - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Device " + mMyBluetoothAddress + " is ready for Streaming"); - msg.setData(bundle); - mHandler.sendMessage(msg); - if (mInitialized == false) { - //only do this during the initialization process to indicate that it is fully initialized, dont do this for a normal inqiuiry - mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_FULLY_INITIALIZED, -1, new ObjectCluster(mMyName, getBluetoothAddress())).sendToTarget(); - mInitialized = true; - } - Log.d("Shimmer", "Shimmer " + mMyBluetoothAddress + " Initialization completed and is ready for Streaming"); - } - - private void isNowStreaming() { - - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Device " + mMyBluetoothAddress + " is now Streaming"); - msg.setData(bundle); - mHandler.sendMessage(msg); - Log.d("Shimmer", "Shimmer " + mMyBluetoothAddress + " is now Streaming"); - } - - /* - * Set and Get Methods - * */ - public void setContinuousSync(boolean continousSync) { - mContinousSync = continousSync; - } - - public boolean getStreamingStatus() { - return mStreaming; - } - - public String getBluetoothAddress() { - return mMyBluetoothAddress; - } - - public int getEnabledSensors() { - return mEnabledSensors; - } - - public void setgetdatainstruction(String... instruction) { - mGetDataInstruction = instruction; - } - - /** - * This returns the variable mTransactionCompleted which indicates whether the Shimmer device is in the midst of a command transaction. True when no transaction is taking place. This is deprecated since the update to a thread model for executing commands - * - * @return mTransactionCompleted - */ - public boolean getInstructionStatus() { - boolean instructionStatus = false; - if (mTransactionCompleted == true) { - instructionStatus = true; - } else { - instructionStatus = false; - } - return instructionStatus; - } - - public double getSamplingRate() { - return mSamplingRate; - } - - - /* - * Data Methods - * */ - - /** - * Converts the raw packet byte values, into the corresponding calibrated and uncalibrated sensor values, the Instruction String determines the output - * - * @param data a byte array containing the current received packet - * @param dataType an array string containing the commands to execute. It is currently not fully supported - * @return - */ - protected int[] parsedData(byte[] data, String[] dataType) { - int iData = 0; - int[] formattedData = new int[dataType.length]; - - for (int i = 0; i < dataType.length; i++) - if (dataType[i] == "u8") { - formattedData[i] = (int) data[iData]; - iData = iData + 1; - } else if (dataType[i] == "i8") { - formattedData[i] = calculatetwoscomplement((int) ((int) 0xFF & data[iData]), 8); - iData = iData + 1; - } else if (dataType[i] == "u12") { - - formattedData[i] = (int) ((int) (data[iData] & 0xFF) + ((int) (data[iData + 1] & 0xFF) << 8)); - iData = iData + 2; - } else if (dataType[i] == "i12>") { - formattedData[i] = calculatetwoscomplement((int) ((int) (data[iData] & 0xFF) + ((int) (data[iData + 1] & 0xFF) << 8)), 16); - formattedData[i] = formattedData[i] >> 4; // shift right by 4 bits - iData = iData + 2; - } else if (dataType[i] == "u16") { - formattedData[i] = (int) ((int) (data[iData] & 0xFF) + ((int) (data[iData + 1] & 0xFF) << 8)); - iData = iData + 2; - } else if (dataType[i] == "i16") { - formattedData[i] = calculatetwoscomplement((int) ((int) (data[iData] & 0xFF) + ((int) (data[iData + 1] & 0xFF) << 8)), 16); - //formattedData[i]=ByteBuffer.wrap(arrayb).order(ByteOrder.LITTLE_ENDIAN).getShort(); - iData = iData + 2; - } else if (dataType[i] == "i16*") { - formattedData[i] = calculatetwoscomplement((int) ((int) (data[iData + 1] & 0xFF) + ((int) (data[iData] & 0xFF) << 8)), 16); - //formattedData[i]=ByteBuffer.wrap(arrayb).order(ByteOrder.LITTLE_ENDIAN).getShort(); - iData = iData + 2; - } - return formattedData; - } - - private int[] formatdatapacketreverse(byte[] data, String[] dataType) { - int iData = 0; - int[] formattedData = new int[dataType.length]; - - for (int i = 0; i < dataType.length; i++) - if (dataType[i] == "u8") { - formattedData[i] = (int) data[iData]; - iData = iData + 1; - } else if (dataType[i] == "i8") { - formattedData[i] = calculatetwoscomplement((int) ((int) 0xFF & data[iData]), 8); - iData = iData + 1; - } else if (dataType[i] == "u12") { - - formattedData[i] = (int) ((int) (data[iData + 1] & 0xFF) + ((int) (data[iData] & 0xFF) << 8)); - iData = iData + 2; - } else if (dataType[i] == "u16") { - - formattedData[i] = (int) ((int) (data[iData + 1] & 0xFF) + ((int) (data[iData] & 0xFF) << 8)); - iData = iData + 2; - } else if (dataType[i] == "i16") { - - formattedData[i] = calculatetwoscomplement((int) ((int) (data[iData + 1] & 0xFF) + ((int) (data[iData] & 0xFF) << 8)), 16); - iData = iData + 2; - } - return formattedData; - } - - private int calculatetwoscomplement(int signedData, int bitLength) { - int newData = signedData; - if (signedData > (1 << (bitLength - 1))) { - newData = -((signedData ^ (int) (Math.pow(2, bitLength) - 1)) + 1); - } - - return newData; - } - - protected int getSignalIndex(String signalName) { - int iSignal = 0; //used to be -1, putting to zero ensure it works eventhough it might be wrong SR30 - for (int i = 0; i < mSignalNameArray.length; i++) { - if (signalName == mSignalNameArray[i]) { - iSignal = i; - } - } - - return iSignal; - } - - private void interpretdatapacketformat(int nC, byte[] signalid) { - String[] signalNameArray = new String[19]; - String[] signalDataTypeArray = new String[19]; - signalNameArray[0] = "TimeStamp"; - signalDataTypeArray[0] = "u16"; - int packetSize = 2; // Time stamp - int enabledSensors = 0x00; - for (int i = 0; i < nC; i++) { - if ((byte) signalid[i] == (byte) 0x00) { - if (mShimmerVersion == SHIMMER_SR30 || mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Low Noise Accelerometer X"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL_S3); - } else { - signalNameArray[i + 1] = "Accelerometer X"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_ACCEL); - } - } else if ((byte) signalid[i] == (byte) 0x01) { - if (mShimmerVersion == SHIMMER_SR30 || mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Low Noise Accelerometer Y"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL_S3); - } else { - signalNameArray[i + 1] = "Accelerometer Y"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_ACCEL); - } - } else if ((byte) signalid[i] == (byte) 0x02) { - if (mShimmerVersion == SHIMMER_SR30 || mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Low Noise Accelerometer Z"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL_S3); - } else { - signalNameArray[i + 1] = "Accelerometer Z"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_ACCEL); - } - } else if ((byte) signalid[i] == (byte) 0x03) { - - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Gyroscope X"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "VSenseBatt"; //should be the battery but this will do for now - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_VBATT_S3); - } else { - signalNameArray[i + 1] = "Gyroscope X"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_GYRO); - } - } else if ((byte) signalid[i] == (byte) 0x04) { - - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Gyroscope Y"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Wide Range Accelerometer X"; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3); - } else { - signalNameArray[i + 1] = "Gyroscope Y"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_GYRO); - } - } else if ((byte) signalid[i] == (byte) 0x05) { - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Gyroscope Z"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Wide Range Accelerometer Y"; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3); - } else { - signalNameArray[i + 1] = "Gyroscope Z"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_GYRO); - } - } else if ((byte) signalid[i] == (byte) 0x06) { - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "VSenseBatt"; //should be the battery but this will do for now - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_VBATT_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Wide Range Accelerometer Z"; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3); - } else { - signalNameArray[i + 1] = "Magnetometer X"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_MAG); - } - - - } else if ((byte) signalid[i] == (byte) 0x07) { - if (mShimmerVersion == SHIMMER_SR30) { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Wide Range Accelerometer X"; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Magnetometer X"; - signalDataTypeArray[i + 1] = "i16*"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3); - } else { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Magnetometer Y"; - enabledSensors = (enabledSensors | SENSOR_MAG); - } - - - } else if ((byte) signalid[i] == (byte) 0x08) { - if (mShimmerVersion == SHIMMER_SR30) { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Wide Range Accelerometer Y"; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Magnetometer Y"; - signalDataTypeArray[i + 1] = "i16*"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3); - } else { - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - signalNameArray[i + 1] = "Magnetometer Z"; - enabledSensors = (enabledSensors | SENSOR_MAG); - } - - } else if ((byte) signalid[i] == (byte) 0x09) { - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Wide Range Accelerometer Z"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Magnetometer Z"; - signalDataTypeArray[i + 1] = "i16*"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3); - } else { - signalNameArray[i + 1] = "ECG RA LL"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_ECG); - } - - - } else if ((byte) signalid[i] == (byte) 0x0A) { - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Magnetometer X"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Gyroscope X"; - signalDataTypeArray[i + 1] = "i16*"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3); - } else { - - signalNameArray[i + 1] = "ECG LA LL"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_ECG); - } - } else if ((byte) signalid[i] == (byte) 0x0B) { - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Magnetometer Y"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Gyroscope Y"; - signalDataTypeArray[i + 1] = "i16*"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3); - } else { - signalNameArray[i + 1] = "GSR Raw"; - signalDataTypeArray[i + 1] = "u16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_GSR); - } - } else if ((byte) signalid[i] == (byte) 0x0C) { - if (mShimmerVersion == SHIMMER_SR30) { - signalNameArray[i + 1] = "Magnetometer Z"; - signalDataTypeArray[i + 1] = "i16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3); - } else if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Gyroscope Z"; - signalDataTypeArray[i + 1] = "i16*"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3); - } else { - signalNameArray[i + 1] = "GSR Res"; - signalDataTypeArray[i + 1] = "u16"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_GSR); - } - } else if ((byte) signalid[i] == (byte) 0x0D) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "External ADC A7"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_EXT_ADC_A7); - } else { - signalNameArray[i + 1] = "EMG"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_EMG); - } - } else if ((byte) signalid[i] == (byte) 0x0E) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "External ADC A6"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_EXT_ADC_A6); - } else { - signalNameArray[i + 1] = "Exp Board A0"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_EXP_BOARD_A0); - } - } else if ((byte) signalid[i] == (byte) 0x0F) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "External ADC A15"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_EXT_ADC_A15); - } else { - signalNameArray[i + 1] = "Exp Board A7"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_EXP_BOARD_A7); - } - } else if ((byte) signalid[i] == (byte) 0x10) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Internal ADC A1"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_INT_ADC_A1); - } else { - signalNameArray[i + 1] = "Strain Gauge High"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_STRAIN); - } - } else if ((byte) signalid[i] == (byte) 0x11) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Internal ADC A12"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_INT_ADC_A12); - } else { - signalNameArray[i + 1] = "Strain Gauge Low"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_STRAIN); - } - } else if ((byte) signalid[i] == (byte) 0x12) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Internal ADC A13"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_INT_ADC_A13); - } else { - signalNameArray[i + 1] = "Heart Rate"; - if (mFWVersion == 0.1) { - signalDataTypeArray[i + 1] = "u8"; - packetSize = packetSize + 1; - } else { - signalDataTypeArray[i + 1] = "u16"; - packetSize = packetSize + 2; - } - enabledSensors = (enabledSensors | SENSOR_HEART); - } - } else if ((byte) signalid[i] == (byte) 0x13) { - if (mShimmerVersion == SHIMMER_3) { - signalNameArray[i + 1] = "Internal ADC A14"; - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - enabledSensors = (enabledSensors | SENSOR_INT_ADC_A14); - } - } else { - signalNameArray[i + 1] = Byte.toString(signalid[i]); - signalDataTypeArray[i + 1] = "u12"; - packetSize = packetSize + 2; - } - } - mSignalNameArray = signalNameArray; - mSignalDataTypeArray = signalDataTypeArray; - mPacketSize = packetSize; - } - - private void retrievecalibrationparametersfrompacket(byte[] bufferCalibrationParameters, int packetType) { - String[] dataType = {"i16", "i16", "i16", "i16", "i16", "i16", "i8", "i8", "i8", "i8", "i8", "i8", "i8", "i8", "i8"}; - int[] formattedPacket = formatdatapacketreverse(bufferCalibrationParameters, dataType); // using the datatype the calibration parameters are converted - double[] AM = new double[9]; - for (int i = 0; i < 9; i++) { - AM[i] = ((double) formattedPacket[6 + i]) / 100; - } - - double[][] AlignmentMatrix = {{AM[0], AM[1], AM[2]}, {AM[3], AM[4], AM[5]}, {AM[6], AM[7], AM[8]}}; - double[][] SensitivityMatrix = {{formattedPacket[3], 0, 0}, {0, formattedPacket[4], 0}, {0, 0, formattedPacket[5]}}; - double[][] OffsetVector = {{formattedPacket[0]}, {formattedPacket[1]}, {formattedPacket[2]}}; - - - if (packetType == ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] != -1) { //used to be 65535 but changed to -1 as we are now using i16 - mDefaultCalibrationParametersAccel = false; - Log.d("Shimmer", "Accel Offet Vector(0,0): " + Double.toString(OffsetVector[0][0]) + "; Accel Sen Matrix(0,0): " + Double.toString(SensitivityMatrix[0][0]) + "; Accel Align Matrix(0,0): " + Double.toString(AlignmentMatrix[0][0])); - AlignmentMatrixAccel = AlignmentMatrix; - OffsetVectorAccel = OffsetVector; - SensitivityMatrixAccel = SensitivityMatrix; - } else if (packetType == ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] == -1) { - mDefaultCalibrationParametersAccel = true; - if (mShimmerVersion != 3) { - AlignmentMatrixAccel = AlignmentMatrixAccelShimmer2; - OffsetVectorAccel = OffsetVectorAccelShimmer2; - if (getAccelRange() == 0) { - SensitivityMatrixAccel = SensitivityMatrixAccel1p5gShimmer2; - } else if (getAccelRange() == 1) { - SensitivityMatrixAccel = SensitivityMatrixAccel2gShimmer2; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel = SensitivityMatrixAccel4gShimmer2; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel = SensitivityMatrixAccel6gShimmer2; - } - } else { - if (getAccelRange() == 0) { - SensitivityMatrixAccel = SensitivityMatrixLowNoiseAccel2gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixLowNoiseAccelShimmer3; - OffsetVectorAccel = OffsetVectorLowNoiseAccelShimmer3; - } else if (getAccelRange() == 1) { - SensitivityMatrixAccel = SensitivityMatrixWideRangeAccel4gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel = SensitivityMatrixWideRangeAccel8gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel = SensitivityMatrixWideRangeAccel16gShimmer3; - AlignmentMatrixAccel = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel = OffsetVectorWideRangeAccelShimmer3; - } - - - } - } - - if (packetType == LSM303DLHC_ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] != -1) { //used to be 65535 but changed to -1 as we are now using i16 - mDefaultCalibrationParametersDigitalAccel = false; - Log.d("Shimmer", "Accel Offet Vector(0,0): " + Double.toString(OffsetVector[0][0]) + "; Accel Sen Matrix(0,0): " + Double.toString(SensitivityMatrix[0][0]) + "; Accel Align Matrix(0,0): " + Double.toString(AlignmentMatrix[0][0])); - AlignmentMatrixAccel2 = AlignmentMatrix; - OffsetVectorAccel2 = OffsetVector; - SensitivityMatrixAccel2 = SensitivityMatrix; - } else if (packetType == LSM303DLHC_ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] == -1) { - mDefaultCalibrationParametersDigitalAccel = true; - if (getAccelRange() == 0) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel2gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixLowNoiseAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorLowNoiseAccelShimmer3; - } else if (getAccelRange() == 1) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel4gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 2) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel8gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } else if (getAccelRange() == 3) { - SensitivityMatrixAccel2 = SensitivityMatrixWideRangeAccel16gShimmer3; - AlignmentMatrixAccel2 = AlignmentMatrixWideRangeAccelShimmer3; - OffsetVectorAccel2 = OffsetVectorWideRangeAccelShimmer3; - } - } - if (packetType == GYRO_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] != -1) { - mDefaultCalibrationParametersGyro = false; - AlignmentMatrixGyro = AlignmentMatrix; - OffsetVectorGyro = OffsetVector; - SensitivityMatrixGyro = SensitivityMatrix; - SensitivityMatrixGyro[0][0] = SensitivityMatrixGyro[0][0] / 100; - SensitivityMatrixGyro[1][1] = SensitivityMatrixGyro[1][1] / 100; - SensitivityMatrixGyro[2][2] = SensitivityMatrixGyro[2][2] / 100; - Log.d("Shimmer", "Gyro Offet Vector(0,0): " + Double.toString(OffsetVector[0][0]) + "; Gyro Sen Matrix(0,0): " + Double.toString(SensitivityMatrix[0][0]) + "; Gyro Align Matrix(0,0): " + Double.toString(AlignmentMatrix[0][0])); - } else if (packetType == GYRO_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] == -1) { - mDefaultCalibrationParametersGyro = true; - if (mShimmerVersion != 3) { - AlignmentMatrixGyro = AlignmentMatrixGyroShimmer2; - OffsetVectorGyro = OffsetVectorGyroShimmer2; - SensitivityMatrixGyro = SensitivityMatrixGyroShimmer2; - } else { - if (mGyroRange == 0) { - SensitivityMatrixGyro = SensitivityMatrixGyro250dpsShimmer3; - - } else if (mGyroRange == 1) { - SensitivityMatrixGyro = SensitivityMatrixGyro500dpsShimmer3; - - } else if (mGyroRange == 2) { - SensitivityMatrixGyro = SensitivityMatrixGyro1000dpsShimmer3; - - } else if (mGyroRange == 3) { - SensitivityMatrixGyro = SensitivityMatrixGyro2000dpsShimmer3; - } - AlignmentMatrixGyro = AlignmentMatrixGyroShimmer3; - OffsetVectorGyro = OffsetVectorGyroShimmer3; - } - } - if (packetType == MAG_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] != -1) { - mDefaultCalibrationParametersMag = false; - AlignmentMatrixMag = AlignmentMatrix; - OffsetVectorMag = OffsetVector; - SensitivityMatrixMag = SensitivityMatrix; - Log.d("Shimmer", "Mag Offet Vector(0,0): " + Double.toString(OffsetVector[0][0]) + "; Mag Sen Matrix(0,0): " + Double.toString(SensitivityMatrix[0][0]) + "; Mag Align Matrix(0,0): " + Double.toString(AlignmentMatrix[0][0])); - } else if (packetType == MAG_CALIBRATION_RESPONSE && SensitivityMatrix[0][0] == -1) { - mDefaultCalibrationParametersMag = true; - if (mShimmerVersion != 3) { - AlignmentMatrixMag = AlignmentMatrixMagShimmer2; - OffsetVectorMag = OffsetVectorMagShimmer2; - SensitivityMatrixMag = SensitivityMatrixMagShimmer2; - } else { - AlignmentMatrixMag = AlignmentMatrixMagShimmer3; - OffsetVectorMag = OffsetVectorMagShimmer3; - SensitivityMatrixMag = SensitivityMatrixMagShimmer3; - } - } - } - - private double[][] matrixinverse3x3(double[][] data) { - double a, b, c, d, e, f, g, h, i; - a = data[0][0]; - b = data[0][1]; - c = data[0][2]; - d = data[1][0]; - e = data[1][1]; - f = data[1][2]; - g = data[2][0]; - h = data[2][1]; - i = data[2][2]; - // - double deter = a * e * i + b * f * g + c * d * h - c * e * g - b * d * i - a * f * h; - double[][] answer = new double[3][3]; - answer[0][0] = (1 / deter) * (e * i - f * h); - - answer[0][1] = (1 / deter) * (c * h - b * i); - answer[0][2] = (1 / deter) * (b * f - c * e); - answer[1][0] = (1 / deter) * (f * g - d * i); - answer[1][1] = (1 / deter) * (a * i - c * g); - answer[1][2] = (1 / deter) * (c * d - a * f); - answer[2][0] = (1 / deter) * (d * h - e * g); - answer[2][1] = (1 / deter) * (g * b - a * h); - answer[2][2] = (1 / deter) * (a * e - b * d); - return answer; - } - - private double[][] matrixminus(double[][] a, double[][] b) { - int aRows = a.length, - aColumns = a[0].length, - bRows = b.length, - bColumns = b[0].length; - if ((aColumns != bColumns) && (aRows != bRows)) { - throw new IllegalArgumentException(" Matrix did not match"); - } - double[][] resultant = new double[aRows][bColumns]; - for (int i = 0; i < aRows; i++) { // aRow - for (int k = 0; k < aColumns; k++) { // aColumn - - resultant[i][k] = a[i][k] - b[i][k]; - - } - } - return resultant; - } - - private double[][] matrixmultiplication(double[][] a, double[][] b) { - - int aRows = a.length, - aColumns = a[0].length, - bRows = b.length, - bColumns = b[0].length; - - if (aColumns != bRows) { - throw new IllegalArgumentException("A:Rows: " + aColumns + " did not match B:Columns " + bRows + "."); - } - - double[][] resultant = new double[aRows][bColumns]; - - for (int i = 0; i < aRows; i++) { // aRow - for (int j = 0; j < bColumns; j++) { // bColumn - for (int k = 0; k < aColumns; k++) { // aColumn - resultant[i][j] += a[i][k] * b[k][j]; - } - } - } - - return resultant; - } - - protected double calibrateTimeStamp(double timeStamp) { - //first convert to continuous time stamp - double calibratedTimeStamp = 0; - if (mLastReceivedTimeStamp > (timeStamp + (65536 * mCurrentTimeStampCycle))) { - mCurrentTimeStampCycle = mCurrentTimeStampCycle + 1; - } - - mLastReceivedTimeStamp = (timeStamp + (65536 * mCurrentTimeStampCycle)); - calibratedTimeStamp = mLastReceivedTimeStamp / 32768 * 1000; // to convert into mS - if (mFirstTimeCalTime) { - mFirstTimeCalTime = false; - mCalTimeStart = calibratedTimeStamp; - } - if (mLastReceivedCalibratedTimeStamp != -1) { - double timeDifference = calibratedTimeStamp - mLastReceivedCalibratedTimeStamp; - if (timeDifference > (1 / (mSamplingRate - 1)) * 1000) { - mPacketLossCount = mPacketLossCount + 1; - Long mTotalNumberofPackets = (long) ((calibratedTimeStamp - mCalTimeStart) / (1 / mSamplingRate * 1000)); - Log.d("SHIMMERPACKETRR", " " + Long.toString(mPacketLossCount) + " " + Double.toString(timeDifference) + " " + Double.toString((double) (mTotalNumberofPackets - mPacketLossCount) / (double) mTotalNumberofPackets)); - mPacketReceptionRate = (double) ((mTotalNumberofPackets - mPacketLossCount) / (double) mTotalNumberofPackets) * 100; - mHandler.obtainMessage(Shimmer.MESSAGE_PACKET_LOSS_DETECTED, new ObjectCluster(mMyName, getBluetoothAddress())).sendToTarget(); - } - } - mLastReceivedCalibratedTimeStamp = calibratedTimeStamp; - return calibratedTimeStamp; - } - - protected double[] calibrateInertialSensorData(double[] data, double[][] AM, double[][] SM, double[][] OV) { - /* Based on the theory outlined by Ferraris F, Grimaldi U, and Parvis M. - in "Procedure for effortless in-field calibration of three-axis rate gyros and accelerometers" Sens. Mater. 1995; 7: 311-30. - C = [R^(-1)] .[K^(-1)] .([U]-[B]) - where..... - [C] -> [3 x n] Calibrated Data Matrix - [U] -> [3 x n] Uncalibrated Data Matrix - [B] -> [3 x n] Replicated Sensor Offset Vector Matrix - [R^(-1)] -> [3 x 3] Inverse Alignment Matrix - [K^(-1)] -> [3 x 3] Inverse Sensitivity Matrix - n = Number of Samples - */ - double[][] data2d = new double[3][1]; - data2d[0][0] = data[0]; - data2d[1][0] = data[1]; - data2d[2][0] = data[2]; - data2d = matrixmultiplication(matrixmultiplication(matrixinverse3x3(AM), matrixinverse3x3(SM)), matrixminus(data2d, OV)); - double[] ansdata = new double[3]; - ansdata[0] = data2d[0][0]; - ansdata[1] = data2d[1][0]; - ansdata[2] = data2d[2][0]; - return ansdata; - } - - protected double calibrateU12AdcValue(double uncalibratedData, double offset, double vRefP, double gain) { - double calibratedData = (uncalibratedData - offset) * (((vRefP * 1000) / gain) / 4095); - return calibratedData; - } - - protected double calibrateGsrData(double gsrUncalibratedData, double p1, double p2) { - gsrUncalibratedData = (double) ((int) gsrUncalibratedData & 4095); - //the following polynomial is deprecated and has been replaced with a more accurate linear one, see GSR user guide for further details - //double gsrCalibratedData = (p1*Math.pow(gsrUncalibratedData,4)+p2*Math.pow(gsrUncalibratedData,3)+p3*Math.pow(gsrUncalibratedData,2)+p4*gsrUncalibratedData+p5)/1000; - //the following is the new linear method see user GSR user guide for further details - double gsrCalibratedData = (1 / (p1 * gsrUncalibratedData + p2)) * 1000; //kohms - return gsrCalibratedData; - } - - - protected Object buildMsg(byte[] newPacket, String... Instructions) { - ObjectCluster objectCluster = new ObjectCluster(mMyName, getBluetoothAddress()); - double[] calibratedData = new double[mNChannels + 1]; //plus 1 because of the time stamp - int[] newPacketInt = parsedData(newPacket, mSignalDataTypeArray); - double[] tempData = new double[3]; - Vector3d accelerometer = new Vector3d(); - Vector3d magnetometer = new Vector3d(); - Vector3d gyroscope = new Vector3d(); - mTempPacketCountforBatt = mTempPacketCountforBatt + 1; - for (int i = 0; i < Instructions.length; i++) { - if ((Instructions[i] == "a" || Instructions[i] == "c")) { - int iTimeStamp = getSignalIndex("TimeStamp"); //find index - tempData[0] = (double) newPacketInt[1]; - objectCluster.mPropertyCluster.put("Timestamp", new FormatCluster("RAW", "no units", (double) newPacketInt[iTimeStamp])); - objectCluster.mPropertyCluster.put("Timestamp", new FormatCluster("CAL", "mSecs", calibrateTimeStamp((double) newPacketInt[iTimeStamp]))); - - if (mShimmerVersion == SHIMMER_SR30 || mShimmerVersion == SHIMMER_3) { - if ((((mEnabledSensors & 0xFF) & SENSOR_ACCEL) > 0) && (mAccelSmartSetting == ACCEL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_SMART_MODE)) { - int iAccelX = getSignalIndex("Low Noise Accelerometer X"); //find index - int iAccelY = getSignalIndex("Low Noise Accelerometer Y"); //find index - int iAccelZ = getSignalIndex("Low Noise Accelerometer Z"); //find index - //check range - if (mAccelRange != 0) { - iAccelX = getSignalIndex("Wide Range Accelerometer X"); //find index - iAccelY = getSignalIndex("Wide Range Accelerometer Y"); //find index - iAccelZ = getSignalIndex("Wide Range Accelerometer Z"); //find index - } - tempData[0] = (double) newPacketInt[iAccelX]; - tempData[1] = (double) newPacketInt[iAccelY]; - tempData[2] = (double) newPacketInt[iAccelZ]; - double[] accelCalibratedData; - if (mAccelRange != 0) { - accelCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixAccel2, SensitivityMatrixAccel2, OffsetVectorAccel2); - } else { - accelCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixAccel, SensitivityMatrixAccel, OffsetVectorAccel); - } - calibratedData[iAccelX] = accelCalibratedData[0]; - calibratedData[iAccelY] = accelCalibratedData[1]; - calibratedData[iAccelZ] = accelCalibratedData[2]; - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelY])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelZ])); - if ((mDefaultCalibrationParametersDigitalAccel == true && mAccelRange != 0) || (mDefaultCalibrationParametersAccel == true && mAccelRange == 0)) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[2])); - accelerometer.x = accelCalibratedData[0]; - accelerometer.y = accelCalibratedData[1]; - accelerometer.z = accelCalibratedData[2]; - } else { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[2])); - accelerometer.x = accelCalibratedData[0]; - accelerometer.y = accelCalibratedData[1]; - accelerometer.z = accelCalibratedData[2]; - } - } - if ((((mEnabledSensors & 0xFF) & SENSOR_ACCEL) > 0) && (mAccelSmartSetting == ACCEL_DUAL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_MODE)) { - int iAccelX = getSignalIndex("Low Noise Accelerometer X"); //find index - int iAccelY = getSignalIndex("Low Noise Accelerometer Y"); //find index - int iAccelZ = getSignalIndex("Low Noise Accelerometer Z"); //find index - //check range - - tempData[0] = (double) newPacketInt[iAccelX]; - tempData[1] = (double) newPacketInt[iAccelY]; - tempData[2] = (double) newPacketInt[iAccelZ]; - double[] accelCalibratedData; - accelCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixAccel, SensitivityMatrixAccel, OffsetVectorAccel); - - calibratedData[iAccelX] = accelCalibratedData[0]; - calibratedData[iAccelY] = accelCalibratedData[1]; - calibratedData[iAccelZ] = accelCalibratedData[2]; - objectCluster.mPropertyCluster.put("Low Noise Accelerometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Low Noise Accelerometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelY])); - objectCluster.mPropertyCluster.put("Low Noise Accelerometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelZ])); - if (((mEnabledSensors & 0xFFFF) & SENSOR_DACCEL) == 0 && mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelY])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelZ])); - } - if (mDefaultCalibrationParametersAccel == true) { - objectCluster.mPropertyCluster.put("Low Noise Accelerometer X", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Low Noise Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Low Noise Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[2])); - if (((mEnabledSensors & 0xFFFF) & SENSOR_DACCEL) == 0 && mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[2])); - } - if (mAccelSmartSetting == ACCEL_DUAL_MODE) { - accelerometer.x = accelCalibratedData[0]; - accelerometer.y = accelCalibratedData[1]; - accelerometer.z = accelCalibratedData[2]; - } - } else { - objectCluster.mPropertyCluster.put("Low Noise Accelerometer X", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Low Noise Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Low Noise Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[2])); - if (((mEnabledSensors & 0xFFFF) & SENSOR_DACCEL) == 0 && mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[2])); - } - if (mAccelSmartSetting == ACCEL_DUAL_MODE) { - accelerometer.x = accelCalibratedData[0]; - accelerometer.y = accelCalibratedData[1]; - accelerometer.z = accelCalibratedData[2]; - } - } - } - if ((((mEnabledSensors & 0xFFFF) & SENSOR_DACCEL) > 0) && (mAccelSmartSetting == ACCEL_DUAL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_MODE)) { - int iAccelX = getSignalIndex("Wide Range Accelerometer X"); //find index - int iAccelY = getSignalIndex("Wide Range Accelerometer Y"); //find index - int iAccelZ = getSignalIndex("Wide Range Accelerometer Z"); //find index - //check range - - tempData[0] = (double) newPacketInt[iAccelX]; - tempData[1] = (double) newPacketInt[iAccelY]; - tempData[2] = (double) newPacketInt[iAccelZ]; - double[] accelCalibratedData; - accelCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixAccel2, SensitivityMatrixAccel2, OffsetVectorAccel2); - - calibratedData[iAccelX] = accelCalibratedData[0]; - calibratedData[iAccelY] = accelCalibratedData[1]; - calibratedData[iAccelZ] = accelCalibratedData[2]; - objectCluster.mPropertyCluster.put("Wide Range Accelerometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Wide Range Accelerometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelY])); - objectCluster.mPropertyCluster.put("Wide Range Accelerometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelZ])); - if (((mEnabledSensors & 0xFF) & SENSOR_ACCEL) == 0 && mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - } - if (mDefaultCalibrationParametersDigitalAccel == true) { - objectCluster.mPropertyCluster.put("Wide Range Accelerometer X", new FormatCluster("CAL", "m/(sec^2)*", calibratedData[iAccelX])); - objectCluster.mPropertyCluster.put("Wide Range Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)*", calibratedData[iAccelY])); - objectCluster.mPropertyCluster.put("Wide Range Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)*", calibratedData[iAccelZ])); - if (((mEnabledSensors & 0xFF) & SENSOR_ACCEL) == 0 && mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)*", calibratedData[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)*", calibratedData[iAccelY])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)*", calibratedData[iAccelZ])); - } - if (mAccelSmartSetting == ACCEL_DUAL_MODE) { - accelerometer.x = calibratedData[iAccelX]; - accelerometer.y = calibratedData[iAccelY]; - accelerometer.z = calibratedData[iAccelZ]; - } - } else { - objectCluster.mPropertyCluster.put("Wide Range Accelerometer X", new FormatCluster("CAL", "m/(sec^2)", calibratedData[iAccelX])); - objectCluster.mPropertyCluster.put("Wide Range Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)", calibratedData[iAccelY])); - objectCluster.mPropertyCluster.put("Wide Range Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)", calibratedData[iAccelZ])); - if (((mEnabledSensors & 0xFF) & SENSOR_ACCEL) == 0 && mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)", calibratedData[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)", calibratedData[iAccelY])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)", calibratedData[iAccelZ])); - } - if (mAccelSmartSetting == ACCEL_DUAL_MODE) { - accelerometer.x = calibratedData[iAccelX]; - accelerometer.y = calibratedData[iAccelY]; - accelerometer.z = calibratedData[iAccelZ]; - } - } - } - if (((mEnabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - int iGyroX = getSignalIndex("Gyroscope X"); - int iGyroY = getSignalIndex("Gyroscope Y"); - int iGyroZ = getSignalIndex("Gyroscope Z"); - tempData[0] = (double) newPacketInt[iGyroX]; - tempData[1] = (double) newPacketInt[iGyroY]; - tempData[2] = (double) newPacketInt[iGyroZ]; - double[] gyroCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixGyro, SensitivityMatrixGyro, OffsetVectorGyro); - calibratedData[iGyroX] = gyroCalibratedData[0]; - calibratedData[iGyroY] = gyroCalibratedData[1]; - calibratedData[iGyroZ] = gyroCalibratedData[2]; - - objectCluster.mPropertyCluster.put("Gyroscope X", new FormatCluster("RAW", "no units", (double) newPacketInt[iGyroX])); - objectCluster.mPropertyCluster.put("Gyroscope Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iGyroY])); - objectCluster.mPropertyCluster.put("Gyroscope Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iGyroZ])); - if (mDefaultCalibrationParametersGyro == true) { - objectCluster.mPropertyCluster.put("Gyroscope X", new FormatCluster("CAL", "deg/sec*", gyroCalibratedData[0])); - objectCluster.mPropertyCluster.put("Gyroscope Y", new FormatCluster("CAL", "deg/sec*", gyroCalibratedData[1])); - objectCluster.mPropertyCluster.put("Gyroscope Z", new FormatCluster("CAL", "deg/sec*", gyroCalibratedData[2])); - gyroscope.x = gyroCalibratedData[0] * Math.PI / 180; - gyroscope.y = gyroCalibratedData[1] * Math.PI / 180; - gyroscope.z = gyroCalibratedData[2] * Math.PI / 180; - } else { - objectCluster.mPropertyCluster.put("Gyroscope X", new FormatCluster("CAL", "deg/sec", gyroCalibratedData[0])); - objectCluster.mPropertyCluster.put("Gyroscope Y", new FormatCluster("CAL", "deg/sec", gyroCalibratedData[1])); - objectCluster.mPropertyCluster.put("Gyroscope Z", new FormatCluster("CAL", "deg/sec", gyroCalibratedData[2])); - gyroscope.x = gyroCalibratedData[0] * Math.PI / 180; - gyroscope.y = gyroCalibratedData[1] * Math.PI / 180; - gyroscope.z = gyroCalibratedData[2] * Math.PI / 180; - if (mEnableOntheFlyGyroOVCal) { - mGyroX.addValue(gyroCalibratedData[0]); - mGyroY.addValue(gyroCalibratedData[1]); - mGyroZ.addValue(gyroCalibratedData[2]); - mGyroXRaw.addValue((double) newPacketInt[iGyroX]); - mGyroYRaw.addValue((double) newPacketInt[iGyroY]); - mGyroZRaw.addValue((double) newPacketInt[iGyroZ]); - if (mGyroX.getStandardDeviation() < mGyroOVCalThreshold && mGyroY.getStandardDeviation() < mGyroOVCalThreshold && mGyroZ.getStandardDeviation() < mGyroOVCalThreshold) { - OffsetVectorGyro[0][0] = mGyroXRaw.getMean(); - OffsetVectorGyro[1][0] = mGyroYRaw.getMean(); - OffsetVectorGyro[2][0] = mGyroZRaw.getMean(); - } - } - } - - } - if (((mEnabledSensors & 0xFF) & SENSOR_MAG) > 0) { - int iMagX = getSignalIndex("Magnetometer X"); - int iMagY = getSignalIndex("Magnetometer Y"); - int iMagZ = getSignalIndex("Magnetometer Z"); - tempData[0] = (double) newPacketInt[iMagX]; - tempData[1] = (double) newPacketInt[iMagY]; - tempData[2] = (double) newPacketInt[iMagZ]; - double[] magCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixMag, SensitivityMatrixMag, OffsetVectorMag); - calibratedData[iMagX] = magCalibratedData[0]; - calibratedData[iMagY] = magCalibratedData[1]; - calibratedData[iMagZ] = magCalibratedData[2]; - - objectCluster.mPropertyCluster.put("Magnetometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iMagX])); - objectCluster.mPropertyCluster.put("Magnetometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iMagY])); - objectCluster.mPropertyCluster.put("Magnetometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iMagZ])); - if (mDefaultCalibrationParametersMag == true) { - objectCluster.mPropertyCluster.put("Magnetometer X", new FormatCluster("CAL", "local*", magCalibratedData[0])); - objectCluster.mPropertyCluster.put("Magnetometer Y", new FormatCluster("CAL", "local*", magCalibratedData[1])); - objectCluster.mPropertyCluster.put("Magnetometer Z", new FormatCluster("CAL", "local*", magCalibratedData[2])); - magnetometer.x = magCalibratedData[0]; - magnetometer.y = magCalibratedData[1]; - magnetometer.z = magCalibratedData[2]; - } else { - objectCluster.mPropertyCluster.put("Magnetometer X", new FormatCluster("CAL", "local", magCalibratedData[0])); - objectCluster.mPropertyCluster.put("Magnetometer Y", new FormatCluster("CAL", "local", magCalibratedData[1])); - objectCluster.mPropertyCluster.put("Magnetometer Z", new FormatCluster("CAL", "local", magCalibratedData[2])); - magnetometer.x = magCalibratedData[0]; - magnetometer.y = magCalibratedData[1]; - magnetometer.z = magCalibratedData[2]; - } - } - - if ((mEnabledSensors & SENSOR_BATT) > 0) { - int iA0 = getSignalIndex("VSenseBatt"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1) * 1.988; - objectCluster.mPropertyCluster.put("VSenseBatt", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("VSenseBatt", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_EXT_ADC_A7) > 0) { - int iA0 = getSignalIndex("External ADC A7"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("External ADC A7", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("External ADC A7", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_EXT_ADC_A6) > 0) { - int iA0 = getSignalIndex("External ADC A6"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("External ADC A6", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("External ADC A6", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_EXT_ADC_A15) > 0) { - int iA0 = getSignalIndex("External ADC A15"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("External ADC A15", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("External ADC A15", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_INT_ADC_A1) > 0) { - int iA0 = getSignalIndex("Internal ADC A1"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("Internal ADC A1", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("Internal ADC A1", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_INT_ADC_A12) > 0) { - int iA0 = getSignalIndex("Internal ADC A12"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("Internal ADC A12", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("Internal ADC A12", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_INT_ADC_A13) > 0) { - int iA0 = getSignalIndex("Internal ADC A13"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("Internal ADC A13", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("Internal ADC A13", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if ((mEnabledSensors & SENSOR_INT_ADC_A14) > 0) { - int iA0 = getSignalIndex("Internal ADC A14"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("Internal ADC A14", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("Internal ADC A14", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } - if (((mEnabledSensors & 0xFF) & SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF) & SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & SENSOR_MAG) > 0 && mOrientationEnabled) { - - Quaternion q = mOrientationAlgo.update(accelerometer.x, accelerometer.y, accelerometer.z, gyroscope.x, gyroscope.y, gyroscope.z, magnetometer.x, magnetometer.y, magnetometer.z); - - - double theta, Rx, Ry, Rz, rho; - rho = Math.acos(q.q1); - theta = rho * 2; - Rx = q.q2 / Math.sin(rho); - Ry = q.q3 / Math.sin(rho); - Rz = q.q4 / Math.sin(rho); - - - objectCluster.mPropertyCluster.put("Axis Angle A", new FormatCluster("CAL", "local", theta)); - objectCluster.mPropertyCluster.put("Axis Angle X", new FormatCluster("CAL", "local", Rx)); - objectCluster.mPropertyCluster.put("Axis Angle Y", new FormatCluster("CAL", "local", Ry)); - objectCluster.mPropertyCluster.put("Axis Angle Z", new FormatCluster("CAL", "local", Rz)); - - - objectCluster.mPropertyCluster.put("Quaternion 0", new FormatCluster("CAL", "local", q.q1)); - objectCluster.mPropertyCluster.put("Quaternion 1", new FormatCluster("CAL", "local", q.q2)); - objectCluster.mPropertyCluster.put("Quaternion 2", new FormatCluster("CAL", "local", q.q3)); - objectCluster.mPropertyCluster.put("Quaternion 3", new FormatCluster("CAL", "local", q.q4)); - } - - - } else { - - if (((mEnabledSensors & 0xFF) & SENSOR_ACCEL) > 0) { - int iAccelX = getSignalIndex("Accelerometer X"); //find index - int iAccelY = getSignalIndex("Accelerometer Y"); //find index - int iAccelZ = getSignalIndex("Accelerometer Z"); //find index - tempData[0] = (double) newPacketInt[iAccelX]; - tempData[1] = (double) newPacketInt[iAccelY]; - tempData[2] = (double) newPacketInt[iAccelZ]; - double[] accelCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixAccel, SensitivityMatrixAccel, OffsetVectorAccel); - calibratedData[iAccelX] = accelCalibratedData[0]; - calibratedData[iAccelY] = accelCalibratedData[1]; - calibratedData[iAccelZ] = accelCalibratedData[2]; - - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelX])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelY])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iAccelZ])); - if (mDefaultCalibrationParametersAccel == true) { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)*", accelCalibratedData[2])); - accelerometer.x = accelCalibratedData[0]; - accelerometer.y = accelCalibratedData[1]; - accelerometer.z = accelCalibratedData[2]; - } else { - objectCluster.mPropertyCluster.put("Accelerometer X", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[0])); - objectCluster.mPropertyCluster.put("Accelerometer Y", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[1])); - objectCluster.mPropertyCluster.put("Accelerometer Z", new FormatCluster("CAL", "m/(sec^2)", accelCalibratedData[2])); - accelerometer.x = accelCalibratedData[0]; - accelerometer.y = accelCalibratedData[1]; - accelerometer.z = accelCalibratedData[2]; - } - - } - - if (((mEnabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - int iGyroX = getSignalIndex("Gyroscope X"); - int iGyroY = getSignalIndex("Gyroscope Y"); - int iGyroZ = getSignalIndex("Gyroscope Z"); - tempData[0] = (double) newPacketInt[iGyroX]; - tempData[1] = (double) newPacketInt[iGyroY]; - tempData[2] = (double) newPacketInt[iGyroZ]; - double[] gyroCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixGyro, SensitivityMatrixGyro, OffsetVectorGyro); - calibratedData[iGyroX] = gyroCalibratedData[0]; - calibratedData[iGyroY] = gyroCalibratedData[1]; - calibratedData[iGyroZ] = gyroCalibratedData[2]; - - objectCluster.mPropertyCluster.put("Gyroscope X", new FormatCluster("RAW", "no units", (double) newPacketInt[iGyroX])); - objectCluster.mPropertyCluster.put("Gyroscope Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iGyroY])); - objectCluster.mPropertyCluster.put("Gyroscope Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iGyroZ])); - if (mDefaultCalibrationParametersGyro == true) { - objectCluster.mPropertyCluster.put("Gyroscope X", new FormatCluster("CAL", "deg/sec*", gyroCalibratedData[0])); - objectCluster.mPropertyCluster.put("Gyroscope Y", new FormatCluster("CAL", "deg/sec*", gyroCalibratedData[1])); - objectCluster.mPropertyCluster.put("Gyroscope Z", new FormatCluster("CAL", "deg/sec*", gyroCalibratedData[2])); - gyroscope.x = gyroCalibratedData[0] * Math.PI / 180; - gyroscope.y = gyroCalibratedData[1] * Math.PI / 180; - gyroscope.z = gyroCalibratedData[2] * Math.PI / 180; - } else { - objectCluster.mPropertyCluster.put("Gyroscope X", new FormatCluster("CAL", "deg/sec", gyroCalibratedData[0])); - objectCluster.mPropertyCluster.put("Gyroscope Y", new FormatCluster("CAL", "deg/sec", gyroCalibratedData[1])); - objectCluster.mPropertyCluster.put("Gyroscope Z", new FormatCluster("CAL", "deg/sec", gyroCalibratedData[2])); - gyroscope.x = gyroCalibratedData[0] * Math.PI / 180; - gyroscope.y = gyroCalibratedData[1] * Math.PI / 180; - gyroscope.z = gyroCalibratedData[2] * Math.PI / 180; - if (mEnableOntheFlyGyroOVCal) { - mGyroX.addValue(gyroCalibratedData[0]); - mGyroY.addValue(gyroCalibratedData[1]); - mGyroZ.addValue(gyroCalibratedData[2]); - mGyroXRaw.addValue((double) newPacketInt[iGyroX]); - mGyroYRaw.addValue((double) newPacketInt[iGyroY]); - mGyroZRaw.addValue((double) newPacketInt[iGyroZ]); - if (mGyroX.getStandardDeviation() < mGyroOVCalThreshold && mGyroY.getStandardDeviation() < mGyroOVCalThreshold && mGyroZ.getStandardDeviation() < mGyroOVCalThreshold) { - OffsetVectorGyro[0][0] = mGyroXRaw.getMean(); - OffsetVectorGyro[1][0] = mGyroYRaw.getMean(); - OffsetVectorGyro[2][0] = mGyroZRaw.getMean(); - } - } - } - - } - if (((mEnabledSensors & 0xFF) & SENSOR_MAG) > 0) { - int iMagX = getSignalIndex("Magnetometer X"); - int iMagY = getSignalIndex("Magnetometer Y"); - int iMagZ = getSignalIndex("Magnetometer Z"); - tempData[0] = (double) newPacketInt[iMagX]; - tempData[1] = (double) newPacketInt[iMagY]; - tempData[2] = (double) newPacketInt[iMagZ]; - double[] magCalibratedData = calibrateInertialSensorData(tempData, AlignmentMatrixMag, SensitivityMatrixMag, OffsetVectorMag); - calibratedData[iMagX] = magCalibratedData[0]; - calibratedData[iMagY] = magCalibratedData[1]; - calibratedData[iMagZ] = magCalibratedData[2]; - - objectCluster.mPropertyCluster.put("Magnetometer X", new FormatCluster("RAW", "no units", (double) newPacketInt[iMagX])); - objectCluster.mPropertyCluster.put("Magnetometer Y", new FormatCluster("RAW", "no units", (double) newPacketInt[iMagY])); - objectCluster.mPropertyCluster.put("Magnetometer Z", new FormatCluster("RAW", "no units", (double) newPacketInt[iMagZ])); - if (mDefaultCalibrationParametersMag == true) { - objectCluster.mPropertyCluster.put("Magnetometer X", new FormatCluster("CAL", "local*", magCalibratedData[0])); - objectCluster.mPropertyCluster.put("Magnetometer Y", new FormatCluster("CAL", "local*", magCalibratedData[1])); - objectCluster.mPropertyCluster.put("Magnetometer Z", new FormatCluster("CAL", "local*", magCalibratedData[2])); - magnetometer.x = magCalibratedData[0]; - magnetometer.y = magCalibratedData[1]; - magnetometer.z = magCalibratedData[2]; - } else { - objectCluster.mPropertyCluster.put("Magnetometer X", new FormatCluster("CAL", "local", magCalibratedData[0])); - objectCluster.mPropertyCluster.put("Magnetometer Y", new FormatCluster("CAL", "local", magCalibratedData[1])); - objectCluster.mPropertyCluster.put("Magnetometer Z", new FormatCluster("CAL", "local", magCalibratedData[2])); - magnetometer.x = magCalibratedData[0]; - magnetometer.y = magCalibratedData[1]; - magnetometer.z = magCalibratedData[2]; - } - } - - - if (((mEnabledSensors & 0xFF) & SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF) & SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & SENSOR_MAG) > 0 && mOrientationEnabled) { - - Quaternion q = mOrientationAlgo.update(accelerometer.x, accelerometer.y, accelerometer.z, gyroscope.x, gyroscope.y, gyroscope.z, magnetometer.x, magnetometer.y, magnetometer.z); - - - double theta, Rx, Ry, Rz, rho; - rho = Math.acos(q.q1); - theta = rho * 2; - Rx = q.q2 / Math.sin(rho); - Ry = q.q3 / Math.sin(rho); - Rz = q.q4 / Math.sin(rho); - - - objectCluster.mPropertyCluster.put("Axis Angle A", new FormatCluster("CAL", "local", theta)); - objectCluster.mPropertyCluster.put("Axis Angle X", new FormatCluster("CAL", "local", Rx)); - objectCluster.mPropertyCluster.put("Axis Angle Y", new FormatCluster("CAL", "local", Ry)); - objectCluster.mPropertyCluster.put("Axis Angle Z", new FormatCluster("CAL", "local", Rz)); - - - objectCluster.mPropertyCluster.put("Quartenion 0", new FormatCluster("CAL", "local", q.q1)); - objectCluster.mPropertyCluster.put("Quartenion 1", new FormatCluster("CAL", "local", q.q2)); - objectCluster.mPropertyCluster.put("Quartenion 2", new FormatCluster("CAL", "local", q.q3)); - objectCluster.mPropertyCluster.put("Quartenion 3", new FormatCluster("CAL", "local", q.q4)); - } - - - if (((mEnabledSensors & 0xFF) & SENSOR_GSR) > 0) { - int iGSR = getSignalIndex("GSR Raw"); - tempData[0] = (double) newPacketInt[iGSR]; - int newGSRRange = -1; // initialized to -1 so it will only come into play if mGSRRange = 4 - - double p1 = 0, p2 = 0;//,p3=0,p4=0,p5=0; - if (mGSRRange == 4) { - newGSRRange = (49152 & (int) tempData[0]) >> 14; - } - if (mGSRRange == 0 || newGSRRange == 0) { //Note that from FW 1.0 onwards the MSB of the GSR data contains the range - // the polynomial function used for calibration has been deprecated, it is replaced with a linear function - /* p1 = 6.5995E-9; - p2 = -6.895E-5; - p3 = 2.699E-1; - p4 = -4.769835E+2; - p5 = 3.403513341E+5;*/ - p1 = 0.0373; - p2 = -24.9915; - } else if (mGSRRange == 1 || newGSRRange == 1) { - /*p1 = 1.3569627E-8; - p2 = -1.650399E-4; - p3 = 7.54199E-1; - p4 = -1.5726287856E+3; - p5 = 1.367507927E+6;*/ - p1 = 0.0054; - p2 = -3.5194; - } else if (mGSRRange == 2 || newGSRRange == 2) { - /*p1 = 2.550036498E-8; - p2 = -3.3136E-4; - p3 = 1.6509426597E+0; - p4 = -3.833348044E+3; - p5 = 3.8063176947E+6;*/ - p1 = 0.0015; - p2 = -1.0163; - } else if (mGSRRange == 3 || newGSRRange == 3) { - /*p1 = 3.7153627E-7; - p2 = -4.239437E-3; - p3 = 1.7905709E+1; - p4 = -3.37238657E+4; - p5 = 2.53680446279E+7;*/ - p1 = 4.5580e-04; - p2 = -0.3014; - } - - calibratedData[iGSR] = calibrateGsrData(tempData[0], p1, p2); - objectCluster.mPropertyCluster.put("GSR", new FormatCluster("RAW", "no units", (double) newPacketInt[iGSR])); - objectCluster.mPropertyCluster.put("GSR", new FormatCluster("CAL", "kOhms", calibratedData[iGSR])); - } - if (((mEnabledSensors & 0xFF) & SENSOR_ECG) > 0) { - int iECGRALL = getSignalIndex("ECG RA LL"); - int iECGLALL = getSignalIndex("ECG LA LL"); - tempData[0] = (double) newPacketInt[iECGRALL]; - tempData[1] = (double) newPacketInt[iECGLALL]; - calibratedData[iECGRALL] = calibrateU12AdcValue(tempData[0], OffsetECGRALL, 3, GainECGRALL); - calibratedData[iECGLALL] = calibrateU12AdcValue(tempData[1], OffsetECGLALL, 3, GainECGLALL); - objectCluster.mPropertyCluster.put("ECG RA-LL", new FormatCluster("RAW", "no units", (double) newPacketInt[iECGRALL])); - objectCluster.mPropertyCluster.put("ECG LA-LL", new FormatCluster("RAW", "no units", (double) newPacketInt[iECGLALL])); - if (mDefaultCalibrationParametersECG == true) { - objectCluster.mPropertyCluster.put("ECG RA-LL", new FormatCluster("CAL", "mVolts*", calibratedData[iECGRALL])); - objectCluster.mPropertyCluster.put("ECG LA-LL", new FormatCluster("CAL", "mVolts*", calibratedData[iECGLALL])); - } else { - objectCluster.mPropertyCluster.put("ECG RA-LL", new FormatCluster("CAL", "mVolts", calibratedData[iECGRALL])); - objectCluster.mPropertyCluster.put("ECG LA-LL", new FormatCluster("CAL", "mVolts", calibratedData[iECGLALL])); - } - } - if (((mEnabledSensors & 0xFF) & SENSOR_EMG) > 0) { - int iEMG = getSignalIndex("EMG"); - tempData[0] = (double) newPacketInt[iEMG]; - calibratedData[iEMG] = calibrateU12AdcValue(tempData[0], OffsetEMG, 3, GainEMG); - objectCluster.mPropertyCluster.put("EMG", new FormatCluster("RAW", "no units", (double) newPacketInt[iEMG])); - - if (mDefaultCalibrationParametersEMG == true) { - objectCluster.mPropertyCluster.put("EMG", new FormatCluster("CAL", "mVolts*", calibratedData[iEMG])); - } else { - objectCluster.mPropertyCluster.put("EMG", new FormatCluster("CAL", "mVolts", calibratedData[iEMG])); - } - } - if (((mEnabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - int iSGHigh = getSignalIndex("Strain Gauge High"); - int iSGLow = getSignalIndex("Strain Gauge Low"); - tempData[0] = (double) newPacketInt[iSGHigh]; - tempData[1] = (double) newPacketInt[iSGLow]; - calibratedData[iSGHigh] = calibrateU12AdcValue(tempData[0], 60, 3, 551 * 2.8); - calibratedData[iSGLow] = calibrateU12AdcValue(tempData[0], 1950, 3, 183.7 * 2.8); - objectCluster.mPropertyCluster.put("Strain Gauge High", new FormatCluster("RAW", "no units", (double) newPacketInt[iSGHigh])); - objectCluster.mPropertyCluster.put("Strain Gauge High", new FormatCluster("CAL", "mVolts", calibratedData[iSGHigh])); - objectCluster.mPropertyCluster.put("Strain Gauge Low", new FormatCluster("RAW", "no units", (double) newPacketInt[iSGLow])); - objectCluster.mPropertyCluster.put("Strain Gauge Low", new FormatCluster("CAL", "mVolts", calibratedData[iSGLow])); - } - if (((mEnabledSensors & 0xFF00) & SENSOR_HEART) > 0) { - int iHeartRate = getSignalIndex("Heart Rate"); - tempData[0] = (double) newPacketInt[iHeartRate]; - calibratedData[iHeartRate] = tempData[0]; - if (mFWVersion == 0.1) { - - } else { - if (tempData[0] == 0) { - calibratedData[iHeartRate] = mLastKnownHeartRate; - } else { - calibratedData[iHeartRate] = (int) (1024 / tempData[0] * 60); - mLastKnownHeartRate = calibratedData[iHeartRate]; - } - } - - objectCluster.mPropertyCluster.put("Heart Rate", new FormatCluster("CAL", "BPM", calibratedData[iHeartRate])); - objectCluster.mPropertyCluster.put("Heart Rate", new FormatCluster("RAW", "no units", tempData[0])); - } - if (((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0) { - int iA0 = getSignalIndex("Exp Board A0"); - tempData[0] = (double) newPacketInt[iA0]; - if (getPMux() == 0) { - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("ExpBoard A0", new FormatCluster("RAW", "no units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("ExpBoard A0", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - } else { - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1) * 1.988; - objectCluster.mPropertyCluster.put("VSenseReg", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("VSenseReg", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - - } - } - if (((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0) { - int iA7 = getSignalIndex("Exp Board A7"); - tempData[0] = (double) newPacketInt[iA7]; - if (getPMux() == 0) { - calibratedData[iA7] = calibrateU12AdcValue(tempData[0], 0, 3, 1); - objectCluster.mPropertyCluster.put("ExpBoard A7", new FormatCluster("RAW", "no units", (double) newPacketInt[iA7])); - objectCluster.mPropertyCluster.put("ExpBoard A7", new FormatCluster("CAL", "mVolts", calibratedData[iA7])); - } - } - if ((mEnabledSensors & SENSOR_BATT) > 0) { - int iA0 = getSignalIndex("Exp Board A0"); - tempData[0] = (double) newPacketInt[iA0]; - calibratedData[iA0] = calibrateU12AdcValue(tempData[0], 0, 3, 1) * 1.988; - objectCluster.mPropertyCluster.put("VSenseReg", new FormatCluster("RAW", "no Units", (double) newPacketInt[iA0])); - objectCluster.mPropertyCluster.put("VSenseReg", new FormatCluster("CAL", "mVolts", calibratedData[iA0])); - - int iA7 = getSignalIndex("Exp Board A7"); - calibratedData[iA7] = calibrateU12AdcValue(tempData[0], 0, 3, 1) * 2; - objectCluster.mPropertyCluster.put("VSenseBatt", new FormatCluster("RAW", "no units", (double) newPacketInt[iA7])); - objectCluster.mPropertyCluster.put("VSenseBatt", new FormatCluster("CAL", "mVolts", calibratedData[iA7])); - - mVSenseBattMA.addValue(calibratedData[iA7]); - if (!mWaitForAck) { - - if (mVSenseBattMA.getMean() < mLowBattLimit * 1000) { - if (mCurrentLEDStatus != 1) { - writeLEDCommand(1); - } - } else if (mVSenseBattMA.getMean() > mLowBattLimit * 1000 + 100) { //+100 is to make sure the limits are different to prevent excessive switching when the batt value is at the threshold - if (mCurrentLEDStatus != 0) { - writeLEDCommand(0); - } - } - - } - - } - } - } - } - return objectCluster; - } - - - private byte[] convertstacktobytearray(Stack b, int packetSize) { - byte[] returnByte = new byte[packetSize]; - b.remove(0); //remove the Data Packet identifier - for (int i = 0; i < packetSize; i++) { - returnByte[packetSize - 1 - i] = (byte) b.pop(); - } - return returnByte; - } - - - /* - * Configure/Read Settings Methods - * */ - - - public boolean sensorConflictCheck(int enabledSensors) { - boolean pass = true; - if (mShimmerVersion != SHIMMER_3) { - if (((enabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_EMG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_ECG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_GSR) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - pass = false; - } - } - - if (((enabledSensors & 0xFF) & SENSOR_MAG) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_EMG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_ECG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_GSR) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - pass = false; - } - } - - if (((enabledSensors & 0xFF) & SENSOR_EMG) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_MAG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_ECG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_GSR) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - pass = false; - } - } - - if (((enabledSensors & 0xFF) & SENSOR_ECG) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_MAG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_EMG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_GSR) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - pass = false; - } - } - - if (((enabledSensors & 0xFF) & SENSOR_GSR) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_MAG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_EMG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_ECG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - pass = false; - } - } - - if (((enabledSensors & 0xFF00) & SENSOR_STRAIN) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_MAG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_EMG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_ECG) > 0) { - pass = false; - } else if (((enabledSensors & 0xFF) & SENSOR_GSR) > 0) { - pass = false; - } else if (get5VReg() == 1) { // if the 5volt reg is set - pass = false; - } - } - - if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0) { - if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { - pass = false; - } else if (getPMux() == 1) { - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Disabling PMux."); - msg.setData(bundle); - mHandler.sendMessage(msg); - writePMux(0); - } - } - - if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0) { - if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { - pass = false; - } else if (getPMux() == 1) { - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Disabling PMux."); - msg.setData(bundle); - mHandler.sendMessage(msg); - writePMux(0); - } - } - - if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { - if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0) { - pass = false; - } - if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0) { - pass = false; - } - if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { - if (getPMux() == 0) { - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Enabling PMux."); - msg.setData(bundle); - mHandler.sendMessage(msg); - writePMux(1); - } - } - } - if (!pass) { - Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Error in Sensor Settings."); - msg.setData(bundle); - mHandler.sendMessage(msg); - } - } - return pass; - } - - /** - * writeAccelRange(range) sets the Accelerometer range on the Shimmer to the value of the input range. When setting/changing the accel range, please ensure you have the correct calibration parameters. Note that the Shimmer device can only carry one set of accel calibration parameters at a single time. - * - * @param range is a numeric value defining the desired accelerometer range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). - */ - public void writeAccelRange(int range) { - mListofInstructions.add(new byte[]{SET_ACCEL_SENSITIVITY_COMMAND, (byte) range}); - mAccelRange = (int) range; - if (mInitialized == true) { //if Shimmer if fully initialized (see initializeShimmer3()), setting the accel range - writeEnabledSensors(mEnabledSensors); - } - } - - /** - * writeGyroRange(range) sets the Gyroscope range on the Shimmer3 to the value of the input range. When setting/changing the range, please ensure you have the correct calibration parameters. - * - * @param range is a numeric value defining the desired gyroscope range. - */ - public void writeGyroRange(int range) { - if (mShimmerVersion == Shimmer.SHIMMER_3) { - mListofInstructions.add(new byte[]{SET_MPU9150_GYRO_RANGE_COMMAND, (byte) range}); - mGyroRange = (int) range; - } - } - - /** - * @param rate Defines the sampling rate to be set (e.g.51.2 sets the sampling rate to 51.2Hz). User should refer to the document Sampling Rate Table to see all possible values. - */ - public void writeSamplingRate(double rate) { - if (getShimmerState() == STATE_CONNECTED) { - - if (mShimmerVersion == SHIMMER_2 || mShimmerVersion == SHIMMER_2R) { - if (!mLowPowerMag) { - if (rate <= 10) { - writeMagSamplingRate(4); - } else if (rate <= 20) { - writeMagSamplingRate(5); - } else { - writeMagSamplingRate(6); - } - } else { - writeMagSamplingRate(4); - } - rate = 1024 / rate; //the equivalent hex setting - mListofInstructions.add(new byte[]{SET_SAMPLING_RATE_COMMAND, (byte) Math.rint(rate), 0x00}); - } else if (mShimmerVersion == SHIMMER_3) { - if (!mLowPowerMag) { - if (rate <= 1) { - writeMagSamplingRate(1); - } else if (rate <= 15) { - writeMagSamplingRate(4); - } else if (rate <= 30) { - writeMagSamplingRate(5); - } else if (rate <= 75) { - writeMagSamplingRate(6); - } else { - writeMagSamplingRate(7); - } - } else { - if (rate >= 10) { - writeMagSamplingRate(4); - } else { - writeMagSamplingRate(1); - } - } - - if (!mLowPowerAccel) { - if (rate <= 1) { - writeAccelSamplingRate(1); - } else if (rate <= 10) { - writeAccelSamplingRate(2); - } else if (rate <= 25) { - writeAccelSamplingRate(3); - } else if (rate <= 50) { - writeAccelSamplingRate(4); - } else if (rate <= 100) { - writeAccelSamplingRate(5); - } else if (rate <= 200) { - writeAccelSamplingRate(6); - } else { - writeAccelSamplingRate(7); - } - } else { - if (rate >= 10) { - writeAccelSamplingRate(2); - } else { - writeAccelSamplingRate(1); - } - } - - if (!mLowPowerGyro) { - if (rate <= 51.28) { - writeGyroSamplingRate(0x9B); - } else if (rate <= 102.56) { - writeGyroSamplingRate(0x4D); - } else if (rate <= 129.03) { - writeGyroSamplingRate(0x3D); - } else if (rate <= 173.91) { - writeGyroSamplingRate(0x2D); - } else if (rate <= 205.13) { - writeGyroSamplingRate(0x26); - } else if (rate <= 258.06) { - writeGyroSamplingRate(0x1E); - } else if (rate <= 533.33) { - writeGyroSamplingRate(0xE); - } else { - writeGyroSamplingRate(6); - } - } else { - writeGyroSamplingRate(0xFF); - } - - - int samplingByteValue = (int) (32768 / rate); - mListofInstructions.add(new byte[]{SET_SAMPLING_RATE_COMMAND, (byte) (samplingByteValue & 0xFF), (byte) ((samplingByteValue >> 8) & 0xFF)}); - - - } - } - } - - private void enableLowResolutionMode(boolean enable) { - while (getInstructionStatus() == false) { - } - ; - if (mFWVersion == 0.1 && mFWInternal == 0) { - - } else if (mShimmerVersion == Shimmer.SHIMMER_3) { - if (enable) { - mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_LPMODE_COMMAND, (byte) 0x01}); - mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_HRMODE_COMMAND, (byte) 0x00}); - - } else { - mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_HRMODE_COMMAND, (byte) 0x01}); - mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_LPMODE_COMMAND, (byte) 0x00}); - - } - - } - } - - /** - * writeMagSamplingRate(range) sets the MagSamplingRate on the Shimmer to the value of the input range. - * - * @param rate for Shimmer 2 it is a value between 1 and 6; 0 = 0.5 Hz; 1 = 1.0 Hz; 2 = 2.0 Hz; 3 = 5.0 Hz; 4 = 10.0 Hz; 5 = 20.0 Hz; 6 = 50.0 Hz, for Shimmer 3 it is a value between 0-7; 0 = 0.75Hz; 1 = 1.5Hz; 2 = 3Hz; 3 = 7.5Hz; 4 = 15Hz ; 5 = 30 Hz; 6 = 75Hz ; 7 = 220Hz - */ - private void writeMagSamplingRate(int rate) { - if (mFWVersion == 0.1 && mFWInternal == 0) { - } else { - mTempIntValue = rate; - mListofInstructions.add(new byte[]{SET_MAG_SAMPLING_RATE_COMMAND, (byte) rate}); - } - } - - /** - * writeAccelSamplingRate(range) sets the AccelSamplingRate on the Shimmer (version 3) to the value of the input range. - * - * @param rate it is a value between 1 and 7; 1 = 1 Hz; 2 = 10 Hz; 3 = 25 Hz; 4 = 50 Hz; 5 = 100 Hz; 6 = 200 Hz; 7 = 400 Hz - */ - private void writeAccelSamplingRate(int rate) { - if (mFWVersion == 0.1 && mFWInternal == 0) { - - } else if (mShimmerVersion == Shimmer.SHIMMER_3) { - mTempIntValue = rate; - mListofInstructions.add(new byte[]{SET_ACCEL_SAMPLING_RATE_COMMAND, (byte) rate}); - } - } - - /** - * writeAccelSamplingRate(range) sets the AccelSamplingRate on the Shimmer (version 3) to the value of the input range. - * - * @param rate it is a value between 0 and 255; 6 = 1152Hz, 77 = 102.56Hz, 255 = 31.25Hz - */ - private void writeGyroSamplingRate(int rate) { - if (mFWVersion == 0.1 && mFWInternal == 0) { - - } else if (mShimmerVersion == Shimmer.SHIMMER_3) { - mTempIntValue = rate; - mListofInstructions.add(new byte[]{SET_MPU9150_SAMPLING_RATE_COMMAND, (byte) rate}); - } - } - - /** - * This enables the low power accel option. When not enabled the sampling rate of the accel is set to the closest value to the actual sampling rate that it can achieve. In low power mode it defaults to 10Hz. Also and additional low power mode is used for the LSM303DLHC. This command will only supports the following Accel range +4g, +8g , +16g - * - * @param enable - */ - public void enableLowPowerAccel(boolean enable) { - mLowPowerAccel = enable; - if (!mLowPowerAccel) { - enableLowResolutionMode(false); - if (mSamplingRate <= 1) { - writeAccelSamplingRate(1); - } else if (mSamplingRate <= 10) { - writeAccelSamplingRate(2); - } else if (mSamplingRate <= 25) { - writeAccelSamplingRate(3); - } else if (mSamplingRate <= 50) { - writeAccelSamplingRate(4); - } else if (mSamplingRate <= 100) { - writeAccelSamplingRate(5); - } else if (mSamplingRate <= 200) { - writeAccelSamplingRate(6); - } else { - writeAccelSamplingRate(7); - } - } else { - enableLowResolutionMode(true); - writeAccelSamplingRate(2); - } - } - - /** - * This enables the low power accel option. When not enabled the sampling rate of the accel is set to the closest value to the actual sampling rate that it can achieve. In low power mode it defaults to 10Hz. Also and additional low power mode is used for the LSM303DLHC. This command will only supports the following Accel range +4g, +8g , +16g - * - * @param enable - */ - public void enableLowPowerGyro(boolean enable) { - mLowPowerGyro = enable; - if (!mLowPowerGyro) { - if (mSamplingRate <= 51.28) { - writeGyroSamplingRate(0x9B); - } else if (mSamplingRate <= 102.56) { - writeGyroSamplingRate(0x4D); - } else if (mSamplingRate <= 129.03) { - writeGyroSamplingRate(0x3D); - } else if (mSamplingRate <= 173.91) { - writeGyroSamplingRate(0x2D); - } else if (mSamplingRate <= 205.13) { - writeGyroSamplingRate(0x26); - } else if (mSamplingRate <= 258.06) { - writeGyroSamplingRate(0x1E); - } else if (mSamplingRate <= 533.33) { - writeGyroSamplingRate(0xE); - } else { - writeGyroSamplingRate(6); - } - } else { - writeGyroSamplingRate(0xFF); - } - } - - - /** - * Transmits a command to the Shimmer device to enable the sensors. To enable multiple sensors an or operator should be used (e.g. writeEnabledSensors(Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO|Shimmer.SENSOR_MAG)). Command should not be used consecutively. Valid values are SENSOR_ACCEL, SENSOR_GYRO, SENSOR_MAG, SENSOR_ECG, SENSOR_EMG, SENSOR_GSR, SENSOR_EXP_BOARD_A7, SENSOR_EXP_BOARD_A0, SENSOR_STRAIN and SENSOR_HEART. - * SENSOR_BATT - * - * @param enabledSensors e.g SENSOR_ACCEL|SENSOR_GYRO|SENSOR_MAG - */ - public void writeEnabledSensors(int enabledSensors) { - if (!sensorConflictCheck(enabledSensors)) { //sensor conflict check - Log.d("Shimmer", "Sensor Conflict Error"); - } else { - enabledSensors = generateSensorBitmapForHardwareControl(enabledSensors); - tempEnabledSensors = enabledSensors; - byte secondByte = (byte) ((enabledSensors & 65280) >> 8); - byte firstByte = (byte) (enabledSensors & 0xFF); - //write(new byte[]{SET_SENSORS_COMMAND,(byte) lowByte, highByte}); - if (mShimmerVersion == Shimmer.SHIMMER_3) { - byte thirdByte = (byte) ((enabledSensors & 16711680) >> 16); - mListofInstructions.add(new byte[]{SET_SENSORS_COMMAND, (byte) firstByte, (byte) secondByte, (byte) thirdByte}); - } else { - mListofInstructions.add(new byte[]{SET_SENSORS_COMMAND, (byte) firstByte, (byte) secondByte}); - } - inquiry(); - } - } - - /** - * @param sensor is a string value that defines the sensor. Accepted sensor values are "Accelerometer","Gyroscope","Magnetometer","ECG","EMG","All" - */ - public void readCalibrationParameters(String sensor) { - if (getShimmerState() == STATE_CONNECTED) { - if (!mInitialized) { - if (mFWVersion == 0.1 && mFWInternal == 0) { - mFWVersionFullName = "BoilerPlate 0.1.0"; - /*Message msg = mHandler.obtainMessage(MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(TOAST, "Firmware Version: " +mFWVersionFullName); - msg.setData(bundle); - mHandler.sendMessage(msg);*/ - } - } - if (sensor.equals("Accelerometer")) { - mListofInstructions.add(new byte[]{GET_ACCEL_CALIBRATION_COMMAND}); - } else if (sensor.equals("Gyroscope")) { - mListofInstructions.add(new byte[]{GET_GYRO_CALIBRATION_COMMAND}); - } else if (sensor.equals("Magnetometer")) { - mListofInstructions.add(new byte[]{GET_MAG_CALIBRATION_COMMAND}); - } else if (sensor.equals("All")) { - mListofInstructions.add(new byte[]{GET_ALL_CALIBRATION_COMMAND}); - } else if (sensor.equals("ECG")) { - mListofInstructions.add(new byte[]{GET_ECG_CALIBRATION_COMMAND}); - } else if (sensor.equals("EMG")) { - mListofInstructions.add(new byte[]{GET_EMG_CALIBRATION_COMMAND}); - } - } - } - - - /** - * writeAccelRange(range) sets the Accelerometer range on the Shimmer to the value of the input range. When setting/changing the accel range, please ensure you have the correct calibration parameters. Note that the Shimmer device can only carry one set of accel calibration parameters at a single time. - * - * @param size is a numeric value defining the desired accelerometer range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). - */ - public void writeBufferSize(int size) { - mListofInstructions.add(new byte[]{SET_BUFFER_SIZE_COMMAND, (byte) size}); - } - - - public void readFWVersion() { - mDummy = false;//false - mListofInstructions.add(new byte[]{GET_FW_VERSION_COMMAND}); - } - - /** - * The reason for this is because sometimes the 1st response is not received by the phone - */ - private void dummyreadSamplingRate() { - mDummy = true; - mListofInstructions.add(new byte[]{GET_SAMPLING_RATE_COMMAND}); - } - - public void stopStreaming() { - mListofInstructions.add(new byte[]{STOP_STREAMING_COMMAND}); - mCurrentLEDStatus = -1; - } - - public void startStreaming() { - mTempPacketCountforBatt = 0; - mPacketLossCount = 0; - mPacketReceptionRate = 100; - mFirstTimeCalTime = true; - mLastReceivedCalibratedTimeStamp = -1; - mOrientationAlgo = new GradDes3DOrientation(0.4, (double) 1 / mSamplingRate, 1, 0, 0, 0); - mSync = true; // a backup sync done every time you start streaming - mListofInstructions.add(new byte[]{START_STREAMING_COMMAND}); - } - - - /** - * writeGSRRange(range) sets the GSR range on the Shimmer to the value of the input range. - * - * @param range numeric value defining the desired GSR range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). - */ - public void writeGSRRange(int range) { - mListofInstructions.add(new byte[]{SET_GSR_RANGE_COMMAND, (byte) range}); - } - - public void readSamplingRate() { - mListofInstructions.add(new byte[]{GET_SAMPLING_RATE_COMMAND}); - } - - /** - * An inquiry is used to request for the current configuration parameters from the Shimmer device (e.g. Accelerometer settings, Configuration Byte, Sampling Rate, Number of Enabled Sensors and Sensors which have been enabled). - */ - public void inquiry() { - mListofInstructions.add(new byte[]{INQUIRY_COMMAND}); - } - - - /** - * writeMagRange(range) sets the MagSamplingRate on the Shimmer to the value of the input range. When setting/changing the accel range, please ensure you have the correct calibration parameters. Note that the Shimmer device can only carry one set of accel calibration parameters at a single time. - * - * @param range is the mag rang - */ - public void writeMagRange(int range) { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "Command not supported on this firmware version"); - } else { - mListofInstructions.add(new byte[]{SET_MAG_GAIN_COMMAND, (byte) range}); - } - } - - - public void writeLEDCommand(int command) { - if (mShimmerVersion != Shimmer.SHIMMER_3) { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{SET_BLINK_LED, (byte) command}); - } - } - } - - /*public void writeGyroTempVref(int value){ - - }*/ - - - public void writeECGCalibrationParameters(int offsetrall, int gainrall, int offsetlall, int gainlall) { - byte[] data = new byte[8]; - data[0] = (byte) ((offsetlall >> 8) & 0xFF); //MSB offset - data[1] = (byte) ((offsetlall) & 0xFF); - data[2] = (byte) ((gainlall >> 8) & 0xFF); //MSB gain - data[3] = (byte) ((gainlall) & 0xFF); - data[4] = (byte) ((offsetrall >> 8) & 0xFF); //MSB offset - data[5] = (byte) ((offsetrall) & 0xFF); - data[6] = (byte) ((gainrall >> 8) & 0xFF); //MSB gain - data[7] = (byte) ((gainrall) & 0xFF); - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{SET_ECG_CALIBRATION_COMMAND, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]}); - } - } - - public void writeEMGCalibrationParameters(int offset, int gain) { - byte[] data = new byte[4]; - data[0] = (byte) ((offset >> 8) & 0xFF); //MSB offset - data[1] = (byte) ((offset) & 0xFF); - data[2] = (byte) ((gain >> 8) & 0xFF); //MSB gain - data[3] = (byte) ((gain) & 0xFF); - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{SET_EMG_CALIBRATION_COMMAND, data[0], data[1], data[2], data[3]}); - } - } - - public void readGSRRange() { - mListofInstructions.add(new byte[]{GET_GSR_RANGE_COMMAND}); - } - - public void readAccelRange() { - mListofInstructions.add(new byte[]{GET_ACCEL_SENSITIVITY_COMMAND}); - } - - public void readGyroRange() { - mListofInstructions.add(new byte[]{GET_MPU9150_GYRO_RANGE_COMMAND}); - } - - public void readBufferSize() { - mListofInstructions.add(new byte[]{GET_BUFFER_SIZE_COMMAND}); - } - - public void readMagSamplingRate() { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{GET_MAG_SAMPLING_RATE_COMMAND}); - } - } - - /** - * Used to retrieve the data rate of the Accelerometer on Shimmer 3 - */ - public void readAccelSamplingRate() { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{GET_ACCEL_SAMPLING_RATE_COMMAND}); - } - } - - - public void readMagRange() { - mListofInstructions.add(new byte[]{GET_MAG_GAIN_COMMAND}); - } - - public void readBlinkLED() { - mListofInstructions.add(new byte[]{GET_BLINK_LED}); - } - - - public void readECGCalibrationParameters() { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{GET_ECG_CALIBRATION_COMMAND}); - } - } - - public void readEMGCalibrationParameters() { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else { - mListofInstructions.add(new byte[]{GET_EMG_CALIBRATION_COMMAND}); - } - } - - public void readShimmerVersion() { - if (mFWVersion == 0.1 && mFWInternal == 0) { - Log.d("Shimmer", "This Shimmer Version does not support the command"); - } else if ((mFWVersion == 0 && mFWInternal >= 3) || mFWVersion >= 1.3) { - mListofInstructions.add(new byte[]{GET_SHIMMER_VERSION_COMMAND_NEW}); - } else { - mListofInstructions.add(new byte[]{GET_SHIMMER_VERSION_COMMAND}); - } - } - - public void readConfigByte0() { - mListofInstructions.add(new byte[]{GET_CONFIG_BYTE0_COMMAND}); - } - - /** - * writeConfigByte0(configByte0) sets the config byte0 value on the Shimmer to the value of the input configByte0. - * - * @param configByte0 is an unsigned 8 bit value defining the desired config byte 0 value. - */ - public void writeConfigByte0(byte configByte0) { - mListofInstructions.add(new byte[]{SET_CONFIG_BYTE0_COMMAND, (byte) configByte0}); - } - - public void writeInstruction() { - if (getShimmerState() == STATE_CONNECTED) { - byte[] instruction = (byte[]) mListofInstructions.get(0); - write(instruction); - } - } - - - /** - * Sets the Pmux bit value on the Shimmer to the value of the input SETBIT. The PMux bit is the 2nd MSB of config byte0. - * - * @param setBit value defining the desired setting of the PMux (1=ON, 0=OFF). - */ - public void writePMux(int setBit) { - mListofInstructions.add(new byte[]{SET_PMUX_COMMAND, (byte) setBit}); - } - - /** - * Sets the configGyroTempVref bit value on the Shimmer to the value of the input SETBIT. The configGyroTempVref bit is the 2nd MSB of config byte0. - * @param setBit value defining the desired setting of the Gyro Vref (1=ON, 0=OFF). - */ - /*public void writeConfigGyroTempVref(int setBit) { - while(getInstructionStatus()==false) {}; - //Bit value defining the desired setting of the PMux (1=ON, 0=OFF). - if (setBit==1) { - mTempByteValue=(byte) (mConfigByte0|32); - } else if (setBit==0) { - mTempByteValue=(byte)(mConfigByte0 & 223); - } - mCurrentCommand=SET_GYRO_TEMP_VREF_COMMAND; - write(new byte[]{SET_GYRO_TEMP_VREF_COMMAND,(byte) setBit}); - mWaitForAck=true; - mTransactionCompleted=false; - responseTimer(ACK_TIMER_DURATION); - }*/ - - - /** - * Enable/disable the 5 Volt Regulator on the Shimmer ExpBoard board - * - * @param setBit value defining the desired setting of the Volt regulator (1=ENABLED, 0=DISABLED). - */ - public void writeFiveVoltReg(int setBit) { - mListofInstructions.add(new byte[]{SET_5V_REGULATOR_COMMAND, (byte) setBit}); - } - - public void toggleLed() { - mListofInstructions.add(new byte[]{TOGGLE_LED_COMMAND}); - } - - public String getDeviceName() { - return mMyName; - } - - public int getAccelRange() { - return mAccelRange; - } - - public int getMagRange() { - return mMagGain; - } - - public int getGyroRange() { - return mGyroRange; - } - - public int getGSRRange() { - return mGSRRange; - } - - public boolean getInitialized() { - return mInitialized; - } - - public double getPacketReceptionRate() { - return mPacketReceptionRate; - } - - public int getPMux() { - if ((mConfigByte0 & (byte) 64) != 0) { - //then set ConfigByte0 at bit position 7 - return 1; - } else { - return 0; - } - } - - public int get5VReg() { - if ((mConfigByte0 & (byte) 128) != 0) { - //then set ConfigByte0 at bit position 7 - return 1; - } else { - return 0; - } - } - - public int getCurrentLEDStatus() { - return mCurrentLEDStatus; - } - - public double getFirmwareVersion() { - return mFWVersion; - } - - public void setDeviceName(String deviceName) { - // TODO Auto-generated method stub - mMyName = deviceName; - } - - /** - * Set the battery voltage limit, when the Shimmer device goes below the limit while streaming the LED on the Shimmer device will turn Yellow, in order to use battery voltage monitoring the Battery has to be enabled. See writeenabledsensors. - * - * @param limit - */ - public void setBattLimitWarning(double limit) { - mLowBattLimit = limit; - } - - public double getBattLimitWarning() { - return mLowBattLimit; - } - - public int getShimmerVersion() { - return mShimmerVersion; - } - - public boolean isUsingDefaultAccelParam() { - return mDefaultCalibrationParametersAccel; - } - - public boolean isUsingDefaultGyroParam() { - return mDefaultCalibrationParametersGyro; - } - - public boolean isUsingDefaultMagParam() { - return mDefaultCalibrationParametersMag; - } - - public boolean isUsingDefaultECGParam() { - return mDefaultCalibrationParametersECG; - } - - public boolean isUsingDefaultEMGParam() { - return mDefaultCalibrationParametersEMG; - } - - public void resetCalibratedTimeStamp() { - mLastReceivedCalibratedTimeStamp = -1; - mFirstTimeCalTime = true; - mCurrentTimeStampCycle = 0; - } - - public void enable3DOrientation(boolean enable) { - //enable the sensors if they have not been enabled - mOrientationEnabled = enable; - } - - /** - * This enables the low power mag option. When not enabled the sampling rate of the mag is set to the closest value to the actual sampling rate that it can achieve. In low power mode it defaults to 10Hz - * - * @param enable - */ - public void enableLowPowerMag(boolean enable) { - mLowPowerMag = enable; - if (!mLowPowerMag) { - if (mSamplingRate >= 50) { - writeMagSamplingRate(6); - } else if (mSamplingRate >= 20) { - writeMagSamplingRate(5); - } else if (mSamplingRate >= 10) { - writeMagSamplingRate(4); - } else { - writeMagSamplingRate(3); - } - } else { - writeMagSamplingRate(4); - } - } - - public boolean isLowPowerMagEnabled() { - return mLowPowerMag; - } - - - /** - * @param enable this enables the calibration of the gyroscope while streaming - * @param bufferSize sets the buffersize of the window used to determine the new calibration parameters, see implementation for more details - * @param threshold sets the threshold of when to use the incoming data to recalibrate gyroscope offset, this is in degrees, and the default value is 1.2 - */ - public void enableOnTheFlyGyroCal(boolean enable, int bufferSize, double threshold) { - if (enable) { - mGyroOVCalThreshold = threshold; - mGyroX = new DescriptiveStatistics(bufferSize); - mGyroY = new DescriptiveStatistics(bufferSize); - mGyroZ = new DescriptiveStatistics(bufferSize); - mGyroXRaw = new DescriptiveStatistics(bufferSize); - mGyroYRaw = new DescriptiveStatistics(bufferSize); - mGyroZRaw = new DescriptiveStatistics(bufferSize); - } - } - - public boolean isGyroOnTheFlyCalEnabled() { - return mEnableOntheFlyGyroOVCal; - } - - public boolean is3DOrientatioEnabled() { - return mOrientationEnabled; - } - - /** - * @param enabledSensors this bitmap is only applicable for the instrument driver and does not correspond with the values in the firmware - * @return enabledSensorsFirmware returns the bitmap for the firmware - * The reason for this is hardware and firmware change may eventually need a different sensor bitmap, to keep the ID forward compatible, this function is used. The ID has its own seperate sensor bitmap. - */ - private int generateSensorBitmapForHardwareControl(int enabledSensors) { - int hardwareSensorBitmap = 0; - - //check if the batt volt is enabled (this is only applicable for Shimmer_2R - if (mShimmerVersion == SHIMMER_2R || mShimmerVersion == SHIMMER_2) { - if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { - enabledSensors = enabledSensors & 0xFFFF; - enabledSensors = enabledSensors | SENSOR_EXP_BOARD_A0 | SENSOR_EXP_BOARD_A7; - } - hardwareSensorBitmap = enabledSensors; - } else if (mShimmerVersion == Shimmer.SHIMMER_3) { - if (((enabledSensors & 0xFF) & SENSOR_ACCEL) > 0) { - //Accel range check shold be done here - if (mAccelSmartSetting == ACCEL_SMART_MODE) { - if (mAccelRange == 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL_S3; - if ((hardwareSensorBitmap & SENSOR_DACCEL) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap - SENSOR_DACCEL; - } - } else { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3; - if ((hardwareSensorBitmap & SENSOR_ACCEL) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap - SENSOR_ACCEL; - } - } - } else { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL_S3; - } - } - if ((enabledSensors & SENSOR_DACCEL) > 0 && mAccelSmartSetting != ACCEL_SMART_MODE) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3; - } - if ((enabledSensors & SENSOR_DACCEL) > 0 && mAccelSmartSetting == ACCEL_SMART_MODE) { - if (mAccelRange == 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL_S3; - } else { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL_S3; - } - } - if (((enabledSensors & 0xFF) & SENSOR_GYRO) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO_S3; - } - if (((enabledSensors & 0xFF) & SENSOR_MAG) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_MAG_S3; - } - if ((enabledSensors & SENSOR_BATT) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_VBATT_S3; - } - if ((enabledSensors & SENSOR_EXT_ADC_A7) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_EXT_A7; - } - if ((enabledSensors & SENSOR_EXT_ADC_A6) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_EXT_A6; - } - if ((enabledSensors & SENSOR_EXT_ADC_A15) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_EXT_A15; - } - if ((enabledSensors & SENSOR_INT_ADC_A1) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A1; - } - if ((enabledSensors & SENSOR_INT_ADC_A12) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A12; - } - if ((enabledSensors & SENSOR_INT_ADC_A13) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A13; - } - if ((enabledSensors & SENSOR_INT_ADC_A14) > 0) { - hardwareSensorBitmap = hardwareSensorBitmap | Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A14; - } - } else { - hardwareSensorBitmap = enabledSensors; - } - - return hardwareSensorBitmap; - } - - private void updateEnabledSensorsFromChannels(byte[] channels) { - // set the sensors value - // crude way of getting this value, but allows for more customised firmware - // to still work with this application - // e.g. if any axis of the accelerometer is being transmitted, then it will - // recognise that the accelerometer is being sampled - int enabledSensors = 0; - for (int i = 0; i < channels.length; i++) { - if (mShimmerVersion == SHIMMER_3) { - if (channels[i] == Configuration.Shimmer3.Channel.XAAccel || channels[i] == Configuration.Shimmer3.Channel.YAAccel || channels[i] == Configuration.Shimmer3.Channel.ZAAccel) { - enabledSensors = enabledSensors | Shimmer.SENSOR_ACCEL; - } - if (channels[i] == Configuration.Shimmer3.Channel.XDAccel || channels[i] == Configuration.Shimmer3.Channel.YDAccel || channels[i] == Configuration.Shimmer3.Channel.ZDAccel) { - if (mAccelSmartSetting == ACCEL_DUAL_MODE || mAccelSmartSetting == ACCEL_DUAL_SMART_MODE) { - enabledSensors = enabledSensors | Shimmer.SENSOR_DACCEL; - } - if (mAccelSmartSetting == ACCEL_SMART_MODE) { - enabledSensors = enabledSensors | Shimmer.SENSOR_ACCEL; - } - } - if (channels[i] == Configuration.Shimmer3.Channel.XGyro || channels[i] == Configuration.Shimmer3.Channel.YGyro || channels[i] == Configuration.Shimmer3.Channel.ZGyro) { - enabledSensors = enabledSensors | Shimmer.SENSOR_GYRO; - } - if (channels[i] == Configuration.Shimmer3.Channel.XMag || channels[i] == Configuration.Shimmer3.Channel.YMag || channels[i] == Configuration.Shimmer3.Channel.ZMag) { - enabledSensors = enabledSensors | Shimmer.SENSOR_MAG; - } - if (channels[i] == Configuration.Shimmer3.Channel.VBatt) { - enabledSensors = enabledSensors | Shimmer.SENSOR_BATT; - } - if (channels[i] == Configuration.Shimmer3.Channel.ExtAdc7) { - enabledSensors = enabledSensors | Shimmer.SENSOR_EXT_ADC_A7; - } - if (channels[i] == Configuration.Shimmer3.Channel.ExtAdc6) { - enabledSensors = enabledSensors | Shimmer.SENSOR_EXT_ADC_A6; - } - if (channels[i] == Configuration.Shimmer3.Channel.ExtAdc15) { - enabledSensors = enabledSensors | Shimmer.SENSOR_EXT_ADC_A15; - } - if (channels[i] == Configuration.Shimmer3.Channel.IntAdc1) { - enabledSensors = enabledSensors | Shimmer.SENSOR_INT_ADC_A1; - } - if (channels[i] == Configuration.Shimmer3.Channel.IntAdc12) { - enabledSensors = enabledSensors | Shimmer.SENSOR_INT_ADC_A12; - } - if (channels[i] == Configuration.Shimmer3.Channel.IntAdc13) { - enabledSensors = enabledSensors | Shimmer.SENSOR_INT_ADC_A13; - } - if (channels[i] == Configuration.Shimmer3.Channel.IntAdc14) { - enabledSensors = enabledSensors | Shimmer.SENSOR_INT_ADC_A14; - } - - } else if (mShimmerVersion == SHIMMER_2R) { - if (channels[i] == Configuration.Shimmer2.Channel.XAccel || channels[i] == Configuration.Shimmer2.Channel.YAccel || channels[i] == Configuration.Shimmer2.Channel.ZAccel) { - enabledSensors = enabledSensors | Shimmer.SENSOR_ACCEL; - } - if (channels[i] == Configuration.Shimmer2.Channel.XGyro || channels[i] == Configuration.Shimmer2.Channel.YGyro || channels[i] == Configuration.Shimmer2.Channel.ZGyro) { - enabledSensors = enabledSensors | Shimmer.SENSOR_GYRO; - } - if (channels[i] == Configuration.Shimmer2.Channel.XMag || channels[i] == Configuration.Shimmer2.Channel.XMag || channels[i] == Configuration.Shimmer2.Channel.XMag) { - enabledSensors = enabledSensors | Shimmer.SENSOR_MAG; - } - if ((channels[i] == Configuration.Shimmer2.Channel.EcgLaLl) || (channels[i] == Configuration.Shimmer2.Channel.EcgRaLl)) { - enabledSensors = enabledSensors | Shimmer.SENSOR_ECG; - } else if (channels[i] == Configuration.Shimmer2.Channel.Emg) { - enabledSensors = enabledSensors | Shimmer.SENSOR_EMG; - } else if (channels[i] == Configuration.Shimmer2.Channel.AnExA0 && getPMux() == 0) { - enabledSensors = enabledSensors | Shimmer.SENSOR_EXP_BOARD_A0; - } else if (channels[i] == Configuration.Shimmer2.Channel.AnExA7 && getPMux() == 0) { - enabledSensors = enabledSensors | Shimmer.SENSOR_EXP_BOARD_A7; - } else if ((channels[i] == Configuration.Shimmer2.Channel.StrainHigh) || (channels[i] == Configuration.Shimmer2.Channel.StrainLow)) { - enabledSensors = enabledSensors | Shimmer.SENSOR_STRAIN; - } else if ((channels[i] == Configuration.Shimmer2.Channel.GsrRaw) || (channels[i] == Configuration.Shimmer2.Channel.GsrRes)) { - enabledSensors = enabledSensors | Shimmer.SENSOR_GSR; - } else if (channels[i] == Configuration.Shimmer2.Channel.HeartRate) { - enabledSensors = enabledSensors | Shimmer.SENSOR_HEART; - } else if (channels[i] == Configuration.Shimmer2.Channel.AnExA0 && getPMux() == 1) { - enabledSensors = enabledSensors | Shimmer.SENSOR_BATT; - } else if (channels[i] == Configuration.Shimmer2.Channel.AnExA7 && getPMux() == 1) { - enabledSensors = enabledSensors | Shimmer.SENSOR_BATT; - } - - } - - - } - mEnabledSensors = enabledSensors; - } - - /** - * @param enabledSensors This takes in the current list of enabled sensors - * @param sensorToCheck This takes in a single sensor which is to be enabled - * @return enabledSensors This returns the new set of enabled sensors, where any sensors which conflicts with sensorToCheck is disabled on the bitmap, so sensorToCheck can be accomodated (e.g. for Shimmer2 using ECG will disable EMG,GSR,..basically any daughter board) - */ - public int sensorConflictCheckandCorrection(int enabledSensors, int sensorToCheck) { - - if (mShimmerVersion == Shimmer.SHIMMER_2R || mShimmerVersion == Shimmer.SHIMMER_2) { - if ((sensorToCheck & Shimmer.SENSOR_GYRO) > 0 || (sensorToCheck & Shimmer.SENSOR_MAG) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_ECG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EMG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GSR); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_STRAIN); - } else if ((sensorToCheck & Shimmer.SENSOR_STRAIN) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_ECG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EMG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GSR); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GYRO); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_MAG); - } else if ((sensorToCheck & Shimmer.SENSOR_GSR) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_ECG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EMG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_STRAIN); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GYRO); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_MAG); - } else if ((sensorToCheck & Shimmer.SENSOR_ECG) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GSR); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EMG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_STRAIN); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GYRO); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_MAG); - } else if ((sensorToCheck & Shimmer.SENSOR_EMG) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GSR); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_ECG); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_STRAIN); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_GYRO); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_MAG); - } else if ((sensorToCheck & Shimmer.SENSOR_HEART) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EXP_BOARD_A0); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EXP_BOARD_A7); - } else if ((sensorToCheck & Shimmer.SENSOR_EXP_BOARD_A0) > 0 || (sensorToCheck & Shimmer.SENSOR_EXP_BOARD_A7) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_HEART); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_BATT); - } else if ((sensorToCheck & Shimmer.SENSOR_BATT) > 0) { - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EXP_BOARD_A0); - enabledSensors = disableBit(enabledSensors, Shimmer.SENSOR_EXP_BOARD_A7); - } - } - enabledSensors = enabledSensors ^ sensorToCheck; - return enabledSensors; - } - - private int disableBit(int number, int disablebitvalue) { - if ((number & disablebitvalue) > 0) { - number = number ^ disablebitvalue; - } - return number; - } - - - public String[] getListofSignals() { - List listofSignals = new ArrayList(); - String[] enabledSignals; - - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && (mAccelSmartSetting == ACCEL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_SMART_MODE)) { - listofSignals.add("Accelerometer X"); - listofSignals.add("Accelerometer Y"); - listofSignals.add("Accelerometer Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0) { - listofSignals.add("Gyroscope X"); - listofSignals.add("Gyroscope Y"); - listofSignals.add("Gyroscope Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0) { - listofSignals.add("Magnetometer X"); - listofSignals.add("Magnetometer Y"); - listofSignals.add("Magnetometer Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GSR) > 0) { - listofSignals.add("GSR"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ECG) > 0) { - listofSignals.add("ECG RA-LL"); - listofSignals.add("ECG LA-LL"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EMG) > 0) { - listofSignals.add("EMG"); - } - if (((mEnabledSensors & 0xFF00) & Shimmer.SENSOR_STRAIN) > 0) { - listofSignals.add("Strain Gauge High"); - listofSignals.add("Strain Gauge Low"); - } - if (((mEnabledSensors & 0xFF00) & Shimmer.SENSOR_HEART) > 0) { - listofSignals.add("Heart Rate"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXP_BOARD_A0) > 0) { - listofSignals.add("ExpBoard A0"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXP_BOARD_A7) > 0) { - listofSignals.add("ExpBoard A7"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0 && mOrientationEnabled) { - listofSignals.add("Axis Angle A"); - listofSignals.add("Axis Angle X"); - listofSignals.add("Axis Angle Y"); - listofSignals.add("Axis Angle Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0 && mOrientationEnabled) { - listofSignals.add("Quartenion 0"); - listofSignals.add("Quartenion 1"); - listofSignals.add("Quartenion 2"); - listofSignals.add("Quartenion 3"); - } - - - enabledSignals = listofSignals.toArray(new String[listofSignals.size()]); - return enabledSignals; - } - - - public List getListofEnabledSensors() { - List listofSensors = new ArrayList(); - - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0) { - listofSensors.add("Accelerometer"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0) { - listofSensors.add("Gyroscope"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0) { - listofSensors.add("Magnetometer"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GSR) > 0) { - listofSensors.add("GSR"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ECG) > 0) { - listofSensors.add("ECG"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EMG) > 0) { - listofSensors.add("EMG"); - } - if (((mEnabledSensors & 0xFF00) & Shimmer.SENSOR_STRAIN) > 0) { - listofSensors.add("Strain Gauge"); - } - if (((mEnabledSensors & 0xFF00) & Shimmer.SENSOR_HEART) > 0) { - listofSensors.add("Heart Rate"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXP_BOARD_A0) > 0 && (mEnabledSensors & Shimmer.SENSOR_BATT) == 0 && mShimmerVersion != Shimmer.SHIMMER_3) { - listofSensors.add("ExpBoard A0"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXP_BOARD_A7) > 0 && (mEnabledSensors & Shimmer.SENSOR_BATT) == 0 && mShimmerVersion != Shimmer.SHIMMER_3) { - listofSensors.add("ExpBoard A7"); - } - if ((mEnabledSensors & Shimmer.SENSOR_BATT) > 0) { - listofSensors.add("Battery Voltage"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXT_ADC_A7) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("External ADC A7"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXT_ADC_A6) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("External ADC A6"); - } - if (((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_EXT_ADC_A15) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("External ADC A15"); - } - if (((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_INT_ADC_A1) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("Internal ADC A1"); - } - if (((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_INT_ADC_A12) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("Internal ADC A12"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_INT_ADC_A13) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("Internal ADC A13"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_INT_ADC_A14) > 0 && mShimmerVersion == Shimmer.SHIMMER_3) { - listofSensors.add("Internal ADC A14"); - } - - return listofSensors; - } - - public String[] getListofSupportedSensors() { - String[] sensorNames = null; - if (mShimmerVersion == Shimmer.SHIMMER_2R || mShimmerVersion == Shimmer.SHIMMER_2) { - sensorNames = Configuration.Shimmer2.ListofCompatibleSensors; - } else if (mShimmerVersion == Shimmer.SHIMMER_3) { - if (mAccelSmartSetting != ACCEL_SMART_MODE) { - sensorNames = Configuration.Shimmer3.ListofCompatibleSensorsAccelDualMode; - } else { - sensorNames = Configuration.Shimmer3.ListofCompatibleSensors; - } - } - return sensorNames; - } - - public static String[] getListofSupportedSensors(int shimmerVersion, int accelSmartSetting) { - String[] sensorNames = null; - if (shimmerVersion == Shimmer.SHIMMER_2R || shimmerVersion == Shimmer.SHIMMER_2) { - sensorNames = Configuration.Shimmer2.ListofCompatibleSensors; - } else if (shimmerVersion == Shimmer.SHIMMER_3) { - if (accelSmartSetting != ACCEL_SMART_MODE) { - sensorNames = Configuration.Shimmer3.ListofCompatibleSensorsAccelDualMode; - } else { - sensorNames = Configuration.Shimmer3.ListofCompatibleSensors; - } - } - return sensorNames; - } - - public boolean isLowPowerAccelEnabled() { - // TODO Auto-generated method stub - return mLowPowerAccel; - } - - public boolean isLowPowerGyroEnabled() { - // TODO Auto-generated method stub - return mLowPowerGyro; - } - - public int getLowPowerAccelEnabled() { - // TODO Auto-generated method stub - if (mLowPowerAccel) - return 1; - else - return 0; - } - - public int getLowPowerGyroEnabled() { - // TODO Auto-generated method stub - if (mLowPowerGyro) - return 1; - else - return 0; - } - - public int getLowPowerMagEnabled() { - // TODO Auto-generated method stub - if (mLowPowerMag) - return 1; - else - return 0; - } - - - /** - * Only should be configured by users who are familiar with the Instrument Driver and the hardware configuration of Shimmer3, for those with less experience please use ACCEL_SMART_MODE. Current version does not support 2g range for the Digital Accelerometer. - * - * @param setting the choise of settings are ACCEL_SMART_MODE which picks the best accelerometer depending on the accelerometer range selected; ACCEL_DUAL_MODE which outputs 'Wide Range Accelerometer X' and 'Low Noise Accelerometer X' - * ; ACCEL_DUAL_SMART_MODE which outputs the best accelerometer depending on the accelerometer range selected (as e.g. 'Accelerometer X') while also outputting both accelerometer data as (e.g 'Wide Range Accelerometer'), this is to keep backward compatibility with applications which rely on 'Accelerometer X' signal names - */ - public void setAccelerometerSpecialMode(int setting) { - mAccelSmartSetting = setting; - generateBiMapSensorIDtoSensorName(); - } - - public int getAccelerometerSpecialMode() { - return mAccelSmartSetting; - } - - - /** - * Should only be used when Shimmer is Connected and Initialized - */ - private void generateBiMapSensorIDtoSensorName() { - if (mShimmerVersion != -1) { - if (mShimmerVersion != SHIMMER_2R) { - final Map tempSensorBMtoName = new HashMap(); - tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); - tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); - tempSensorBMtoName.put(Integer.toString(SENSOR_STRAIN), "Strain Gauge"); - tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); - tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); - if (mAccelSmartSetting == ACCEL_SMART_MODE) { - tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); - mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } else if (mAccelSmartSetting == ACCEL_DUAL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_MODE) { - tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Low Noise Accelerometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_DACCEL), "Wide Range Accelerometer"); - } - mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } else { - final Map tempSensorBMtoName = new HashMap(); - tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); - tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); - tempSensorBMtoName.put(Integer.toString(SENSOR_STRAIN), "Strain Gauge"); - tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); - tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); - mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } - - } - } - - /** - * Should only be used when Shimmer is Connected and Initialized - */ - public static BiMap generateBiMapSensorIDtoSensorName(int shimmerVersion, int mAccelSmartSetting) { - BiMap sensorBitmaptoName = null; - if (shimmerVersion != SHIMMER_2R) { - final Map tempSensorBMtoName = new HashMap(); - tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); - tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); - tempSensorBMtoName.put(Integer.toString(SENSOR_STRAIN), "Strain Gauge"); - tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); - tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); - if (mAccelSmartSetting == ACCEL_SMART_MODE) { - tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); - sensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } else if (mAccelSmartSetting == ACCEL_DUAL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_MODE) { - tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Low Noise Accelerometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_DACCEL), "Wide Range Accelerometer"); - } - sensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } else { - final Map tempSensorBMtoName = new HashMap(); - tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); - tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); - tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); - tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); - tempSensorBMtoName.put(Integer.toString(SENSOR_STRAIN), "Strain Gauge"); - tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); - tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); - tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); - tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); - sensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); - } - return sensorBitmaptoName; - } - - - public String[] getListofEnabledSensorSignals() { - List listofSignals = new ArrayList(); - String[] enabledSignals; - if (mShimmerVersion != Shimmer.SHIMMER_3) { - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0) { - listofSignals.add("Accelerometer X"); - listofSignals.add("Accelerometer Y"); - listofSignals.add("Accelerometer Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0) { - listofSignals.add("Gyroscope X"); - listofSignals.add("Gyroscope Y"); - listofSignals.add("Gyroscope Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0) { - listofSignals.add("Magnetometer X"); - listofSignals.add("Magnetometer Y"); - listofSignals.add("Magnetometer Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GSR) > 0) { - listofSignals.add("GSR"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ECG) > 0) { - listofSignals.add("ECG RA-LL"); - listofSignals.add("ECG LA-LL"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EMG) > 0) { - listofSignals.add("EMG"); - } - if (((mEnabledSensors & 0xFF00) & Shimmer.SENSOR_STRAIN) > 0) { - listofSignals.add("Strain Gauge High"); - listofSignals.add("Strain Gauge Low"); - } - if (((mEnabledSensors & 0xFF00) & Shimmer.SENSOR_HEART) > 0) { - listofSignals.add("Heart Rate"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXP_BOARD_A0) > 0) { - listofSignals.add("ExpBoard A0"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_EXP_BOARD_A7) > 0) { - listofSignals.add("ExpBoard A7"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0 && mOrientationEnabled) { - listofSignals.add("Axis Angle A"); - listofSignals.add("Axis Angle X"); - listofSignals.add("Axis Angle Y"); - listofSignals.add("Axis Angle Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0 && mOrientationEnabled) { - listofSignals.add("Quartenion 0"); - listofSignals.add("Quartenion 1"); - listofSignals.add("Quartenion 2"); - listofSignals.add("Quartenion 3"); - } - } else { - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && (mAccelSmartSetting == ACCEL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_SMART_MODE)) { - listofSignals.add("Accelerometer X"); - listofSignals.add("Accelerometer Y"); - listofSignals.add("Accelerometer Z"); - } else if (((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_DACCEL) > 0 && (mAccelSmartSetting == ACCEL_SMART_MODE || mAccelSmartSetting == ACCEL_DUAL_SMART_MODE)) { - listofSignals.add("Accelerometer X"); - listofSignals.add("Accelerometer Y"); - listofSignals.add("Accelerometer Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 && (mAccelSmartSetting != ACCEL_SMART_MODE)) { - listofSignals.add("Low Noise Accelerometer X"); - listofSignals.add("Low Noise Accelerometer Y"); - listofSignals.add("Low Noise Accelerometer Z"); - } - if (((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_DACCEL) > 0 && (mAccelSmartSetting != ACCEL_SMART_MODE)) { - listofSignals.add("Wide Range Accelerometer X"); - listofSignals.add("Wide Range Accelerometer Y"); - listofSignals.add("Wide Range Accelerometer Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0) { - listofSignals.add("Gyroscope X"); - listofSignals.add("Gyroscope Y"); - listofSignals.add("Gyroscope Z"); - } - if (((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0) { - listofSignals.add("Magnetometer X"); - listofSignals.add("Magnetometer Y"); - listofSignals.add("Magnetometer Z"); - } - if (((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_BATT) > 0) { - listofSignals.add("VSenseBatt"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_EXT_ADC_A15) > 0) { - listofSignals.add("External ADC A15"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_EXT_ADC_A7) > 0) { - listofSignals.add("External ADC A7"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_EXT_ADC_A6) > 0) { - listofSignals.add("External ADC A6"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_INT_ADC_A1) > 0) { - listofSignals.add("Internal ADC A1"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_INT_ADC_A12) > 0) { - listofSignals.add("Internal ADC A12"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_INT_ADC_A13) > 0) { - listofSignals.add("Internal ADC A13"); - } - if (((mEnabledSensors & 0xFFFFFF) & Shimmer.SENSOR_INT_ADC_A14) > 0) { - listofSignals.add("Internal ADC A14"); - } - if ((((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 || ((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_DACCEL) > 0) && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0 && mOrientationEnabled) { - listofSignals.add("Axis Angle A"); - listofSignals.add("Axis Angle X"); - listofSignals.add("Axis Angle Y"); - listofSignals.add("Axis Angle Z"); - } - if ((((mEnabledSensors & 0xFF) & Shimmer.SENSOR_ACCEL) > 0 || ((mEnabledSensors & 0xFFFF) & Shimmer.SENSOR_DACCEL) > 0) && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF) & Shimmer.SENSOR_MAG) > 0 && mOrientationEnabled) { - listofSignals.add("Quartenion 0"); - listofSignals.add("Quartenion 1"); - listofSignals.add("Quartenion 2"); - listofSignals.add("Quartenion 3"); - } - } - enabledSignals = listofSignals.toArray(new String[listofSignals.size()]); - return enabledSignals; - } - - -} \ No newline at end of file diff --git a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/tools/Logging.java b/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/tools/Logging.java deleted file mode 100644 index 8e27f6d2..00000000 --- a/SensorLib/sls-shimmer/src/main/java/com.shimmerresearch/tools/Logging.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.shimmerresearch.tools; - -import android.os.Environment; -import android.util.Log; - -import com.google.common.collect.Multimap; -import com.shimmerresearch.driver.FormatCluster; -import com.shimmerresearch.driver.ObjectCluster; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Collection; -import java.util.Iterator; - -public class Logging { - boolean mFirstWrite = true; - String[] mSensorNames; - String[] mSensorFormats; - String[] mSensorUnits; - String mFileName = ""; - BufferedWriter writer = null; - File outputFile; - String mDelimiter = ","; //default is comma - - /** - * @param myName is the file name which will be used - */ - public Logging(String myName) { - mFileName = myName; - File root = Environment.getExternalStorageDirectory(); - Log.d("AbsolutePath", root.getAbsolutePath()); - outputFile = new File(root, mFileName + ".dat"); - } - - public Logging(String myName, String delimiter) { - mFileName = myName; - mDelimiter = delimiter; - File root = Environment.getExternalStorageDirectory(); - Log.d("AbsolutePath", root.getAbsolutePath()); - outputFile = new File(root, mFileName + ".dat"); - } - - /** - * @param myName - * @param delimiter - * @param folderName will create a new folder if it does not exist - */ - public Logging(String myName, String delimiter, String folderName) { - mFileName = myName; - mDelimiter = delimiter; - - File root = new File(Environment.getExternalStorageDirectory() + "/" + folderName); - - if (!root.exists()) { - if (root.mkdir()) ; //directory is created; - } - outputFile = new File(root, mFileName + ".dat"); - } - - - /** - * This function takes an object cluster and logs all the data within it. User should note that the function will write over prior files with the same name. - * - * @param objectCluster data which will be written into the file - */ - public void logData(ObjectCluster objectCluster) { - ObjectCluster objectClusterLog = objectCluster; - try { - - - if (mFirstWrite == true) { - writer = new BufferedWriter(new FileWriter(outputFile, true)); - - //First retrieve all the unique keys from the objectClusterLog - Multimap m = objectClusterLog.mPropertyCluster; - - int size = m.size(); - System.out.print(size); - mSensorNames = new String[size]; - mSensorFormats = new String[size]; - mSensorUnits = new String[size]; - int i = 0; - int p = 0; - for (String key : m.keys()) { - //first check that there are no repeat entries - - if (compareStringArray(mSensorNames, key) == true) { - for (FormatCluster formatCluster : m.get(key)) { - mSensorFormats[p] = formatCluster.mFormat; - mSensorUnits[p] = formatCluster.mUnits; - //Log.d("Shimmer",key + " " + mSensorFormats[p] + " " + mSensorUnits[p]); - p++; - } - - } - - mSensorNames[i] = key; - i++; - } - - - // write header to a file - - writer = new BufferedWriter(new FileWriter(outputFile, false)); - - for (int k = 0; k < mSensorNames.length; k++) { - writer.write(objectClusterLog.mMyName); - writer.write(mDelimiter); - } - writer.newLine(); // notepad recognized new lines as \r\n - - for (int k = 0; k < mSensorNames.length; k++) { - writer.write(mSensorNames[k]); - writer.write(mDelimiter); - } - writer.newLine(); - - for (int k = 0; k < mSensorFormats.length; k++) { - writer.write(mSensorFormats[k]); - - writer.write(mDelimiter); - } - writer.newLine(); - - for (int k = 0; k < mSensorUnits.length; k++) { - if (mSensorUnits[k] == "u8") { - writer.write(""); - } else if (mSensorUnits[k] == "i8") { - writer.write(""); - } else if (mSensorUnits[k] == "u12") { - writer.write(""); - } else if (mSensorUnits[k] == "u16") { - writer.write(""); - } else if (mSensorUnits[k] == "i16") { - writer.write(""); - } else if (mSensorUnits[k] == "no units") { - writer.write(""); - } else { - writer.write(mSensorUnits[k]); - } - writer.write(mDelimiter); - } - writer.newLine(); - Log.d("Shimmer", "Data Written"); - mFirstWrite = false; - } - - //now print data - for (int r = 0; r < mSensorNames.length; r++) { - Collection dataFormats = objectClusterLog.mPropertyCluster.get(mSensorNames[r]); - FormatCluster formatCluster = (FormatCluster) returnFormatCluster(dataFormats, mSensorFormats[r], mSensorUnits[r]); // retrieve the calibrated data - Log.d("Shimmer", "Data : " + mSensorNames[r] + formatCluster.mData + " " + formatCluster.mUnits); - writer.write(Double.toString(formatCluster.mData)); - writer.write(mDelimiter); - } - writer.newLine(); - - - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - Log.d("Shimmer", "Error with bufferedwriter"); - } - } - - public void closeFile() { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - } - - public String getName() { - return mFileName; - } - - public String getAbsoluteName() { - return outputFile.getAbsolutePath(); - } - - private boolean compareStringArray(String[] stringArray, String string) { - boolean uniqueString = true; - int size = stringArray.length; - for (int i = 0; i < size; i++) { - if (stringArray[i] == string) { - uniqueString = false; - } - - } - return uniqueString; - } - - private FormatCluster returnFormatCluster(Collection collectionFormatCluster, String format, String units) { - Iterator iFormatCluster = collectionFormatCluster.iterator(); - FormatCluster formatCluster; - FormatCluster returnFormatCluster = null; - - while (iFormatCluster.hasNext()) { - formatCluster = (FormatCluster) iFormatCluster.next(); - if (formatCluster.mFormat == format && formatCluster.mUnits == units) { - returnFormatCluster = formatCluster; - } - } - return returnFormatCluster; - } - -} - - diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/algorithms/Filter.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/algorithms/Filter.java new file mode 100644 index 00000000..a971d650 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/algorithms/Filter.java @@ -0,0 +1,332 @@ +/*Rev 0.4 + * + + This is a BlackMan-Windowed-Sinc Filter. Algorithm for calculating + filter coefficients from "The Scientist and Engineer's Guide to Digital Signal Processing", + copyright ©1997-1998 by Steven W. Smith. + For more information visit the book's website at: www.DSPguide.com. + + * Copyright (c) 2010 - 2014, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Alejandro Saez + * + * @date July, 2014 + * + * Changes since 0.3 + * - Updated to coefficients[(nTaps/2)] = coefficients[(nTaps/2)] +1; + * + * Changes since 0.2 + * - Changed the way the filtered data is calculated. + * - Changed the buffer implementation. Now is a LIFO queue. More efficient. + * - Possibility of filter either one data or an array of data + * + * + * Changes since 0.1 + * - Handle an error case - when array of data to filter (number of samples) is bigger than the array of data to filter from the previous iteration + * - Added resetBuffers() function +*/ +package com.shimmerresearch.algorithms; + +import java.util.Arrays; +import java.util.List; + +/** + * + This is a BlackMan-Windowed-Sinc Filter. Algorithm for calculating + filter coefficients from "The Scientist and Engineer's Guide to Digital Signal Processing", + copyright ©1997-1998 by Steven W. Smith. + For more information visit the book's website at: www.DSPguide.com. + * + */ + +public class Filter { + + public static int LOW_PASS = 0; + public static int HIGH_PASS = 1; + public static int BAND_PASS = 2; + public static int BAND_STOP = 3; + + // filter parameters + private int filterType; + private double samplingRate = Double.NaN; + private double[] cornerFrequency; + private int nTaps; + private double minCornerFrequency, maxCornerFrequency; + + // buffered data (for filtering streamed data) + private double[] bufferedX; + + // filter coefficients {h} + private double[] coefficients; + + // input parameters are invalid + private boolean validparameters = false; + + // default parameters + private double defaultSamplingRate = 512; + private double[] defaultCornerFrequency = { 0.5 }; + private int defaultNTaps = 200; + + public Filter() throws Exception{ + filterType=LOW_PASS; + + SetFilterParameters(LOW_PASS, defaultSamplingRate, defaultCornerFrequency, defaultNTaps); + } + + public Filter(int filterType) throws Exception{ + + this.filterType=filterType; + + SetFilterParameters(filterType, defaultSamplingRate, defaultCornerFrequency, defaultNTaps); + } + + public Filter(int filterType, double samplingRate, double[] cornerFrequency) throws Exception{ + + this.filterType=filterType; + + SetFilterParameters(filterType, samplingRate, cornerFrequency, defaultNTaps); + } + + public Filter(int filterType, double samplingRate, double[] cornerFrequency, int nTaps) throws Exception{ + + this.filterType=filterType; + + SetFilterParameters(filterType, samplingRate, cornerFrequency, nTaps); + } + + + public void SetFilterParameters(int LoHi, double samplingRate, double[] cornerFrequency, int nTaps) throws Exception{ + + //reset the buffers + this.bufferedX = null; + + if(cornerFrequency.length!=1){ + if(cornerFrequency[0] > cornerFrequency[1]){ + minCornerFrequency = cornerFrequency[1]; + maxCornerFrequency = cornerFrequency[0]; + } + else{ + minCornerFrequency = cornerFrequency[0]; + maxCornerFrequency = cornerFrequency[1]; + } + } + else + minCornerFrequency = maxCornerFrequency = cornerFrequency[0]; + + + if (maxCornerFrequency > samplingRate / 2) + { + this.validparameters = false; + throw new Exception("Error: cornerFrequency is greater than Nyquist frequency. Please choose valid parameters."); + } + else + { + if (nTaps % 2 != 0) + { + nTaps--; + } + + if (LoHi == LOW_PASS || LoHi == HIGH_PASS) // High pass or Low pass filter + { + this.samplingRate = samplingRate; + this.cornerFrequency = cornerFrequency; + this.nTaps = nTaps; + + double fc = (cornerFrequency[0] / samplingRate); + // calculate filter coefficients + coefficients = new double[nTaps]; + coefficients = calculateCoefficients(fc, LoHi, nTaps); + this.validparameters = true; + } + else if (LoHi == BAND_PASS || LoHi == BAND_STOP) + { + if (cornerFrequency.length != 2) + throw new Exception("Error. Bandpass or bandstop filter requires two corner frequencies to be specified"); + + this.samplingRate = samplingRate; + this.nTaps = nTaps; + + double fcHigh = maxCornerFrequency / samplingRate; + double fcLow = minCornerFrequency / samplingRate; + + // calculate filter coefficients + double[] coefficientHighPass = calculateCoefficients(fcHigh, HIGH_PASS, nTaps); + double[] coefficientLowPass = calculateCoefficients(fcLow, LOW_PASS, nTaps); + + coefficients = new double[coefficientHighPass.length]; + for(int i=0; i list){ + + double [] array = new double[list.size()]; + for(int i=0;i 0.0){ + norm = 1.0 / norm; + ax *= norm; + ay *= norm; + az *= norm; + } + else{ + + } + + // Normalise magnetometer measurement + norm = Math.sqrt(mx * mx + my * my + mz * mz); + if (norm > 0.0){ + norm = 1.0 / norm; + mx *= norm; + my *= norm; + mz *= norm; + } + else{ + + } + + + + hx = mx * q1q1 - (2 * q1 * my) * q4 + (2 * q1 * mz) * q3 + mx * q2q2 + (2.0 * q2) * my * q3 + (2.0 * q2) * mz * q4 - mx * q3q3 - mx * q4q4; + hy = (2 * q1 * mx) * q4 + my * q1q1 - (2 * q1 * mz) * q2 + (2 * q2 * mx) * q3 - my * q2q2 + my * q3q3 + (2.0 * q3) * mz * q4 - my * q4q4; + _2bx = Math.sqrt(hx * hx + hy * hy); + _2bz = -(2 * q1 * mx) * q3 + (2 * q1 * my) * q2 + mz * q1q1 + (2 * q2 * mx) * q4 - mz * q2q2 + (2.0 * q3) * my * q4 - mz * q3q3 + mz * q4q4; + _4bx = 2 * _2bx; + _4bz = 2 * _2bz; + + // Corrective step + s1 = -(2.0 * q3) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q2) * (2.0 * q1q2 + _2q3q4 - ay) - _2bz * q3 * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q4 + _2bz * q2) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q3 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); + s2 = (2.0 * q4) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q1) * (2.0 * q1q2 + _2q3q4 - ay) - 4.0 * q2 * (1.0 - 2.0 * q2q2 - 2.0 * q3q3 - az) + _2bz * q4 * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q3 + _2bz * q1) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q4 - _4bz * q2) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); + s3 = -(2.0 * q1) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q4) * (2.0 * q1q2 + _2q3q4 - ay) - 4.0 * q3 * (1.0 - 2.0 * q2q2 - 2.0 * q3q3 - az) + (-_4bx * q3 - _2bz * q1) * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (_2bx * q2 + _2bz * q4) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + (_2bx * q1 - _4bz * q3) * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); + s4 = (2.0 * q2) * (2.0 * q2q4 - _2q1q3 - ax) + (2.0 * q3) * (2.0 * q1q2 + _2q3q4 - ay) + (-_4bx * q4 + _2bz * q2) * (_2bx * (0.5 - q3q3 - q4q4) + _2bz * (q2q4 - q1q3) - mx) + (-_2bx * q1 + _2bz * q3) * (_2bx * (q2q3 - q1q4) + _2bz * (q1q2 + q3q4) - my) + _2bx * q2 * (_2bx * (q1q3 + q2q4) + _2bz * (0.5 - q2q2 - q3q3) - mz); + + norm = 1.0 / Math.sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s4 * s4); // normalise + s1 *= norm; + s2 *= norm; + s3 *= norm; + s4 *= norm; + + // Compute rate of change of quaternion + qDot1 = 0.5 * (-q2 * gx - q3 * gy - q4 * gz) - mBeta * s1; + qDot2 = 0.5 * (q1 * gx + q3 * gz - q4 * gy) - mBeta * s2; + qDot3 = 0.5 * (q1 * gy - q2 * gz + q4 * gx) - mBeta * s3; + qDot4 = 0.5 * (q1 * gz + q2 * gy - q3 * gx) - mBeta * s4; + + // Integrate to yield quaternion + q1 += qDot1 * mSamplingPeriod; + q2 += qDot2 * mSamplingPeriod; + q3 += qDot3 * mSamplingPeriod; + q4 += qDot4 * mSamplingPeriod; + norm = 1.0 / Math.sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4); // normalise quaternion + + q1 = q1 * norm; + q2 = q2 * norm; + q3 = q3 * norm; + q4 = q4 * norm; + + + return new Quaternion(q1,q2,q3,q4); + } + + + public class Quaternion{ + + public double q1, q2, q3, q4; + + public Quaternion(double q1, double q2, double q3, double q4) + { + this.q1 = q1; + this.q2 = q2; + this.q3 = q3; + this.q4 = q4; + } + } + + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/algorithms/GradDes3DOrientation6DoF.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/algorithms/GradDes3DOrientation6DoF.java new file mode 100644 index 00000000..8dd5c0ea --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/algorithms/GradDes3DOrientation6DoF.java @@ -0,0 +1,215 @@ +package com.shimmerresearch.algorithms; +/* Rev 0.1 + * + * Madgwick, Sebastian OH, Andrew JL Harrison, and Ravi Vaidyanathan. "Estimation of imu and marg orientation using a gradient descent algorithm." Rehabilitation Robotics (ICORR), 2011 IEEE International Conference on. IEEE, 2011. + * + * 3D orientation code taken from https://code.google.com/p/labview-quaternion-ahrs/ which is licensed under GNU_Lesser_GPL + * + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim + * @date October, 2013 + * + * + * + */ + + + +/* + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim + * @date October, 2013 + */ + +import javax.vecmath.AxisAngle4d; +import javax.vecmath.Matrix4d; +import javax.vecmath.Quat4d; +import javax.vecmath.Tuple3d; +import javax.vecmath.Vector3d; +import javax.vecmath.Vector3f; +import javax.vecmath.Vector4d; +import javax.vecmath.Vector4f; + +import com.shimmerresearch.algorithms.GradDes3DOrientation.Quaternion; + +public class GradDes3DOrientation6DoF { + + double mBeta = 1; + double mSamplingPeriod = 1; + double q0, q1, q2, q3; + public GradDes3DOrientation6DoF(double beta, double samplingPeriod, double q1, double q2, double q3, double q4) + { + mBeta = beta; + this.q0 = q1; + this.q1 = q2; + this.q2 = q3; + this.q3 = q4; + mSamplingPeriod = samplingPeriod; + } + + + + /** + * @param ax Accelerometer X in m/(sec^2) + * @param ay Accelerometer Y in m/(sec^2) + * @param az Accelerometer Z in m/(sec^2) + * @param gx Gyroscope X in rad/sec + * @param gy Gyroscope X in rad/sec + * @param gz Gyroscope X in rad/sec + * @return Calculated Quaternion value + */ + public Quaternion update(double ax,double ay,double az,double gx, double gy, double gz) + { + double norm; + double s0, s1, s2, s3; + double qDot1, qDot2, qDot3, qDot4; + double _2q0, _2q1, _2q2, _2q3, _4q0, _4q1, _4q2 ,_8q1, _8q2, q0q0, q1q1, q2q2, q3q3; + + // Rate of change of quaternion from gyroscope + qDot1 = 0.5f * (-q1 * gx - q2 * gy - q3 * gz); + qDot2 = 0.5f * (q0 * gx + q2 * gz - q3 * gy); + qDot3 = 0.5f * (q0 * gy - q1 * gz + q3 * gx); + qDot4 = 0.5f * (q0 * gz + q1 * gy - q2 * gx); + + // Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation) + if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { + + // Normalise accelerometer measurement + norm = Math.sqrt(ax * ax + ay * ay + az * az); + if (norm > 0.0){ + norm = 1.0 / norm; + ax *= norm; + ay *= norm; + az *= norm; + } + else{ + + } + + // Auxiliary variables to avoid repeated arithmetic + _2q0 = 2.0f * q0; + _2q1 = 2.0f * q1; + _2q2 = 2.0f * q2; + _2q3 = 2.0f * q3; + _4q0 = 4.0f * q0; + _4q1 = 4.0f * q1; + _4q2 = 4.0f * q2; + _8q1 = 8.0f * q1; + _8q2 = 8.0f * q2; + q0q0 = q0 * q0; + q1q1 = q1 * q1; + q2q2 = q2 * q2; + q3q3 = q3 * q3; + + // Gradient decent algorithm corrective step + s0 = _4q0 * q2q2 + _2q2 * ax + _4q0 * q1q1 - _2q1 * ay; + s1 = _4q1 * q3q3 - _2q3 * ax + 4.0f * q0q0 * q1 - _2q0 * ay - _4q1 + _8q1 * q1q1 + _8q1 * q2q2 + _4q1 * az; + s2 = 4.0f * q0q0 * q2 + _2q0 * ax + _4q2 * q3q3 - _2q3 * ay - _4q2 + _8q2 * q1q1 + _8q2 * q2q2 + _4q2 * az; + s3 = 4.0f * q1q1 * q3 - _2q1 * ax + 4.0f * q2q2 * q3 - _2q2 * ay; + + norm = 1.0 / Math.sqrt(s1 * s1 + s2 * s2 + s3 * s3 + s0 * s0); // normalise + s0 *= norm; + s1 *= norm; + s2 *= norm; + s3 *= norm; + + + // Apply feedback step + qDot1 -= mBeta * s0; + qDot2 -= mBeta * s1; + qDot3 -= mBeta * s2; + qDot4 -= mBeta * s3; + } + + + + // Integrate to yield quaternion + q0 += qDot1 * mSamplingPeriod; + q1 += qDot2 * mSamplingPeriod; + q2 += qDot3 * mSamplingPeriod; + q3 += qDot4 * mSamplingPeriod; + norm = 1.0 / Math.sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q0 * q0); // normalise quaternion + + q1 = q1 * norm; + q2 = q2 * norm; + q3 = q3 * norm; + q0 = q0 * norm; + + + return new Quaternion(q0,q1,q2,q3); + } + + + public class Quaternion{ + + public double q1, q2, q3, q4; + + public Quaternion(double q1, double q2, double q3, double q4) + { + this.q1 = q1; + this.q2 = q2; + this.q3 = q3; + this.q4 = q4; + } + } + + + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/android/Shimmer.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/android/Shimmer.java new file mode 100644 index 00000000..ef16ced5 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/android/Shimmer.java @@ -0,0 +1,1119 @@ +//Rev_1.7 +/* + * Copyright (c) 2010 - 2014, Shimmer Research, Ltd. + * All rights reserved + + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim, Ruaidhri Molloy + * @date October, 2013 + * + * Changes since 1.6 + * - cancel timers for log and stream upon disconnect + * + * Changes since 1.5.1 + * - move response time out to ShimmerBluetooth + * + * Changes since 1.5 (12 May 2014, RM first revision) + * - Addition of Strain Gauge for Shimmer3 + * + * Changes since beta 1.4 + * - updated lowbattindicator for Shimmer2r + * + * Changes since beta 1.3.1 (17 Oct 2013) + * - added get method for mPressureResolution + * - updated the smart accel mode, which was over complicating things, right now there are two modes, smart accel mode will include 'Accelerometer X'. 'Accelerometer X' is picked based on which accelerometer meets the defined range and has the lowest noise. For backward compatibility users are advised to use Smart Mode. Normal_Mode will not add 'Accelerometer X'. + * - fixed boolean indicator for gyro on the fly method + * - fixed getListofEnabledSensors method + * - fixed decimalformat which was returning commas for decimal points for certain regions/locale + * - fixed a bug when using max number of sensors on Shimmer3 + * - updated initialize2r method which was not reading the magrange + * - fixed a bug with the pressure sensor calibration parameters + * - rename NORMAL_MODE to ACCEL_NORMAL_MODE + * - added support for Shimmer3 GSR + * - minor fix to ACCEL_NORMAL_MODE + * - added rawdata and systemtimestamp to objectcluster + * - add option to disable the calibration of data, see function enableCalibration() + * - removed mgetdatainstructions, not used for anything + * - added support for saving and retrieving rawcalibrationparams, should only be used after connected to a device + * - updated various variables to protected so it can be inherited + * - switch logfile id to mClassName from "Shimmer" + * - fixed initialize Shimmer3, maggain and gyrorange being set wrongly + * - Shimmer3 GSR support + * - Updated the structure to allow future addons (.eg. ShimmerFile , ShimmerBTLE, Shimmer802_15_4) which will all inherit ShimmerObject, also will allow exporting the code to non andoid use, users will just have to remove Shimmer.java which has the Android related code + * - Support for internal exp power (Shimmer3) added + * + * Changes since beta 1.2 (14 Oct 2013) + * - added support read data for Shimmer3 pressure sensor + * - added support to set pressure resolution + * + * Changes since beta 1.1.3 (10 Oct 2013) + * - updated to work with Boilerplate and to fix a bug with version control as there is BTStream 0.1.0 and Boilerplate 0.1.0 + * - minor change to comments + * - fixed twos complement function + * + * Changes since beta 1.1.2 (1 Oct 2013) + * - mag gain command implemented for Shimmer2 + * + * Changes since beta 1.1.1 (17 July 2013) + * - + * - added support for dual accelerometer mode for Shimmer 3 + * - updated wide range accel from i12> to i16 and updated default calibration values + * + * Changes since beta 1.0.2 (17 July 2013) + * - started integration with Shimmer 3, major changes include the use of i16* now. This indicates array of bytes where MSB is on the far left/smallest index number of the array. + * - minor fix to the stop streaming command, causing it to block the inputstream, and not being able to clear the bytes from minstream + * - added default calibration parameters for Shimmer 3 + * - added functionality for internal and external adc + * - added new constructor to support setup device on connect (Shimmer 3) + * + * Changes since beta 1.0.1 (20 June 2013) + * - Fix the no response bug, through the use of the function dummyreadSamplingRate() + * - Updates to allow operation with Boilerplate + * - add get functions for lower power mag and gyro cal on the fly + * + * Changes since beta 1.0 (21 May 2013) + * - Added support for on the fly gyro offset calibration + * - Added quartenions + * - Convert to an instruction stack format, no longer supports Boilerplate + * + * Changes since beta 0.9 (1 January 2013) + * + * - Packet Reception Rate is now provided, whenever a packet loss detected a message is sent via handler, see MESSAGE_PACKET_LOSS_DETECTED + * - Changed Accel cal parameters + * - Added default cal parameters for the other accel ranges, if default accel range is being used, changing the accel range will change the defaults automatically as well + * - Revised the GSR calibration method, now uses a linear fit + * - Batt Voltage Monitoring + * - Sensor Conflict checks, have to wire the handler in order to see the msgs + * - Bug fix, timer wasnt triggering when waiting for response which was not received, causing the driver to get stuck in a loop + * - Added retrieve all,ecg & emg calibration parameters, only works with Boilerplate >= 1.0 + * - Rearranged the data reception section, to accommodate for in streaming ack detection + * - Added uncalibrated heart rate, which is a pulse now, with the value being the time difference between the last pulse and the current one + * - Updated the name of the formats, units and property names, so as to stay consistent with the rest of the instrument drivers + * - Low Battery Voltage warning at 3.4V where LED turns yellow + * - Added Packet Reception Rate monitoring + * - Added MESSAGE_NOT_SYNC for MSS support + * - Updated the initialization process, if a connection fails during the initialization process, disconnect is done immediately + * - Update Toggle LED + * - Switched to the use of createInsecureRfcommSocketToServiceRecord + * - ECG and EMG units have a * (mVolts*) as an indicator when default parameters are used + * - SR 30 support + * - Orientation + * - Support for low and high power Mag (high power == high sampling rate Mag) + * - Support for different mag range + * - Updated the execution model when transmitting commands, now uses a thread, and will improve Main UI thread latency + + * */ + +package com.shimmerresearch.android; + +import it.gerdavax.easybluetooth.BtSocket; +import it.gerdavax.easybluetooth.LocalDevice; +import it.gerdavax.easybluetooth.RemoteDevice; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Stack; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; + + + + + + + + +import com.shimmerresearch.algorithms.GradDes3DOrientation; +import com.shimmerresearch.bluetooth.ShimmerBluetooth; +import com.shimmerresearch.driver.Configuration; +import com.shimmerresearch.driver.ObjectCluster; +import com.shimmerresearch.driver.ShimmerMsg; +import com.shimmerresearch.driver.ShimmerObject; +import com.shimmerresearch.driver.Configuration.Shimmer3; +import com.shimmerresearch.driver.Configuration.Shimmer3.SensorBitmap; + + + + + + + + + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +//import java.io.FileOutputStream; + +public class Shimmer extends ShimmerBluetooth{ + //generic UUID for serial port protocol + private UUID mSPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + // Message types sent from the Shimmer Handler + public static final int MESSAGE_STATE_CHANGE = 1; + public static final int MESSAGE_READ = 2; + public static final int MESSAGE_WRITE = 3; + public static final int MESSAGE_ACK_RECEIVED = 4; + public static final int MESSAGE_DEVICE_NAME = 5; + public static final int MESSAGE_TOAST = 6; + public static final int MESSAGE_SAMPLING_RATE_RECEIVED = 7; + public static final int MESSAGE_INQUIRY_RESPONSE = 8; + public static final int MESSAGE_STOP_STREAMING_COMPLETE = 9; + public static final int MESSAGE_PACKET_LOSS_DETECTED = 11; + public static final int MESSAGE_NOT_SYNC = 12; + public static final int MESSAGE_LOG_AND_STREAM_STATUS_CHANGED = 13; + + // Key names received from the Shimmer Handler + public static final String TOAST = "toast"; + private final BluetoothAdapter mAdapter; + public final Handler mHandler; + + private ConnectThread mConnectThread; + private ConnectedThread mConnectedThread; + private boolean mDummy=false; + private LocalDevice localDevice; + //private InputStream mInputStream=null; + //private DataInputStream mInStream=null; + private DataInputStream mInStream; + //private BufferedInputStream mInStream=null; + private OutputStream mmOutStream=null; + + public static final int MSG_STATE_FULLY_INITIALIZED = 3; // This is the connected state, indicating the device has establish a connection + tx/rx commands and reponses (Initialized) + public static final int MSG_STATE_STREAMING = 4; + public static final int MSG_STATE_STOP_STREAMING = 5; + + protected String mClassName="Shimmer"; + + private int mBluetoothLib=0; // 0 = default lib, 1 = arduino lib + private BluetoothAdapter mBluetoothAdapter = null; + + + + + /** + * Constructor. Prepares a new Bluetooth session. + * @param context The UI Activity Context + * @param handler A Handler to send messages back to the UI Activity + * @param myName To allow the user to set a unique identifier for each Shimmer device + * @param continuousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. + */ + public Shimmer(Handler handler, String myName, Boolean continuousSync) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mState = STATE_NONE; + mHandler = handler; + mMyName=myName; + mContinousSync=continuousSync; + mSetupDevice=false; + } + + public Shimmer(Context context, Handler handler, String myName, Boolean continousSync) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mState = STATE_NONE; + mHandler = handler; + mMyName=myName; + mContinousSync=continousSync; + mSetupDevice=false; + } + + + /** + * Constructor. Prepares a new Bluetooth session. Additional fields allows the device to be set up immediately. + * @param context The UI Activity Context + * @param handler A Handler to send messages back to the UI Activity + * @param myName To allow the user to set a unique identifier for each Shimmer device + * @param samplingRate Defines the sampling rate + * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). + * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). + * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) + * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. + */ + public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, long setEnabledSensors, boolean continousSync) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mState = STATE_NONE; + mHandler = handler; + mShimmerSamplingRate = samplingRate; + mAccelRange = accelRange; + mGSRRange = gsrRange; + mSetEnabledSensors=setEnabledSensors; + mMyName = myName; + mSetupDevice = true; + mContinousSync = continousSync; + } + + /** + * Constructor. Prepares a new Bluetooth session. Additional fields allows the device to be set up immediately. + * @param context The UI Activity Context + * @param handler A Handler to send messages back to the UI Activity + * @param myName To allow the user to set a unique identifier for each Shimmer device + * @param samplingRate Defines the sampling rate + * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). + * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). + * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) + * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. + */ + public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, long setEnabledSensors, boolean continousSync, int magGain) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mState = STATE_NONE; + mHandler = handler; + mShimmerSamplingRate = samplingRate; + mAccelRange = accelRange; + mMagRange = magGain; + mGSRRange = gsrRange; + mSetEnabledSensors=setEnabledSensors; + mMyName = myName; + mSetupDevice = true; + mContinousSync = continousSync; + } + + + /** + * Constructor. Prepares a new Bluetooth session. Additional fields allows the device to be set up immediately. + * @param context The UI Activity Context + * @param handler A Handler to send messages back to the UI Activity + * @param myName To allow the user to set a unique identifier for each Shimmer device + * @param samplingRate Defines the sampling rate + * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). + * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). + * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) + * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. + */ + public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, long setEnabledSensors, boolean continousSync, boolean enableLowPowerAccel, boolean enableLowPowerGyro, boolean enableLowPowerMag, int gyroRange, int magRange) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mState = STATE_NONE; + mHandler = handler; + mShimmerSamplingRate = samplingRate; + mAccelRange = accelRange; + mGSRRange = gsrRange; + mSetEnabledSensors=setEnabledSensors; + mMyName = myName; + mSetupDevice = true; + mContinousSync = continousSync; + mLowPowerMag = enableLowPowerMag; + mLowPowerAccelWR = enableLowPowerAccel; + mLowPowerGyro = enableLowPowerGyro; + mGyroRange = gyroRange; + mMagRange = magRange; + } + + + /** + * Constructor. Prepares a new Bluetooth session. Additional fields allows the device to be set up immediately. + * @param context The UI Activity Context + * @param handler A Handler to send messages back to the UI Activity + * @param myName To allow the user to set a unique identifier for each Shimmer device + * @param samplingRate Defines the sampling rate + * @param accelRange Defines the Acceleration range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). + * @param gsrRange Numeric value defining the desired gsr range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). + * @param setEnabledSensors Defines the sensors to be enabled (e.g. 'Shimmer.SENSOR_ACCEL|Shimmer.SENSOR_GYRO' enables the Accelerometer and Gyroscope) + * @param continousSync A boolean value defining whether received packets should be checked continuously for the correct start and end of packet. + */ + public Shimmer(Context context, Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, long setEnabledSensors, boolean continousSync, boolean enableLowPowerAccel, boolean enableLowPowerGyro, boolean enableLowPowerMag, int gyroRange, int magRange,byte[] exg1,byte[] exg2) { + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mState = STATE_NONE; + mHandler = handler; + mShimmerSamplingRate = samplingRate; + mAccelRange = accelRange; + mGSRRange = gsrRange; + mSetEnabledSensors=setEnabledSensors; + mMyName = myName; + mSetupDevice = true; + mContinousSync = continousSync; + mLowPowerMag = enableLowPowerMag; + mLowPowerAccelWR = enableLowPowerAccel; + mLowPowerGyro = enableLowPowerGyro; + mGyroRange = gyroRange; + mMagRange = magRange; + mSetupEXG = true; + mEXG1RegisterArray = exg1; + mEXG2RegisterArray = exg2; + } + + + + /** + * Set the current state of the chat connection + * @param state An integer defining the current connection state + */ + protected synchronized void setState(int state) { + mState = state; + // Give the new state to the Handler so the UI Activity can update + mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, state, -1, new ObjectCluster(mMyName,getBluetoothAddress())).sendToTarget(); + } + + /** + * Return the current connection state. */ + public synchronized int getShimmerState() { + return mState; + } + + /** + * Start the ConnectThread to initiate a connection to a remote device. The purpose of having two libraries is because some Stock firmware do not implement the full Bluetooth Stack. In such cases use 'gerdavax'. If problems persist consider installing an aftermarket firmware, with a mature Bluetooth stack. + * @param address Bluetooth Address of Device to connect too + * @param bluetoothLibrary Supported libraries are 'default' and 'gerdavax' + */ + public synchronized void connect(final String address, String bluetoothLibrary) { + mIamAlive = false; + mListofInstructions.clear(); + mFirstTime=true; + if (bluetoothLibrary=="default"){ + mMyBluetoothAddress=address; + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); + + // Cancel any thread attempting to make a connection + if (mState == STATE_CONNECTING) { + if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} + } + // Cancel any thread currently running a connection + if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} + + // Start the thread to connect with the given device + mConnectThread = new ConnectThread(device); + mConnectThread.start(); + setState(STATE_CONNECTING); + } else if (bluetoothLibrary=="gerdavax"){ + mMyBluetoothAddress=address; + // Cancel any thread attempting to make a connection + if (mState == STATE_CONNECTING) { + if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} + } + // Cancel any thread currently running a connection + if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} + + if (address == null) return; + Log.d("ConnectionStatus","Get Local Device " + address); + + localDevice = LocalDevice.getInstance(); + RemoteDevice device = localDevice.getRemoteForAddr(address); + new ConnectThreadArduino(device).start(); + setState(STATE_CONNECTING); + /*localDevice.init(this, new ReadyListener() { + @Override + public synchronized void ready() { + + + //localDevice.destroy(); + + + } + });*/ + + + } + } + + /** + * Start the ConnectedThread to begin managing a Bluetooth connection + * @param socket The BluetoothSocket on which the connection was made + * @param device The BluetoothDevice that has been connected + */ + public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { + // Cancel the thread that completed the connection + if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} + // Cancel any thread currently running a connection + if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} + // Start the thread to manage the connection and perform transmissions + mConnectedThread = new ConnectedThread(socket); + mIOThread = new IOThread(); + mIOThread.start(); + mPThread = new ProcessingThread(); + mPThread.start(); + + mMyBluetoothAddress = device.getAddress(); + // Send the name of the connected device back to the UI Activity + Message msg = mHandler.obtainMessage(Shimmer.MESSAGE_DEVICE_NAME); + mHandler.sendMessage(msg); + setState(STATE_CONNECTED); + initialize(); + } + + /** + * Stop all threads + */ + public synchronized void stop() { + + if (mTimerToReadStatus!=null) { + mTimerToReadStatus.cancel(); + mTimerToReadStatus.purge(); + } + + if (mAliveTimer!=null){ + mAliveTimer.cancel(); + mAliveTimer.purge(); + mAliveTimer = null; + } + + if (mTimer!=null){ + mTimer.cancel(); + mTimer.purge(); + } + setState(STATE_NONE); + mStreaming = false; + mInitialized = false; + if (mIOThread != null) { + mIOThread.stop = true; + mIOThread = null; + mPThread.stop =true; + mPThread = null; + + } + if (mConnectThread != null) { + mConnectThread.cancel(); + mConnectThread = null; + } + if (mConnectedThread != null) { + mConnectedThread.cancel(); + mConnectedThread = null; + } + + } + + /** + * Write to the ConnectedThread in an unsynchronized manner + * @param out The bytes to write + * @see ConnectedThread write(byte[]) + */ + public void write(byte[] out) { + // Create temporary object + ConnectedThread r; + // Synchronize a copy of the ConnectedThread + synchronized (this) { + if (mState != STATE_CONNECTED) return; + r = mConnectedThread; + } + // Perform the write unsynchronized + r.write(out); + } + + /** + * Indicate that the connection attempt failed and notify the UI Activity. + */ + private void connectionFailed() { + setState(STATE_NONE); + mInitialized = false; + // Send a failure message back to the Activity + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Unable to connect device"); + msg.setData(bundle); + mHandler.sendMessage(msg); + } + + /** + * Indicate that the connection was lost and notify the UI Activity. + */ + protected void connectionLost() { + if (mIOThread != null) { + mIOThread.stop = true; + mIOThread = null; + mPThread.stop =true; + mPThread = null; + + } + setState(STATE_NONE); + mInitialized = false; + // Send a failure message back to the Activity + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Device connection was lost"); + msg.setData(bundle); + mHandler.sendMessage(msg); + } + + /** + * This thread runs while attempting to make an outgoing connection + * with a device. It runs straight through; the connection either + * succeeds or fails. + */ + private class ConnectThread extends Thread { + private final BluetoothSocket mmSocket; + private final BluetoothDevice mmDevice; + + public ConnectThread(BluetoothDevice device) { + mmDevice = device; + BluetoothSocket tmp = null; + Log.d(mClassName,"Start of Default ConnectThread"); + // Get a BluetoothSocket for a connection with the + // given BluetoothDevice + try { + tmp = device.createInsecureRfcommSocketToServiceRecord(mSPP_UUID); // If your device fails to pair try: device.createInsecureRfcommSocketToServiceRecord(mSPP_UUID) + } catch (IOException e) { + connectionLost(); + + } + mmSocket = tmp; + } + + public void run() { + setName("ConnectThread"); + + // Always cancel discovery because it will slow down a connection + mAdapter.cancelDiscovery(); + + try { + // Connect the device through the socket. This will block + // until it succeeds or throws an exception + mmSocket.connect(); + } catch (IOException connectException) { + connectionFailed(); + // Unable to connect; close the socket and get out + try { + mmSocket.close(); + } catch (IOException closeException) { } + return; + } + // Reset the ConnectThread because we're done + synchronized (Shimmer.this) { + mConnectThread = null; + } + // Start the connected thread + connected(mmSocket, mmDevice); + } + + public void cancel() { + try { + mmSocket.close(); + } catch (IOException e) { } + } + } + //arduino + private class ConnectThreadArduino extends Thread { + + //private static final String TAG = "ConnectThread"; + private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); + + private final RemoteDevice mDevice; + private BtSocket mSocket; + + public ConnectThreadArduino(RemoteDevice device) { + mDevice = device; + Log.d(mClassName," Start of ArduinoConnectThread"); + } + + public void run() { + try { + boolean isPaired = false; + + try { + isPaired = mDevice.ensurePaired(); + + + } + catch (RuntimeException re){ + re.printStackTrace(); + } + + //add a timer to wait for the user to pair the device otherwise quit + if (!isPaired){ + Thread.sleep(10000); + isPaired = mDevice.ensurePaired(); + } + + if (!isPaired){ + Log.d(mClassName, "not paired!"); + connectionFailed(); + + + } + else { + Log.d(mClassName, "is paired!"); + // Let main thread do some stuff to render UI immediately + //Thread.yield(); + // Get a BluetoothSocket to connect with the given BluetoothDevice + try { + mSocket = mDevice.openSocket(SPP_UUID); + } catch (Exception e) { + Log.d(mClassName, "Connection via SDP unsuccessful, try to connect via port directly"); + // 1.x Android devices only work this way since SDP was not part of their firmware then + mSocket = mDevice.openSocket(1); + //connectionFailed(); + Log.d(mClassName, "I am here"); + } + + // Do work to manage the connection (in a separate thread) + Log.d(mClassName, "Going to Manage Socket"); + if (getShimmerState() != STATE_NONE){ + Log.d(mClassName, "ManagingSocket"); + manageConnectedSocket(mSocket); + } + } + } + + catch (Exception e) { + Log.d(mClassName,"Connection Failed"); + //sendConnectionFailed(mDevice.getAddress()); + connectionFailed(); + e.printStackTrace(); + if (mSocket != null) + try { + mSocket.close(); + Log.d(mClassName,"Arduinothreadclose"); + } catch (IOException e1) {} + + return; + } + } + + /** Will cancel an in-progress connection, and close the socket */ + @SuppressWarnings("unused") + public void cancel() { + try { + if (mSocket != null) mSocket.close(); + //sendConnectionDisconnected(mDevice.getAddress()); + } + catch (IOException e) { Log.e("Shimmer", "cannot close socket to " + mDevice.getAddress()); } + } + + private void manageConnectedSocket(BtSocket socket){ + // Logger.d(TAG, "connection established."); + // pass the socket to a worker thread + String address = mDevice.getAddress(); + mConnectedThread = new ConnectedThread(socket, address); + Log.d(mClassName, "ConnectedThread is about to start"); + mIOThread = new IOThread(); + mIOThread.start(); + mPThread = new ProcessingThread(); + mPThread.start(); + // Send the name of the connected device back to the UI Activity + mMyBluetoothAddress = mDevice.getAddress(); + Message msg = mHandler.obtainMessage(Shimmer.MESSAGE_DEVICE_NAME); + mHandler.sendMessage(msg); + // Send the name of the connected device back to the UI Activity + while(!mIOThread.isAlive()){}; + Log.d(mClassName, "alive!!"); + setState(STATE_CONNECTED); + //startStreaming(); + initialize(); + } + } + + + + + /** + * This thread runs during a connection with a remote device. + * It handles all incoming and outgoing transmissions. + */ + private class ConnectedThread{ + private BluetoothSocket mmSocket=null; + + private BtSocket mSocket=null; + + public ConnectedThread(BluetoothSocket socket) { + + mmSocket = socket; + InputStream tmpIn = null; + OutputStream tmpOut = null; + + // Get the BluetoothSocket input and output streams + try { + tmpIn = socket.getInputStream(); + tmpOut = socket.getOutputStream(); + } catch (IOException e) { + connectionLost(); + } + + //mInStream = new BufferedInputStream(tmpIn); + mInStream = new DataInputStream(tmpIn); + mmOutStream = tmpOut; + } + + public ConnectedThread(BtSocket socket, String address) { + mSocket = socket; + //this.mAddress = address; + InputStream tmpIn = null; + OutputStream tmpOut = null; + + // Get the input and output streams, using temp objects because + // member streams are final + try { + tmpIn = socket.getInputStream(); + tmpOut = socket.getOutputStream(); + } catch (Exception e) { Log.d(mClassName,"Connected Thread Error"); + connectionLost();} + + //mInStream = new BufferedInputStream(tmpIn); + mInStream = new DataInputStream(tmpIn); + mmOutStream = tmpOut; + + } + + /** + *The received packets are processed here + */ + + /** + * Write to the connected OutStream. + * @param buffer The bytes to write + */ + private void write(byte[] buffer) { + try { + mmOutStream.write(buffer); + Log.d(mClassName, "Command transmitted: " + mMyBluetoothAddress + "; Command Issued: " + mCurrentCommand ); + + } catch (IOException e) { + Log.d(mClassName, "Command NOT transmitted: " + mMyBluetoothAddress + "; Command Issued: " + mCurrentCommand ); + } + } + + public void cancel() { + if(mInStream != null) { + try { + mInStream.close(); + } catch (IOException e) {} + } + if(mmOutStream != null) { + try { + mmOutStream.close(); + } catch (IOException e) {} + } + if(mmSocket != null) { + try { + if (mBluetoothLib==0){ + mmSocket.close(); + } else { + mSocket.close(); + } + } catch (IOException e) {} + } + } + } + + + + + + + protected void inquiryDone() { + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Inquiry done for device-> " + mMyBluetoothAddress); + msg.setData(bundle); + mHandler.sendMessage(msg); + isReadyForStreaming(); + } + + protected void isReadyForStreaming(){ + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Device " + mMyBluetoothAddress +" is ready for Streaming"); + msg.setData(bundle); + mHandler.sendMessage(msg); + if (mInitialized == false){ + //only do this during the initialization process to indicate that it is fully initialized, dont do this for a normal inqiuiry + mInitialized = true; + } + mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_FULLY_INITIALIZED, -1, new ObjectCluster(mMyName,getBluetoothAddress())).sendToTarget(); + Log.d(mClassName,"Shimmer " + mMyBluetoothAddress +" Initialization completed and is ready for Streaming"); + } + + protected void isNowStreaming() { + + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Device " + mMyBluetoothAddress + " is now Streaming"); + msg.setData(bundle); + mHandler.sendMessage(msg); + Log.d(mClassName,"Shimmer " + mMyBluetoothAddress +" is now Streaming"); + mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_STREAMING, -1, new ObjectCluster(mMyName,getBluetoothAddress())).sendToTarget(); + + } + + /* + * Set and Get Methods + * */ + public void setContinuousSync(boolean continousSync){ + mContinousSync=continousSync; + } + + public boolean getStreamingStatus(){ + return mStreaming; + } + + + + + /** + * This returns the variable mTransactionCompleted which indicates whether the Shimmer device is in the midst of a command transaction. True when no transaction is taking place. This is deprecated since the update to a thread model for executing commands + * @return mTransactionCompleted + */ + public boolean getInstructionStatus() + { + boolean instructionStatus=false; + if (mTransactionCompleted == true) { + instructionStatus=true; + } else { + instructionStatus=false; + } + return instructionStatus; + } + + public double getSamplingRate(){ + return mShimmerSamplingRate; + } + + /** + * Purpose of disabling calibration are for logging applications, to reduce the amount of computations needed to compute the data thus reducing risk of a performance bottleneck occuring and maximizing logging performance + * @param enable enables or disables calibration, note that this need to be enabled when using the ID as to calculate 3D orientation, see enable3DOrientation + */ + public void enableCalibration(boolean enable){ + mEnableCalibration = enable; + } + + + + + + public void writeInstruction(){ + if (getShimmerState() == STATE_CONNECTED) { + byte[] instruction = (byte[]) mListofInstructions.get(0); + write(instruction); + } + } + + + + + + @Override + protected void sendStatusMsgPacketLossDetected() { + // TODO Auto-generated method stub + mHandler.obtainMessage(Shimmer.MESSAGE_PACKET_LOSS_DETECTED, new ObjectCluster(mMyName,getBluetoothAddress())).sendToTarget(); + } + + + + + @Override + protected boolean bytesToBeRead() { + // TODO Auto-generated method stub + try { + if (mInStream.available()!=0){ + return true; + } else { + return false; + } + } catch (IOException e) { + // TODO Auto-generated catch block + connectionLost(); + e.printStackTrace(); + return false; + } + } + + @Override + protected int availableBytes() { + try { + return mInStream.available(); + } catch (IOException e) { + // TODO Auto-generated catch block + connectionLost(); + e.printStackTrace(); + return 0; + } + } + + + + @Override + protected void writeBytes(byte[] data) { + // TODO Auto-generated method stub + write(data); + } + + /* + public byte[] readBytes(int numberofBytes){ + byte[] b = new byte[numberofBytes]; + try{ + + int timeoutMillis = 500; + int bufferOffset = 0; + long maxTimeMillis = System.currentTimeMillis() + timeoutMillis; + while (System.currentTimeMillis() < maxTimeMillis && bufferOffset < b.length && mState!=STATE_NONE) { + int readLength = java.lang.Math.min(mInStream.available(),b.length-bufferOffset); + // can alternatively use bufferedReader, guarded by isReady(): + int readResult = mInStream.read(b, bufferOffset, readLength); + if (readResult == -1) break; + bufferOffset += readResult; + } + return b; + } catch (IOException e) { + // TODO Auto-generated catch block + connectionLost(); + e.printStackTrace(); + return b; + } + }*/ + + @Override + protected byte[] readBytes(int numberofBytes) { + // TODO Auto-generated method stub + byte[] b = new byte[numberofBytes]; + try { + //mIN.read(b,0,numberofBytes); + mInStream.readFully(b,0,numberofBytes); + return(b); + } catch (IOException e) { + // TODO Auto-generated catch block + System.out.println("Connection Lost"); + e.printStackTrace(); + } + + + return null; + } + + @Override + protected byte readByte() { + byte[] tb = new byte[1]; + try { + //mInStream.read(tb,0,1); + mInStream.readFully(tb,0,1); + return tb[0]; + } catch (IOException e) { + // TODO Auto-generated catch block + connectionLost(); + e.printStackTrace(); + return 0; + } + } + + @Override + protected void dataHandler(ObjectCluster ojc) { + // TODO Auto-generated method stub + mHandler.obtainMessage(MESSAGE_READ, ojc).sendToTarget(); + } + + @Override + protected void sendStatusMSGtoUI(String smsg) { + // TODO Auto-generated method stub + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, smsg); + msg.setData(bundle); + mHandler.sendMessage(msg); + } + + @Override + protected void printLogDataForDebugging(String msg) { + // TODO Auto-generated method stub + Log.d(mClassName,msg); + } + + @Override + protected void hasStopStreaming() { + // TODO Auto-generated method stub + Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Device " + mMyBluetoothAddress +" stopped streaming"); + msg.setData(bundle); + mHandler.sendMessage(msg); + mHandler.obtainMessage(Shimmer.MESSAGE_STATE_CHANGE, MSG_STATE_STOP_STREAMING, -1, new ObjectCluster(mMyName,getBluetoothAddress())).sendToTarget(); + + } + + @Override + protected void logAndStreamStatusChanged() { + // TODO Auto-generated method stub + + int docked, sensing; + + if(isDocked()) + docked=1; + else + docked=0; + + if(isSensing()) + sensing=1; + else + sensing=0; + + mHandler.obtainMessage(Shimmer.MESSAGE_LOG_AND_STREAM_STATUS_CHANGED, docked, sensing).sendToTarget(); + Log.d(mClassName,"Shimmer " + mMyBluetoothAddress +" Status has changed. Docked: "+docked+" Sensing: "+sensing); + } + + @Override + protected void processMsgFromCallback(ShimmerMsg shimmerMSG) { + // TODO Auto-generated method stub + + } + +// @Override +// protected void checkBatteryShimmer2r() { +// if (!mWaitForAck) { +// if (mVSenseBattMA.getMean()mLowBattLimit*1000+100) { //+100 is to make sure the limits are different to prevent excessive switching when the batt value is at the threshold +// if (mCurrentLEDStatus!=0) { +// writeLEDCommand(0); +// } +// } +// +// } +// } +// +// @Override +// protected void checkBatteryShimmer3(){ +// if (!mWaitForAck){ +// if(mVSenseBattMA.getMean()mLowBattLimit*1000+100){ //+100 is to make sure the limits are different to prevent excessive switching when the batt value is at the threshold +// if (mCurrentLEDStatus!=0) { +// writeLEDCommand(0); +// } +// } +// } +// } + + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/bluetooth/ShimmerBluetooth.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/bluetooth/ShimmerBluetooth.java new file mode 100644 index 00000000..044b4223 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/bluetooth/ShimmerBluetooth.java @@ -0,0 +1,4452 @@ +//Rev_1.9 +/* + * Copyright (c) 2010 - 2014, Shimmer Research, Ltd. + * All rights reserved + + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim, Ruaidhri Molloy, Mark Nolan + * @date September, 2014 + * + * Changes since 1.8 + * - set mInstructionStackLock in initialize(), this fix a bug when upon a ack timeout disconnect shimmer is unable to reconnect + * - add mtimer cancel and purge to intialize for precaution + * - added reset, to prevent API thinking it is the wrong fwidentifier (e.g. using btstream after logandstream) causing the get_status timer to be called + * - added readBlinkLED to initializeShimmer3, remove mCurrentLEDStatus from startStreaming + * - added a check for get_dir and get_status timeout, device won't disconnect if there is packet loss detected + * + * Changes since since 1.7 + * - updated logandstream support, now supports push button, start-stop streaming + * + * Changes since 1.6 + * - updated to support LogAndStream + * - updated checkBatt() + * + * Changes since 1.5 + * - updated comments + * - Baud rate setting support + * + * Changes since 1.4.04 + * - Reduce timeout for get_shimmer_version_command_new, to speed up connection for Shimmer2r + * - Move timeout response task to here, removed from Shimmer and ShimmerPCBT + * - Added + * + * Changes since 1.4.03 + * - support for Shimmer3 bridge amplifier, sensor conflict handling for Shimmer3 + * - Added isEXGUsingTestSignal24Configuration() isEXGUsingTestSignal16Configuration() isEXGUsingECG24Configuration() isEXGUsingECG16Configuration() isEXGUsingEMG24Configuration() isEXGUsingEMG16Configuration() + * + * Changes since 1.4.02 + * - moved setting of writeexg setting to after the ack, otherwise readexg and writeexg in the instruction stack will yield wrong results + * + * Changes since 1.4.01 + * - added exg set configuration to initialize shimmer3 exg from constructor + * + * Changes since 1.4 + * - removed mShimmerSamplingRate decimal formatter, decimal formatter should be done on the UI + * - remove null characters from mListofInstructions, after a stop streaming command, this was causing a race condition error + * + */ + + + +package com.shimmerresearch.bluetooth; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EmptyStackException; +import java.util.List; +import java.util.Locale; +import java.util.Stack; +import java.util.Timer; +import java.util.TimerTask; + + + + + + + + + + + + + + +import java.util.concurrent.ArrayBlockingQueue; + + +import com.shimmerresearch.driver.Configuration; +import com.shimmerresearch.driver.ShimmerVerDetails.FW_ID; +import com.shimmerresearch.driver.ObjectCluster; +import com.shimmerresearch.driver.ShimmerVerDetails.HW_ID; +import com.shimmerresearch.driver.ShimmerObject; +import com.shimmerresearch.tools.ArrayUtils; + +public abstract class ShimmerBluetooth extends ShimmerObject implements Serializable{ + + //region --------- CLASS VARIABLES AND ABSTRACT METHODS --------- + + protected long mSetEnabledSensors = SENSOR_ACCEL; // Only used during the initialization process, see initialize(); + // Constants that indicate the current connection state + + public static final int STATE_NONE = 0; // The class is doing nothing + public static final int STATE_CONNECTING = 1; // The class is now initiating an outgoing connection + public static final int STATE_CONNECTED = 2; // The class is now connected to a remote device + protected boolean mInstructionStackLock = false; + protected int mState; + protected byte mCurrentCommand; + protected boolean mWaitForAck=false; // This indicates whether the device is waiting for an acknowledge packet from the Shimmer Device + protected boolean mWaitForResponse=false; // This indicates whether the device is waiting for a response packet from the Shimmer Device + protected boolean mTransactionCompleted=true; // Variable is used to ensure a command has finished execution prior to executing the next command (see initialize()) + transient protected IOThread mIOThread; + transient protected ProcessingThread mPThread; + protected boolean mContinousSync=false; // This is to select whether to continuously check the data packets + protected boolean mSetupDevice=false; + protected Stack byteStack = new Stack(); + protected double mLowBattLimit=3.4; + protected int numBytesToReadFromExpBoard=0; + ArrayBlockingQueue mABQ = new ArrayBlockingQueue(10000); + protected boolean mIamAlive = false; + protected abstract void connect(String address,String bluetoothLibrary); + protected abstract void dataHandler(ObjectCluster ojc); + protected abstract boolean bytesToBeRead(); + protected abstract int availableBytes(); + + protected abstract void writeBytes(byte[] data); + protected abstract void stop(); + protected abstract void isNowStreaming(); + protected abstract void hasStopStreaming(); + protected abstract void sendStatusMsgPacketLossDetected(); + protected abstract void inquiryDone(); + protected abstract void sendStatusMSGtoUI(String msg); + protected abstract void printLogDataForDebugging(String msg); + protected abstract void isReadyForStreaming(); + protected abstract void connectionLost(); + protected abstract void setState(int state); + protected abstract void logAndStreamStatusChanged(); + + protected boolean mInitialized = false; + protected abstract byte[] readBytes(int numberofBytes); + protected abstract byte readByte(); + protected List mListofInstructions = new ArrayList(); + private final int ACK_TIMER_DURATION = 2; // Duration to wait for an ack packet (seconds) + transient protected Timer mTimer; // Timer variable used when waiting for an ack or response packet + protected boolean mDummy=false; + protected boolean mFirstTime=true; + private byte mTempByteValue; // A temporary variable used to store Byte value + protected int mTempIntValue; // A temporary variable used to store Integer value, used mainly to store a value while waiting for an acknowledge packet (e.g. when writeGRange() is called, the range is stored temporarily and used to update GSRRange when the acknowledge packet is received. + protected long tempEnabledSensors; // This stores the enabled sensors + private int mTempChipID; + protected boolean mSync=true; // Variable to keep track of sync + protected boolean mSetupEXG = false; + private byte[] cmdcalibrationParameters = new byte [22]; + private int mReadStatusPeriod=5000; + private int mAliveStatusPeriod=2000; + transient protected Timer mTimerToReadStatus; + transient protected Timer mAliveTimer; + private int mCountDeadConnection = 0; + private boolean mCheckIfConnectionisAlive = false; + + transient ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream(); + + //endregion + + /** + * Provides an interface directly to the method BuildMSG. This can be used to implement algorithm/filters/etc. Two methods are provided, processdata to implement your methods, and InitializeProcessData which is called everytime you startstreaming, in the event you need to reinitialize your method/algorithm everytime a Shimmer starts streaming + * + */ + public interface DataProcessing { + + /** + * Initialise your method/algorithm here, this callback is called when startstreaming is called + */ + + /** Initialise Process Data here. This is called whenever the startStreaming command is called and can be used to initialise algorithms + * + */ + public void InitializeProcessData(); + + /** Process data here, algorithms can access the object cluster built by the buildMsg method here + * @param ojc the objectCluster built by the buildMsg method + * @return the processed objectCluster + */ + public ObjectCluster ProcessData(ObjectCluster ojc); + + } + DataProcessing mDataProcessing; + + + public class ProcessingThread extends Thread { + byte[] tb ={0}; + byte[] newPacket=new byte[mPacketSize+1]; + public boolean stop = false; + int count=0; + public synchronized void run() { + while (!stop) { + if (!mABQ.isEmpty()){ + count++; + if (count%1000==0){ + System.out.print("Queue Size: " + mABQ.size() + "\n"); + printLogDataForDebugging("Queue Size: " + mABQ.size() + "\n"); + } + byte[] packet = mABQ.remove(); + ObjectCluster objectCluster=buildMsg(packet, FW_TYPE_BT, 0); + if (mDataProcessing!=null){ + objectCluster = mDataProcessing.ProcessData(objectCluster); + } + dataHandler(objectCluster); + } + } + } + } + + //region --------- BLUETOOH STACK --------- + + public class IOThread extends Thread { + byte[] tb ={0}; + byte[] newPacket=new byte[mPacketSize+1]; + public boolean stop = false; + public synchronized void run() { + while (!stop) { + ///////////////////////// + // is an instruction running ? if not proceed + if (mInstructionStackLock==false){ + // check instruction stack, are there any other instructions left to be executed? + if (!mListofInstructions.isEmpty()) { + if (mListofInstructions.get(0)==null) { + mListofInstructions.remove(0); + String msg = "Null Removed "; + printLogDataForDebugging(msg); + } + } + if (!mListofInstructions.isEmpty()){ + + byte[] insBytes = (byte[]) mListofInstructions.get(0); + mCurrentCommand=insBytes[0]; + mInstructionStackLock=true; + mWaitForAck=true; + + String msg = "Command Transmitted: " + Arrays.toString(insBytes); + printLogDataForDebugging(msg); + + if(!mStreaming){ + while(availableBytes()>0){ //this is to clear the buffer + tb=readBytes(availableBytes()); + } + } + if(mCurrentCommand==SET_RWC_COMMAND){ + byte[] bytearray=ByteBuffer.allocate(8).putLong(System.currentTimeMillis()).array(); + ArrayUtils.reverse(bytearray); + byte[] bytearraycommand= new byte[9]; + bytearraycommand[0]=SET_RWC_COMMAND; + System.arraycopy(bytearray, 0, bytearraycommand, 1, 8); + insBytes=bytearraycommand; + } + writeBytes(insBytes); + + + if (mCurrentCommand==STOP_STREAMING_COMMAND){ + mStreaming=false; + mListofInstructions.removeAll(Collections.singleton(null)); + } else { + if (mCurrentCommand==GET_FW_VERSION_COMMAND){ + startResponseTimer(ACK_TIMER_DURATION); + } else if (mCurrentCommand==GET_SAMPLING_RATE_COMMAND){ + startResponseTimer(ACK_TIMER_DURATION); + } else if (mCurrentCommand==GET_SHIMMER_VERSION_COMMAND_NEW){ + startResponseTimer(ACK_TIMER_DURATION); + } else { + if(mStreaming){ + startResponseTimer(ACK_TIMER_DURATION); + } else { + startResponseTimer(ACK_TIMER_DURATION+10); + } + } + } + + mTransactionCompleted=false; + + } + + + } + + + if (mWaitForAck==true && mStreaming ==false) { + + if (bytesToBeRead()){ + tb=readBytes(1); + mIamAlive = true; + String msg=""; + // msg = "rxb resp : " + Arrays.toString(tb); + // printLogDataForDebugging(msg); + + if (mCurrentCommand==STOP_STREAMING_COMMAND) { //due to not receiving the ack from stop streaming command we will skip looking for it. + mTimer.cancel(); + mTimer.purge(); + mStreaming=false; + mTransactionCompleted=true; + mWaitForAck=false; + try { + Thread.sleep(200); // Wait to ensure that we dont missed any bytes which need to be cleared + } catch (InterruptedException e) { + e.printStackTrace(); + } + byteStack.clear(); + + while(availableBytes()>0){ //this is to clear the buffer + + tb=readBytes(availableBytes()); + + } + hasStopStreaming(); + mListofInstructions.remove(0); + mListofInstructions.removeAll(Collections.singleton(null)); + mInstructionStackLock=false; + } + + if ((byte)tb[0]==ACK_COMMAND_PROCESSED) + { + msg = "Ack Received for Command: " + Byte.toString(mCurrentCommand); + printLogDataForDebugging(msg); + if (mCurrentCommand==START_STREAMING_COMMAND || mCurrentCommand==START_SDBT_COMMAND) { + mTimer.cancel(); + mTimer.purge(); + mStreaming=true; + mTransactionCompleted=true; + byteStack.clear(); + isNowStreaming(); + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + + else if (mCurrentCommand==SET_SAMPLING_RATE_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted=true; + mWaitForAck=false; + byte[] instruction=mListofInstructions.get(0); + double tempdouble=-1; + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + tempdouble=(double)1024/instruction[1]; + } else { + tempdouble = 32768/(double)((int)(instruction[1] & 0xFF) + ((int)(instruction[2] & 0xFF) << 8)); + } + mShimmerSamplingRate = tempdouble; + mListofInstructions.remove(0); + mInstructionStackLock=false; + if (mHardwareVersion == HW_ID.SHIMMER_3){ // has to be here because to ensure the current exgregister settings have been read back + //check sampling rate and adjust accordingly; + /*if (mShimmerSamplingRate<=128){ + writeEXGRateSetting(1,0); + writeEXGRateSetting(2,0); + } else if (mShimmerSamplingRate<=256){ + writeEXGRateSetting(1,1); + writeEXGRateSetting(2,1); + } + else if (mShimmerSamplingRate<=512){ + writeEXGRateSetting(1,2); + writeEXGRateSetting(2,2); + }*/ + } + + } + else if (mCurrentCommand==SET_BUFFER_SIZE_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted = true; + mWaitForAck=false; + mBufferSize=(int)((byte[])mListofInstructions.get(0))[1]; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==INQUIRY_COMMAND) { + mWaitForResponse=true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_LSM303DLHC_ACCEL_LPMODE_COMMAND) { + mWaitForResponse=true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_LSM303DLHC_ACCEL_HRMODE_COMMAND) { + mWaitForResponse=true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_BUFFER_SIZE_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_RWC_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_BLINK_LED) { + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_MAG_SAMPLING_RATE_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_MAG_GAIN_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_ACCEL_SENSITIVITY_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + } + else if (mCurrentCommand==GET_MPU9150_GYRO_RANGE_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + } + else if (mCurrentCommand==GET_GSR_RANGE_COMMAND) { + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_FW_VERSION_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + } + else if (mCurrentCommand==GET_ECG_CALIBRATION_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_EMG_CALIBRATION_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==SET_BLINK_LED) { + mCurrentLEDStatus=(int)((byte[])mListofInstructions.get(0))[1]; + mTransactionCompleted = true; + //mWaitForAck=false; + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_GSR_RANGE_COMMAND) { + + mTransactionCompleted = true; + mWaitForAck=false; + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mGSRRange=(int)((byte [])mListofInstructions.get(0))[1]; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==GET_SAMPLING_RATE_COMMAND) { + mWaitForResponse=true; + mWaitForAck=false; + + } + else if (mCurrentCommand==GET_CONFIG_BYTE0_COMMAND) { + mWaitForResponse=true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==SET_CONFIG_BYTE0_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mConfigByte0=(int)((byte [])mListofInstructions.get(0))[1]; + mWaitForAck=false; + mTransactionCompleted=true; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==SET_LSM303DLHC_ACCEL_LPMODE_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForAck=false; + mTransactionCompleted=true; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==SET_LSM303DLHC_ACCEL_HRMODE_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForAck=false; + mTransactionCompleted=true; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_PMUX_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + if (((byte[])mListofInstructions.get(0))[1]==1) { + mConfigByte0=(byte) ((byte) (mConfigByte0|64)&(0xFF)); + } + else if (((byte[])mListofInstructions.get(0))[1]==0) { + mConfigByte0=(byte) ((byte)(mConfigByte0 & 191)&(0xFF)); + } + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if(mCurrentCommand==SET_BMP180_PRES_RESOLUTION_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mPressureResolution=(int)((byte [])mListofInstructions.get(0))[1]; + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_GYRO_TEMP_VREF_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted=true; + mConfigByte0=mTempByteValue; + mWaitForAck=false; + } + else if (mCurrentCommand==SET_5V_REGULATOR_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + if (((byte[])mListofInstructions.get(0))[1]==1) { + mConfigByte0=(byte) (mConfigByte0|128); + } + else if (((byte[])mListofInstructions.get(0))[1]==0) { + mConfigByte0=(byte)(mConfigByte0 & 127); + } + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_INTERNAL_EXP_POWER_ENABLE_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + if (((byte[])mListofInstructions.get(0))[1]==1) { + mConfigByte0 = (mConfigByte0|16777216); + mInternalExpPower = 1; + } + else if (((byte[])mListofInstructions.get(0))[1]==0) { + mConfigByte0 = mConfigByte0 & 4278190079l; + mInternalExpPower = 0; + } + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==SET_VBATT_FREQ_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_RWC_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_ACCEL_SENSITIVITY_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mAccelRange=(int)(((byte[])mListofInstructions.get(0))[1]); + if (mDefaultCalibrationParametersAccel == true){ + if (mHardwareVersion != HW_ID.SHIMMER_3){ + if (getAccelRange()==0){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel1p5gShimmer2; + } else if (getAccelRange()==1){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel2gShimmer2; + } else if (getAccelRange()==2){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel4gShimmer2; + } else if (getAccelRange()==3){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel6gShimmer2; + } + } else if(mHardwareVersion == HW_ID.SHIMMER_3){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixLowNoiseAccel2gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixLowNoiseAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorLowNoiseAccelShimmer3; + } + } + + if (mDefaultCalibrationParametersDigitalAccel){ + if (mHardwareVersion == HW_ID.SHIMMER_3){ + if (getAccelRange()==1){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel4gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==2){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel8gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==3){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel16gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==0){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel2gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } + } + } + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + + else if (mCurrentCommand==SET_ACCEL_CALIBRATION_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + retrievekinematiccalibrationparametersfrompacket(Arrays.copyOfRange(mListofInstructions.get(0), 1, mListofInstructions.get(0).length), ACCEL_CALIBRATION_RESPONSE); + mTransactionCompleted = true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_GYRO_CALIBRATION_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + retrievekinematiccalibrationparametersfrompacket(Arrays.copyOfRange(mListofInstructions.get(0), 1, mListofInstructions.get(0).length), GYRO_CALIBRATION_RESPONSE); + mTransactionCompleted = true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_MAG_CALIBRATION_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + retrievekinematiccalibrationparametersfrompacket(Arrays.copyOfRange(mListofInstructions.get(0), 1, mListofInstructions.get(0).length), MAG_CALIBRATION_RESPONSE); + mTransactionCompleted = true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_LSM303DLHC_ACCEL_CALIBRATION_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + retrievekinematiccalibrationparametersfrompacket(Arrays.copyOfRange(mListofInstructions.get(0), 1, mListofInstructions.get(0).length), LSM303DLHC_ACCEL_CALIBRATION_RESPONSE); + mTransactionCompleted = true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + + else if (mCurrentCommand==SET_MPU9150_GYRO_RANGE_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mGyroRange=(int)(((byte[])mListofInstructions.get(0))[1]); + if (mDefaultCalibrationParametersGyro == true){ + if(mHardwareVersion == HW_ID.SHIMMER_3){ + mAlignmentMatrixGyroscope = AlignmentMatrixGyroShimmer3; + mOffsetVectorGyroscope = OffsetVectorGyroShimmer3; + if (mGyroRange==0){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro250dpsShimmer3; + + } else if (mGyroRange==1){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro500dpsShimmer3; + + } else if (mGyroRange==2){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro1000dpsShimmer3; + + } else if (mGyroRange==3){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro2000dpsShimmer3; + + } + } + } + mTransactionCompleted=true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_MAG_SAMPLING_RATE_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted = true; + mLSM303MagRate = mTempIntValue; + mWaitForAck = false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==GET_ACCEL_SAMPLING_RATE_COMMAND){ + mWaitForAck=false; + mWaitForResponse=true; + mListofInstructions.remove(0); + } else if (mCurrentCommand==SET_ACCEL_SAMPLING_RATE_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted = true; + mLSM303DigitalAccelRate = mTempIntValue; + mWaitForAck = false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==SET_MPU9150_SAMPLING_RATE_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted = true; + mMPU9150GyroAccelRate = mTempIntValue; + mWaitForAck = false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==SET_EXG_REGS_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + byte[] bytearray = mListofInstructions.get(0); + if (bytearray[1]==EXG_CHIP1){ //0 = CHIP 1 + System.arraycopy(bytearray, 4, mEXG1RegisterArray, 0, 10); + mEXG1RateSetting = mEXG1RegisterArray[0] & 7; + mEXG1CH1GainSetting = (mEXG1RegisterArray[3] >> 4) & 7; + mEXG1CH1GainValue = convertEXGGainSettingToValue(mEXG1CH1GainSetting); + mEXG1CH2GainSetting = (mEXG1RegisterArray[4] >> 4) & 7; + mEXG1CH2GainValue = convertEXGGainSettingToValue(mEXG1CH2GainSetting); + mEXGReferenceElectrode = mEXG1RegisterArray[5] & 0x0f; + + } else if (bytearray[1]==EXG_CHIP2){ //1 = CHIP 2 + System.arraycopy(bytearray, 4, mEXG2RegisterArray, 0, 10); + mEXG2RateSetting = mEXG2RegisterArray[0] & 7; + mEXG2CH1GainSetting = (mEXG2RegisterArray[3] >> 4) & 7; + mEXG2CH1GainValue = convertEXGGainSettingToValue(mEXG2CH1GainSetting); + mEXG2CH2GainSetting = (mEXG2RegisterArray[4] >> 4) & 7; + mEXG2CH2GainValue = convertEXGGainSettingToValue(mEXG2CH2GainSetting); + } + mTransactionCompleted = true; + mWaitForAck = false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (mCurrentCommand==SET_SENSORS_COMMAND) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForAck=false; + mEnabledSensors=tempEnabledSensors; + byteStack.clear(); // Always clear the packetStack after setting the sensors, this is to ensure a fresh start + mTransactionCompleted=true; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_MAG_GAIN_COMMAND){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted = true; + mWaitForAck = false; + mMagRange=(int)((byte [])mListofInstructions.get(0))[1]; + if (mDefaultCalibrationParametersMag == true){ + if(mHardwareVersion == HW_ID.SHIMMER_3){ + mAlignmentMatrixMagnetometer = AlignmentMatrixMagShimmer3; + mOffsetVectorMagnetometer = OffsetVectorMagShimmer3; + if (mMagRange==1){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag1p3GaShimmer3; + } else if (mMagRange==2){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag1p9GaShimmer3; + } else if (mMagRange==3){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag2p5GaShimmer3; + } else if (mMagRange==4){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag4GaShimmer3; + } else if (mMagRange==5){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag4p7GaShimmer3; + } else if (mMagRange==6){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag5p6GaShimmer3; + } else if (mMagRange==7){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag8p1GaShimmer3; + } + } + } + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==GET_ACCEL_CALIBRATION_COMMAND || mCurrentCommand==GET_GYRO_CALIBRATION_COMMAND || mCurrentCommand==GET_MAG_CALIBRATION_COMMAND || mCurrentCommand==GET_ALL_CALIBRATION_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_SHIMMER_VERSION_COMMAND_NEW) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==GET_BMP180_CALIBRATION_COEFFICIENTS_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } else if (mCurrentCommand==GET_SHIMMER_VERSION_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } else if (mCurrentCommand==GET_EXG_REGS_COMMAND){ + byte[] bytearray = mListofInstructions.get(0); + mTempChipID = bytearray[1]; + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==SET_ECG_CALIBRATION_COMMAND){ + //mGSRRange=mTempIntValue; + mDefaultCalibrationParametersECG = false; + OffsetECGLALL=(double)((((byte[])mListofInstructions.get(0))[0]&0xFF)<<8)+(((byte[])mListofInstructions.get(0))[1]&0xFF); + GainECGLALL=(double)((((byte[])mListofInstructions.get(0))[2]&0xFF)<<8)+(((byte[])mListofInstructions.get(0))[3]&0xFF); + OffsetECGRALL=(double)((((byte[])mListofInstructions.get(0))[4]&0xFF)<<8)+(((byte[])mListofInstructions.get(0))[5]&0xFF); + GainECGRALL=(double)((((byte[])mListofInstructions.get(0))[6]&0xFF)<<8)+(((byte[])mListofInstructions.get(0))[7]&0xFF); + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mTransactionCompleted = true; + mWaitForAck=false; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==SET_EMG_CALIBRATION_COMMAND){ + //mGSRRange=mTempIntValue; + mDefaultCalibrationParametersEMG = false; + OffsetEMG=(double)((((byte[])mListofInstructions.get(0))[0]&0xFF)<<8)+(((byte[])mListofInstructions.get(0))[1]&0xFF); + GainEMG=(double)((((byte[])mListofInstructions.get(0))[2]&0xFF)<<8)+(((byte[])mListofInstructions.get(0))[3]&0xFF); + mTransactionCompleted = true; + mWaitForAck=false; + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==TOGGLE_LED_COMMAND){ + //mGSRRange=mTempIntValue; + mTransactionCompleted = true; + mWaitForAck=false; + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mListofInstructions.remove(0); + mInstructionStackLock=false; + } + else if (mCurrentCommand==GET_BAUD_RATE_COMMAND) { + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if (mCurrentCommand==SET_BAUD_RATE_COMMAND) { + mTransactionCompleted = true; + mWaitForAck=false; + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mBluetoothBaudRate=(int)((byte [])mListofInstructions.get(0))[1]; + mListofInstructions.remove(0); + mInstructionStackLock=false; +// reconnect(); + } + else if(mCurrentCommand==GET_DAUGHTER_CARD_ID_COMMAND){ + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if(mCurrentCommand==GET_DIR_COMMAND){ + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + else if(mCurrentCommand==GET_STATUS_COMMAND){ + mWaitForResponse = true; + mWaitForAck=false; + mListofInstructions.remove(0); + } + + } + + + } + } else if (mWaitForResponse==true && !mStreaming) { + if (mFirstTime){ + while (availableBytes()!=0){ + int avaible = availableBytes(); + if (bytesToBeRead()){ + tb=readBytes(1); + String msg = "First Time : " + Arrays.toString(tb); + printLogDataForDebugging(msg); + } + + } + + } else if (availableBytes()!=0){ + + tb=readBytes(1); + mIamAlive = true; + String msg=""; + //msg = "rxb : " + Arrays.toString(tb); + //printLogDataForDebugging(msg); + + if (tb[0]==FW_VERSION_RESPONSE){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + + try { + Thread.sleep(200); // Wait to ensure the packet has been fully received + } catch (InterruptedException e) { + e.printStackTrace(); + } + byte[] bufferInquiry = new byte[6]; + bufferInquiry = readBytes(6); + mFirmwareIdentifier=(int)((bufferInquiry[1]&0xFF)<<8)+(int)(bufferInquiry[0]&0xFF); +// mFWVersion=(double)((bufferInquiry[3]&0xFF)<<8)+(double)(bufferInquiry[2]&0xFF)+((double)((bufferInquiry[4]&0xFF))/10); + mFirmwareVersionMajor = (int)((bufferInquiry[3]&0xFF)<<8)+(int)(bufferInquiry[2]&0xFF); + mFirmwareVersionMinor = ((int)((bufferInquiry[4]&0xFF))); + mFirmwareVersionInternal=(int)(bufferInquiry[5]&0xFF); + +// if (((double)((bufferInquiry[4]&0xFF))/10)==0){ +// mFirmwareVersionParsed = "BtStream " + Double.toString(mFWVersion) + "."+ Integer.toString(mFirmwareVersionRelease); +// } else { +// mFirmwareVersionParsed = "BtStream " + Double.toString(mFWVersion) + "."+ Integer.toString(mFirmwareVersionRelease); +// } + if(mFirmwareIdentifier==1){ //BTStream + if((mFirmwareVersionMajor==0 && mFirmwareVersionMinor==1) || (mFirmwareVersionMajor==1 && mFirmwareVersionMinor==2 && mHardwareVersion==HW_ID.SHIMMER_2R)) + mFirmwareVersionCode = 1; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==2) + mFirmwareVersionCode = 2; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==3) + mFirmwareVersionCode = 3; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==4) + mFirmwareVersionCode = 4; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor>=5) + mFirmwareVersionCode = 5; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==7 && mFirmwareVersionInternal>=3)//need to change to 8 + mFirmwareVersionCode = 7; + if (mFirmwareVersionMajor==0 && mFirmwareVersionMinor>=8) + mFirmwareVersionCode = 7; + + mFirmwareVersionParsed = "BtStream " + mFirmwareVersionMajor + "." + mFirmwareVersionMinor + "."+ mFirmwareVersionInternal; + } + else if(mFirmwareIdentifier==3){ //LogAndStream + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==1) + mFirmwareVersionCode = 3; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==2) + mFirmwareVersionCode = 4; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor>=3) + mFirmwareVersionCode = 5; + if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor>=6) + mFirmwareVersionCode = 6; + + mFirmwareVersionParsed = "LogAndStream " + mFirmwareVersionMajor + "." + mFirmwareVersionMinor + "."+ mFirmwareVersionInternal; + } + + //Once the version is known update settings accordingly + if (mFirmwareVersionCode>=6){ + mTimeStampPacketByteSize =3; + mTimeStampPacketRawMaxValue = 16777216; + } + else if (mFirmwareVersionCode<6){ + mTimeStampPacketByteSize =2; + mTimeStampPacketRawMaxValue = 65536; + } + + + printLogDataForDebugging("FW Version Response Received. FW Code: " + mFirmwareVersionCode); + msg = "FW Version Response Received: " +mFirmwareVersionParsed; + printLogDataForDebugging(msg); + mListofInstructions.remove(0); + mInstructionStackLock=false; + mTransactionCompleted=true; + if (mHardwareVersion == HW_ID.SHIMMER_2R){ + initializeShimmer2R(); + } else if (mHardwareVersion == HW_ID.SHIMMER_3) { + initializeShimmer3(); + } + + if (mCheckIfConnectionisAlive){ + if(mAliveTimer==null){ + mAliveTimer = new Timer(); + } + mAliveTimer.schedule(new checkIfAliveTask(), mAliveStatusPeriod, mAliveStatusPeriod); + + } + +// readShimmerVersion(); + } else if (tb[0]==BMP180_CALIBRATION_COEFFICIENTS_RESPONSE){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + + //get pressure + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + + byte[] pressureResoRes = new byte[22]; + + pressureResoRes = readBytes(22); + mPressureCalRawParams = new byte[23]; + System.arraycopy(pressureResoRes, 0, mPressureCalRawParams, 1, 22); + mPressureCalRawParams[0] = tb[0]; + retrievepressurecalibrationparametersfrompacket(pressureResoRes,tb[0]); + msg = "BMP180 Response Received"; + printLogDataForDebugging(msg); + mInstructionStackLock=false; + } else if (tb[0]==INQUIRY_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + try { + Thread.sleep(500); // Wait to ensure the packet has been fully received + } catch (InterruptedException e) { + e.printStackTrace(); + } + List buffer = new ArrayList(); + if (!(mHardwareVersion==HW_ID.SHIMMER_3)) + { + for (int i = 0; i < 5; i++) + { + // get Sampling rate, accel range, config setup byte0, num chans and buffer size + buffer.add(readByte()); + } + + for (int i = 0; i < (int)buffer.get(3); i++) + { + // read each channel type for the num channels + buffer.add(readByte()); + } + } + else + { + for (int i = 0; i < 8; i++) + { + // get Sampling rate, accel range, config setup byte0, num chans and buffer size + buffer.add(readByte()); + } + for (int i = 0; i < (int)buffer.get(6); i++) + { + // read each channel type for the num channels + buffer.add(readByte()); + } + } + byte[] bufferInquiry = new byte[buffer.size()]; + for (int i = 0; i < bufferInquiry.length; i++) { + bufferInquiry[i] = (byte) buffer.get(i); + } + + msg = "Inquiry Response Received: " + Arrays.toString(bufferInquiry); + printLogDataForDebugging(msg); + interpretInqResponse(bufferInquiry); + inquiryDone(); + mWaitForResponse = false; + mTransactionCompleted=true; + mInstructionStackLock=false; + } else if(tb[0] == GSR_RANGE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferGSRRange = readBytes(1); + mGSRRange=bufferGSRRange[0]; + msg = "GSR Range Response Received: " + Arrays.toString(bufferGSRRange); + printLogDataForDebugging(msg); + mInstructionStackLock=false; + } else if(tb[0] == MAG_SAMPLING_RATE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAns = readBytes(1); + mLSM303MagRate=bufferAns[0]; + msg = "Mag Sampling Rate Response Received: " + Arrays.toString(bufferAns); + printLogDataForDebugging(msg); + mInstructionStackLock=false; + } else if(tb[0] == ACCEL_SAMPLING_RATE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAns = readBytes(1); + mLSM303DigitalAccelRate=bufferAns[0]; + mInstructionStackLock=false; + } else if(tb[0] == RWC_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAns = readBytes(8); + mInstructionStackLock=false; + } else if(tb[0] == EXG_REGS_RESPONSE){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + try { + Thread.sleep(300); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + byte[] bufferAns = readBytes(11); + if (mTempChipID==0){ + System.arraycopy(bufferAns, 1, mEXG1RegisterArray, 0, 10); + // retrieve the gain and rate from the the registers + mEXG1RateSetting = mEXG1RegisterArray[0] & 7; + mEXG1CH1GainSetting = (mEXG1RegisterArray[3] >> 4) & 7; + mEXG1CH1GainValue = convertEXGGainSettingToValue(mEXG1CH1GainSetting); + mEXG1CH2GainSetting = (mEXG1RegisterArray[4] >> 4) & 7; + mEXG1CH2GainValue = convertEXGGainSettingToValue(mEXG1CH2GainSetting); + mEXGReferenceElectrode = mEXG1RegisterArray[5] & 0x0F; + mEXG1LeadOffCurrentMode = mEXG1RegisterArray[2] & 1; + mEXG1Comparators = mEXG1RegisterArray[1] & 0x40; + mEXGRLDSense = mEXG1RegisterArray[5] & 0x10; + mEXG1LeadOffSenseSelection = mEXG1RegisterArray[6] & 0x0f; + mEXGLeadOffDetectionCurrent = (mEXG1RegisterArray[2] >> 2) & 3; + mEXGLeadOffComparatorTreshold = (mEXG1RegisterArray[2] >> 5) & 7; + } else if (mTempChipID==1){ + System.arraycopy(bufferAns, 1, mEXG2RegisterArray, 0, 10); + mEXG2RateSetting = mEXG2RegisterArray[0] & 7; + mEXG2CH1GainSetting = (mEXG2RegisterArray[3] >> 4) & 7; + mEXG2CH1GainValue = convertEXGGainSettingToValue(mEXG2CH1GainSetting); + mEXG2CH2GainSetting = (mEXG2RegisterArray[4] >> 4) & 7; + mEXG2CH2GainValue = convertEXGGainSettingToValue(mEXG2CH2GainSetting); + mEXG2LeadOffCurrentMode = mEXG2RegisterArray[2] & 1; + mEXG2Comparators = mEXG2RegisterArray[1] & 0x40; + mEXG2LeadOffSenseSelection = mEXG2RegisterArray[6] & 0x0f; + } + if(mEXG1Comparators == 0 && mEXG2Comparators == 0 && mEXG1LeadOffSenseSelection == 0 && mEXG2LeadOffSenseSelection == 0){ + mLeadOffDetectionMode = 0; // Off + } + else if(mEXG1LeadOffCurrentMode == mEXG2LeadOffCurrentMode && mEXG1LeadOffCurrentMode == 0){ + mLeadOffDetectionMode = 1; // DC Current + } + else if(mEXG1LeadOffCurrentMode == mEXG2LeadOffCurrentMode && mEXG1LeadOffCurrentMode == 1){ + mLeadOffDetectionMode = 2; // AC Current. Not supported yet + } + mInstructionStackLock=false; + } else if(tb[0] == MAG_GAIN_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAns = readBytes(1); + mMagRange=bufferAns[0]; + mInstructionStackLock=false; + } else if(tb[0] == LSM303DLHC_ACCEL_HRMODE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAns = readBytes(1); + mInstructionStackLock=false; + } else if(tb[0] == LSM303DLHC_ACCEL_LPMODE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAns = readBytes(1); + mInstructionStackLock=false; + } else if(tb[0]==BUFFER_SIZE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] byteled = readBytes(1); + mBufferSize = byteled[0] & 0xFF; + mInstructionStackLock=false; + } else if(tb[0]==BLINK_LED_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] byteled = readBytes(1); + mCurrentLEDStatus = byteled[0]&0xFF; + mInstructionStackLock=false; + } else if(tb[0]==ACCEL_SENSITIVITY_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferAccelSensitivity = readBytes(1); + mAccelRange=bufferAccelSensitivity[0]; + if (mDefaultCalibrationParametersAccel == true){ + if (mHardwareVersion != HW_ID.SHIMMER_3){ + if (getAccelRange()==0){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel1p5gShimmer2; + } else if (getAccelRange()==1){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel2gShimmer2; + } else if (getAccelRange()==2){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel4gShimmer2; + } else if (getAccelRange()==3){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel6gShimmer2; + } + } else if(mHardwareVersion == HW_ID.SHIMMER_3){ + if (getAccelRange()==0){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixLowNoiseAccel2gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixLowNoiseAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorLowNoiseAccelShimmer3; + } else if (getAccelRange()==1){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixWideRangeAccel4gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==2){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixWideRangeAccel8gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==3){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixWideRangeAccel16gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorWideRangeAccelShimmer3; + } + } + } + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if(tb[0]==MPU9150_GYRO_RANGE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferGyroSensitivity = readBytes(1); + mGyroRange=bufferGyroSensitivity[0]; + if (mDefaultCalibrationParametersGyro == true){ + if(mHardwareVersion == HW_ID.SHIMMER_3){ + mAlignmentMatrixGyroscope = AlignmentMatrixGyroShimmer3; + mOffsetVectorGyroscope = OffsetVectorGyroShimmer3; + if (mGyroRange==0){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro250dpsShimmer3; + + } else if (mGyroRange==1){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro500dpsShimmer3; + + } else if (mGyroRange==2){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro1000dpsShimmer3; + + } else if (mGyroRange==3){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro2000dpsShimmer3; + } + } + } + mListofInstructions.remove(0); + mInstructionStackLock=false; + }else if (tb[0]==SAMPLING_RATE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + if(mStreaming==false) { + if (mHardwareVersion==HW_ID.SHIMMER_2R || mHardwareVersion==HW_ID.SHIMMER_2){ + byte[] bufferSR = readBytes(1); + if (mCurrentCommand==GET_SAMPLING_RATE_COMMAND) { // this is a double check, not necessary + double val=(double)(bufferSR[0] & (byte) ACK_COMMAND_PROCESSED); + mShimmerSamplingRate=1024/val; + } + } else if (mHardwareVersion==HW_ID.SHIMMER_3){ + byte[] bufferSR = readBytes(2); //read the sampling rate + mShimmerSamplingRate = 32768/(double)((int)(bufferSR[0] & 0xFF) + ((int)(bufferSR[1] & 0xFF) << 8)); + } + } + + msg = "Sampling Rate Response Received: " + Double.toString(mShimmerSamplingRate); + printLogDataForDebugging(msg); + mTransactionCompleted=true; + mListofInstructions.remove(0); + mInstructionStackLock=false; + } else if (tb[0]==ACCEL_CALIBRATION_RESPONSE ) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + mWaitForResponse=false; + byte[] bufferCalibrationParameters = readBytes(21); + + mAccelCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mAccelCalRawParams, 1, 21); + mAccelCalRawParams[0] = tb[0]; + + int packetType=tb[0]; + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, packetType); + msg = "Accel Calibration Response Received"; + printLogDataForDebugging(msg); + mTransactionCompleted=true; + mInstructionStackLock=false; + } else if (tb[0]==ALL_CALIBRATION_RESPONSE ) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (mHardwareVersion != HW_ID.SHIMMER_3){ + byte[] bufferCalibrationParameters = readBytes(21); + mAccelCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mAccelCalRawParams, 1, 21); + mAccelCalRawParams[0] = ACCEL_CALIBRATION_RESPONSE; + + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, ACCEL_CALIBRATION_RESPONSE); + + //get gyro + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + bufferCalibrationParameters = readBytes(21); + mGyroCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mGyroCalRawParams, 1, 21); + mGyroCalRawParams[0] = GYRO_CALIBRATION_RESPONSE; + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, GYRO_CALIBRATION_RESPONSE); + + //get mag + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + bufferCalibrationParameters = readBytes(21); + mMagCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mMagCalRawParams, 1, 21); + mMagCalRawParams[0] = MAG_CALIBRATION_RESPONSE; + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, MAG_CALIBRATION_RESPONSE); + + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + + bufferCalibrationParameters = readBytes(4); + mEMGCalRawParams = new byte[5]; + System.arraycopy(bufferCalibrationParameters, 0, mEMGCalRawParams, 1, 4); + mEMGCalRawParams[0] = EMG_CALIBRATION_RESPONSE; + retrievebiophysicalcalibrationparametersfrompacket( bufferCalibrationParameters,EMG_CALIBRATION_RESPONSE); + + bufferCalibrationParameters = readBytes(8); + + mECGCalRawParams = new byte[9]; + System.arraycopy(bufferCalibrationParameters, 0, mECGCalRawParams, 1, 8); + mECGCalRawParams[0] = ECG_CALIBRATION_RESPONSE; + retrievebiophysicalcalibrationparametersfrompacket( bufferCalibrationParameters,ECG_CALIBRATION_RESPONSE); + + mTransactionCompleted=true; + mInstructionStackLock=false; + + } else { + + + byte[] bufferCalibrationParameters =readBytes(21); + + mAccelCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mAccelCalRawParams, 1, 21); + mAccelCalRawParams[0] = ACCEL_CALIBRATION_RESPONSE; + + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, ACCEL_CALIBRATION_RESPONSE); + + //get gyro + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + bufferCalibrationParameters = readBytes(21); + + mGyroCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mGyroCalRawParams, 1, 21); + mGyroCalRawParams[0] = GYRO_CALIBRATION_RESPONSE; + + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, GYRO_CALIBRATION_RESPONSE); + + //get mag + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + bufferCalibrationParameters = readBytes(21); + + mMagCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mMagCalRawParams, 1, 21); + mMagCalRawParams[0] = MAG_CALIBRATION_RESPONSE; + + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, MAG_CALIBRATION_RESPONSE); + + //second accel cal params + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + bufferCalibrationParameters = readBytes(21); + + mDigiAccelCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mDigiAccelCalRawParams, 1, 21); + mDigiAccelCalRawParams[0] = LSM303DLHC_ACCEL_CALIBRATION_RESPONSE; + msg = "All Calibration Response Received"; + printLogDataForDebugging(msg); + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, LSM303DLHC_ACCEL_CALIBRATION_RESPONSE); + mTransactionCompleted=true; + mInstructionStackLock=false; + + } + } else if (tb[0]==GYRO_CALIBRATION_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + mWaitForResponse=false; + byte[] bufferCalibrationParameters = readBytes(21); + mGyroCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mGyroCalRawParams, 1, 21); + mGyroCalRawParams[0] = tb[0]; + + int packetType=tb[0]; + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, packetType); + msg = "Gyro Calibration Response Received"; + printLogDataForDebugging(msg); + mTransactionCompleted=true; + mInstructionStackLock=false; + } else if (tb[0]==MAG_CALIBRATION_RESPONSE ) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + byte[] bufferCalibrationParameters = readBytes(21); + mMagCalRawParams = new byte[22]; + System.arraycopy(bufferCalibrationParameters, 0, mMagCalRawParams, 1, 21); + mMagCalRawParams[0] = tb[0]; + int packetType=tb[0]; + retrievekinematiccalibrationparametersfrompacket(bufferCalibrationParameters, packetType); + msg = "Mag Calibration Response Received"; + printLogDataForDebugging(msg); + mTransactionCompleted=true; + mInstructionStackLock=false; + } else if(tb[0]==CONFIG_BYTE0_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + + if (mHardwareVersion==HW_ID.SHIMMER_2R || mHardwareVersion==HW_ID.SHIMMER_2){ + byte[] bufferConfigByte0 = readBytes(1); + mConfigByte0 = bufferConfigByte0[0] & 0xFF; + } else { + byte[] bufferConfigByte0 = readBytes(4); + mConfigByte0 = ((long)(bufferConfigByte0[0] & 0xFF) +((long)(bufferConfigByte0[1] & 0xFF) << 8)+((long)(bufferConfigByte0[2] & 0xFF) << 16) +((long)(bufferConfigByte0[3] & 0xFF) << 24)); + } + msg = "ConfigByte0 response received Response Received"; + printLogDataForDebugging(msg); + mTransactionCompleted=true; + mInstructionStackLock=false; + } else if(tb[0]==GET_SHIMMER_VERSION_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + byte[] bufferShimmerVersion = new byte[1]; + bufferShimmerVersion = readBytes(1); + mHardwareVersion=(int)bufferShimmerVersion[0]; + mTransactionCompleted=true; + mInstructionStackLock=false; +// if (mShimmerVersion == HW_ID.SHIMMER_2R){ +// initializeShimmer2R(); +// } else if (mShimmerVersion == HW_ID.SHIMMER_3) { +// initializeShimmer3(); +// } + msg = "Shimmer Version (HW) Response Received: " + Arrays.toString(bufferShimmerVersion); + printLogDataForDebugging(msg); + readFWVersion(); + } else if (tb[0]==ECG_CALIBRATION_RESPONSE){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + byte[] bufferCalibrationParameters = new byte[8]; + bufferCalibrationParameters = readBytes(4); + + mECGCalRawParams = new byte[9]; + System.arraycopy(bufferCalibrationParameters, 0, mECGCalRawParams, 1, 8); + mECGCalRawParams[0] = ECG_CALIBRATION_RESPONSE; + //get ecg + retrievebiophysicalcalibrationparametersfrompacket( bufferCalibrationParameters,ECG_CALIBRATION_RESPONSE); + msg = "ECG Calibration Response Received"; + printLogDataForDebugging(msg); + mTransactionCompleted=true; + mInstructionStackLock=false; + } else if (tb[0]==EMG_CALIBRATION_RESPONSE){ + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + try { + Thread.sleep(100); // Due to the nature of the Bluetooth SPP stack a delay has been added to ensure the buffer is filled before it is read + } catch (InterruptedException e) { + e.printStackTrace(); + } + byte[] bufferCalibrationParameters = new byte[4]; + bufferCalibrationParameters = readBytes(4); + + mEMGCalRawParams = new byte[5]; + System.arraycopy(bufferCalibrationParameters, 0, mEMGCalRawParams, 1, 4); + mEMGCalRawParams[0] = EMG_CALIBRATION_RESPONSE; + //get EMG + msg = "EMG Calibration Response Received"; + printLogDataForDebugging(msg); + retrievebiophysicalcalibrationparametersfrompacket( bufferCalibrationParameters,EMG_CALIBRATION_RESPONSE); + mTransactionCompleted=true; + mInstructionStackLock=false; + } + else if(tb[0] == BAUD_RATE_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + byte[] bufferBaud = readBytes(1); + printLogDataForDebugging(msg); + mBluetoothBaudRate=bufferBaud[0] & 0xFF; + mInstructionStackLock=false; + } + else if(tb[0] == DAUGHTER_CARD_ID_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + printLogDataForDebugging(msg); + mExpBoardArray = readBytes(numBytesToReadFromExpBoard+1); + mInstructionStackLock=false; + } + else if(tb[0] == INSTREAM_CMD_RESPONSE) { + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForResponse=false; + mTransactionCompleted=true; + printLogDataForDebugging(msg); + byte[] bufferLogCommandType = new byte[2]; + bufferLogCommandType = readBytes(2); + System.out.println("Instrucction received (113 = STATUS_RESPONSE) = "+bufferLogCommandType[0]); + if(bufferLogCommandType[0]==DIR_RESPONSE){ + mDirectoryNameLength = bufferLogCommandType[1]; + byte[] bufferDirectoryName = new byte[mDirectoryNameLength]; + bufferDirectoryName = readBytes(mDirectoryNameLength); + String tempDirectory = new String(bufferDirectoryName); + mDirectoryName = tempDirectory; + System.out.println("Directory Name = "+ mDirectoryName); + } + else if(bufferLogCommandType[0]==STATUS_RESPONSE){ + int sensing = bufferLogCommandType[1] & 2; + if(sensing==2) + mSensingStatus = true; + else + mSensingStatus = false; + + int docked = bufferLogCommandType[1] & 1; + if(docked==1) + mDockedStatus = true; + else + mDockedStatus = false; + + mIsSDLogging = ((bufferLogCommandType[1] & 0x08) > 0)? true:false; + mIsStreaming = ((bufferLogCommandType[1] & 0x10) > 0)? true:false; + + + System.out.println("Sensing = "+sensing); + System.out.println("Sensing status = "+mSensingStatus); + System.out.println("Docked = "+docked); + System.out.println("Docked status = "+mDockedStatus); + + if (mSensingStatus == false){ + if (mInitialized== false){ + writeRTCCommand(); + } + } + + } + mInstructionStackLock=false; + } + } + } + + + if (mWaitForAck==false && mWaitForResponse == false && mStreaming ==false && availableBytes()!=0 && mFirmwareIdentifier==3) { + tb=readBytes(1); + if(tb[0]==ACK_COMMAND_PROCESSED){ + System.out.println("ACK RECEIVED , Connected State!!"); + tb = readBytes(1); + if (tb[0]==ACK_COMMAND_PROCESSED){ + tb = readBytes(1); + } + if(tb[0]==INSTREAM_CMD_RESPONSE){ + System.out.println("INS CMD RESP"); + byte[] command = readBytes(2); + if(command[0]==DIR_RESPONSE){ + mDirectoryNameLength = command[1]; + byte[] bufferDirectoryName = new byte[mDirectoryNameLength]; + bufferDirectoryName = readBytes(mDirectoryNameLength); + String tempDirectory = new String(bufferDirectoryName); + mDirectoryName = tempDirectory; + + System.out.println("DIR RESP : " + mDirectoryName); + } + else if(command[0]==STATUS_RESPONSE){ + int sensing = command[1] & 2; + if(sensing==2) + mSensingStatus = true; + else + mSensingStatus = false; + + int docked = command[1] & 1; + if(docked==1) + mDockedStatus = true; + else + mDockedStatus = false; + + if (mSensingStatus){ + //flush all the bytes + while(availableBytes()!=0){ + System.out.println("Throwing away = "+readBytes(1)); + } + startStreaming(); + } + + logAndStreamStatusChanged(); + + System.out.println("Sensing = "+sensing); + System.out.println("Sensing status = "+mSensingStatus); + System.out.println("Docked = "+docked); + System.out.println("Docked status = "+mDockedStatus); + } + } + } + + while(availableBytes()!=0){ + System.out.println("Throwing away = "+readBytes(1)); + } + } + + + if (mStreaming==true) { + + tb = readBytes(1); + if (tb!=null){ + mByteArrayOutputStream.write(tb[0]); + } else { + System.out.print("readbyte null"); + } + + + + //If there is a full packet and the subsequent sequence number of following packet + if (mByteArrayOutputStream.size()>=mPacketSize+2){ + mIamAlive = true; + byte[] bufferTemp = mByteArrayOutputStream.toByteArray(); + if (bufferTemp[0]==DATA_PACKET && bufferTemp[mPacketSize+1]==DATA_PACKET){ + newPacket = new byte[mPacketSize]; + System.arraycopy(bufferTemp, 1, newPacket, 0, mPacketSize); + mABQ.add(newPacket); + //Finally clear the parsed packet from the bytearrayoutputstream, NOTE the last two bytes(seq number of next packet) are added back on after the reset + //System.out.print("Byte size reset: " + mByteArrayOutputStream.size() + "\n"); + mByteArrayOutputStream.reset(); + mByteArrayOutputStream.write(bufferTemp[mPacketSize+1]); + //System.out.print(bufferTemp[mPacketSize+1] + "\n"); + + } else if (bufferTemp[0]==DATA_PACKET && bufferTemp[mPacketSize+1]==ACK_COMMAND_PROCESSED){ + if (mByteArrayOutputStream.size()>mPacketSize+2){ + if (bufferTemp[mPacketSize+2]==DATA_PACKET){ + newPacket = new byte[mPacketSize]; + System.arraycopy(bufferTemp, 1, newPacket, 0, mPacketSize); + mABQ.add(newPacket); + //Finally clear the parsed packet from the bytearrayoutputstream, NOTE the last two bytes(seq number of next packet) are added back on after the reset + mByteArrayOutputStream.reset(); + mByteArrayOutputStream.write(bufferTemp[mPacketSize+2]); + System.out.print(bufferTemp[mPacketSize+2] + "\n"); + + if (mCurrentCommand==SET_BLINK_LED){ + System.out.println("LED COMMAND ACK RECEIVED"); + mCurrentLEDStatus=(int)((byte[])mListofInstructions.get(0))[1]; + mListofInstructions.remove(0); + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mWaitForAck=false; + mTransactionCompleted = true; + mInstructionStackLock=false; + } + + + } else if (mFirmwareIdentifier == FW_ID.SHIMMER3.LOGANDSTREAM && bufferTemp[mPacketSize+2]==INSTREAM_CMD_RESPONSE){ //this is for logandstream stupport, command is trasmitted and ack received + System.out.println("COMMAND TXed and ACK RECEIVED IN STREAM"); + System.out.println("INS CMD RESP"); + byte[] command = readBytes(2); + if(command[0]==DIR_RESPONSE){ + int mDirectoryNameLength = command[1]; + byte[] bufferDirectoryName = new byte[mDirectoryNameLength]; + bufferDirectoryName = readBytes(mDirectoryNameLength); + String tempDirectory = new String(bufferDirectoryName); + mDirectoryName = tempDirectory; + + System.out.println("DIR RESP : " + mDirectoryName); + } + else if(command[0]==STATUS_RESPONSE){ + int sensing = command[1] & 2; + if(sensing==2) + mSensingStatus = true; + else + mSensingStatus = false; + + int docked = command[1] & 1; + if(docked==1) + mDockedStatus = true; + else + mDockedStatus = false; + + System.out.println("Sensing = "+sensing); + System.out.println("Sensing status = "+mSensingStatus); + System.out.println("Docked = "+docked); + System.out.println("Docked status = "+mDockedStatus); + } + + mWaitForAck=false; + mTransactionCompleted = true; + mTimer.cancel(); //cancel the ack timer + mTimer.purge(); + mListofInstructions.remove(0); + mInstructionStackLock=false; + newPacket = new byte[mPacketSize]; + System.arraycopy(bufferTemp, 1, newPacket, 0, mPacketSize); + mABQ.add(newPacket); + mByteArrayOutputStream.reset(); + } else { + System.out.print("?? \n"); + } + } + if (mByteArrayOutputStream.size()>mPacketSize+2){ //throw the first byte away + byte[] bTemp = mByteArrayOutputStream.toByteArray(); + mByteArrayOutputStream.reset(); + mByteArrayOutputStream.write(bTemp, 1, bTemp.length-1); //this will throw the first byte away + System.out.print("Throw Byte \n"); + } + + } else {//throw the first byte away + byte[] bTemp = mByteArrayOutputStream.toByteArray(); + mByteArrayOutputStream.reset(); + mByteArrayOutputStream.write(bTemp, 1, bTemp.length-1); //this will throw the first byte away + System.out.print("Throw Byte \n"); + } + } + } + } + } + } + + private byte[] convertstacktobytearray(Stack b,int packetSize) { + byte[] returnByte=new byte[packetSize]; + b.remove(0); //remove the Data Packet identifier + for (int i=0;i=7){ + writeDisableBattTXFreq(); + } + if (mFirmwareVersionCode>=6 && mFirmwareIdentifier == FW_ID.SHIMMER3.LOGANDSTREAM){ + //readRWCCommand(); + //writeRWCCommand(); + readStatusLogAndStream(); + } + //enableLowPowerMag(mLowPowerMag); + if (mSetupDevice==true){ + //writeAccelRange(mDigitalAccelRange); + if (mSetupEXG){ + writeEXGConfiguration(mEXG1RegisterArray,1); + writeEXGConfiguration(mEXG2RegisterArray,2); + mSetupEXG = false; + } + writeGSRRange(mGSRRange); + writeAccelRange(mAccelRange); + writeGyroRange(mGyroRange); + writeMagRange(mMagRange); + writeSamplingRate(mShimmerSamplingRate); + writeInternalExpPower(1); +// setContinuousSync(mContinousSync); + writeEnabledSensors(mSetEnabledSensors); //this should always be the last command + } else { + inquiry(); + } + + + if(mFirmwareIdentifier==3){ // if shimmer is using LogAndStream FW, read its status perdiocally + if (mTimerToReadStatus!=null) { + mTimerToReadStatus.cancel(); + mTimerToReadStatus.purge(); + + + } + printLogDataForDebugging("Waiting for ack/response for command: " + Integer.toString(mCurrentCommand)); + mTimerToReadStatus = new Timer(); + mTimerToReadStatus.schedule(new readStatusTask(), mReadStatusPeriod, mReadStatusPeriod); + } + } + + //endregion + + + //region --------- START/STOP STREAMING FUNCTIONS --------- + + public void startStreaming() { + //mCurrentLEDStatus=-1; + //provides a callback for users to initialize their algorithms when start streaming is called + if (mDataProcessing!=null){ + mDataProcessing.InitializeProcessData(); + } + else { + //do nothing + } + + if(mFirmwareIdentifier==3){ // if shimmer is using LogAndStream FW, stop reading its status perdiocally + if(mTimerToReadStatus!=null){ + mTimerToReadStatus.cancel(); + mTimerToReadStatus.purge(); + mTimerToReadStatus = null; + } + } + + mPacketLossCount = 0; + mPacketReceptionRate = 100; + mFirstTimeCalTime=true; + mLastReceivedCalibratedTimeStamp = -1; + mSync=true; // a backup sync done every time you start streaming + mByteArrayOutputStream.reset(); + mListofInstructions.add(new byte[]{START_STREAMING_COMMAND}); + } + + public void startDataLogAndStreaming(){ + if(mFirmwareIdentifier==3){ // if shimmer is using LogAndStream FW, stop reading its status perdiocally + + if (mDataProcessing!=null){ + mDataProcessing.InitializeProcessData(); + } + else { + //do nothing + } + + + if(mTimerToReadStatus!=null){ + mTimerToReadStatus.cancel(); + mTimerToReadStatus.purge(); + mTimerToReadStatus = null; + } + + mPacketLossCount = 0; + mPacketReceptionRate = 100; + mFirstTimeCalTime=true; + mLastReceivedCalibratedTimeStamp = -1; + mSync=true; // a backup sync done every time you start streaming + mListofInstructions.add(new byte[]{START_SDBT_COMMAND}); + } + } + + + public void stopStreaming() { + mListofInstructions.add(new byte[]{STOP_STREAMING_COMMAND}); + if(mFirmwareIdentifier==3){ // if shimmer is using LogAndStream FW, read its status perdiocally + if(mTimerToReadStatus==null){ + mTimerToReadStatus = new Timer(); + } + mTimerToReadStatus.schedule(new readStatusTask(), mReadStatusPeriod, mReadStatusPeriod); + } + } + + + //endregion + + + //region --------- READ FUNCTIONS --------- + + public void readShimmerVersion() { + mDummy=false;//false +// if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ +// mShimmerVersion = HW_ID.SHIMMER_2R; // on Shimmer2r has + +// } else if (mFWVersion!=1.2){ + mListofInstructions.add(new byte[]{GET_SHIMMER_VERSION_COMMAND_NEW}); +// } else { +// mListofInstructions.add(new byte[]{GET_SHIMMER_VERSION_COMMAND}); +// } + } + + @Deprecated + public void readShimmerVersionDepracated(){ + mListofInstructions.add(new byte[]{GET_SHIMMER_VERSION_COMMAND}); + } + + /** + * The reason for this is because sometimes the 1st response is not received by the phone + */ + protected void dummyreadSamplingRate() { + mDummy=true; + mListofInstructions.add(new byte[]{GET_SAMPLING_RATE_COMMAND}); + } + + /** + * This reads the configuration of a chip from the EXG board + * @param chipID Chip id can either be 1 or 2 + */ + public void readEXGConfigurations(int chipID){ + if ((mFirmwareVersionInternal >=8 && mFirmwareVersionCode==2) || mFirmwareVersionCode>2){ + if (chipID==1 || chipID==2){ + mListofInstructions.add(new byte[]{GET_EXG_REGS_COMMAND,(byte)(chipID-1),0,10}); + } + } + } + + public void readpressurecalibrationcoefficients() { + if (mHardwareVersion == HW_ID.SHIMMER_3){ + if (mFirmwareVersionCode>1){ + mListofInstructions.add(new byte[]{ GET_BMP180_CALIBRATION_COEFFICIENTS_COMMAND}); + } + } + } + + + /** + * @param sensor is a string value that defines the sensor. Accepted sensor values are "Accelerometer","Gyroscope","Magnetometer","ECG","EMG","All" + */ + public void readCalibrationParameters(String sensor) { + + if (!mInitialized){ + if (mFirmwareVersionCode==1 && mFirmwareVersionInternal==0 && mHardwareVersion!=3) { + //mFirmwareVersionParsed="BoilerPlate 0.1.0"; + /*Message msg = mHandler.obtainMessage(MESSAGE_TOAST); + Bundle bundle = new Bundle(); + bundle.putString(TOAST, "Firmware Version: " +mFirmwareVersionParsed); + msg.setData(bundle); + mHandler.sendMessage(msg);*/ + } + } + if (sensor.equals("Accelerometer")) { + mListofInstructions.add(new byte[]{GET_ACCEL_CALIBRATION_COMMAND}); + } + else if (sensor.equals("Gyroscope")) { + mListofInstructions.add(new byte[]{GET_GYRO_CALIBRATION_COMMAND}); + } + else if (sensor.equals("Magnetometer")) { + mListofInstructions.add(new byte[]{GET_MAG_CALIBRATION_COMMAND}); + } + else if (sensor.equals("All")){ + mListofInstructions.add(new byte[]{GET_ALL_CALIBRATION_COMMAND}); + } + else if (sensor.equals("ECG")){ + mListofInstructions.add(new byte[]{GET_ECG_CALIBRATION_COMMAND}); + } + else if (sensor.equals("EMG")){ + mListofInstructions.add(new byte[]{GET_EMG_CALIBRATION_COMMAND}); + } + + } + + public void readSamplingRate() { + mListofInstructions.add(new byte[]{GET_SAMPLING_RATE_COMMAND}); + } + + public void readGSRRange() { + mListofInstructions.add(new byte[]{GET_GSR_RANGE_COMMAND}); + } + + public void readAccelRange() { + mListofInstructions.add(new byte[]{GET_ACCEL_SENSITIVITY_COMMAND}); + } + + public void readGyroRange() { + mListofInstructions.add(new byte[]{GET_MPU9150_GYRO_RANGE_COMMAND}); + } + + public void readBufferSize() { + mListofInstructions.add(new byte[]{GET_BUFFER_SIZE_COMMAND}); + } + + public void readMagSamplingRate() { + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{GET_MAG_SAMPLING_RATE_COMMAND}); + } + } + + /** + * Used to retrieve the data rate of the Accelerometer on Shimmer 3 + */ + public void readAccelSamplingRate() { + if (mHardwareVersion!=3){ + } else { + mListofInstructions.add(new byte[]{GET_ACCEL_SAMPLING_RATE_COMMAND}); + } + } + + public void readMagRange() { + mListofInstructions.add(new byte[]{GET_MAG_GAIN_COMMAND}); + } + + public void readBlinkLED() { + mListofInstructions.add(new byte[]{GET_BLINK_LED}); + } + + public void readECGCalibrationParameters() { + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{GET_ECG_CALIBRATION_COMMAND}); + } + } + + public void readEMGCalibrationParameters() { + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{GET_EMG_CALIBRATION_COMMAND}); + } + } + + public void readBaudRate(){ + if(mFirmwareVersionCode>=5){ + mListofInstructions.add(new byte[]{GET_BAUD_RATE_COMMAND}); + } + } + + /** + * Read the number of bytes specified starting in the offset from the expansion board attached to the Shimmer Device + * @param numBytes number of bytes to be read. there can be read up to 256 bytes + * @param offset point from where the function starts to read + */ + public void readExpansionBoardByBytes(int numBytes, int offset){ + if(mFirmwareVersionCode>=5){ + if(numBytes+offset<=256){ + numBytesToReadFromExpBoard = numBytes; + mListofInstructions.add(new byte[]{GET_DAUGHTER_CARD_ID_COMMAND, (byte) numBytes, (byte) offset}); + } + } + } + + public void readExpansionBoardID(){ + if(mFirmwareVersionCode>=5){ + numBytesToReadFromExpBoard=3; + int offset=0; + mListofInstructions.add(new byte[]{GET_DAUGHTER_CARD_ID_COMMAND, (byte) numBytesToReadFromExpBoard, (byte) offset}); + } + } + + public void readDirectoryName(){ + if(mFirmwareIdentifier==3){ // check if Shimmer is using LogAndStream firmware + mListofInstructions.add(new byte[]{GET_DIR_COMMAND}); + } + } + + public void readStatusLogAndStream(){ + if(mFirmwareIdentifier==3){ // check if Shimmer is using LogAndStream firmware + mListofInstructions.add(new byte[]{GET_STATUS_COMMAND}); + System.out.println("Instrucction added to the list"); + } + } + + public void readConfigByte0() { + mListofInstructions.add(new byte[]{GET_CONFIG_BYTE0_COMMAND}); + } + + public void readFWVersion() { + mDummy=false;//false + mListofInstructions.add(new byte[]{GET_FW_VERSION_COMMAND}); + } + + /** + * Class used to read perdiocally the shimmer status when LogAndStream FW is installed + */ + public class readStatusTask extends TimerTask{ + + @Override + public void run() { + // TODO Auto-generated method stub + mListofInstructions.add(new byte[]{GET_STATUS_COMMAND}); + } + + } + + /** + * @author Lim + * Used to check if the connection is alive + */ + private class checkIfAliveTask extends TimerTask{ + + @Override + public void run() { + if (!mIamAlive){ + mCountDeadConnection++; + writeLEDCommand(0); + if (mCountDeadConnection>5){ + setState(STATE_NONE); + } + } else { + mCountDeadConnection = 0; + mIamAlive=false; + } + } + + } + + + + //endregion + + + //region --------- WRITE FUNCTIONS --------- + + + /** + * writeGyroSamplingRate(range) sets the GyroSamplingRate on the Shimmer (version 3) to the value of the input range. + * @param rate it is a value between 0 and 255; 6 = 1152Hz, 77 = 102.56Hz, 255 = 31.25Hz + */ + private void writeGyroSamplingRate(int rate) { + if (mHardwareVersion == HW_ID.SHIMMER_3){ + mTempIntValue=rate; + mListofInstructions.add(new byte[]{SET_MPU9150_SAMPLING_RATE_COMMAND, (byte)rate}); + } + } + + /** + * writeMagSamplingRate(range) sets the MagSamplingRate on the Shimmer to the value of the input range. + * @param rate for Shimmer 2 it is a value between 1 and 6; 0 = 0.5 Hz; 1 = 1.0 Hz; 2 = 2.0 Hz; 3 = 5.0 Hz; 4 = 10.0 Hz; 5 = 20.0 Hz; 6 = 50.0 Hz, for Shimmer 3 it is a value between 0-7; 0 = 0.75Hz; 1 = 1.5Hz; 2 = 3Hz; 3 = 7.5Hz; 4 = 15Hz ; 5 = 30 Hz; 6 = 75Hz ; 7 = 220Hz + * + * */ + private void writeMagSamplingRate(int rate) { + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mTempIntValue=rate; + mListofInstructions.add(new byte[]{SET_MAG_SAMPLING_RATE_COMMAND, (byte)rate}); + } + } + + /** + * writeAccelSamplingRate(range) sets the AccelSamplingRate on the Shimmer (version 3) to the value of the input range. + * @param rate it is a value between 1 and 7; 1 = 1 Hz; 2 = 10 Hz; 3 = 25 Hz; 4 = 50 Hz; 5 = 100 Hz; 6 = 200 Hz; 7 = 400 Hz + */ + private void writeAccelSamplingRate(int rate) { + if (mHardwareVersion == HW_ID.SHIMMER_3){ + mTempIntValue=rate; + mListofInstructions.add(new byte[]{SET_ACCEL_SAMPLING_RATE_COMMAND, (byte)rate}); + } + } + + /** + * Transmits a command to the Shimmer device to enable the sensors. To enable multiple sensors an or operator should be used (e.g. writeEnabledSensors(SENSOR_ACCEL|SENSOR_GYRO|SENSOR_MAG)). Command should not be used consecutively. Valid values are SENSOR_ACCEL, SENSOR_GYRO, SENSOR_MAG, SENSOR_ECG, SENSOR_EMG, SENSOR_GSR, SENSOR_EXP_BOARD_A7, SENSOR_EXP_BOARD_A0, SENSOR_BRIDGE_AMP and SENSOR_HEART. + SENSOR_BATT + * @param enabledSensors e.g SENSOR_ACCEL|SENSOR_GYRO|SENSOR_MAG + */ + public void writeEnabledSensors(long enabledSensors) { + + if (!sensorConflictCheck(enabledSensors)){ //sensor conflict check + + } else { + enabledSensors=generateSensorBitmapForHardwareControl(enabledSensors); + tempEnabledSensors=enabledSensors; + + byte secondByte=(byte)((enabledSensors & 65280)>>8); + byte firstByte=(byte)(enabledSensors & 0xFF); + + //write(new byte[]{SET_SENSORS_COMMAND,(byte) lowByte, highByte}); + if (mHardwareVersion == HW_ID.SHIMMER_3){ + byte thirdByte=(byte)((enabledSensors & 16711680)>>16); + + mListofInstructions.add(new byte[]{SET_SENSORS_COMMAND,(byte) firstByte,(byte) secondByte,(byte) thirdByte}); + } else { + mListofInstructions.add(new byte[]{SET_SENSORS_COMMAND,(byte) firstByte,(byte) secondByte}); + } + inquiry(); + + } + } + + /** + * writePressureResolution(range) sets the resolution of the pressure sensor on the Shimmer3 + * @param settinge Numeric value defining the desired resolution of the pressure sensor. Valid range settings are 0 (low), 1 (normal), 2 (high), 3 (ultra high) + * + * */ + public void writePressureResolution(int setting) { + if (mHardwareVersion==HW_ID.SHIMMER_3){ + mListofInstructions.add(new byte[]{SET_BMP180_PRES_RESOLUTION_COMMAND, (byte)setting}); + } + } + + /** + * + * + */ + private void writeDisableBattTXFreq() { + if (mFirmwareVersionCode==7){ + byte[] freq={SET_VBATT_FREQ_COMMAND,0,0,0,0}; + mListofInstructions.add(freq); + } + + } + + private void readRTCCommand(){ + mListofInstructions.add(new byte[]{GET_ACCEL_SENSITIVITY_COMMAND}); + } + + private void writeRTCCommand(){ + byte[] bytearray=ByteBuffer.allocate(8).putLong(System.currentTimeMillis()).array(); + ArrayUtils.reverse(bytearray); + byte[] bytearraycommand= new byte[9]; + bytearraycommand[0]=SET_RWC_COMMAND; + System.arraycopy(bytearray, 0, bytearraycommand, 1, 8); + mListofInstructions.add(bytearraycommand); + } + + /** + * writeAccelRange(range) sets the Accelerometer range on the Shimmer to the value of the input range. When setting/changing the accel range, please ensure you have the correct calibration parameters. Note that the Shimmer device can only carry one set of accel calibration parameters at a single time. + * @param range is a numeric value defining the desired accelerometer range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). + */ + public void writeAccelRange(int range) { + mListofInstructions.add(new byte[]{SET_ACCEL_SENSITIVITY_COMMAND, (byte)range}); + mAccelRange=(int)range; + + } + + /** + * writeGyroRange(range) sets the Gyroscope range on the Shimmer3 to the value of the input range. When setting/changing the range, please ensure you have the correct calibration parameters. + * @param range is a numeric value defining the desired gyroscope range. + */ + public void writeGyroRange(int range) { + if (mHardwareVersion==HW_ID.SHIMMER_3){ + mListofInstructions.add(new byte[]{SET_MPU9150_GYRO_RANGE_COMMAND, (byte)range}); + mGyroRange=(int)range; + } + } + + /** + * @param rate Defines the sampling rate to be set (e.g.51.2 sets the sampling rate to 51.2Hz). User should refer to the document Sampling Rate Table to see all possible values. + */ + public void writeSamplingRate(double rate) { + if (mInitialized=true) { + setShimmerSamplingRate(rate); + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + + writeMagSamplingRate(mShimmer2MagRate); + + int samplingByteValue = (int) (1024/mShimmerSamplingRate); //the equivalent hex setting + mListofInstructions.add(new byte[]{SET_SAMPLING_RATE_COMMAND, (byte)Math.rint(samplingByteValue), 0x00}); + } else if (mHardwareVersion==HW_ID.SHIMMER_3) { + + writeMagSamplingRate(mLSM303MagRate); + writeAccelSamplingRate(mLSM303DigitalAccelRate); + writeGyroSamplingRate(mMPU9150GyroAccelRate); + + int samplingByteValue = (int) (32768/mShimmerSamplingRate); + mListofInstructions.add(new byte[]{SET_SAMPLING_RATE_COMMAND, (byte)(samplingByteValue&0xFF), (byte)((samplingByteValue>>8)&0xFF)}); + } + } + +// if (mInitialized=true) { +// +// if (mShimmerVersion==HW_ID.SHIMMER_2 || mShimmerVersion==HW_ID.SHIMMER_2R){ +// if (!mLowPowerMag){ +// if (rate<=10) { +// writeMagSamplingRate(4); +// } else if (rate<=20) { +// writeMagSamplingRate(5); +// } else { +// writeMagSamplingRate(6); +// } +// } else { +// writeMagSamplingRate(4); +// } +// rate=1024/rate; //the equivalent hex setting +// mListofInstructions.add(new byte[]{SET_SAMPLING_RATE_COMMAND, (byte)Math.rint(rate), 0x00}); +// } else if (mShimmerVersion==HW_ID.SHIMMER_3) { +// if (!mLowPowerMag){ +// if (rate<=1) { +// writeMagSamplingRate(1); +// } else if (rate<=15) { +// writeMagSamplingRate(4); +// } else if (rate<=30){ +// writeMagSamplingRate(5); +// } else if (rate<=75){ +// writeMagSamplingRate(6); +// } else { +// writeMagSamplingRate(7); +// } +// } else { +// if (rate >=10){ +// writeMagSamplingRate(4); +// } else { +// writeMagSamplingRate(1); +// } +// } +// +// if (!mLowPowerAccelWR){ +// if (rate<=1){ +// writeAccelSamplingRate(1); +// } else if (rate<=10){ +// writeAccelSamplingRate(2); +// } else if (rate<=25){ +// writeAccelSamplingRate(3); +// } else if (rate<=50){ +// writeAccelSamplingRate(4); +// } else if (rate<=100){ +// writeAccelSamplingRate(5); +// } else if (rate<=200){ +// writeAccelSamplingRate(6); +// } else { +// writeAccelSamplingRate(7); +// } +// } +// else { +// if (rate>=10){ +// writeAccelSamplingRate(2); +// } else { +// writeAccelSamplingRate(1); +// } +// } +// +// if (!mLowPowerGyro){ +// if (rate<=51.28){ +// writeGyroSamplingRate(0x9B); +// } else if (rate<=102.56){ +// writeGyroSamplingRate(0x4D); +// } else if (rate<=129.03){ +// writeGyroSamplingRate(0x3D); +// } else if (rate<=173.91){ +// writeGyroSamplingRate(0x2D); +// } else if (rate<=205.13){ +// writeGyroSamplingRate(0x26); +// } else if (rate<=258.06){ +// writeGyroSamplingRate(0x1E); +// } else if (rate<=533.33){ +// writeGyroSamplingRate(0xE); +// } else { +// writeGyroSamplingRate(6); +// } +// } +// else { +// writeGyroSamplingRate(0xFF); +// } +// +// +// +// int samplingByteValue = (int) (32768/rate); +// mListofInstructions.add(new byte[]{SET_SAMPLING_RATE_COMMAND, (byte)(samplingByteValue&0xFF), (byte)((samplingByteValue>>8)&0xFF)}); +// +// +// +// +// } +// } + } + + /** + * Only supported on Shimmer3, note that unlike previous write commands where the values are only set within the instrument driver after the ACK is received, this is set immediately. Fail safe should the settings not be actually set successfully is a timeout will occur, and the ID will disconnect from the device + * This function set the treshold of the ExG Lead-Off Comparator. There are 8 possible values: + * 1. Pos:95% - Neg:5%, 2. Pos:92.5% - Neg:7.5%, 3. Pos:90% - Neg:10%, 4. Pos:87.5% - Neg:12.5%, 5. Pos:85% - Neg:15%, + * 6. Pos:80% - Neg:20%, 7. Pos:75% - Neg:25%, 8. Pos:70% - Neg:30% + * @param treshold where 0 = 95-5, 1 = 92.5-7.5, 2 = 90-10, 3 = 87.5-12.5, 4 = 85-15, 5 = 80-20, 6 = 75-25, 7 = 70-30 + */ + public void writeEXGLeadOffComparatorTreshold(int treshold){ + if(mFirmwareVersionCode>2){ + if(treshold >=0 && treshold<8){ + byte[] reg1 = mEXG1RegisterArray; + byte[] reg2 = mEXG2RegisterArray; + byte currentLeadOffTresholdChip1 = reg1[2]; + byte currentLeadOffTresholdChip2 = reg2[2]; + currentLeadOffTresholdChip1 = (byte) (currentLeadOffTresholdChip1 & 31); + currentLeadOffTresholdChip2 = (byte) (currentLeadOffTresholdChip2 & 31); + currentLeadOffTresholdChip1 = (byte) (currentLeadOffTresholdChip1 | (treshold<<5)); + currentLeadOffTresholdChip2 = (byte) (currentLeadOffTresholdChip2 | (treshold<<5)); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 0,0,10,reg1[0],reg1[1],currentLeadOffTresholdChip1,reg1[3],reg1[4],reg1[5],reg1[6],reg1[7],reg1[8],reg1[9]}); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 1,0,10,reg2[0],reg2[1],currentLeadOffTresholdChip2,reg2[3],reg2[4],reg2[5],reg2[6],reg2[7],reg2[8],reg2[9]}); + } + } + } + + + /** + * Only supported on Shimmer3, note that unlike previous write commands where the values are only set within the instrument driver after the ACK is received, this is set immediately. Fail safe should the settings not be actually set successfully is a timeout will occur, and the ID will disconnect from the device + * This function set the ExG Lead-Off Current. There are 4 possible values: 6nA (default), 22nA, 6uA and 22uA. + * @param LeadOffCurrent where 0 = 6nA, 1 = 22nA, 2 = 6uA and 3 = 22uA + */ + public void writeEXGLeadOffDetectionCurrent(int leadOffCurrent){ + if(mFirmwareVersionCode>2){ + if(leadOffCurrent >=0 && leadOffCurrent<4){ + byte[] reg1 = mEXG1RegisterArray; + byte[] reg2 = mEXG2RegisterArray; + byte currentLeadOffDetectionCurrentChip1 = reg1[2]; + byte currentLeadOffDetectionCurrentChip2 = reg2[2]; + currentLeadOffDetectionCurrentChip1 = (byte) (currentLeadOffDetectionCurrentChip1 & 243); + currentLeadOffDetectionCurrentChip2 = (byte) (currentLeadOffDetectionCurrentChip2 & 243); + currentLeadOffDetectionCurrentChip1 = (byte) (currentLeadOffDetectionCurrentChip1 | (leadOffCurrent<<2)); + currentLeadOffDetectionCurrentChip2 = (byte) (currentLeadOffDetectionCurrentChip2 | (leadOffCurrent<<2)); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 0,0,10,reg1[0],reg1[1],currentLeadOffDetectionCurrentChip1,reg1[3],reg1[4],reg1[5],reg1[6],reg1[7],reg1[8],reg1[9]}); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 1,0,10,reg2[0],reg2[1],currentLeadOffDetectionCurrentChip2,reg2[3],reg2[4],reg2[5],reg2[6],reg2[7],reg2[8],reg2[9]}); + } + } + } + + + /** + * Only supported on Shimmer3 + * This function set the ExG Lead-Off detection mode. There are 3 possible modes: DC Current, AC Current (not supported yet), and Off. + * @param detectionMode where 0 = Off, 1 = DC Current, and 2 = AC Current + */ + public void writeEXGLeadOffDetectionMode(int detectionMode){ + + if(mFirmwareVersionCode>2){ + if(detectionMode == 0){ + mLeadOffDetectionMode = detectionMode; + byte[] reg1 = mEXG1RegisterArray; + byte[] reg2 = mEXG2RegisterArray; + byte currentComparatorChip1 = reg1[1]; + byte currentComparatorChip2 = reg2[1]; + currentComparatorChip1 = (byte) (currentComparatorChip1 & 191); + currentComparatorChip2 = (byte) (currentComparatorChip2 & 191); + byte currentRDLSense = reg1[5]; + currentRDLSense = (byte) (currentRDLSense & 239); + byte current2P1N1P = reg1[6]; + current2P1N1P = (byte) (current2P1N1P & 240); + byte current2P = reg2[6]; + current2P = (byte) (current2P & 240); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 0,0,10,reg1[0],currentComparatorChip1,reg1[2],reg1[3],reg1[4],currentRDLSense,current2P1N1P,reg1[7],reg1[8],reg1[9]}); + if(isEXGUsingDefaultEMGConfiguration()){ + byte currentEMGConfiguration = reg2[4]; + currentEMGConfiguration = (byte) (currentEMGConfiguration & 127); + currentEMGConfiguration = (byte) (currentEMGConfiguration | 128); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 1,0,10,reg2[0],currentComparatorChip2,reg2[2],reg2[3],currentEMGConfiguration,reg2[5],current2P,reg2[7],reg2[8],reg2[9]}); + } + else + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 1,0,10,reg2[0],currentComparatorChip2,reg2[2],reg2[3],reg2[4],reg2[5],current2P,reg2[7],reg2[8],reg2[9]}); + } + else if(detectionMode == 1){ + mLeadOffDetectionMode = detectionMode; + + byte[] reg1 = mEXG1RegisterArray; + byte[] reg2 = mEXG2RegisterArray; + byte currentDetectionModeChip1 = reg1[2]; + byte currentDetectionModeChip2 = reg2[2]; + currentDetectionModeChip1 = (byte) (currentDetectionModeChip1 & 254); // set detection mode chip1 + currentDetectionModeChip2 = (byte) (currentDetectionModeChip2 & 254); // set detection mode chip2 + byte currentComparatorChip1 = reg1[1]; + byte currentComparatorChip2 = reg2[1]; + currentComparatorChip1 = (byte) (currentComparatorChip1 & 191); + currentComparatorChip2 = (byte) (currentComparatorChip2 & 191); + currentComparatorChip1 = (byte) (currentComparatorChip1 | 64); // set comparator chip1 + currentComparatorChip2 = (byte) (currentComparatorChip2 | 64); // set comparator chip2 + byte currentRDLSense = reg1[5]; + currentRDLSense = (byte) (currentRDLSense & 239); + currentRDLSense = (byte) (currentRDLSense | 16); // set RLD sense + byte current2P1N1P = reg1[6]; + current2P1N1P = (byte) (current2P1N1P & 240); + current2P1N1P = (byte) (current2P1N1P | 7); // set 2P, 1N, 1P + byte current2P = reg2[6]; + current2P = (byte) (current2P & 240); + current2P = (byte) (current2P | 4); // set 2P + + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 0,0,10,reg1[0], currentComparatorChip1, currentDetectionModeChip1,reg1[3],reg1[4], currentRDLSense, current2P1N1P,reg1[7],reg1[8],reg1[9]}); + if(isEXGUsingDefaultEMGConfiguration()){ //if the EMG configuration is used, then enable the chanel 2 since it is needed for the Lead-off detection + byte currentEMGConfiguration = reg2[4]; + currentEMGConfiguration = (byte) (currentEMGConfiguration & 127); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 1,0,10,reg2[0], currentComparatorChip2, currentDetectionModeChip2,reg2[3],currentEMGConfiguration,reg2[5],current2P,reg2[7],reg2[8],reg2[9]}); + } + else + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 1,0,10,reg2[0], currentComparatorChip2, currentDetectionModeChip2,reg2[3],reg2[4],reg2[5],current2P,reg2[7],reg2[8],reg2[9]}); + } + else if(detectionMode == 2){ + mLeadOffDetectionMode = detectionMode; + //NOT SUPPORTED YET + } + } + } + + /** + * Only supported on Shimmer3, note that unlike previous write commands where the values are only set within the instrument driver after the ACK is received, this is set immediately. Fail safe should the settings not be actually set successfully is a timeout will occur, and the ID will disconnect from the device + * This function set the ExG reference electrode. There are 2 possible values when using ECG configuration: Inverse Wilson CT (default) and Fixed Potential + * and 2 possible values when using EMG configuration: Fixed Potential (default) and Inverse of Ch 1 + * @param referenceElectrode reference electrode code where 0 = Fixed Potential and 13 = Inverse Wilson CT (default) for an ECG configuration, and + * where 0 = Fixed Potential (default) and 3 = Inverse Ch1 for an EMG configuration + */ + public void writeEXGReferenceElectrode(int referenceElectrode){ + if (mFirmwareVersionCode>2){ + byte currentByteValue = mEXG1RegisterArray[5]; + byte[] reg = mEXG1RegisterArray; + currentByteValue = (byte) (currentByteValue & 240); + currentByteValue = (byte) (currentByteValue | referenceElectrode); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) 0,0,10,reg[0],reg[1],reg[2],reg[3],reg[4],currentByteValue,reg[6],reg[7],reg[8],reg[9]}); + } + } + + /** + * Only supported on Shimmer3, note that unlike previous write commands where the values are only set within the instrument driver after the ACK is received, this is set immediately. Fail safe should the settings not be actually set successfully is a timeout will occur, and the ID will disconnect from the device + * @param chipID Either a 1 or 2 value + * @param rateSettingsam , where 0=125SPS ; 1=250SPS; 2=500SPS; 3=1000SPS; 4=2000SPS + */ + public void writeEXGRateSetting(int chipID, int rateSetting){ + if ((mFirmwareVersionInternal >=8 && mFirmwareVersionCode==2) || mFirmwareVersionCode>2){ + if (chipID==1 || chipID==2){ + if (chipID==1){ + byte currentByteValue = mEXG1RegisterArray[0]; + byte[] reg = mEXG1RegisterArray; + currentByteValue = (byte) (currentByteValue & 248); + currentByteValue = (byte) (currentByteValue | rateSetting); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) (chipID-1),0,10,currentByteValue,reg[1],reg[2],reg[3],reg[4],reg[5],reg[6],reg[7],reg[8],reg[9]}); + } else if (chipID==2){ + byte currentByteValue = mEXG2RegisterArray[0]; + byte[] reg = mEXG2RegisterArray; + currentByteValue = (byte) (currentByteValue & 248); + currentByteValue = (byte) (currentByteValue | rateSetting); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) (chipID-1),0,10,currentByteValue,reg[1],reg[2],reg[3],reg[4],reg[5],reg[6],reg[7],reg[8],reg[9]}); + } + } + } + } + + + /** + * This is only supported on SHimmer3,, note that unlike previous write commands where the values are only set within the instrument driver after the ACK is received, this is set immediately. Fail safe should the settings not be actually set successfully is a timeout will occur, and the ID will disconnect from the device + * @param chipID Either a 1 or 2 value + * @param gainSetting , where 0 = 6x Gain, 1 = 1x , 2 = 2x , 3 = 3x, 4 = 4x, 5 = 8x, 6 = 12x + * @param channel Either a 1 or 2 value + */ + public void writeEXGGainSetting(int chipID, int channel, int gainSetting){ + if ((mFirmwareVersionInternal >=8 && mFirmwareVersionCode==2) || mFirmwareVersionCode>2){ + if ((chipID==1 || chipID==2) && (channel==1 || channel==2)){ + if (chipID==1){ + if (channel==1){ + byte currentByteValue = mEXG1RegisterArray[3]; + byte[] reg = mEXG1RegisterArray; + currentByteValue = (byte) (currentByteValue & 143); + currentByteValue = (byte) (currentByteValue | (gainSetting<<4)); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) (chipID-1),0,10,reg[0],reg[1],reg[2],currentByteValue,reg[4],reg[5],reg[6],reg[7],reg[8],reg[9]}); + } else { + byte currentByteValue = mEXG1RegisterArray[4]; + byte[] reg = mEXG1RegisterArray; + currentByteValue = (byte) (currentByteValue & 143); + currentByteValue = (byte) (currentByteValue | (gainSetting<<4)); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) (chipID-1),0,10,reg[0],reg[1],reg[2],reg[3],currentByteValue,reg[5],reg[6],reg[7],reg[8],reg[9]}); + } + } else if (chipID==2){ + if (channel==1){ + byte currentByteValue = mEXG2RegisterArray[3]; + byte[] reg = mEXG2RegisterArray; + currentByteValue = (byte) (currentByteValue & 143); + currentByteValue = (byte) (currentByteValue | (gainSetting<<4)); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) (chipID-1),0,10,reg[0],reg[1],reg[2],currentByteValue,reg[4],reg[5],reg[6],reg[7],reg[8],reg[9]}); + } else { + byte currentByteValue = mEXG2RegisterArray[4]; + byte[] reg = mEXG2RegisterArray; + currentByteValue = (byte) (currentByteValue & 143); + currentByteValue = (byte) (currentByteValue | (gainSetting<<4)); + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte) (chipID-1),0,10,reg[0],reg[1],reg[2],reg[3],currentByteValue,reg[5],reg[6],reg[7],reg[8],reg[9]}); + } + } + } + } + } + + /** + * Only supported on Shimmer3, note that unlike previous write commands where the values are only set within the instrument driver after the ACK is received, this is set immediately. Fail safe should the settings not be actually set successfully is a timeout will occur, and the ID will disconnect from the device + * @param reg A 10 byte value + * @param chipID value can either be 1 or 2. + */ + public void writeEXGConfiguration(byte[] reg,int chipID){ + if ((mFirmwareVersionInternal >=8 && mFirmwareVersionCode==2) || mFirmwareVersionCode>2){ + if (chipID==1 || chipID==2){ + mListofInstructions.add(new byte[]{SET_EXG_REGS_COMMAND,(byte)(chipID-1),0,10,reg[0],reg[1],reg[2],reg[3],reg[4],reg[5],reg[6],reg[7],reg[8],reg[9]}); + } + }} + + /** + * writeGSRRange(range) sets the GSR range on the Shimmer to the value of the input range. + * @param range numeric value defining the desired GSR range. Valid range settings are 0 (10kOhm to 56kOhm), 1 (56kOhm to 220kOhm), 2 (220kOhm to 680kOhm), 3 (680kOhm to 4.7MOhm) and 4 (Auto Range). + */ + public void writeGSRRange(int range) { + if (mHardwareVersion == HW_ID.SHIMMER_3){ + if (mFirmwareVersionCode!=1 || mFirmwareVersionInternal >4){ + mListofInstructions.add(new byte[]{SET_GSR_RANGE_COMMAND, (byte)range}); + } + } else { + mListofInstructions.add(new byte[]{SET_GSR_RANGE_COMMAND, (byte)range}); + } + } + + /** + * writeMagRange(range) sets the MagSamplingRate on the Shimmer to the value of the input range. When setting/changing the accel range, please ensure you have the correct calibration parameters. Note that the Shimmer device can only carry one set of accel calibration parameters at a single time. + * @param range is the mag rang + */ + public void writeMagRange(int range) { + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{SET_MAG_GAIN_COMMAND, (byte)range}); + } + } + + public void writeLEDCommand(int command) { + +// if (mShimmerVersion!=HW_ID.SHIMMER_3){ + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{SET_BLINK_LED, (byte)command}); + } +// } + } + + public void writeAccelCalibrationParameters(byte[] calibrationParameters) { + cmdcalibrationParameters[0] = SET_ACCEL_CALIBRATION_COMMAND; + System.arraycopy(calibrationParameters, 0, cmdcalibrationParameters, 1, 21); + mListofInstructions.add(cmdcalibrationParameters); + } + + public void writeGyroCalibrationParameters(byte[] calibrationParameters) { + cmdcalibrationParameters[0] = SET_GYRO_CALIBRATION_COMMAND; + System.arraycopy(calibrationParameters, 0, cmdcalibrationParameters, 1, 21); + mListofInstructions.add(cmdcalibrationParameters); + } + + public void writeMagCalibrationParameters(byte[] calibrationParameters) { + cmdcalibrationParameters[0] = SET_MAG_CALIBRATION_COMMAND; + System.arraycopy(calibrationParameters, 0, cmdcalibrationParameters, 1, 21); + mListofInstructions.add(cmdcalibrationParameters); + } + + public void writeWRAccelCalibrationParameters(byte[] calibrationParameters) { + if(mHardwareVersion==HW_ID.SHIMMER_3){ + cmdcalibrationParameters[0] = SET_LSM303DLHC_ACCEL_CALIBRATION_COMMAND; + System.arraycopy(calibrationParameters, 0, cmdcalibrationParameters, 1, 21); + mListofInstructions.add(cmdcalibrationParameters); + } + } + + public void writeECGCalibrationParameters(int offsetrall, int gainrall,int offsetlall, int gainlall) { + byte[] data = new byte[8]; + data[0] = (byte) ((offsetlall>>8)& 0xFF); //MSB offset + data[1] = (byte) ((offsetlall)& 0xFF); + data[2] = (byte) ((gainlall>>8)& 0xFF); //MSB gain + data[3] = (byte) ((gainlall)& 0xFF); + data[4] = (byte) ((offsetrall>>8)& 0xFF); //MSB offset + data[5] = (byte) ((offsetrall)& 0xFF); + data[6] = (byte) ((gainrall>>8)& 0xFF); //MSB gain + data[7] = (byte) ((gainrall)& 0xFF); + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{SET_ECG_CALIBRATION_COMMAND,data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]}); + } + } + + public void writeEMGCalibrationParameters(int offset, int gain) { + byte[] data = new byte[4]; + data[0] = (byte) ((offset>>8)& 0xFF); //MSB offset + data[1] = (byte) ((offset)& 0xFF); + data[2] = (byte) ((gain>>8)& 0xFF); //MSB gain + data[3] = (byte) ((gain)& 0xFF); + if (mFirmwareVersionParsed.equals("BoilerPlate 0.1.0")){ + } else { + mListofInstructions.add(new byte[]{SET_EMG_CALIBRATION_COMMAND,data[0],data[1],data[2],data[3]}); + } + } + + /** + * writeBaudRate(value) sets the baud rate on the Shimmer. + * @param value numeric value defining the desired Baud rate. Valid rate settings are 0 (115200 default), + * 1 (1200), 2 (2400), 3 (4800), 4 (9600) 5 (19200), + * 6 (38400), 7 (57600), 8 (230400), 9 (460800) and 10 (921600) + */ + public void writeBaudRate(int value) { + if (mFirmwareVersionCode>=5){ + if(value>=0 && value<=10){ + mBluetoothBaudRate = value; + mListofInstructions.add(new byte[]{SET_BAUD_RATE_COMMAND, (byte)value}); + try { + Thread.sleep(200); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + this.reconnect(); + } + + } + } + + /** + * writeConfigByte0(configByte0) sets the config byte0 value on the Shimmer to the value of the input configByte0. + * @param configByte0 is an unsigned 8 bit value defining the desired config byte 0 value. + */ + public void writeConfigByte0(byte configByte0) { + mListofInstructions.add(new byte[]{SET_CONFIG_BYTE0_COMMAND,(byte) configByte0}); + } + + /** + * writeAccelRange(range) sets the Accelerometer range on the Shimmer to the value of the input range. When setting/changing the accel range, please ensure you have the correct calibration parameters. Note that the Shimmer device can only carry one set of accel calibration parameters at a single time. + * @param range is a numeric value defining the desired accelerometer range. Valid range setting values for the Shimmer 2 are 0 (+/- 1.5g), 1 (+/- 2g), 2 (+/- 4g) and 3 (+/- 6g). Valid range setting values for the Shimmer 2r are 0 (+/- 1.5g) and 3 (+/- 6g). + */ + public void writeBufferSize(int size) { + mListofInstructions.add(new byte[]{SET_BUFFER_SIZE_COMMAND, (byte)size}); + } + + /** + * Sets the Pmux bit value on the Shimmer to the value of the input SETBIT. The PMux bit is the 2nd MSB of config byte0. + * @param setBit value defining the desired setting of the PMux (1=ON, 0=OFF). + */ + public void writePMux(int setBit) { + mListofInstructions.add(new byte[]{SET_PMUX_COMMAND,(byte) setBit}); + } + + /** + * Sets the configGyroTempVref bit value on the Shimmer to the value of the input SETBIT. The configGyroTempVref bit is the 2nd MSB of config byte0. + * @param setBit value defining the desired setting of the Gyro Vref (1=ON, 0=OFF). + */ + /*public void writeConfigGyroTempVref(int setBit) { + while(getInstructionStatus()==false) {}; + //Bit value defining the desired setting of the PMux (1=ON, 0=OFF). + if (setBit==1) { + mTempByteValue=(byte) (mConfigByte0|32); + } else if (setBit==0) { + mTempByteValue=(byte)(mConfigByte0 & 223); + } + mCurrentCommand=SET_GYRO_TEMP_VREF_COMMAND; + write(new byte[]{SET_GYRO_TEMP_VREF_COMMAND,(byte) setBit}); + mWaitForAck=true; + mTransactionCompleted=false; + responseTimer(ACK_TIMER_DURATION); + }*/ + + /** + * Enable/disable the Internal Exp Power on the Shimmer3 + * @param setBit value defining the desired setting of the Volt regulator (1=ENABLED, 0=DISABLED). + */ + public void writeInternalExpPower(int setBit) { + if (mHardwareVersion == HW_ID.SHIMMER_3 && mFirmwareVersionCode>=2){ + mListofInstructions.add(new byte[]{SET_INTERNAL_EXP_POWER_ENABLE_COMMAND,(byte) setBit}); + } else { + + } + } + + /** + * Enable/disable the 5 Volt Regulator on the Shimmer ExpBoard board + * @param setBit value defining the desired setting of the Volt regulator (1=ENABLED, 0=DISABLED). + */ + public void writeFiveVoltReg(int setBit) { + mListofInstructions.add(new byte[]{SET_5V_REGULATOR_COMMAND,(byte) setBit}); + } + + //endregion + + + //region --------- GET/SET FUNCTIONS --------- + + /**** GET FUNCTIONS *****/ + + /** + * This returns the variable mTransactionCompleted which indicates whether the Shimmer device is in the midst of a command transaction. True when no transaction is taking place. This is deprecated since the update to a thread model for executing commands + * @return mTransactionCompleted + */ + public boolean getInstructionStatus(){ + boolean instructionStatus=false; + if (mTransactionCompleted == true) { + instructionStatus=true; + } else { + instructionStatus=false; + } + return instructionStatus; + } + + public int getLowPowerAccelEnabled(){ + // TODO Auto-generated method stub + if (mLowPowerAccelWR) + return 1; + else + return 0; + } + + public int getLowPowerGyroEnabled() { + // TODO Auto-generated method stub + if (mLowPowerGyro) + return 1; + else + return 0; + } + + public int getLowPowerMagEnabled() { + // TODO Auto-generated method stub + if (mLowPowerMag) + return 1; + else + return 0; + } + + public int getPacketSize(){ + return mPacketSize; + } + + public boolean getInitialized(){ + return mInitialized; + } + + public double getPacketReceptionRate(){ + return mPacketReceptionRate; + } + + /** + * Get the 5V Reg. Only supported on Shimmer2/2R. + * @return 0 in case the 5V Reg is disableb, 1 in case the 5V Reg is enabled, and -1 in case the device doesn't support this feature + */ + public int get5VReg(){ + if(mHardwareVersion!=HW_ID.SHIMMER_3){ + if ((mConfigByte0 & (byte)128)!=0) { + //then set ConfigByte0 at bit position 7 + return 1; + } else { + return 0; + } + } + else + return -1; + } + + public String getDirectoryName(){ + if(mDirectoryName!=null) + return mDirectoryName; + else + return "Directory not read yet"; + } + + public int getCurrentLEDStatus() { + return mCurrentLEDStatus; + } + + public int getFirmwareMajorVersion(){ + return mFirmwareVersionMajor; + } + + public int getFirmwareMinorVersion(){ + return mFirmwareVersionMinor; + } + + public int getFirmwareCode(){ + return mFirmwareVersionCode; + } + + public String getFWVersionName(){ + return mFirmwareVersionParsed; + } + + /** + * Get the FW Identifier. It is equal to 3 when LogAndStream, and equal to 4 when BTStream. + * @return The FW identifier + */ + public int getFWIdentifier(){ + return (int) mFirmwareIdentifier; + } + + public int getBaudRate(){ + return mBluetoothBaudRate; + } + + public int getReferenceElectrode(){ + return mEXGReferenceElectrode; + } + + public int getLeadOffDetectionMode(){ + return mLeadOffDetectionMode; + } + + public int getLeadOffDetectionCurrent(){ + return mEXGLeadOffDetectionCurrent; + } + + public int getLeadOffComparatorTreshold(){ + return mEXGLeadOffComparatorTreshold; + } + + public byte[] getExG1Register(){ + + return mEXG1RegisterArray; + + } + + + + public byte[] getExG2Register(){ + + return mEXG2RegisterArray; + + } + + public int getExGComparatorsChip1(){ + return mEXG1Comparators; + } + + public int getExGComparatorsChip2(){ + return mEXG2Comparators; + } + + public String getExpBoardID(){ + + if(mExpBoardArray!=null){ +// if(mExpBoardName==null){ + int boardID = mExpBoardArray[1] & 0xFF; + int boardRev = mExpBoardArray[2] & 0xFF; + int specialRevision = mExpBoardArray[3] & 0xFF; + String boardName; + switch(boardID){ + case 8: + boardName="Bridge Amplifier+"; + break; + case 14: + boardName="GSR+"; + break; + case 36: + boardName="PROTO3 Mini"; + break; + case 37: + boardName="ExG"; + break; + case 38: + boardName="PROTO3 Deluxe"; + break; + default: + boardName="Unknown"; + break; + + } + if(!boardName.equals("Unknown")){ + boardName += " (SR" + boardID + "." + boardRev + "." + specialRevision +")"; + } + + mExpBoardName = boardName; +// } + } + else + return "Need to read ExpBoard ID first"; + + return mExpBoardName; + } + + public double getBattLimitWarning(){ + return mLowBattLimit; + } + + public int getShimmerVersion(){ + return mHardwareVersion; + } + + public String getShimmerName(){ + return mMyName; + } + + public void setShimmerName(String name){ + mMyName = name; + } + + /** + * Get the Gain value for the ExG1 Channel 1 + * @return the value of the gain. The Gain can be 1, 2, 3, 4, 6 (default), 8 or 12. The function return -1 when it is not possible to get the value. + */ + public int getEXG1CH1GainValue(){ + + int gain = -1; + while(!mListofInstructions.isEmpty()); + int tmpGain = getExg1CH1GainValue(); + if(tmpGain==1 || tmpGain==2 || tmpGain==3 || tmpGain==4 || tmpGain==6 || tmpGain==8 || tmpGain==12){ + gain = tmpGain; + } + return gain; + } + + /** + * Get the Gain value for the ExG1 Channel 1 + * @return the value of the gain. The Gain can be 1, 2, 3, 4, 6 (default), 8 or 12. The function return -1 when it is not possible to get the value. + */ + public int getEXG1CH2GainValue(){ + + int gain = -1; + while(!mListofInstructions.isEmpty()); + int tmpGain = getExg1CH2GainValue(); + if(tmpGain==1 || tmpGain==2 || tmpGain==3 || tmpGain==4 || tmpGain==6 || tmpGain==8 || tmpGain==12){ + gain = tmpGain; + } + return gain; + } + + /** + * Get the Gain value for the ExG1 Channel 1 + * @return the value of the gain. The Gain can be 1, 2, 3, 4, 6 (default), 8 or 12. The function return -1 when it is not possible to get the value. + */ + public int getEXG2CH1GainValue(){ + + int gain = -1; + while(!mListofInstructions.isEmpty()); + int tmpGain = getExg2CH1GainValue(); + if(tmpGain==1 || tmpGain==2 || tmpGain==3 || tmpGain==4 || tmpGain==6 || tmpGain==8 || tmpGain==12){ + gain = tmpGain; + } + return gain; + } + + /** + * Get the Gain value for the ExG1 Channel 1 + * @return the value of the gain. The Gain can be 1, 2, 3, 4, 6 (default), 8 or 12. The function return -1 when it is not possible to get the value. + */ + public int getEXG2CH2GainValue(){ + + int gain = -1; + while(!mListofInstructions.isEmpty()); + int tmpGain = getExg2CH2GainValue(); + if(tmpGain==1 || tmpGain==2 || tmpGain==3 || tmpGain==4 || tmpGain==6 || tmpGain==8 || tmpGain==12){ + gain = tmpGain; + } + return gain; + } + + public int getState(){ + return mState; + } + + /** Returns true if device is streaming (Bluetooth) + * @return + */ + public boolean isStreaming(){ + return mStreaming; + } + + /**** SET FUNCTIONS *****/ + + /** + * + * Register a callback to be invoked after buildmsg has executed (A new packet has been successfully received -> raw bytes interpreted into Raw and Calibrated Sensor data) + * + * @param d The callback that will be invoked + */ + public void setDataProcessing(DataProcessing d) { + mDataProcessing=d; + } + + /** + * Set the battery voltage limit, when the Shimmer device goes below the limit while streaming the LED on the Shimmer device will turn Yellow, in order to use battery voltage monitoring the Battery has to be enabled. See writeenabledsensors. Only to be used with Shimmer2. Calibration also has to be enabled, see enableCalibration. + * @param limit + */ + public void setBattLimitWarning(double limit){ + mLowBattLimit=limit; + } + + public void setContinuousSync(boolean continousSync){ + mContinousSync=continousSync; + } + + //endregion + + + //region --------- IS+something FUNCTIONS --------- + + public boolean isLowPowerMagEnabled(){ + return mLowPowerMag; + } + + public boolean isGyroOnTheFlyCalEnabled(){ + return mEnableOntheFlyGyroOVCal; + } + + public boolean is3DOrientatioEnabled(){ + return mOrientationEnabled; + } + + /**Only used for LogAndStream + * @return + */ + public boolean isSensing(){ + return mSensingStatus; + } + + public boolean isDocked(){ + return mDockedStatus; + } + + public boolean isLowPowerAccelEnabled() { + // TODO Auto-generated method stub + return mLowPowerAccelWR; + } + + public boolean isLowPowerGyroEnabled() { + // TODO Auto-generated method stub + return mLowPowerGyro; + } + + public boolean isUsingDefaultLNAccelParam(){ + return mDefaultCalibrationParametersAccel; + } + + public boolean isUsingDefaultAccelParam(){ + return mDefaultCalibrationParametersAccel; + } + + public boolean isUsingDefaultWRAccelParam(){ + return mDefaultCalibrationParametersDigitalAccel; + } + + public boolean isUsingDefaultGyroParam(){ + return mDefaultCalibrationParametersGyro; + } + + public boolean isUsingDefaultMagParam(){ + return mDefaultCalibrationParametersMag; + } + + public boolean isUsingDefaultECGParam(){ + return mDefaultCalibrationParametersECG; + } + + public boolean isUsingDefaultEMGParam(){ + return mDefaultCalibrationParametersEMG; + } + + + + + /** + * Checks if 16 bit ECG configuration is set on the Shimmer device. Do not use this command right after setting an EXG setting, as due to the execution model, the old settings might be returned, if this command is executed before an ack is received. + * @return true if 16 bit ECG is set + */ + @Override + public boolean isEXGUsingECG16Configuration(){ + while(!mListofInstructions.isEmpty()); + return super.isEXGUsingECG16Configuration(); + } + + /** + * Checks if 24 bit ECG configuration is set on the Shimmer device. Do not use this command right after setting an EXG setting, as due to the execution model, the old settings might be returned, if this command is executed before an ack is received. + * @return true if 24 bit ECG is set + */ + @Override + public boolean isEXGUsingECG24Configuration(){ + while(!mListofInstructions.isEmpty()); + return super.isEXGUsingECG24Configuration(); + } + + /** + * Checks if 16 bit EMG configuration is set on the Shimmer device. Do not use this command right after setting an EXG setting, as due to the execution model, the old settings might be returned, if this command is executed before an ack is received. + * @return true if 16 bit EMG is set + */ + @Override + public boolean isEXGUsingEMG16Configuration(){ + while(!mListofInstructions.isEmpty()); + return super.isEXGUsingEMG16Configuration(); + } + + /** + * Checks if 24 bit EMG configuration is set on the Shimmer device. Do not use this command right after setting an EXG setting, as due to the execution model, the old settings might be returned, if this command is executed before an ack is received. + * @return true if 24 bit EMG is set + */ + @Override + public boolean isEXGUsingEMG24Configuration(){ + while(!mListofInstructions.isEmpty()); + return super.isEXGUsingEMG24Configuration(); + } + + /** + * Checks if 16 bit test signal configuration is set on the Shimmer device. Do not use this command right after setting an EXG setting, as due to the execution model, the old settings might be returned, if this command is executed before an ack is received. + * @return true if 24 bit test signal is set + */ + @Override + public boolean isEXGUsingTestSignal16Configuration(){ + while(!mListofInstructions.isEmpty()); + return super.isEXGUsingTestSignal16Configuration(); + } + + /** + * Checks if 24 bit test signal configuration is set on the Shimmer device. + * @return true if 24 bit test signal is set + */ + @Override + public boolean isEXGUsingTestSignal24Configuration(){ + while(!mListofInstructions.isEmpty()); + return super.isEXGUsingTestSignal24Configuration(); + } + + //endregion + + + //region --------- ENABLE/DISABLE FUNCTIONS --------- + + /**** ENABLE FUNCTIONS *****/ + + //TODO: use set3DOrientation(enable) in ShimmerObject instead -> check that the "enable the sensors if they have not been enabled" comment is correct + /** + * This enables the calculation of 3D orientation through the use of the gradient descent algorithm, note that the user will have to ensure that mEnableCalibration has been set to true (see enableCalibration), and that the accel, gyro and mag has been enabled + * @param enable + */ + public void enable3DOrientation(boolean enable){ + //enable the sensors if they have not been enabled + mOrientationEnabled = enable; + } + + /** + * This enables the low power accel option. When not enabled the sampling rate of the accel is set to the closest value to the actual sampling rate that it can achieve. In low power mode it defaults to 10Hz. Also and additional low power mode is used for the LSM303DLHC. This command will only supports the following Accel range +4g, +8g , +16g + * @param enable + */ + public void enableLowPowerAccel(boolean enable){ + enableHighResolutionMode(!enable); + writeAccelSamplingRate(mLSM303DigitalAccelRate); + } + + private void enableHighResolutionMode(boolean enable) { + while(getInstructionStatus()==false) {}; + + if (mFirmwareVersionCode==1 && mFirmwareVersionInternal==0) { + + } else if (mHardwareVersion == HW_ID.SHIMMER_3) { + setLowPowerAccelWR(!enable); +// setHighResAccelWR(enable); + if (enable) { + // High-Res = On, Low-power = Off + mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_HRMODE_COMMAND, (byte)0x01}); + mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_LPMODE_COMMAND, (byte)0x00}); + } else { + // High-Res = Off, Low-power = On + mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_HRMODE_COMMAND, (byte)0x00}); + mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_LPMODE_COMMAND, (byte)0x01}); + } + } + } + +// private void enableLowResolutionMode(boolean enable){ +// while(getInstructionStatus()==false) {}; +// if (mFirmwareVersionCode==1 && mFirmwareVersionRelease==0) { +// +// } else if (mShimmerVersion == HW_ID.SHIMMER_3) { +// if (enable) { +// mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_LPMODE_COMMAND, (byte)0x01}); +// mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_HRMODE_COMMAND, (byte)0x00}); +// } else { +// mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_HRMODE_COMMAND, (byte)0x01}); +// mListofInstructions.add(new byte[]{SET_LSM303DLHC_ACCEL_LPMODE_COMMAND, (byte)0x00}); +// } +// } +// } + + /** + * This enables the low power accel option. When not enabled the sampling rate of the accel is set to the closest value to the actual sampling rate that it can achieve. In low power mode it defaults to 10Hz. Also and additional low power mode is used for the LSM303DLHC. This command will only supports the following Accel range +4g, +8g , +16g + * @param enable + */ + public void enableLowPowerGyro(boolean enable){ + setLowPowerGyro(enable); + writeGyroSamplingRate(mMPU9150GyroAccelRate); + } + + /** + * This enables the low power mag option. When not enabled the sampling rate of the mag is set to the closest value to the actual sampling rate that it can achieve. In low power mode it defaults to 10Hz + * @param enable + */ + public void enableLowPowerMag(boolean enable){ + setLowPowerMag(enable); + writeMagSamplingRate(mLSM303MagRate); + } + + + /** + *This can only be used for Shimmer3 devices (EXG) + *When a enable configuration is loaded, the advanced ExG configuration is removed, so it needs to be set again + */ + public void enableDefaultECGConfiguration() { + if (mHardwareVersion==3){ + setDefaultECGConfiguration(); + writeEXGConfiguration(mEXG1RegisterArray,1); + writeEXGConfiguration(mEXG2RegisterArray,2); + } + } + + /** + * This can only be used for Shimmer3 devices (EXG) + * When a enable configuration is loaded, the advanced ExG configuration is removed, so it needs to be set again + */ + public void enableDefaultEMGConfiguration(){ + if (mHardwareVersion==3){ + setDefaultEMGConfiguration(); + writeEXGConfiguration(mEXG1RegisterArray,1); + writeEXGConfiguration(mEXG2RegisterArray,2); + } + } + + /** + * This can only be used for Shimmer3 devices (EXG). Enables the test signal (square wave) of both EXG chips, to use, both EXG1 and EXG2 have to be enabled + */ + public void enableEXGTestSignal(){ + if (mHardwareVersion==3){ + setEXGTestSignal(); + writeEXGConfiguration(mEXG1RegisterArray,1); + writeEXGConfiguration(mEXG2RegisterArray,2); + } + } + + /**** DISABLE FUNCTIONS *****/ + + private long disableBit(long number,long disablebitvalue){ + if ((number&disablebitvalue)>0){ + number = number ^ disablebitvalue; + } + return number; + } + + //endregion + + + //region --------- MISCELLANEOUS FUNCTIONS --------- + + public void reconnect(){ + if (mState==ShimmerBluetooth.STATE_CONNECTED && !mStreaming){ + String msgReconnect = "Reconnecting the Shimmer..."; + sendStatusMSGtoUI(msgReconnect); + stop(); + try { + Thread.sleep(300); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + connect(mMyBluetoothAddress,"default"); + } + } + + + /** + * An inquiry is used to request for the current configuration parameters from the Shimmer device (e.g. Accelerometer settings, Configuration Byte, Sampling Rate, Number of Enabled Sensors and Sensors which have been enabled). + */ + public void inquiry() { + mListofInstructions.add(new byte[]{INQUIRY_COMMAND}); + } + + /** + * @param enabledSensors This takes in the current list of enabled sensors + * @param sensorToCheck This takes in a single sensor which is to be enabled + * @return enabledSensors This returns the new set of enabled sensors, where any sensors which conflicts with sensorToCheck is disabled on the bitmap, so sensorToCheck can be accomodated (e.g. for Shimmer2 using ECG will disable EMG,GSR,..basically any daughter board) + * + */ + public long sensorConflictCheckandCorrection(long enabledSensors,long sensorToCheck){ + + if (mHardwareVersion==HW_ID.SHIMMER_2R || mHardwareVersion==HW_ID.SHIMMER_2){ + if ((sensorToCheck & SENSOR_GYRO) >0 || (sensorToCheck & SENSOR_MAG) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_ECG); + enabledSensors = disableBit(enabledSensors,SENSOR_EMG); + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } else if ((sensorToCheck & SENSOR_BRIDGE_AMP) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_ECG); + enabledSensors = disableBit(enabledSensors,SENSOR_EMG); + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_GYRO); + enabledSensors = disableBit(enabledSensors,SENSOR_MAG); + } else if ((sensorToCheck & SENSOR_GSR) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_ECG); + enabledSensors = disableBit(enabledSensors,SENSOR_EMG); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + enabledSensors = disableBit(enabledSensors,SENSOR_GYRO); + enabledSensors = disableBit(enabledSensors,SENSOR_MAG); + } else if ((sensorToCheck & SENSOR_ECG) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_EMG); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + enabledSensors = disableBit(enabledSensors,SENSOR_GYRO); + enabledSensors = disableBit(enabledSensors,SENSOR_MAG); + } else if ((sensorToCheck & SENSOR_EMG) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_ECG); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + enabledSensors = disableBit(enabledSensors,SENSOR_GYRO); + enabledSensors = disableBit(enabledSensors,SENSOR_MAG); + } else if ((sensorToCheck & SENSOR_HEART) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_EXP_BOARD_A0); + enabledSensors = disableBit(enabledSensors,SENSOR_EXP_BOARD_A7); + } else if ((sensorToCheck & SENSOR_EXP_BOARD_A0) >0 || (sensorToCheck & SENSOR_EXP_BOARD_A7) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_HEART); + enabledSensors = disableBit(enabledSensors,SENSOR_BATT); + } else if ((sensorToCheck & SENSOR_BATT) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_EXP_BOARD_A0); + enabledSensors = disableBit(enabledSensors,SENSOR_EXP_BOARD_A7); + } + } + + else if(mHardwareVersion==HW_ID.SHIMMER_3){ + + if((sensorToCheck & SENSOR_GSR) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A1); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A14); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } + else if((sensorToCheck & SENSOR_EXG1_16BIT) >0 || (sensorToCheck & SENSOR_EXG2_16BIT) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A1); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A12); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A13); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A14); + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } + else if((sensorToCheck & SENSOR_EXG1_24BIT) >0 || (sensorToCheck & SENSOR_EXG2_24BIT) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A1); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A12); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A13); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A14); + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } + else if((sensorToCheck & SENSOR_BRIDGE_AMP) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A12); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A13); + enabledSensors = disableBit(enabledSensors,SENSOR_INT_ADC_A14); + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + } + else if ((sensorToCheck & SENSOR_INT_ADC_A14) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + } + else if ((sensorToCheck & SENSOR_INT_ADC_A12) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } + else if ((sensorToCheck & SENSOR_INT_ADC_A13) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } + else if ((sensorToCheck & SENSOR_INT_ADC_A14) >0){ + enabledSensors = disableBit(enabledSensors,SENSOR_GSR); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_16BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG1_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_EXG2_24BIT); + enabledSensors = disableBit(enabledSensors,SENSOR_BRIDGE_AMP); + } + + } + enabledSensors = enabledSensors ^ sensorToCheck; + return enabledSensors; + } + + public boolean sensorConflictCheck(long enabledSensors){ + boolean pass=true; + if (mHardwareVersion != HW_ID.SHIMMER_3){ + if (((enabledSensors & 0xFF)& SENSOR_GYRO) > 0){ + if (((enabledSensors & 0xFF)& SENSOR_EMG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_ECG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF)& SENSOR_MAG) > 0){ + if (((enabledSensors & 0xFF)& SENSOR_EMG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_ECG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF)& SENSOR_EMG) > 0){ + if (((enabledSensors & 0xFF)& SENSOR_GYRO) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_MAG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_ECG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF)& SENSOR_ECG) > 0){ + if (((enabledSensors & 0xFF)& SENSOR_GYRO) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_MAG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_EMG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_GSR) > 0){ + pass=false; + }else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF)& SENSOR_GSR) > 0){ + if (((enabledSensors & 0xFF)& SENSOR_GYRO) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_MAG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_EMG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_ECG) > 0){ + pass=false; + }else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + if (((enabledSensors & 0xFF)& SENSOR_GYRO) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_MAG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_EMG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_ECG) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF)& SENSOR_GSR) > 0){ + pass=false; + } else if (get5VReg()==1){ // if the 5volt reg is set + pass=false; + } + } + + if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0) { + if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { + pass=false; + } else if (getPMux()==1){ + + writePMux(0); + } + } + + if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0) { + if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { + pass=false; + }else if (getPMux()==1){ + writePMux(0); + } + } + + if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0) { + if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0){ + pass=false; + } + if (((enabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0){ + pass=false; + } + if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0){ + if (getPMux()==0){ + + writePMux(1); + } + } + } + if (!pass){ + + } + } + + else{ + + if(((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0 || ((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + + if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A1) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A12) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A13) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_INT_ADC_A14) > 0){ + pass=false; + } else if(((enabledSensors & 0xFF) & SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if(((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0 || ((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + + if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A1) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A12) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A13) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_INT_ADC_A14) > 0){ + pass=false; + } else if(((enabledSensors & 0xFF) & SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + + if(((enabledSensors & 0xFF) & SENSOR_GSR) > 0){ + + if (((enabledSensors & 0xFF0000) & SENSOR_INT_ADC_A1) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_INT_ADC_A14) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + + if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A12) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A13) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_INT_ADC_A14) > 0){ + pass=false; + } else if(((enabledSensors & 0xFF) & SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A1) > 0){ + + if(((enabledSensors & 0xFF) & SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A12) > 0){ + + if (((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF00) & SENSOR_INT_ADC_A13) > 0){ + + if (((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + + if (((enabledSensors & 0xFF0000) & SENSOR_INT_ADC_A14) > 0){ + + if(((enabledSensors & 0xFF) & SENSOR_GSR) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG1_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF0000) & SENSOR_EXG2_16BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG1_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF) & SENSOR_EXG2_24BIT) > 0){ + pass=false; + } else if (((enabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0){ + pass=false; + } + } + } + + return pass; + } + + /** + * @param enabledSensors this bitmap is only applicable for the instrument driver and does not correspond with the values in the firmware + * @return enabledSensorsFirmware returns the bitmap for the firmware + * The reason for this is hardware and firmware change may eventually need a different sensor bitmap, to keep the ID forward compatible, this function is used. Therefor the ID can have its own seperate sensor bitmap if needed + */ + private long generateSensorBitmapForHardwareControl(long enabledSensors){ + long hardwareSensorBitmap=0; + + //check if the batt volt is enabled (this is only applicable for HW_ID.SHIMMER_2R + if (mHardwareVersion == HW_ID.SHIMMER_2R || mHardwareVersion == HW_ID.SHIMMER_2){ + if (((enabledSensors & 0xFFFFF) & SENSOR_BATT) > 0 ){ + enabledSensors = enabledSensors & 0xFFFF; + enabledSensors = enabledSensors|SENSOR_EXP_BOARD_A0|SENSOR_EXP_BOARD_A7; + } + hardwareSensorBitmap = enabledSensors; + } else if (mHardwareVersion == HW_ID.SHIMMER_3){ + if (((enabledSensors & 0xFF)& SENSOR_ACCEL) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_A_ACCEL; + } + if ((enabledSensors & SENSOR_DACCEL) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_D_ACCEL; + } + if (((enabledSensors & 0xFF)& SENSOR_EXG1_24BIT) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXG1_24BIT; + } + if (((enabledSensors & 0xFF)& SENSOR_EXG2_24BIT) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXG2_24BIT; + } + + if ((enabledSensors& SENSOR_EXG1_16BIT) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXG1_16BIT; + } + if ((enabledSensors & SENSOR_EXG2_16BIT) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXG2_16BIT; + } + if (((enabledSensors & 0xFF)& SENSOR_GYRO) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_GYRO; + } + if (((enabledSensors & 0xFF)& SENSOR_MAG) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_MAG; + } + if ((enabledSensors & SENSOR_BATT) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_VBATT; + } + if ((enabledSensors & SENSOR_EXT_ADC_A7) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXT_A7; + } + if ((enabledSensors & SENSOR_EXT_ADC_A6) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXT_A6; + } + if ((enabledSensors & SENSOR_EXT_ADC_A15) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_EXT_A15; + } + if ((enabledSensors & SENSOR_INT_ADC_A1) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A1; + } + if ((enabledSensors & SENSOR_INT_ADC_A12) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A12; + } + if ((enabledSensors & SENSOR_INT_ADC_A13) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A13; + } + if ((enabledSensors & SENSOR_INT_ADC_A14) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_INT_A14; + } + if ((enabledSensors & SENSOR_BMP180) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_BMP180; + } + if ((enabledSensors & SENSOR_GSR) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_GSR; + } + if ((enabledSensors & SENSOR_BRIDGE_AMP) > 0){ + hardwareSensorBitmap = hardwareSensorBitmap|Configuration.Shimmer3.SensorBitmap.SENSOR_BRIDGE_AMP; + } + } else { + hardwareSensorBitmap = enabledSensors; + } + + return hardwareSensorBitmap; + } + + public void toggleLed() { + mListofInstructions.add(new byte[]{TOGGLE_LED_COMMAND}); + } + + @Override + protected void checkBattery(){ + if (mStreaming ){ + if(mHardwareVersion == HW_ID.SHIMMER_3 && mFirmwareIdentifier==3){ + if (!mWaitForAck) { + if (mVSenseBattMA.getMean()mLowBattLimit*1000+100) { //+100 is to make sure the limits are different to prevent excessive switching when the batt value is at the threshold + if (mCurrentLEDStatus!=0) { + writeLEDCommand(0); + } + } + + } + } + if(mHardwareVersion == HW_ID.SHIMMER_2R){ + if (!mWaitForAck) { + if (mVSenseBattMA.getMean()mLowBattLimit*1000+100) { //+100 is to make sure the limits are different to prevent excessive switching when the batt value is at the threshold + if (mCurrentLEDStatus!=0) { + writeLEDCommand(0); + } + } + + } + } + + + + } + + } + + public void enableCheckifAlive(boolean set){ + mCheckIfConnectionisAlive = set; + } + + public void resetCalibratedTimeStamp(){ + mLastReceivedCalibratedTimeStamp = -1; + mFirstTimeCalTime = true; + mCurrentTimeStampCycle = 0; + } + + //endregion + + public Object slotDetailsGetMethods(String componentName) { + Object returnValue = null; + switch(componentName){ +//Booleans + case(Configuration.Shimmer3.GuiLabelConfig.KINEMATIC_LPM): + if(isLSM303DigitalAccelLPM()&&checkLowPowerGyro()&&checkLowPowerMag()) { + returnValue = true; + } + else { + returnValue = false; + } + break; + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_LPM): + returnValue = isLSM303DigitalAccelLPM(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_LPM): + returnValue = checkLowPowerGyro(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_LPM): + returnValue = checkLowPowerMag(); + break; + +//Integers + case(Configuration.Shimmer3.GuiLabelConfig.BLUETOOTH_BAUD_RATE): + returnValue = getBluetoothBaudRate(); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RANGE): + returnValue = getAccelRange(); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RANGE): + returnValue = getGyroRange(); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RANGE): + //TODO check below and commented out code + returnValue = getMagRange(); + +// // firmware sets mag range to 7 (i.e. index 6 in combobox) if user set mag range to 0 in config file +// if(getMagRange() == 0) cmBx.setSelectedIndex(6); +// else cmBx.setSelectedIndex(getMagRange()-1); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.PRESSURE_RESOLUTION): + returnValue = getPressureResolution(); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.GSR_RANGE): + returnValue = getGSRRange(); //TODO: check with RM re firmware bug?? + break; + + case(Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION): + returnValue = getExGResolution(); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN): + //TODO: What should this be? + //returnValue = getExGGainSetting(); + //consolePrintLn("Get " + configValue); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE): + int configValue = getLSM303DigitalAccelRate(); + + if(!isLSM303DigitalAccelLPM()) { + if(configValue==8) { + configValue = 9; + } + } + returnValue = configValue; + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RATE): + returnValue = getLSM303MagRate(); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_ACCEL_RANGE): + returnValue = getMPU9150AccelRange(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_DMP_GYRO_CAL): + returnValue = getMPU9150MotCalCfg(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_LPF): + returnValue = getMPU9150LPF(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL_RATE): + returnValue = getMPU9150MPLSamplingRate(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MAG_RATE): + returnValue = getMPU9150MagSamplingRate(); + break; + + //TODO + case(Configuration.Shimmer3.GuiLabelConfig.EXG_RATE): + returnValue = getEXG1RateSetting(); + //returnValue = getEXG2RateSetting(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_REFERENCE_ELECTRODE): + returnValue = getEXGReferenceElectrode(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_DETECTION): + returnValue = getEXG2LeadOffCurrentMode(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_CURRENT): + returnValue = getEXGLeadOffDetectionCurrent(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_COMPARATOR): + returnValue = getEXGLeadOffComparatorTreshold(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_FREQ): + returnValue = getEXG2RespirationDetectFreq(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_PHASE): + returnValue = getEXG2RespirationDetectPhase(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER): + returnValue = getInternalExpPower(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.PPG_ADC_SELECTION): + returnValue = getPpgAdcSelectionGsrBoard(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.PPG1_ADC_SELECTION): + returnValue = getPpg1AdcSelectionProto3DeluxeBoard(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.PPG2_ADC_SELECTION): + returnValue = getPpg2AdcSelectionProto3DeluxeBoard(); + break; + + + case(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_GSR): + returnValue = getSamplingDividerGsr(); + break; + case(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_LSM303DLHC_ACCEL): + returnValue = getSamplingDividerLsm303dlhcAccel(); + break; + case(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_PPG): + returnValue = getSamplingDividerPpg(); + break; + case(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_VBATT): + returnValue = getSamplingDividerVBatt(); + break; + + +//Strings + case(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_USER_ASSIGNED_NAME): + returnValue = getShimmerUserAssignedName(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_NAME): + returnValue = getExperimentName(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_SAMPLING_RATE): + Double readSamplingRate = getShimmerSamplingRate(); + Double actualSamplingRate = 32768/Math.floor(32768/readSamplingRate); // get Shimmer compatible sampling rate + actualSamplingRate = (double)Math.round(actualSamplingRate * 100) / 100; // round sampling rate to two decimal places +// consolePrintLn("GET SAMPLING RATE: " + componentName); + returnValue = actualSamplingRate.toString(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.BUFFER_SIZE): + returnValue = Integer.toString(getBufferSize()); + break; + case(Configuration.Shimmer3.GuiLabelConfig.CONFIG_TIME): + returnValue = getConfigTimeParsed(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_MAC_FROM_INFOMEM): + returnValue = getMacIdFromInfoMem(); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_ID): + returnValue = Integer.toString(getExperimentId()); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_NUMBER_OF_SHIMMERS): + returnValue = Integer.toString(getExperimentNumberOfShimmers()); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_DURATION_ESTIMATED): + returnValue = Integer.toString(getExperimentDurationEstimated()); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_DURATION_MAXIMUM): + returnValue = Integer.toString(getExperimentDurationMaximum()); + break; + case(Configuration.Shimmer3.GuiLabelConfig.BROADCAST_INTERVAL): + returnValue = Integer.toString(getSyncBroadcastInterval()); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RATE): + returnValue = Double.toString((double)Math.round(getMPU9150GyroAccelRateInHz() * 100) / 100); // round sampling rate to two decimal places +// System.out.println("Gyro Sampling rate: " + getMPU9150GyroAccelRateInHz() + " " + returnValue); + + break; + default: + break; + } + + return returnValue; + } + + public Object slotDetailsSetMethods(String componentName, Object valueToSet) { + + Object returnValue = null; + int buf = 0; + + switch(componentName){ +//Booleans + case(Configuration.Shimmer3.GuiLabelConfig.KINEMATIC_LPM): + enableLowPowerAccel((boolean)valueToSet); + enableLowPowerGyro((boolean)valueToSet); + enableLowPowerMag((boolean)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_LPM): + enableLowPowerAccel((boolean)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_LPM): + this.enableLowPowerGyro((boolean)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_LPM): + enableLowPowerMag((boolean)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_BOOLEAN): + if ((boolean)valueToSet){ + writeInternalExpPower(1); + } else { + writeInternalExpPower(0); + } + break; + + +//Integers + case(Configuration.Shimmer3.GuiLabelConfig.BLUETOOTH_BAUD_RATE): + //TODO: Test + writeBaudRate((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RANGE): + writeAccelRange((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RANGE): + writeGyroRange((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RANGE): + writeMagRange((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.PRESSURE_RESOLUTION): + writePressureResolution((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.GSR_RANGE): + writeGSRRange((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION): + //writeExGResolution((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN): + + //TODO: Implementation + //consolePrintLn("before set " + getExGGain()); + //writeExGGainSetting((int)valueToSet); + //consolePrintLn("after set " + getExGGain()); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE): + writeAccelSamplingRate((int)valueToSet); + break; + + case(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RATE): + writeMagSamplingRate((int)valueToSet); + break; + //TODO: regenerate EXG register bytes on each change (just in case) + + //TODO + case(Configuration.Shimmer3.GuiLabelConfig.EXG_RATE): + writeEXGRateSetting(1,(int)valueToSet); + writeEXGRateSetting(2,(int)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_REFERENCE_ELECTRODE): + writeEXGReferenceElectrode((int)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_DETECTION): + writeEXGLeadOffDetectionMode((int)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_CURRENT): + writeEXGLeadOffDetectionCurrent((int)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_COMPARATOR): + writeEXGLeadOffComparatorTreshold((int)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER): + writeInternalExpPower((int)valueToSet); + break; + +//Strings + case(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_USER_ASSIGNED_NAME): + setShimmerName((String)valueToSet); + break; + case(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_SAMPLING_RATE): + // don't let sampling rate be empty + Double enteredSamplingRate; + if(((String)valueToSet).isEmpty()) { + enteredSamplingRate = 1.0; + } + else { + enteredSamplingRate = Double.parseDouble((String)valueToSet); + } + setShimmerSamplingRate(enteredSamplingRate); + + returnValue = Double.toString(getShimmerSamplingRate()); + break; +// case(Configuration.Shimmer3.GuiLabelConfig.BUFFER_SIZE): +// break; +// case(Configuration.Shimmer3.GuiLabelConfig.CONFIG_TIME): +// break; +// case(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_MAC_FROM_INFOMEM): +// break; + + case(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RATE): + double bufDouble = 4.0; // Minimum = 4Hz + if(((String)valueToSet).isEmpty()) { + bufDouble = 4.0; + } + else { + bufDouble = Double.parseDouble((String)valueToSet); + } + + // Since user is manually entering a freq., clear low-power mode so that their chosen rate will be set correctly. Tick box will be re-enabled automatically if they enter LPM freq. + enableLowPowerGyro(false); + setMPU9150GyroAccelRateFromFreq(bufDouble); + + returnValue = Double.toString((double)Math.round(getMPU9150GyroAccelRateInHz() * 100) / 100); // round sampling rate to two decimal places +// System.out.println("Gyro Sampling rate: " + getMPU9150GyroAccelRateInHz() + " " + returnValue); + + break; + default: + break; + } + + return returnValue; + + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/BasicProcessWithCallBack.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/BasicProcessWithCallBack.java new file mode 100644 index 00000000..1aa75a08 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/BasicProcessWithCallBack.java @@ -0,0 +1,135 @@ +package com.shimmerresearch.driver; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; + + +public abstract class BasicProcessWithCallBack { + + protected Callable mThread = null; + //protected BlockingQueue mQueue = new ArrayBlockingQueue(1024); + protected LinkedBlockingDeque mQueue = new LinkedBlockingDeque(1024); + protected ConsumerThread mGUIConsumerThread = null; + WaitForData mWaitForData = null; + List mListOfThreads = new ArrayList(); + List mListWaitForData = new ArrayList(); + public BasicProcessWithCallBack(){ + + } + + public void queueMethod(int i,Object ojc){ + try { + mQueue.put(new ShimmerMsg(i,ojc)); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /**This is a seperate thread running on the callback msgs from lower layer + * @param shimmerMSG + */ + protected abstract void processMsgFromCallback(ShimmerMsg shimmerMSG); + + + + + + public class ConsumerThread extends Thread { + public boolean stop = false; + public void run() { + while (!stop) { + try { + ShimmerMsg shimmerMSG = mQueue.take(); + processMsgFromCallback(shimmerMSG); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + System.out.print("QUE BLOCKED"); + e.printStackTrace(); + } + } + }; + + } + + + + public BasicProcessWithCallBack(BasicProcessWithCallBack b){ + mWaitForData = new WaitForData(b); + } + + public void setWaitForData(BasicProcessWithCallBack b){ + if (mGUIConsumerThread==null){ + mGUIConsumerThread = new ConsumerThread(); + mGUIConsumerThread.start(); + } + if (mWaitForData!=null){ + mListWaitForData.add(new WaitForData(b)); + } else { + mWaitForData = new WaitForData(b); + } + }; + + public void passCallback(Callable c) { + // TODO Auto-generated method stub + if (mThread!=null){ + mListOfThreads.add(c); + } else { + mThread = c; + } + } + + + public void sendCallBackMsg(ShimmerMsg s){ + if (mThread!=null){ + mThread.callBackMethod(s); + } + for (Callable c:mListOfThreads){ + c.callBackMethod(s); + } + } + + public void sendCallBackMsg(int i, Object ojc){ + if (mThread!=null){ + mThread.callBackMethod( i, ojc); + } + for (Callable c:mListOfThreads){ + c.callBackMethod(i,ojc); + } + } + + //this is for the upper layer + public class WaitForData implements com.shimmerresearch.driver.Callable + { + + public WaitForData(BasicProcessWithCallBack bpwcb) + { + bpwcb.passCallback(this); + } + + @Override + public void callBackMethod(ShimmerMsg s) { + try { + mQueue.put(s); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }} + + @Override + public void callBackMethod(int i, Object ojc) { + try { + mQueue.put(new ShimmerMsg(i,ojc)); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }} + + } + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Callable.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Callable.java new file mode 100644 index 00000000..e52f31d5 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Callable.java @@ -0,0 +1,53 @@ +//Rev0.3 + +/* + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim + * @date October, 2013 + * + * Changes since 0.2 + * - added callBackMethodQueue + * + * Changes since 0.1 + * - included object to callable + * + */ + +package com.shimmerresearch.driver; + + +public interface Callable +{ + public void callBackMethod(int i, Object ojc); + + public void callBackMethod(ShimmerMsg s); + +} \ No newline at end of file diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ChannelDetails.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ChannelDetails.java new file mode 100644 index 00000000..d55489fa --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ChannelDetails.java @@ -0,0 +1,69 @@ +package com.shimmerresearch.driver; + +import java.io.Serializable; + +/** + * Holds Channel details for parsing. Experimental feature not used currently + * in standard Shimmer operations. + * + * @author Mark Nolan + * + */ +public class ChannelDetails implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -2662151922286820989L; + + public class ChannelDataType { + public static final String UINT8 = "uint8"; + public static final String UINT12 = "uint12"; + public static final String UINT16 = "uint16"; + public static final String UINT24 = "int24"; + public static final String UINT32 = "uint32"; + public static final String INT16 = "int16"; + public static final String INT24 = "int24"; + public static final String INT32 = "int32"; + public static final String UINT64 = "uint64"; + public static final String UINT48 = "uint48"; + } + + public class ChannelDataEndian { + public static final String UNKOWN = ""; + public static final String LSB = "LSB"; + public static final String MSB = "MSB"; + } + + public String mChannelName = ""; + public String mChannelDataType = ""; + public int mNumBytes = 0; + public String mChannelDataEndian = ChannelDataEndian.UNKOWN; + + /** + * Holds Channel details for parsing. Experimental feature not used + * currently in standard Shimmer operations. + * + * @param channelName the String name to assign to the channel + * @param channelDataType the ChannelDataType of the channel + * @param numBytes the number of bytes the channel takes up in a data packet + * @param channelDataEndian the endianness of the byte order in a data packet + */ + public ChannelDetails(String channelName, String channelDataType, int numBytes, String channelDataEndian){ + mChannelName = channelName; + mChannelDataType = channelDataType; + mNumBytes = numBytes; + mChannelDataEndian = channelDataEndian; + } + + + + /** + * Empty constructor not used in standard Shimmer operations (GQ related). + * + */ + public ChannelDetails() { + // TODO Auto-generated constructor stub + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Configuration.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Configuration.java new file mode 100644 index 00000000..f38830e9 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Configuration.java @@ -0,0 +1,936 @@ +/*Rev 2.6 + * + * + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim, Ruaidhri Molloy + * @date May, 2014 + * + * The purpose of this code is to maintain the configurations of BTSTREAM + * + * + * Changes since 2.5 (RM first revision) + * - Addition of Strain Gauge for Shimmer3 + * + * Changes since 2.2 + * - Changed list of compatible sensors to public + * + */ + + +package com.shimmerresearch.driver; + +public class Configuration { + //Channel Contents + public static class Shimmer3Gq{ + public class GuiLabelConfig{ + public static final String SAMPLING_RATE_DIVIDER_VBATT = "VBATT Divider"; + public static final String SAMPLING_RATE_DIVIDER_GSR = "GSR Divider"; + public static final String SAMPLING_RATE_DIVIDER_PPG = "PPG Divider"; + public static final String SAMPLING_RATE_DIVIDER_LSM303DLHC_ACCEL = "LSM3030DLHC Divider"; + } + + public final static String[] ListofSamplingRateDividers={"0.75Hz","1.5Hz","3Hz","7.5Hz","15Hz","30Hz","75Hz","220Hz"}; + public final static Integer[] ListofSamplingRateDividersValues={0,1,2,3,4,5,6,7}; + + } + public static class CHANNEL_UNITS{ + //Sensors units + public static final String NO_UNITS = "no units"; + public static final String MILLISECONDS = "ms"; + public static final String METER_PER_SECOND_SQUARE = "m/(s^2)"; + public static final String DEGREES_PER_SECOND = "deg/s"; + public static final String LOCAL_FLUX = "local_flux"; + public static final String KOHMS = "kOhms"; + public static final String MILLIVOLTS = "mV"; + public static final String BEATS_PER_MINUTE = "BPM"; + public static final String KPASCAL = "kPa"; + public static final String DEGREES_CELSUIS = "Degrees Celsius"; + public static final String DEGREES = "Degrees"; + public static final String U_TESLA = "uT"; + public static final String DATE_FORMAT = "yyyy/mm/dd hh:mm:ss.000"; + public static final String GRAVITY = "g"; + public static final String CLOCK_UNIT = "Ticks"; + + public static final String ACCEL_CAL_UNIT = METER_PER_SECOND_SQUARE; + public static final String ACCEL_DEFAULT_CAL_UNIT = METER_PER_SECOND_SQUARE+"*"; + public static final String GYRO_CAL_UNIT = DEGREES_PER_SECOND; + public static final String GYRO_DEFAULT_CAL_UNIT = DEGREES_PER_SECOND+"*"; + public static final String MAG_CAL_UNIT = LOCAL_FLUX; + public static final String MAG_DEFAULT_CAL_UNIT = LOCAL_FLUX+"*"; + + public static final String LOCAL = "local"; //used for axis-angle and madgewick quaternions + } + + public static class CHANNEL_TYPE{ + public static final String CAL = "CAL"; + public static final String UNCAL = "UNCAL"; + public static final String RAW = "RAW"; + } + + public static class Shimmer3{ + public class Channel{ + public final static int XAAccel = 0x00; + public final static int YAAccel = 0x01; + public final static int ZAAccel = 0x02; + public final static int VBatt = 0x03; + public final static int XDAccel = 0x04; + public final static int YDAccel = 0x05; + public final static int ZDAccel = 0x06; + public final static int XMag = 0x07; + public final static int YMag = 0x08; + public final static int ZMag = 0x09; + public final static int XGyro = 0x0A; + public final static int YGyro = 0x0B; + public final static int ZGyro = 0x0C; + public final static int ExtAdc7 = 0x0D; + public final static int ExtAdc6 = 0x0E; + public final static int ExtAdc15 = 0x0F; + public final static int IntAdc1 = 0x10; + public final static int IntAdc12 = 0x11; + public final static int IntAdc13 = 0x12; + public final static int IntAdc14 = 0x13; + public final static int XAlterAccel = 0x14; //Alternative Accelerometer + public final static int YAlterAccel = 0x15; + public final static int ZAlterAccel = 0x16; + public final static int XAlterMag = 0x17; //Alternative Magnetometer + public final static int YAlterMag = 0x18; + public final static int ZAlterMag = 0x19; + public final static int Temperature = 0x1A; + public final static int Pressure = 0x1B; + public final static int GsrRaw = 0x1C; + public final static int EXG_ADS1292R_1_STATUS = 0x1D; + public final static int EXG_ADS1292R_1_CH1_24BIT = 0x1E; + public final static int EXG_ADS1292R_1_CH2_24BIT = 0x1F; + public final static int EXG_ADS1292R_2_STATUS = 0x20; + public final static int EXG_ADS1292R_2_CH1_24BIT = 0x21; + public final static int EXG_ADS1292R_2_CH2_24BIT = 0x22; + public final static int EXG_ADS1292R_1_CH1_16BIT = 0x23; + public final static int EXG_ADS1292R_1_CH2_16BIT = 0x24; + public final static int EXG_ADS1292R_2_CH1_16BIT = 0x25; + public final static int EXG_ADS1292R_2_CH2_16BIT = 0x26; + public final static int BridgeAmpHigh = 0x27; + public final static int BridgeAmpLow = 0x28; + } + + public class SensorBitmap{ + //Sensor Bitmap for Shimmer 3 + public static final int SENSOR_A_ACCEL = 0x80; + public static final int SENSOR_GYRO = 0x40; + public static final int SENSOR_MAG = 0x20; + public static final int SENSOR_EXG1_24BIT = 0x10; + public static final int SENSOR_EXG2_24BIT = 0x08; + public static final int SENSOR_GSR = 0x04; + public static final int SENSOR_EXT_A7 = 0x02; + public static final int SENSOR_EXT_A6 = 0x01; + public static final int SENSOR_VBATT = 0x2000; + public static final int SENSOR_D_ACCEL = 0x1000; + public static final int SENSOR_EXT_A15 = 0x0800; + public static final int SENSOR_INT_A1 = 0x0400; + public static final int SENSOR_INT_A12 = 0x0200; + public static final int SENSOR_INT_A13 = 0x0100; + public static final int SENSOR_INT_A14 = 0x800000; + public static final int SENSOR_BMP180 = 0x40000; + public static final int SENSOR_EXG1_16BIT = 0x100000; + public static final int SENSOR_EXG2_16BIT = 0x080000; + public static final int SENSOR_BRIDGE_AMP = 0x8000; + } + + public final static String[] ListofCompatibleSensors={"Low Noise Accelerometer","Wide Range Accelerometer","Gyroscope","Magnetometer","Battery Voltage","External ADC A7","External ADC A6","External ADC A15","Internal ADC A1","Internal ADC A12","Internal ADC A13","Internal ADC A14","Pressure","GSR","EXG1","EXG2","EXG1 16Bit","EXG2 16Bit", "Bridge Amplifier"}; + public final static String[] ListofAccelRange={"+/- 2g","+/- 4g","+/- 8g","+/- 16g"}; + public final static String[] ListofGyroRange={"+/- 250 dps","+/- 500 dps","+/- 1000 dps","+/- 2000 dps"}; + public final static String[] ListofMagRange={"+/- 1.3 Ga","+/- 1.9 Ga","+/- 2.5 Ga","+/- 4.0 Ga","+/- 4.7 Ga","+/- 5.6 Ga","+/- 8.1 Ga"}; + public final static String[] ListofPressureResolution={"Low","Standard","High","Very High"}; + public final static String[] ListofGSRRange={"10k\u2126 to 56k\u2126","56k\u2126 to 220k\u2126","220k\u2126 to 680k\u2126","680k\u2126 to 4.7M\u2126","Auto"}; + public final static String[] ListofDefaultEXG={"ECG","EMG","Test Signal"}; + public final static String[] ListOfExGGain={"6","1","2","3","4","8","12"}; + public final static String[] ListOfECGReferenceElectrode={"Inverse Wilson CT","Fixed Potential"}; + public final static String[] ListOfEMGReferenceElectrode={"Fixed Potential", "Inverse of Ch1"}; + public final static String[] ListOfExGLeadOffDetection={"Off","DC Current"}; + public final static String[] ListOfExGLeadOffCurrent={"6 nA","22 nA", "6 uA", "22 uA"}; + public final static String[] ListOfExGLeadOffComparator={"Pos:95%-Neg:5%","Pos:92.5%-Neg:7.5%","Pos:90%-Neg:10%","Pos:87.5%-Neg:12.5%","Pos:85%-Neg:15%","Pos:80%-Neg:20%","Pos:75%-Neg:25%","Pos:70%-Neg:30%"}; + public final static String[] ListofMPU9150AccelRange={"+/- 2g","+/- 4g","+/- 8g","+/- 16g"}; + public final static String[] ListofBluetoothBaudRates={"115200","1200","2400","4800","9600","19200","38400","57600","230400","460800","921600"}; + + + //TODO: From here onwards is is Mark TESTING - not finished + //TODO: check all indexes below + public final static Integer[] ListofBluetoothBaudRatesConfigValues={0,1,2,3,4,5,6,7,8,9,10}; + + public final static String[] ListofMPU9150MplCalibrationOptions={"No Cal","Fast Cal","1s no motion","2s no motion","5s no motion","10s no motion","30s no motion","60s no motion"}; + public final static String[] ListofMPU9150MplLpfOptions={"No LPF","188Hz","98Hz","42Hz","20Hz","10Hz","5Hz"}; + + // public final static String[] ListofLSM303DLHCAccelRate={"Power-down","1Hz","10Hz","25Hz","50Hz","100Hz","200Hz","400Hz","1620Hz","1344Hz","5376Hz"}; // 1620Hz and 5376Hz are only available in low-power mode, 1344Hz only available in full power mode + // public final static Integer[] ListofLSM303DLHCAccelRateConfigValues={0,1,2,3,4,5,6,7,8,9,9}; + public final static String[] ListofLSM303DLHCAccelRate={"Power-down","1Hz","10Hz","25Hz","50Hz","100Hz","200Hz","400Hz","1344Hz"}; + public final static Integer[] ListofLSM303DLHCAccelRateConfigValues={0,1,2,3,4,5,6,7,9}; + public final static String[] ListofLSM303DLHCAccelRateLpm={"Power-down","1Hz","10Hz","25Hz","50Hz","100Hz","200Hz","400Hz","1620Hz","5376Hz"}; // 1620Hz and 5376Hz are only available in low-power mode + public final static Integer[] ListofLSM303DLHCAccelRateLpmConfigValues={0,1,2,3,4,5,6,7,8,9}; + + public final static String[] ListofLSM303DLHCMagRate={"0.75Hz","1.5Hz","3Hz","7.5Hz","15Hz","30Hz","75Hz","220Hz"}; + public final static Integer[] ListofLSM303DLHCMagRateConfigValues={0,1,2,3,4,5,6,7}; + public final static String[] ListofMPU9150MplRate={"10Hz","20Hz","40Hz","50Hz","100Hz"}; + public final static Integer[] ListofMPU9150MplRateConfigValues={0,1,2,3,4}; + public final static String[] ListofMPU9150MagRate={"10Hz","20Hz","40Hz","50Hz","100Hz"}; + public final static Integer[] ListofMPU9150MagRateConfigValues={0,1,2,3,4}; + + public final static Integer[] ListofLSM303DLHCAccelRangeConfigValues={0,1,2,3}; + public final static Integer[] ListofMPU9150GyroRangeConfigValues={0,1,2,3}; + + public final static Integer[] ListofPressureResolutionConfigValues={0,1,2,3}; + public final static Integer[] ListofGSRRangeConfigValues={0,1,2,3,4}; + public final static Integer[] ListofMagRangeConfigValues={1,2,3,4,5,6,7}; // no '0' option + + public final static Integer[] ListofMPU9150AccelRangeConfigValues={0,1,2,3}; + public final static Integer[] ListofMPU9150MplCalibrationOptionsConfigValues={0,1,2,3,4,5,6,7}; + public final static Integer[] ListofMPU9150MplLpfOptionsConfigValues={0,1,2,3,4,5,6}; + + public final static Integer[] ListOfExGGainConfigValues={0,1,2,3,4,5,6}; + public final static String[] ListOfExGResolutions={"16-bit","24-bit"}; + public final static Integer[] ListOfExGResolutionsConfigValues={0,1}; + + public final static Integer[] ListOfECGReferenceElectrodeConfigValues={13,0}; + public final static Integer[] ListOfEMGReferenceElectrodeConfigValues={0,3}; + public final static Integer[] ListOfExGLeadOffDetectionConfigValues={-1,0}; + public final static Integer[] ListOfExGLeadOffCurrentConfigValues={0,1,2,3}; + public final static Integer[] ListOfExGLeadOffComparatorConfigValues={0,1,2,3,4,5,6,7}; + + public final static String[] ListOfExGRespirationDetectFreq={"32 kHz","64 kHz"}; + public final static Integer[] ListOfExGRespirationDetectFreqConfigValues={0,1}; + public final static String[] ListOfExGRespirationDetectPhase32khz={"0°","11.25°","22.5°","33.75°","45°","56.25°","67.5°","78.75°","90°","101.25°","112.5°","123.75°","135°","146.25°","157.5°","168.75°"}; + public final static Integer[] ListOfExGRespirationDetectPhase32khzConfigValues={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + public final static String[] ListOfExGRespirationDetectPhase64khz={"0°","22.5°","45°","67.5°","90°","112.5°","135°","157.5°"}; + public final static Integer[] ListOfExGRespirationDetectPhase64khzConfigValues={0,1,2,3,4,5,6,7}; + + public final static String[] ListOfExGRate={"125 Hz","250 Hz","500 Hz","1 kHz","2 kHz","4 kHz","8 kHz"}; + public final static Integer[] ListOfExGRateConfigValues={0,1,2,3,4,5,6}; + + public final static String[] ListOfOnOff={"On","Off"}; + public final static Integer[] ListOfOnOffConfigValues={0x01,0x00}; + + + public final static String[] ListOfPpgAdcSelection={"Int A13","Int A12"}; + public final static Integer[] ListOfPpgAdcSelectionConfigValues={0,1}; + public final static String[] ListOfPpg1AdcSelection={"Int A13","Int A12"}; + public final static Integer[] ListOfPpg1AdcSelectionConfigValues={0,1}; + public final static String[] ListOfPpg2AdcSelection={"Int A1","Int A14"}; + public final static Integer[] ListOfPpg2AdcSelectionConfigValues={0,1}; + + + public class SensorMapKey{ + /** + * Shimmer3 Low-noise analog accelerometer + */ + public final static int A_ACCEL = 0; + /** + * Shimmer3 Gyroscope + */ + public final static int MPU9150_GYRO = 1; + /** + * Shimmer3 Primary magnetometer + */ + public final static int LSM303DLHC_MAG = 2; + public final static int EXG1_24BIT = 3; + public final static int EXG2_24BIT = 4; + public final static int GSR = 5; + public final static int EXT_EXP_ADC_A6 = 6; + public final static int EXT_EXP_ADC_A7 = 7; + public final static int BRIDGE_AMP = 8; + public final static int RESISTANCE_AMP = 9; + //public final static int HR = 9; + public final static int VBATT = 10; + /** + * Shimmer3 Wide-range digital accelerometer + */ + public final static int LSM303DLHC_ACCEL = 11; + public final static int EXT_EXP_ADC_A15 = 12; + public final static int INT_EXP_ADC_A1 = 13; + public final static int INT_EXP_ADC_A12 = 14; + public final static int INT_EXP_ADC_A13 = 15; + public final static int INT_EXP_ADC_A14 = 16; + /** + * Shimmer3 Alternative accelerometer + */ + public final static int MPU9150_ACCEL = 17; + /** + * Shimmer3 Alternative magnetometer + */ + public final static int MPU9150_MAG = 18; + public final static int EXG1_16BIT = 19; + public final static int EXG2_16BIT = 21; + public final static int BMP180_PRESSURE = 22; + //public final static int BMP180_TEMPERATURE = 23; // not yet implemented + //public final static int MSP430_TEMPERATURE = 24; // not yet implemented + public final static int MPU9150_TEMP = 25; + //public final static int LSM303DLHC_TEMPERATURE = 26; // not yet implemented + //public final static int MPU9150_MPL_TEMPERATURE = 1<<17; // same as SENSOR_SHIMMER3_MPU9150_TEMP + public final static int MPU9150_MPL_QUAT_6DOF = 27; + public final static int MPU9150_MPL_QUAT_9DOF = 28; + public final static int MPU9150_MPL_EULER_6DOF = 29; + public final static int MPU9150_MPL_EULER_9DOF = 30; + public final static int MPU9150_MPL_HEADING = 31; + public final static int MPU9150_MPL_PEDOMETER = 32; + public final static int MPU9150_MPL_TAP = 33; + public final static int MPU9150_MPL_MOTION_ORIENT = 34; + public final static int MPU9150_MPL_GYRO = 35; + public final static int MPU9150_MPL_ACCEL = 36; + public final static int MPU9150_MPL_MAG = 37; + public final static int MPU9150_MPL_QUAT_6DOF_RAW = 38; + + // Combination Channels + public final static int ECG = 100; + public final static int EMG = 101; + public final static int EXG_TEST = 102; + + // Derived Channels + public final static int EXG_RESPIRATION = 103; + public final static int SKIN_TEMP_PROBE = 104; + + // Derived Channels - GSR Board + public final static int PPG_DUMMY = 105; + public final static int PPG_A12 = 106; + public final static int PPG_A13 = 107; + + // Derived Channels - Proto3 Deluxe Board + + public final static int PPG1_DUMMY = 110; + public final static int PPG1_A12 = 111; + public final static int PPG1_A13 = 112; + public final static int PPG2_DUMMY = 113; + public final static int PPG2_A1 = 114; + public final static int PPG2_A14 = 115; + } + + // Sensor Options Map + public class GuiLabelConfig{ + public static final String SHIMMER_USER_ASSIGNED_NAME = "Shimmer Name"; + public static final String EXPERIMENT_NAME = "Experiment Name"; + public static final String SHIMMER_SAMPLING_RATE = "Sampling Rate"; + public static final String BUFFER_SIZE = "Buffer Size"; + public static final String CONFIG_TIME = "Config Time"; + public static final String EXPERIMENT_NUMBER_OF_SHIMMERS = "Number Of Shimmers"; + public static final String SHIMMER_MAC_FROM_INFOMEM = "InfoMem MAC"; + public static final String EXPERIMENT_ID = "Experiment ID"; + public static final String EXPERIMENT_DURATION_ESTIMATED = "Estimated Duration"; + public static final String EXPERIMENT_DURATION_MAXIMUM = "Maximum Duration"; + public static final String BROADCAST_INTERVAL = "Broadcast Interval"; + public static final String BLUETOOTH_BAUD_RATE = "Bluetooth Baud Rate"; + + public static final String USER_BUTTON_START = "User Button"; + public static final String UNDOCK_START = "Undock/Dock"; + public static final String SINGLE_TOUCH_START = "Single Touch Start"; + public static final String EXPERIMENT_MASTER_SHIMMER = "Master Shimmer"; + public static final String EXPERIMENT_SYNC_WHEN_LOGGING = "Sync When Logging"; + + public static final String LSM303DLHC_ACCEL_RATE = "Wide Range Accel Rate"; + public static final String LSM303DLHC_ACCEL_RANGE = "Wide Range Accel Range"; + public static final String MPU9150_GYRO_RANGE = "Gyro Range"; + public static final String MPU9150_GYRO_RATE = "Gyro Sampling Rate"; + public static final String LSM303DLHC_MAG_RANGE = "Mag Range"; + public static final String LSM303DLHC_MAG_RATE = "Mag Rate"; + public static final String PRESSURE_RESOLUTION = "Pressure Resolution"; + public static final String GSR_RANGE = "GSR Range"; + public static final String EXG_RESOLUTION = "Resolution"; + public static final String EXG_GAIN = "Gain"; + + public static final String EXG_RATE = "Rate"; + public static final String EXG_REFERENCE_ELECTRODE = "Reference Electrode"; + public static final String EXG_LEAD_OFF_DETECTION = "Lead-Off Detection"; + public static final String EXG_LEAD_OFF_CURRENT = "Lead-Off Current"; + public static final String EXG_LEAD_OFF_COMPARATOR = "Lead-Off Compartor Threshold"; + public static final String EXG_RESPIRATION_DETECT_FREQ = "Respiration Detection Freq."; + public static final String EXG_RESPIRATION_DETECT_PHASE = "Respiration Detection Phase"; + + public static final String MPU9150_ACCEL_RANGE = "MPU Accel Range"; + public static final String MPU9150_DMP_GYRO_CAL = "MPU Gyro Cal"; + public static final String MPU9150_LPF = "MPU LPF"; + public static final String MPU9150_MPL_RATE = "MPL Rate"; + public static final String MPU9150_MAG_RATE = "MPU Mag Rate"; + + public static final String MPU9150_DMP = "DMP"; + public static final String MPU9150_MPL = "MPL"; + public static final String MPU9150_MPL_9DOF_SENSOR_FUSION = "9DOF Sensor Fusion"; + public static final String MPU9150_MPL_GYRO_CAL = "Gyro Calibration"; + public static final String MPU9150_MPL_VECTOR_CAL = "Vector Compensation Calibration"; + public static final String MPU9150_MPL_MAG_CAL = "Magnetic Disturbance Calibration"; + + public static final String KINEMATIC_LPM = "Kinematic Sensors Low-Power Mode"; + public static final String LSM303DLHC_ACCEL_LPM = "Wide Range Accel Low-Power Mode"; + public static final String MPU9150_GYRO_LPM = "Gyro Low-Power Mode"; + public static final String LSM303DLHC_MAG_LPM = "Mag Low-Power Mode"; + public static final String TCX0 = "TCX0"; + public static final String INT_EXP_BRD_POWER_BOOLEAN = "Internal Expansion Board Power"; + public static final String INT_EXP_BRD_POWER_INTEGER = "Int Exp Power"; + + public static final String PPG_ADC_SELECTION = "PPG Channel"; + public static final String PPG1_ADC_SELECTION = "PPG1 Channel"; + public static final String PPG2_ADC_SELECTION = "PPG2 Channel"; + + } + + // GUI Sensor Tiles + public class GuiLabelSensorTiles{ + public static final String LOW_NOISE_ACCEL = Configuration.Shimmer3.GuiLabelSensors.ACCEL_LN; + public static final String GYRO = Configuration.Shimmer3.GuiLabelSensors.GYRO; + public static final String MAG = Configuration.Shimmer3.GuiLabelSensors.MAG; + public static final String BATTERY_MONITORING = Configuration.Shimmer3.GuiLabelSensors.BATTERY; + public static final String WIDE_RANGE_ACCEL = Configuration.Shimmer3.GuiLabelSensors.ACCEL_WR; + public static final String PRESSURE_TEMPERATURE = Configuration.Shimmer3.GuiLabelSensors.PRESS_TEMP_BMP180; + public static final String EXTERNAL_EXPANSION_ADC = "External Expansion ADCs"; + public static final String GSR = "GSR+"; + public static final String EXG = "ECG/EMG"; + public static final String PROTO3_MINI = "Proto Mini"; + public static final String PROTO3_DELUXE = "Proto Deluxe"; + public static final String PROTO3_DELUXE_SUPP = "PPG"; + public static final String BRIDGE_AMPLIFIER = "Bridge Amplifier+"; + public static final String BRIDGE_AMPLIFIER_SUPP = Configuration.Shimmer3.GuiLabelSensors.SKIN_TEMP_PROBE; + public static final String HIGH_G_ACCEL = Configuration.Shimmer3.GuiLabelSensors.HIGH_G_ACCEL; + public static final String INTERNAL_EXPANSION_ADC = "Internal Expansion ADCs"; + //public static final String GPS = "GPS"; + } + + //GUI SENSORS + public class GuiLabelSensors{ + public static final String ACCEL_LN = "Low-Noise Accelerometer"; + public static final String BATTERY = "Battery Voltage"; + public static final String EXT_EXP_A7 = "Ext A7"; + public static final String EXT_EXP_A6 = "Ext A6"; + public static final String EXT_EXP_A15 = "Ext A15"; + public static final String INT_EXP_A12 = "Int A12"; + public static final String INT_EXP_A13 = "Int A13"; + public static final String INT_EXP_A14 = "Int A14"; + public static final String BRIDGE_AMPLIFIER = "Bridge Amp"; + public static final String GSR = "GSR"; + public static final String INT_EXP_A1 = "Int A1"; + public static final String RESISTANCE_AMP = "Resistance Amp"; + public static final String GYRO = "Gyroscope"; + public static final String ACCEL_WR = "Wide-Range Accelerometer"; + public static final String MAG = "Magnetometer"; + public static final String ACCEL_MPU = "Alternative Accel"; + public static final String MAG_MPU = "Alternative Mag"; + public static final String PRESS_TEMP_BMP180 = "Pressure & Temperature"; + public static final String EMG = "EMG"; + public static final String ECG = "ECG"; + public static final String EXG_TEST = "Test"; + public static final String EXT_EXP_ADC = "External Expansion"; + public static final String QUAT_MPL_6DOF = "MPU Quat 6DOF"; + public static final String QUAT_MPL_9DOF = "MPU Quat 9DOF"; + public static final String EULER_MPL_6DOF = "MPU Euler 6DOF"; + public static final String EULER_MPL_9DOF = "MPU Euler 9DOF"; + public static final String MPL_HEADING = "MPU Heading"; + public static final String MPL_TEMPERATURE = "MPU Temp"; + public static final String MPL_PEDOM_CNT = "MPL_Pedom_cnt"; // not currently supported + public static final String MPL_PEDOM_TIME = "MPL_Pedom_Time"; // not currently supported + public static final String MPL_TAPDIRANDTAPCNT = "TapDirAndTapCnt"; // not currently supported + public static final String MPL_MOTIONANDORIENT = "MotionAndOrient"; // not currently supported + public static final String GYRO_MPU_MPL = "MPU Gyro"; + public static final String ACCEL_MPU_MPL = "MPU Accel"; + public static final String MAG_MPU_MPL = "MPU Mag"; + public static final String QUAT_DMP_6DOF = "MPU Quat 6DOF (from DMP)"; + public static final String ECG_TO_HR = "ECG To HR"; + public static final String PPG_TO_HR = "PPG To HR"; + public static final String ORIENTATION_3D_6DOF = "3D Orientation (6DOF)"; + public static final String ORIENTATION_3D_9DOF = "3D Orientation (9DOF)"; + public static final String EULER_ANGLES_6DOF = "Euler Angles (6DOF)"; + public static final String EULER_ANGLES_9DOF = "Euler Angles (9DOF)"; + + public static final String HIGH_G_ACCEL = "200g Accel"; + + public static final String PPG_DUMMY = "PPG"; + public static final String PPG_A12 = "PPG A12"; + public static final String PPG_A13 = "PPG A13"; + public static final String PPG1_DUMMY = "PPG1"; + public static final String PPG1_A12 = "PPG1 A12"; + public static final String PPG1_A13 = "PPG1 A13"; + public static final String PPG2_DUMMY = "PPG2"; + public static final String PPG2_A1 = "PPG2 A1"; + public static final String PPG2_A14 = "PPG2 A14"; + public static final String EXG_RESPIRATION = "Respiration"; + public static final String SKIN_TEMP_PROBE = "Temperature Probe"; + public static final String BRAMP_HIGHGAIN = "High Gain"; + public static final String BRAMP_LOWGAIN = "Low Gain"; + + public static final String EXG1_24BIT = "EXG1 24BIT"; + public static final String EXG2_24BIT = "EXG2 24BIT"; + public static final String EXG1_16BIT = "EXG1 16BIT"; + public static final String EXG2_16BIT = "EXG2 16BIT"; + } + + //DATABASE NAMES + //GUI AND EXPORT CHANNELS + public static class ObjectClusterSensorName{ + public static String TIMESTAMP = "Timestamp"; + public static String REAL_TIME_CLOCK = "RealTime"; + public static String ACCEL_LN_X = "Accel_LN_X"; + public static String ACCEL_LN_Y = "Accel_LN_Y"; + public static String ACCEL_LN_Z = "Accel_LN_Z"; + public static String BATTERY = "Battery"; + public static String EXT_EXP_A7 = "Ext_Exp_A7"; + public static String EXT_EXP_A6 = "Ext_Exp_A6"; + public static String EXT_EXP_A15 = "Ext_Exp_A15"; + public static String INT_EXP_A12 = "Int_Exp_A12"; + public static String INT_EXP_A13 = "Int_Exp_A13"; + public static String INT_EXP_A14 = "Int_Exp_A14"; + public static String BRIDGE_AMP_HIGH = "Bridge_Amp_High"; + public static String BRIDGE_AMP_LOW = "Bridge_Amp_Low"; + public static String GSR = "GSR"; + public static String GSR_CONDUCTANCE = "GSR_Conductance"; + public static String INT_EXP_A1 = "Int_Exp_A1"; + public static String RESISTANCE_AMP = "Resistance_Amp"; + public static String GYRO_X = "Gyro_X"; + public static String GYRO_Y = "Gyro_Y"; + public static String GYRO_Z = "Gyro_Z"; + public static String ACCEL_WR_X = "Accel_WR_X"; + public static String ACCEL_WR_Y = "Accel_WR_Y"; + public static String ACCEL_WR_Z= "Accel_WR_Z"; + public static String MAG_X = "Mag_X"; + public static String MAG_Y = "Mag_Y"; + public static String MAG_Z = "Mag_Z"; + public static String ACCEL_MPU_X = "Accel_MPU_X"; + public static String ACCEL_MPU_Y = "Accel_MPU_Y"; + public static String ACCEL_MPU_Z = "Accel_MPU_Z"; + public static String MAG_MPU_X = "Mag_MPU_X"; + public static String MAG_MPU_Y = "Mag_MPU_Y"; + public static String MAG_MPU_Z = "Mag_MPU_Z"; + public static String TEMPERATURE_BMP180 = "Temperature_BMP180"; + public static String PRESSURE_BMP180 = "Pressure_BMP180"; + public static String EMG_CH1_24BIT = "EMG_CH1_24BIT"; + public static String EMG_CH2_24BIT = "EMG_CH2_24BIT"; + public static String EMG_CH1_16BIT = "EMG_CH1_16BIT"; + public static String EMG_CH2_16BIT = "EMG_CH2_16BIT"; + public static String ECG_LL_RA_24BIT = "ECG_LL-RA_24BIT"; + public static String ECG_LA_RA_24BIT = "ECG_LA-RA_24BIT"; + public static String ECG_LL_RA_16BIT = "ECG_LL-RA_16BIT"; + public static String ECG_LA_RA_16BIT = "ECG_LA-RA_16BIT"; + public static String TEST_CHIP1_CH1_24BIT = "Test_CHIP1_CH1_24BIT"; + public static String TEST_CHIP1_CH2_24BIT = "Test_CHIP1_CH2_24BIT"; + public static String TEST_CHIP2_CH1_24BIT = "Test_CHIP2_CH1_24BIT"; + public static String TEST_CHIP2_CH2_24BIT = "Test_CHIP2_CH2_24BIT"; + public static String TEST_CHIP1_CH1_16BIT = "Test_CHIP1_CH1_16BIT"; + public static String TEST_CHIP1_CH2_16BIT = "Test_CHIP1_CH2_16BIT"; + public static String TEST_CHIP2_CH1_16BIT = "Test_CHIP2_CH1_16BIT"; + public static String TEST_CHIP2_CH2_16BIT = "Test_CHIP2_CH2_16BIT"; + public static String EXG1_STATUS = "ECG_EMG_Status1"; + public static String ECG_RESP_24BIT = "ECG_RESP_24BIT"; + public static String ECG_VX_RL_24BIT = "ECG_Vx-RL_24BIT"; + public static String ECG_RESP_16BIT = "ECG_RESP_16BIT"; + public static String ECG_VX_RL_16BIT = "ECG_Vx-RL_16BIT"; + public static String EXG1_CH1_24BIT = "ExG1_CH1_24BIT"; + public static String EXG1_CH2_24BIT = "ExG1_CH2_24BIT"; + public static String EXG1_CH1_16BIT = "ExG1_CH1_16BIT"; + public static String EXG1_CH2_16BIT = "ExG1_CH2_16BIT"; + public static String EXG2_CH1_24BIT = "ExG2_CH1_24BIT"; + public static String EXG2_CH2_24BIT = "ExG2_CH2_24BIT"; + public static String EXG2_CH1_16BIT = "ExG2_CH1_16BIT"; + public static String EXG2_CH2_16BIT = "ExG2_CH2_16BIT"; + public static String EXG2_STATUS = "ECG_EMG_Status2"; + public static String QUAT_MPL_6DOF_W = "Quat_MPL_6DOF_W"; + public static String QUAT_MPL_6DOF_X = "Quat_MPL_6DOF_X"; + public static String QUAT_MPL_6DOF_Y = "Quat_MPL_6DOF_Y"; + public static String QUAT_MPL_6DOF_Z = "Quat_MPL_6DOF_Z"; + public static String QUAT_MPL_9DOF_W = "Quat_MPL_9DOF_W"; + public static String QUAT_MPL_9DOF_X = "Quat_MPL_9DOF_X"; + public static String QUAT_MPL_9DOF_Y = "Quat_MPL_9DOF_Y"; + public static String QUAT_MPL_9DOF_Z = "Quat_MPL_9DOF_Z"; + public static String EULER_MPL_6DOF_X = "Euler_MPL_6DOF_X"; + public static String EULER_MPL_6DOF_Y = "Euler_MPL_6DOF_Y"; + public static String EULER_MPL_6DOF_Z = "Euler_MPL_6DOF_Z"; + public static String EULER_MPL_9DOF_X = "Euler_MPL_9DOF_X"; + public static String EULER_MPL_9DOF_Y = "Euler_MPL_9DOF_Y"; + public static String EULER_MPL_9DOF_Z = "Euler_MPL_9DOF_Z"; + public static String MPL_HEADING = "MPL_heading"; + public static String MPL_TEMPERATURE = "MPL_Temperature"; + public static String MPL_PEDOM_CNT = "MPL_Pedom_cnt"; + public static String MPL_PEDOM_TIME = "MPL_Pedom_Time"; + public static String TAPDIRANDTAPCNT = "TapDirAndTapCnt"; + public static String MOTIONANDORIENT = "MotionAndOrient"; + public static String GYRO_MPU_MPL_X = "Gyro_MPU_MPL_X"; + public static String GYRO_MPU_MPL_Y = "Gyro_MPU_MPL_Y"; + public static String GYRO_MPU_MPL_Z = "Gyro_MPU_MPL_Z"; + public static String ACCEL_MPU_MPL_X = "Accel_MPU_MPL_X"; + public static String ACCEL_MPU_MPL_Y = "Accel_MPU_MPL_Y"; + public static String ACCEL_MPU_MPL_Z = "Accel_MPU_MPL_Z"; + public static String MAG_MPU_MPL_X = "Mag_MPU_MPL_X"; + public static String MAG_MPU_MPL_Y = "Mag_MPU_MPL_Y"; + public static String MAG_MPU_MPL_Z = "Mag_MPU_MPL_Z"; + public static String QUAT_DMP_6DOF_W = "Quat_DMP_6DOF_W"; + public static String QUAT_DMP_6DOF_X = "Quat_DMP_6DOF_X"; + public static String QUAT_DMP_6DOF_Y = "Quat_DMP_6DOF_Y"; + public static String QUAT_DMP_6DOF_Z = "Quat_DMP_6DOF_Z"; + public static String ECG_TO_HR = "ECGtoHR"; + public static String PPG_TO_HR = "PPGtoHR"; + public static String QUAT_MADGE_6DOF_W = "Quat_Madge_6DOF_W"; + public static String QUAT_MADGE_6DOF_X = "Quat_Madge_6DOF_X"; + public static String QUAT_MADGE_6DOF_Y = "Quat_Madge_6DOF_Y"; + public static String QUAT_MADGE_6DOF_Z = "Quat_Madge_6DOF_Z"; + public static String QUAT_MADGE_9DOF_W = "Quat_Madge_9DOF_W"; + public static String QUAT_MADGE_9DOF_X = "Quat_Madge_9DOF_X"; + public static String QUAT_MADGE_9DOF_Y = "Quat_Madge_9DOF_Y"; + public static String QUAT_MADGE_9DOF_Z = "Quat_Madge_9DOF_Z"; + public static String EULER_6DOF_A = "Euler_6DOF_A"; + public static String EULER_6DOF_X = "Euler_6DOF_X"; + public static String EULER_6DOF_Y = "Euler_6DOF_Y"; + public static String EULER_6DOF_Z = "Euler_6DOF_Z"; + public static String EULER_9DOF_A = "Euler_9DOF_A"; + public static String EULER_9DOF_X = "Euler_9DOF_X"; + public static String EULER_9DOF_Y = "Euler_9DOF_Y"; + public static String EULER_9DOF_Z = "Euler_9DOF_Z"; + public static String AXIS_ANGLE_A = "Axis_Angle_A"; + public static String AXIS_ANGLE_X = "Axis_Angle_X"; + public static String AXIS_ANGLE_Y = "Axis_Angle_Y"; + public static String AXIS_ANGLE_Z = "Axis_Angle_Z"; + public static String PPG_A12 = "PPG_A12"; + public static String PPG_A13 = "PPG_A13"; + public static String PPG1_A12 = "PPG1_A12"; + public static String PPG1_A13 = "PPG1_A13"; + public static String PPG2_A1 = "PPG2_A1"; + public static String PPG2_A14 = "PPG2_A14"; + public static String REAL_TIME_CLOCK_SYNC = "RealTime_Sync"; + public static String TIMESTAMP_SYNC = "Timestamp_Sync"; + } + + + + //Names used for parsing the GQ configuration header file + public class HeaderFileSensorName{ + public static final String SHIMMER3 = "shimmer3"; + public static final String VBATT = "VBATT"; + public static final String GSR = "GSR"; + public static final String LSM303DLHC_ACCEL = "LSM303DLHC_ACCEL"; + } + } + + + + public static class Shimmer2{ + public class Channel{ + public final static int XAccel = 0x00; + public final static int YAccel = 0x01; + public final static int ZAccel = 0x02; + public final static int XGyro = 0x03; + public final static int YGyro = 0x04; + public final static int ZGyro = 0x05; + public final static int XMag = 0x06; + public final static int YMag = 0x07; + public final static int ZMag = 0x08; + public final static int EcgRaLl = 0x09; + public final static int EcgLaLl = 0x0A; + public final static int GsrRaw = 0x0B; + public final static int GsrRes = 0x0C; + public final static int Emg = 0x0D; + public final static int AnExA0 = 0x0E; + public final static int AnExA7 = 0x0F; + public final static int BridgeAmpHigh = 0x10; + public final static int BridgeAmpLow = 0x11; + public final static int HeartRate = 0x12; + } + public class SensorBitmap{ + public static final int SENSOR_ACCEL = 0x80; + public static final int SENSOR_GYRO = 0x40; + public static final int SENSOR_MAG = 0x20; + public static final int SENSOR_ECG = 0x10; + public static final int SENSOR_EMG = 0x08; + public static final int SENSOR_GSR = 0x04; + public static final int SENSOR_EXP_BOARD_A7 = 0x02; + public static final int SENSOR_EXP_BOARD_A0 = 0x01; + public static final int SENSOR_BRIDGE_AMP = 0x8000; + public static final int SENSOR_HEART = 0x4000; + } + + //DATABASE NAMES + //GUI AND EXPORT CHANNELS + public static class ObjectClusterSensorName{ + public static String TIMESTAMP = "Timestamp"; + public static String REAL_TIME_CLOCK = "RealTime"; + public static String ACCEL_X = "Accel_X"; + public static String ACCEL_Y = "Accel_Y"; + public static String ACCEL_Z = "Accel_Z"; + public static String BATTERY = "Battery"; + public static String REG = "Reg"; + public static String EXT_EXP_A7 = "Ext_Exp_A7"; + public static String EXT_EXP_A6 = "Ext_Exp_A6"; + public static String EXT_EXP_A15 = "Ext_Exp_A15"; + public static String INT_EXP_A12 = "Int_Exp_A12"; + public static String INT_EXP_A13 = "Int_Exp_A13"; + public static String INT_EXP_A14 = "Int_Exp_A14"; + public static String BRIDGE_AMP_HIGH = "Bridge_Amp_High"; + public static String BRIDGE_AMP_LOW = "Bridge_Amp_Low"; + public static String GSR = "GSR"; + //public static String GSR_RAW = "GSR Raw"; + public static String GSR_RES = "GSR Res"; + public static String INT_EXP_A1 = "Int_Exp_A1"; + public static String EXP_BOARD_A0 = "Exp_Board_A0"; + public static String EXP_BOARD_A7 = "Exp_Board_A7"; + public static String GYRO_X = "Gyro_X"; + public static String GYRO_Y = "Gyro_Y"; + public static String GYRO_Z = "Gyro_Z"; + public static String MAG_X = "Mag_X"; + public static String MAG_Y = "Mag_Y"; + public static String MAG_Z = "Mag_Z"; + public static String EMG = "EMG"; + public static String ECG_RA_LL = "ECG_RA-LL"; + public static String ECG_LA_LL = "ECG_LA-LL"; + public static String ECG_TO_HR = "ECGtoHR"; + public static String QUAT_MADGE_6DOF_W = "Quat_Madge_6DOF_W"; + public static String QUAT_MADGE_6DOF_X = "Quat_Madge_6DOF_X"; + public static String QUAT_MADGE_6DOF_Y = "Quat_Madge_6DOF_Y"; + public static String QUAT_MADGE_6DOF_Z = "Quat_Madge_6DOF_Z"; + public static String QUAT_MADGE_9DOF_W = "Quat_Madge_9DOF_W"; + public static String QUAT_MADGE_9DOF_X = "Quat_Madge_9DOF_X"; + public static String QUAT_MADGE_9DOF_Y = "Quat_Madge_9DOF_Y"; + public static String QUAT_MADGE_9DOF_Z = "Quat_Madge_9DOF_Z"; + public static String EULER_6DOF_A = "Euler_6DOF_A"; + public static String EULER_6DOF_X = "Euler_6DOF_X"; + public static String EULER_6DOF_Y = "Euler_6DOF_Y"; + public static String EULER_6DOF_Z = "Euler_6DOF_Z"; + public static String EULER_9DOF_A = "Euler_9DOF_A"; + public static String EULER_9DOF_X = "Euler_9DOF_X"; + public static String EULER_9DOF_Y = "Euler_9DOF_Y"; + public static String EULER_9DOF_Z = "Euler_9DOF_Z"; + public static String HEART_RATE = "Heart_Rate"; //for the heart rate strap now no longer sold + public static String AXIS_ANGLE_A = "Axis_Angle_A"; + public static String AXIS_ANGLE_X = "Axis_Angle_X"; + public static String AXIS_ANGLE_Y = "Axis_Angle_Y"; + public static String AXIS_ANGLE_Z = "Axis_Angle_Z"; + public static String VOLT_REG = "VSenseReg"; + } + + public final static String[] ListofCompatibleSensors={"Accelerometer","Gyroscope","Magnetometer","Battery Voltage","ECG","EMG","GSR","Exp Board","Bridge Amplifier","Heart Rate"}; + public final static String[] ListofAccelRange={"+/- 1.5g","+/- 6g"}; + public final static String[] ListofMagRange={"+/- 0.8Ga","+/- 1.3Ga","+/- 1.9Ga","+/- 2.5Ga","+/- 4.0Ga","+/- 4.7Ga","+/- 5.6Ga","+/- 8.1Ga"}; + public final static String[] ListofGSRRange={"10kOhm to 56kOhm","56kOhm to 220kOhm","220kOhm to 680kOhm","680kOhm to 4.7MOhm","Auto Range"}; + + public class SensorMapKey{ + public final static int ACCEL = 0; + public final static int GYRO = 1; + public final static int MAG = 2; + public final static int EMG = 3; + public final static int ECG = 4; + public final static int GSR = 5; + public final static int EXP_BOARD_A7 = 6; + public final static int EXP_BOARD_A0 = 7; + public final static int EXP_BOARD = 8; + public final static int BRIDGE_AMP = 9; + public final static int HEART = 10; + public final static int BATT = 11; + public final static int EXT_ADC_A15 = 12; + public final static int INT_ADC_A1 = 13; + public final static int INT_ADC_A12 = 14; + public final static int INT_ADC_A13 = 15; + public final static int INT_ADC_A14 = 16; + } + } + + + public static void setTooLegacyObjectClusterSensorNames(){ + + Shimmer3.ObjectClusterSensorName.TIMESTAMP = "Timestamp"; + Shimmer3.ObjectClusterSensorName.REAL_TIME_CLOCK = "RealTime"; + Shimmer3.ObjectClusterSensorName.ACCEL_LN_X = "Low Noise Accelerometer X"; + Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y = "Low Noise Accelerometer Y"; + Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z = "Low Noise Accelerometer Z"; + Shimmer3.ObjectClusterSensorName.BATTERY = "VSenseBatt"; + Shimmer3.ObjectClusterSensorName.EXT_EXP_A7 = "ExpBoard A7"; + Shimmer3.ObjectClusterSensorName.EXT_EXP_A6 = "ExpBoard A6"; + Shimmer3.ObjectClusterSensorName.EXT_EXP_A15 = "External ADC A15"; + Shimmer3.ObjectClusterSensorName.INT_EXP_A12 = "Internal ADC A12"; + Shimmer3.ObjectClusterSensorName.INT_EXP_A13 = "Internal ADC A13"; + Shimmer3.ObjectClusterSensorName.INT_EXP_A14 = "Internal ADC A14"; + Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH = "Bridge Amplifier High"; + Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW = "Bridge Amplifier Low"; + Shimmer3.ObjectClusterSensorName.GSR = "GSR"; + Shimmer3.ObjectClusterSensorName.INT_EXP_A1 = "Internal ADC A1"; + Shimmer3.ObjectClusterSensorName.RESISTANCE_AMP = "Resistance Amp"; + Shimmer3.ObjectClusterSensorName.GYRO_X = "Gyroscope X"; + Shimmer3.ObjectClusterSensorName.GYRO_Y = "Gyroscope Y"; + Shimmer3.ObjectClusterSensorName.GYRO_Z = "Gyroscope Z"; + Shimmer3.ObjectClusterSensorName.ACCEL_WR_X = "Wide Range Accelerometer X"; + Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y = "Wide Range Accelerometer Y"; + Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z= "Wide Range Accelerometer Z"; + Shimmer3.ObjectClusterSensorName.MAG_X = "Magnetometer X"; + Shimmer3.ObjectClusterSensorName.MAG_Y = "Magnetometer Y"; + Shimmer3.ObjectClusterSensorName.MAG_Z = "Magnetometer Z"; + Shimmer3.ObjectClusterSensorName.ACCEL_MPU_X = "Accel_MPU_X"; + Shimmer3.ObjectClusterSensorName.ACCEL_MPU_Y = "Accel_MPU_Y"; + Shimmer3.ObjectClusterSensorName.ACCEL_MPU_Z = "Accel_MPU_Z"; + Shimmer3.ObjectClusterSensorName.MAG_MPU_X = "Mag_MPU_X"; + Shimmer3.ObjectClusterSensorName.MAG_MPU_Y = "Mag_MPU_Y"; + Shimmer3.ObjectClusterSensorName.MAG_MPU_Z = "Mag_MPU_Z"; + Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180 = "Temperature"; + Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180 = "Pressure"; + Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT = "EMG CH1"; + Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT = "EMG CH2"; + Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT = "EMG CH1"; + Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT = "EMG CH2"; + Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT = "ECG LL-RA"; + Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT = "ECG LA-RA"; + Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT = "ECG LL-RA"; + Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT = "ECG LA-RA"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP1_CH1_24BIT = "EXG1 CH1"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP2_CH1_24BIT = "EXG1 CH1"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP1_CH2_24BIT = "EXG1 CH2"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP2_CH2_24BIT = "EXG1 CH2"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP1_CH1_16BIT = "EXG1 CH1 16BIT"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP2_CH1_16BIT = "EXG1 CH1 16BIT"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP1_CH2_16BIT = "EXG1 CH2 16BIT"; + Shimmer3.ObjectClusterSensorName.TEST_CHIP2_CH2_16BIT = "EXG1 CH2 16BIT"; + Shimmer3.ObjectClusterSensorName.EXG1_STATUS = "EXG1 Status"; + Shimmer3.ObjectClusterSensorName.ECG_RESP_24BIT = "ECG RESP"; + Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT = "ECG Vx-RL"; + Shimmer3.ObjectClusterSensorName.ECG_RESP_16BIT = "ECG RESP"; + Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT = "ECG Vx-RL"; + Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT = "ExG1 CH1"; + Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT = "ExG1 CH2"; + Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT = "ExG1 CH1 16Bit"; + Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT = "ExG1 CH2 16Bit"; + Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT = "ExG2 CH1"; + Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT = "ExG2 CH2"; + Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT = "ExG2 CH1 16Bit"; + Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT = "ExG2 CH2 16Bit"; + Shimmer3.ObjectClusterSensorName.EXG2_STATUS = "EXG2 Status"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_W = "Quat_MPL_6DOF_W"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_X = "Quat_MPL_6DOF_X"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_Y = "Quat_MPL_6DOF_Y"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_Z = "Quat_MPL_6DOF_Z"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_W = "Quat_MPL_9DOF_W"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_X = "Quat_MPL_9DOF_X"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_Y = "Quat_MPL_9DOF_Y"; + Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_Z = "Quat_MPL_9DOF_Z"; + Shimmer3.ObjectClusterSensorName.EULER_MPL_6DOF_X = "Euler_MPL_6DOF_X"; + Shimmer3.ObjectClusterSensorName.EULER_MPL_6DOF_Y = "Euler_MPL_6DOF_Y"; + Shimmer3.ObjectClusterSensorName.EULER_MPL_6DOF_Z = "Euler_MPL_6DOF_Z"; + Shimmer3.ObjectClusterSensorName.EULER_MPL_9DOF_X = "Euler_MPL_9DOF_X"; + Shimmer3.ObjectClusterSensorName.EULER_MPL_9DOF_Y = "Euler_MPL_9DOF_Y"; + Shimmer3.ObjectClusterSensorName.EULER_MPL_9DOF_Z = "Euler_MPL_9DOF_Z"; + Shimmer3.ObjectClusterSensorName.MPL_HEADING = "MPL_heading"; + Shimmer3.ObjectClusterSensorName.MPL_TEMPERATURE = "MPL_Temperature"; + Shimmer3.ObjectClusterSensorName.MPL_PEDOM_CNT = "MPL_Pedom_cnt"; + Shimmer3.ObjectClusterSensorName.MPL_PEDOM_TIME = "MPL_Pedom_Time"; + Shimmer3.ObjectClusterSensorName.TAPDIRANDTAPCNT = "TapDirAndTapCnt"; + Shimmer3.ObjectClusterSensorName.MOTIONANDORIENT = "MotionAndOrient"; + Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_X = "Gyro_MPU_MPL_X"; + Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_Y = "Gyro_MPU_MPL_Y"; + Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_Z = "Gyro_MPU_MPL_Z"; + Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_X = "Accel_MPU_MPL_X"; + Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Y = "Accel_MPU_MPL_Y"; + Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Z = "Accel_MPU_MPL_Z"; + Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_X = "Mag_MPU_MPL_X"; + Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_Y = "Mag_MPU_MPL_Y"; + Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_Z = "Mag_MPU_MPL_Z"; + Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_W = "Quat_DMP_6DOF_W"; + Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_X = "Quat_DMP_6DOF_X"; + Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_Y = "Quat_DMP_6DOF_Y"; + Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_Z = "Quat_DMP_6DOF_Z"; + Shimmer3.ObjectClusterSensorName.ECG_TO_HR = "ECGtoHR"; + Shimmer3.ObjectClusterSensorName.PPG_TO_HR = "PPGtoHR"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_6DOF_W = "Quaternion 0"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_6DOF_X = "Quaternion 1"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_6DOF_Y = "Quaternion 2"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_6DOF_Z = "Quaternion 3"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_W = "Quaternion 0"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_X = "Quaternion 1"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y = "Quaternion 2"; + Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z = "Quaternion 3"; + Shimmer3.ObjectClusterSensorName.EULER_6DOF_A = "Euler_6DOF_A"; + Shimmer3.ObjectClusterSensorName.EULER_6DOF_X = "Euler_6DOF_X"; + Shimmer3.ObjectClusterSensorName.EULER_6DOF_Y = "Euler_6DOF_Y"; + Shimmer3.ObjectClusterSensorName.EULER_6DOF_Z = "Euler_6DOF_Z"; + Shimmer3.ObjectClusterSensorName.EULER_9DOF_A = "Euler_9DOF_A"; + Shimmer3.ObjectClusterSensorName.EULER_9DOF_X = "Euler_9DOF_X"; + Shimmer3.ObjectClusterSensorName.EULER_9DOF_Y = "Euler_9DOF_Y"; + Shimmer3.ObjectClusterSensorName.EULER_9DOF_Z = "Euler_9DOF_Z"; + Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_A = "Axis Angle A"; + Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_X = "Axis Angle X"; + Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Y = "Axis Angle Y"; + Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Z = "Axis Angle Z"; + Shimmer3.ObjectClusterSensorName.PPG_A12 = "PPG_A12"; + Shimmer3.ObjectClusterSensorName.PPG_A13 = "PPG_A13"; + Shimmer3.ObjectClusterSensorName.PPG1_A12 = "PPG1_A12"; + Shimmer3.ObjectClusterSensorName.PPG1_A13 = "PPG1_A13"; + Shimmer3.ObjectClusterSensorName.PPG2_A1 = "PPG2_A1"; + Shimmer3.ObjectClusterSensorName.PPG2_A14 = "PPG2_A14"; + Shimmer3.ObjectClusterSensorName.REAL_TIME_CLOCK_SYNC = "RealTime_Sync"; + Shimmer3.ObjectClusterSensorName.TIMESTAMP_SYNC = "Timestamp_Sync"; + + + Shimmer2.ObjectClusterSensorName.TIMESTAMP = "Timestamp"; + Shimmer2.ObjectClusterSensorName.REAL_TIME_CLOCK = "RealTime"; + Shimmer2.ObjectClusterSensorName.ACCEL_X = "Accelerometer X"; + Shimmer2.ObjectClusterSensorName.ACCEL_Y = "Accelerometer Y"; + Shimmer2.ObjectClusterSensorName.ACCEL_Z = "Accelerometer Z"; + Shimmer2.ObjectClusterSensorName.BATTERY = "VSenseBatt"; + Shimmer2.ObjectClusterSensorName.VOLT_REG = "VSenseReg"; + Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH = "Bridge Amplifier High"; + Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW = "Bridge Amplifier Low"; + Shimmer2.ObjectClusterSensorName.GSR = "GSR"; + //Shimmer2.ObjectClusterSensorName.GSR_RAW = "GSR Raw"; + Shimmer2.ObjectClusterSensorName.GSR_RES = "GSR Res"; + Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0 = "ExpBoard A0"; + Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7 = "ExpBoard A7"; + Shimmer2.ObjectClusterSensorName.GYRO_X = "Gyroscope X"; + Shimmer2.ObjectClusterSensorName.GYRO_Y = "Gyroscope Y"; + Shimmer2.ObjectClusterSensorName.GYRO_Z = "Gyroscope Z"; + Shimmer2.ObjectClusterSensorName.MAG_X = "Magnetometer X"; + Shimmer2.ObjectClusterSensorName.MAG_Y = "Magnetometer Y"; + Shimmer2.ObjectClusterSensorName.MAG_Z = "Magnetometer Z"; + Shimmer2.ObjectClusterSensorName.EMG = "EMG"; + Shimmer2.ObjectClusterSensorName.ECG_RA_LL = "ECG RA-LL"; + Shimmer2.ObjectClusterSensorName.ECG_LA_LL = "ECG LA-LL"; + Shimmer2.ObjectClusterSensorName.ECG_TO_HR = "ECGtoHR"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_6DOF_W = "Quaternion 0"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_6DOF_X = "Quaternion 1"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_6DOF_Y = "Quaternion 2"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_6DOF_Z = "Quaternion 3"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_W = "Quaternion 0"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_X = "Quaternion 1"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y = "Quaternion 2"; + Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z = "Quaternion 3"; + Shimmer2.ObjectClusterSensorName.EULER_6DOF_A = "Euler_6DOF_A"; + Shimmer2.ObjectClusterSensorName.EULER_6DOF_X = "Euler_6DOF_X"; + Shimmer2.ObjectClusterSensorName.EULER_6DOF_Y = "Euler_6DOF_Y"; + Shimmer2.ObjectClusterSensorName.EULER_6DOF_Z = "Euler_6DOF_Z"; + Shimmer2.ObjectClusterSensorName.EULER_9DOF_A = "Euler_9DOF_A"; + Shimmer2.ObjectClusterSensorName.EULER_9DOF_X = "Euler_9DOF_X"; + Shimmer2.ObjectClusterSensorName.EULER_9DOF_Y = "Euler_9DOF_Y"; + Shimmer2.ObjectClusterSensorName.EULER_9DOF_Z = "Euler_9DOF_Z"; + Shimmer2.ObjectClusterSensorName.HEART_RATE = "Heart_Rate"; //for the heart rate strap now no longer sold + Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_A = "Axis Angle A"; + Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_X = "Axis Angle X"; + Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Y = "Axis Angle Y"; + Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Z = "Axis Angle Z"; + + + + + } + +} + + diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ExpansionBoardDetails.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ExpansionBoardDetails.java new file mode 100644 index 00000000..1853687c --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ExpansionBoardDetails.java @@ -0,0 +1,64 @@ +package com.shimmerresearch.driver; + +import com.shimmerresearch.driver.ShimmerVerDetails; + +/** + * Holds the Shimmer's Expansion board information as read from the memory chip + * on the Shimmers expansion board. + * + * @author Mark Nolan + * + */ +public class ExpansionBoardDetails { + + public int mExpBoardId = -1; + public int mExpBoardRev = -1; + public int mExpBoardSpecialRev = -1; + public String mExpBoardParsed = ""; + public String mExpBoardParsedWithVer = ""; + + public ExpansionBoardDetails( + int boardID, + int boardRev, + int specialRev) { + parseExpansionBoardDetails(boardID, boardRev, specialRev); + } + + public ExpansionBoardDetails(byte[] mExpBoardArray) { + if(mExpBoardArray!=null){ + int boardID = mExpBoardArray[0] & 0xFF; + int boardRev = mExpBoardArray[1] & 0xFF; + int specialRev = mExpBoardArray[2] & 0xFF; + parseExpansionBoardDetails(boardID, boardRev, specialRev); + } + } + + private void parseExpansionBoardDetails(int boardID, + int boardRev, + int specialRev) { + String boardName = ""; + String boardNameWithVer = ""; + + if(boardID==ShimmerVerDetails.EXP_BRD_NONE_ID){ + boardName = ShimmerVerDetails.EXP_BRD_NONE; + } + else { + if(ShimmerVerDetails.mMapOfShimmmerHardware.containsKey(boardID)){ + boardName = ShimmerVerDetails.mMapOfShimmmerHardware.get(boardID); + } + else { + boardName="Unknown"; + } + } + + boardNameWithVer = boardName; + if((!boardName.equals("Unknown"))&&(!boardName.equals("None"))){ + boardNameWithVer += " (SR" + boardID + "." + boardRev + "." + specialRev +")"; + } + mExpBoardId = boardID; + mExpBoardRev = boardRev; + mExpBoardSpecialRev = specialRev; + mExpBoardParsed = boardName; + mExpBoardParsedWithVer = boardNameWithVer; + } +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/FormatCluster.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/FormatCluster.java new file mode 100644 index 00000000..24ab06d9 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/FormatCluster.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim + * @date October, 2013 + */ +package com.shimmerresearch.driver; + +import java.io.Serializable; + + +public class FormatCluster implements Serializable{ + /** + * + */ + private static final long serialVersionUID = -5291610942413655763L; + public String mFormat; + public String mUnits; + public double mData; + + public FormatCluster(String format,String units, double data){ + mFormat = format; + mUnits = units; + mData = data; + } + + public FormatCluster(String format,String units){ + mFormat = format; + mUnits = units; + } + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/InfoMemLayout.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/InfoMemLayout.java new file mode 100644 index 00000000..9b3b2fdf --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/InfoMemLayout.java @@ -0,0 +1,501 @@ +package com.shimmerresearch.driver; + +import com.shimmerresearch.driver.ShimmerVerDetails.FW_ID; + +/** + * Hold the Shimmer3's microcontroller information memory layout. This region of + * the the microcontrollers RAM can be used to configure all properties of the + * Shimmer when configured through a docking station using Consensys. Variables + * stored in this class are based on firmware header files for mapping which + * bits in each information memory byte represents various configurable settings + * on the Shimmer. + * + * @author Mark Nolan + * + */ +public class InfoMemLayout { + + public byte[] invalidMacId = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; + public int maxNumOfExperimentNodes = 21; + + int mFirmwareIdentifier = -1; + int mFirmwareVersionMajor = -1; + int mFirmwareVersionMinor = -1; + int mFirmwareVersionInternal = -1; + int mInfoMemSize = 512; + +// //SENSORS0 +// public int SENSOR_A_ACCEL = 0x80; +// public int SENSOR_MPU9150_GYRO = 0x40; +// public int SENSOR_LSM303DLHC_MAG = 0x20; +// public int SENSOR_EXG1_24BIT = 0x10; +// public int SENSOR_EXG2_24BIT = 0x08; +// public int SENSOR_GSR = 0x04; +// public int SENSOR_EXT_A7 = 0x02; +// public int SENSOR_EXT_A6 = 0x01; +// //SENSORS1 +// public int SENSOR_STRAIN = 0x80; //higher priority than SENSOR_INT_A13 and SENSOR_INT_A14 +// public int SENSOR_VBATT = 0x20; +// public int SENSOR_LSM303DLHC_ACCEL = 0x10; +// public int SENSOR_EXT_A15 = 0x08; +// public int SENSOR_INT_A1 = 0x04; +// public int SENSOR_INT_A12 = 0x02; +// public int SENSOR_INT_A13 = 0x01; +// //SENORS2 +// public int SENSOR_INT_A14 = 0x80; +// public int SENSOR_MPU9150_ACCEL = 0x40; +// public int SENSOR_MPU9150_MAG = 0x20; +// public int SENSOR_EXG1_16BIT = 0x10; +// public int SENSOR_EXG2_16BIT = 0x08; +// public int SENSOR_BMP180_PRESSURE = 0x04; +// public int SENSOR_MPU9150_TEMP = 0x02; +// +// //SENSORS3 +// public int SENSOR_MPU9150_MPL_QUAT_6DOF = 0x80; +// public int SENSOR_MPU9150_MPL_QUAT_9DOF = 0x40; +// public int SENSOR_MPU9150_MPL_EULER_6DOF = 0x20; +// public int SENSOR_MPU9150_MPL_EULER_9DOF = 0x10; +// public int SENSOR_MPU9150_MPL_HEADING = 0x08; +// public int SENSOR_MPU9150_MPL_PEDOMETER = 0x04; +// public int SENSOR_MPU9150_MPL_TAP = 0x02; +// public int SENSOR_MPU9150_MPL_MOTION_ORIENT = 0x01; +// +// //SENSORS4 +// public int SENSOR_MPU9150_GYRO_CAL = 0x80; +// public int SENSOR_MPU9150_ACCEL_CAL = 0x40; +// public int SENSOR_MPU9150_MAG_CAL = 0x20; +// public int SENSOR_MPU9150_MPL_QUAT_6DOF_RAW = 0x10; +// +// //public int SENSOR_LSM303DLHC_TEMPERATURE = 0x08; +// //public int SENSOR_MSP430_TEMPERATURE = 0x01; +// //public int SENSOR_BMP180_TEMPERATURE = 0x02; +// //public int SENSOR_EXP_POWER = 0x01; +// //public int SENSOR_MPU9150_MPL_ROT_MAT = 0x; + + public int idxShimmerSamplingRate = 0; + public int idxBufferSize = 2; + public int idxSensors0 = 3; + public int idxSensors1 = 4; + public int idxSensors2 = 5; + public int idxConfigSetupByte0 = 6; //sensors setting bytes + public int idxConfigSetupByte1 = 7; + public int idxConfigSetupByte2 = 8; + public int idxConfigSetupByte3 = 9; + public int idxEXGADS1292RChip1Config1 = 10;// exg bytes, not implemented yet + public int idxEXGADS1292RChip1Config2 = 11; + public int idxEXGADS1292RChip1LOff = 12; + public int idxEXGADS1292RChip1Ch1Set = 13; + public int idxEXGADS1292RChip1Ch2Set = 14; + public int idxEXGADS1292RChip1RldSens = 15; + public int idxEXGADS1292RChip1LOffSens = 16; + public int idxEXGADS1292RChip1LOffStat = 17; + public int idxEXGADS1292RChip1Resp1 = 18; + public int idxEXGADS1292RChip1Resp2 = 19; + public int idxEXGADS1292RChip2Config1 = 20; + public int idxEXGADS1292RChip2Config2 = 21; + public int idxEXGADS1292RChip2LOff = 22; + public int idxEXGADS1292RChip2Ch1Set = 23; + public int idxEXGADS1292RChip2Ch2Set = 24; + public int idxEXGADS1292RChip2RldSens = 25; + public int idxEXGADS1292RChip2LOffSens = 26; + public int idxEXGADS1292RChip2LOffStat = 27; + public int idxEXGADS1292RChip2Resp1 = 28; + public int idxEXGADS1292RChip2Resp2 = 29; + public int idxBtCommBaudRate = 30; + public int idxAnalogAccelCalibration = 31; + public int idxMPU9150GyroCalibration = 52; + public int idxLSM303DLHCMagCalibration = 73; + public int idxLSM303DLHCAccelCalibration = 94; //94->114 + + // Derived Channels - used by SW not FW + public int idxDerivedSensors0 = 0; + public int idxDerivedSensors1 = 0; + public int idxDerivedSensors2 = 0; + + public int idxConfigSetupByte4 = 128+0; + public int idxConfigSetupByte5 = 128+1; + public int idxSensors3 = 128+2; + public int idxSensors4 = 128+3; + public int idxConfigSetupByte6 = 128+4; + public int idxMPLAccelCalibration = 128+5; //+21 + public int idxMPLMagCalibration = 128+26; //+21 + public int idxMPLGyroCalibration = 128+47; //+12 + public int idxSDShimmerName = 128+59; // +12 bytes + public int idxSDEXPIDName = 128+71; // +12 bytes + public int idxSDConfigTime0 = 128+83; // +4 bytes + public int idxSDConfigTime1 = 128+84; + public int idxSDConfigTime2 = 128+85; + public int idxSDConfigTime3 = 128+86; + public int idxSDMyTrialID = 128+87; // 1 byte + public int idxSDNumOfShimmers = 128+88; // 1 byte + public int idxSDExperimentConfig0 = 128+89; + public int idxSDExperimentConfig1 = 128+90; + public int idxSDBTInterval = 128+91; + public int idxEstimatedExpLengthMsb = 128+92; // 2bytes + public int idxEstimatedExpLengthLsb = 128+93; + public int idxMaxExpLengthMsb = 128+94; // 2bytes + public int idxMaxExpLengthLsb = 128+95; + public int idxMacAddress = 128+96; // 6bytes + public int idxSDConfigDelayFlag = 128+102; + + public int idxNode0 = 128+128+0; + + + // Masks and Bitshift values + public int maskShimmerSamplingRate = 0xFF; + public int maskBufferSize = 0xFF; + + // Sensors + public int maskSensors = 0xFF; + public int byteShiftSensors0 = 0; + public int byteShiftSensors1 = 8; + public int byteShiftSensors2 = 16; + + //Config Byte0 + public int bitShiftLSM303DLHCAccelSamplingRate = 4; + public int maskLSM303DLHCAccelSamplingRate = 0x0F; + public int bitShiftLSM303DLHCAccelRange = 2; + public int maskLSM303DLHCAccelRange = 0x03; + + public int bitShiftLSM303DLHCAccelLPM = 1; + public int maskLSM303DLHCAccelLPM = 0x01; + + public int bitShiftLSM303DLHCAccelHRM = 0; // HIGH_RESOLUTION_MODE + public int maskLSM303DLHCAccelHRM = 0x01; // HIGH_RESOLUTION_MODE + + //Config Byte1 + public int bitShiftMPU9150AccelGyroSamplingRate = 0; + public int maskMPU9150AccelGyroSamplingRate = 0xFF; + + //Config Byte2 + public int bitShiftLSM303DLHCMagRange = 5; + public int maskLSM303DLHCMagRange = 0x07; + public int bitShiftLSM303DLHCMagSamplingRate = 2; + public int maskLSM303DLHCMagSamplingRate = 0x07; + public int bitShiftMPU9150GyroRange = 0; + public int maskMPU9150GyroRange = 0x03; + //Config Byte3 + public int bitShiftMPU9150AccelRange = 6; + public int maskMPU9150AccelRange = 0x03; + public int bitShiftBMP180PressureResolution = 4; + public int maskBMP180PressureResolution = 0x03; + public int bitShiftGSRRange = 1; + public int maskGSRRange = 0x07; + public int bitShiftEXPPowerEnable = 0; + public int maskEXPPowerEnable = 0x01; + //Unused bits 3-0 + + // Derived Channels - used by SW not FW + public int maskDerivedChannelsByte = 0xFF; + public int byteShiftDerivedSensors0 = 0; + public int byteShiftDerivedSensors1 = 8; + public int byteShiftDerivedSensors2 = 16; + +// public int maskDerivedChannel = 0x01; +// public int bitShiftDerivedChannelResAmp = 0; +// public int bitShiftDerivedChannelSkinTemp = 1; +// public int bitShiftDerivedChannelPpg_ADC12ADC13 = 2; +// public int bitShiftDerivedChannelPpg1_ADC12ADC13 = 3; +// public int bitShiftDerivedChannelPpg2_ADC1ADC14 = 4; +// public int bitShiftDerivedChannelPpgToHr = 5; +// public int bitShiftDerivedChannelEcgToHr = 6; +// public int bitShiftDerivedChannel6DofMadgewick = 8; +// public int bitShiftDerivedChannel9DofMadgewick = 9; + + public int maskDerivedChannelResAmp = 0x000001; + public int maskDerivedChannelSkinTemp = 0x000002; + public int maskDerivedChannelPpg_ADC12ADC13 = 0x000004; + public int maskDerivedChannelPpg1_ADC12ADC13 = 0x000008; + public int maskDerivedChannelPpg2_ADC1ADC14 = 0x000010; + public int maskDerivedChannelPpgToHr = 0x000020; + public int maskDerivedChannelEcgToHr = 0x000040; + + public int maskDerivedChannel6DofMadgewick = 0x000100; + public int maskDerivedChannel9DofMadgewick = 0x000200; + + + // ExG related config bytes + public int idxEXGADS1292RConfig1 = 0; + public int idxEXGADS1292RConfig2 = 1; + public int idxEXGADS1292RLOff = 2; + public int idxEXGADS1292RCH1Set = 3; + public int idxEXGADS1292RCH2Set = 4; + public int idxEXGADS1292RRLDSens = 5; + public int idxEXGADS1292RLOffSens = 6; + public int idxEXGADS1292RLOffStat = 7; + public int idxEXGADS1292RResp1 = 8; + public int idxEXGADS1292RResp2 = 9; + +// public int bitShiftEXGRateSetting = 0; +// public int maskEXGRateSetting = 0x07; +// +// public int bitShiftEXGGainSetting = 4; +// public int maskEXGGainSetting = 0x07; +// +// public int bitShiftEXGReferenceElectrode = 0; +// public int maskEXGReferenceElectrode = 0x07; + + public int maskBaudRate = 0xFF; + + public int lengthGeneralCalibrationBytes = 21; + + public int lengthShimmerName = 12; + public int lengthExperimentName = 12; + + public int lengthConfigTimeBytes = 4; + + // MPL related + public int bitShiftMPU9150DMP = 7; + public int maskMPU9150DMP = 0x01; + + public int bitShiftMPU9150LPF = 3; + public int maskMPU9150LPF = 0x07; + + public int bitShiftMPU9150MotCalCfg = 0; + public int maskMPU9150MotCalCfg = 0x07; + + public int bitShiftMPU9150MPLSamplingRate = 5; + public int maskMPU9150MPLSamplingRate = 0x07; + + public int bitShiftMPU9150MagSamplingRate = 2; + public int maskMPU9150MagSamplingRate = 0x07; + + public int bitShiftSensors3 = 24; + public int bitShiftSensors4 = 32; + + public int bitShiftMPLSensorFusion = 7; + public int maskMPLSensorFusion = 0x01; + + public int bitShiftMPLGyroCalTC = 6; + public int maskMPLGyroCalTC = 0x01; + + public int bitShiftMPLVectCompCal = 5; + public int maskMPLVectCompCal = 0x01; + + public int bitShiftMPLMagDistCal = 4; + public int maskMPLMagDistCal = 0x01; + + public int bitShiftMPLEnable = 3; + public int maskMPLEnable = 0x01; + + // SD logging related + public int bitShiftButtonStart = 5; + public int maskButtonStart = 0x01; + + public int bitShiftTimeSyncWhenLogging = 2; + public int maskTimeSyncWhenLogging = 0x01; + + public int bitShiftMasterShimmer = 1; + public int maskTimeMasterShimmer = 0x01; + + public int bitShiftSingleTouch = 7; + public int maskTimeSingleTouch = 0x01; + + public int bitShiftTCX0 = 4; + public int maskTimeTCX0 = 0x01; + + public int lengthMacIdBytes = 6; + + public int bitShiftSDConfigTime0 = 24; + public int bitShiftSDConfigTime1 = 16; + public int bitShiftSDConfigTime2 = 8; + public int bitShiftSDConfigTime3 = 0; + + + public int bitShiftSDCfgFileWriteFlag = 0; + public int maskSDCfgFileWriteFlag = 0x01; + public int bitShiftSDCalibFileWriteFlag = 1; + public int maskSDCalibFileWriteFlag = 0x01; + + + // //ADC initialisation mask +// public int MASK_A_ACCEL = 0x0001; +// public int MASK_VBATT = 0x0002; +// public int MASK_EXT_A7 = 0x0004; +// public int MASK_EXT_A6 = 0x0008; +// public int MASK_EXT_A15 = 0x0010; +// public int MASK_INT_A1 = 0x0020; +// public int MASK_GSR = 0x0020; //uses ADC1 +// public int MASK_INT_A12 = 0x0040; +// public int MASK_INT_A13 = 0x0080; +// public int MASK_INT_A14 = 0x0100; +// public int MASK_STRAIN = 0x0180; //uses ADC13 and ADC14 +// //public int MASK_MSP_TEMP = 0x0200; +// +// //LSM303DLHC Accel Range +// //Corresponds to the FS field of the LSM303DLHC's CTRL_REG4_A register +// //and the AFS_SEL field of the MPU9150's ACCEL_CONFIG register +// public int ACCEL_2G = 0x00; +// public int ACCEL_4G = 0x01; +// public int ACCEL_8G = 0x02; +// public int ACCEL_16G = 0x03; +// +// //LSM303DLHC Accel Sampling Rate +// //Corresponds to the ODR field of the LSM303DLHC's CTRL_REG1_A register +// public int LSM303DLHC_ACCEL_POWER_DOWN = 0x00; +// public int LSM303DLHC_ACCEL_1HZ = 0x01; +// public int LSM303DLHC_ACCEL_10HZ = 0x02; +// public int LSM303DLHC_ACCEL_25HZ = 0x03; +// public int LSM303DLHC_ACCEL_50HZ = 0x04; +// public int LSM303DLHC_ACCEL_100HZ = 0x05; +// public int LSM303DLHC_ACCEL_200HZ = 0x06; +// public int LSM303DLHC_ACCEL_400HZ = 0x07; +// public int LSM303DLHC_ACCEL_1_620KHZ = 0x08; //1.620kHz in Low-power mode only +// public int LSM303DLHC_ACCEL_1_344KHZ = 0x09; //1.344kHz in normal mode, 5.376kHz in low-power mode +// +// //LSM303DLHC Mag gain +// public int LSM303DLHC_MAG_1_3G = 0x01; //+/-1.3 Gauss +// public int LSM303DLHC_MAG_1_9G = 0x02; //+/-1.9 Gauss +// public int LSM303DLHC_MAG_2_5G = 0x03; //+/-2.5 Gauss +// public int LSM303DLHC_MAG_4_0G = 0x04; //+/-4.0 Gauss +// public int LSM303DLHC_MAG_4_7G = 0x05; //+/-4.7 Gauss +// public int LSM303DLHC_MAG_5_6G = 0x06; //+/-5.6 Gauss +// public int LSM303DLHC_MAG_8_1G = 0x07; //+/-8.1 Gauss +// +// //LSM303DLHC Mag sampling rate +// public int LSM303DLHC_MAG_0_75HZ = 0x00; //0.75 Hz +// public int LSM303DLHC_MAG_1_5HZ = 0x01; //1.5 Hz +// public int LSM303DLHC_MAG_3HZ = 0x02; //3.0 Hz +// public int LSM303DLHC_MAG_7_5HZ = 0x03; //7.5 Hz +// public int LSM303DLHC_MAG_15HZ = 0x04; //15 Hz +// public int LSM303DLHC_MAG_30HZ = 0x05; //30 Hz +// public int LSM303DLHC_MAG_75HZ = 0x06; //75 Hz +// public int LSM303DLHC_MAG_220HZ = 0x07; //220 Hz +// +// +// //calibration info +// public int S_ACCEL = 0; +// public int S_GYRO = 1; +// public int S_MAG = 2; +// public int S_ACCEL_A = 3; +// public int S_MPL_ACCEL = 4; +// public int S_MPL_MAG = 5; +// public int S_MPL_GYRO = 6; +// //public int S_ECG = 3; +// //public int S_EMG = 4; +// +// //MPU9150 Gyro range +// public int MPU9150_GYRO_250DPS = 0x00; //+/-250 dps +// public int MPU9150_GYRO_500DPS = 0x01; //+/-500 dps +// public int MPU9150_GYRO_1000DPS = 0x02; //+/-1000 dps +// public int MPU9150_GYRO_2000DPS = 0x03; //+/-2000 dps +// +// //#digital accel_range +// public int RANGE_2G = 0; +// public int RANGE_4G = 1; +// public int RANGE_8G = 2; +// public int RANGE_16G = 3; +// +// //#mag_gain +// public int LSM303_MAG_13GA = 1; +// public int LSM303_MAG_19GA = 2; +// public int LSM303_MAG_25GA = 3; +// public int LSM303_MAG_40GA = 4; +// public int LSM303_MAG_47GA = 5; +// public int LSM303_MAG_56GA = 6; +// public int LSM303_MAG_81GA = 7; +// +// // MPU Low Pass filter cut-off +// public int MPU9150_LPF_256HZ_NOLPF2 = 0x00; +// public int MPU9150_LPF_188HZ = 0x01; +// public int MPU9150_LPF_98HZ = 0x02; +// public int MPU9150_LPF_42HZ = 0x03; +// public int MPU9150_LPF_20HZ = 0x04; +// public int MPU9150_LPF_10HZ = 0x05; +// public int MPU9150_LPF_5HZ = 0x06; +// public int MPU9150_LPF_2500HZ_NOLPF = 0x07; +// +// // On-the-fly gyro calibration settings +// public int MPL_MOT_CAL_OFF = 0x00; +// public int MPL_MOT_CAL_FAST_NO_MOT = 0x01; +// public int MPL_MOT_CAL_MOT_NO_MOT_1S = 0x02; +// public int MPL_MOT_CAL_MOT_NO_MOT_2S = 0x03; +// public int MPL_MOT_CAL_MOT_NO_MOT_5S = 0x04; +// public int MPL_MOT_CAL_MOT_NO_MOT_10S = 0x05; +// public int MPL_MOT_CAL_MOT_NO_MOT_30S = 0x06; +// public int MPL_MOT_CAL_MOT_NO_MOT_60S = 0x07; +// +// public int MPL_RATE_10HZ = 0x00; +// public int MPL_RATE_20HZ = 0x01; +// public int MPL_RATE_40HZ = 0x02; +// public int MPL_RATE_50HZ = 0x03; +// public int MPL_RATE_100HZ = 0x04; +// //public int MPL_RATE_200HZ = 0x05; +// +// //Pansenti 9DOF MagMix +// public int GYRO_ONLY = 0x00; +// public int MAG_ONLY = 0x01; +// public int GYRO_AND_MAG = 0x02; +// public int GYRO_AND_SOME_MAG = 0x03; + + + /** + * Hold the Shimmer3's microcontroller information memory layout. This + * region of the the microcontrollers RAM can be used to configure all + * properties of the Shimmer when configured through a docking station using + * Consensys. Variables stored in this class are based on firmware header + * files for mapping which bits in each information memory byte represents + * various configurable settings on the Shimmer. + * + * @param firmwareIdentifier + * @param firmwareVersionMajor + * @param firmwareVersionMinor + * @param firmwareVersionInternal + */ + public InfoMemLayout(int firmwareIdentifier, int firmwareVersionMajor, int firmwareVersionMinor, int firmwareVersionInternal) { + mFirmwareIdentifier = firmwareIdentifier; + mFirmwareVersionMajor = firmwareVersionMajor; + mFirmwareVersionMinor = firmwareVersionMinor; + mFirmwareVersionInternal = firmwareVersionInternal; + + mInfoMemSize = calculateInfoMemByteLength(mFirmwareIdentifier,mFirmwareVersionMajor,mFirmwareVersionMinor,mFirmwareVersionInternal); + + //Include changes to mapping below in order of oldest to newest in + //seperate "if statements" + + if((Util.compareVersions(mFirmwareIdentifier,mFirmwareVersionMajor,mFirmwareVersionMinor,mFirmwareVersionInternal,FW_ID.SHIMMER3.SDLOG,0,8,42)) + ||(Util.compareVersions(mFirmwareIdentifier,mFirmwareVersionMajor,mFirmwareVersionMinor,mFirmwareVersionInternal,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,4))) { + idxSensors3 = 128+0; + idxSensors4 = 128+1; + idxConfigSetupByte4 = 128+2; + idxConfigSetupByte5 = 128+3; + idxConfigSetupByte6 = 128+4; + idxDerivedSensors0 = 115; + idxDerivedSensors1 = 116; + idxDerivedSensors2 = 117; + } + + if((Util.compareVersions(mFirmwareIdentifier,mFirmwareVersionMajor,mFirmwareVersionMinor,mFirmwareVersionInternal,FW_ID.SHIMMER3.SDLOG,0,8,68)) + ||(Util.compareVersions(mFirmwareIdentifier,mFirmwareVersionMajor,mFirmwareVersionMinor,mFirmwareVersionInternal,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,17)) + ||(Util.compareVersions(mFirmwareIdentifier,mFirmwareVersionMajor,mFirmwareVersionMinor,mFirmwareVersionInternal,FW_ID.SHIMMER3.BTSTREAM,0,6,0))) { + idxDerivedSensors0 = 31; + idxDerivedSensors1 = 32; + idxDerivedSensors2 = 33; + idxAnalogAccelCalibration = 34; + idxMPU9150GyroCalibration = 55; + idxLSM303DLHCMagCalibration = 76; + idxLSM303DLHCAccelCalibration = 97; + } + + } + + public int calculateInfoMemByteLength(int mFirmwareIdentifier, int mFirmwareVersionMajor, int mFirmwareVersionMinor, int mFirmwareVersionRelease) { + //TODO: should add full FW version checking here to support different size InfoMems in the future + if(mFirmwareIdentifier == FW_ID.SHIMMER3.SDLOG) { + return 384; + } + else if(mFirmwareIdentifier == FW_ID.SHIMMER3.BTSTREAM) { + return 128; + } + else if(mFirmwareIdentifier == FW_ID.SHIMMER3.LOGANDSTREAM) { + return 384; + } + else if(mFirmwareIdentifier == FW_ID.SHIMMER3.GQ_GSR) { + return 128; + } + else { + return 512; + } + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ObjectCluster.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ObjectCluster.java new file mode 100644 index 00000000..ff66d01b --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ObjectCluster.java @@ -0,0 +1,190 @@ +/*Rev 0.3 + * + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim + * @date October, 2013 + * + * Changes since 0.2 + * - SDLog support + * + * Changes since 0.1 + * - Added method to remove a format + * + */ +package com.shimmerresearch.driver; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; + +final public class ObjectCluster implements Cloneable,Serializable{ + /** + * + */ + private static final long serialVersionUID = -7601464501144773539L; + public Multimap mPropertyCluster = HashMultimap.create(); + public String mMyName; + public String mBluetoothAddress; + public byte[] mRawData; + public double[] mUncalData; + public double[] mCalData; + public String[] mSensorNames; + public String[] mUnitCal; + public String[] mUnitUncal; + + + String[] mSensorFormats; + String[] mSensorUnits; + + + public byte[] mSystemTimeStamp = new byte[8]; + + public ObjectCluster(){ + } + + public ObjectCluster(String myName){ + mMyName = myName; + } + + public ObjectCluster(String myName, String myBlueAdd){ + mMyName = myName; + mBluetoothAddress=myBlueAdd; + } + + /** + * Takes in a collection of Format Clusters and returns the Format Cluster specified by the string format + * @param collectionFormatCluster + * @param format + * @return FormatCluster + */ + public static FormatCluster returnFormatCluster(Collection collectionFormatCluster, String format){ + Iterator iFormatCluster=collectionFormatCluster.iterator(); + FormatCluster formatCluster; + FormatCluster returnFormatCluster = null; + + while(iFormatCluster.hasNext()){ + formatCluster=(FormatCluster)iFormatCluster.next(); + if (formatCluster.mFormat.equals(format)){ + returnFormatCluster=formatCluster; + } + } + return returnFormatCluster; + } + + /** + * Users should note that a property has to be removed before it is replaced + * @param propertyname Property name you want to delete + * @param formatname Format you want to delete + */ + public void removePropertyFormat(String propertyname, String formatname){ + Collection colFormats = mPropertyCluster.get(propertyname); // first retrieve all the possible formats for the current sensor device + FormatCluster formatCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(colFormats,formatname)); // retrieve format; + mPropertyCluster.remove(propertyname, formatCluster); + } + + /**Serializes the object cluster into an array of bytes + * @return byte[] an array of bytes + * @see java.io.Serializable + */ + public byte[] serialize() { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(this); + return baos.toByteArray(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + private List getListofEnabledSensorSignalsandFormats(){ + List listofSignals = new ArrayList(); + for (int i=0;i generateArrayOfChannels(){ + //First retrieve all the unique keys from the objectClusterLog + Multimap m = mPropertyCluster; + + int size = m.size(); + System.out.print(size); + mSensorNames=new String[size]; + mSensorFormats=new String[size]; + mSensorUnits=new String[size]; + int i=0; + int p=0; + for(String key : m.keys()) { + //first check that there are no repeat entries + + if(compareStringArray(mSensorNames, key) == true) { + for(FormatCluster formatCluster : m.get(key)) { + mSensorFormats[p]=formatCluster.mFormat; + mSensorUnits[p]=formatCluster.mUnits; + //Log.d("Shimmer",key + " " + mSensorFormats[p] + " " + mSensorUnits[p]); + p++; + } + + } + + mSensorNames[i]=key; + i++; + } + return getListofEnabledSensorSignalsandFormats(); + } + + private boolean compareStringArray(String[] stringArray, String string){ + boolean uniqueString=true; + int size = stringArray.length; + for (int i=0;i mCompatibleVersionInfo = null; + + /** + * Used in Consensys to hold Shimmer configuration GUI information for + * each configuration option to allow for dynamic GUI creation based on + * compatible HW&FW version checking. + * + * This constructor = ComboBox (compatible with all HW, FW and Expansion Boards) + * + * @param guiValues array of configuration values to show in the GUI + * @param configValues bit/bytes values written to the Shimmer corresponding to the shown GUI options. + * @param guiComponentType + */ + public SensorConfigOptionDetails(String[] guiValues, Integer[] configValues, GUI_COMPONENT_TYPE guiComponentType) { + mGuiValues = guiValues; + mConfigValues = configValues; + mGuiComponentType = guiComponentType; + + mCompatibleVersionInfo = null; + } + + /** + * Used in Consensys to hold Shimmer configuration GUI information for + * each configuration option to allow for dynamic GUI creation based on + * compatible HW&FW version checking. + * + * This constructor = ComboBox (with compatible HW, FW, and Expansion Board information) + * + * @param guiValues + * @param configValues + * @param guiComponentType + */ + public SensorConfigOptionDetails(String[] guiValues, Integer[] configValues, GUI_COMPONENT_TYPE guiComponentType, List compatibleVersionInfo) { + mGuiValues = guiValues; + mConfigValues = configValues; + mGuiComponentType = guiComponentType; + + mCompatibleVersionInfo = compatibleVersionInfo; + } + + + /** + * Used in Consensys to hold Shimmer configuration GUI information for + * each configuration option to allow for dynamic GUI creation based on + * compatible HW&FW version checking. + * + * This constructor = CheckBox (compatible with all HW, FW and Expansion Boards) + * + * @param guiValues + * @param configValues + * @param guiComponentType + */ + public SensorConfigOptionDetails(GUI_COMPONENT_TYPE guiComponentType) { + mGuiComponentType = guiComponentType; + + mCompatibleVersionInfo = null; + } + + /** + * Used in Consensys to hold Shimmer configuration GUI information for + * each configuration option to allow for dynamic GUI creation based on + * compatible HW&FW version checking. + * + * This constructor = CheckBox (with compatible HW, FW, and Expansion Board information) + * + * @param guiValues + * @param configValues + * @param guiComponentType + */ + public SensorConfigOptionDetails(GUI_COMPONENT_TYPE guiComponentType, List compatibleVersionInfo) { + mGuiComponentType = guiComponentType; + + mCompatibleVersionInfo = compatibleVersionInfo; + } + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/SensorDetails.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/SensorDetails.java new file mode 100644 index 00000000..061ada7d --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/SensorDetails.java @@ -0,0 +1,105 @@ +package com.shimmerresearch.driver; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; + +/** + * Holds all information related individual sensor channels for dynamic GUI and + * configuration purposes. Currently used in Consensys only. + * + * @author Mark Nolan + * + */ +public class SensorDetails implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4567211941610864326L; + + /** + * Indicates if sensors channel is enabled. + */ + public boolean mIsEnabled = false; + /** + * Used for the BtStream and LogAndStream firmware to indicate enabled sensors when connected over Bluetooth. + */ + public long mSensorBitmapIDStreaming = 0; + /** + * Used in the configuration header in RAW data logged to the Shimmer's on-board SD-card. + */ + public long mSensorBitmapIDSDLogHeader = 0; + + public long mDerivedSensorBitmapID = 0; + + public String mLabel = ""; + public List mListOfSensorMapKeysRequired = null; + public List mListOfSensorMapKeysConflicting = null; + public boolean mIntExpBoardPowerRequired = false; + public List mListOfConfigOptionKeysAssociated = null; + public List mListOfCompatibleVersionInfo = null; + + //Testing for GQ + public String mHeaderFileLabel = ""; + public int mHeaderByteMask = 0; + public int mNumChannels = 0; + //public LinkedHashMap mMapOfChannels = new LinkedHashMap(); + public List mListOfChannels = new ArrayList(); + + /** + * Holds all information related individual sensor channels for dynamic GUI + * and configuration purposes. Currently used in Consensys only. + * + * This constructor is used for standard Shimmer3 firmware (SDLog, + * LogAndStream and BtStream) + * + * @param isChannelEnabled + * @param sensorBitmapIDStreaming + * @param sensorBitmapIDSDLogHeader + * @param label + */ + public SensorDetails(boolean isChannelEnabled, long sensorBitmapIDStreaming, long sensorBitmapIDSDLogHeader, String label) { + mIsEnabled = isChannelEnabled; + mSensorBitmapIDStreaming = sensorBitmapIDStreaming; + mSensorBitmapIDSDLogHeader = sensorBitmapIDSDLogHeader; + mLabel = label; + mIntExpBoardPowerRequired = false; + mListOfCompatibleVersionInfo = null; + } + + /** + * Holds all information related individual sensor channels for dynamic GUI + * and configuration purposes. Currently used in Consensys only. + * + * This constructor is used for Shimmer3 GQ firmware + * + * @param isChannelEnabled + * @param label + */ + public SensorDetails(boolean isChannelEnabled, String label) { + mIsEnabled = isChannelEnabled; + mLabel = label; + mIntExpBoardPowerRequired = false; + mListOfCompatibleVersionInfo = null; + } + + public void setEnabledState(boolean state) { + mIsEnabled = state; + } + + public boolean isDerivedChannel() { + if(mDerivedSensorBitmapID>0) { + return true; + } + return false; + } + + public void resetMapKeyLists() { + mListOfSensorMapKeysRequired = null; + mListOfSensorMapKeysConflicting = null; + mListOfConfigOptionKeysAssociated = null; + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/SensorTileDetails.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/SensorTileDetails.java new file mode 100644 index 00000000..4f30394d --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/SensorTileDetails.java @@ -0,0 +1,54 @@ +package com.shimmerresearch.driver; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Holds all information related the sensor 'tiles' used in Consensys for + * dynamic GUI and configuration purposes. + * + * @author Mark Nolan + * + */ +public class SensorTileDetails implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4373658361698230203L; + /** + * Indicates if sensors channel is enabled. + */ + public boolean mIsEnabled = false; + + public List mListOfSensorMapKeysAssociated = null; + public List mListOfConfigOptionKeysAssociated = new ArrayList(); + + public List mListOfCompatibleVersionInfo = null; + + /** + * Holds all information related the sensor 'tiles' used in Consensys for + * dynamic GUI and configuration purposes. + * + * @param listOfChannelMapKeysAssociated + */ + public SensorTileDetails(List listOfChannelMapKeysAssociated) { + mListOfSensorMapKeysAssociated = listOfChannelMapKeysAssociated; + mListOfCompatibleVersionInfo = null; + } + + /** + * Holds all information related the sensor 'tiles' used in Consensys for + * dynamic GUI and configuration purposes. + * + * @param listOfChannelMapKeysAssociated + * @param listOfCompatibleVersionInfo + */ + public SensorTileDetails(List listOfChannelMapKeysAssociated, List listOfCompatibleVersionInfo) { + mListOfSensorMapKeysAssociated = listOfChannelMapKeysAssociated; + mListOfCompatibleVersionInfo = listOfCompatibleVersionInfo; + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerBattStatusDetails.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerBattStatusDetails.java new file mode 100644 index 00000000..9eca119a --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerBattStatusDetails.java @@ -0,0 +1,102 @@ +package com.shimmerresearch.driver; + +/** + * Holds the Shimmer's Battery charging information (state, voltage and + * percentage charge) received from communication with the Shimmer's UART. + * + * @author Mark Nolan + * + */ +public class ShimmerBattStatusDetails { + public int mChargingStatus; + public String mChargingStatusParsed; + public int mBattAdcValue; + public String mBattVoltage; + public String mEstimatedChargePercentage; + + public ShimmerBattStatusDetails() { + } + + public ShimmerBattStatusDetails(int battAdcValue, int chargeStatus) { + boolean adcVoltageError = false; + + mBattAdcValue = battAdcValue; + mChargingStatus = chargeStatus; + + // Calibration method copied from + // com.shimmerresearch.driver.ShimmerObject.calibrateU12AdcValue + double calibratedData=((double)battAdcValue-0.0)*(((3.0*1000.0)/1.0)/4095.0); + //double calibratedData = calibrateU12AdcValue((double)battAdcValue, 0.0, 3.0, 1.0); + double battVoltage = ((calibratedData * 1.988)) / 1000; + + if (battVoltage > 4.5) { + mChargingStatusParsed = "Checking..."; + adcVoltageError = true; + } + else if((chargeStatus & 0xFF) == 0x00) { + mChargingStatusParsed = "Charging suspended"; + } + else if ((chargeStatus & 0xFF) == 0x40) { + mChargingStatusParsed = "Fully charged"; + } + else if ((chargeStatus & 0xFF) == 0x80) { + String chargingStage = ""; + if (battVoltage < 3.0) {// from lm3658 datasheet + chargingStage = " (Preconditioning)"; + } + //else if (battVoltage < .0) + //{ + // chargingStage = " (Primary charging)"; + //} + //else if (battVoltage < .0) + //{ + // chargingStage = " (Conditioning)"; + //} + else { + chargingStage = "..."; + } + + mChargingStatusParsed = "Charging" + chargingStage; + } + else if ((chargeStatus & 0xFF) == 0xC0) { + mChargingStatusParsed = "Bad battery"; + } + else { + mChargingStatusParsed = "Error"; + } + + if(adcVoltageError == false) { + mBattVoltage = String.format("%,.1f",battVoltage) + " V"; + + // equations are only valid when: 3.2 < x < 4.167. Leaving a 0.2v either side just incase + if (battVoltage > (4.167 + 0.2)) { + battVoltage = 4.167; + } + else if (battVoltage < (3.2 - 0.2)) { + battVoltage = 3.2; + } + + double battPercentage = 0; + // 4th order polynomial fit - good enough for purpose + battPercentage = (1109.739792 * Math.pow(battVoltage, 4)) - (17167.12674 * Math.pow(battVoltage, 3)) + (99232.71686 * Math.pow(battVoltage, 2)) - (253825.397 * battVoltage) + 242266.0527; + + // 6th order polynomial fit - best fit -> think there is a bug with this one + //battPercentage = -(29675.10393 * Math.pow(battVoltage, 6)) + (675893.9095 * Math.pow(battVoltage, 5)) - (6404308.2798 * Math.pow(battVoltage, 4)) + (32311485.5704 * Math.pow(battVoltage, 3)) - (91543800.1720 * Math.pow(battVoltage, 2)) + (138081754.0880 * battVoltage) - 86624424.6584; + + if (battPercentage > 100) { + battPercentage = 100.0; + } + else if (battPercentage < 0) { + battPercentage = 0.0; + } + + if ((chargeStatus&0xFF) != 0xC0) {// Bad battery + mEstimatedChargePercentage = String.format("%,.1f",battPercentage) + "%"; + } + else { + mEstimatedChargePercentage = "0.0%"; + } + } + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerMsg.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerMsg.java new file mode 100644 index 00000000..59de593e --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerMsg.java @@ -0,0 +1,11 @@ +package com.shimmerresearch.driver; + +public class ShimmerMsg { + public int mIdentifier; + public Object mB; + + public ShimmerMsg(int a, Object b){ + mIdentifier=a; + mB=b; + } +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerObject.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerObject.java new file mode 100644 index 00000000..dd14fcb2 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerObject.java @@ -0,0 +1,9631 @@ +//Rev_1.9 +/* + * Copyright (c) 2010 - 2014, Shimmer Research, Ltd. + * All rights reserved + + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim, Ruaidhri Molloy, Alejandro Saez, Mark Nolan + * + * Changes since 1.8 + * - updated to work with SDLOG + * - change method formatdatapacketreverse to protected + * - added i32r to parsed data + * - mSignalNameArray changed to protected + * - fix twos complement for long numbers (32bit>=) + * - fix 6dof calculation ~ long + * - fix intiali time stamp ~ long + * + * + * Changes since 1.7 + * - remove multiplying factor (2.8) from the gain in the calculation of the Bridge Amplifier calibrated data + * + * @date September, 2014 + * + * Changes since 1.6 + * - Added functionality for plotmanager see MSSAPI , addExtraSignalProperty, removeExtraSignalProperty ,getListofEnabledSensorSignalsandFormats() + * - various exg advance updates + * + * @date July, 2014 + * + * Changes since 1.5 + * - Bridge Amplifier gauge support for Shimmer3 + * - Bug fix for strain gauge calibration for Shimmer2r + * - Enable 3D orientation for wide range accel, orientation algorithm defaults to low noise even if wide range is enabled + * - Fixed quaternion naming typo + * - Commented out initialisation mSensorBitmaptoName + * - add method getPressureRawCoefficients + * + * @date October, 2013 + * + * Changes since 1.4 + * - fix getListofEnabledSensors, which was not returning accel shimmer2r + * - fix null pointer graddes algo when using Shimmer2 + * - converted to abstract class , and added checkbattery abstract method for the Shimmer2r + * - updated gsr calibrate command parameters for Shimmer3 + * - removed mShimmerSamplingRate decimal formatter, decimal formatter should be done on the UI + * - fixed a GSR Shimmer2 problem when using autorange + * - added VSense Batt and VSense Reg and Timestamp to getListOfEnabledSensorSignals + * - added getSamplingRate() + * - added get methods for calibration parameters accel,gyro,mag,accel2 + * - updated getoffsetaccel + * - added exg configurations + * - added i24r for exg + * - add get exg configurations + * - renamed i16* to i16r for consistency + * - added EXG_CHIP1 = 0 and EXG_CHIP2=1 + * - updated Mag Default Range + * + */ + +//v0.1.0 consensys + +package com.shimmerresearch.driver; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.text.DateFormat; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; + +import javax.vecmath.Quat4d; +import javax.vecmath.Vector3d; + +import org.apache.commons.math.stat.descriptive.DescriptiveStatistics; + + +//import sun.util.calendar.BaseCalendar.Date; +//import sun.util.calendar.CalendarDate; +import java.util.Date; + +import com.google.common.collect.BiMap; +import com.google.common.collect.ImmutableBiMap; +import com.shimmerresearch.algorithms.GradDes3DOrientation; +import com.shimmerresearch.driver.ChannelDetails.ChannelDataEndian; +import com.shimmerresearch.driver.ChannelDetails.ChannelDataType; +import com.shimmerresearch.driver.Configuration.Shimmer2; +import com.shimmerresearch.driver.ShimmerVerDetails.FW_ID; +import com.shimmerresearch.driver.ShimmerVerDetails.HW_ID; +import com.shimmerresearch.driver.SensorDetails; +import com.shimmerresearch.driver.Configuration.Shimmer3; +import com.shimmerresearch.driver.ShimmerVerDetails.HW_ID_SR_CODES; +import com.shimmerresearch.algorithms.GradDes3DOrientation.Quaternion; + +public abstract class ShimmerObject extends BasicProcessWithCallBack implements Serializable { + + /** + * + */ + + private static final long serialVersionUID = -1364568867018921219L; + + public static final String ACCEL_CAL_UNIT = "m/s^2"; + public static final String ACCEL_DEFAULT_CAL_UNIT = "m/s^2"; + public static final String ADC_CAL_UNIT = "mV"; + public static final String GSR_CAL_UNIT = "kOhms"; + public static final String GYRO_CAL_UNIT = "deg/s"; + public static final String GYRO_DEFAULT_CAL_UNIT = "deg/s"; + public static final String MAG_CAL_UNIT = "local flux"; + public static final String MAG_DEFAULT_CAL_UNIT = "local flux"; + public static final String TEMP_CAL_UNIT = "Degrees Celsius"; + public static final String PRESSURE_CAL_UNIT = "kPa"; + public static final String HEARTRATE_CAL_UNIT = "bpm"; + + public static final String NO_UNIT = "No Units"; + public static final String CLOCK_UNIT = "Ticks"; + + public final static String DEFAULT_SHIMMER_NAME = "Shimmer"; + public final static String DEFAULT_EXPERIMENT_NAME = "Trial"; + + protected boolean mFirstTime = true; + double mFirstRawTS = 0; + public int OFFSET_LENGTH = 9; + + //Sensor Bitmap for ID ; for the purpose of forward compatibility the sensor bitmap and the ID and the sensor bitmap for the Shimmer firmware has been kept separate, + public static final int SENSOR_ACCEL = 0x80; + public static final int SENSOR_DACCEL = 0x1000; //only + public static final int SENSOR_GYRO = 0x40; + public static final int SENSOR_MAG = 0x20; + public static final int SENSOR_ECG = 0x10; + public static final int SENSOR_EMG = 0x08; + public static final int SENSOR_EXG1_24BIT = 0x10; //only applicable for Shimmer3 + public static final int SENSOR_EXG2_24BIT = 0x08; //only applicable for Shimmer3 + public static final int SHIMMER3_SENSOR_ECG = SENSOR_EXG1_24BIT + SENSOR_EXG2_24BIT; + public static final int SHIMMER3_SENSOR_EMG = SENSOR_EXG1_24BIT; + public static final int SENSOR_GSR = 0x04; + public static final int SENSOR_EXP_BOARD_A7 = 0x02; //only Applicable for Shimmer2 + public static final int SENSOR_EXP_BOARD_A0 = 0x01; //only Applicable for Shimmer2 + public static final int SENSOR_EXP_BOARD = SENSOR_EXP_BOARD_A7+SENSOR_EXP_BOARD_A0; + public static final int SENSOR_BRIDGE_AMP = 0x8000; + public static final int SENSOR_HEART = 0x4000; + public static final int SENSOR_BATT = 0x2000; //THIS IS A DUMMY VALUE + public static final int SENSOR_EXT_ADC_A7 = 0x02; //only Applicable for Shimmer3 + public static final int SENSOR_EXT_ADC_A6 = 0x01; //only Applicable for Shimmer3 + public static final int SENSOR_EXT_ADC_A15 = 0x0800; + public static final int SENSOR_INT_ADC_A1 = 0x0400; + public static final int SENSOR_INT_ADC_A12 = 0x0200; + public static final int SENSOR_INT_ADC_A13 = 0x0100; + public static final int SENSOR_INT_ADC_A14 = 0x800000; + public static final int SENSOR_ALL_ADC_SHIMMER3 = SENSOR_INT_ADC_A14 | SENSOR_INT_ADC_A13 | SENSOR_INT_ADC_A12 | SENSOR_INT_ADC_A1 | SENSOR_EXT_ADC_A7 | SENSOR_EXT_ADC_A6 | SENSOR_EXT_ADC_A15; + public static final int SENSOR_BMP180 = 0x40000; + public static final int SENSOR_EXG1_16BIT = 0x100000; //only applicable for Shimmer3 + public static final int SENSOR_EXG2_16BIT = 0x080000; //only applicable for Shimmer3 + public BiMap mSensorBitmaptoName; + + public class SDLogHeader { + public final static int ACCEL_LN = 1<<7; + public final static int GYRO = 1<<6; + public final static int MAG = 1<<5; + public final static int EXG1_24BIT = 1<<4; + public final static int EXG2_24BIT = 1<<3; + public final static int GSR = 1<<2; + public final static int EXT_EXP_A7 = 1<<1; + public final static int EXT_EXP_A6 = 1<<0; + public final static int BRIDGE_AMP = 1<<15; + // 1<<9 NONE + public final static int BATTERY = 1<<13; + public final static int ACCEL_WR = 1<<12; + public final static int EXT_EXP_A15 = 1<<11; + public final static int INT_EXP_A1 = 1<<10; + public final static int INT_EXP_A12 = 1<<9; + public final static int INT_EXP_A13 = 1<<8; + public final static int INT_EXP_A14 = 1<<23; + public final static int ACCEL_MPU = 1<<22; + public final static int MAG_MPU = 1<<21; + public final static int EXG1_16BIT = 1<<20; + public final static int EXG2_16BIT = 1<<19; + public final static int BMP180 = 1<<18; + public final static int MPL_TEMPERATURE = 1<<17; + // 1<<23 + public final static int MPL_QUAT_6DOF = 1<<31; + public final static int MPL_QUAT_9DOF = 1<<30; + public final static int MPL_EULER_6DOF = 1<<29; + public final static int MPL_EULER_9DOF = 1<<28; + public final static int MPL_HEADING = 1<<27; + public final static int MPL_PEDOMETER = 1<<26; + public final static int MPL_TAP = 1<<25; + public final static int MPL_MOTION_ORIENT = 1<<24; + public final static long GYRO_MPU_MPL = (long)1<<39; + public final static long ACCEL_MPU_MPL = (long)1<<38; + public final static long MAG_MPU_MPL = (long)1<<37; + public final static long SD_SENSOR_MPL_QUAT_6DOF_RAW = (long)1<<36; + } + + public class SDLogHeaderDerivedSensors{ + public final static int PPG2_1_14 = 1<<4; + public final static int PPG1_12_13 = 1<<3; + public final static int PPG_12_13 = 1<<2; + public final static int SKIN_TEMP = 1<<1; + public final static int RES_AMP = 1<<0; + } + + public class BTStream { + public final static int ACCEL_LN = 0x80; + public final static int GYRO = 0x40; + public final static int MAG = 0x20; + public final static int EXG1_24BIT = 0x10; + public final static int EXG2_24BIT = 0x08; + public final static int GSR = 0x04; + public final static int EXT_EXP_A7 = 0x02; + public final static int EXT_EXP_A6 = 0x01; + public final static int BRIDGE_AMP = 0x8000; + // 1<<9 NONE + public final static int BATTERY = 0x2000; + public final static int ACCEL_WR = 0x1000; + public final static int EXT_EXP_A15 = 0x0800; + public final static int INT_EXP_A1 = 0x0400; + public final static int INT_EXP_A12 = 0x0200; + public final static int INT_EXP_A13 = 0x0100; + public final static int INT_EXP_A14 = 0x800000; + public final static int ACCEL_MPU = 0x400000; + public final static int MAG_MPU = 0x200000; + public final static int EXG1_16BIT = 0x100000; + public final static int EXG2_16BIT = 0x080000; + public final static int BMP180 = 0x40000; + public final static int MPL_TEMPERATURE = 1<<22; + // 1<<23 + //public final static int MPL_QUAT_6DOF = 1<<24; + //public final static int MPL_QUAT_9DOF = 1<<25; + //public final static int MPL_EULER_6DOF = 1<<26; + //public final static int MPL_EULER_9DOF = 1<<27; + //public final static int MPL_HEADING = 1<<28; + //public final static int MPL_PEDOMETER = 1<<29; + //public final static int MPL_TAP = 1<<30; + //public final static int MPL_MOTION_ORIENT = 1<<31; + //public final static long GYRO_MPU_MPL = 1<<32; + //public final static long ACCEL_MPU_MPL = 1<<33; + //public final static long MAG_MPU_MPL = 1<<34; + //public final static long SD_SENSOR_MPL_QUAT_6DOF_RAW = 1<<35; + } + + + /* + { + final Map tempSensorBMtoName = new HashMap(); + tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); + tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BRIDGE_AMP), "Bridge Amplifier"); + tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); + mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); + } + */ + + protected TreeMap mSensorMap = new TreeMap(); + protected LinkedHashMap mSensorTileMap = new LinkedHashMap(); + protected HashMap mConfigOptionsMap = new HashMap(); + + + //Constants describing the packet type + public static final byte DATA_PACKET = (byte) 0x00; + public static final byte INQUIRY_COMMAND = (byte) 0x01; + public static final byte INQUIRY_RESPONSE = (byte) 0x02; + public static final byte GET_SAMPLING_RATE_COMMAND = (byte) 0x03; + public static final byte SAMPLING_RATE_RESPONSE = (byte) 0x04; + public static final byte SET_SAMPLING_RATE_COMMAND = (byte) 0x05; + public static final byte TOGGLE_LED_COMMAND = (byte) 0x06; + public static final byte START_STREAMING_COMMAND = (byte) 0x07; + public static final byte SET_SENSORS_COMMAND = (byte) 0x08; + public static final byte SET_ACCEL_SENSITIVITY_COMMAND = (byte) 0x09; + public static final byte ACCEL_SENSITIVITY_RESPONSE = (byte) 0x0A; + public static final byte GET_ACCEL_SENSITIVITY_COMMAND = (byte) 0x0B; + public static final byte SET_5V_REGULATOR_COMMAND = (byte) 0x0C; // only Shimmer 2 + public static final byte SET_PMUX_COMMAND = (byte) 0x0D; // only Shimmer 2 + public static final byte SET_CONFIG_BYTE0_COMMAND = (byte) 0x0E; + public static final byte CONFIG_BYTE0_RESPONSE = (byte) 0x0F; + public static final byte GET_CONFIG_BYTE0_COMMAND = (byte) 0x10; + public static final byte STOP_STREAMING_COMMAND = (byte) 0x20; + public static final byte SET_ACCEL_CALIBRATION_COMMAND = (byte) 0x11; + public static final byte ACCEL_CALIBRATION_RESPONSE = (byte) 0x12; + public static final byte LSM303DLHC_ACCEL_CALIBRATION_RESPONSE = (byte) 0x1B; + public static final byte SET_LSM303DLHC_ACCEL_CALIBRATION_COMMAND = (byte) 0x1A; + public static final byte GET_ACCEL_CALIBRATION_COMMAND = (byte) 0x13; + public static final byte SET_GYRO_CALIBRATION_COMMAND = (byte) 0x14; + public static final byte GYRO_CALIBRATION_RESPONSE = (byte) 0x15; + public static final byte GET_GYRO_CALIBRATION_COMMAND = (byte) 0x16; + public static final byte SET_MAG_CALIBRATION_COMMAND = (byte) 0x17; + public static final byte MAG_CALIBRATION_RESPONSE = (byte) 0x18; + public static final byte GET_MAG_CALIBRATION_COMMAND = (byte) 0x19; + public static final byte SET_GSR_RANGE_COMMAND = (byte) 0x21; + public static final byte GSR_RANGE_RESPONSE = (byte) 0x22; + public static final byte GET_GSR_RANGE_COMMAND = (byte) 0x23; + public static final byte GET_SHIMMER_VERSION_COMMAND = (byte) 0x24; + public static final byte GET_SHIMMER_VERSION_COMMAND_NEW = (byte) 0x3F; //this is to avoid the $ char which is used by rn42 + public static final byte GET_SHIMMER_VERSION_RESPONSE = (byte) 0x25; + public static final byte SET_EMG_CALIBRATION_COMMAND = (byte) 0x26; + public static final byte EMG_CALIBRATION_RESPONSE = (byte) 0x27; + public static final byte GET_EMG_CALIBRATION_COMMAND = (byte) 0x28; + public static final byte SET_ECG_CALIBRATION_COMMAND = (byte) 0x29; + public static final byte ECG_CALIBRATION_RESPONSE = (byte) 0x2A; + public static final byte GET_ECG_CALIBRATION_COMMAND = (byte) 0x2B; + public static final byte GET_ALL_CALIBRATION_COMMAND = (byte) 0x2C; + public static final byte ALL_CALIBRATION_RESPONSE = (byte) 0x2D; + public static final byte GET_FW_VERSION_COMMAND = (byte) 0x2E; + public static final byte FW_VERSION_RESPONSE = (byte) 0x2F; + public static final byte SET_BLINK_LED = (byte) 0x30; + public static final byte BLINK_LED_RESPONSE = (byte) 0x31; + public static final byte GET_BLINK_LED = (byte) 0x32; + public static final byte SET_GYRO_TEMP_VREF_COMMAND = (byte) 0x33; + public static final byte SET_BUFFER_SIZE_COMMAND = (byte) 0x34; + public static final byte BUFFER_SIZE_RESPONSE = (byte) 0x35; + public static final byte GET_BUFFER_SIZE_COMMAND = (byte) 0x36; + public static final byte SET_MAG_GAIN_COMMAND = (byte) 0x37; + public static final byte MAG_GAIN_RESPONSE = (byte) 0x38; + public static final byte GET_MAG_GAIN_COMMAND = (byte) 0x39; + public static final byte SET_MAG_SAMPLING_RATE_COMMAND = (byte) 0x3A; + public static final byte MAG_SAMPLING_RATE_RESPONSE = (byte) 0x3B; + public static final byte GET_MAG_SAMPLING_RATE_COMMAND = (byte) 0x3C; + public static final byte SET_ACCEL_SAMPLING_RATE_COMMAND = (byte) 0x40; + public static final byte ACCEL_SAMPLING_RATE_RESPONSE = (byte) 0x41; + public static final byte GET_ACCEL_SAMPLING_RATE_COMMAND = (byte) 0x42; + public static final byte SET_LSM303DLHC_ACCEL_LPMODE_COMMAND = (byte) 0x43; + public static final byte LSM303DLHC_ACCEL_LPMODE_RESPONSE = (byte) 0x44; + public static final byte GET_LSM303DLHC_ACCEL_LPMODE_COMMAND = (byte) 0x45; + public static final byte SET_LSM303DLHC_ACCEL_HRMODE_COMMAND = (byte) 0x46; + public static final byte LSM303DLHC_ACCEL_HRMODE_RESPONSE = (byte) 0x47; + public static final byte GET_LSM303DLHC_ACCEL_HRMODE_COMMAND = (byte) 0x48; + public static final byte SET_MPU9150_GYRO_RANGE_COMMAND = (byte) 0x49; + public static final byte MPU9150_GYRO_RANGE_RESPONSE = (byte) 0x4A; + public static final byte GET_MPU9150_GYRO_RANGE_COMMAND = (byte) 0x4B; + public static final byte SET_MPU9150_SAMPLING_RATE_COMMAND = (byte) 0x4C; + public static final byte MPU9150_SAMPLING_RATE_RESPONSE = (byte) 0x4D; + public static final byte GET_MPU9150_SAMPLING_RATE_COMMAND = (byte) 0x4E; + public static final byte SET_BMP180_PRES_RESOLUTION_COMMAND = (byte) 0x52; + public static final byte BMP180_PRES_RESOLUTION_RESPONSE = (byte) 0x53; + public static final byte GET_BMP180_PRES_RESOLUTION_COMMAND = (byte) 0x54; + public static final byte SET_BMP180_PRES_CALIBRATION_COMMAND = (byte) 0x55; + public static final byte BMP180_PRES_CALIBRATION_RESPONSE = (byte) 0x56; + public static final byte GET_BMP180_PRES_CALIBRATION_COMMAND = (byte) 0x57; + public static final byte BMP180_CALIBRATION_COEFFICIENTS_RESPONSE = (byte) 0x58; + public static final byte GET_BMP180_CALIBRATION_COEFFICIENTS_COMMAND = (byte) 0x59; + public static final byte RESET_TO_DEFAULT_CONFIGURATION_COMMAND = (byte) 0x5A; + public static final byte RESET_CALIBRATION_VALUE_COMMAND = (byte) 0x5B; + public static final byte MPU9150_MAG_SENS_ADJ_VALS_RESPONSE = (byte) 0x5C; + public static final byte GET_MPU9150_MAG_SENS_ADJ_VALS_COMMAND = (byte) 0x5D; + public static final byte SET_INTERNAL_EXP_POWER_ENABLE_COMMAND = (byte) 0x5E; + public static final byte INTERNAL_EXP_POWER_ENABLE_RESPONSE = (byte) 0x5F; + public static final byte GET_INTERNAL_EXP_POWER_ENABLE_COMMAND = (byte) 0x60; + public static final byte SET_EXG_REGS_COMMAND = (byte) 0x61; + public static final byte EXG_REGS_RESPONSE = (byte) 0x62; + public static final byte GET_EXG_REGS_COMMAND = (byte) 0x63; + public static final byte DAUGHTER_CARD_ID_RESPONSE = (byte) 0x65; + public static final byte GET_DAUGHTER_CARD_ID_COMMAND = (byte) 0x66; + public static final byte SET_BAUD_RATE_COMMAND = (byte) 0x6A; + public static final byte BAUD_RATE_RESPONSE = (byte) 0x6B; + public static final byte GET_BAUD_RATE_COMMAND = (byte) 0x6C; + public static final byte START_SDBT_COMMAND = (byte) 0x70; + public static final byte STATUS_RESPONSE = (byte) 0x71; + public static final byte GET_STATUS_COMMAND = (byte) 0x72; + public static final byte DIR_RESPONSE = (byte) 0x88; + public static final byte GET_DIR_COMMAND = (byte) 0x89; + public static final byte INSTREAM_CMD_RESPONSE = (byte) 0x8A; + public static final byte SET_RWC_COMMAND = (byte) 0x8F; + public static final byte RWC_RESPONSE = (byte) 0x90; + public static final byte GET_RWC_COMMAND = (byte) 0x91; + public static final byte SET_VBATT_FREQ_COMMAND = (byte) 0x98; + public static final byte VBATT_FREQ_RESPONSE = (byte) 0x99; + public static final byte GET_VBATT_FREQ_COMMAND = (byte) 0x9A; + public static final byte ACK_COMMAND_PROCESSED = (byte) 0xFF; + protected String mMyName=""; // This stores the user assigned name + protected String mMyBluetoothAddress=""; + public static final int MAX_NUMBER_OF_SIGNALS = 50; //used to be 11 but now 13 because of the SR30 + 8 for 3d orientation + public static final int MAX_INQUIRY_PACKET_SIZE = 47; +// protected int mFWCode=0; + + public final static int MSP430_5XX_INFOMEM_D_ADDRESS = 0x001800; + public final static int MSP430_5XX_INFOMEM_C_ADDRESS = 0x001880; + public final static int MSP430_5XX_INFOMEM_B_ADDRESS = 0x001900; + public final static int MSP430_5XX_INFOMEM_A_ADDRESS = 0x001980; + public final static int MSP430_5XX_INFOMEM_LAST_ADDRESS = 0x0019FF; +// public final static int MSP430_5XX_PROGRAM_START_ADDRESS = 0x00FFFE; + + protected int mHardwareVersion=-1; + public String mHardwareVersionParsed = ""; + + public int mFirmwareVersionCode = 0; + public int mFirmwareIdentifier = 0; + public int mFirmwareVersionMajor = 0; + public int mFirmwareVersionMinor = 0; + public int mFirmwareVersionInternal = 0; + public String mFirmwareVersionParsed = ""; + + public int mExpansionBoardId = -1; + public int mExpansionBoardRev = -1; + public int mExpansionBoardSpecialRev = -1; + public String mExpansionBoardParsed = ""; + public String mExpansionBoardParsedWithVer = ""; + public static final int ANY_VERSION = -1; + + //TODO: change mExpBoardArray from ShimmerObject to mShimmerExpansionBoardId or are they different? + //TODO: change mExpBoardName from ShimmerObject to mShimmerExpansionBoardParsed and mShimmerExpansionBoardParsedWithVer + protected byte[] mExpBoardArray; // Array where the expansion board response is stored + protected String mExpBoardName; // Name of the expansion board. ONLY SHIMMER 3 + + protected String mClassName="Shimmer"; + private double mLastReceivedTimeStamp=0; + protected double mCurrentTimeStampCycle=0; + protected double mShimmerSamplingRate; // 51.2Hz is the default sampling rate + protected long mEnabledSensors = (long)0; // This stores the enabled sensors + protected long mDerivedSensors = (long)0; // This stores the sensors channels derived in SW + protected int mBluetoothBaudRate=0; + + protected int mPacketSize=0; // Default 2 bytes for time stamp and 6 bytes for accelerometer + protected int mAccelRange=0; // This stores the current accelerometer range being used. The accelerometer range is stored during two instances, once an ack packet is received after a writeAccelRange(), and after a response packet has been received after readAccelRange() +// protected boolean mLowPowerAccelWR = false; //TODO: add comment and set from BT command + protected boolean mHighResAccelWR = false; //TODO: add comment and set from BT command + protected int mLSM303MagRate=4; // This stores the current Mag Sampling rate, it is a value between 0 and 6; 0 = 0.5 Hz; 1 = 1.0 Hz; 2 = 2.0 Hz; 3 = 5.0 Hz; 4 = 10.0 Hz; 5 = 20.0 Hz; 6 = 50.0 Hz + protected int mLSM303DigitalAccelRate=0; + protected int mMPU9150GyroAccelRate=0; + protected int mMagRange=1; // Currently not supported on Shimmer2. This stores the current Mag Range, it is a value between 0 and 6; 0 = 0.7 Ga; 1 = 1.0 Ga; 2 = 1.5 Ga; 3 = 2.0 Ga; 4 = 3.2 Ga; 5 = 3.8 Ga; 6 = 4.5 Ga + protected int mGyroRange=1; // This stores the current Gyro Range, it is a value between 0 and 3; 0 = +/- 250dps,1 = 500dps, 2 = 1000dps, 3 = 2000dps + protected int mMPU9150AccelRange=0; // This stores the current MPU9150 Accel Range. 0 = 2g, 1 = 4g, 2 = 8g, 4 = 16g + protected int mGSRRange=4; // This stores the current GSR range being used. + protected int mPastGSRRange=4; // this is to fix a bug with SDLog v0.9 + protected int mPastGSRUncalibratedValue=4; // this is to fix a bug with SDLog v0.9 + protected boolean mPastGSRFirstTime=true; // this is to fix a bug with SDLog v0.9 + protected int mInternalExpPower=-1; // This shows whether the internal exp power is enabled. + protected long mConfigByte0; + protected int mNChannels=0; // Default number of sensor channels set to three because of the on board accelerometer + protected int mBufferSize; + + protected String[] mSignalNameArray=new String[MAX_NUMBER_OF_SIGNALS]; // 19 is the maximum number of signal thus far + protected String[] mSignalDataTypeArray=new String[MAX_NUMBER_OF_SIGNALS]; // 19 is the maximum number of signal thus far + protected boolean mDefaultCalibrationParametersECG = true; + protected boolean mDefaultCalibrationParametersEMG = true; + protected boolean mDefaultCalibrationParametersAccel = true; + protected boolean mDefaultCalibrationParametersDigitalAccel = true; //Also known as the wide range accelerometer + protected int mPressureResolution = 0; + protected int mExGResolution = 0; + protected int mShimmer2MagRate=0; + + //TODO add comments and default values + //protected int mDigitalAccelRange = 0; + //protected int mAccelRange = 0; +// protected int mAccelLPM = 0; +// protected int mAccelHPM = 0; +// protected int mMPU9150GyroRate = 0; +// protected int mMPUAccelRange = 0; + protected int mMPU9150DMP = 0; + protected int mMPU9150LPF = 0; + protected int mMPU9150MotCalCfg = 0; + protected int mMPU9150MPLSamplingRate = 0; + protected int mMPU9150MagSamplingRate = 0; + protected int mMPLSensorFusion = 0; + protected int mMPLGyroCalTC = 0; + protected int mMPLVectCompCal = 0; + protected int mMPLMagDistCal = 0; + protected int mMPLEnable = 0; + protected int mButtonStart = 0; + protected int mMasterShimmer = 0; + protected int mSingleTouch = 0; + protected int mTCXO = 0; + protected long mConfigTime; //this is in milliseconds, utc + protected long mRTCOffset; //this is in ticks + protected int mSyncWhenLogging = 0; + protected int mSyncBroadcastInterval = 0; + protected byte[] mInfoMemBytes = createEmptyInfoMemByteArray(512); + protected boolean mShimmerUsingConfigFromInfoMem = false; + + protected long mInitialTimeStamp; + + protected final static int FW_TYPE_BT=0; + protected final static int FW_TYPE_SD=1; + + protected String mShimmerUserAssignedName = ""; //TODO: this seems to be a duplicate of mMyName and ?devicename? + protected String mExperimentName = ""; //TODO: this seems to be a duplicate of mMyTrial + protected int mExperimentId = 0; + protected int mExperimentNumberOfShimmers = 0; + protected int mExperimentDurationEstimated = 0; + protected int mExperimentDurationMaximum = 0; + + protected String mMacIdFromInfoMem = ""; + protected String mMacIdFromUart = ""; + protected String mMacIdFromUartParsed = ""; + + protected boolean mConfigFileCreationFlag = false; + protected boolean mCalibFileCreationFlag = false; + + protected List syncNodesList = new ArrayList(); + + protected int mPpgAdcSelectionGsrBoard = 0; + protected int mPpg1AdcSelectionProto3DeluxeBoard = 0; + protected int mPpg2AdcSelectionProto3DeluxeBoard = 0; + + + // + protected double[][] mAlignmentMatrixAnalogAccel = {{-1,0,0},{0,-1,0},{0,0,1}}; + protected double[][] mSensitivityMatrixAnalogAccel = {{38,0,0},{0,38,0},{0,0,38}}; + protected double[][] mOffsetVectorAnalogAccel = {{2048},{2048},{2048}}; + protected abstract void checkBattery(); + protected double[][] mAlignmentMatrixWRAccel = {{-1,0,0},{0,1,0},{0,0,-1}}; + protected double[][] mSensitivityMatrixWRAccel = {{1631,0,0},{0,1631,0},{0,0,1631}}; + protected double[][] mOffsetVectorWRAccel = {{0},{0},{0}}; + + //Default values Shimmer2 + protected static double[][] SensitivityMatrixAccel1p5gShimmer2 = {{101,0,0},{0,101,0},{0,0,101}}; + protected static double[][] SensitivityMatrixAccel2gShimmer2 = {{76,0,0},{0,76,0},{0,0,76}}; + protected static double[][] SensitivityMatrixAccel4gShimmer2 = {{38,0,0},{0,38,0},{0,0,38}}; + protected static double[][] SensitivityMatrixAccel6gShimmer2 = {{25,0,0},{0,25,0},{0,0,25}}; + protected static double[][] AlignmentMatrixAccelShimmer2 = {{-1,0,0},{0,-1,0},{0,0,1}}; + protected static double[][] OffsetVectorAccelShimmer2 = {{2048},{2048},{2048}}; + //Shimmer3 + protected static double[][] SensitivityMatrixLowNoiseAccel2gShimmer3 = {{83,0,0},{0,83,0},{0,0,83}}; + protected static double[][] SensitivityMatrixWideRangeAccel2gShimmer3 = {{1631,0,0},{0,1631,0},{0,0,1631}}; + protected static double[][] SensitivityMatrixWideRangeAccel4gShimmer3 = {{815,0,0},{0,815,0},{0,0,815}}; + protected static double[][] SensitivityMatrixWideRangeAccel8gShimmer3 = {{408,0,0},{0,408,0},{0,0,408}}; + protected static double[][] SensitivityMatrixWideRangeAccel16gShimmer3 = {{135,0,0},{0,135,0},{0,0,135}}; + protected static double[][] AlignmentMatrixLowNoiseAccelShimmer3 = {{0,-1,0},{-1,0,0},{0,0,-1}}; + + protected static double[][] AlignmentMatrixWideRangeAccelShimmer3 = {{-1,0,0},{0,1,0},{0,0,-1}}; + protected static double[][] AlignmentMatrixAccelShimmer3 = {{0,-1,0},{-1,0,0},{0,0,-1}}; + protected static double[][] OffsetVectorLowNoiseAccelShimmer3 = {{2047},{2047},{2047}}; + protected static double[][] OffsetVectorWideRangeAccelShimmer3 = {{0},{0},{0}}; + + protected double OffsetECGRALL=2060; + protected double GainECGRALL=175; + protected double OffsetECGLALL=2060; + protected double GainECGLALL=175; + protected double OffsetEMG=2060; + protected double GainEMG=750; + + protected boolean mDefaultCalibrationParametersGyro = true; + protected double[][] mAlignmentMatrixGyroscope = {{0,-1,0},{-1,0,0},{0,0,-1}}; + protected double[][] mSensitivityMatrixGyroscope = {{2.73,0,0},{0,2.73,0},{0,0,2.73}}; + protected double[][] mOffsetVectorGyroscope = {{1843},{1843},{1843}}; + + //Default values Shimmer2 + protected static double[][] AlignmentMatrixGyroShimmer2 = {{0,-1,0},{-1,0,0},{0,0,-1}}; + protected static double[][] SensitivityMatrixGyroShimmer2 = {{2.73,0,0},{0,2.73,0},{0,0,2.73}}; + protected static double[][] OffsetVectorGyroShimmer2 = {{1843},{1843},{1843}}; + //Shimmer3 + protected static double[][] SensitivityMatrixGyro250dpsShimmer3 = {{131,0,0},{0,131,0},{0,0,131}}; + protected static double[][] SensitivityMatrixGyro500dpsShimmer3 = {{65.5,0,0},{0,65.5,0},{0,0,65.5}}; + protected static double[][] SensitivityMatrixGyro1000dpsShimmer3 = {{32.8,0,0},{0,32.8,0},{0,0,32.8}}; + protected static double[][] SensitivityMatrixGyro2000dpsShimmer3 = {{16.4,0,0},{0,16.4,0},{0,0,16.4}}; + protected static double[][] AlignmentMatrixGyroShimmer3 = {{0,-1,0},{-1,0,0},{0,0,-1}}; + protected static double[][] OffsetVectorGyroShimmer3 = {{0},{0},{0}}; + + protected int mCurrentLEDStatus=0; + protected boolean mDefaultCalibrationParametersMag = true; + protected double[][] mAlignmentMatrixMagnetometer = {{1,0,0},{0,1,0},{0,0,-1}}; + protected double[][] mSensitivityMatrixMagnetometer = {{580,0,0},{0,580,0},{0,0,580}}; + protected double[][] mOffsetVectorMagnetometer = {{0},{0},{0}}; + + //Default values Shimmer2 and Shimmer3 + protected static double[][] AlignmentMatrixMagShimmer2 = {{1,0,0},{0,1,0},{0,0,-1}}; + protected static double[][] SensitivityMatrixMagShimmer2 = {{580,0,0},{0,580,0},{0,0,580}}; + protected static double[][] OffsetVectorMagShimmer2 = {{0},{0},{0}}; + //Shimmer3 + protected static double[][] AlignmentMatrixMagShimmer3 = {{-1,0,0},{0,1,0},{0,0,-1}}; + protected static double[][] SensitivityMatrixMagShimmer3 = {{1100,0,0},{0,1100,0},{0,0,980}}; + protected static double[][] OffsetVectorMagShimmer3 = {{0},{0},{0}}; + + + protected double[][] AlignmentMatrixMPLAccel = {{-1,0,0},{0,1,0},{0,0,-1}}; + protected double[][] SensitivityMatrixMPLAccel = {{1631,0,0},{0,1631,0},{0,0,1631}}; + protected double[][] OffsetVectorMPLAccel = {{0},{0},{0}}; + + protected double[][] AlignmentMatrixMPLMag = {{-1,0,0},{0,1,0},{0,0,-1}}; + protected double[][] SensitivityMatrixMPLMag = {{1631,0,0},{0,1631,0},{0,0,1631}}; + protected double[][] OffsetVectorMPLMag = {{0},{0},{0}}; + + protected double[][] AlignmentMatrixMPLGyro = {{-1,0,0},{0,1,0},{0,0,-1}}; + protected double[][] SensitivityMatrixMPLGyro = {{1631,0,0},{0,1631,0},{0,0,1631}}; + protected double[][] OffsetVectorMPLGyro = {{0},{0},{0}}; + + + protected static double[][] SensitivityMatrixMag1p3GaShimmer3 = {{1100,0,0},{0,1100,0},{0,0,980}}; + protected static double[][] SensitivityMatrixMag1p9GaShimmer3 = {{855,0,0},{0,855,0},{0,0,760}}; + protected static double[][] SensitivityMatrixMag2p5GaShimmer3 = {{670,0,0},{0,670,0},{0,0,600}}; + protected static double[][] SensitivityMatrixMag4GaShimmer3 = {{450,0,0},{0,450,0},{0,0,400}}; + protected static double[][] SensitivityMatrixMag4p7GaShimmer3 = {{400,0,0},{0,400,0},{0,0,355}}; + protected static double[][] SensitivityMatrixMag5p6GaShimmer3 = {{330,0,0},{0,330,0},{0,0,295}}; + protected static double[][] SensitivityMatrixMag8p1GaShimmer3 = {{230,0,0},{0,230,0},{0,0,205}}; + + protected static double[][] SensitivityMatrixMag0p8GaShimmer2 = {{1370,0,0},{0,1370,0},{0,0,1370}}; + protected static double[][] SensitivityMatrixMag1p3GaShimmer2 = {{1090,0,0},{0,1090,0},{0,0,1090}}; + protected static double[][] SensitivityMatrixMag1p9GaShimmer2 = {{820,0,0},{0,820,0},{0,0,820}}; + protected static double[][] SensitivityMatrixMag2p5GaShimmer2 = {{660,0,0},{0,660,0},{0,0,660}}; + protected static double[][] SensitivityMatrixMag4p0GaShimmer2 = {{440,0,0},{0,440,0},{0,0,440}}; + protected static double[][] SensitivityMatrixMag4p7GaShimmer2 = {{390,0,0},{0,390,0},{0,0,390}}; + protected static double[][] SensitivityMatrixMag5p6GaShimmer2 = {{330,0,0},{0,330,0},{0,0,330}}; + protected static double[][] SensitivityMatrixMag8p1GaShimmer2 = {{230,0,0},{0,230,0},{0,0,230}}; + + + protected double AC1 = 408; + protected double AC2 = -72; + protected double AC3 = -14383; + protected double AC4 = 332741; + protected double AC5 = 32757; + protected double AC6 = 23153; + protected double B1 = 6190; + protected double B2 = 4; + protected double MB = -32767; + protected double MC = -8711; + protected double MD = 2868; + + protected boolean mLowPowerMag = false; + protected boolean mLowPowerAccelWR = false; + protected boolean mLowPowerGyro = false; + + protected long mPacketLossCount=0; + protected double mPacketReceptionRate=100; + protected double mLastReceivedCalibratedTimeStamp=-1; + protected boolean mFirstTimeCalTime=true; + protected double mCalTimeStart; + private double mLastKnownHeartRate=0; + protected DescriptiveStatistics mVSenseBattMA= new DescriptiveStatistics(1024); + Quat4d mQ = new Quat4d(); + GradDes3DOrientation mOrientationAlgo; + protected boolean mOrientationEnabled = false; + protected boolean mEnableOntheFlyGyroOVCal = false; + + protected double mGyroOVCalThreshold = 1.2; + DescriptiveStatistics mGyroX; + DescriptiveStatistics mGyroY; + DescriptiveStatistics mGyroZ; + DescriptiveStatistics mGyroXRaw; + DescriptiveStatistics mGyroYRaw; + DescriptiveStatistics mGyroZRaw; + protected boolean mEnableCalibration = true; + protected byte[] mInquiryResponseBytes; + protected boolean mStreaming =false; // This is used to monitor whether the device is in streaming mode + //all raw params should start with a 1 byte identifier in position [0] + protected byte[] mAccelCalRawParams = new byte[22]; + protected byte[] mDigiAccelCalRawParams = new byte[22]; + protected byte[] mGyroCalRawParams = new byte[22]; + protected byte[] mMagCalRawParams = new byte[22]; + protected byte[] mPressureRawParams = new byte[23]; + protected byte[] mEMGCalRawParams = new byte[13]; + protected byte[] mECGCalRawParams = new byte[13]; + protected byte[] mPressureCalRawParams = new byte[23]; + + //EXG + protected byte[] mEXG1RegisterArray = new byte[10]; + protected byte[] mEXG2RegisterArray = new byte[10]; + protected int mEXG1RateSetting; //setting not value + protected int mEXG1CH1GainSetting; // this is the setting not to be confused with the actual value + protected int mEXG1CH1GainValue; // this is the value + protected int mEXG1CH2GainSetting; // this is the setting not to be confused with the actual value + protected int mEXG1CH2GainValue; // this is the value + protected int mEXG2RateSetting; //setting not value + protected int mEXG2CH1GainSetting; // this is the setting not to be confused with the actual value + protected int mEXG2CH1GainValue; // this is the value + protected int mEXG2CH2GainSetting; // this is the setting not to be confused with the actual value + protected int mEXG2CH2GainValue; // this is the value + protected static final int EXG_CHIP1 = 0; + protected static final int EXG_CHIP2 = 1; + //EXG ADVANCED + protected int mEXGReferenceElectrode=-1; + protected int mLeadOffDetectionMode; + protected int mEXG1LeadOffCurrentMode; + protected int mEXG2LeadOffCurrentMode; + protected int mEXG1Comparators; + protected int mEXG2Comparators; + protected int mEXGRLDSense; + protected int mEXG1LeadOffSenseSelection; + protected int mEXG2LeadOffSenseSelection; + protected int mEXGLeadOffDetectionCurrent; + protected int mEXGLeadOffComparatorTreshold; + protected int mEXG2RespirationDetectState; + protected int mEXG2RespirationDetectFreq; + protected int mEXG2RespirationDetectPhase; + + + protected int mTimeStampPacketByteSize = 2; + protected int mTimeStampPacketRawMaxValue = 65536;// 16777216 or 65536 + + //This features are only used in LogAndStream FW + protected String mDirectoryName; + protected int mDirectoryNameLength; + protected boolean mSensingStatus; + protected boolean mDockedStatus; + protected boolean mIsSDLogging; + protected boolean mIsStreaming; + private List mExtraSignalProperties = null; + + //Testing for GQ + protected int mGqPacketNumHeaderBytes = 0; + protected int mSamplingDividerVBatt = 0; + protected int mSamplingDividerGsr = 0; + protected int mSamplingDividerPpg = 0; + protected int mSamplingDividerLsm303dlhcAccel = 0; + + protected ObjectCluster buildMsg(byte[] newPacket, int fwIdentifier, int timeSync) { + ObjectCluster objectCluster = new ObjectCluster(); + + objectCluster.mMyName = mMyName; + objectCluster.mBluetoothAddress = mMyBluetoothAddress; + objectCluster.mRawData = newPacket; + objectCluster.mSystemTimeStamp=ByteBuffer.allocate(8).putLong(System.currentTimeMillis()).array(); + + double [] calibratedData; + double [] uncalibratedData; + String [] uncalibratedDataUnits; + String [] calibratedDataUnits; + String [] sensorNames; + + + + if (fwIdentifier == FW_TYPE_BT){ + objectCluster.mSystemTimeStamp=ByteBuffer.allocate(8).putLong(System.currentTimeMillis()).array(); + calibratedData=new double[mNChannels + 1]; //plus 1 because of the time stamp + uncalibratedData=new double[mNChannels + 1]; //plus 1 because of the time stamp + uncalibratedDataUnits = new String[mNChannels + 1]; + calibratedDataUnits = new String[mNChannels + 1]; + sensorNames = new String[mNChannels + 1]; + } else { + if (mRTCOffset == 0){ + calibratedData=new double[mNChannels]; //sd log time stamp already included in mnChannels + uncalibratedData=new double[mNChannels]; + uncalibratedDataUnits = new String[mNChannels]; + calibratedDataUnits = new String[mNChannels]; + sensorNames = new String[mNChannels]; + } else { + calibratedData=new double[mNChannels+1]; //for RTC + uncalibratedData=new double[mNChannels+1]; + uncalibratedDataUnits = new String[mNChannels+1]; + calibratedDataUnits = new String[mNChannels+1]; + sensorNames = new String[mNChannels+1]; + } + } + + System.arraycopy(mSignalNameArray, 0, sensorNames, 0, sensorNames.length); + + //PARSE DATA + long[] newPacketInt=parsedData(newPacket,mSignalDataTypeArray); + + double[] tempData=new double[3]; + Vector3d accelerometer = new Vector3d(); + Vector3d magnetometer = new Vector3d(); + Vector3d gyroscope = new Vector3d(); + + + if (mHardwareVersion==HW_ID.SHIMMER_SR30 || mHardwareVersion==HW_ID.SHIMMER_3){ + + int iTimeStamp=getSignalIndex("TimeStamp"); //find index + if(mFirstTime && fwIdentifier == FW_TYPE_SD){ + //this is to make sure the Raw starts from zero + mFirstRawTS = (double)newPacketInt[iTimeStamp]; + mFirstTime = false; + } + double calibratedTS = calibrateTimeStamp((double)newPacketInt[iTimeStamp]); + + //TIMESTAMP + if (fwIdentifier == FW_TYPE_SD){ + // RTC timestamp uncal. (shimmer timestamp + RTC offset from header); unit = ticks + double unwrappedrawtimestamp = calibratedTS*32768/1000; + unwrappedrawtimestamp = unwrappedrawtimestamp - mFirstRawTS; //deduct this so it will start from 0 + long sdlograwtimestamp = (long)mInitialTimeStamp + (long)unwrappedrawtimestamp; + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("RAW",CLOCK_UNIT,(double)sdlograwtimestamp)); + uncalibratedData[iTimeStamp] = (double)sdlograwtimestamp; + uncalibratedDataUnits[iTimeStamp] = CLOCK_UNIT; + + if (mEnableCalibration){ + double sdlogcaltimestamp = (double)sdlograwtimestamp/32768*1000; + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("CAL","mSecs",sdlogcaltimestamp)); + calibratedData[iTimeStamp] = sdlogcaltimestamp; + calibratedDataUnits[iTimeStamp] = "mSecs"; + } + } else if (fwIdentifier == FW_TYPE_BT){ + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iTimeStamp])); + uncalibratedData[iTimeStamp] = (double)newPacketInt[iTimeStamp]; + uncalibratedDataUnits[iTimeStamp] = NO_UNIT; + if (mEnableCalibration){ + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("CAL","mSecs",calibratedTS)); + calibratedData[iTimeStamp] = calibratedTS; + calibratedDataUnits[iTimeStamp] = "mSecs"; + } + } + + //RAW RTC + if ((fwIdentifier == FW_TYPE_SD) && mRTCOffset!=0) + { + double unwrappedrawtimestamp = calibratedTS*32768/1000; + unwrappedrawtimestamp = unwrappedrawtimestamp - mFirstRawTS; //deduct this so it will start from 0 + long rtctimestamp = (long)mInitialTimeStamp + (long)unwrappedrawtimestamp + mRTCOffset; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.REAL_TIME_CLOCK,new FormatCluster("RAW",CLOCK_UNIT,(double)rtctimestamp)); + uncalibratedData[sensorNames.length-1] = (double)rtctimestamp; + uncalibratedDataUnits[sensorNames.length-1] = CLOCK_UNIT; + sensorNames[sensorNames.length-1]= Shimmer3.ObjectClusterSensorName.REAL_TIME_CLOCK; + if (mEnableCalibration){ + double rtctimestampcal = ((double)mInitialTimeStamp/32768.0*1000.0) + calibratedTS + ((double)mRTCOffset/32768.0*1000.0) - (mFirstRawTS/32768.0*1000.0); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.REAL_TIME_CLOCK,new FormatCluster("CAL","mSecs",rtctimestampcal)); + calibratedData[sensorNames.length-1] = rtctimestampcal; + calibratedDataUnits[sensorNames.length-1] = "mSecs"; + } + } + + //OFFSET + if(timeSync==1 && (fwIdentifier == FW_TYPE_SD)){ + int iOffset=getSignalIndex("Offset"); //find index + double offsetValue = Double.NaN; + if (OFFSET_LENGTH==9){ + if(newPacketInt[iOffset] == 1152921504606846975L){ + offsetValue=Double.NaN; + } else { + offsetValue=(double)newPacketInt[iOffset]; + } + } + else{ + if(newPacketInt[iOffset] == 4294967295L){ //this is 4 bytes + offsetValue=Double.NaN; + } else { + offsetValue=(double)newPacketInt[iOffset]; + } + } + + objectCluster.mPropertyCluster.put("Offset",new FormatCluster("RAW",NO_UNIT,offsetValue)); + uncalibratedData[iOffset] = offsetValue; + calibratedData[iOffset] = Double.NaN; + uncalibratedDataUnits[iOffset] = NO_UNIT; + calibratedDataUnits[iOffset] = NO_UNIT; + } + + + objectCluster = callAdditionalServices(objectCluster); + + + //first get raw and calibrated data, this is data derived from the Shimmer device and involves no involvement from the API + + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.ACCEL_LN) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.ACCEL_LN) > 0) + ){ + int iAccelX=getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_LN_X); //find index + int iAccelY=getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y); //find index + int iAccelZ=getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z); //find index + tempData[0]=(double)newPacketInt[iAccelX]; + tempData[1]=(double)newPacketInt[iAccelY]; + tempData[2]=(double)newPacketInt[iAccelZ]; + + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelX])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelY])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelZ])); + uncalibratedData[iAccelX]=(double)newPacketInt[iAccelX]; + uncalibratedData[iAccelY]=(double)newPacketInt[iAccelY]; + uncalibratedData[iAccelZ]=(double)newPacketInt[iAccelZ]; + uncalibratedDataUnits[iAccelX]=NO_UNIT; + uncalibratedDataUnits[iAccelY]=NO_UNIT; + uncalibratedDataUnits[iAccelZ]=NO_UNIT; + + + if (mEnableCalibration){ + double[] accelCalibratedData; + accelCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixAnalogAccel, mSensitivityMatrixAnalogAccel, mOffsetVectorAnalogAccel); + calibratedData[iAccelX]=accelCalibratedData[0]; + calibratedData[iAccelY]=accelCalibratedData[1]; + calibratedData[iAccelZ]=accelCalibratedData[2]; + + if (mDefaultCalibrationParametersAccel == true) { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_X,new FormatCluster("CAL",ACCEL_DEFAULT_CAL_UNIT,accelCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y,new FormatCluster("CAL",ACCEL_DEFAULT_CAL_UNIT,accelCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z,new FormatCluster("CAL",ACCEL_DEFAULT_CAL_UNIT,accelCalibratedData[2])); + calibratedDataUnits[iAccelX]=ACCEL_DEFAULT_CAL_UNIT; + calibratedDataUnits[iAccelY]=ACCEL_DEFAULT_CAL_UNIT; + calibratedDataUnits[iAccelZ]=ACCEL_DEFAULT_CAL_UNIT; + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + + } else { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_X,new FormatCluster("CAL",ACCEL_CAL_UNIT,accelCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y,new FormatCluster("CAL",ACCEL_CAL_UNIT,accelCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z,new FormatCluster("CAL",ACCEL_CAL_UNIT,accelCalibratedData[2])); + calibratedDataUnits[iAccelX] = ACCEL_CAL_UNIT; + calibratedDataUnits[iAccelY] = ACCEL_CAL_UNIT; + calibratedDataUnits[iAccelZ] = ACCEL_CAL_UNIT; + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + + } + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.ACCEL_WR) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.ACCEL_WR) > 0) + ){ + int iAccelX=getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_WR_X); //find index + int iAccelY=getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y); //find index + int iAccelZ=getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z); //find index + //check range + + tempData[0]=(double)newPacketInt[iAccelX]; + tempData[1]=(double)newPacketInt[iAccelY]; + tempData[2]=(double)newPacketInt[iAccelZ]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelX])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelY])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelZ])); + uncalibratedData[iAccelX]=(double)newPacketInt[iAccelX]; + uncalibratedData[iAccelY]=(double)newPacketInt[iAccelY]; + uncalibratedData[iAccelZ]=(double)newPacketInt[iAccelZ]; + uncalibratedDataUnits[iAccelX]=NO_UNIT; + uncalibratedDataUnits[iAccelY]=NO_UNIT; + uncalibratedDataUnits[iAccelZ]=NO_UNIT; + + if (mEnableCalibration){ + double[] accelCalibratedData; + accelCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixWRAccel, mSensitivityMatrixWRAccel, mOffsetVectorWRAccel); + calibratedData[iAccelX]=accelCalibratedData[0]; + calibratedData[iAccelY]=accelCalibratedData[1]; + calibratedData[iAccelZ]=accelCalibratedData[2]; + if (mDefaultCalibrationParametersDigitalAccel == true) { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_X,new FormatCluster("CAL",ACCEL_DEFAULT_CAL_UNIT,calibratedData[iAccelX])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y,new FormatCluster("CAL",ACCEL_DEFAULT_CAL_UNIT,calibratedData[iAccelY])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z,new FormatCluster("CAL",ACCEL_DEFAULT_CAL_UNIT,calibratedData[iAccelZ])); + calibratedDataUnits[iAccelX]=ACCEL_DEFAULT_CAL_UNIT; + calibratedDataUnits[iAccelY]=ACCEL_DEFAULT_CAL_UNIT; + calibratedDataUnits[iAccelZ]=ACCEL_DEFAULT_CAL_UNIT; + if (((mEnabledSensors & SENSOR_ACCEL) == 0)){ + accelerometer.x=accelCalibratedData[0]; //this is used to calculate quaternions // skip if Low noise is enabled + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } + } else { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_X,new FormatCluster("CAL",ACCEL_CAL_UNIT,calibratedData[iAccelX])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y,new FormatCluster("CAL",ACCEL_CAL_UNIT,calibratedData[iAccelY])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z,new FormatCluster("CAL",ACCEL_CAL_UNIT,calibratedData[iAccelZ])); + calibratedDataUnits[iAccelX]=ACCEL_CAL_UNIT; + calibratedDataUnits[iAccelY]=ACCEL_CAL_UNIT; + calibratedDataUnits[iAccelZ]=ACCEL_CAL_UNIT; + if (((mEnabledSensors & SENSOR_ACCEL) == 0)){ + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } + + } + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.GYRO) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.GYRO) > 0) + ) { + int iGyroX=getSignalIndex(Shimmer3.ObjectClusterSensorName.GYRO_X); + int iGyroY=getSignalIndex(Shimmer3.ObjectClusterSensorName.GYRO_Y); + int iGyroZ=getSignalIndex(Shimmer3.ObjectClusterSensorName.GYRO_Z); + tempData[0]=(double)newPacketInt[iGyroX]; + tempData[1]=(double)newPacketInt[iGyroY]; + tempData[2]=(double)newPacketInt[iGyroZ]; + + + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroX])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroY])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroZ])); + uncalibratedData[iGyroX]=(double)newPacketInt[iGyroX]; + uncalibratedData[iGyroY]=(double)newPacketInt[iGyroY]; + uncalibratedData[iGyroZ]=(double)newPacketInt[iGyroZ]; + uncalibratedDataUnits[iGyroX]=NO_UNIT; + uncalibratedDataUnits[iGyroY]=NO_UNIT; + uncalibratedDataUnits[iGyroZ]=NO_UNIT; + if (mEnableCalibration){ + double[] gyroCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixGyroscope, mSensitivityMatrixGyroscope, mOffsetVectorGyroscope); + calibratedData[iGyroX]=gyroCalibratedData[0]; + calibratedData[iGyroY]=gyroCalibratedData[1]; + calibratedData[iGyroZ]=gyroCalibratedData[2]; + if (mDefaultCalibrationParametersGyro == true) { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_X,new FormatCluster("CAL",GYRO_DEFAULT_CAL_UNIT,gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_Y,new FormatCluster("CAL",GYRO_DEFAULT_CAL_UNIT,gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_Z,new FormatCluster("CAL",GYRO_DEFAULT_CAL_UNIT,gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + calibratedDataUnits[iGyroX]=GYRO_DEFAULT_CAL_UNIT; + calibratedDataUnits[iGyroY]=GYRO_DEFAULT_CAL_UNIT; + calibratedDataUnits[iGyroZ]=GYRO_DEFAULT_CAL_UNIT; + } else { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_X,new FormatCluster("CAL",GYRO_CAL_UNIT,gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_Y,new FormatCluster("CAL",GYRO_CAL_UNIT,gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GYRO_Z,new FormatCluster("CAL",GYRO_CAL_UNIT,gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + calibratedDataUnits[iGyroX]=GYRO_CAL_UNIT; + calibratedDataUnits[iGyroY]=GYRO_CAL_UNIT; + calibratedDataUnits[iGyroZ]=GYRO_CAL_UNIT; + + } + if (mEnableOntheFlyGyroOVCal){ + mGyroX.addValue(gyroCalibratedData[0]); + mGyroY.addValue(gyroCalibratedData[1]); + mGyroZ.addValue(gyroCalibratedData[2]); + mGyroXRaw.addValue((double)newPacketInt[iGyroX]); + mGyroYRaw.addValue((double)newPacketInt[iGyroY]); + mGyroZRaw.addValue((double)newPacketInt[iGyroZ]); + if (mGyroX.getStandardDeviation() 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.MAG) > 0) + ) { + int iMagX=getSignalIndex(Shimmer3.ObjectClusterSensorName.MAG_X); + int iMagY=getSignalIndex(Shimmer3.ObjectClusterSensorName.MAG_Y); + int iMagZ=getSignalIndex(Shimmer3.ObjectClusterSensorName.MAG_Z); + tempData[0]=(double)newPacketInt[iMagX]; + tempData[1]=(double)newPacketInt[iMagY]; + tempData[2]=(double)newPacketInt[iMagZ]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagX])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagY])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagZ])); + uncalibratedData[iMagX]=(double)newPacketInt[iMagX]; + uncalibratedData[iMagY]=(double)newPacketInt[iMagY]; + uncalibratedData[iMagZ]=(double)newPacketInt[iMagZ]; + uncalibratedDataUnits[iMagX]=NO_UNIT; + uncalibratedDataUnits[iMagY]=NO_UNIT; + uncalibratedDataUnits[iMagZ]=NO_UNIT; + if (mEnableCalibration){ + double[] magCalibratedData; + magCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixMagnetometer, mSensitivityMatrixMagnetometer, mOffsetVectorMagnetometer); + calibratedData[iMagX]=magCalibratedData[0]; + calibratedData[iMagY]=magCalibratedData[1]; + calibratedData[iMagZ]=magCalibratedData[2]; + if (mDefaultCalibrationParametersMag == true) { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_X,new FormatCluster("CAL",MAG_DEFAULT_CAL_UNIT,magCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_Y,new FormatCluster("CAL",MAG_DEFAULT_CAL_UNIT,magCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_Z,new FormatCluster("CAL",MAG_DEFAULT_CAL_UNIT,magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + calibratedDataUnits[iMagX]=MAG_DEFAULT_CAL_UNIT; + calibratedDataUnits[iMagY]=MAG_DEFAULT_CAL_UNIT; + calibratedDataUnits[iMagZ]=MAG_DEFAULT_CAL_UNIT; + } else { + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_X,new FormatCluster("CAL",MAG_CAL_UNIT,magCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_Y,new FormatCluster("CAL",MAG_CAL_UNIT,magCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.MAG_Z,new FormatCluster("CAL",MAG_CAL_UNIT,magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + calibratedDataUnits[iMagX]=MAG_CAL_UNIT; + calibratedDataUnits[iMagY]=MAG_CAL_UNIT; + calibratedDataUnits[iMagZ]=MAG_CAL_UNIT; + } + } + } + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.BATTERY) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.BATTERY) > 0) + ) { + int iBatt = getSignalIndex(Shimmer3.ObjectClusterSensorName.BATTERY); + tempData[0] = (double)newPacketInt[iBatt]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.BATTERY,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBatt])); + uncalibratedData[iBatt]=(double)newPacketInt[iBatt]; + uncalibratedDataUnits[iBatt]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iBatt]=calibrateU12AdcValue(tempData[0],0,3,1)*2; + calibratedDataUnits[iBatt] = ADC_CAL_UNIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.BATTERY,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iBatt])); + mVSenseBattMA.addValue(calibratedData[iBatt]); + checkBattery(); + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXT_EXP_A7) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXT_EXP_A7) > 0) + ) { + int iA7 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXT_EXP_A7); + tempData[0] = (double)newPacketInt[iA7]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXT_EXP_A7,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA7])); + uncalibratedData[iA7]=(double)newPacketInt[iA7]; + uncalibratedDataUnits[iA7]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iA7]=calibrateU12AdcValue(tempData[0],0,3,1); + calibratedDataUnits[iA7] = ADC_CAL_UNIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXT_EXP_A7,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA7])); + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXT_EXP_A6) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXT_EXP_A6) > 0) + ) { + int iA6 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXT_EXP_A6); + tempData[0] = (double)newPacketInt[iA6]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXT_EXP_A6,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA6])); + uncalibratedData[iA6]=(double)newPacketInt[iA6]; + uncalibratedDataUnits[iA6]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iA6]=calibrateU12AdcValue(tempData[0],0,3,1); + calibratedDataUnits[iA6] = ADC_CAL_UNIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXT_EXP_A6,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA6])); + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXT_EXP_A15) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXT_EXP_A15) > 0) + ) { + int iA15 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXT_EXP_A15); + tempData[0] = (double)newPacketInt[iA15]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXT_EXP_A15,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA15])); + uncalibratedData[iA15]=(double)newPacketInt[iA15]; + uncalibratedDataUnits[iA15]=NO_UNIT; + + if (mEnableCalibration){ + calibratedData[iA15]=calibrateU12AdcValue(tempData[0],0,3,1); + calibratedDataUnits[iA15] = ADC_CAL_UNIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXT_EXP_A15,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA15])); + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.INT_EXP_A1) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.INT_EXP_A1) > 0) + ) { + int iA1 = getSignalIndex(Shimmer3.ObjectClusterSensorName.INT_EXP_A1); + tempData[0] = (double)newPacketInt[iA1]; + String sensorName = Shimmer3.ObjectClusterSensorName.INT_EXP_A1; + + //to Support derived sensor renaming + if (fwIdentifier == FW_TYPE_SD){ + //change name based on derived sensor value + if ((mDerivedSensors & SDLogHeaderDerivedSensors.PPG2_1_14)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.PPG2_A1; + } else if ((mDerivedSensors & SDLogHeaderDerivedSensors.RES_AMP)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.RESISTANCE_AMP; + } + } + sensorNames[iA1]=sensorName; + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA1])); + uncalibratedData[iA1]=(double)newPacketInt[iA1]; + uncalibratedDataUnits[iA1]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iA1]=calibrateU12AdcValue(tempData[0],0,3,1); + calibratedDataUnits[iA1] = ADC_CAL_UNIT; + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA1])); + } + + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.INT_EXP_A12) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.INT_EXP_A12) > 0) + ) { + int iA12 = getSignalIndex(Shimmer3.ObjectClusterSensorName.INT_EXP_A12); + tempData[0] = (double)newPacketInt[iA12]; + String sensorName = Shimmer3.ObjectClusterSensorName.INT_EXP_A12; + //to Support derived sensor renaming + if (fwIdentifier == FW_TYPE_SD){ + //change name based on derived sensor value + if ((mDerivedSensors & SDLogHeaderDerivedSensors.PPG_12_13)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.PPG_A12; + } else if ((mDerivedSensors & SDLogHeaderDerivedSensors.PPG1_12_13)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.PPG1_A12; + } + } + + sensorNames[iA12]=sensorName; + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA12])); + uncalibratedData[iA12]=(double)newPacketInt[iA12]; + uncalibratedDataUnits[iA12]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iA12]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA12])); + calibratedDataUnits[iA12] = ADC_CAL_UNIT; + + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.INT_EXP_A13) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.INT_EXP_A13) > 0) + ) { + int iA13 = getSignalIndex(Shimmer3.ObjectClusterSensorName.INT_EXP_A13); + tempData[0] = (double)newPacketInt[iA13]; + String sensorName = Shimmer3.ObjectClusterSensorName.INT_EXP_A13; + //to Support derived sensor renaming + if (fwIdentifier == FW_TYPE_SD){ + //change name based on derived sensor value + if ((mDerivedSensors & SDLogHeaderDerivedSensors.PPG_12_13)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.PPG_A13; + } else if ((mDerivedSensors & SDLogHeaderDerivedSensors.PPG1_12_13)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.PPG1_A13; + } + } + + sensorNames[iA13]=sensorName; + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA13])); + uncalibratedData[iA13]=(double)newPacketInt[iA13]; + uncalibratedDataUnits[iA13]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iA13]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA13])); + calibratedDataUnits[iA13] = ADC_CAL_UNIT; + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.INT_EXP_A14) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.INT_EXP_A14) > 0) + ) { + int iA14 = getSignalIndex(Shimmer3.ObjectClusterSensorName.INT_EXP_A14); + tempData[0] = (double)newPacketInt[iA14]; + String sensorName = Shimmer3.ObjectClusterSensorName.INT_EXP_A14; + //to Support derived sensor renaming + if (fwIdentifier == FW_TYPE_SD){ + //change name based on derived sensor value + if ((mDerivedSensors & SDLogHeaderDerivedSensors.PPG2_1_14)>0){ + sensorName = Shimmer3.ObjectClusterSensorName.PPG2_A14; + } + } + sensorNames[iA14]=sensorName; + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA14])); + uncalibratedData[iA14]=(double)newPacketInt[iA14]; + uncalibratedDataUnits[iA14]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iA14]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put(sensorName,new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iA14])); + calibratedDataUnits[iA14] = ADC_CAL_UNIT; + } + } + //((fwIdentifier == FW_IDEN_BTSTREAM) && (mEnabledSensors & BTStream.ACCEL_WR) > 0) + //|| ((fwIdentifier == FW_IDEN_SD) && (mEnabledSensors & SDLogHeader.ACCEL_WR) > 0) + + + + + if (((fwIdentifier == FW_TYPE_BT)&&((mEnabledSensors & BTStream.ACCEL_LN) > 0 || (mEnabledSensors & BTStream.ACCEL_WR) > 0) && ((mEnabledSensors & BTStream.GYRO) > 0) && ((mEnabledSensors & BTStream.MAG) > 0) && mOrientationEnabled ) + ||((fwIdentifier == FW_TYPE_SD)&&((mEnabledSensors & SDLogHeader.ACCEL_LN) > 0 || (mEnabledSensors & SDLogHeader.ACCEL_WR) > 0) && ((mEnabledSensors & SDLogHeader.GYRO) > 0) && ((mEnabledSensors & SDLogHeader.MAG) > 0) && mOrientationEnabled )){ + if (mEnableCalibration){ + if (mOrientationAlgo==null){ + mOrientationAlgo = new GradDes3DOrientation(0.4, (double)1/mShimmerSamplingRate, 1, 0, 0,0); + } + Quaternion q = mOrientationAlgo.update(accelerometer.x,accelerometer.y,accelerometer.z, gyroscope.x,gyroscope.y,gyroscope.z, magnetometer.x,magnetometer.y,magnetometer.z); double theta, Rx, Ry, Rz, rho; + rho = Math.acos(q.q1); + theta = rho * 2; + Rx = q.q2 / Math.sin(rho); + Ry = q.q3 / Math.sin(rho); + Rz = q.q4 / Math.sin(rho); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_A,new FormatCluster("CAL","local",theta)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_X,new FormatCluster("CAL","local",Rx)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Y,new FormatCluster("CAL","local",Ry)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Z,new FormatCluster("CAL","local",Rz)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_W,new FormatCluster("CAL","local",q.q1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_X,new FormatCluster("CAL","local",q.q2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y,new FormatCluster("CAL","local",q.q3)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z,new FormatCluster("CAL","local",q.q4)); + } + } + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXG1_24BIT) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXG1_24BIT) > 0) + ){ + int iexg1ch1 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT); + int iexg1ch2 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT); + int iexg1sta = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG1_STATUS); + double exg1ch1 = (double)newPacketInt[iexg1ch1]; + double exg1ch2 = (double)newPacketInt[iexg1ch2]; + double exg1sta = (double)newPacketInt[iexg1sta]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_STATUS,new FormatCluster("RAW",NO_UNIT,exg1sta)); + uncalibratedData[iexg1sta]=(double)newPacketInt[iexg1sta]; + uncalibratedData[iexg1ch1]=(double)newPacketInt[iexg1ch1]; + uncalibratedData[iexg1ch2]=(double)newPacketInt[iexg1ch2]; + uncalibratedDataUnits[iexg1sta]=NO_UNIT; + uncalibratedDataUnits[iexg1ch1]=NO_UNIT; + uncalibratedDataUnits[iexg1ch2]=NO_UNIT; + if (mEnableCalibration){ + double calexg1ch1 = exg1ch1 *(((2.42*1000)/mEXG1CH1GainValue)/(Math.pow(2,23)-1)); + double calexg1ch2 = exg1ch2 *(((2.42*1000)/mEXG1CH2GainValue)/(Math.pow(2,23)-1)); + calibratedData[iexg1ch1]=calexg1ch1; + calibratedData[iexg1ch2]=calexg1ch2; + calibratedData[iexg1sta]=(double)newPacketInt[iexg1sta]; + calibratedDataUnits[iexg1sta]=NO_UNIT; + calibratedDataUnits[iexg1ch1]=ADC_CAL_UNIT; + calibratedDataUnits[iexg1ch2]=ADC_CAL_UNIT; + if (isEXGUsingDefaultECGConfiguration()){ + sensorNames[iexg1ch1]=Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT; + sensorNames[iexg1ch2]=Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT,new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT,new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch2)); + } else if (isEXGUsingDefaultEMGConfiguration()){ + sensorNames[iexg1ch1]=Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT; + sensorNames[iexg1ch2]=Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT,new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT,new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch2)); + } else { + sensorNames[iexg1ch1]=Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT; + sensorNames[iexg1ch2]=Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT,new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT,new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch2)); + } + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXG2_24BIT) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXG2_24BIT) > 0) + ){ + int iexg2ch1 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT); + int iexg2ch2 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT); + int iexg2sta = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG2_STATUS); + double exg2ch1 = (double)newPacketInt[iexg2ch1]; + double exg2ch2 = (double)newPacketInt[iexg2ch2]; + double exg2sta = (double)newPacketInt[iexg2sta]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_STATUS,new FormatCluster("RAW",NO_UNIT,exg2sta)); + uncalibratedData[iexg2sta]=(double)newPacketInt[iexg2sta]; + uncalibratedData[iexg2ch1]=(double)newPacketInt[iexg2ch1]; + uncalibratedData[iexg2ch2]=(double)newPacketInt[iexg2ch2]; + uncalibratedDataUnits[iexg2sta]=NO_UNIT; + uncalibratedDataUnits[iexg2ch1]=NO_UNIT; + uncalibratedDataUnits[iexg2ch2]=NO_UNIT; + if (mEnableCalibration){ + double calexg2ch1 = exg2ch1 *(((2.42*1000)/mEXG2CH1GainValue)/(Math.pow(2,23)-1)); + double calexg2ch2 = exg2ch2 *(((2.42*1000)/mEXG2CH2GainValue)/(Math.pow(2,23)-1)); + calibratedData[iexg2ch1]=calexg2ch1; + calibratedData[iexg2ch2]=calexg2ch2; + calibratedData[iexg2sta]=(double)newPacketInt[iexg2sta]; + calibratedDataUnits[iexg2sta]=NO_UNIT; + calibratedDataUnits[iexg2ch1]=ADC_CAL_UNIT; + calibratedDataUnits[iexg2ch2]=ADC_CAL_UNIT; + if (isEXGUsingDefaultECGConfiguration()){ + sensorNames[iexg2ch1]=Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT; + sensorNames[iexg2ch2]=Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT,new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch2)); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + sensorNames[iexg2ch1]=Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT; + sensorNames[iexg2ch2]=Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,0)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,0)); + } else { + sensorNames[iexg2ch1]=Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT; + sensorNames[iexg2ch2]=Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch2)); + } + } + } + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXG1_16BIT) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXG1_16BIT) > 0) + ){ + int iexg1ch1 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT); + int iexg1ch2 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT); + int iexg1sta = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG1_STATUS); + double exg1ch1 = (double)newPacketInt[iexg1ch1]; + double exg1ch2 = (double)newPacketInt[iexg1ch2]; + double exg1sta = (double)newPacketInt[iexg1sta]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_STATUS,new FormatCluster("RAW",NO_UNIT,exg1sta)); + uncalibratedData[iexg1sta]=(double)newPacketInt[iexg1sta]; + uncalibratedData[iexg1ch1]=(double)newPacketInt[iexg1ch1]; + uncalibratedData[iexg1ch2]=(double)newPacketInt[iexg1ch2]; + uncalibratedDataUnits[iexg1sta]=NO_UNIT; + uncalibratedDataUnits[iexg1ch1]=NO_UNIT; + uncalibratedDataUnits[iexg1ch2]=NO_UNIT; + if (mEnableCalibration){ + double calexg1ch1 = exg1ch1 *(((2.42*1000)/(mEXG1CH1GainValue*2))/(Math.pow(2,15)-1)); + double calexg1ch2 = exg1ch2 *(((2.42*1000)/(mEXG1CH2GainValue*2))/(Math.pow(2,15)-1)); + calibratedData[iexg1ch1]=calexg1ch1; + calibratedData[iexg1ch2]=calexg1ch2; + calibratedData[iexg1sta]=(double)newPacketInt[iexg1sta]; + calibratedDataUnits[iexg1sta]=NO_UNIT; + calibratedDataUnits[iexg1ch1]=ADC_CAL_UNIT; + calibratedDataUnits[iexg1ch2]=ADC_CAL_UNIT; + if (isEXGUsingDefaultECGConfiguration()){ + sensorNames[iexg1ch1]=Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT; + sensorNames[iexg1ch2]=Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT,new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT,new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch2)); + } else if (isEXGUsingDefaultEMGConfiguration()){ + sensorNames[iexg1ch1]=Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT; + sensorNames[iexg1ch2]=Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT,new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT,new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch2)); + } else { + sensorNames[iexg1ch1]=Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT; + sensorNames[iexg1ch2]=Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT,new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT,new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg1ch2)); + } + } + } + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.EXG2_16BIT) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.EXG2_16BIT) > 0) + ){ + int iexg2ch1 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT); + int iexg2ch2 = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT); + int iexg2sta = getSignalIndex(Shimmer3.ObjectClusterSensorName.EXG2_STATUS); + double exg2ch1 = (double)newPacketInt[iexg2ch1]; + double exg2ch2 = (double)newPacketInt[iexg2ch2]; + double exg2sta = (double)newPacketInt[iexg2sta]; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_STATUS,new FormatCluster("RAW",NO_UNIT,exg2sta)); + uncalibratedData[iexg2sta]=(double)newPacketInt[iexg2sta]; + uncalibratedData[iexg2ch1]=(double)newPacketInt[iexg2ch1]; + uncalibratedData[iexg2ch2]=(double)newPacketInt[iexg2ch2]; + uncalibratedDataUnits[iexg2sta]=NO_UNIT; + uncalibratedDataUnits[iexg2ch1]=NO_UNIT; + uncalibratedDataUnits[iexg2ch2]=NO_UNIT; + if (mEnableCalibration){ + double calexg2ch1 = ((exg2ch1)) *(((2.42*1000)/(mEXG2CH1GainValue*2))/(Math.pow(2,15)-1)); + double calexg2ch2 = ((exg2ch2)) *(((2.42*1000)/(mEXG2CH2GainValue*2))/(Math.pow(2,15)-1)); + calibratedData[iexg2ch1]=calexg2ch1; + calibratedData[iexg2ch2]=calexg2ch2; + calibratedData[iexg2sta]=(double)newPacketInt[iexg2sta]; + calibratedDataUnits[iexg2sta]=NO_UNIT; + calibratedDataUnits[iexg2ch1]=ADC_CAL_UNIT; + calibratedDataUnits[iexg2ch2]=ADC_CAL_UNIT; + if (isEXGUsingDefaultECGConfiguration()){ + sensorNames[iexg2ch1]=Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT; + sensorNames[iexg2ch2]=Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT,new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch2)); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + sensorNames[iexg2ch1]=Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT; + sensorNames[iexg2ch2]=Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,0)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,0)); + } else { + sensorNames[iexg2ch1]=Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT; + sensorNames[iexg2ch2]=Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT; + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch1)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,new FormatCluster("CAL",ADC_CAL_UNIT,calexg2ch1)); + } + } + } + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.BMP180) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.BMP180) > 0) + ){ + int iUT = getSignalIndex(Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180); + int iUP = getSignalIndex(Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180); + double UT = (double)newPacketInt[iUT]; + double UP = (double)newPacketInt[iUP]; + UP=UP/Math.pow(2,8-mPressureResolution); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180,new FormatCluster("RAW",NO_UNIT,UP)); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180,new FormatCluster("RAW",NO_UNIT,UT)); + uncalibratedData[iUT]=(double)newPacketInt[iUT]; + uncalibratedData[iUP]=(double)newPacketInt[iUP]; + uncalibratedDataUnits[iUT]=NO_UNIT; + uncalibratedDataUnits[iUP]=NO_UNIT; + if (mEnableCalibration){ + double[] bmp180caldata= calibratePressureSensorData(UP,UT); + objectCluster.mPropertyCluster.put("Pressure",new FormatCluster("CAL",PRESSURE_CAL_UNIT,bmp180caldata[0]/1000)); + objectCluster.mPropertyCluster.put("Temperature",new FormatCluster("CAL",TEMP_CAL_UNIT,bmp180caldata[1])); + calibratedData[iUT]=bmp180caldata[1]; + calibratedData[iUP]=bmp180caldata[0]/1000; + calibratedDataUnits[iUT]=TEMP_CAL_UNIT; + calibratedDataUnits[iUP]=PRESSURE_CAL_UNIT; + } + } + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.BRIDGE_AMP) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.BRIDGE_AMP) > 0) + ) { + int iBAHigh = getSignalIndex(Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH); + int iBALow = getSignalIndex(Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBAHigh])); + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBALow])); + uncalibratedData[iBAHigh]=(double)newPacketInt[iBAHigh]; + uncalibratedData[iBALow]=(double)newPacketInt[iBALow]; + uncalibratedDataUnits[iBAHigh]=NO_UNIT; + uncalibratedDataUnits[iBALow]=NO_UNIT; + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iBAHigh]; + tempData[1] = (double)newPacketInt[iBALow]; + calibratedData[iBAHigh]=calibrateU12AdcValue(tempData[0],60,3,551); + calibratedData[iBALow]=calibrateU12AdcValue(tempData[1],1950,3,183.7); + calibratedDataUnits[iBAHigh]=ADC_CAL_UNIT; + calibratedDataUnits[iBALow]=ADC_CAL_UNIT; + objectCluster.mPropertyCluster.put("Bridge Amplifier High",new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iBAHigh])); + objectCluster.mPropertyCluster.put("Bridge Amplifier Low",new FormatCluster("CAL",ADC_CAL_UNIT,calibratedData[iBALow])); + } + } + + if (((fwIdentifier == FW_TYPE_BT) && (mEnabledSensors & BTStream.GSR) > 0) + || ((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.GSR) > 0) + ) { + int iGSR = getSignalIndex(Shimmer3.ObjectClusterSensorName.GSR); + double p1=0,p2=0;//,p3=0,p4=0,p5=0; + if (fwIdentifier == FW_TYPE_SD && mFirmwareVersionMajor ==0 && mFirmwareVersionMinor==9){ + tempData[0] = (double)newPacketInt[iGSR]; + int gsrUncalibratedData = ((int)tempData[0] & 4095); + int newGSRRange = -1; // initialized to -1 so it will only come into play if mGSRRange = 4 + + /* + * for i = 2:length(range) + * if range(i-1)~=range(i) + * if abs(gsrValue(i-1)-gsrValue(i))< 300 + * range(i) = range(i-1); + * end + * end + * end + */ + + if (mGSRRange==4){ + newGSRRange=(49152 & (int)tempData[0])>>14; + if (mPastGSRFirstTime){ + mPastGSRRange = newGSRRange; + mPastGSRFirstTime = false; + } + if (newGSRRange != mPastGSRRange) + { + + if (Math.abs(mPastGSRUncalibratedValue-gsrUncalibratedData)<300){ + newGSRRange = mPastGSRRange; + } else { + mPastGSRRange = newGSRRange; + } + mPastGSRUncalibratedValue = gsrUncalibratedData; + } + + } + if (mGSRRange==0 || newGSRRange==0) { //Note that from FW 1.0 onwards the MSB of the GSR data contains the range + // the polynomial function used for calibration has been deprecated, it is replaced with a linear function + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0373; + p2 = -24.9915; + } else { + //p1 = 0.0363; + //p2 = -24.8617; + p1 = 0.0373; + p2 = -24.9915; + } + } else if (mGSRRange==1 || newGSRRange==1) { + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0054; + p2 = -3.5194; + } else { + //p1 = 0.0051; + //p2 = -3.8357; + p1 = 0.0054; + p2 = -3.5194; + } + } else if (mGSRRange==2 || newGSRRange==2) { + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0015; + p2 = -1.0163; + } else { + //p1 = 0.0015; + //p2 = -1.0067; + p1 = 0.0015; + p2 = -1.0163; + } + } else if (mGSRRange==3 || newGSRRange==3) { + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 4.5580e-04; + p2 = -0.3014; + } else { + //p1 = 4.4513e-04; + //p2 = -0.3193; + p1 = 4.5580e-04; + p2 = -0.3014; + } + } + } else { + tempData[0] = (double)newPacketInt[iGSR]; + int newGSRRange = -1; // initialized to -1 so it will only come into play if mGSRRange = 4 + + if (mGSRRange==4){ + newGSRRange=(49152 & (int)tempData[0])>>14; + } + if (mGSRRange==0 || newGSRRange==0) { //Note that from FW 1.0 onwards the MSB of the GSR data contains the range + // the polynomial function used for calibration has been deprecated, it is replaced with a linear function + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0373; + p2 = -24.9915; + + } else { //Values have been reverted to 2r values + //p1 = 0.0363; + //p2 = -24.8617; + p1 = 0.0373; + p2 = -24.9915; + } + } else if (mGSRRange==1 || newGSRRange==1) { + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0054; + p2 = -3.5194; + } else { + //p1 = 0.0051; + //p2 = -3.8357; + p1 = 0.0054; + p2 = -3.5194; + } + } else if (mGSRRange==2 || newGSRRange==2) { + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0015; + p2 = -1.0163; + } else { + //p1 = 0.0015; + //p2 = -1.0067; + p1 = 0.0015; + p2 = -1.0163; + } + } else if (mGSRRange==3 || newGSRRange==3) { + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 4.5580e-04; + p2 = -0.3014; + } else { + //p1 = 4.4513e-04; + //p2 = -0.3193; + p1 = 4.5580e-04; + p2 = -0.3014; + } + } + } + objectCluster.mPropertyCluster.put(Shimmer3.ObjectClusterSensorName.GSR,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGSR])); + uncalibratedData[iGSR]=(double)newPacketInt[iGSR]; + uncalibratedDataUnits[iGSR]=NO_UNIT; + if (mEnableCalibration){ + calibratedData[iGSR] = calibrateGsrData(tempData[0],p1,p2); + calibratedDataUnits[iGSR]=GSR_CAL_UNIT; + objectCluster.mPropertyCluster.put("GSR",new FormatCluster("CAL",GSR_CAL_UNIT,calibratedData[iGSR])); + } + } + + if (((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.GYRO_MPU_MPL) > 0)){ + int iGyroX = getSignalIndex(Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_X); + int iGyroY = getSignalIndex(Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_Y); + int iGyroZ = getSignalIndex(Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_Z); + calibratedData[iGyroX] = (double)newPacketInt[iGyroX]/Math.pow(2, 16); + calibratedData[iGyroY] = (double)newPacketInt[iGyroY]/Math.pow(2, 16); + calibratedData[iGyroZ] = (double)newPacketInt[iGyroZ]/Math.pow(2, 16); + calibratedDataUnits[iGyroX] = GYRO_CAL_UNIT; + calibratedDataUnits[iGyroY] = GYRO_CAL_UNIT; + calibratedDataUnits[iGyroZ] = GYRO_CAL_UNIT; + uncalibratedData[iGyroX] = (double)newPacketInt[iGyroX]; + uncalibratedData[iGyroY] = (double)newPacketInt[iGyroY]; + uncalibratedData[iGyroZ] = (double)newPacketInt[iGyroZ]; + uncalibratedDataUnits[iGyroX] = NO_UNIT; + uncalibratedDataUnits[iGyroY] = NO_UNIT; + uncalibratedDataUnits[iGyroZ] = NO_UNIT; + } + + if (((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.ACCEL_MPU_MPL) > 0)){ + int iAccelX = getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_X); + int iAccelY = getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Y); + int iAccelZ = getSignalIndex(Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Z); + calibratedData[iAccelX] = (double)newPacketInt[iAccelX]/Math.pow(2, 16); + calibratedData[iAccelY] = (double)newPacketInt[iAccelY]/Math.pow(2, 16); + calibratedData[iAccelZ] = (double)newPacketInt[iAccelZ]/Math.pow(2, 16); + calibratedDataUnits[iAccelX] = ACCEL_CAL_UNIT; + calibratedDataUnits[iAccelY] = ACCEL_CAL_UNIT; + calibratedDataUnits[iAccelZ] = ACCEL_CAL_UNIT; + uncalibratedData[iAccelX] = (double)newPacketInt[iAccelX]; + uncalibratedData[iAccelY] = (double)newPacketInt[iAccelX]; + uncalibratedData[iAccelZ] = (double)newPacketInt[iAccelX]; + uncalibratedDataUnits[iAccelX] = NO_UNIT; + uncalibratedDataUnits[iAccelY] = NO_UNIT; + uncalibratedDataUnits[iAccelZ] = NO_UNIT; + } + + if (((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.MAG_MPU_MPL) > 0)){ + int iMagX = getSignalIndex(Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_X); + int iMagY = getSignalIndex(Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_Y); + int iMagZ = getSignalIndex(Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_Z); + calibratedData[iMagX] = (double)newPacketInt[iMagX]/Math.pow(2, 16); + calibratedData[iMagY] = (double)newPacketInt[iMagY]/Math.pow(2, 16); + calibratedData[iMagZ] = (double)newPacketInt[iMagZ]/Math.pow(2, 16); + calibratedDataUnits[iMagX] = MAG_CAL_UNIT; + calibratedDataUnits[iMagY] = MAG_CAL_UNIT; + calibratedDataUnits[iMagZ] = MAG_CAL_UNIT; + uncalibratedData[iMagX] = (double)newPacketInt[iMagX]; + uncalibratedData[iMagY] = (double)newPacketInt[iMagY]; + uncalibratedData[iMagZ] = (double)newPacketInt[iMagZ]; + uncalibratedDataUnits[iMagX] = NO_UNIT; + uncalibratedDataUnits[iMagY] = NO_UNIT; + uncalibratedDataUnits[iMagZ] = NO_UNIT; + } + + if (((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.MPL_QUAT_6DOF) > 0)){ + int iQW = getSignalIndex(Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_W); + int iQX = getSignalIndex(Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_X); + int iQY = getSignalIndex(Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_Y); + int iQZ = getSignalIndex(Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_Z); + calibratedData[iQW] = (double)newPacketInt[iQW]/Math.pow(2, 30); + calibratedData[iQX] = (double)newPacketInt[iQX]/Math.pow(2, 30); + calibratedData[iQY] = (double)newPacketInt[iQY]/Math.pow(2, 30); + calibratedData[iQZ] = (double)newPacketInt[iQZ]/Math.pow(2, 30); + calibratedDataUnits[iQW] = NO_UNIT; + calibratedDataUnits[iQX] = NO_UNIT; + calibratedDataUnits[iQY] = NO_UNIT; + calibratedDataUnits[iQZ] = NO_UNIT; + uncalibratedData[iQW] = (double)newPacketInt[iQW]; + uncalibratedData[iQX] = (double)newPacketInt[iQX]; + uncalibratedData[iQY] = (double)newPacketInt[iQY]; + uncalibratedData[iQZ] = (double)newPacketInt[iQZ]; + uncalibratedDataUnits[iQW] = NO_UNIT; + uncalibratedDataUnits[iQX] = NO_UNIT; + uncalibratedDataUnits[iQY] = NO_UNIT; + calibratedDataUnits[iQZ] = NO_UNIT; + } + if (((fwIdentifier == FW_TYPE_SD) && (mEnabledSensors & SDLogHeader.MPL_TEMPERATURE) > 0)){ + int iT = getSignalIndex(Shimmer3.ObjectClusterSensorName.MPL_TEMPERATURE); + calibratedData[iT] = (double)newPacketInt[iT]/Math.pow(2, 16); + calibratedDataUnits[iT] = TEMP_CAL_UNIT; + uncalibratedData[iT] = (double)newPacketInt[iT]; + uncalibratedDataUnits[iT] = NO_UNIT; + } + objectCluster.mCalData = calibratedData; + objectCluster.mUncalData = uncalibratedData; + objectCluster.mUnitCal = calibratedDataUnits; + objectCluster.mUnitUncal = uncalibratedDataUnits; + objectCluster.mSensorNames = sensorNames; + + } else if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + //start of Shimmer2 + + int iTimeStamp=getSignalIndex("TimeStamp"); //find index + double calibratedTS = calibrateTimeStamp((double)newPacketInt[iTimeStamp]); + + //TIMESTAMP + if (fwIdentifier == FW_TYPE_BT){ + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iTimeStamp])); + uncalibratedData[iTimeStamp] = (double)newPacketInt[iTimeStamp]; + uncalibratedDataUnits[iTimeStamp] = NO_UNIT; + if (mEnableCalibration){ + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("CAL","mSecs",calibratedTS)); + calibratedData[iTimeStamp] = calibratedTS; + calibratedDataUnits[iTimeStamp] = "mSecs"; + } + } + + if ((mEnabledSensors & SENSOR_ACCEL) > 0){ + int iAccelX=getSignalIndex(Shimmer2.ObjectClusterSensorName.ACCEL_X); //find index + int iAccelY=getSignalIndex(Shimmer2.ObjectClusterSensorName.ACCEL_Y); //find index + int iAccelZ=getSignalIndex(Shimmer2.ObjectClusterSensorName.ACCEL_Z); //find index + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelX])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelY])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelZ])); + if (mEnableCalibration){ + tempData[0]=(double)newPacketInt[iAccelX]; + tempData[1]=(double)newPacketInt[iAccelY]; + tempData[2]=(double)newPacketInt[iAccelZ]; + double[] accelCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixAnalogAccel, mSensitivityMatrixAnalogAccel, mOffsetVectorAnalogAccel); + calibratedData[iAccelX]=accelCalibratedData[0]; + calibratedData[iAccelY]=accelCalibratedData[1]; + calibratedData[iAccelZ]=accelCalibratedData[2]; + if (mDefaultCalibrationParametersAccel == true) { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_X,new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_Y,new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_Z,new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[2])); + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_X,new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_Y,new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ACCEL_Z,new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[2])); + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } + } + + } + + if ((mEnabledSensors & SENSOR_GYRO) > 0) { + int iGyroX=getSignalIndex(Shimmer2.ObjectClusterSensorName.GYRO_X); + int iGyroY=getSignalIndex(Shimmer2.ObjectClusterSensorName.GYRO_Y); + int iGyroZ=getSignalIndex(Shimmer2.ObjectClusterSensorName.GYRO_Z); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroX])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroY])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroZ])); + if (mEnableCalibration){ + tempData[0]=(double)newPacketInt[iGyroX]; + tempData[1]=(double)newPacketInt[iGyroY]; + tempData[2]=(double)newPacketInt[iGyroZ]; + double[] gyroCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixGyroscope, mSensitivityMatrixGyroscope, mOffsetVectorGyroscope); + calibratedData[iGyroX]=gyroCalibratedData[0]; + calibratedData[iGyroY]=gyroCalibratedData[1]; + calibratedData[iGyroZ]=gyroCalibratedData[2]; + if (mDefaultCalibrationParametersGyro == true) { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_X,new FormatCluster("CAL","deg/sec*",gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_Y,new FormatCluster("CAL","deg/sec*",gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_Z,new FormatCluster("CAL","deg/sec*",gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_X,new FormatCluster("CAL","deg/sec",gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_Y,new FormatCluster("CAL","deg/sec",gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GYRO_Z,new FormatCluster("CAL","deg/sec",gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + if (mEnableOntheFlyGyroOVCal){ + mGyroX.addValue(gyroCalibratedData[0]); + mGyroY.addValue(gyroCalibratedData[1]); + mGyroZ.addValue(gyroCalibratedData[2]); + mGyroXRaw.addValue((double)newPacketInt[iGyroX]); + mGyroYRaw.addValue((double)newPacketInt[iGyroY]); + mGyroZRaw.addValue((double)newPacketInt[iGyroZ]); + if (mGyroX.getStandardDeviation() 0) { + int iMagX=getSignalIndex(Shimmer2.ObjectClusterSensorName.MAG_X); + int iMagY=getSignalIndex(Shimmer2.ObjectClusterSensorName.MAG_Y); + int iMagZ=getSignalIndex(Shimmer2.ObjectClusterSensorName.MAG_Z); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_X,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagX])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_Y,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagY])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_Z,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagZ])); + if (mEnableCalibration){ + tempData[0]=(double)newPacketInt[iMagX]; + tempData[1]=(double)newPacketInt[iMagY]; + tempData[2]=(double)newPacketInt[iMagZ]; + double[] magCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixMagnetometer, mSensitivityMatrixMagnetometer, mOffsetVectorMagnetometer); + calibratedData[iMagX]=magCalibratedData[0]; + calibratedData[iMagY]=magCalibratedData[1]; + calibratedData[iMagZ]=magCalibratedData[2]; + if (mDefaultCalibrationParametersMag == true) { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_X,new FormatCluster("CAL","local*",magCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_Y,new FormatCluster("CAL","local*",magCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_Z,new FormatCluster("CAL","local*",magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_X,new FormatCluster("CAL","local",magCalibratedData[0])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_Y,new FormatCluster("CAL","local",magCalibratedData[1])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.MAG_Z,new FormatCluster("CAL","local",magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + } + } + } + + + if ((mEnabledSensors & SENSOR_ACCEL) > 0 && (mEnabledSensors & SENSOR_GYRO) > 0 && (mEnabledSensors & SENSOR_MAG) > 0 && mOrientationEnabled ){ + if (mEnableCalibration){ + if (mOrientationAlgo==null){ + mOrientationAlgo = new GradDes3DOrientation(0.4, (double)1/mShimmerSamplingRate, 1, 0, 0,0); + } + Quaternion q = mOrientationAlgo.update(accelerometer.x,accelerometer.y,accelerometer.z, gyroscope.x,gyroscope.y,gyroscope.z, magnetometer.x,magnetometer.y,magnetometer.z); + double theta, Rx, Ry, Rz, rho; + rho = Math.acos(q.q1); + theta = rho * 2; + Rx = q.q2 / Math.sin(rho); + Ry = q.q3 / Math.sin(rho); + Rz = q.q4 / Math.sin(rho); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_A,new FormatCluster("CAL","local",theta)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_X,new FormatCluster("CAL","local",Rx)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Y,new FormatCluster("CAL","local",Ry)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Z,new FormatCluster("CAL","local",Rz)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_W,new FormatCluster("CAL","local",q.q1)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_X,new FormatCluster("CAL","local",q.q2)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y,new FormatCluster("CAL","local",q.q3)); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z,new FormatCluster("CAL","local",q.q4)); + } + } + + if ((mEnabledSensors & SENSOR_GSR) > 0) { + int iGSR = getSignalIndex(Shimmer2.ObjectClusterSensorName.GSR); + tempData[0] = (double)newPacketInt[iGSR]; + int newGSRRange = -1; // initialized to -1 so it will only come into play if mGSRRange = 4 + + double p1=0,p2=0;//,p3=0,p4=0,p5=0; + if (mGSRRange==4){ + newGSRRange=(49152 & (int)tempData[0])>>14; + } + if (mGSRRange==0 || newGSRRange==0) { //Note that from FW 1.0 onwards the MSB of the GSR data contains the range + // the polynomial function used for calibration has been deprecated, it is replaced with a linear function + + p1 = 0.0373; + p2 = -24.9915; + } else if (mGSRRange==1 || newGSRRange==1) { + p1 = 0.0054; + p2 = -3.5194; + } else if (mGSRRange==2 || newGSRRange==2) { + p1 = 0.0015; + p2 = -1.0163; + } else if (mGSRRange==3 || newGSRRange==3) { + p1 = 4.5580e-04; + p2 = -0.3014; + } + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GSR,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGSR])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iGSR]; + calibratedData[iGSR] = calibrateGsrData(tempData[0],p1,p2); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.GSR,new FormatCluster("CAL","kOhms",calibratedData[iGSR])); + } + } + if ((mEnabledSensors & SENSOR_ECG) > 0) { + int iECGRALL = getSignalIndex(Shimmer2.ObjectClusterSensorName.ECG_RA_LL); + int iECGLALL = getSignalIndex(Shimmer2.ObjectClusterSensorName.ECG_LA_LL); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ECG_RA_LL,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iECGRALL])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ECG_LA_LL,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iECGLALL])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iECGRALL]; + tempData[1] = (double)newPacketInt[iECGLALL]; + calibratedData[iECGRALL]=calibrateU12AdcValue(tempData[0],OffsetECGRALL,3,GainECGRALL); + calibratedData[iECGLALL]=calibrateU12AdcValue(tempData[1],OffsetECGLALL,3,GainECGLALL); + if (mDefaultCalibrationParametersECG == true) { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ECG_RA_LL,new FormatCluster("CAL","mVolts*",calibratedData[iECGRALL])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ECG_LA_LL,new FormatCluster("CAL","mVolts*",calibratedData[iECGLALL])); + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ECG_RA_LL,new FormatCluster("CAL","mVolts",calibratedData[iECGRALL])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.ECG_LA_LL,new FormatCluster("CAL","mVolts",calibratedData[iECGLALL])); + } + } + } + if ((mEnabledSensors & SENSOR_EMG) > 0) { + int iEMG = getSignalIndex(Shimmer2.ObjectClusterSensorName.EMG); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EMG,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iEMG])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iEMG]; + calibratedData[iEMG]=calibrateU12AdcValue(tempData[0],OffsetEMG,3,GainEMG); + if (mDefaultCalibrationParametersEMG == true){ + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EMG,new FormatCluster("CAL","mVolts*",calibratedData[iEMG])); + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EMG,new FormatCluster("CAL","mVolts",calibratedData[iEMG])); + } + } + } + if ((mEnabledSensors & SENSOR_BRIDGE_AMP) > 0) { + int iBAHigh = getSignalIndex(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH); + int iBALow = getSignalIndex(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBAHigh])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBALow])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iBAHigh]; + tempData[1] = (double)newPacketInt[iBALow]; + calibratedData[iBAHigh]=calibrateU12AdcValue(tempData[0],60,3,551); + calibratedData[iBALow]=calibrateU12AdcValue(tempData[1],1950,3,183.7); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH,new FormatCluster("CAL","mVolts",calibratedData[iBAHigh])); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW,new FormatCluster("CAL","mVolts",calibratedData[iBALow])); + } + } + if ((mEnabledSensors & SENSOR_HEART) > 0) { + int iHeartRate = getSignalIndex(Shimmer2.ObjectClusterSensorName.HEART_RATE); + tempData[0] = (double)newPacketInt[iHeartRate]; + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.HEART_RATE,new FormatCluster("RAW",NO_UNIT,tempData[0])); + if (mEnableCalibration){ + calibratedData[iHeartRate]=tempData[0]; + if (mFirmwareVersionMajor==0 && mFirmwareVersionMinor==1){ + + } else { + if (tempData[0]==0){ + calibratedData[iHeartRate]= mLastKnownHeartRate; + } else { + calibratedData[iHeartRate]=(int)(1024/tempData[0]*60); + mLastKnownHeartRate=calibratedData[iHeartRate]; + } + } + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.HEART_RATE,new FormatCluster("CAL","BPM",calibratedData[iHeartRate])); + } + } + if ((mEnabledSensors& SENSOR_EXP_BOARD_A0) > 0) { + int iA0 = getSignalIndex(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0); + tempData[0] = (double)newPacketInt[iA0]; + if (getPMux()==0){ + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0,new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.VOLT_REG,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1)*1.988; + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.VOLT_REG,new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + + } + } + if ((mEnabledSensors & SENSOR_EXP_BOARD_A7) > 0) { + int iA7 = getSignalIndex(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7); + tempData[0] = (double)newPacketInt[iA7]; + if (getPMux()==0){ + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA7])); + if (mEnableCalibration){ + calibratedData[iA7]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7,new FormatCluster("CAL","mVolts",calibratedData[iA7])); + } else { + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BATTERY,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA7])); + if (mEnableCalibration){ + calibratedData[iA7]=calibrateU12AdcValue(tempData[0],0,3,1)*2; + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BATTERY,new FormatCluster("CAL","mVolts",calibratedData[iA7])); + } + + } + } + } + if ((mEnabledSensors & SENSOR_BATT) > 0) { + int iA0 = getSignalIndex(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.VOLT_REG,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + + int iA7 = getSignalIndex(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7); + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BATTERY,new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA7])); + + + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iA0]; + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1)*1.988; + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.VOLT_REG,new FormatCluster("CAL","mVolts",calibratedData[iA0])); + + tempData[0] = (double)newPacketInt[iA7]; + calibratedData[iA7]=calibrateU12AdcValue(tempData[0],0,3,1)*2; + objectCluster.mPropertyCluster.put(Shimmer2.ObjectClusterSensorName.BATTERY,new FormatCluster("CAL","mVolts",calibratedData[iA7])); + mVSenseBattMA.addValue(calibratedData[iA7]); + checkBattery(); + } + } + + + } + + + return objectCluster; + } + + @Deprecated + protected Object buildMsg(byte[] newPacket, Object object) { + ObjectCluster objectCluster = (ObjectCluster) object; + objectCluster.mRawData = newPacket; + objectCluster.mSystemTimeStamp=ByteBuffer.allocate(8).putLong(System.currentTimeMillis()).array(); + double [] calibratedData=new double[mNChannels + 1]; //plus 1 because of the time stamp + long[] newPacketInt=parsedData(newPacket,mSignalDataTypeArray); + double[] tempData=new double[3]; + Vector3d accelerometer = new Vector3d(); + Vector3d magnetometer = new Vector3d(); + Vector3d gyroscope = new Vector3d(); + + int iTimeStamp=getSignalIndex("TimeStamp"); //find index + tempData[0]=(double)newPacketInt[1]; + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iTimeStamp])); + if (mEnableCalibration){ + objectCluster.mPropertyCluster.put("Timestamp",new FormatCluster("CAL","mSecs",calibrateTimeStamp((double)newPacketInt[iTimeStamp]))); + } + objectCluster = callAdditionalServices(objectCluster); + + + if (mHardwareVersion==HW_ID.SHIMMER_SR30 || mHardwareVersion==HW_ID.SHIMMER_3){ + if (((mEnabledSensors & SENSOR_ACCEL) > 0)){ + int iAccelX=getSignalIndex("Low Noise Accelerometer X"); //find index + int iAccelY=getSignalIndex("Low Noise Accelerometer Y"); //find index + int iAccelZ=getSignalIndex("Low Noise Accelerometer Z"); //find index + tempData[0]=(double)newPacketInt[iAccelX]; + tempData[1]=(double)newPacketInt[iAccelY]; + tempData[2]=(double)newPacketInt[iAccelZ]; + + objectCluster.mPropertyCluster.put("Low Noise Accelerometer X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelX])); + objectCluster.mPropertyCluster.put("Low Noise Accelerometer Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelY])); + objectCluster.mPropertyCluster.put("Low Noise Accelerometer Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelZ])); + + if (mEnableCalibration){ + double[] accelCalibratedData; + accelCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixAnalogAccel, mSensitivityMatrixAnalogAccel, mOffsetVectorAnalogAccel); + calibratedData[iAccelX]=accelCalibratedData[0]; + calibratedData[iAccelY]=accelCalibratedData[1]; + calibratedData[iAccelZ]=accelCalibratedData[2]; + if (mDefaultCalibrationParametersAccel == true) { + objectCluster.mPropertyCluster.put("Low Noise Accelerometer X",new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[0])); + objectCluster.mPropertyCluster.put("Low Noise Accelerometer Y",new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[1])); + objectCluster.mPropertyCluster.put("Low Noise Accelerometer Z",new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[2])); + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + + } else { + objectCluster.mPropertyCluster.put("Low Noise Accelerometer X",new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[0])); + objectCluster.mPropertyCluster.put("Low Noise Accelerometer Y",new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[1])); + objectCluster.mPropertyCluster.put("Low Noise Accelerometer Z",new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[2])); + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + + } + } + } + if (((mEnabledSensors & SENSOR_DACCEL) > 0)){ + int iAccelX=getSignalIndex("Wide Range Accelerometer X"); //find index + int iAccelY=getSignalIndex("Wide Range Accelerometer Y"); //find index + int iAccelZ=getSignalIndex("Wide Range Accelerometer Z"); //find index + //check range + + tempData[0]=(double)newPacketInt[iAccelX]; + tempData[1]=(double)newPacketInt[iAccelY]; + tempData[2]=(double)newPacketInt[iAccelZ]; + objectCluster.mPropertyCluster.put("Wide Range Accelerometer X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelX])); + objectCluster.mPropertyCluster.put("Wide Range Accelerometer Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelY])); + objectCluster.mPropertyCluster.put("Wide Range Accelerometer Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelZ])); + + + if (mEnableCalibration){ + double[] accelCalibratedData; + accelCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixWRAccel, mSensitivityMatrixWRAccel, mOffsetVectorWRAccel); + calibratedData[iAccelX]=accelCalibratedData[0]; + calibratedData[iAccelY]=accelCalibratedData[1]; + calibratedData[iAccelZ]=accelCalibratedData[2]; + if (mDefaultCalibrationParametersDigitalAccel == true) { + objectCluster.mPropertyCluster.put("Wide Range Accelerometer X",new FormatCluster("CAL","m/(sec^2)*",calibratedData[iAccelX])); + objectCluster.mPropertyCluster.put("Wide Range Accelerometer Y",new FormatCluster("CAL","m/(sec^2)*",calibratedData[iAccelY])); + objectCluster.mPropertyCluster.put("Wide Range Accelerometer Z",new FormatCluster("CAL","m/(sec^2)*",calibratedData[iAccelZ])); + if (((mEnabledSensors & SENSOR_ACCEL) == 0)){ + accelerometer.x=accelCalibratedData[0]; //this is used to calculate quaternions // skip if Low noise is enabled + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } + } else { + objectCluster.mPropertyCluster.put("Wide Range Accelerometer X",new FormatCluster("CAL","m/(sec^2)",calibratedData[iAccelX])); + objectCluster.mPropertyCluster.put("Wide Range Accelerometer Y",new FormatCluster("CAL","m/(sec^2)",calibratedData[iAccelY])); + objectCluster.mPropertyCluster.put("Wide Range Accelerometer Z",new FormatCluster("CAL","m/(sec^2)",calibratedData[iAccelZ])); + if (((mEnabledSensors & SENSOR_ACCEL) == 0)){ + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } + + } + } + } + if (((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0) { + int iGyroX=getSignalIndex("Gyroscope X"); + int iGyroY=getSignalIndex("Gyroscope Y"); + int iGyroZ=getSignalIndex("Gyroscope Z"); + tempData[0]=(double)newPacketInt[iGyroX]; + tempData[1]=(double)newPacketInt[iGyroY]; + tempData[2]=(double)newPacketInt[iGyroZ]; + + + objectCluster.mPropertyCluster.put("Gyroscope X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroX])); + objectCluster.mPropertyCluster.put("Gyroscope Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroY])); + objectCluster.mPropertyCluster.put("Gyroscope Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroZ])); + + if (mEnableCalibration){ + double[] gyroCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixGyroscope, mSensitivityMatrixGyroscope, mOffsetVectorGyroscope); + calibratedData[iGyroX]=gyroCalibratedData[0]; + calibratedData[iGyroY]=gyroCalibratedData[1]; + calibratedData[iGyroZ]=gyroCalibratedData[2]; + if (mDefaultCalibrationParametersGyro == true) { + objectCluster.mPropertyCluster.put("Gyroscope X",new FormatCluster("CAL","deg/sec*",gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put("Gyroscope Y",new FormatCluster("CAL","deg/sec*",gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put("Gyroscope Z",new FormatCluster("CAL","deg/sec*",gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + } else { + objectCluster.mPropertyCluster.put("Gyroscope X",new FormatCluster("CAL","deg/sec",gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put("Gyroscope Y",new FormatCluster("CAL","deg/sec",gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put("Gyroscope Z",new FormatCluster("CAL","deg/sec",gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + if (mEnableOntheFlyGyroOVCal){ + mGyroX.addValue(gyroCalibratedData[0]); + mGyroY.addValue(gyroCalibratedData[1]); + mGyroZ.addValue(gyroCalibratedData[2]); + mGyroXRaw.addValue((double)newPacketInt[iGyroX]); + mGyroYRaw.addValue((double)newPacketInt[iGyroY]); + mGyroZRaw.addValue((double)newPacketInt[iGyroZ]); + if (mGyroX.getStandardDeviation() 0) { + int iMagX=getSignalIndex("Magnetometer X"); + int iMagY=getSignalIndex("Magnetometer Y"); + int iMagZ=getSignalIndex("Magnetometer Z"); + tempData[0]=(double)newPacketInt[iMagX]; + tempData[1]=(double)newPacketInt[iMagY]; + tempData[2]=(double)newPacketInt[iMagZ]; + objectCluster.mPropertyCluster.put("Magnetometer X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagX])); + objectCluster.mPropertyCluster.put("Magnetometer Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagY])); + objectCluster.mPropertyCluster.put("Magnetometer Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagZ])); + if (mEnableCalibration){ + double[] magCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixMagnetometer, mSensitivityMatrixMagnetometer, mOffsetVectorMagnetometer); + calibratedData[iMagX]=magCalibratedData[0]; + calibratedData[iMagY]=magCalibratedData[1]; + calibratedData[iMagZ]=magCalibratedData[2]; + if (mDefaultCalibrationParametersMag == true) { + objectCluster.mPropertyCluster.put("Magnetometer X",new FormatCluster("CAL","local*",magCalibratedData[0])); + objectCluster.mPropertyCluster.put("Magnetometer Y",new FormatCluster("CAL","local*",magCalibratedData[1])); + objectCluster.mPropertyCluster.put("Magnetometer Z",new FormatCluster("CAL","local*",magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + } else { + objectCluster.mPropertyCluster.put("Magnetometer X",new FormatCluster("CAL","local",magCalibratedData[0])); + objectCluster.mPropertyCluster.put("Magnetometer Y",new FormatCluster("CAL","local",magCalibratedData[1])); + objectCluster.mPropertyCluster.put("Magnetometer Z",new FormatCluster("CAL","local",magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + } + } + } + + if ((mEnabledSensors & SENSOR_BATT) > 0) { + int iA0 = getSignalIndex("VSenseBatt"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("VSenseBatt",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1)*1.988; + objectCluster.mPropertyCluster.put("VSenseBatt",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + mVSenseBattMA.addValue(calibratedData[iA0]); + checkBattery(); + } + } + if ((mEnabledSensors & SENSOR_EXT_ADC_A7) > 0) { + int iA0 = getSignalIndex("External ADC A7"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("External ADC A7",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("External ADC A7",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if ((mEnabledSensors & SENSOR_EXT_ADC_A6) > 0) { + int iA0 = getSignalIndex("External ADC A6"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("External ADC A6",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("External ADC A6",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if ((mEnabledSensors & SENSOR_EXT_ADC_A15) > 0) { + int iA0 = getSignalIndex("External ADC A15"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("External ADC A15",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("External ADC A15",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if ((mEnabledSensors & SENSOR_INT_ADC_A1) > 0) { + int iA0 = getSignalIndex("Internal ADC A1"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("Internal ADC A1",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("Internal ADC A1",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if ((mEnabledSensors & SENSOR_INT_ADC_A12) > 0) { + int iA0 = getSignalIndex("Internal ADC A12"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("Internal ADC A12",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("Internal ADC A12",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if ((mEnabledSensors & SENSOR_INT_ADC_A13) > 0) { + int iA0 = getSignalIndex("Internal ADC A13"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("Internal ADC A13",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("Internal ADC A13",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if ((mEnabledSensors & SENSOR_INT_ADC_A14) > 0) { + int iA0 = getSignalIndex("Internal ADC A14"); + tempData[0] = (double)newPacketInt[iA0]; + objectCluster.mPropertyCluster.put("Internal ADC A14",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("Internal ADC A14",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } + if (((mEnabledSensors & SENSOR_ACCEL) > 0 || (mEnabledSensors & SENSOR_DACCEL) > 0) && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled ){ + if (mEnableCalibration){ + if (mOrientationAlgo==null){ + mOrientationAlgo = new GradDes3DOrientation(0.4, (double)1/mShimmerSamplingRate, 1, 0, 0,0); + } + Quaternion q = mOrientationAlgo.update(accelerometer.x,accelerometer.y,accelerometer.z, gyroscope.x,gyroscope.y,gyroscope.z, magnetometer.x,magnetometer.y,magnetometer.z); double theta, Rx, Ry, Rz, rho; + rho = Math.acos(q.q1); + theta = rho * 2; + Rx = q.q2 / Math.sin(rho); + Ry = q.q3 / Math.sin(rho); + Rz = q.q4 / Math.sin(rho); + objectCluster.mPropertyCluster.put("Axis Angle A",new FormatCluster("CAL","local",theta)); + objectCluster.mPropertyCluster.put("Axis Angle X",new FormatCluster("CAL","local",Rx)); + objectCluster.mPropertyCluster.put("Axis Angle Y",new FormatCluster("CAL","local",Ry)); + objectCluster.mPropertyCluster.put("Axis Angle Z",new FormatCluster("CAL","local",Rz)); + objectCluster.mPropertyCluster.put("Quaternion 0",new FormatCluster("CAL","local",q.q1)); + objectCluster.mPropertyCluster.put("Quaternion 1",new FormatCluster("CAL","local",q.q2)); + objectCluster.mPropertyCluster.put("Quaternion 2",new FormatCluster("CAL","local",q.q3)); + objectCluster.mPropertyCluster.put("Quaternion 3",new FormatCluster("CAL","local",q.q4)); + } + } + + if ((mEnabledSensors & SENSOR_EXG1_24BIT) >0){ + int iexg1ch1 = getSignalIndex("EXG1 24Bit CH1"); + int iexg1ch2 = getSignalIndex("EXG1 24Bit CH2"); + int iexg1sta = getSignalIndex("EXG1 STATUS"); + double exg1ch1 = (double)newPacketInt[iexg1ch1]; + double exg1ch2 = (double)newPacketInt[iexg1ch2]; + double exg1sta = (double)newPacketInt[iexg1sta]; + objectCluster.mPropertyCluster.put("EXG1 STATUS",new FormatCluster("RAW",NO_UNIT,exg1sta)); + if (mEnableCalibration){ + double calexg1ch1 = exg1ch1 *(((2.42*1000)/mEXG1CH1GainValue)/(Math.pow(2,23)-1)); + double calexg1ch2 = exg1ch2 *(((2.42*1000)/mEXG1CH2GainValue)/(Math.pow(2,23)-1)); + if (isEXGUsingDefaultECGConfiguration()){ + objectCluster.mPropertyCluster.put("ECG LL-RA",new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put("ECG LA-RA",new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put("ECG LL-RA",new FormatCluster("CAL","mVolts",calexg1ch1)); + objectCluster.mPropertyCluster.put("ECG LA-RA",new FormatCluster("CAL","mVolts",calexg1ch2)); + } else if (isEXGUsingDefaultEMGConfiguration()){ + objectCluster.mPropertyCluster.put("EMG CH1",new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put("EMG CH2",new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put("EMG CH1",new FormatCluster("CAL","mVolts",calexg1ch1)); + objectCluster.mPropertyCluster.put("EMG CH2",new FormatCluster("CAL","mVolts",calexg1ch2)); + } else { + objectCluster.mPropertyCluster.put("EXG1 CH1",new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put("EXG1 CH2",new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put("EXG1 CH1",new FormatCluster("CAL","mVolts",calexg1ch1)); + objectCluster.mPropertyCluster.put("EXG1 CH2",new FormatCluster("CAL","mVolts",calexg1ch2)); + } + } + } + if ((mEnabledSensors & SENSOR_EXG2_24BIT) >0){ + int iexg2ch1 = getSignalIndex("EXG2 24Bit CH1"); + int iexg2ch2 = getSignalIndex("EXG2 24Bit CH2"); + int iexg2sta = getSignalIndex("EXG2 STATUS"); + double exg2ch1 = (double)newPacketInt[iexg2ch1]; + double exg2ch2 = (double)newPacketInt[iexg2ch2]; + double exg2sta = (double)newPacketInt[iexg2sta]; + + objectCluster.mPropertyCluster.put("EXG2 STATUS",new FormatCluster("RAW",NO_UNIT,exg2sta)); + if (mEnableCalibration){ + double calexg2ch1 = exg2ch1 *(((2.42*1000)/mEXG2CH1GainValue)/(Math.pow(2,23)-1)); + double calexg2ch2 = exg2ch2 *(((2.42*1000)/mEXG2CH2GainValue)/(Math.pow(2,23)-1)); + if (isEXGUsingDefaultECGConfiguration()){ + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put("ECG Vx-RL",new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("CAL","mVolts",calexg2ch1)); + objectCluster.mPropertyCluster.put("ECG Vx-RL",new FormatCluster("CAL","mVolts",calexg2ch2)); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put("EXG2 CH2",new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("CAL","mVolts",0)); + objectCluster.mPropertyCluster.put("EXG2 CH2",new FormatCluster("CAL","mVolts",0)); + } else { + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put("EXG2 CH2",new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("CAL","mVolts",calexg2ch1)); + objectCluster.mPropertyCluster.put("EXG2 CH2",new FormatCluster("CAL","mVolts",calexg2ch2)); + } + } + } + + if ((mEnabledSensors & SENSOR_EXG1_16BIT) >0){ + int iexg1ch1 = getSignalIndex("EXG1 16Bit CH1"); + int iexg1ch2 = getSignalIndex("EXG1 16Bit CH2"); + int iexg1sta = getSignalIndex("EXG1 STATUS"); + double exg1ch1 = (double)newPacketInt[iexg1ch1]; + double exg1ch2 = (double)newPacketInt[iexg1ch2]; + double exg1sta = (double)newPacketInt[iexg1sta]; + objectCluster.mPropertyCluster.put("EXG1 STATUS",new FormatCluster("RAW",NO_UNIT,exg1sta)); + if (mEnableCalibration){ + double calexg1ch1 = exg1ch1 *(((2.42*1000)/(mEXG1CH1GainValue*2))/(Math.pow(2,15)-1)); + double calexg1ch2 = exg1ch2 *(((2.42*1000)/(mEXG1CH2GainValue*2))/(Math.pow(2,15)-1)); + if (isEXGUsingDefaultECGConfiguration()){ + objectCluster.mPropertyCluster.put("ECG LL-RA",new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put("ECG LA-RA",new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put("ECG LL-RA",new FormatCluster("CAL","mVolts",calexg1ch1)); + objectCluster.mPropertyCluster.put("ECG LA-RA",new FormatCluster("CAL","mVolts",calexg1ch2)); + } else if (isEXGUsingDefaultEMGConfiguration()){ + objectCluster.mPropertyCluster.put("EMG CH1",new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put("EMG CH2",new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put("EMG CH1",new FormatCluster("CAL","mVolts",calexg1ch1)); + objectCluster.mPropertyCluster.put("EMG CH2",new FormatCluster("CAL","mVolts",calexg1ch2)); + } else { + objectCluster.mPropertyCluster.put("EXG1 CH1 16Bit",new FormatCluster("RAW",NO_UNIT,exg1ch1)); + objectCluster.mPropertyCluster.put("EXG1 CH2 16Bit",new FormatCluster("RAW",NO_UNIT,exg1ch2)); + objectCluster.mPropertyCluster.put("EXG1 CH1 16Bit",new FormatCluster("CAL","mVolts",calexg1ch1)); + objectCluster.mPropertyCluster.put("EXG1 CH2 16Bit",new FormatCluster("CAL","mVolts",calexg1ch2)); + } + } + } + if ((mEnabledSensors & SENSOR_EXG2_16BIT) >0){ + int iexg2ch1 = getSignalIndex("EXG2 16Bit CH1"); + int iexg2ch2 = getSignalIndex("EXG2 16Bit CH2"); + int iexg2sta = getSignalIndex("EXG2 STATUS"); + double exg2ch1 = (double)newPacketInt[iexg2ch1]; + double exg2ch2 = (double)newPacketInt[iexg2ch2]; + double exg2sta = (double)newPacketInt[iexg2sta]; + + objectCluster.mPropertyCluster.put("EXG2 STATUS",new FormatCluster("RAW",NO_UNIT,exg2sta)); + if (mEnableCalibration){ + double calexg2ch1 = ((exg2ch1)) *(((2.42*1000)/(mEXG2CH1GainValue*2))/(Math.pow(2,15)-1)); + double calexg2ch2 = ((exg2ch2)) *(((2.42*1000)/(mEXG2CH2GainValue*2))/(Math.pow(2,15)-1)); + if (isEXGUsingDefaultECGConfiguration()){ + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put("ECG Vx-RL",new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("CAL","mVolts",calexg2ch1)); + objectCluster.mPropertyCluster.put("ECG Vx-RL",new FormatCluster("CAL","mVolts",calexg2ch2)); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put("EXG2 CH2",new FormatCluster("RAW",NO_UNIT,0)); + objectCluster.mPropertyCluster.put("EXG2 CH1",new FormatCluster("CAL","mVolts",0)); + objectCluster.mPropertyCluster.put("EXG2 CH2",new FormatCluster("CAL","mVolts",0)); + } else { + objectCluster.mPropertyCluster.put("EXG2 CH1 16Bit",new FormatCluster("RAW",NO_UNIT,exg2ch1)); + objectCluster.mPropertyCluster.put("EXG2 CH2 16Bit",new FormatCluster("RAW",NO_UNIT,exg2ch2)); + objectCluster.mPropertyCluster.put("EXG2 CH1 16Bit",new FormatCluster("CAL","mVolts",calexg2ch1)); + objectCluster.mPropertyCluster.put("EXG2 CH2 16Bit",new FormatCluster("CAL","mVolts",calexg2ch2)); + } + } + } + + if ((mEnabledSensors & SENSOR_BMP180) >0){ + int iUT = getSignalIndex("Temperature"); + int iUP = getSignalIndex("Pressure"); + double UT = (double)newPacketInt[iUT]; + double UP = (double)newPacketInt[iUP]; + UP=UP/Math.pow(2,8-mPressureResolution); + objectCluster.mPropertyCluster.put("Pressure",new FormatCluster("RAW",NO_UNIT,UP)); + objectCluster.mPropertyCluster.put("Temperature",new FormatCluster("RAW",NO_UNIT,UT)); + if (mEnableCalibration){ + double[] bmp180caldata= calibratePressureSensorData(UP,UT); + objectCluster.mPropertyCluster.put("Pressure",new FormatCluster("CAL","kPa",bmp180caldata[0]/1000)); + objectCluster.mPropertyCluster.put("Temperature",new FormatCluster("CAL","Celsius",bmp180caldata[1])); + } + } + + if ((mEnabledSensors & SENSOR_BRIDGE_AMP) > 0) { + int iBAHigh = getSignalIndex("Bridge Amplifier High"); + int iBALow = getSignalIndex("Bridge Amplifier Low"); + objectCluster.mPropertyCluster.put("Bridge Amplifier High",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBAHigh])); + objectCluster.mPropertyCluster.put("Bridge Amplifier Low",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBALow])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iBAHigh]; + tempData[1] = (double)newPacketInt[iBALow]; + calibratedData[iBAHigh]=calibrateU12AdcValue(tempData[0],60,3,551); + calibratedData[iBALow]=calibrateU12AdcValue(tempData[1],1950,3,183.7); + objectCluster.mPropertyCluster.put("Bridge Amplifier High",new FormatCluster("CAL","mVolts",calibratedData[iBAHigh])); + objectCluster.mPropertyCluster.put("Bridge Amplifier Low",new FormatCluster("CAL","mVolts",calibratedData[iBALow])); + } + } + + if ((mEnabledSensors & SENSOR_GSR) > 0) { + int iGSR = getSignalIndex("GSR Raw"); + tempData[0] = (double)newPacketInt[iGSR]; + int newGSRRange = -1; // initialized to -1 so it will only come into play if mGSRRange = 4 + + double p1=0,p2=0;//,p3=0,p4=0,p5=0; + if (mGSRRange==4){ + newGSRRange=(49152 & (int)tempData[0])>>14; + } + if (mGSRRange==0 || newGSRRange==0) { //Note that from FW 1.0 onwards the MSB of the GSR data contains the range + // the polynomial function used for calibration has been deprecated, it is replaced with a linear function + /* p1 = 6.5995E-9; + p2 = -6.895E-5; + p3 = 2.699E-1; + p4 = -4.769835E+2; + p5 = 3.403513341E+5;*/ + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0373; + p2 = -24.9915; + } else { + p1 = 0.0363; + p2 = -24.8617; + } + } else if (mGSRRange==1 || newGSRRange==1) { + /*p1 = 1.3569627E-8; + p2 = -1.650399E-4; + p3 = 7.54199E-1; + p4 = -1.5726287856E+3; + p5 = 1.367507927E+6;*/ + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0054; + p2 = -3.5194; + } else { + p1 = 0.0051; + p2 = -3.8357; + } + } else if (mGSRRange==2 || newGSRRange==2) { + /*p1 = 2.550036498E-8; + p2 = -3.3136E-4; + p3 = 1.6509426597E+0; + p4 = -3.833348044E+3; + p5 = 3.8063176947E+6;*/ + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 0.0015; + p2 = -1.0163; + } else { + p1 = 0.0015; + p2 = -1.0067; + } + } else if (mGSRRange==3 || newGSRRange==3) { + /*p1 = 3.7153627E-7; + p2 = -4.239437E-3; + p3 = 1.7905709E+1; + p4 = -3.37238657E+4; + p5 = 2.53680446279E+7;*/ + if (mHardwareVersion!=HW_ID.SHIMMER_3){ + p1 = 4.5580e-04; + p2 = -0.3014; + } else { + p1 = 4.4513e-04; + p2 = -0.3193; + } + } + objectCluster.mPropertyCluster.put("GSR",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGSR])); + if (mEnableCalibration){ + calibratedData[iGSR] = calibrateGsrData(tempData[0],p1,p2); + objectCluster.mPropertyCluster.put("GSR",new FormatCluster("CAL","kOhms",calibratedData[iGSR])); + } + } + } else { //start of Shimmer2 + + if ((mEnabledSensors & SENSOR_ACCEL) > 0){ + int iAccelX=getSignalIndex("Accelerometer X"); //find index + int iAccelY=getSignalIndex("Accelerometer Y"); //find index + int iAccelZ=getSignalIndex("Accelerometer Z"); //find index + objectCluster.mPropertyCluster.put("Accelerometer X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelX])); + objectCluster.mPropertyCluster.put("Accelerometer Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelY])); + objectCluster.mPropertyCluster.put("Accelerometer Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iAccelZ])); + if (mEnableCalibration){ + tempData[0]=(double)newPacketInt[iAccelX]; + tempData[1]=(double)newPacketInt[iAccelY]; + tempData[2]=(double)newPacketInt[iAccelZ]; + double[] accelCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixAnalogAccel, mSensitivityMatrixAnalogAccel, mOffsetVectorAnalogAccel); + calibratedData[iAccelX]=accelCalibratedData[0]; + calibratedData[iAccelY]=accelCalibratedData[1]; + calibratedData[iAccelZ]=accelCalibratedData[2]; + if (mDefaultCalibrationParametersAccel == true) { + objectCluster.mPropertyCluster.put("Accelerometer X",new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[0])); + objectCluster.mPropertyCluster.put("Accelerometer Y",new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[1])); + objectCluster.mPropertyCluster.put("Accelerometer Z",new FormatCluster("CAL","m/(sec^2)*",accelCalibratedData[2])); + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } else { + objectCluster.mPropertyCluster.put("Accelerometer X",new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[0])); + objectCluster.mPropertyCluster.put("Accelerometer Y",new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[1])); + objectCluster.mPropertyCluster.put("Accelerometer Z",new FormatCluster("CAL","m/(sec^2)",accelCalibratedData[2])); + accelerometer.x=accelCalibratedData[0]; + accelerometer.y=accelCalibratedData[1]; + accelerometer.z=accelCalibratedData[2]; + } + } + + } + + if ((mEnabledSensors & SENSOR_GYRO) > 0) { + int iGyroX=getSignalIndex("Gyroscope X"); + int iGyroY=getSignalIndex("Gyroscope Y"); + int iGyroZ=getSignalIndex("Gyroscope Z"); + objectCluster.mPropertyCluster.put("Gyroscope X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroX])); + objectCluster.mPropertyCluster.put("Gyroscope Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroY])); + objectCluster.mPropertyCluster.put("Gyroscope Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGyroZ])); + if (mEnableCalibration){ + tempData[0]=(double)newPacketInt[iGyroX]; + tempData[1]=(double)newPacketInt[iGyroY]; + tempData[2]=(double)newPacketInt[iGyroZ]; + double[] gyroCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixGyroscope, mSensitivityMatrixGyroscope, mOffsetVectorGyroscope); + calibratedData[iGyroX]=gyroCalibratedData[0]; + calibratedData[iGyroY]=gyroCalibratedData[1]; + calibratedData[iGyroZ]=gyroCalibratedData[2]; + if (mDefaultCalibrationParametersGyro == true) { + objectCluster.mPropertyCluster.put("Gyroscope X",new FormatCluster("CAL","deg/sec*",gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put("Gyroscope Y",new FormatCluster("CAL","deg/sec*",gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put("Gyroscope Z",new FormatCluster("CAL","deg/sec*",gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + } else { + objectCluster.mPropertyCluster.put("Gyroscope X",new FormatCluster("CAL","deg/sec",gyroCalibratedData[0])); + objectCluster.mPropertyCluster.put("Gyroscope Y",new FormatCluster("CAL","deg/sec",gyroCalibratedData[1])); + objectCluster.mPropertyCluster.put("Gyroscope Z",new FormatCluster("CAL","deg/sec",gyroCalibratedData[2])); + gyroscope.x=gyroCalibratedData[0]*Math.PI/180; + gyroscope.y=gyroCalibratedData[1]*Math.PI/180; + gyroscope.z=gyroCalibratedData[2]*Math.PI/180; + if (mEnableOntheFlyGyroOVCal){ + mGyroX.addValue(gyroCalibratedData[0]); + mGyroY.addValue(gyroCalibratedData[1]); + mGyroZ.addValue(gyroCalibratedData[2]); + mGyroXRaw.addValue((double)newPacketInt[iGyroX]); + mGyroYRaw.addValue((double)newPacketInt[iGyroY]); + mGyroZRaw.addValue((double)newPacketInt[iGyroZ]); + if (mGyroX.getStandardDeviation() 0) { + int iMagX=getSignalIndex("Magnetometer X"); + int iMagY=getSignalIndex("Magnetometer Y"); + int iMagZ=getSignalIndex("Magnetometer Z"); + objectCluster.mPropertyCluster.put("Magnetometer X",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagX])); + objectCluster.mPropertyCluster.put("Magnetometer Y",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagY])); + objectCluster.mPropertyCluster.put("Magnetometer Z",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iMagZ])); + if (mEnableCalibration){ + tempData[0]=(double)newPacketInt[iMagX]; + tempData[1]=(double)newPacketInt[iMagY]; + tempData[2]=(double)newPacketInt[iMagZ]; + double[] magCalibratedData=calibrateInertialSensorData(tempData, mAlignmentMatrixMagnetometer, mSensitivityMatrixMagnetometer, mOffsetVectorMagnetometer); + calibratedData[iMagX]=magCalibratedData[0]; + calibratedData[iMagY]=magCalibratedData[1]; + calibratedData[iMagZ]=magCalibratedData[2]; + if (mDefaultCalibrationParametersMag == true) { + objectCluster.mPropertyCluster.put("Magnetometer X",new FormatCluster("CAL","local*",magCalibratedData[0])); + objectCluster.mPropertyCluster.put("Magnetometer Y",new FormatCluster("CAL","local*",magCalibratedData[1])); + objectCluster.mPropertyCluster.put("Magnetometer Z",new FormatCluster("CAL","local*",magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + } else { + objectCluster.mPropertyCluster.put("Magnetometer X",new FormatCluster("CAL","local",magCalibratedData[0])); + objectCluster.mPropertyCluster.put("Magnetometer Y",new FormatCluster("CAL","local",magCalibratedData[1])); + objectCluster.mPropertyCluster.put("Magnetometer Z",new FormatCluster("CAL","local",magCalibratedData[2])); + magnetometer.x=magCalibratedData[0]; + magnetometer.y=magCalibratedData[1]; + magnetometer.z=magCalibratedData[2]; + } + } + } + + + if ((mEnabledSensors & SENSOR_ACCEL) > 0 && (mEnabledSensors & SENSOR_GYRO) > 0 && (mEnabledSensors & SENSOR_MAG) > 0 && mOrientationEnabled ){ + if (mEnableCalibration){ + if (mOrientationAlgo==null){ + mOrientationAlgo = new GradDes3DOrientation(0.4, (double)1/mShimmerSamplingRate, 1, 0, 0,0); + } + Quaternion q = mOrientationAlgo.update(accelerometer.x,accelerometer.y,accelerometer.z, gyroscope.x,gyroscope.y,gyroscope.z, magnetometer.x,magnetometer.y,magnetometer.z); + double theta, Rx, Ry, Rz, rho; + rho = Math.acos(q.q1); + theta = rho * 2; + Rx = q.q2 / Math.sin(rho); + Ry = q.q3 / Math.sin(rho); + Rz = q.q4 / Math.sin(rho); + objectCluster.mPropertyCluster.put("Axis Angle A",new FormatCluster("CAL","local",theta)); + objectCluster.mPropertyCluster.put("Axis Angle X",new FormatCluster("CAL","local",Rx)); + objectCluster.mPropertyCluster.put("Axis Angle Y",new FormatCluster("CAL","local",Ry)); + objectCluster.mPropertyCluster.put("Axis Angle Z",new FormatCluster("CAL","local",Rz)); + objectCluster.mPropertyCluster.put("Quaternion 0",new FormatCluster("CAL","local",q.q1)); + objectCluster.mPropertyCluster.put("Quaternion 1",new FormatCluster("CAL","local",q.q2)); + objectCluster.mPropertyCluster.put("Quaternion 2",new FormatCluster("CAL","local",q.q3)); + objectCluster.mPropertyCluster.put("Quaternion 3",new FormatCluster("CAL","local",q.q4)); + } + } + + if ((mEnabledSensors & SENSOR_GSR) > 0) { + int iGSR = getSignalIndex("GSR Raw"); + tempData[0] = (double)newPacketInt[iGSR]; + int newGSRRange = -1; // initialized to -1 so it will only come into play if mGSRRange = 4 + + double p1=0,p2=0;//,p3=0,p4=0,p5=0; + if (mGSRRange==4){ + newGSRRange=(49152 & (int)tempData[0])>>14; + } + if (mGSRRange==0 || newGSRRange==0) { //Note that from FW 1.0 onwards the MSB of the GSR data contains the range + // the polynomial function used for calibration has been deprecated, it is replaced with a linear function + /* p1 = 6.5995E-9; + p2 = -6.895E-5; + p3 = 2.699E-1; + p4 = -4.769835E+2; + p5 = 3.403513341E+5;*/ + p1 = 0.0373; + p2 = -24.9915; + } else if (mGSRRange==1 || newGSRRange==1) { + /*p1 = 1.3569627E-8; + p2 = -1.650399E-4; + p3 = 7.54199E-1; + p4 = -1.5726287856E+3; + p5 = 1.367507927E+6;*/ + p1 = 0.0054; + p2 = -3.5194; + } else if (mGSRRange==2 || newGSRRange==2) { + /*p1 = 2.550036498E-8; + p2 = -3.3136E-4; + p3 = 1.6509426597E+0; + p4 = -3.833348044E+3; + p5 = 3.8063176947E+6;*/ + p1 = 0.0015; + p2 = -1.0163; + } else if (mGSRRange==3 || newGSRRange==3) { + /*p1 = 3.7153627E-7; + p2 = -4.239437E-3; + p3 = 1.7905709E+1; + p4 = -3.37238657E+4; + p5 = 2.53680446279E+7;*/ + p1 = 4.5580e-04; + p2 = -0.3014; + } + objectCluster.mPropertyCluster.put("GSR",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iGSR])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iGSR]; + calibratedData[iGSR] = calibrateGsrData(tempData[0],p1,p2); + objectCluster.mPropertyCluster.put("GSR",new FormatCluster("CAL","kOhms",calibratedData[iGSR])); + } + } + if ((mEnabledSensors & SENSOR_ECG) > 0) { + int iECGRALL = getSignalIndex("ECG RA LL"); + int iECGLALL = getSignalIndex("ECG LA LL"); + objectCluster.mPropertyCluster.put("ECG RA-LL",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iECGRALL])); + objectCluster.mPropertyCluster.put("ECG LA-LL",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iECGLALL])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iECGRALL]; + tempData[1] = (double)newPacketInt[iECGLALL]; + calibratedData[iECGRALL]=calibrateU12AdcValue(tempData[0],OffsetECGRALL,3,GainECGRALL); + calibratedData[iECGLALL]=calibrateU12AdcValue(tempData[1],OffsetECGLALL,3,GainECGLALL); + if (mDefaultCalibrationParametersECG == true) { + objectCluster.mPropertyCluster.put("ECG RA-LL",new FormatCluster("CAL","mVolts*",calibratedData[iECGRALL])); + objectCluster.mPropertyCluster.put("ECG LA-LL",new FormatCluster("CAL","mVolts*",calibratedData[iECGLALL])); + } else { + objectCluster.mPropertyCluster.put("ECG RA-LL",new FormatCluster("CAL","mVolts",calibratedData[iECGRALL])); + objectCluster.mPropertyCluster.put("ECG LA-LL",new FormatCluster("CAL","mVolts",calibratedData[iECGLALL])); + } + } + } + if ((mEnabledSensors & SENSOR_EMG) > 0) { + int iEMG = getSignalIndex("EMG"); + objectCluster.mPropertyCluster.put("EMG",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iEMG])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iEMG]; + calibratedData[iEMG]=calibrateU12AdcValue(tempData[0],OffsetEMG,3,GainEMG); + if (mDefaultCalibrationParametersEMG == true){ + objectCluster.mPropertyCluster.put("EMG",new FormatCluster("CAL","mVolts*",calibratedData[iEMG])); + } else { + objectCluster.mPropertyCluster.put("EMG",new FormatCluster("CAL","mVolts",calibratedData[iEMG])); + } + } + } + if ((mEnabledSensors & SENSOR_BRIDGE_AMP) > 0) { + int iBAHigh = getSignalIndex("Bridge Amplifier High"); + int iBALow = getSignalIndex("Bridge Amplifier Low"); + objectCluster.mPropertyCluster.put("Bridge Amplifier High",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBAHigh])); + objectCluster.mPropertyCluster.put("Bridge Amplifier Low",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iBALow])); + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iBAHigh]; + tempData[1] = (double)newPacketInt[iBALow]; + calibratedData[iBAHigh]=calibrateU12AdcValue(tempData[0],60,3,551); + calibratedData[iBALow]=calibrateU12AdcValue(tempData[1],1950,3,183.7); + objectCluster.mPropertyCluster.put("Bridge Amplifier High",new FormatCluster("CAL","mVolts",calibratedData[iBAHigh])); + objectCluster.mPropertyCluster.put("Bridge Amplifier Low",new FormatCluster("CAL","mVolts",calibratedData[iBALow])); + } + } + if ((mEnabledSensors & SENSOR_HEART) > 0) { + int iHeartRate = getSignalIndex("Heart Rate"); + tempData[0] = (double)newPacketInt[iHeartRate]; + objectCluster.mPropertyCluster.put("Heart Rate",new FormatCluster("RAW",NO_UNIT,tempData[0])); + if (mEnableCalibration){ + calibratedData[iHeartRate]=tempData[0]; + if (mFirmwareVersionMajor==0 && mFirmwareVersionMinor==1){ + + } else { + if (tempData[0]==0){ + calibratedData[iHeartRate]= mLastKnownHeartRate; + } else { + calibratedData[iHeartRate]=(int)(1024/tempData[0]*60); + mLastKnownHeartRate=calibratedData[iHeartRate]; + } + } + objectCluster.mPropertyCluster.put("Heart Rate",new FormatCluster("CAL","BPM",calibratedData[iHeartRate])); + } + } + if ((mEnabledSensors& SENSOR_EXP_BOARD_A0) > 0) { + int iA0 = getSignalIndex("Exp Board A0"); + tempData[0] = (double)newPacketInt[iA0]; + if (getPMux()==0){ + objectCluster.mPropertyCluster.put("ExpBoard A0",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("ExpBoard A0",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + } else { + objectCluster.mPropertyCluster.put("VSenseReg",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + if (mEnableCalibration){ + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1)*1.988; + objectCluster.mPropertyCluster.put("VSenseReg",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + } + + } + } + if ((mEnabledSensors & SENSOR_EXP_BOARD_A7) > 0) { + int iA7 = getSignalIndex("Exp Board A7"); + tempData[0] = (double)newPacketInt[iA7]; + if (getPMux()==0){ + objectCluster.mPropertyCluster.put("ExpBoard A7",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA7])); + if (mEnableCalibration){ + calibratedData[iA7]=calibrateU12AdcValue(tempData[0],0,3,1); + objectCluster.mPropertyCluster.put("ExpBoard A7",new FormatCluster("CAL","mVolts",calibratedData[iA7])); + } + } + } + if ((mEnabledSensors & SENSOR_BATT) > 0) { + int iA0 = getSignalIndex("Exp Board A0"); + objectCluster.mPropertyCluster.put("VSenseReg",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA0])); + + int iA7 = getSignalIndex("Exp Board A7"); + objectCluster.mPropertyCluster.put("VSenseBatt",new FormatCluster("RAW",NO_UNIT,(double)newPacketInt[iA7])); + + + if (mEnableCalibration){ + tempData[0] = (double)newPacketInt[iA0]; + calibratedData[iA0]=calibrateU12AdcValue(tempData[0],0,3,1)*1.988; + objectCluster.mPropertyCluster.put("VSenseReg",new FormatCluster("CAL","mVolts",calibratedData[iA0])); + + tempData[0] = (double)newPacketInt[iA7]; + calibratedData[iA7]=calibrateU12AdcValue(tempData[0],0,3,1)*2; + objectCluster.mPropertyCluster.put("VSenseBatt",new FormatCluster("CAL","mVolts",calibratedData[iA7])); + mVSenseBattMA.addValue(calibratedData[iA7]); + checkBattery(); + } + } + } + + + + return objectCluster; + } + + + + + //protected abstract void writeLEDCommand(int i); + + /** + * Converts the raw packet byte values, into the corresponding calibrated and uncalibrated sensor values, the Instruction String determines the output + * @param newPacket a byte array containing the current received packet + * @param Instructions an array string containing the commands to execute. It is currently not fully supported + * @return + */ + + protected long[] parsedData(byte[] data,String[] dataType) + { + int iData=0; + long[] formattedData=new long[dataType.length]; + + for (int i=0;i")) { + formattedData[i]=calculatetwoscomplement((int)((int)(data[iData] & 0xFF) + ((int)(data[iData+1] & 0xFF) << 8)),16); + formattedData[i]=formattedData[i]>>4; // shift right by 4 bits + iData=iData+2; + } else if (dataType[i].equals("u16")) { + formattedData[i]=(int)((int)(data[iData] & 0xFF) + ((int)(data[iData+1] & 0xFF) << 8)); + iData=iData+2; + } else if (dataType[i].equals("u16r")) { + formattedData[i]=(int)((int)(data[iData+1] & 0xFF) + ((int)(data[iData+0] & 0xFF) << 8)); + iData=iData+2; + } else if (dataType[i].equals("i16")) { + formattedData[i]=calculatetwoscomplement((int)((int)(data[iData] & 0xFF) + ((int)(data[iData+1] & 0xFF) << 8)),16); + //formattedData[i]=ByteBuffer.wrap(arrayb).order(ByteOrder.LITTLE_ENDIAN).getShort(); + iData=iData+2; + } else if (dataType[i].equals("i16r")){ + formattedData[i]=calculatetwoscomplement((int)((int)(data[iData+1] & 0xFF) + ((int)(data[iData] & 0xFF) << 8)),16); + //formattedData[i]=ByteBuffer.wrap(arrayb).order(ByteOrder.LITTLE_ENDIAN).getShort(); + iData=iData+2; + } else if (dataType[i].equals("u24r")) { + long xmsb =((long)(data[iData+0] & 0xFF) << 16); + long msb =((long)(data[iData+1] & 0xFF) << 8); + long lsb =((long)(data[iData+2] & 0xFF)); + formattedData[i]=xmsb + msb + lsb; + iData=iData+3; + } else if (dataType[i].equals("u24")) { + long xmsb =((long)(data[iData+2] & 0xFF) << 16); + long msb =((long)(data[iData+1] & 0xFF) << 8); + long lsb =((long)(data[iData+0] & 0xFF)); + formattedData[i]=xmsb + msb + lsb; + iData=iData+3; + } else if (dataType[i].equals("i24r")) { + long xmsb =((long)(data[iData+0] & 0xFF) << 16); + long msb =((long)(data[iData+1] & 0xFF) << 8); + long lsb =((long)(data[iData+2] & 0xFF)); + formattedData[i]=calculatetwoscomplement((int)(xmsb + msb + lsb),24); + iData=iData+3; + } else if (dataType[i].equals("u32signed")) { + long offset = (((long)data[iData] & 0xFF)); + if (offset == 255){ + offset = 0; + } + long xxmsb =(((long)data[iData+4] & 0xFF) << 24); + long xmsb =(((long)data[iData+3] & 0xFF) << 16); + long msb =(((long)data[iData+2] & 0xFF) << 8); + long lsb =(((long)data[iData+1] & 0xFF)); + formattedData[i]=(1-2*offset)*(xxmsb + xmsb + msb + lsb); + iData=iData+5; + } else if (dataType[i].equals("i32r")) { + long xxmsb =((long)(data[iData+0] & 0xFF) << 24); + long xmsb =((long)(data[iData+1] & 0xFF) << 16); + long msb =((long)(data[iData+2] & 0xFF) << 8); + long lsb =((long)(data[iData+3] & 0xFF) << 0); + formattedData[i]=calculatetwoscomplement((long)(xxmsb + xmsb + msb + lsb),32); + iData=iData+4; + } else if (dataType[i].equals("u72")){ + // do something to parse the 9 byte data + long offset = (((long)data[iData] & 0xFF)); + if (offset == 255){ + offset = 0; + } + + long eigthmsb =(((long)data[iData+8] & 0x0FL) << 56); + long seventhmsb =(((long)data[iData+7] & 0xFFL) << 48); + long sixthmsb =(((long)data[iData+6] & 0xFFL) << 40); + long fifthmsb =(((long)data[iData+5] & 0xFFL) << 32); + long forthmsb =(((long)data[iData+4] & 0xFFL) << 24); + long thirdmsb =(((long)data[iData+3] & 0xFFL) << 16); + long msb =(((long)data[iData+2] & 0xFF) << 8); + long lsb =(((long)data[iData+1] & 0xFF)); + formattedData[i]=(1-2*offset)*(eigthmsb + seventhmsb + sixthmsb + fifthmsb+ forthmsb+ thirdmsb + msb + lsb); + iData=iData+9; + } + return formattedData; + } + /* + * Data Methods + * */ + + + protected int[] formatdatapacketreverse(byte[] data,String[] dataType) + { + int iData=0; + int[] formattedData=new int[dataType.length]; + + for (int i=0;i=(1<<(bitLength-1))) { + newData=-((signedData^(int)(Math.pow(2, bitLength)-1))+1); + } + + return newData; + } + + private long calculatetwoscomplement(long signedData, int bitLength) + { + long newData=signedData; + if (signedData>=(1L<<(bitLength-1))) { + newData=-((signedData^(long)(Math.pow(2, bitLength)-1))+1); + } + + return newData; + } + + protected int getSignalIndex(String signalName) { + int iSignal=-1; //better to fail //used to be -1, putting to zero ensure it works eventhough it might be wrong SR30 + for (int i=0;i generateBiMapSensorIDtoSensorName(int shimmerVersion){ + BiMap sensorBitmaptoName =null; + if (shimmerVersion != HW_ID.SHIMMER_2R){ + final Map tempSensorBMtoName = new HashMap(); + tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); + tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BRIDGE_AMP), "Bridge Amplifier"); + tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BMP180), "Pressure"); + tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Low Noise Accelerometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_DACCEL), "Wide Range Accelerometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXG1_24BIT), "EXG1"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXG2_24BIT), "EXG2"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXG1_16BIT), "EXG1 16Bit"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXG2_16BIT), "EXG2 16Bit"); + sensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); + } else { + final Map tempSensorBMtoName = new HashMap(); + tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); + tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BRIDGE_AMP), "Bridge Amplifier"); + tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); + sensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); + } + return sensorBitmaptoName; + } + + /** + * Should only be used when Shimmer is Connected and Initialized + */ + public void generateBiMapSensorIDtoSensorName(){ + if (mHardwareVersion != -1){ + if (mHardwareVersion != HW_ID.SHIMMER_2R){ + final Map tempSensorBMtoName = new HashMap(); + tempSensorBMtoName.put(Integer.toString(SENSOR_BMP180), "Pressure"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); + tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); + tempSensorBMtoName.put(Integer.toString(SHIMMER3_SENSOR_ECG), "ECG"); + tempSensorBMtoName.put(Integer.toString(SHIMMER3_SENSOR_EMG), "EMG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BRIDGE_AMP), "Bridge Amplifier"); + tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); + tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Low Noise Accelerometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_DACCEL), "Wide Range Accelerometer"); + mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); + + + } else { + final Map tempSensorBMtoName = new HashMap(); + tempSensorBMtoName.put(Integer.toString(SENSOR_ACCEL), "Accelerometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GYRO), "Gyroscope"); + tempSensorBMtoName.put(Integer.toString(SENSOR_MAG), "Magnetometer"); + tempSensorBMtoName.put(Integer.toString(SENSOR_ECG), "ECG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EMG), "EMG"); + tempSensorBMtoName.put(Integer.toString(SENSOR_GSR), "GSR"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A7), "Exp Board A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD_A0), "Exp Board A0"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXP_BOARD), "Exp Board"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BRIDGE_AMP), "Bridge Amplifier"); + tempSensorBMtoName.put(Integer.toString(SENSOR_HEART), "Heart Rate"); + tempSensorBMtoName.put(Integer.toString(SENSOR_BATT), "Battery Voltage"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A7), "External ADC A7"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A6), "External ADC A6"); + tempSensorBMtoName.put(Integer.toString(SENSOR_EXT_ADC_A15), "External ADC A15"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A1), "Internal ADC A1"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A12), "Internal ADC A12"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A13), "Internal ADC A13"); + tempSensorBMtoName.put(Integer.toString(SENSOR_INT_ADC_A14), "Internal ADC A14"); + mSensorBitmaptoName = ImmutableBiMap.copyOf(Collections.unmodifiableMap(tempSensorBMtoName)); + } + + } + } + + + + public String[] getListofEnabledSensorSignals(){ + List listofSignals = new ArrayList(); + String[] enabledSignals; + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + listofSignals.add("Timestamp"); + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0){ + listofSignals.add(Shimmer2.ObjectClusterSensorName.ACCEL_X); + listofSignals.add(Shimmer2.ObjectClusterSensorName.ACCEL_Y); + listofSignals.add(Shimmer2.ObjectClusterSensorName.ACCEL_Z); + } + if (((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.GYRO_X); + listofSignals.add(Shimmer2.ObjectClusterSensorName.GYRO_Y); + listofSignals.add(Shimmer2.ObjectClusterSensorName.GYRO_Z); + } + if (((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.MAG_X); + listofSignals.add(Shimmer2.ObjectClusterSensorName.MAG_Y); + listofSignals.add(Shimmer2.ObjectClusterSensorName.MAG_Z); + } + if (((mEnabledSensors & 0xFF) & SENSOR_GSR) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.GSR); + //listofSignals.add(Shimmer2.ObjectClusterSensorName.GSR_RES); + } + if (((mEnabledSensors & 0xFF) & SENSOR_ECG) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.ECG_RA_LL); + listofSignals.add(Shimmer2.ObjectClusterSensorName.ECG_LA_LL); + } + if (((mEnabledSensors & 0xFF) & SENSOR_EMG) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.EMG); + } + if (((mEnabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH); + listofSignals.add(Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW); + } + if (((mEnabledSensors & 0xFF00) & SENSOR_HEART) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.HEART_RATE); + } + if ((((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0) && getPMux() == 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0); + } + if ((((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0 && getPMux() == 0)) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_BATT) > 0) { + listofSignals.add(Shimmer2.ObjectClusterSensorName.BATTERY); + listofSignals.add(Shimmer2.ObjectClusterSensorName.REG); + } + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ + listofSignals.add(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_A); + listofSignals.add(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_X); + listofSignals.add(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Y); + listofSignals.add(Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Z); + } + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ + listofSignals.add(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_W); + listofSignals.add(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_X); + listofSignals.add(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y); + listofSignals.add(Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z); + } + + } else { + listofSignals.add("Timestamp"); + if ((mEnabledSensors & SENSOR_ACCEL) >0){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.ACCEL_LN_X); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z); + } + if ((mEnabledSensors& SENSOR_DACCEL) >0){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.ACCEL_WR_X); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z); + } + if (((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.GYRO_X); + listofSignals.add(Shimmer3.ObjectClusterSensorName.GYRO_Y); + listofSignals.add(Shimmer3.ObjectClusterSensorName.GYRO_Z); + } + if (((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.MAG_X); + listofSignals.add(Shimmer3.ObjectClusterSensorName.MAG_Y); + listofSignals.add(Shimmer3.ObjectClusterSensorName.MAG_Z); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_BATT) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.BATTERY); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_EXT_ADC_A15) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXT_EXP_A15); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_EXT_ADC_A7) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXT_EXP_A7); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_EXT_ADC_A6) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXT_EXP_A6); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A1) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.INT_EXP_A1); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A12) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.INT_EXP_A12); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A13) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.INT_EXP_A13); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A14) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.INT_EXP_A14); + } + if ((((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 || ((mEnabledSensors & 0xFFFF)& SENSOR_DACCEL) > 0)&& ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_A); + listofSignals.add(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_X); + listofSignals.add(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Y); + listofSignals.add(Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Z); + } + if ((((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 || ((mEnabledSensors & 0xFFFF)& SENSOR_DACCEL) > 0) && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_W); + listofSignals.add(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_X); + listofSignals.add(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y); + listofSignals.add(Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z); + } + if ((mEnabledSensors & SENSOR_BMP180)>0){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180); + listofSignals.add(Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180); + } + if ((mEnabledSensors & SENSOR_GSR)>0){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.GSR); + } + if (((mEnabledSensors & SENSOR_EXG1_24BIT)>0)|| ((mEnabledSensors & SENSOR_EXG1_16BIT)>0)){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG1_STATUS); + } + if (((mEnabledSensors & SENSOR_EXG2_24BIT)>0)|| ((mEnabledSensors & SENSOR_EXG2_16BIT)>0)){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_STATUS); + } + if ((mEnabledSensors & SENSOR_EXG1_24BIT)>0){ + if (isEXGUsingDefaultECGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT); + } else { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT); + } + + } + if ((mEnabledSensors & SENSOR_EXG2_24BIT)>0){ + if (isEXGUsingDefaultECGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT); + } else { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT); + } + } + if ((mEnabledSensors & SENSOR_EXG1_16BIT)>0){ + if (isEXGUsingDefaultECGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT); + } else { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT); + } + } + if ((mEnabledSensors & SENSOR_EXG2_16BIT)>0){ + if (isEXGUsingDefaultECGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT); + } else { + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT); + listofSignals.add(Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT); + } + } + if (((mEnabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0) { + listofSignals.add(Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH); + listofSignals.add(Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW); + } + } + enabledSignals = listofSignals.toArray(new String[listofSignals.size()]); + return enabledSignals; + } + + protected void retrievebiophysicalcalibrationparametersfrompacket(byte[] bufferCalibrationParameters, int packetType) + { + if (packetType == ECG_CALIBRATION_RESPONSE){ + if (bufferCalibrationParameters[0]==-1 && bufferCalibrationParameters[1] == -1 && bufferCalibrationParameters[2] == -1 && bufferCalibrationParameters[3]==-1){ + mDefaultCalibrationParametersECG = true; + } else { + mDefaultCalibrationParametersECG = false; + OffsetECGLALL=(double)((bufferCalibrationParameters[0]&0xFF)<<8)+(bufferCalibrationParameters[1]&0xFF); + GainECGLALL=(double)((bufferCalibrationParameters[2]&0xFF)<<8)+(bufferCalibrationParameters[3]&0xFF); + OffsetECGRALL=(double)((bufferCalibrationParameters[4]&0xFF)<<8)+(bufferCalibrationParameters[5]&0xFF); + GainECGRALL=(double)((bufferCalibrationParameters[6]&0xFF)<<8)+(bufferCalibrationParameters[7]&0xFF); + } + } + + if (packetType == EMG_CALIBRATION_RESPONSE){ + + if (bufferCalibrationParameters[0]==-1 && bufferCalibrationParameters[1] == -1 && bufferCalibrationParameters[2] == -1 && bufferCalibrationParameters[3]==-1){ + mDefaultCalibrationParametersEMG = true; + } else { + mDefaultCalibrationParametersEMG = false; + OffsetEMG=(double)((bufferCalibrationParameters[0]&0xFF)<<8)+(bufferCalibrationParameters[1]&0xFF); + GainEMG=(double)((bufferCalibrationParameters[2]&0xFF)<<8)+(bufferCalibrationParameters[3]&0xFF); + } + } + + } + + protected void retrievekinematiccalibrationparametersfrompacket(byte[] bufferCalibrationParameters, int packetType) + { + if (packetType==ACCEL_CALIBRATION_RESPONSE || packetType==LSM303DLHC_ACCEL_CALIBRATION_RESPONSE || packetType==GYRO_CALIBRATION_RESPONSE || packetType==MAG_CALIBRATION_RESPONSE ){ + String[] dataType={"i16","i16","i16","i16","i16","i16","i8","i8","i8","i8","i8","i8","i8","i8","i8"}; + int[] formattedPacket=formatdatapacketreverse(bufferCalibrationParameters,dataType); // using the datatype the calibration parameters are converted + double[] AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + + double[][] AlignmentMatrix = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] SensitivityMatrix = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] OffsetVector = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + + + if (packetType==ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]!=-1) { //used to be 65535 but changed to -1 as we are now using i16 + mDefaultCalibrationParametersAccel = false; + mAlignmentMatrixAnalogAccel = AlignmentMatrix; + mOffsetVectorAnalogAccel = OffsetVector; + mSensitivityMatrixAnalogAccel = SensitivityMatrix; + } else if(packetType==ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]==-1){ + mDefaultCalibrationParametersAccel = true; + if (mHardwareVersion!=3){ + mAlignmentMatrixAnalogAccel = AlignmentMatrixAccelShimmer2; + mOffsetVectorAnalogAccel = OffsetVectorAccelShimmer2; + if (getAccelRange()==0){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel1p5gShimmer2; + } else if (getAccelRange()==1){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel2gShimmer2; + } else if (getAccelRange()==2){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel4gShimmer2; + } else if (getAccelRange()==3){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixAccel6gShimmer2; + } + } else { + if (getAccelRange()==0){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixLowNoiseAccel2gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixLowNoiseAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorLowNoiseAccelShimmer3; + } else if (getAccelRange()==1){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixWideRangeAccel4gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==2){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixWideRangeAccel8gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==3){ + mSensitivityMatrixAnalogAccel = SensitivityMatrixWideRangeAccel16gShimmer3; + mAlignmentMatrixAnalogAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorAnalogAccel = OffsetVectorWideRangeAccelShimmer3; + } + + } + } + + if (packetType==LSM303DLHC_ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]!=-1) { //used to be 65535 but changed to -1 as we are now using i16 + mDefaultCalibrationParametersDigitalAccel = false; + mAlignmentMatrixWRAccel = AlignmentMatrix; + mOffsetVectorWRAccel = OffsetVector; + mSensitivityMatrixWRAccel = SensitivityMatrix; + } else if(packetType==LSM303DLHC_ACCEL_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]==-1){ + mDefaultCalibrationParametersDigitalAccel = true; + if (getAccelRange()==0){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel2gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==1){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel4gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==2){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel8gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } else if (getAccelRange()==3){ + mSensitivityMatrixWRAccel = SensitivityMatrixWideRangeAccel16gShimmer3; + mAlignmentMatrixWRAccel = AlignmentMatrixWideRangeAccelShimmer3; + mOffsetVectorWRAccel = OffsetVectorWideRangeAccelShimmer3; + } + } + if (packetType==GYRO_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]!=-1) { + mDefaultCalibrationParametersGyro = false; + mAlignmentMatrixGyroscope = AlignmentMatrix; + mOffsetVectorGyroscope = OffsetVector; + mSensitivityMatrixGyroscope = SensitivityMatrix; + mSensitivityMatrixGyroscope[0][0] = mSensitivityMatrixGyroscope[0][0]/100; + mSensitivityMatrixGyroscope[1][1] = mSensitivityMatrixGyroscope[1][1]/100; + mSensitivityMatrixGyroscope[2][2] = mSensitivityMatrixGyroscope[2][2]/100; + + } else if(packetType==GYRO_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]==-1){ + mDefaultCalibrationParametersGyro = true; + if (mHardwareVersion!=3){ + mAlignmentMatrixGyroscope = AlignmentMatrixGyroShimmer2; + mOffsetVectorGyroscope = OffsetVectorGyroShimmer2; + mSensitivityMatrixGyroscope = SensitivityMatrixGyroShimmer2; + } else { + if (mGyroRange==0){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro250dpsShimmer3; + + } else if (mGyroRange==1){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro500dpsShimmer3; + + } else if (mGyroRange==2){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro1000dpsShimmer3; + + } else if (mGyroRange==3){ + mSensitivityMatrixGyroscope = SensitivityMatrixGyro2000dpsShimmer3; + } + mAlignmentMatrixGyroscope = AlignmentMatrixGyroShimmer3; + mOffsetVectorGyroscope = OffsetVectorGyroShimmer3; + } + } + if (packetType==MAG_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]!=-1) { + mDefaultCalibrationParametersMag = false; + mAlignmentMatrixMagnetometer = AlignmentMatrix; + mOffsetVectorMagnetometer = OffsetVector; + mSensitivityMatrixMagnetometer = SensitivityMatrix; + + } else if(packetType==MAG_CALIBRATION_RESPONSE && SensitivityMatrix[0][0]==-1){ + mDefaultCalibrationParametersMag = true; + if (mHardwareVersion!=3){ + mAlignmentMatrixMagnetometer = AlignmentMatrixMagShimmer2; + mOffsetVectorMagnetometer = OffsetVectorMagShimmer2; + if (mMagRange==0){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag0p8GaShimmer2; + } else if (mMagRange==1){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag1p3GaShimmer2; + } else if (mMagRange==2){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag1p9GaShimmer2; + } else if (mMagRange==3){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag2p5GaShimmer2; + } else if (mMagRange==4){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag4p0GaShimmer2; + } else if (mMagRange==5){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag4p7GaShimmer2; + } else if (mMagRange==6){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag5p6GaShimmer2; + } else if (mMagRange==7){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag8p1GaShimmer2; + } + } else { + mAlignmentMatrixMagnetometer = AlignmentMatrixMagShimmer3; + mOffsetVectorMagnetometer = OffsetVectorMagShimmer3; + if (mMagRange==1){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag1p3GaShimmer3; + } else if (mMagRange==2){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag1p9GaShimmer3; + } else if (mMagRange==3){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag2p5GaShimmer3; + } else if (mMagRange==4){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag4GaShimmer3; + } else if (mMagRange==5){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag4p7GaShimmer3; + } else if (mMagRange==6){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag5p6GaShimmer3; + } else if (mMagRange==7){ + mSensitivityMatrixMagnetometer = SensitivityMatrixMag8p1GaShimmer3; + } + } + } + } + } + + private double[][] matrixinverse3x3(double[][] data) { + double a,b,c,d,e,f,g,h,i; + a=data[0][0]; + b=data[0][1]; + c=data[0][2]; + d=data[1][0]; + e=data[1][1]; + f=data[1][2]; + g=data[2][0]; + h=data[2][1]; + i=data[2][2]; + // + double deter=a*e*i+b*f*g+c*d*h-c*e*g-b*d*i-a*f*h; + double[][] answer=new double[3][3]; + answer[0][0]=(1/deter)*(e*i-f*h); + + answer[0][1]=(1/deter)*(c*h-b*i); + answer[0][2]=(1/deter)*(b*f-c*e); + answer[1][0]=(1/deter)*(f*g-d*i); + answer[1][1]=(1/deter)*(a*i-c*g); + answer[1][2]=(1/deter)*(c*d-a*f); + answer[2][0]=(1/deter)*(d*h-e*g); + answer[2][1]=(1/deter)*(g*b-a*h); + answer[2][2]=(1/deter)*(a*e-b*d); + return answer; + } + private double[][] matrixminus(double[][] a ,double[][] b) { + int aRows = a.length, + aColumns = a[0].length, + bRows = b.length, + bColumns = b[0].length; + if (( aColumns != bColumns )&&( aRows != bRows )) { + throw new IllegalArgumentException(" Matrix did not match"); + } + double[][] resultant = new double[aRows][bColumns]; + for(int i = 0; i < aRows; i++) { // aRow + for(int k = 0; k < aColumns; k++) { // aColumn + + resultant[i][k]=a[i][k]-b[i][k]; + + } + } + return resultant; + } + + private double[][] matrixmultiplication(double[][] a,double[][] b) { + + int aRows = a.length, + aColumns = a[0].length, + bRows = b.length, + bColumns = b[0].length; + + if ( aColumns != bRows ) { + throw new IllegalArgumentException("A:Rows: " + aColumns + " did not match B:Columns " + bRows + "."); + } + + double[][] resultant = new double[aRows][bColumns]; + + for(int i = 0; i < aRows; i++) { // aRow + for(int j = 0; j < bColumns; j++) { // bColumn + for(int k = 0; k < aColumns; k++) { // aColumn + resultant[i][j] += a[i][k] * b[k][j]; + } + } + } + + return resultant; + } + + protected double calibrateTimeStamp(double timeStamp){ + //first convert to continuous time stamp + double calibratedTimeStamp=0; + if (mLastReceivedTimeStamp>(timeStamp+(mTimeStampPacketRawMaxValue*mCurrentTimeStampCycle))){ + mCurrentTimeStampCycle=mCurrentTimeStampCycle+1; + } + + mLastReceivedTimeStamp=(timeStamp+(mTimeStampPacketRawMaxValue*mCurrentTimeStampCycle)); + calibratedTimeStamp=mLastReceivedTimeStamp/32768*1000; // to convert into mS + if (mFirstTimeCalTime){ + mFirstTimeCalTime=false; + mCalTimeStart = calibratedTimeStamp; + } + if (mLastReceivedCalibratedTimeStamp!=-1){ + double timeDifference=calibratedTimeStamp-mLastReceivedCalibratedTimeStamp; + double expectedTimeDifference = (1/mShimmerSamplingRate)*1000; + double expectedTimeDifferenceLimit = expectedTimeDifference + (expectedTimeDifference*0.1); + //if (timeDifference>(1/(mShimmerSamplingRate-1))*1000){ + if (timeDifference>expectedTimeDifferenceLimit){ +// mPacketLossCount=mPacketLossCount+1; + mPacketLossCount+= (long) (timeDifference/expectedTimeDifferenceLimit); + Long mTotalNumberofPackets=(long) ((calibratedTimeStamp-mCalTimeStart)/(1/mShimmerSamplingRate*1000)); + + mPacketReceptionRate = (double)((mTotalNumberofPackets-mPacketLossCount)/(double)mTotalNumberofPackets)*100; + sendStatusMsgPacketLossDetected(); + } + } + mLastReceivedCalibratedTimeStamp=calibratedTimeStamp; + return calibratedTimeStamp; + } + + //protected abstract void sendStatusMsgPacketLossDetected(); + protected void sendStatusMsgPacketLossDetected() { + } + + protected double[] calibrateInertialSensorData(double[] data, double[][] AM, double[][] SM, double[][] OV) { + /* Based on the theory outlined by Ferraris F, Grimaldi U, and Parvis M. + in "Procedure for effortless in-field calibration of three-axis rate gyros and accelerometers" Sens. Mater. 1995; 7: 311-30. + C = [R^(-1)] .[K^(-1)] .([U]-[B]) + where..... + [C] -> [3 x n] Calibrated Data Matrix + [U] -> [3 x n] Uncalibrated Data Matrix + [B] -> [3 x n] Replicated Sensor Offset Vector Matrix + [R^(-1)] -> [3 x 3] Inverse Alignment Matrix + [K^(-1)] -> [3 x 3] Inverse Sensitivity Matrix + n = Number of Samples + */ + double [][] data2d=new double [3][1]; + data2d[0][0]=data[0]; + data2d[1][0]=data[1]; + data2d[2][0]=data[2]; + data2d= matrixmultiplication(matrixmultiplication(matrixinverse3x3(AM),matrixinverse3x3(SM)),matrixminus(data2d,OV)); + double[] ansdata=new double[3]; + ansdata[0]=data2d[0][0]; + ansdata[1]=data2d[1][0]; + ansdata[2]=data2d[2][0]; + return ansdata; + } + + protected double[] calibratePressureSensorData(double UP, double UT){ + double X1 = (UT - AC6) * AC5 / 32768; + double X2 = (MC * 2048 / (X1 + MD)); + double B5 = X1 + X2; + double T = (B5 + 8) / 16; + + double B6 = B5 - 4000; + X1 = (B2 * (Math.pow(B6,2)/ 4096)) / 2048; + X2 = AC2 * B6 / 2048; + double X3 = X1 + X2; + double B3 = (((AC1 * 4 + X3)*(1<>mPressureResolution); + double p=0; + if (B7 < 2147483648L ){ //0x80000000 + p = (B7 * 2) / B4; + } + else{ + p = (B7 / B4) * 2; + } + X1 = ((p / 256.0) * (p / 256.0) * 3038) / 65536; + X2 = (-7357 * p) / 65536; + p = p +( (X1 + X2 + 3791) / 16); + + double[] caldata = new double[2]; + caldata[0]=p; + caldata[1]=T/10; + return caldata; + } + + + protected double calibrateU12AdcValue(double uncalibratedData,double offset,double vRefP,double gain){ + double calibratedData=(uncalibratedData-offset)*(((vRefP*1000)/gain)/4095); + return calibratedData; + } + + protected double calibrateGsrData(double gsrUncalibratedData,double p1, double p2){ + gsrUncalibratedData = (double)((int)gsrUncalibratedData & 4095); + //the following polynomial is deprecated and has been replaced with a more accurate linear one, see GSR user guide for further details + //double gsrCalibratedData = (p1*Math.pow(gsrUncalibratedData,4)+p2*Math.pow(gsrUncalibratedData,3)+p3*Math.pow(gsrUncalibratedData,2)+p4*gsrUncalibratedData+p5)/1000; + //the following is the new linear method see user GSR user guide for further details + double gsrCalibratedData = (1/((p1*gsrUncalibratedData)+p2)*1000); //kohms + return gsrCalibratedData; + } + + public double getSamplingRate(){ + return mShimmerSamplingRate; + } + + public int getAccelRange(){ + return mAccelRange; + } + + public int getPressureResolution(){ + return mPressureResolution; + } + + public int getMagRange(){ + return mMagRange; + } + + public int getGyroRange(){ + return mGyroRange; + } + + public int getGSRRange(){ + return mGSRRange; + } + + public int getInternalExpPower(){ + return mInternalExpPower; + } + + public int getPMux(){ + if ((mConfigByte0 & (byte)64)!=0) { + //then set ConfigByte0 at bit position 7 + return 1; + } else{ + return 0; + } + } + + protected ObjectCluster callAdditionalServices(ObjectCluster objectCluster) { + return objectCluster; + } + + protected void interpretInqResponse(byte[] bufferInquiry){ + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + + mPacketSize = mTimeStampPacketByteSize+bufferInquiry[3]*2; + mShimmerSamplingRate = (double)1024/bufferInquiry[0]; + if (mLSM303MagRate==3 && mShimmerSamplingRate>10){ + mLowPowerMag = true; + } + mAccelRange = bufferInquiry[1]; + mConfigByte0 = bufferInquiry[2] & 0xFF; //convert the byte to unsigned integer + mNChannels = bufferInquiry[3]; + mBufferSize = bufferInquiry[4]; + byte[] signalIdArray = new byte[mNChannels]; + System.arraycopy(bufferInquiry, 5, signalIdArray, 0, mNChannels); + updateEnabledSensorsFromChannels(signalIdArray); + interpretdatapacketformat(mNChannels,signalIdArray); + mInquiryResponseBytes = new byte[5+mNChannels]; + System.arraycopy(bufferInquiry, 0, mInquiryResponseBytes , 0, mInquiryResponseBytes.length); + } else if (mHardwareVersion==HW_ID.SHIMMER_3) { + mPacketSize = mTimeStampPacketByteSize+bufferInquiry[6]*2; + mShimmerSamplingRate = (32768/(double)((int)(bufferInquiry[0] & 0xFF) + ((int)(bufferInquiry[1] & 0xFF) << 8))); + mNChannels = bufferInquiry[6]; + mBufferSize = bufferInquiry[7]; + mConfigByte0 = ((long)(bufferInquiry[2] & 0xFF) +((long)(bufferInquiry[3] & 0xFF) << 8)+((long)(bufferInquiry[4] & 0xFF) << 16) +((long)(bufferInquiry[5] & 0xFF) << 24)); + mAccelRange = ((int)(mConfigByte0 & 0xC))>>2; + mGyroRange = ((int)(mConfigByte0 & 196608))>>16; + mMagRange = ((int)(mConfigByte0 & 14680064))>>21; + mLSM303DigitalAccelRate = ((int)(mConfigByte0 & 0xF0))>>4; + mMPU9150GyroAccelRate = ((int)(mConfigByte0 & 65280))>>8; + mLSM303MagRate = ((int)(mConfigByte0 & 1835008))>>18; + mPressureResolution = (((int)(mConfigByte0 >>28)) & 3); + mGSRRange = (((int)(mConfigByte0 >>25)) & 7); + mInternalExpPower = (((int)(mConfigByte0 >>24)) & 1); + mInquiryResponseBytes = new byte[8+mNChannels]; + System.arraycopy(bufferInquiry, 0, mInquiryResponseBytes , 0, mInquiryResponseBytes.length); + if ((mLSM303DigitalAccelRate==2 && mShimmerSamplingRate>10)){ + mLowPowerAccelWR = true; + } + if ((mMPU9150GyroAccelRate==0xFF && mShimmerSamplingRate>10)){ + mLowPowerGyro = true; + } + if ((mLSM303MagRate==4 && mShimmerSamplingRate>10)){ + mLowPowerMag = true; + } + byte[] signalIdArray = new byte[mNChannels]; + System.arraycopy(bufferInquiry, 8, signalIdArray, 0, mNChannels); + updateEnabledSensorsFromChannels(signalIdArray); + interpretdatapacketformat(mNChannels,signalIdArray); + } else if (mHardwareVersion==HW_ID.SHIMMER_SR30) { + mPacketSize = mTimeStampPacketByteSize+bufferInquiry[2]*2; + mShimmerSamplingRate = (double)1024/bufferInquiry[0]; + mAccelRange = bufferInquiry[1]; + mNChannels = bufferInquiry[2]; + mBufferSize = bufferInquiry[3]; + byte[] signalIdArray = new byte[mNChannels]; + System.arraycopy(bufferInquiry, 4, signalIdArray, 0, mNChannels); // this is 4 because there is no config byte + interpretdatapacketformat(mNChannels,signalIdArray); + + } + } + + + protected void updateEnabledSensorsFromChannels(byte[] channels){ + // set the sensors value + // crude way of getting this value, but allows for more customised firmware + // to still work with this application + // e.g. if any axis of the accelerometer is being transmitted, then it will + // recognise that the accelerometer is being sampled + int enabledSensors = 0; + for (int i=0;i getListofEnabledSensors(){ + List listofSensors = new ArrayList(); + if (mHardwareVersion==HW_ID.SHIMMER_3){ + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0){ + listofSensors.add("Low Noise Accelerometer"); + } + if ((mEnabledSensors & SENSOR_DACCEL) > 0){ + listofSensors.add("Wide Range Accelerometer"); + } + } else { + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0){ + listofSensors.add("Accelerometer"); + } + } + if (((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0) { + listofSensors.add("Gyroscope"); + } + if (((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0) { + listofSensors.add("Magnetometer"); + } + if (((mEnabledSensors & 0xFF) & SENSOR_GSR) > 0) { + listofSensors.add("GSR"); + } + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + if (((mEnabledSensors & 0xFF) & SENSOR_ECG) > 0) { + listofSensors.add("ECG"); + } + if (((mEnabledSensors & 0xFF) & SENSOR_EMG) > 0) { + listofSensors.add("EMG"); + } + } + if (((mEnabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0) { + listofSensors.add("Bridge Amplifier"); + } + + if (((mEnabledSensors & 0xFF00) & SENSOR_HEART) > 0) { + listofSensors.add("Heart Rate"); + } + if (((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0 && (mEnabledSensors & SENSOR_BATT) == 0 && mHardwareVersion != HW_ID.SHIMMER_3) { + listofSensors.add("ExpBoard A0"); + } + if (((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0 && (mEnabledSensors & SENSOR_BATT) == 0 && mHardwareVersion != HW_ID.SHIMMER_3) { + listofSensors.add("ExpBoard A7"); + } + if ((mEnabledSensors & SENSOR_BATT) > 0) { + listofSensors.add("Battery Voltage"); + } + if (((mEnabledSensors & 0xFF) & SENSOR_EXT_ADC_A7) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("External ADC A7"); + } + if (((mEnabledSensors & 0xFF) & SENSOR_EXT_ADC_A6) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("External ADC A6"); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_EXT_ADC_A15) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("External ADC A15"); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_INT_ADC_A1) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("Internal ADC A1"); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_INT_ADC_A12) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("Internal ADC A12"); + } + if (((mEnabledSensors & 0xFFFFFF) & SENSOR_INT_ADC_A13) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("Internal ADC A13"); + } + if (((mEnabledSensors & 0xFFFFFF) & SENSOR_INT_ADC_A14) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("Internal ADC A14"); + } + if ((mEnabledSensors & SENSOR_BMP180) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("Pressure"); + } + if ((mEnabledSensors & SENSOR_EXG1_24BIT) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("EXG1"); + } + if ((mEnabledSensors & SENSOR_EXG2_24BIT) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("EXG2"); + } + if ((mEnabledSensors & SENSOR_EXG1_16BIT) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("EXG1 16Bit"); + } + if ((mEnabledSensors & SENSOR_EXG2_16BIT) > 0 && mHardwareVersion == HW_ID.SHIMMER_3) { + listofSensors.add("EXG2 16Bit"); + } + + return listofSensors; + } + + /** Returns a list of string[] of the four properties. 1) Shimmer Name - 2) Property/Signal Name - 3) Format Name - 4) Unit Name + * @return list string array of properties + */ + public List getListofEnabledSensorSignalsandFormats(){ + List listofSignals = new ArrayList(); + + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R){ + String[] channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.TIMESTAMP,"CAL","mSecs"}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.TIMESTAMP,"RAW",NO_UNIT}; + listofSignals.add(channel); + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0){ + String unit = "m/(sec^2)"; + if (mDefaultCalibrationParametersAccel == true) { + unit = "m/(sec^2)*"; + } + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ACCEL_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ACCEL_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ACCEL_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ACCEL_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ACCEL_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ACCEL_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + if (((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0) { + String unit = "deg/sec"; + if (mDefaultCalibrationParametersGyro == true) { + unit = "deg/sec*"; + } + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GYRO_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GYRO_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GYRO_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GYRO_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GYRO_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GYRO_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0) { + String unit = "local"; + if (mDefaultCalibrationParametersGyro == true) { + unit = "local*"; + } + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.MAG_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.MAG_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.MAG_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.MAG_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.MAG_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.MAG_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF) & SENSOR_GSR) > 0) { + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GSR,"CAL","kOhms"}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GSR,"RAW",NO_UNIT}; + listofSignals.add(channel); + + //channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.GSR_RES,"RAW",NO_UNIT}; + //listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF) & SENSOR_ECG) > 0) { + + String unit = "mVolts"; + if (mDefaultCalibrationParametersECG == true) { + unit = "mVolts*"; + } + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ECG_RA_LL,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ECG_RA_LL,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ECG_LA_LL,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.ECG_LA_LL,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + if (((mEnabledSensors & 0xFF) & SENSOR_EMG) > 0) { + String unit = "mVolts"; + if (mDefaultCalibrationParametersECG == true) { + unit = "mVolts*"; + } + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.EMG,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.EMG,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_HIGH,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.BRIDGE_AMP_LOW,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF00) & SENSOR_HEART) > 0) { + String unit = "BPM"; + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.HEART_RATE,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.HEART_RATE,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if ((((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A0) > 0) && getPMux() == 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.EXP_BOARD_A0,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if ((((mEnabledSensors & 0xFF) & SENSOR_EXP_BOARD_A7) > 0 && getPMux() == 0)) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.EXP_BOARD_A7,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_BATT) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.REG,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.REG,"RAW",NO_UNIT}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.BATTERY,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.BATTERY,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ + String unit = "local"; + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_A,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.AXIS_ANGLE_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_W,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer2.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z,"CAL",unit}; + listofSignals.add(channel); + } +// if (((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ +// String unit = "local"; +// channel = new String[]{mMyName,"Quaternion 0","CAL",unit}; +// listofSignals.add(channel); +// channel = new String[]{mMyName,"Quaternion 1","CAL",unit}; +// listofSignals.add(channel); +// channel = new String[]{mMyName,"Quaternion 2","CAL",unit}; +// listofSignals.add(channel); +// channel = new String[]{mMyName,"Quaternion 3","CAL",unit}; +// listofSignals.add(channel); +// } + + } else if (mHardwareVersion==HW_ID.SHIMMER_3) { + + String[] channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.TIMESTAMP,"CAL","mSecs"}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.TIMESTAMP,"RAW",NO_UNIT}; + listofSignals.add(channel); + if ((mEnabledSensors & SENSOR_ACCEL) >0){ + + String unit = "m/(sec^2)"; + if (mDefaultCalibrationParametersAccel == true) { + unit = "m/(sec^2)*"; + } + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_LN_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_LN_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + if ((mEnabledSensors& SENSOR_DACCEL) >0){ + + + String unit = "m/(sec^2)"; + if (mDefaultCalibrationParametersDigitalAccel == true) { + unit = "m/(sec^2)*"; + } + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_WR_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_WR_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + + + } + if (((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0) { + String unit = "deg/sec"; + if (mDefaultCalibrationParametersGyro == true) { + unit = "deg/sec*"; + } + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GYRO_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GYRO_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GYRO_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GYRO_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GYRO_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GYRO_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0) { + String unit = "local"; + if (mDefaultCalibrationParametersGyro == true) { + unit = "local*"; + } + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.MAG_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.MAG_X,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.MAG_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.MAG_Y,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.MAG_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.MAG_Z,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFF) & SENSOR_BATT) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.BATTERY,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.BATTERY,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_EXT_ADC_A15) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXT_EXP_A15,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXT_EXP_A15,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_EXT_ADC_A7) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXT_EXP_A7,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXT_EXP_A7,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_EXT_ADC_A6) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXT_EXP_A6,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXT_EXP_A6,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A1) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A1,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A1,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A12) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A12,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A12,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A13) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A13,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A13,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & 0xFFFFFF)& SENSOR_INT_ADC_A14) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A14,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.INT_EXP_A14,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if ((((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 || ((mEnabledSensors & 0xFFFF)& SENSOR_DACCEL) > 0)&& ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ + String unit = "local"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_A,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.AXIS_ANGLE_Z,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_W,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_X,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Y,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.QUAT_MADGE_9DOF_Z,"CAL",unit}; + listofSignals.add(channel); + } +// if ((((mEnabledSensors & 0xFF)& SENSOR_ACCEL) > 0 || ((mEnabledSensors & 0xFFFF)& SENSOR_DACCEL) > 0) && ((mEnabledSensors & 0xFF)& SENSOR_GYRO) > 0 && ((mEnabledSensors & 0xFF)& SENSOR_MAG) > 0 && mOrientationEnabled){ +// String unit = "local"; +// channel = new String[]{mMyName,"Quaternion 0","CAL",unit}; +// listofSignals.add(channel); +// channel = new String[]{mMyName,"Quaternion 1","CAL",unit}; +// listofSignals.add(channel); +// channel = new String[]{mMyName,"Quaternion 2","CAL",unit}; +// listofSignals.add(channel); +// channel = new String[]{mMyName,"Quaternion 3","CAL",unit}; +// listofSignals.add(channel); +// } + if ((mEnabledSensors & SENSOR_BMP180)>0){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180,"CAL","kPa"}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180,"RAW",NO_UNIT}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180,"CAL","Celsius"}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if ((mEnabledSensors & SENSOR_GSR)>0){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.GSR,"CAL","kOhms"}; + listofSignals.add(channel); + //channel = new String[]{mMyName,"Magnetometer X","RAW",NO_UNIT}; + //listofSignals.add(channel); + } + if (((mEnabledSensors & SENSOR_EXG1_24BIT)>0)|| ((mEnabledSensors & SENSOR_EXG1_16BIT)>0)){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_STATUS,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if (((mEnabledSensors & SENSOR_EXG2_24BIT)>0)|| ((mEnabledSensors & SENSOR_EXG2_16BIT)>0)){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_STATUS,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + if ((mEnabledSensors & SENSOR_EXG1_24BIT)>0){ + String unit = "mVolts"; + if (isEXGUsingDefaultECGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LL_RA_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LA_RA_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH1_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH2_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } else { + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + + } + if ((mEnabledSensors & SENSOR_EXG2_24BIT)>0){ + String unit = "mVolts"; + if (isEXGUsingDefaultECGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_VX_RL_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + else { + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + } + if ((mEnabledSensors & SENSOR_EXG1_16BIT)>0){ + String unit = "mVolts"; + if (isEXGUsingDefaultECGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LL_RA_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_LA_RA_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH1_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EMG_CH2_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } else { + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + + } + if ((mEnabledSensors & SENSOR_EXG2_16BIT)>0){ + String unit = "mVolts"; + if (isEXGUsingDefaultECGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.ECG_VX_RL_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + else if (isEXGUsingDefaultEMGConfiguration()){ + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + else { + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,"RAW",NO_UNIT}; + listofSignals.add(channel); + + } + } + if (((mEnabledSensors & 0xFF00) & SENSOR_BRIDGE_AMP) > 0) { + String unit = "mVolts"; + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH,"RAW",NO_UNIT}; + listofSignals.add(channel); + + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW,"CAL",unit}; + listofSignals.add(channel); + channel = new String[]{mMyName,Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW,"RAW",NO_UNIT}; + listofSignals.add(channel); + } + } + + if (mExtraSignalProperties != null){ + listofSignals.addAll(mExtraSignalProperties); + } + + return listofSignals; + } + + public void addExtraSignalProperty(String [] property){ + if (mExtraSignalProperties==null){ + mExtraSignalProperties = new ArrayList(); + } + mExtraSignalProperties.add(property); + } + + public void removeExtraSignalProperty(String [] property){ + for (int i=mExtraSignalProperties.size()-1;i>-1;i--){ + String[]p = mExtraSignalProperties.get(i); + if (p[0].equals(property[0]) && p[1].equals(property[1]) && p[2].equals(property[2]) && p[3].equals(property[3])){ + mExtraSignalProperties.remove(i); + } + + } + } + + //AlignmentMatrixMag, SensitivityMatrixMag, OffsetVectorMag + + public double[][] getAlignmentMatrixMag(){ + return mAlignmentMatrixMagnetometer; + } + + public double[][] getSensitivityMatrixMag(){ + return mSensitivityMatrixMagnetometer; + } + + public double[][] getOffsetVectorMatrixMag(){ + return mOffsetVectorMagnetometer; + } + + public double[][] getAlighmentMatrixGyro(){ + return mAlignmentMatrixGyroscope; + } + + public double[][] getSensitivityMatrixGyro(){ + return mSensitivityMatrixGyroscope; + } + + public double[][] getOffsetVectorMatrixGyro(){ + return mOffsetVectorGyroscope; + } + + public double[][] getAlighmentMatrixAccel(){ + return mAlignmentMatrixAnalogAccel; + } + + public double[][] getSensitivityMatrixAccel(){ + return mSensitivityMatrixAnalogAccel; + } + + public double[][] getOffsetVectorMatrixAccel(){ + return mOffsetVectorAnalogAccel; + } + + public double[][] getAlighmentMatrixWRAccel(){ + return mAlignmentMatrixWRAccel; + } + + public double[][] getSensitivityMatrixWRAccel(){ + return mSensitivityMatrixWRAccel; + } + + public double[][] getOffsetVectorMatrixWRAccel(){ + return mOffsetVectorWRAccel; + } + + public double[][] getOffsetVectorMPLAccel(){ + return OffsetVectorMPLAccel; + } + + public double[][] getSensitivityMatrixMPLAccel(){ + return SensitivityMatrixMPLAccel; + } + + public double[][] getAlignmentMatrixMPLAccel(){ + return AlignmentMatrixMPLAccel; + } + + public double[][] getOffsetVectorMPLMag(){ + return OffsetVectorMPLMag; + } + + public double[][] getSensitivityMatrixMPLMag(){ + return SensitivityMatrixMPLMag; + } + + public double[][] getAlignmentMatrixMPLMag(){ + return AlignmentMatrixMPLMag; + } + + public double[][] getOffsetVectorMPLGyro(){ + return OffsetVectorMPLGyro; + } + + public double[][] getSensitivityMatrixMPLGyro(){ + return SensitivityMatrixMPLGyro; + } + + public double[][] getAlignmentMatrixMPLGyro(){ + return AlignmentMatrixMPLGyro; + } + + + public long getEnabledSensors() { + return mEnabledSensors; + } + + public String[] getListofSupportedSensors(){ + String[] sensorNames = null; + if (mHardwareVersion==HW_ID.SHIMMER_2R || mHardwareVersion==HW_ID.SHIMMER_2){ + sensorNames = Configuration.Shimmer2.ListofCompatibleSensors; + } else if (mHardwareVersion==HW_ID.SHIMMER_3){ + sensorNames = Configuration.Shimmer3.ListofCompatibleSensors; + } + return sensorNames; + } + + public static String[] getListofSupportedSensors(int shimmerVersion){ + String[] sensorNames = null; + if (shimmerVersion==HW_ID.SHIMMER_2R || shimmerVersion==HW_ID.SHIMMER_2){ + sensorNames = Configuration.Shimmer2.ListofCompatibleSensors; + } else if (shimmerVersion==HW_ID.SHIMMER_3){ + sensorNames = Configuration.Shimmer3.ListofCompatibleSensors; + } + return sensorNames; + } + + /** + * @param enable this enables the calibration of the gyroscope while streaming + * @param bufferSize sets the buffersize of the window used to determine the new calibration parameters, see implementation for more details + * @param threshold sets the threshold of when to use the incoming data to recalibrate gyroscope offset, this is in degrees, and the default value is 1.2 + */ + public void enableOnTheFlyGyroCal(boolean enable,int bufferSize,double threshold){ + if (enable){ + mGyroOVCalThreshold=threshold; + mGyroX=new DescriptiveStatistics(bufferSize); + mGyroY=new DescriptiveStatistics(bufferSize); + mGyroZ=new DescriptiveStatistics(bufferSize); + mGyroXRaw=new DescriptiveStatistics(bufferSize); + mGyroYRaw=new DescriptiveStatistics(bufferSize); + mGyroZRaw=new DescriptiveStatistics(bufferSize); + mEnableOntheFlyGyroOVCal = enable; + } + } + + protected int convertEXGGainSettingToValue(int setting){ + + if (setting==0){ + return 6; + } else if (setting==1){ + return 1; + } else if (setting==2){ + return 2; + } else if (setting==3){ + return 3; + } else if (setting==4){ + return 4; + } else if (setting==5){ + return 8; + } else if (setting==6){ + return 12; + } + else { + return -1; // -1 means invalid value + } + + } + + /** + * Checks the EXG register bytes, and determines whether default ecg/emg are being used. + * @return 0 for ECG, 1 for EMG, 3 for test signal and 4 for custom + */ + public int checkEXGConfiguration(){ + return -1; + } + + public byte[] getEXG1RegisterContents(){ + return mEXG1RegisterArray; + } + + public byte[] getEXG2RegisterContents(){ + return mEXG2RegisterArray; + } + + public boolean isEXGUsingDefaultRespirationConfiguration(){ + boolean using = false; + if(((mEXG1RegisterArray[3] & 0x0F)==0)&&((mEXG1RegisterArray[4] & 0x0F)==0)&&((mEXG2RegisterArray[3] & 0x0F)==0)&&((mEXG2RegisterArray[4] & 0x0F)==7)&&((mEXG2RegisterArray[8] & 0xC0)==0xC0)){ + using = true; + } + return using; + } + + public boolean isEXGUsingDefaultECGConfiguration(){ + boolean using = false; + if(((mEXG1RegisterArray[3] & 0x0F)==0)&&((mEXG1RegisterArray[4] & 0x0F)==0)&& ((mEXG2RegisterArray[3] & 0x0F)==0)&&((mEXG2RegisterArray[4] & 0x0F)==7)){ + using = true; + } + return using; + } + + public boolean isEXGUsingDefaultTestSignalConfiguration(){ + boolean using = false; + if(((mEXG1RegisterArray[3] & 0x0F)==5)&&((mEXG1RegisterArray[4] & 0x0F)==5)&& ((mEXG2RegisterArray[3] & 0x0F)==5)&&((mEXG2RegisterArray[4] & 0x0F)==5)){ + using = true; + } + return using; + } + + public boolean isEXGUsingDefaultEMGConfiguration(){ + boolean using = false; + if(((mEXG1RegisterArray[3] & 0x0F)==9)&&((mEXG1RegisterArray[4] & 0x0F)==0)&& ((mEXG2RegisterArray[3] & 0x0F)==1)&&((mEXG2RegisterArray[4] & 0x0F)==1)){ + using = true; + } + return using; + } + + public byte[] getPressureRawCoefficients(){ + return mPressureCalRawParams; + } + + public int getExg1CH1GainValue(){ + return mEXG1CH1GainValue; + } + + public int getExg1CH2GainValue(){ + return mEXG1CH2GainValue; + } + + public int getExg2CH1GainValue(){ + return mEXG2CH1GainValue; + } + + public int getExg2CH2GainValue(){ + return mEXG2CH2GainValue; + } + + public String parseReferenceElectrodeTotring(int referenceElectrode){ + String refElectrode = "Unknown"; + + if(referenceElectrode==0 && (isEXGUsingDefaultECGConfiguration() || isEXGUsingDefaultEMGConfiguration())) + refElectrode = "Fixed Potential"; + else if(referenceElectrode==13 && isEXGUsingDefaultECGConfiguration()) + refElectrode = "Inverse Wilson CT"; + else if(referenceElectrode==3 && isEXGUsingDefaultEMGConfiguration()) + refElectrode = "Inverse of Ch1"; + + return refElectrode; + } + + public String parseLeadOffComparatorTresholdToString(int treshold){ + + String tresholdString=""; + switch(treshold){ + case 0: + tresholdString = "Pos:95% - Neg:5%"; + break; + case 1: + tresholdString = "Pos:92.5% - Neg:7.5%"; + break; + case 2: + tresholdString = "Pos:90% - Neg:10%"; + break; + case 3: + tresholdString = "Pos:87.5% - Neg:12.5%"; + break; + case 4: + tresholdString = "Pos:85% - Neg:15%"; + break; + case 5: + tresholdString = "Pos:80% - Neg:20%"; + break; + case 6: + tresholdString = "Pos:75% - Neg:25%"; + break; + case 7: + tresholdString = "Pos:70% - Neg:30%"; + break; + default: + tresholdString = "Treshold unread"; + break; + } + + return tresholdString; + } + + public String parseLeadOffModeToString(int leadOffMode){ + + String modeString=""; + switch(leadOffMode){ + case 0: + modeString +="Off"; + break; + case 1: + modeString +="DC Current"; + break; + case 2: + modeString +="AC Current"; + break; + default: + modeString +="No mode selected"; + break; + } + + return modeString; + } + + public String parseLeadOffDetectionCurrentToString(int current){ + + String currentString=""; + switch(current){ + case 0: + currentString +="6 nA"; + break; + case 1: + currentString +="22 nA"; + break; + case 2: + currentString +="6 uA"; + break; + default: + currentString +="22 uA"; + break; + } + + return currentString; + } + + + /** + * Computes the closest compatible sampling rate for the Shimmer based on + * the passed in 'rate' variable. Also computes the next highest available + * sampling rate for the Shimmer's sensors (dependent on pre-set low-power + * modes). + * + * @param rate + */ + public void setShimmerSamplingRate(double rate){ + + double maxRate = 0.0; + if (mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R) { + maxRate = 1024.0; + } else if (mHardwareVersion==HW_ID.SHIMMER_3 || mHardwareVersion==HW_ID.SHIMMER_GQ) { + maxRate = 2048.0; + } + // don't let sampling rate < 0 OR > maxRate + if(rate < 1) { + rate = 1.0; + } + else if (rate > maxRate) { + rate = maxRate; + } + + // get Shimmer compatible sampling rate + Double actualSamplingRate = maxRate/Math.floor(maxRate/rate); + // round sampling rate to two decimal places + actualSamplingRate = (double)Math.round(actualSamplingRate * 100) / 100; + mShimmerSamplingRate = actualSamplingRate; + + if(mHardwareVersion==HW_ID.SHIMMER_2 || mHardwareVersion==HW_ID.SHIMMER_2R) { + if(!mLowPowerMag){ + if(rate<=10) { + mShimmer2MagRate = 4; + } + else if (rate<=20) { + mShimmer2MagRate = 5; + } + else { + mShimmer2MagRate = 6; + } + } + else { + mShimmer2MagRate = 4; + } + } + else if (mHardwareVersion==HW_ID.SHIMMER_3 || mHardwareVersion==HW_ID.SHIMMER_GQ) { + setLSM303MagRateFromFreq(mShimmerSamplingRate); + setLSM303AccelRateFromFreq(mShimmerSamplingRate); + setMPU9150GyroAccelRateFromFreq(mShimmerSamplingRate); + setExGRateFromFreq(mShimmerSamplingRate); + } + } + + /** + * Computes next higher available sensor sampling rate setting based on + * passed in "freq" variable and dependent on whether low-power mode is set. + * + * @param freq + * @return int the rate configuration setting for the respective sensor + */ + private int setLSM303AccelRateFromFreq(double freq) { + // Unused: 8 = 1.620kHz (only low-power mode), 9 = 1.344kHz (normal-mode) / 5.376kHz (low-power mode) + + // Check if channel is enabled + if (mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL) != null) { + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mIsEnabled) { + mLSM303DigitalAccelRate = 0; // Power down + return mLSM303DigitalAccelRate; + } + } + + if (!mLowPowerAccelWR){ + if (freq<=1){ + mLSM303DigitalAccelRate = 1; // 1Hz + } else if (freq<=10){ + mLSM303DigitalAccelRate = 2; // 10Hz + } else if (freq<=25){ + mLSM303DigitalAccelRate = 3; // 25Hz + } else if (freq<=50){ + mLSM303DigitalAccelRate = 4; // 50Hz + } else if (freq<=100){ + mLSM303DigitalAccelRate = 5; // 100Hz + } else if (freq<=200){ + mLSM303DigitalAccelRate = 6; // 200Hz + } else if (freq<=400){ + mLSM303DigitalAccelRate = 7; // 400Hz + } else { + mLSM303DigitalAccelRate = 9; // 1344Hz + } + } + else { + if (freq>=10){ + mLSM303DigitalAccelRate = 2; // 10Hz + } else { + mLSM303DigitalAccelRate = 1; // 1Hz + } + } + return mLSM303DigitalAccelRate; + } + + /** + * Computes next higher available sensor sampling rate setting based on + * passed in "freq" variable and dependent on whether low-power mode is set. + * + * @param freq + * @return int the rate configuration setting for the respective sensor + */ + private int setLSM303MagRateFromFreq(double freq) { + // Check if channel is enabled + if (mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG) != null) { + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mIsEnabled) { + mLSM303MagRate = 0; // 0.75Hz + return mLSM303MagRate; + } + } + + if (!mLowPowerMag){ + if (freq<=0.75){ + mLSM303MagRate = 0; // 0.75Hz + } else if (freq<=1){ + mLSM303MagRate = 1; // 1.5Hz + } else if (freq<=3) { + mLSM303MagRate = 2; // 3Hz + } else if (freq<=7.5) { + mLSM303MagRate = 3; // 7.5Hz + } else if (freq<=15) { + mLSM303MagRate = 4; // 15Hz + } else if (freq<=30) { + mLSM303MagRate = 5; // 30Hz + } else if (freq<=75) { + mLSM303MagRate = 6; // 75Hz + } else { + mLSM303MagRate = 7; // 220Hz + } + } else { + if (freq>=10){ + mLSM303MagRate = 4; // 15Hz + } else { + mLSM303MagRate = 1; // 1.5Hz + } + } + return mLSM303MagRate; + } + + /** + * Computes next higher available sensor sampling rate setting based on + * passed in "freq" variable and dependent on whether low-power mode is set. + * + * @param freq + * @return int the rate configuration setting for the respective sensor + */ + public int setMPU9150GyroAccelRateFromFreq(double freq) { + // Check if channel is enabled + if (mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO) != null) { + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mIsEnabled) { + mMPU9150GyroAccelRate = 0xFF; // Dec. = 255, Freq. = 31.25Hz + return mMPU9150GyroAccelRate; + } + } + + // Gyroscope Output Rate = 8kHz when the DLPF (Digital Low-pass filter) is disabled (DLPF_CFG = 0 or 7), and 1kHz when the DLPF is enabled + double numerator = 1000; + if(mMPU9150LPF == 0) { + numerator = 8000; + } + + if (!mLowPowerGyro){ + if(freq<4) { + freq = 4; + } + else if(freq>numerator) { + freq = numerator; + } + int result = (int) Math.floor(((numerator / freq) - 1)); + if(result>255) { + result = 255; + } + mMPU9150GyroAccelRate = result; + + } + else { + mMPU9150GyroAccelRate = 0xFF; // Dec. = 255, Freq. = 31.25Hz + } + return mMPU9150GyroAccelRate; + } + + /** + * Computes next higher available sensor sampling rate setting based on + * passed in "freq" variable and dependent on whether low-power mode is set. + * + * @param freq + * @return int the rate configuration setting for the respective sensor + */ + public int setExGRateFromFreq(double freq) { + if (freq<=125) { + mEXG1RateSetting = 0x00; // 125Hz + } else if (freq<=250) { + mEXG1RateSetting = 0x01; // 250Hz + } else if (freq<=500) { + mEXG1RateSetting = 0x02; // 500Hz + } else if (freq<=1000) { + mEXG1RateSetting = 0x03; // 1000Hz + } else if (freq<=2000) { + mEXG1RateSetting = 0x04; // 2000Hz + } else if (freq<=4000) { + mEXG1RateSetting = 0x05; // 4000Hz + } else if (freq<=8000) { + mEXG1RateSetting = 0x06; // 8000Hz + } else { + mEXG1RateSetting = 0x02; // 500Hz + } + mEXG2RateSetting = mEXG1RateSetting; + + mEXG1RegisterArray[0] = (byte) ((mEXG1RegisterArray[0] & ~0x07) | mEXG1RateSetting); + mEXG2RegisterArray[0] = (byte) ((mEXG2RegisterArray[0] & ~0x07) | mEXG2RateSetting); + + //TODO decide whether to include exgBytesGetFromConfig() here or not + //exgBytesGetFromConfig(); + return mEXG1RateSetting; + } + + /** + * Checks to see if the MPU9150 gyro is in low power mode. As determined by + * the sensor's sampling rate being set to the lowest possible value and not + * related to any specific configuration bytes sent to the Shimmer/MPU9150. + * + * @return boolean, true if low-power mode enabled + */ + public boolean checkLowPowerGyro() { + if(mMPU9150GyroAccelRate == 0xFF) { + mLowPowerGyro = true; + } + else { + mLowPowerGyro = false; + } + return mLowPowerGyro; + } + + /** + * Checks to see if the LSM303DLHC Mag is in low power mode. As determined by + * the sensor's sampling rate being set to the lowest possible value and not + * related to any specific configuration bytes sent to the Shimmer/MPU9150. + * + * @return boolean, true if low-power mode enabled + */ + public boolean checkLowPowerMag() { + if(mLSM303MagRate <= 4) { + mLowPowerMag = true; + } + else { + mLowPowerMag = false; + } + return mLowPowerMag; + } + + + /** + * Populates the individual ExG related variables in ShimmerObject per ExG + * chip based on the ExG configuration byte arrays + * + * @param chipIndex + * indicates whether the bytes are specific to chip 1 or chip 2 + * on the ExG expansion board. + * @param byteArray + * the configuration byte array for an individual chip (10-bytes + * long) + */ + public void exgBytesGetConfigFrom(int chipIndex, byte[] byteArray) { + // to overcome possible backward compatability issues (where + // bufferAns.length was 11 or 12 using all of the ExG config bytes) + int index = 1; + if(byteArray.length == 10) { + index = 0; + } + + if (chipIndex==1){ + System.arraycopy(byteArray, index, mEXG1RegisterArray, 0, 10); + // retrieve the gain and rate from the the registers + mEXG1RateSetting = mEXG1RegisterArray[0] & 7; + mEXGLeadOffDetectionCurrent = (mEXG1RegisterArray[2] >> 2) & 3; + mEXGLeadOffComparatorTreshold = (mEXG1RegisterArray[2] >> 5) & 7; + mEXG1CH1GainSetting = (mEXG1RegisterArray[3] >> 4) & 7; + mEXG1CH1GainValue = convertEXGGainSettingToValue(mEXG1CH1GainSetting); + mEXG1CH2GainSetting = (mEXG1RegisterArray[4] >> 4) & 7; + mEXG1CH2GainValue = convertEXGGainSettingToValue(mEXG1CH2GainSetting); + mEXGReferenceElectrode = mEXG1RegisterArray[5] & 0x0F; + mEXG1LeadOffCurrentMode = mEXG1RegisterArray[2] & 1; + mEXG1Comparators = mEXG1RegisterArray[1] & 0x40; + mEXGRLDSense = mEXG1RegisterArray[5] & 0x10; + mEXG1LeadOffSenseSelection = mEXG1RegisterArray[6] & 0x0f; //2P1N1P + + } else if (chipIndex==2){ + System.arraycopy(byteArray, index, mEXG2RegisterArray, 0, 10); + mEXG2RateSetting = mEXG2RegisterArray[0] & 7; + mEXG2CH1GainSetting = (mEXG2RegisterArray[3] >> 4) & 7; + mEXG2CH1GainValue = convertEXGGainSettingToValue(mEXG2CH1GainSetting); + mEXG2CH2GainSetting = (mEXG2RegisterArray[4] >> 4) & 7; + mEXG2CH2GainValue = convertEXGGainSettingToValue(mEXG2CH2GainSetting); + mEXG2LeadOffCurrentMode = mEXG2RegisterArray[2] & 1; + mEXG2Comparators = mEXG2RegisterArray[1] & 0x40; + mEXG2LeadOffSenseSelection = mEXG2RegisterArray[6] & 0x0f; //2P + + mEXG2RespirationDetectState = (mEXG2RegisterArray[8] >> 6) & 0x03; + mEXG2RespirationDetectPhase = (mEXG2RegisterArray[8] >> 2) & 0x0F; + mEXG2RespirationDetectFreq = (mEXG2RegisterArray[9] >> 2) & 0x01; + } + } + + /** + * Generates the ExG configuration byte arrays based on the individual ExG + * related variables stored in ShimmerObject. The resulting arrays are + * stored in the global variables mEXG1RegisterArray and mEXG2RegisterArray. + * + */ + public void exgBytesGetFromConfig() { + //ExG Chip1 + mEXG1RegisterArray[0] &= ~(0x07 << 0); + mEXG1RegisterArray[0] |= (mEXG1RateSetting & 7) << 0; + + mEXG1RegisterArray[1] &= (~(0x40 << 0)); + mEXG1RegisterArray[1] |= ((mEXG1Comparators & 0x40) << 0); + + mEXG1RegisterArray[2] &= (~(0x01 << 0)); + mEXG1RegisterArray[2] |= ((mEXG1LeadOffCurrentMode & 0x01) << 0); + mEXG1RegisterArray[2] &= (~(0x03 << 2)); + mEXG1RegisterArray[2] |= ((mEXGLeadOffDetectionCurrent & 0x03) << 2); + mEXG1RegisterArray[2] &= (~(0x07 << 5)); + mEXG1RegisterArray[2] |= ((mEXGLeadOffComparatorTreshold & 0x07) << 5); + + mEXG1RegisterArray[3] &= (~(0x07 << 4)); + mEXG1RegisterArray[3] |= ((mEXG1CH1GainSetting & 0x07) << 4); + mEXG1RegisterArray[4] &= (~(0x07 << 4)); + mEXG1RegisterArray[4] |= ((mEXG1CH2GainSetting & 0x07) << 4); + + mEXG1RegisterArray[5] &= (~(0x0F << 0)); + mEXG1RegisterArray[5] |= ((mEXGReferenceElectrode & 0x0F) << 0); + mEXG1RegisterArray[1] &= (~(0x04 << 0)); + mEXG1RegisterArray[1] |= ((mEXG1Comparators & 0x40) << 0); + mEXG1RegisterArray[5] &= (~(0x10 << 0)); + mEXG1RegisterArray[5] |= ((mEXGRLDSense & 0x10) << 0); + mEXG1RegisterArray[6] &= (~(0x0F << 0)); + mEXG1RegisterArray[6] |= ((mEXG1LeadOffSenseSelection & 0x0F) << 0); + + //ExG Chip2 + mEXG2RegisterArray[0] &= (~(0x07 << 0)); + mEXG2RegisterArray[0] |= ((mEXG2RateSetting & 0x07) << 0); + + mEXG2RegisterArray[1] &= (~(0x40 << 0)); + mEXG2RegisterArray[1] |= ((mEXG2Comparators & 0x40) << 0); + + mEXG2RegisterArray[2] &= (~(0x01 << 0)); + mEXG2RegisterArray[2] |= ((mEXG2LeadOffCurrentMode & 0x01) << 0); + mEXG2RegisterArray[2] &= (~(0x03 << 2)); + mEXG2RegisterArray[2] |= ((mEXGLeadOffDetectionCurrent & 0x03) << 2); + mEXG2RegisterArray[2] &= (~(0x07 << 5)); + mEXG2RegisterArray[2] |= ((mEXGLeadOffComparatorTreshold & 0x07) << 5); + + mEXG2RegisterArray[3] &= (~(0x07 << 4)); + mEXG2RegisterArray[3] |= ((mEXG2CH1GainSetting & 0x07) << 4); + mEXG2RegisterArray[4] &= (~(0x07 << 4)); + mEXG2RegisterArray[4] |= ((mEXG2CH2GainSetting & 0x07) << 4); + + mEXG2RegisterArray[6] &= (~(0x0F << 0)); + mEXG2RegisterArray[6] |= ((mEXG2LeadOffSenseSelection & 0x0F) << 0); + + mEXG2RegisterArray[8] &= (~(0x03 << 6)); + mEXG2RegisterArray[8] |= ((mEXG2RespirationDetectState & 0x03) << 6); + mEXG2RegisterArray[8] &= (~(0x03 << 2)); + mEXG2RegisterArray[8] |= ((mEXG2RespirationDetectPhase & 0x0F) << 2); + mEXG2RegisterArray[9] &= (~(0x01 << 2)); + mEXG2RegisterArray[9] |= ((mEXG2RespirationDetectFreq & 0x01) << 2); + } + + + /** + * Checks if 16 bit ECG configuration is set on the Shimmer device. Do not + * use this command right after setting an EXG setting, as due to the + * execution model, the old settings might be returned, if this command is + * executed before an ack is received. + * + * @return true if 16 bit ECG is set + */ + public boolean isEXGUsingECG16Configuration(){ + boolean using = false; + if ((mEnabledSensors & SENSOR_EXG1_16BIT)>0 && (mEnabledSensors & SENSOR_EXG2_16BIT)>0){ + if(isEXGUsingDefaultECGConfiguration()){ + using = true; + } + } + return using; + } + + /** + * Checks if 24 bit ECG configuration is set on the Shimmer device. Do not + * use this command right after setting an EXG setting, as due to the + * execution model, the old settings might be returned, if this command is + * executed before an ack is received. + * + * @return true if 24 bit ECG is set + */ + public boolean isEXGUsingECG24Configuration(){ + boolean using = false; + if ((mEnabledSensors & SENSOR_EXG1_24BIT)>0 && (mEnabledSensors & SENSOR_EXG2_24BIT)>0){ + if(isEXGUsingDefaultECGConfiguration()){ + using = true; + } + } + return using; + } + + /** + * Checks if 16 bit EMG configuration is set on the Shimmer device. Do not + * use this command right after setting an EXG setting, as due to the + * execution model, the old settings might be returned, if this command is + * executed before an ack is received. + * + * @return true if 16 bit EMG is set + */ + public boolean isEXGUsingEMG16Configuration(){ + boolean using = false; + if ((mEnabledSensors & SENSOR_EXG1_16BIT)>0 && (mEnabledSensors & SENSOR_EXG2_16BIT)>0){ + if(isEXGUsingDefaultEMGConfiguration()){ + using = true; + } + } + return using; + } + + /** + * Checks if 24 bit EMG configuration is set on the Shimmer device. Do not + * use this command right after setting an EXG setting, as due to the + * execution model, the old settings might be returned, if this command is + * executed before an ack is received. + * + * @return true if 24 bit EMG is set + */ + public boolean isEXGUsingEMG24Configuration(){ + boolean using = false; + if ((mEnabledSensors & SENSOR_EXG1_24BIT)>0 && (mEnabledSensors & SENSOR_EXG2_24BIT)>0){ + if(isEXGUsingDefaultEMGConfiguration()){ + using = true; + } + } + return using; + } + + /** + * Checks if 16 bit test signal configuration is set on the Shimmer device. + * Do not use this command right after setting an EXG setting, as due to the + * execution model, the old settings might be returned, if this command is + * executed before an ack is received. + * + * @return true if 24 bit test signal is set + */ + public boolean isEXGUsingTestSignal16Configuration(){ + boolean using = false; + if ((mEnabledSensors & SENSOR_EXG1_16BIT)>0 && (mEnabledSensors & SENSOR_EXG2_16BIT)>0){ + if(isEXGUsingDefaultTestSignalConfiguration()){ + using = true; + } + } + return using; + } + + /** + * Checks if 24 bit test signal configuration is set on the Shimmer device. + * @return true if 24 bit test signal is set + */ + public boolean isEXGUsingTestSignal24Configuration(){ + boolean using = false; + if ((mEnabledSensors & SENSOR_EXG1_24BIT)>0 && (mEnabledSensors & SENSOR_EXG2_24BIT)>0){ + if(isEXGUsingDefaultTestSignalConfiguration()){ + using = true; + } + } + return using; + } + + /** + * This enables the calculation of 3D orientation through the use of the + * gradient descent algorithm, note that the user will have to ensure that + * mEnableCalibration has been set to true (see enableCalibration), and that + * the accel, gyro and mag has been enabled + * + * @param enable + */ + protected void set3DOrientation(boolean enable){ + //enable the sensors if they have not been enabled + mOrientationEnabled = enable; + } + + /** + * This enables the low power accel option. When not enabled the sampling + * rate of the accel is set to the closest value to the actual sampling rate + * that it can achieve. In low power mode it defaults to 10Hz. Also and + * additional low power mode is used for the LSM303DLHC. This command will + * only supports the following Accel range +4g, +8g , +16g + * + * @param enable + */ + protected void setLowPowerAccelWR(boolean enable){ + mLowPowerAccelWR = enable; + mHighResAccelWR = !enable; + + setLSM303AccelRateFromFreq(mShimmerSamplingRate); + + if(mConfigOptionsMap!=null) { + if(mLowPowerAccelWR) { + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCAccelRateLpm, + Configuration.Shimmer3.ListofLSM303DLHCAccelRateLpmConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + } + else { + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCAccelRate, + Configuration.Shimmer3.ListofLSM303DLHCAccelRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + } + } + } + + /** + * This enables the low-power gyro option. When not enabled the sampling + * rate of the gyro is set to the closest supported value to the actual + * sampling rate that it can achieve. For the Shimmer2, in low power mode it + * defaults to 10Hz. + * + * @param enable + */ + protected void setLowPowerGyro(boolean enable){ + mLowPowerGyro = enable; + setMPU9150GyroAccelRateFromFreq(mShimmerSamplingRate); + } + + /** + * This enables the low power mag option. When not enabled the sampling rate + * of the mag is set to the closest supported value to the actual sampling + * rate that it can achieve. In low power mode it defaults to 10Hz + * + * @param enable + */ + protected void setLowPowerMag(boolean enable){ + mLowPowerMag = enable; + if((mHardwareVersion==HW_ID.SHIMMER_2)||(mHardwareVersion==HW_ID.SHIMMER_2R)){ + if (!mLowPowerMag){ + if (mShimmerSamplingRate>=50){ + mShimmer2MagRate = 6; + } else if (mShimmerSamplingRate>=20) { + mShimmer2MagRate = 5; + } else if (mShimmerSamplingRate>=10) { + mShimmer2MagRate = 4; + } else { + mShimmer2MagRate = 3; + } + } else { + mShimmer2MagRate = 4; + } + } else { + setLSM303MagRateFromFreq(mShimmerSamplingRate); + } + } + + /** + * This can only be used for Shimmer3 devices (EXG) When a enable + * configuration is load, the advanced exg configuration is removed, so it + * needs to be set again + * + */ + protected void setDefaultRespirationConfiguration() { + if (mHardwareVersion==HW_ID.SHIMMER_3){ + mEXG1RegisterArray = new byte[]{(byte) 2,(byte) 160,(byte) 16,(byte) 64,(byte) 64,(byte) 0x20,(byte) 0,(byte) 0,(byte) 2,(byte) 3}; + mEXG2RegisterArray = new byte[]{(byte) 2,(byte) 160,(byte) 16,(byte) 64,(byte) 71,(byte) 0,(byte) 0,(byte) 0,(byte) 0xEA,(byte) 1}; + setExGRateFromFreq(mShimmerSamplingRate); + exgBytesGetConfigFrom(1, mEXG1RegisterArray); + exgBytesGetConfigFrom(2, mEXG2RegisterArray); + } + } + + /** + * This can only be used for Shimmer3 devices (EXG) When a enable + * configuration is load, the advanced exg configuration is removed, so it + * needs to be set again + * + */ + protected void setDefaultECGConfiguration() { + if (mHardwareVersion==HW_ID.SHIMMER_3){ + mEXG1RegisterArray = new byte[]{(byte) 2,(byte) 160,(byte) 16,(byte) 64,(byte) 64,(byte) 45,(byte) 0,(byte) 0,(byte) 2,(byte) 3}; + mEXG2RegisterArray = new byte[]{(byte) 2,(byte) 160,(byte) 16,(byte) 64,(byte) 71,(byte) 0,(byte) 0,(byte) 0,(byte) 2,(byte) 1}; + setExGRateFromFreq(mShimmerSamplingRate); + exgBytesGetConfigFrom(1, mEXG1RegisterArray); + exgBytesGetConfigFrom(2, mEXG2RegisterArray); + } + } + + /** + * This can only be used for Shimmer3 devices (EXG) When a enable + * configuration is load, the advanced exg configuration is removed, so it + * needs to be set again + */ + protected void setDefaultEMGConfiguration(){ + if (mHardwareVersion==HW_ID.SHIMMER_3){ + mEXG1RegisterArray = new byte[]{(byte) 2,(byte) 160,(byte) 16,(byte) 105,(byte) 96,(byte) 32,(byte) 0,(byte) 0,(byte) 2,(byte) 3}; + mEXG2RegisterArray = new byte[]{(byte) 2,(byte) 160,(byte) 16,(byte) 129,(byte) 129,(byte) 0,(byte) 0,(byte) 0,(byte) 2,(byte) 1}; + setExGRateFromFreq(mShimmerSamplingRate); + exgBytesGetConfigFrom(1, mEXG1RegisterArray); + exgBytesGetConfigFrom(2, mEXG2RegisterArray); + } + + } + + /** + * This can only be used for Shimmer3 devices (EXG). Enables the test signal + * (square wave) of both EXG chips, to use, both EXG1 and EXG2 have to be + * enabled + */ + protected void setEXGTestSignal(){ + if (mHardwareVersion==HW_ID.SHIMMER_3){ + mEXG1RegisterArray = new byte[]{(byte) 2,(byte) 163,(byte) 16,(byte) 5,(byte) 5,(byte) 0,(byte) 0,(byte) 0,(byte) 2,(byte) 1}; + mEXG2RegisterArray = new byte[]{(byte) 2,(byte) 163,(byte) 16,(byte) 5,(byte) 5,(byte) 0,(byte) 0,(byte) 0,(byte) 2,(byte) 1}; + setExGRateFromFreq(mShimmerSamplingRate); + exgBytesGetConfigFrom(1, mEXG1RegisterArray); + exgBytesGetConfigFrom(2, mEXG2RegisterArray); + } + } + + + /**Sets all default Shimmer settings in ShimmerObject. + * + */ + public void setDefaultShimmerConfiguration() { + if (mHardwareVersion != -1){ + + mShimmerUserAssignedName = DEFAULT_SHIMMER_NAME; + mExperimentName = DEFAULT_EXPERIMENT_NAME; + + mExperimentNumberOfShimmers = 1; + mExperimentId = 0; + mButtonStart = 1; + + mBluetoothBaudRate=0; + + mInternalExpPower=0; + + mExGResolution = 0; + mShimmer2MagRate=0; + + mMasterShimmer = 0; + mSingleTouch = 0; + mTCXO = 0; + + mPacketSize=0; + mConfigByte0=0; + mNChannels=0; + mBufferSize=0; + mSyncBroadcastInterval = 0; + mInitialTimeStamp = 0; + + setShimmerSamplingRate(51.2); + setDefaultECGConfiguration(); + + syncNodesList.clear(); + + sensorAndConfigMapsCreate(); + if (mHardwareVersion == HW_ID.SHIMMER_3){ + setSensorEnabledState(Configuration.Shimmer3.SensorMapKey.A_ACCEL, true); + setSensorEnabledState(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO, true); + setSensorEnabledState(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG, true); + setSensorEnabledState(Configuration.Shimmer3.SensorMapKey.VBATT, true); + } + } + } + + + /** + * Parse the Shimmer's Information Memory when read through the Shimmer + * Dock/Consensys Base. The Information Memory is a region of the Shimmer's + * inbuilt RAM where all configuration information is stored. + * + * @param infoMemContents + * the array of InfoMem bytes. + */ + protected void infoMemByteArrayParse(byte[] infoMemContents) { + String shimmerName = ""; + + // Check first 6 bytes of InfoMem for 0xFF to determine if contents are valid + byte[] comparisonBuffer = new byte[]{-1,-1,-1,-1,-1,-1}; + byte[] detectionBuffer = new byte[comparisonBuffer.length]; + System.arraycopy(infoMemContents, 0, detectionBuffer, 0, detectionBuffer.length); + if(Arrays.equals(comparisonBuffer, detectionBuffer)) { + // InfoMem not valid + setDefaultShimmerConfiguration(); + mShimmerUsingConfigFromInfoMem = false; + +// mShimmerInfoMemBytes = infoMemByteArrayGenerate(); +// mShimmerInfoMemBytes = new byte[infoMemContents.length]; + mInfoMemBytes = infoMemContents; + } + else { + mShimmerUsingConfigFromInfoMem = true; + + // InfoMem valid + + mInfoMemBytes = infoMemContents; + InfoMemLayout infoMemMap = new InfoMemLayout(mFirmwareIdentifier, mFirmwareVersionMajor, mFirmwareVersionMinor, mFirmwareVersionInternal); + + // InfoMem D - Start - used by BtStream, SdLog and LogAndStream + // Sampling Rate + mShimmerSamplingRate = (32768/(double)((int)(infoMemContents[infoMemMap.idxShimmerSamplingRate] & infoMemMap.maskShimmerSamplingRate) + ((int)(infoMemContents[infoMemMap.idxShimmerSamplingRate+1] & infoMemMap.maskShimmerSamplingRate) << 8))); + + mBufferSize = (int)(infoMemContents[infoMemMap.idxBufferSize] & infoMemMap.maskBufferSize); + + // Sensors + mEnabledSensors = ((long)infoMemContents[infoMemMap.idxSensors0] & infoMemMap.maskSensors) << infoMemMap.byteShiftSensors0; + mEnabledSensors += ((long)infoMemContents[infoMemMap.idxSensors1] & infoMemMap.maskSensors) << infoMemMap.byteShiftSensors1; + mEnabledSensors += ((long)infoMemContents[infoMemMap.idxSensors2] & infoMemMap.maskSensors) << infoMemMap.byteShiftSensors2; + + // Configuration + mLSM303DigitalAccelRate = (infoMemContents[infoMemMap.idxConfigSetupByte0] >> infoMemMap.bitShiftLSM303DLHCAccelSamplingRate) & infoMemMap.maskLSM303DLHCAccelSamplingRate; + mAccelRange = (infoMemContents[infoMemMap.idxConfigSetupByte0] >> infoMemMap.bitShiftLSM303DLHCAccelRange) & infoMemMap.maskLSM303DLHCAccelRange; + if(((infoMemContents[infoMemMap.idxConfigSetupByte0] >> infoMemMap.bitShiftLSM303DLHCAccelLPM) & infoMemMap.maskLSM303DLHCAccelLPM) == infoMemMap.maskLSM303DLHCAccelLPM) { + mLowPowerAccelWR = true; + } + else { + mLowPowerAccelWR = false; + } + if(((infoMemContents[infoMemMap.idxConfigSetupByte0] >> infoMemMap.bitShiftLSM303DLHCAccelHRM) & infoMemMap.maskLSM303DLHCAccelHRM) == infoMemMap.maskLSM303DLHCAccelHRM) { + mHighResAccelWR = true; + } + else { + mHighResAccelWR = false; + } + mMPU9150GyroAccelRate = (infoMemContents[infoMemMap.idxConfigSetupByte1] >> infoMemMap.bitShiftMPU9150AccelGyroSamplingRate) & infoMemMap.maskMPU9150AccelGyroSamplingRate; + checkLowPowerGyro(); // check rate to determine if Sensor is in LPM mode + + mMagRange = (infoMemContents[infoMemMap.idxConfigSetupByte2] >> infoMemMap.bitShiftLSM303DLHCMagRange) & infoMemMap.maskLSM303DLHCMagRange; + mLSM303MagRate = (infoMemContents[infoMemMap.idxConfigSetupByte2] >> infoMemMap.bitShiftLSM303DLHCMagSamplingRate) & infoMemMap.maskLSM303DLHCMagSamplingRate; + checkLowPowerMag(); // check rate to determine if Sensor is in LPM mode + + mGyroRange = (infoMemContents[infoMemMap.idxConfigSetupByte2] >> infoMemMap.bitShiftMPU9150GyroRange) & infoMemMap.maskMPU9150GyroRange; + + mMPU9150AccelRange = (infoMemContents[infoMemMap.idxConfigSetupByte3] >> infoMemMap.bitShiftMPU9150AccelRange) & infoMemMap.maskMPU9150AccelRange; + mPressureResolution = (infoMemContents[infoMemMap.idxConfigSetupByte3] >> infoMemMap.bitShiftBMP180PressureResolution) & infoMemMap.maskBMP180PressureResolution; + mGSRRange = (infoMemContents[infoMemMap.idxConfigSetupByte3] >> infoMemMap.bitShiftGSRRange) & infoMemMap.maskGSRRange; + mInternalExpPower = (infoMemContents[infoMemMap.idxConfigSetupByte3] >> infoMemMap.bitShiftEXPPowerEnable) & infoMemMap.maskEXPPowerEnable; + + //EXG Configuration + System.arraycopy(infoMemContents, infoMemMap.idxEXGADS1292RChip1Config1, mEXG1RegisterArray, 0, 10); + exgBytesGetConfigFrom(1,mEXG1RegisterArray); + + System.arraycopy(infoMemContents, infoMemMap.idxEXGADS1292RChip2Config1, mEXG2RegisterArray, 0, 10); + exgBytesGetConfigFrom(2,mEXG2RegisterArray); + + mBluetoothBaudRate = infoMemContents[infoMemMap.idxBtCommBaudRate] & infoMemMap.maskBaudRate; + //TODO: hack below -> fix +// if(!(mBluetoothBaudRate>=0 && mBluetoothBaudRate<=10)){ +// mBluetoothBaudRate = 0; +// } + + String[] dataType={"i16","i16","i16","i16","i16","i16","i8","i8","i8","i8","i8","i8","i8","i8","i8"}; + // Analog Accel Calibration Parameters + byte[] bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxAnalogAccelCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + int[] formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + double[] AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixAA = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixAA = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorAA = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + mAlignmentMatrixAnalogAccel = alignmentMatrixAA; + mSensitivityMatrixAnalogAccel = sensitivityMatrixAA; + mOffsetVectorAnalogAccel = offsetVectorAA; + + // MPU9150 Gyroscope Calibration Parameters + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxMPU9150GyroCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixG = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixG = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorG = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + mAlignmentMatrixGyroscope = alignmentMatrixG; + mSensitivityMatrixGyroscope = sensitivityMatrixG; + mSensitivityMatrixGyroscope[0][0] = mSensitivityMatrixGyroscope[0][0]/100; + mSensitivityMatrixGyroscope[1][1] = mSensitivityMatrixGyroscope[1][1]/100; + mSensitivityMatrixGyroscope[2][2] = mSensitivityMatrixGyroscope[2][2]/100; + mOffsetVectorGyroscope = offsetVectorG; + + // LSM303DLHC Magnetometer Calibration Parameters + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxLSM303DLHCMagCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixM = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixM = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorM = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + mAlignmentMatrixMagnetometer = alignmentMatrixM; + mSensitivityMatrixMagnetometer = sensitivityMatrixM; + mOffsetVectorMagnetometer = offsetVectorM; + + // LSM303DLHC Digital Accel Calibration Parameters + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxLSM303DLHCAccelCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + parseCalParamLSM303DLHCAccel(bufferCalibrationParameters); + + //TODO: decide what to do + // BMP180 Pressure Calibration Parameters + +// mDerivedSensors = (long)0; +// if((infoMemMap.idxDerivedSensors0>=0)&&(infoMemMap.idxDerivedSensors1>=0)) { // Check if compatible +// if((infoMemContents[infoMemMap.idxDerivedSensors0] != (byte)infoMemMap.maskDerivedChannelsByte) +// &&(infoMemContents[infoMemMap.idxDerivedSensors1] != (byte)infoMemMap.maskDerivedChannelsByte)){ +// mDerivedSensors = ((long)infoMemContents[infoMemMap.idxDerivedSensors0] & infoMemMap.maskDerivedChannelsByte) << infoMemMap.byteShiftDerivedSensors0; +// mDerivedSensors |= ((long)infoMemContents[infoMemMap.idxDerivedSensors1] & infoMemMap.maskDerivedChannelsByte) << infoMemMap.byteShiftDerivedSensors1; +// if(infoMemMap.idxDerivedSensors2>=0) { // Check if compatible +// mDerivedSensors |= ((long)infoMemContents[infoMemMap.idxDerivedSensors2] & infoMemMap.maskDerivedChannelsByte) << infoMemMap.byteShiftDerivedSensors2; +// } +// } +// } + + mDerivedSensors = (long)0; + if((infoMemMap.idxDerivedSensors0>=0)&&(infoMemContents[infoMemMap.idxDerivedSensors0] != (byte)infoMemMap.maskDerivedChannelsByte) + &&(infoMemMap.idxDerivedSensors1>=0)&&(infoMemContents[infoMemMap.idxDerivedSensors1] != (byte)infoMemMap.maskDerivedChannelsByte)) { // Check if compatible + + mDerivedSensors = ((long)infoMemContents[infoMemMap.idxDerivedSensors0] & infoMemMap.maskDerivedChannelsByte) << infoMemMap.byteShiftDerivedSensors0; + mDerivedSensors |= ((long)infoMemContents[infoMemMap.idxDerivedSensors1] & infoMemMap.maskDerivedChannelsByte) << infoMemMap.byteShiftDerivedSensors1; + + if((infoMemMap.idxDerivedSensors2>=0)&&(infoMemContents[infoMemMap.idxDerivedSensors2] != (byte)infoMemMap.maskDerivedChannelsByte)){ // Check if compatible + mDerivedSensors |= ((long)infoMemContents[infoMemMap.idxDerivedSensors2] & infoMemMap.maskDerivedChannelsByte) << infoMemMap.byteShiftDerivedSensors2; + } + } + + // InfoMem D - End + + //SDLog and LogAndStream + if(((mFirmwareIdentifier==FW_ID.SHIMMER3.LOGANDSTREAM)||(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG))&&(mInfoMemBytes.length >=384)) { + + // InfoMem C - Start - used by SdLog and LogAndStream + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + mMPU9150DMP = (infoMemContents[infoMemMap.idxConfigSetupByte4] >> infoMemMap.bitShiftMPU9150DMP) & infoMemMap.maskMPU9150DMP; + mMPU9150LPF = (infoMemContents[infoMemMap.idxConfigSetupByte4] >> infoMemMap.bitShiftMPU9150LPF) & infoMemMap.maskMPU9150LPF; + mMPU9150MotCalCfg = (infoMemContents[infoMemMap.idxConfigSetupByte4] >> infoMemMap.bitShiftMPU9150MotCalCfg) & infoMemMap.maskMPU9150MotCalCfg; + + mMPU9150MPLSamplingRate = (infoMemContents[infoMemMap.idxConfigSetupByte5] >> infoMemMap.bitShiftMPU9150MPLSamplingRate) & infoMemMap.maskMPU9150MPLSamplingRate; + mMPU9150MagSamplingRate = (infoMemContents[infoMemMap.idxConfigSetupByte5] >> infoMemMap.bitShiftMPU9150MagSamplingRate) & infoMemMap.maskMPU9150MagSamplingRate; + + mEnabledSensors += ((long)infoMemContents[infoMemMap.idxSensors3] & 0xFF) << infoMemMap.bitShiftSensors3; + mEnabledSensors += ((long)infoMemContents[infoMemMap.idxSensors4] & 0xFF) << infoMemMap.bitShiftSensors4; + + mMPLSensorFusion = (infoMemContents[infoMemMap.idxConfigSetupByte6] >> infoMemMap.bitShiftMPLSensorFusion) & infoMemMap.maskMPLSensorFusion; + mMPLGyroCalTC = (infoMemContents[infoMemMap.idxConfigSetupByte6] >> infoMemMap.bitShiftMPLGyroCalTC) & infoMemMap.maskMPLGyroCalTC; + mMPLVectCompCal = (infoMemContents[infoMemMap.idxConfigSetupByte6] >> infoMemMap.bitShiftMPLVectCompCal) & infoMemMap.maskMPLVectCompCal; + mMPLMagDistCal = (infoMemContents[infoMemMap.idxConfigSetupByte6] >> infoMemMap.bitShiftMPLMagDistCal) & infoMemMap.maskMPLMagDistCal; + mMPLEnable = (infoMemContents[infoMemMap.idxConfigSetupByte6] >> infoMemMap.bitShiftMPLEnable) & infoMemMap.maskMPLEnable; + + //MPL Accel Calibration Parameters + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxMPLAccelCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixMPLA = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixMPLA = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorMPLA = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + AlignmentMatrixMPLAccel = alignmentMatrixMPLA; + SensitivityMatrixMPLAccel = sensitivityMatrixMPLA; + OffsetVectorMPLAccel = offsetVectorMPLA; + + //MPL Mag Calibration Configuration + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxMPLMagCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixMPLMag = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixMPLMag = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorMPLMag = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + AlignmentMatrixMPLMag = alignmentMatrixMPLMag; + SensitivityMatrixMPLMag = sensitivityMatrixMPLMag; + OffsetVectorMPLMag = offsetVectorMPLMag; + + //MPL Gyro Calibration Configuration + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxMPLGyroCalibration, bufferCalibrationParameters, 0 , infoMemMap.lengthGeneralCalibrationBytes); + formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixMPLGyro = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixMPLGyro = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorMPLGyro = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + AlignmentMatrixMPLGyro = alignmentMatrixMPLGyro; + SensitivityMatrixMPLGyro = sensitivityMatrixMPLGyro; + OffsetVectorMPLGyro = offsetVectorMPLGyro; + } + + // Shimmer Name + byte[] shimmerNameBuffer = new byte[infoMemMap.lengthShimmerName]; + System.arraycopy(infoMemContents, infoMemMap.idxSDShimmerName, shimmerNameBuffer, 0 , infoMemMap.lengthShimmerName); + for(byte b : shimmerNameBuffer) { + if(!Util.isAsciiPrintable((char)b)) { + break; + } + shimmerName += (char)b; + } + + // Experiment Name + byte[] experimentNameBuffer = new byte[infoMemMap.lengthExperimentName]; + System.arraycopy(infoMemContents, infoMemMap.idxSDEXPIDName, experimentNameBuffer, 0 , infoMemMap.lengthExperimentName); + String experimentName = ""; + for(byte b : experimentNameBuffer) { + if(!Util.isAsciiPrintable((char)b)) { + break; + } + experimentName += (char)b; + } + mExperimentName = new String(experimentName); + + //Configuration Time + int bitShift = (infoMemMap.lengthConfigTimeBytes-1) * 8; + mConfigTime = 0; + for(int x=0; x> infoMemMap.bitShiftButtonStart) & infoMemMap.maskButtonStart; + + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + mSyncWhenLogging = (infoMemContents[infoMemMap.idxSDExperimentConfig0] >> infoMemMap.bitShiftTimeSyncWhenLogging) & infoMemMap.maskTimeSyncWhenLogging; + mMasterShimmer = (infoMemContents[infoMemMap.idxSDExperimentConfig0] >> infoMemMap.bitShiftMasterShimmer) & infoMemMap.maskTimeMasterShimmer; + mSingleTouch = (infoMemContents[infoMemMap.idxSDExperimentConfig1] >> infoMemMap.bitShiftSingleTouch) & infoMemMap.maskTimeSingleTouch; + mTCXO = (infoMemContents[infoMemMap.idxSDExperimentConfig1] >> infoMemMap.bitShiftTCX0) & infoMemMap.maskTimeTCX0; + + mSyncBroadcastInterval = (int)(infoMemContents[infoMemMap.idxSDBTInterval] & 0xFF); + + // Maximum and Estimated Length in minutes + mExperimentDurationEstimated = ((int)(infoMemContents[infoMemMap.idxEstimatedExpLengthLsb] & 0xFF) + (((int)(infoMemContents[infoMemMap.idxEstimatedExpLengthMsb] & 0xFF)) << 8)); + mExperimentDurationMaximum = ((int)(infoMemContents[infoMemMap.idxMaxExpLengthLsb] & 0xFF) + (((int)(infoMemContents[infoMemMap.idxMaxExpLengthMsb] & 0xFF)) << 8)); + } + + byte[] macIdBytes = new byte[infoMemMap.lengthMacIdBytes]; + System.arraycopy(infoMemContents, infoMemMap.idxMacAddress, macIdBytes, 0 , infoMemMap.lengthMacIdBytes); + mMacIdFromInfoMem = Util.bytesToHex(macIdBytes); + + + if(((infoMemContents[infoMemMap.idxSDConfigDelayFlag]>>infoMemMap.bitShiftSDCfgFileWriteFlag)&infoMemMap.maskSDCfgFileWriteFlag) == infoMemMap.maskSDCfgFileWriteFlag) { + mConfigFileCreationFlag = true; + } + else { + mConfigFileCreationFlag = false; + } + if(((infoMemContents[infoMemMap.idxSDConfigDelayFlag]>>infoMemMap.bitShiftSDCalibFileWriteFlag)&infoMemMap.maskSDCalibFileWriteFlag) == infoMemMap.maskSDCalibFileWriteFlag) { + mCalibFileCreationFlag = true; + } + else { + mCalibFileCreationFlag = false; + } + + // InfoMem C - End + + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + // InfoMem B Start -> Slave MAC ID for Multi-Shimmer Syncronisation + syncNodesList.clear(); + for (int i = 0; i < infoMemMap.maxNumOfExperimentNodes; i++) { + System.arraycopy(infoMemContents, infoMemMap.idxNode0 + (i*infoMemMap.lengthMacIdBytes), macIdBytes, 0 , infoMemMap.lengthMacIdBytes); + if(Arrays.equals(macIdBytes, infoMemMap.invalidMacId)) { +// if(Arrays.equals(macIdBytes, new byte[]{-1,-1,-1,-1,-1,-1})) { + break; + } + else { + syncNodesList.add(Util.bytesToHex(macIdBytes)); + } + } + // InfoMem B End + } + } + + //TODO Complete and tidy below + sensorAndConfigMapsCreate(); + sensorMapUpdateWithEnabledSensors(); + +// sensorMapCheckandCorrectSensorDependencies(); + } + + // Set name if nothing was read from InfoMem + if(!shimmerName.isEmpty()) { + mShimmerUserAssignedName = new String(shimmerName); + } + else { + mShimmerUserAssignedName = DEFAULT_SHIMMER_NAME; + if(!mMacIdFromUartParsed.isEmpty()) { + mShimmerUserAssignedName += "_" + mMacIdFromUartParsed; + } + } + + } + + /** + * Generate the Shimmer's Information Memory byte array based on the + * settings stored in ShimmerObject. These bytes can then be written to the + * Shimmer via the Shimmer Dock/Consensys Base. The Information Memory is is + * a region of the Shimmer's inbuilt RAM where all configuration information + * is stored. + * + * @param generateForWritingToShimmer + * @return + */ + protected byte[] infoMemByteArrayGenerate(boolean generateForWritingToShimmer) { + + InfoMemLayout infoMemMap = new InfoMemLayout(mFirmwareIdentifier, mFirmwareVersionMajor, mFirmwareVersionMinor, mFirmwareVersionInternal); + + byte[] infoMemBackup = mInfoMemBytes.clone(); + + mInfoMemBytes = new byte[infoMemMap.mInfoMemSize]; +// mShimmerInfoMemBytes = createEmptyInfoMemByteArray(getExpectedInfoMemByteLength()); + + // InfoMem defaults to 0xFF on firmware flash + for(int i =0; i < mInfoMemBytes.length; i++) { + mInfoMemBytes[i] = (byte) 0xFF; + } + + // If not being generated from scratch then copy across exisiting InfoMem contents + if(!generateForWritingToShimmer) { + System.arraycopy(infoMemBackup, 0, mInfoMemBytes, 0, (infoMemBackup.length > mInfoMemBytes.length) ? mInfoMemBytes.length:infoMemBackup.length); + } + + + // InfoMem D - Start - used by BtStream, SdLog and LogAndStream + // Sampling Rate + int samplingRate = (int)(32768 / mShimmerSamplingRate); + mInfoMemBytes[infoMemMap.idxShimmerSamplingRate] = (byte) (samplingRate & infoMemMap.maskShimmerSamplingRate); + mInfoMemBytes[infoMemMap.idxShimmerSamplingRate+1] = (byte) ((samplingRate >> 8) & infoMemMap.maskShimmerSamplingRate); + + //FW not using this feature and BtStream will reject infomem if this isn't set to '1' + mInfoMemBytes[infoMemMap.idxBufferSize] = (byte) 1;//(byte) (mBufferSize & infoMemMap.maskBufferSize); + + // Sensors + //TODO: check version compatible? + mEnabledSensors = (long)0; + sensorMapCheckandCorrectHwDependencies(); + for(Integer key:mSensorMap.keySet()) { + if(mSensorMap.get(key).mIsEnabled) { + mEnabledSensors |= mSensorMap.get(key).mSensorBitmapIDSDLogHeader; + } + } + mInfoMemBytes[infoMemMap.idxSensors0] = (byte) ((mEnabledSensors >> infoMemMap.byteShiftSensors0) & infoMemMap.maskSensors); + mInfoMemBytes[infoMemMap.idxSensors1] = (byte) ((mEnabledSensors >> infoMemMap.byteShiftSensors1) & infoMemMap.maskSensors); + mInfoMemBytes[infoMemMap.idxSensors2] = (byte) ((mEnabledSensors >> infoMemMap.byteShiftSensors2) & infoMemMap.maskSensors); +// setDefaultConfigForDisabledSensors(); + + // Configuration + mInfoMemBytes[infoMemMap.idxConfigSetupByte0] = (byte) ((mLSM303DigitalAccelRate & infoMemMap.maskLSM303DLHCAccelSamplingRate) << infoMemMap.bitShiftLSM303DLHCAccelSamplingRate); + mInfoMemBytes[infoMemMap.idxConfigSetupByte0] |= (byte) ((mAccelRange & infoMemMap.maskLSM303DLHCAccelRange) << infoMemMap.bitShiftLSM303DLHCAccelRange); + if(mLowPowerAccelWR) { + mInfoMemBytes[infoMemMap.idxConfigSetupByte0] |= (infoMemMap.maskLSM303DLHCAccelLPM << infoMemMap.bitShiftLSM303DLHCAccelLPM); + } + if(mHighResAccelWR) { + mInfoMemBytes[infoMemMap.idxConfigSetupByte0] |= (infoMemMap.maskLSM303DLHCAccelHRM << infoMemMap.bitShiftLSM303DLHCAccelHRM); + } + + mInfoMemBytes[infoMemMap.idxConfigSetupByte1] = (byte) ((mMPU9150GyroAccelRate & infoMemMap.maskMPU9150AccelGyroSamplingRate) << infoMemMap.bitShiftMPU9150AccelGyroSamplingRate); + + mInfoMemBytes[infoMemMap.idxConfigSetupByte2] = (byte) ((mMagRange & infoMemMap.maskLSM303DLHCMagRange) << infoMemMap.bitShiftLSM303DLHCMagRange); + mInfoMemBytes[infoMemMap.idxConfigSetupByte2] |= (byte) ((mLSM303MagRate & infoMemMap.maskLSM303DLHCMagSamplingRate) << infoMemMap.bitShiftLSM303DLHCMagSamplingRate); + mInfoMemBytes[infoMemMap.idxConfigSetupByte2] |= (byte) ((mGyroRange & infoMemMap.maskMPU9150GyroRange) << infoMemMap.bitShiftMPU9150GyroRange); + + mInfoMemBytes[infoMemMap.idxConfigSetupByte3] = (byte) ((mMPU9150AccelRange & infoMemMap.maskMPU9150AccelRange) << infoMemMap.bitShiftMPU9150AccelRange); + mInfoMemBytes[infoMemMap.idxConfigSetupByte3] |= (byte) ((mPressureResolution & infoMemMap.maskBMP180PressureResolution) << infoMemMap.bitShiftBMP180PressureResolution); + mInfoMemBytes[infoMemMap.idxConfigSetupByte3] |= (byte) ((mGSRRange & infoMemMap.maskGSRRange) << infoMemMap.bitShiftGSRRange); + mInfoMemBytes[infoMemMap.idxConfigSetupByte3] |= (byte) ((mInternalExpPower & infoMemMap.maskEXPPowerEnable) << infoMemMap.bitShiftEXPPowerEnable); + + //EXG Configuration + //update mEXG1Register and mEXG2Register + exgBytesGetFromConfig(); + System.arraycopy(mEXG1RegisterArray, 0, mInfoMemBytes, infoMemMap.idxEXGADS1292RChip1Config1, 10); + System.arraycopy(mEXG2RegisterArray, 0, mInfoMemBytes, infoMemMap.idxEXGADS1292RChip2Config1, 10); +// exgBytesGetConfigFrom(1, mEXG1Register); +// exgBytesGetConfigFrom(2, mEXG2Register); + + mInfoMemBytes[infoMemMap.idxBtCommBaudRate] = (byte) (mBluetoothBaudRate & infoMemMap.maskBaudRate); + + // Analog Accel Calibration Parameters + byte[] bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + // offsetVector -> buffer offset = 0 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[0+(i*2)] = (byte) ((((int)mOffsetVectorAnalogAccel[i][0]) >> 0) & 0xFF); + bufferCalibrationParameters[0+(i*2)+1] = (byte) ((((int)mOffsetVectorAnalogAccel[i][0]) >> 8) & 0xFF); + } + // sensitivityMatrix -> buffer offset = 6 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[6+(i*2)] = (byte) ((((int)mSensitivityMatrixAnalogAccel[i][i]) >> 0) & 0xFF); + bufferCalibrationParameters[6+(i*2)+1] = (byte) ((((int)mSensitivityMatrixAnalogAccel[i][i]) >> 8) & 0xFF); + } + // alignmentMatrix -> buffer offset = 12 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[12+(i*3)] = (byte) (((int)(mAlignmentMatrixAnalogAccel[i][0]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+1] = (byte) (((int)(mAlignmentMatrixAnalogAccel[i][1]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+2] = (byte) (((int)(mAlignmentMatrixAnalogAccel[i][2]*100)) & 0xFF); + } + System.arraycopy(bufferCalibrationParameters, 0, mInfoMemBytes, infoMemMap.idxAnalogAccelCalibration, infoMemMap.lengthGeneralCalibrationBytes); + + // MPU9150 Gyroscope Calibration Parameters + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + // offsetVector -> buffer offset = 0 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[0+(i*2)] = (byte) ((((int)mOffsetVectorGyroscope[i][0]) >> 0) & 0xFF); + bufferCalibrationParameters[0+(i*2)+1] = (byte) ((((int)mOffsetVectorGyroscope[i][0]) >> 8) & 0xFF); + } + // sensitivityMatrix -> buffer offset = 6 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[6+(i*2)] = (byte) ((((int)mSensitivityMatrixGyroscope[i][i]) >> 0) & 0xFF); + bufferCalibrationParameters[6+(i*2)+1] = (byte) ((((int)mSensitivityMatrixGyroscope[i][i]) >> 8) & 0xFF); + } + // alignmentMatrix -> buffer offset = 12 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[12+(i*3)] = (byte) (((int)(mAlignmentMatrixAnalogAccel[i][0]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+1] = (byte) (((int)(mAlignmentMatrixAnalogAccel[i][1]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+2] = (byte) (((int)(mAlignmentMatrixAnalogAccel[i][2]*100)) & 0xFF); + } + System.arraycopy(bufferCalibrationParameters, 0, mInfoMemBytes, infoMemMap.idxMPU9150GyroCalibration, infoMemMap.lengthGeneralCalibrationBytes); + + // LSM303DLHC Magnetometer Calibration Parameters + bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + // offsetVector -> buffer offset = 0 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[0+(i*2)] = (byte) ((((int)mOffsetVectorMagnetometer[i][0]) >> 0) & 0xFF); + bufferCalibrationParameters[0+(i*2)+1] = (byte) ((((int)mOffsetVectorMagnetometer[i][0]) >> 8) & 0xFF); + } + // sensitivityMatrix -> buffer offset = 6 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[6+(i*2)] = (byte) ((((int)mSensitivityMatrixMagnetometer[i][i]) >> 0) & 0xFF); + bufferCalibrationParameters[6+(i*2)+1] = (byte) ((((int)mSensitivityMatrixMagnetometer[i][i]) >> 8) & 0xFF); + } + // alignmentMatrix -> buffer offset = 12 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[12+(i*3)] = (byte) (((int)(mAlignmentMatrixMagnetometer[i][0]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+1] = (byte) (((int)(mAlignmentMatrixMagnetometer[i][1]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+2] = (byte) (((int)(mAlignmentMatrixMagnetometer[i][2]*100)) & 0xFF); + } + System.arraycopy(bufferCalibrationParameters, 0, mInfoMemBytes, infoMemMap.idxLSM303DLHCMagCalibration, infoMemMap.lengthGeneralCalibrationBytes); + + // LSM303DLHC Digital Accel Calibration Parameters +// bufferCalibrationParameters = new byte[infoMemMap.lengthGeneralCalibrationBytes]; + bufferCalibrationParameters = generateCalParamLSM303DLHCAccel(); + System.arraycopy(bufferCalibrationParameters, 0, mInfoMemBytes, infoMemMap.idxLSM303DLHCAccelCalibration, infoMemMap.lengthGeneralCalibrationBytes); + + //TODO: decide what to do + // BMP180 Pressure Calibration Parameters + + // Derived Sensors + mDerivedSensors = (long)0; + if((infoMemMap.idxDerivedSensors0>=0)&&(infoMemMap.idxDerivedSensors1>=0)) { // Check if compatible + for(Integer key:mSensorMap.keySet()) { + if(mSensorMap.get(key).mIsEnabled) { + mDerivedSensors |= mSensorMap.get(key).mDerivedSensorBitmapID; + } + } + mInfoMemBytes[infoMemMap.idxDerivedSensors0] = (byte) ((mDerivedSensors >> infoMemMap.byteShiftDerivedSensors0) & infoMemMap.maskDerivedChannelsByte); + mInfoMemBytes[infoMemMap.idxDerivedSensors1] = (byte) ((mDerivedSensors >> infoMemMap.byteShiftDerivedSensors1) & infoMemMap.maskDerivedChannelsByte); + if(infoMemMap.idxDerivedSensors2>=0) { // Check if compatible + mInfoMemBytes[infoMemMap.idxDerivedSensors2] = (byte) ((mDerivedSensors >> infoMemMap.byteShiftDerivedSensors2) & infoMemMap.maskDerivedChannelsByte); + } + + } + + // InfoMem D - End + + + //TODO: Add full FW version checking here to support future changes to FW + //SDLog and LogAndStream + if(((mFirmwareIdentifier==FW_ID.SHIMMER3.LOGANDSTREAM)||(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG))&&(mInfoMemBytes.length >=384)) { + + // InfoMem C - Start - used by SdLog and LogAndStream + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + mInfoMemBytes[infoMemMap.idxConfigSetupByte4] = (byte) ((mMPU9150DMP & infoMemMap.maskMPU9150DMP) << infoMemMap.bitShiftMPU9150DMP); + mInfoMemBytes[infoMemMap.idxConfigSetupByte4] |= (byte) ((mMPU9150LPF & infoMemMap.maskMPU9150LPF) << infoMemMap.bitShiftMPU9150LPF); + mInfoMemBytes[infoMemMap.idxConfigSetupByte4] |= (byte) ((mMPU9150MotCalCfg & infoMemMap.maskMPU9150MotCalCfg) << infoMemMap.bitShiftMPU9150MotCalCfg); + + mInfoMemBytes[infoMemMap.idxConfigSetupByte5] = (byte) ((mMPU9150MPLSamplingRate & infoMemMap.maskMPU9150MPLSamplingRate) << infoMemMap.bitShiftMPU9150MPLSamplingRate); + mInfoMemBytes[infoMemMap.idxConfigSetupByte5] |= (byte) ((mMPU9150MagSamplingRate & infoMemMap.maskMPU9150MPLSamplingRate) << infoMemMap.bitShiftMPU9150MagSamplingRate); + + mInfoMemBytes[infoMemMap.idxSensors3] = (byte) ((mEnabledSensors >> infoMemMap.bitShiftSensors3) & 0xFF); + mInfoMemBytes[infoMemMap.idxSensors4] = (byte) ((mEnabledSensors >> infoMemMap.bitShiftSensors4) & 0xFF); + + mInfoMemBytes[infoMemMap.idxConfigSetupByte6] = (byte) ((mMPLSensorFusion & infoMemMap.maskMPLSensorFusion) << infoMemMap.bitShiftMPLSensorFusion); + mInfoMemBytes[infoMemMap.idxConfigSetupByte6] |= (byte) ((mMPLGyroCalTC & infoMemMap.maskMPLGyroCalTC) << infoMemMap.bitShiftMPLGyroCalTC); + mInfoMemBytes[infoMemMap.idxConfigSetupByte6] |= (byte) ((mMPLVectCompCal & infoMemMap.maskMPLVectCompCal) << infoMemMap.bitShiftMPLVectCompCal); + mInfoMemBytes[infoMemMap.idxConfigSetupByte6] |= (byte) ((mMPLMagDistCal & infoMemMap.maskMPLMagDistCal) << infoMemMap.bitShiftMPLMagDistCal); + mInfoMemBytes[infoMemMap.idxConfigSetupByte6] |= (byte) ((mMPLEnable & infoMemMap.maskMPLEnable) << infoMemMap.bitShiftMPLEnable); + + //TODO: decide what to do + //MPL Accel Calibration Parameters + //MPL Mag Calibration Configuration + //MPL Gyro Calibration Configuration + } + + // Shimmer Name + for (int i = 0; i < infoMemMap.lengthShimmerName; i++) { + if (i < mShimmerUserAssignedName.length()) { + mInfoMemBytes[infoMemMap.idxSDShimmerName + i] = (byte) mShimmerUserAssignedName.charAt(i); + } + else { + mInfoMemBytes[infoMemMap.idxSDShimmerName + i] = (byte) 0xFF; + } + } + + // Experiment Name + for (int i = 0; i < infoMemMap.lengthExperimentName; i++) { + if (i < mExperimentName.length()) { + mInfoMemBytes[infoMemMap.idxSDEXPIDName + i] = (byte) mExperimentName.charAt(i); + } + else { + mInfoMemBytes[infoMemMap.idxSDEXPIDName + i] = (byte) 0xFF; + } + } + + //Configuration Time + mInfoMemBytes[infoMemMap.idxSDConfigTime0] = (byte) ((mConfigTime >> infoMemMap.bitShiftSDConfigTime0) & 0xFF); + mInfoMemBytes[infoMemMap.idxSDConfigTime1] = (byte) ((mConfigTime >> infoMemMap.bitShiftSDConfigTime1) & 0xFF); + mInfoMemBytes[infoMemMap.idxSDConfigTime2] = (byte) ((mConfigTime >> infoMemMap.bitShiftSDConfigTime2) & 0xFF); + mInfoMemBytes[infoMemMap.idxSDConfigTime3] = (byte) ((mConfigTime >> infoMemMap.bitShiftSDConfigTime3) & 0xFF); + + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + mInfoMemBytes[infoMemMap.idxSDMyTrialID] = (byte) (mExperimentId & 0xFF); + + mInfoMemBytes[infoMemMap.idxSDNumOfShimmers] = (byte) (mExperimentNumberOfShimmers & 0xFF); + } + + mInfoMemBytes[infoMemMap.idxSDExperimentConfig0] = (byte) ((mButtonStart & infoMemMap.maskButtonStart) << infoMemMap.bitShiftButtonStart); + + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + mInfoMemBytes[infoMemMap.idxSDExperimentConfig0] |= (byte) ((mSyncWhenLogging & infoMemMap.maskTimeSyncWhenLogging) << infoMemMap.bitShiftTimeSyncWhenLogging); + mInfoMemBytes[infoMemMap.idxSDExperimentConfig0] |= (byte) ((mMasterShimmer & infoMemMap.maskTimeMasterShimmer) << infoMemMap.bitShiftMasterShimmer); + + mInfoMemBytes[infoMemMap.idxSDExperimentConfig1] = (byte) ((mSingleTouch & infoMemMap.maskTimeSingleTouch) << infoMemMap.bitShiftSingleTouch); + mInfoMemBytes[infoMemMap.idxSDExperimentConfig1] |= (byte) ((mTCXO & infoMemMap.maskTimeTCX0) << infoMemMap.bitShiftTCX0); + + mInfoMemBytes[infoMemMap.idxSDBTInterval] = (byte) (mSyncBroadcastInterval & 0xFF); + + // Maximum and Estimated Length in minutes + mInfoMemBytes[infoMemMap.idxEstimatedExpLengthLsb] = (byte) ((mExperimentDurationEstimated >> 0) & 0xFF); + mInfoMemBytes[infoMemMap.idxEstimatedExpLengthMsb] = (byte) ((mExperimentDurationEstimated >> 8) & 0xFF); + mInfoMemBytes[infoMemMap.idxMaxExpLengthLsb] = (byte) ((mExperimentDurationMaximum >> 0) & 0xFF); + mInfoMemBytes[infoMemMap.idxMaxExpLengthMsb] = (byte) ((mExperimentDurationMaximum >> 8) & 0xFF); + } + + if(generateForWritingToShimmer) { + // MAC address - set to all 0xFF (i.e. invalid MAC) so that Firmware will know to check for MAC from Bluetooth transceiver + // (already set to 0xFF at start of method but just incase) + System.arraycopy(infoMemMap.invalidMacId, 0, mInfoMemBytes, infoMemMap.idxMacAddress, infoMemMap.lengthMacIdBytes); + + //TODO base below off mCalibFileCreationFlag and mCfgFileCreationFlag global variables? + + // Tells the Shimmer to create a new config file on undock/power cycle + mInfoMemBytes[infoMemMap.idxSDConfigDelayFlag] = (byte) (infoMemMap.maskSDCfgFileWriteFlag << infoMemMap.bitShiftSDCfgFileWriteFlag); + + //TODO decide what to do about calibration info + //mInfoMemBytes[infoMemMap.idxSDConfigDelayFlag] = (byte) (infoMemMap.maskSDCalibFileWriteFlag << infoMemMap.bitShiftSDCalibFileWriteFlag); + } + // InfoMem C - End + + if(mFirmwareIdentifier==FW_ID.SHIMMER3.SDLOG) { + // InfoMem B Start -> Slave MAC ID for Multi-Shimmer Syncronisation + for (int i = 0; i < infoMemMap.maxNumOfExperimentNodes; i++) { // Limit of 21 nodes + byte[] macIdArray; + if((syncNodesList.size()>0) && (i0)) { + macIdArray = Util.hexStringToByteArray(syncNodesList.get(i)); + } + else { + macIdArray = infoMemMap.invalidMacId; + } + System.arraycopy(macIdArray, 0, mInfoMemBytes, infoMemMap.idxNode0 + (i*infoMemMap.lengthMacIdBytes), infoMemMap.lengthMacIdBytes); + } + // InfoMem B End + } + } + return mInfoMemBytes; + } + + + /** + * Creates an empty byte array for the purposes of generating the + * configuration bytes to write to the Shimmer (default all bytes = 0xFF). + * + * @param size the size of the byte array to create. + * @return byte array + */ + public byte[] createEmptyInfoMemByteArray(int size) { + byte[] newArray = new byte[size]; + for(byte b:newArray) { + b = (byte)0xFF; + } + return newArray; + } + + /** + * Parses the LSM303DLHC Accel calibration variables from a byte array stored + * in the Shimmer's infomem or in the SD header of logged data files. + * + * @param bufferCalibrationParameters + * the byte array containing the LSM303DLHC Accel calibration + */ + public void parseCalParamLSM303DLHCAccel(byte[] bufferCalibrationParameters){ + String[] dataType={"i16","i16","i16","i16","i16","i16","i8","i8","i8","i8","i8","i8","i8","i8","i8"}; + int[] formattedPacket = formatdatapacketreverse(bufferCalibrationParameters,dataType); + double[] AM=new double[9]; + for (int i=0;i<9;i++) + { + AM[i]=((double)formattedPacket[6+i])/100; + } + double[][] alignmentMatrixDA = {{AM[0],AM[1],AM[2]},{AM[3],AM[4],AM[5]},{AM[6],AM[7],AM[8]}}; + double[][] sensitivityMatrixDA = {{formattedPacket[3],0,0},{0,formattedPacket[4],0},{0,0,formattedPacket[5]}}; + double[][] offsetVectorDA = {{formattedPacket[0]},{formattedPacket[1]},{formattedPacket[2]}}; + mAlignmentMatrixWRAccel = alignmentMatrixDA; + mSensitivityMatrixWRAccel = sensitivityMatrixDA; + mOffsetVectorWRAccel = offsetVectorDA; + } + + /** + * Converts the LSM303DLHC Accel calibration variables from Shimmer Object + * into a byte array for sending to the Shimmer. + * + * @return the bytes array containing the LSM303DLHC Accel calibration + */ + public byte[] generateCalParamLSM303DLHCAccel(){ + byte[] bufferCalibrationParameters = new byte[21]; + // offsetVector -> buffer offset = 0 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[0+(i*2)] = (byte) ((((int)mOffsetVectorWRAccel[i][0]) >> 0) & 0xFF); + bufferCalibrationParameters[0+(i*2)+1] = (byte) ((((int)mOffsetVectorWRAccel[i][0]) >> 8) & 0xFF); + } + // sensitivityMatrix -> buffer offset = 6 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[6+(i*2)] = (byte) ((((int)mSensitivityMatrixWRAccel[i][i]) >> 0) & 0xFF); + bufferCalibrationParameters[6+(i*2)+1] = (byte) ((((int)mSensitivityMatrixWRAccel[i][i]) >> 8) & 0xFF); + } + // alignmentMatrix -> buffer offset = 12 + for (int i=0; i<3; i++) { + bufferCalibrationParameters[12+(i*3)] = (byte) (((int)(mAlignmentMatrixWRAccel[i][0]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+1] = (byte) (((int)(mAlignmentMatrixWRAccel[i][1]*100)) & 0xFF); + bufferCalibrationParameters[12+(i*3)+2] = (byte) (((int)(mAlignmentMatrixWRAccel[i][2]*100)) & 0xFF); + } + return bufferCalibrationParameters; + } + + /** + * This method is used as the basis for configuring a Shimmer through the + * Consensys application. All sensor and configuration information is stored + * in dynamically created and controlled Maps. + * + * Should only be used after the Shimmer HW and FW version information is + * set + */ + public void sensorAndConfigMapsCreate() { + + mSensorMap = new TreeMap(); + mSensorTileMap = new LinkedHashMap(); + mConfigOptionsMap = new HashMap(); + + if (mHardwareVersion != -1){ + if (mHardwareVersion == HW_ID.SHIMMER_2R){ + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.ACCEL, new SensorDetails(false, 0x80, 0, "Accelerometer")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.GYRO, new SensorDetails(false, 0x40, 0, "Gyroscope")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.MAG, new SensorDetails(false, 0x20, 0, "Magnetometer")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.EMG, new SensorDetails(false, 0x08, 0, "EMG")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.ECG, new SensorDetails(false, 0x10, 0, "ECG")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.GSR, new SensorDetails(false, 0x04, 0, "GSR")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A7, new SensorDetails(false, 0x02, 0, "Exp Board A7")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A0, new SensorDetails(false, 0x01, 0, "Exp Board A0")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.EXP_BOARD, new SensorDetails(false, 0x02|0x01, 0, "Exp Board")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP, new SensorDetails(false, 0x8000, 0, "Bridge Amplifier")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.HEART, new SensorDetails(false, 0x4000, 0, "Heart Rate")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.BATT, new SensorDetails(false, 0x2000, 0, "Battery Voltage")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.EXT_ADC_A15, new SensorDetails(false, 0x0800, 0, "External ADC A15")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.INT_ADC_A1, new SensorDetails(false, 0x0400, 0, "Internal ADC A1")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.INT_ADC_A12, new SensorDetails(false, 0x0200, 0, "Internal ADC A12")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.INT_ADC_A13, new SensorDetails(false, 0x0100, 0, "Internal ADC A13")); + mSensorMap.put(Configuration.Shimmer2.SensorMapKey.INT_ADC_A14, new SensorDetails(false, 0x800000, 0, "Internal ADC A14")); + + // Conflicting Channels + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.GYRO).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.ECG, + Configuration.Shimmer2.SensorMapKey.EMG, + Configuration.Shimmer2.SensorMapKey.GSR, + Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.MAG).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.ECG, + Configuration.Shimmer2.SensorMapKey.EMG, + Configuration.Shimmer2.SensorMapKey.GSR, + Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.EMG).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.GSR, + Configuration.Shimmer2.SensorMapKey.ECG, + Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer2.SensorMapKey.GYRO, + Configuration.Shimmer2.SensorMapKey.MAG); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.ECG).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.GSR, + Configuration.Shimmer2.SensorMapKey.EMG, + Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer2.SensorMapKey.GYRO, + Configuration.Shimmer2.SensorMapKey.MAG); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.GSR).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.ECG, + Configuration.Shimmer2.SensorMapKey.EMG, + Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer2.SensorMapKey.GYRO, + Configuration.Shimmer2.SensorMapKey.MAG); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A7).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.HEART, + Configuration.Shimmer2.SensorMapKey.BATT); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A0).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.HEART, + Configuration.Shimmer2.SensorMapKey.BATT); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.BRIDGE_AMP).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.ECG, + Configuration.Shimmer2.SensorMapKey.EMG, + Configuration.Shimmer2.SensorMapKey.GSR, + Configuration.Shimmer2.SensorMapKey.GYRO, + Configuration.Shimmer2.SensorMapKey.MAG); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.HEART).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A0, + Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A7); + mSensorMap.get(Configuration.Shimmer2.SensorMapKey.BATT).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A0, + Configuration.Shimmer2.SensorMapKey.EXP_BOARD_A7); + + } + else if (mHardwareVersion == HW_ID.SHIMMER_3) { + InfoMemLayout infoMemMap = new InfoMemLayout(mFirmwareIdentifier, mFirmwareVersionMajor, mFirmwareVersionMinor, mFirmwareVersionInternal); + + // These can be used to enable/disble GUI options depending on what HW, FW, Expansion boards versions are present + ShimmerVerObject baseAnyIntExpBoardAndFw = new ShimmerVerObject(HW_ID.SHIMMER_3,ANY_VERSION,ANY_VERSION,ANY_VERSION,ANY_VERSION,ANY_VERSION); + ShimmerVerObject baseAnyIntExpBoardAndSdlog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,ANY_VERSION,ANY_VERSION,ANY_VERSION,ANY_VERSION); + ShimmerVerObject baseAnyIntExpBoardAndBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,ANY_VERSION,ANY_VERSION,ANY_VERSION,ANY_VERSION); + ShimmerVerObject baseAnyIntExpBoardAndLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,ANY_VERSION,ANY_VERSION,ANY_VERSION,ANY_VERSION); + + ShimmerVerObject baseNoIntExpBoardSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,ShimmerVerDetails.EXP_BRD_NONE_ID); + + ShimmerVerObject baseSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,ANY_VERSION); + ShimmerVerObject baseBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,ANY_VERSION); + ShimmerVerObject baseLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,ANY_VERSION); + + ShimmerVerObject baseExgSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_EXG); + ShimmerVerObject baseExgUnifiedSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED); + ShimmerVerObject baseExgBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_EXG); + ShimmerVerObject baseExgUnifiedBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED); + ShimmerVerObject baseExgLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_EXG); + ShimmerVerObject baseExgUnifiedLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED); + + ShimmerVerObject baseGsrSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_GSR); + ShimmerVerObject baseGsrUnifiedSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_GSR_UNIFIED); + ShimmerVerObject baseGsrBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_GSR); + ShimmerVerObject baseGsrUnifiedBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_GSR_UNIFIED); + ShimmerVerObject baseGsrLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_GSR); + ShimmerVerObject baseGsrUnifiedLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_GSR_UNIFIED); + ShimmerVerObject baseGsrGq = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.GQ_GSR,ANY_VERSION,ANY_VERSION,ANY_VERSION,HW_ID_SR_CODES.EXP_BRD_GSR); + ShimmerVerObject baseGsrUnifiedGq = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.GQ_GSR,ANY_VERSION,ANY_VERSION,ANY_VERSION,HW_ID_SR_CODES.EXP_BRD_GSR_UNIFIED); + + ShimmerVerObject baseBrAmpSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_BR_AMP); + ShimmerVerObject baseBrAmpUnifiedSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_BR_AMP_UNIFIED); + ShimmerVerObject baseBrAmpBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_BR_AMP); + ShimmerVerObject baseBrAmpUnifiedBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_BR_AMP_UNIFIED); + ShimmerVerObject baseBrAmpLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_BR_AMP); + ShimmerVerObject baseBrAmpUnifiedLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_BR_AMP_UNIFIED); + + ShimmerVerObject baseProto3MiniSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_PROTO3_MINI); + ShimmerVerObject baseProto3MiniBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_PROTO3_MINI); + ShimmerVerObject baseProto3MiniLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_PROTO3_MINI); + + ShimmerVerObject baseProto3DeluxeSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_PROTO3_DELUXE); + ShimmerVerObject baseProto3DeluxeBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_PROTO3_DELUXE); + ShimmerVerObject baseProto3DeluxeLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_PROTO3_DELUXE); + + ShimmerVerObject baseHighGAccelSdLog = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.SDLOG,0,8,0,HW_ID_SR_CODES.EXP_BRD_HIGH_G_ACCEL); + ShimmerVerObject baseHighGAccelBtStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.BTSTREAM,0,5,0,HW_ID_SR_CODES.EXP_BRD_HIGH_G_ACCEL); + ShimmerVerObject baseHighGAccelLogAndStream = new ShimmerVerObject(HW_ID.SHIMMER_3,FW_ID.SHIMMER3.LOGANDSTREAM,0,3,3,HW_ID_SR_CODES.EXP_BRD_HIGH_G_ACCEL); + + List listOfCompatibleVersionInfoExg = Arrays.asList( + baseExgSdLog, baseExgBtStream, baseExgLogAndStream, + baseExgUnifiedSdLog, baseExgUnifiedBtStream, baseExgUnifiedLogAndStream); + + List listOfCompatibleVersionInfoSdLog = Arrays.asList(baseSdLog); + List listOfCompatibleVersionInfoAnyExpBoardAndFw = Arrays.asList(baseAnyIntExpBoardAndFw); + List listOfCompatibleVersionInfoAnyExpBoardStandardFW = Arrays.asList( + baseAnyIntExpBoardAndSdlog,baseAnyIntExpBoardAndBtStream,baseAnyIntExpBoardAndLogAndStream); + + List listOfCompatibleVersionInfoGsr = Arrays.asList( + baseGsrSdLog, baseGsrBtStream, baseGsrLogAndStream, baseGsrGq, + baseGsrUnifiedSdLog, baseGsrUnifiedBtStream, baseGsrUnifiedLogAndStream, baseGsrUnifiedGq); + + List listOfCompatibleVersionInfoBrAmp = Arrays.asList( + baseBrAmpSdLog, baseBrAmpBtStream, baseBrAmpLogAndStream, + baseBrAmpUnifiedSdLog, baseBrAmpUnifiedBtStream, baseBrAmpUnifiedLogAndStream); + + List listOfCompatibleVersionInfoProto3Mini = Arrays.asList( + baseProto3MiniSdLog, baseProto3MiniBtStream, baseProto3MiniLogAndStream); + + List listOfCompatibleVersionInfoProto3Deluxe = Arrays.asList( + baseProto3DeluxeSdLog, baseProto3DeluxeBtStream, baseProto3DeluxeLogAndStream); + + List listOfCompatibleVersionInfoIntExpA1 = Arrays.asList( + baseProto3MiniSdLog, baseProto3MiniBtStream, baseProto3MiniLogAndStream, + baseProto3DeluxeSdLog, baseProto3DeluxeBtStream, baseProto3DeluxeLogAndStream, + baseHighGAccelSdLog, baseHighGAccelBtStream, baseHighGAccelLogAndStream); + + List listOfCompatibleVersionInfoIntExpA12 = Arrays.asList( + baseProto3MiniSdLog, baseProto3MiniBtStream, baseProto3MiniLogAndStream, + baseProto3DeluxeSdLog, baseProto3DeluxeBtStream, baseProto3DeluxeLogAndStream, + baseGsrSdLog, baseGsrBtStream, baseGsrLogAndStream, + baseGsrUnifiedSdLog, baseGsrUnifiedBtStream, baseGsrUnifiedLogAndStream, + baseHighGAccelSdLog, baseHighGAccelBtStream, baseHighGAccelLogAndStream); + + List listOfCompatibleVersionInfoIntExpA13 = Arrays.asList( + baseProto3MiniSdLog, baseProto3MiniBtStream, baseProto3MiniLogAndStream, + baseProto3DeluxeSdLog, baseProto3DeluxeBtStream, baseProto3DeluxeLogAndStream, + baseHighGAccelSdLog, baseHighGAccelBtStream, baseHighGAccelLogAndStream, + baseGsrSdLog, baseGsrBtStream, baseGsrLogAndStream, + baseGsrUnifiedSdLog, baseGsrUnifiedBtStream, baseGsrUnifiedLogAndStream + ); + + List listOfCompatibleVersionInfoIntExpA14 = Arrays.asList( + baseProto3MiniSdLog, baseProto3MiniBtStream, baseProto3MiniLogAndStream, + baseProto3DeluxeSdLog, baseProto3DeluxeBtStream, baseProto3DeluxeLogAndStream, + baseHighGAccelSdLog, baseHighGAccelBtStream, baseHighGAccelLogAndStream + ); + + List listOfCompatibleVersionInfoStreaming = Arrays.asList( + baseBtStream, baseLogAndStream); + + List listOfCompatibleVersionInfoLogging = Arrays.asList( + baseSdLog, baseLogAndStream); + + List listOfCompatibleVersionInfoRespiration = Arrays.asList( + baseExgUnifiedSdLog, baseExgUnifiedBtStream, baseExgUnifiedLogAndStream); + + List listOfCompatibleVersionInfoHighGAccel = Arrays.asList( + baseHighGAccelSdLog,baseHighGAccelBtStream,baseHighGAccelLogAndStream); + + + // Assemble the channel map + // NV_SENSORS0 + long streamingByteIndex = 0; + long logHeaderByteIndex = 0; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.A_ACCEL, new SensorDetails(false, 0x80<<(streamingByteIndex*8), 0x80<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.ACCEL_LN)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO, new SensorDetails(false, 0x40<<(streamingByteIndex*8), 0x40<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.GYRO)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG, new SensorDetails(false, 0x20<<(streamingByteIndex*8), 0x20<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MAG)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, new SensorDetails(false, 0x10<<(streamingByteIndex*8), 0x10<<(logHeaderByteIndex*8), Configuration.Shimmer3.GuiLabelSensors.EXG1_24BIT)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, new SensorDetails(false, 0x08<<(streamingByteIndex*8), 0x08<<(logHeaderByteIndex*8), Configuration.Shimmer3.GuiLabelSensors.EXG2_24BIT)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.GSR, new SensorDetails(false, 0x04<<(streamingByteIndex*8), 0x04<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.GSR)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A7, new SensorDetails(false, 0x02<<(streamingByteIndex*8), 0x02<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.EXT_EXP_A7)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A6, new SensorDetails(false, 0x01<<(streamingByteIndex*8), 0x01<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.EXT_EXP_A6)); + + // NV_SENSORS1 + streamingByteIndex = 1; + logHeaderByteIndex = 1; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, new SensorDetails(false, 0x80<<(streamingByteIndex*8), 0x80<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.BRIDGE_AMPLIFIER)); + //shimmerChannels.put(, new ChannelDetails(false, 0x40<<(streamingByteIndex*8), 0x40<<(logHeaderByteIndex*8), "")); // unused? - new PPG bit might be here now + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.VBATT, new SensorDetails(false, 0x20<<(streamingByteIndex*8), 0x20<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.BATTERY)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL, new SensorDetails(false, 0x10<<(streamingByteIndex*8), 0x10<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.ACCEL_WR)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A15, new SensorDetails(false, 0x08<<(streamingByteIndex*8), 0x08<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.EXT_EXP_A15)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, new SensorDetails(false, 0x04<<(streamingByteIndex*8), 0x04<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.INT_EXP_A1)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, new SensorDetails(false, 0x02<<(streamingByteIndex*8), 0x02<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.INT_EXP_A12)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, new SensorDetails(false, 0x01<<(streamingByteIndex*8), 0x01<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.INT_EXP_A13)); + + // NV_SENSORS2 + streamingByteIndex = 2; + logHeaderByteIndex = 2; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, new SensorDetails(false, 0x80<<(streamingByteIndex*8), 0x80<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.INT_EXP_A14)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_ACCEL, new SensorDetails(false, 0x40<<(streamingByteIndex*8), 0x40<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.ACCEL_MPU)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MAG, new SensorDetails(false, 0x20<<(streamingByteIndex*8), 0x20<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MAG_MPU)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, new SensorDetails(false, 0x10<<(streamingByteIndex*8), 0x10<<(logHeaderByteIndex*8), Configuration.Shimmer3.GuiLabelSensors.EXG1_16BIT)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, new SensorDetails(false, 0x08<<(streamingByteIndex*8), 0x08<<(logHeaderByteIndex*8), Configuration.Shimmer3.GuiLabelSensors.EXG2_16BIT)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE, new SensorDetails(false, 0x04<<(streamingByteIndex*8), 0x04<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.PRESS_TEMP_BMP180)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_TEMP, new SensorDetails(false, 0x20<<(streamingByteIndex*8), 0x20<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MPL_TEMPERATURE)); + //shimmerChannels.put(SENSOR_SHIMMER3_MSP430_TEMPERATURE, new ChannelDetails(false, 0x01<<(btStreamByteIndex*8), 0x01<<(sDHeaderByteIndex*8), "")); // not yet implemented + //shimmerChannels.put(SENSOR_SHIMMER3_LSM303DLHC_TEMPERATURE, new ChannelDetails(false, 0x01<<(btStreamByteIndex*8), 0x01<<(sDHeaderByteIndex*8), "")); // not yet implemented + + // NV_SENSORS3 + streamingByteIndex = 3; + logHeaderByteIndex = 3; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF, new SensorDetails(false, (long)0, (long)0x80<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.QUAT_MPL_6DOF)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF, new SensorDetails(false, (long)0, (long)0x40<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.QUAT_MPL_9DOF)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF, new SensorDetails(false, (long)0, (long)0x20<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.EULER_ANGLES_6DOF)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF, new SensorDetails(false, (long)0, (long)0x10<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.EULER_ANGLES_9DOF)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_HEADING, new SensorDetails(false, (long)0, (long)0x08<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MPL_HEADING)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER, new SensorDetails(false, (long)0, (long)0x04<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MPL_PEDOM_CNT)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_TAP, new SensorDetails(false, (long)0, (long)0x02<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MPL_TAPDIRANDTAPCNT)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MOTION_ORIENT, new SensorDetails(false, (long)0, (long)0x01<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MPL_MOTIONANDORIENT)); + + // NV_SENSORS4 + streamingByteIndex = 4; + logHeaderByteIndex = 4; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_GYRO, new SensorDetails(false, (long)0, (long)0x80<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.GYRO_MPU_MPL)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_ACCEL, new SensorDetails(false, (long)0, (long)0x40<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.ACCEL_MPU_MPL)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG, new SensorDetails(false, (long)0, (long)0x20<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.MAG_MPU_MPL)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW, new SensorDetails(false, (long)0, (long)0x10<<(logHeaderByteIndex*8), Shimmer3.GuiLabelSensors.QUAT_DMP_6DOF)); + //shimmerChannels.put(, new ChannelDetails(false, 0, 0x08<<(loggingHeaderByteIndex*8), "")); // unused + //shimmerChannels.put(, new ChannelDetails(false, 0, 0x04<<(loggingHeaderByteIndex*8), "")); // unused + //shimmerChannels.put(, new ChannelDetails(false, 0, 0x02<<(loggingHeaderByteIndex*8), "")); // unused + //shimmerChannels.put(, new ChannelDetails(false, 0, 0x01<<(loggingHeaderByteIndex*8), "")); // unused + + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.ECG, new SensorDetails(false, 0, 0, Shimmer3.GuiLabelSensors.ECG)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXG_TEST, new SensorDetails(false, 0, 0, Shimmer3.GuiLabelSensors.EXG_TEST)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.EXG_RESPIRATION)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.EMG, new SensorDetails(false, 0, 0, Shimmer3.GuiLabelSensors.EMG)); + + // Derived Channels - Bridge Amp Board + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, new SensorDetails(false, 0, 0, Shimmer3.GuiLabelSensors.RESISTANCE_AMP)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelResAmp; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE, new SensorDetails(false, 0, 0, Shimmer3.GuiLabelSensors.SKIN_TEMP_PROBE)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelSkinTemp; + + // Derived Channels - GSR Board + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG_DUMMY, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG_DUMMY)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG_A12, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG_A12)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelPpg_ADC12ADC13; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG_A13, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG_A13)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelPpg_ADC12ADC13; + + // Derived Channels - Proto3 Board + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG1_DUMMY)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG1_A12, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG1_A12)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelPpg1_ADC12ADC13; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG1_A13, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG1_A13)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelPpg1_ADC12ADC13; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG2_DUMMY)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG2_A1, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG2_A1)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelPpg2_ADC1ADC14; + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG2_A14, new SensorDetails(false, 0, 0, Configuration.Shimmer3.GuiLabelSensors.PPG2_A14)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mSensorBitmapIDStreaming = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mSensorBitmapIDStreaming; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mSensorBitmapIDSDLogHeader = mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mSensorBitmapIDSDLogHeader; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mDerivedSensorBitmapID = infoMemMap.maskDerivedChannelPpg2_ADC1ADC14; + + + // Now that channel map is assembled we can add compatiblity + // information, internal expansion board power requirements, + // associated required channels, conflicting channels and + // associated configuration options. + + // Channels that have compatibility considerations (used to auto-hide/disable channels/config options in GUI) + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGsr; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoBrAmp; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoIntExpA1; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoIntExpA12; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoIntExpA13; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_DUMMY).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGsr; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGsr; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGsr; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoIntExpA14; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_TEMP).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_HEADING).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_TAP).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MOTION_ORIENT).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_GYRO).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoSdLog; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoRespiration; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoBrAmp; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoBrAmp; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.A_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A6).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A7).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A15).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + + // Channels that require Internal Expansion board power (automatically enabled internal expansion board power when each Channel is enabled) + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIntExpBoardPowerRequired = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIntExpBoardPowerRequired = true; + + // Required Channels - these get auto enabled/disabled when the parent channel is enabled/disabled + //mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mListOfSensorMapKeysRequired = Arrays.asList( + // Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1); + //mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mListOfSensorMapKeysRequired = Arrays.asList( + // Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1); + + // Conflicting Channels (stop two conflicting channels from being enabled and the same time) + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG2_A1, + Configuration.Shimmer3.SensorMapKey.PPG2_A14, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.PPG_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG_A12, + Configuration.Shimmer3.SensorMapKey.PPG_A13, + Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG1_A12, + Configuration.Shimmer3.SensorMapKey.PPG1_A13, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.PPG_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG_A12, + Configuration.Shimmer3.SensorMapKey.PPG_A13, + Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG1_A12, + Configuration.Shimmer3.SensorMapKey.PPG1_A13, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG2_A1, + Configuration.Shimmer3.SensorMapKey.PPG2_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST); + + //The A12 and A13 based PPG channels have the same channel exceptions as GSR with the addition of their counterpart channel + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mListOfSensorMapKeysConflicting = new ArrayList(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfSensorMapKeysConflicting); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mListOfSensorMapKeysConflicting.add(Configuration.Shimmer3.SensorMapKey.PPG_A13); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mListOfSensorMapKeysConflicting.add(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mListOfSensorMapKeysConflicting.add(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mListOfSensorMapKeysConflicting = new ArrayList(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfSensorMapKeysConflicting); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mListOfSensorMapKeysConflicting.add(Configuration.Shimmer3.SensorMapKey.PPG_A12); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mListOfSensorMapKeysConflicting.add(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mListOfSensorMapKeysConflicting.add(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.PPG1_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.PPG1_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.PPG2_A14, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mListOfSensorMapKeysConflicting = Arrays.asList( + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION, + Configuration.Shimmer3.SensorMapKey.EXG1_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_16BIT, + Configuration.Shimmer3.SensorMapKey.EXG1_24BIT, + Configuration.Shimmer3.SensorMapKey.EXG2_24BIT, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP, + Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.PPG2_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14); + + // Associated config options for each channel (currently used for the ChannelTileMap) + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RANGE, + Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RANGE, + Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RATE); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RANGE, + Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RATE); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.PRESSURE_RESOLUTION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.GSR_RANGE); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION, + Configuration.Shimmer3.GuiLabelConfig.EXG_REFERENCE_ELECTRODE, + Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_DETECTION, + Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_CURRENT, + Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_COMPARATOR, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_FREQ, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_PHASE); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION, + Configuration.Shimmer3.GuiLabelConfig.EXG_REFERENCE_ELECTRODE, + Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_DETECTION, + Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_CURRENT, + Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_COMPARATOR); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_FREQ, + Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_PHASE); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_DUMMY).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.PPG_ADC_SELECTION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.PPG1_ADC_SELECTION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.PPG2_ADC_SELECTION); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER); + + + //Sensor Grouping for Configuration Panel 'tile' generation. + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.LOW_NOISE_ACCEL, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.A_ACCEL))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.WIDE_RANGE_ACCEL, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.GYRO, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.MAG, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.PRESSURE_TEMPERATURE, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.BATTERY_MONITORING, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.VBATT))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.EXTERNAL_EXPANSION_ADC, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A6, + Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A7, + Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A15))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.GSR, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.PPG_DUMMY))); +// Configuration.Shimmer3.SensorMapKey.PPG_A12, +// Configuration.Shimmer3.SensorMapKey.PPG_A13))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.EXG, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.ECG, + Configuration.Shimmer3.SensorMapKey.EMG, + Configuration.Shimmer3.SensorMapKey.EXG_TEST, + Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.PROTO3_MINI, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.PROTO3_DELUXE, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.PROTO3_DELUXE_SUPP, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY, + Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.BRIDGE_AMPLIFIER, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP, + Configuration.Shimmer3.SensorMapKey.RESISTANCE_AMP))); + //mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.BRIDGE_AMPLIFIER_SUPP, new SensorTileDetails( + // Arrays.asList(Configuration.Shimmer3.SensorMapKey.SKIN_TEMP_PROBE))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.HIGH_G_ACCEL, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, //X-axis + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, //Y-axis + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14, //Z-axis + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1))); //unused but accessible + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.INTERNAL_EXPANSION_ADC, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13, + Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14))); + //mChannelTileMap.put(Configuration.Shimmer3.GUI_LABEL_CHANNELTILE_9DOF, new ChannelTileDetails( + // Arrays.asList(Configuration.Shimmer3.SensorMapKey.A_ACCEL, + // Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL, + // Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO, + // Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG))); + //Not implemented: GUI_LABEL_CHANNEL_GROUPING_GPS + + // ChannelTiles that have compatibility considerations (used to auto generate tiles in GUI) + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.LOW_NOISE_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.GYRO).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.MAG).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.BATTERY_MONITORING).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardAndFw; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.WIDE_RANGE_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardAndFw; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.PRESSURE_TEMPERATURE).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.EXTERNAL_EXPANSION_ADC).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoAnyExpBoardStandardFW; + //mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.INTERNAL_EXPANSION_ADC).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGsr; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.GSR).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGsr; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.EXG).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoExg; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.PROTO3_MINI).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Mini; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.PROTO3_DELUXE).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.PROTO3_DELUXE_SUPP).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoProto3Deluxe; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.BRIDGE_AMPLIFIER).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoBrAmp; + //mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.BRIDGE_AMPLIFIER_SUPP).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoBrAmp; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.HIGH_G_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoHighGAccel; + //mShimmerChannelGroupingMap.get(Configuration.Shimmer3.GUI_LABEL_CHANNEL_GROUPING_GPS).mCompatibleVersionInfo = listOfCompatibleVersionInfoGps; + + // For loop to automatically inherit associated channel configuration options from mSensorMap in the mSensorTileMap + for (String channelGroup : mSensorTileMap.keySet()) { + // Ok to clear here because variable is initiated in the class + mSensorTileMap.get(channelGroup).mListOfConfigOptionKeysAssociated.clear(); + for (Integer channel : mSensorTileMap.get(channelGroup).mListOfSensorMapKeysAssociated) { + List associatedConfigOptions = mSensorMap.get(channel).mListOfConfigOptionKeysAssociated; + if (associatedConfigOptions != null) { + for (String configOption : associatedConfigOptions) { + // do not add duplicates + if (!(mSensorTileMap.get(channelGroup).mListOfConfigOptionKeysAssociated.contains(configOption))) { + mSensorTileMap.get(channelGroup).mListOfConfigOptionKeysAssociated.add(configOption); + } + } + } + } + } + + + // Assemble the channel configuration options map + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_USER_ASSIGNED_NAME, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoLogging)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_SAMPLING_RATE, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_MAC_FROM_INFOMEM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.BUFFER_SIZE, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.CONFIG_TIME, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoLogging)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_NAME, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoLogging)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_ID, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoLogging)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_NUMBER_OF_SHIMMERS, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_DURATION_ESTIMATED, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_DURATION_MAXIMUM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.BROADCAST_INTERVAL, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + new ArrayList(){})); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.BLUETOOTH_BAUD_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofBluetoothBaudRates, + Configuration.Shimmer3.ListofBluetoothBaudRatesConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoStreaming)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofAccelRange, + Configuration.Shimmer3.ListofLSM303DLHCAccelRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + if(mLowPowerAccelWR) { + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCAccelRateLpm, + Configuration.Shimmer3.ListofLSM303DLHCAccelRateLpmConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + } + else { + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCAccelRate, + Configuration.Shimmer3.ListofLSM303DLHCAccelRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + } + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofGyroRange, + Configuration.Shimmer3.ListofMPU9150GyroRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofMagRange, + Configuration.Shimmer3.ListofMagRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCMagRate, + Configuration.Shimmer3.ListofLSM303DLHCMagRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.PRESSURE_RESOLUTION, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofPressureResolution, + Configuration.Shimmer3.ListofPressureResolutionConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.GSR_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofGSRRange, + Configuration.Shimmer3.ListofGSRRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoGsr)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_GAIN, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGGain, + Configuration.Shimmer3.ListOfExGGainConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_RESOLUTION, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGResolutions, + Configuration.Shimmer3.ListOfExGResolutionsConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + + //Advanced ExG + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_REFERENCE_ELECTRODE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfECGReferenceElectrode, + Configuration.Shimmer3.ListOfECGReferenceElectrodeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + //TODO EMG vs. ECG vs. ExG Test vs. Respiration + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGRate, + Configuration.Shimmer3.ListOfExGRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_DETECTION, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGLeadOffDetection, + Configuration.Shimmer3.ListOfExGLeadOffDetectionConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_CURRENT, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGLeadOffCurrent, + Configuration.Shimmer3.ListOfExGLeadOffCurrentConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_LEAD_OFF_COMPARATOR, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGLeadOffComparator, + Configuration.Shimmer3.ListOfExGLeadOffComparatorConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoExg)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_FREQ, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGRespirationDetectFreq, + Configuration.Shimmer3.ListOfExGRespirationDetectFreqConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoRespiration)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXG_RESPIRATION_DETECT_PHASE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfExGRespirationDetectPhase32khz, + Configuration.Shimmer3.ListOfExGRespirationDetectPhase32khzConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoRespiration)); + + //MPL Options + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_ACCEL_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofMPU9150AccelRange, + Configuration.Shimmer3.ListofMPU9150AccelRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_DMP_GYRO_CAL, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofMPU9150MplCalibrationOptions, + Configuration.Shimmer3.ListofMPU9150MplCalibrationOptionsConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_LPF, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofMPU9150MplLpfOptions, + Configuration.Shimmer3.ListofMPU9150MplLpfOptionsConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofMPU9150MplRate, + Configuration.Shimmer3.ListofMPU9150MplRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MAG_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofMPU9150MagRate, + Configuration.Shimmer3.ListofMPU9150MagRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoSdLog)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfOnOff, + Configuration.Shimmer3.ListOfOnOffConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + + //MPL CheckBoxes + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_DMP, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL_9DOF_SENSOR_FUSION, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL_GYRO_CAL, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL_VECTOR_CAL, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_MPL_MAG_CAL, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + + //General Config + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_RATE, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD,listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.USER_BUTTON_START, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoLogging)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SINGLE_TOUCH_START, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_MASTER_SHIMMER, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_SYNC_WHEN_LOGGING, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.KINEMATIC_LPM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_LPM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.MPU9150_GYRO_LPM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_MAG_LPM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoAnyExpBoardStandardFW)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.TCX0, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoSdLog)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_BOOLEAN, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.PPG_ADC_SELECTION, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfPpgAdcSelection, + Configuration.Shimmer3.ListOfPpgAdcSelectionConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoGsr)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.PPG1_ADC_SELECTION, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfPpg1AdcSelection, + Configuration.Shimmer3.ListOfPpg1AdcSelectionConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoProto3Deluxe)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.PPG2_ADC_SELECTION, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfPpg2AdcSelection, + Configuration.Shimmer3.ListOfPpg2AdcSelectionConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoProto3Deluxe)); + + + // All Information required for parsing each of the channels + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.A_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_LN_X,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.A_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_LN_Y,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.A_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_LN_Z,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.VBATT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.BATTERY,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + + //ADC + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A7).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXT_EXP_A15,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A6).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXT_EXP_A6,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXT_EXP_ADC_A15).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXT_EXP_A15,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.INT_EXP_A1,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.INT_EXP_A12,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.INT_EXP_A13,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.INT_EXP_A14,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + + //Bridge Amp High + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_HIGH,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BRIDGE_AMP).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.BRIDGE_AMP_LOW,ChannelDataType.UINT12,2,ChannelDataEndian.LSB)); + + //GSR + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GSR,ChannelDataType.UINT16,2,ChannelDataEndian.LSB)); + + //GyroMPU + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GYRO_X,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GYRO_Y,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GYRO_Z,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_WR_X,ChannelDataType.INT16,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_WR_Y,ChannelDataType.INT16,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_WR_Z,ChannelDataType.INT16,2,ChannelDataEndian.LSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_X,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_Y,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_Z,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_X,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Y,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Z,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_MPU_X,ChannelDataType.INT16,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_MPU_Y,ChannelDataType.INT16,2,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_MPU_Z,ChannelDataType.INT16,2,ChannelDataEndian.LSB)); + + //bmp180 - pressure + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.PRESSURE_BMP180,ChannelDataType.UINT24,3,ChannelDataEndian.MSB)); + //bmp180 - temp + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.TEMPERATURE_BMP180,ChannelDataType.UINT16,2,ChannelDataEndian.MSB)); + + //exg + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG1_STATUS,ChannelDataType.UINT8,1,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG1_CH1_24BIT,ChannelDataType.INT24,3,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG1_CH2_24BIT,ChannelDataType.INT24,3,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG2_STATUS,ChannelDataType.UINT8,1,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG2_CH1_24BIT,ChannelDataType.INT24,3,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG2_CH2_24BIT,ChannelDataType.INT24,3,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG1_STATUS,ChannelDataType.UINT8,1,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG1_CH1_16BIT,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG1_CH2_16BIT,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG2_STATUS,ChannelDataType.UINT8,1,ChannelDataEndian.LSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG2_CH1_16BIT,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EXG2_CH2_16BIT,ChannelDataType.INT16,2,ChannelDataEndian.MSB)); + + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_W,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_6DOF_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_W,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_MPL_9DOF_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + //euler + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EULER_MPL_6DOF_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EULER_MPL_6DOF_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EULER_MPL_6DOF_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EULER_MPL_9DOF_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EULER_MPL_9DOF_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.EULER_MPL_9DOF_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + //heading + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_HEADING).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MPL_HEADING,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + //mpu temp + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_TEMP).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MPL_TEMPERATURE,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + //mpl pedom + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MPL_PEDOM_CNT,ChannelDataType.UINT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MPL_PEDOM_TIME,ChannelDataType.UINT32,4,ChannelDataEndian.MSB)); + + //mpl tap + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_TAP).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.TAPDIRANDTAPCNT,ChannelDataType.UINT8,1,ChannelDataEndian.MSB)); + + //mpl motion orient + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MOTION_ORIENT).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.TAPDIRANDTAPCNT,ChannelDataType.UINT8,1,ChannelDataEndian.MSB)); + + //mpl gyro cal + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_GYRO).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_GYRO).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_GYRO).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.GYRO_MPU_MPL_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + //mpl accel cal + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_ACCEL).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_MPU_MPL_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + //mpl mag cal + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.MAG_MPU_MPL_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + // Raw 6DOF quaterians from the DMP hardware module of the MPU9150 + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_W,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_X,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_Y,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW).mListOfChannels.add(new ChannelDetails(Configuration.Shimmer3.ObjectClusterSensorName.QUAT_DMP_6DOF_Z,ChannelDataType.INT32,4,ChannelDataEndian.MSB)); + + } + else if (mHardwareVersion == HW_ID.SHIMMER_GQ) { + + // These can be used to enable/disble GUI options depending on what HW, FW, Expansion boards versions are present + ShimmerVerObject baseAnyIntExpBoardAndFw = new ShimmerVerObject(HW_ID.SHIMMER_GQ,FW_ID.SHIMMER3.GQ_GSR,ANY_VERSION,ANY_VERSION,ANY_VERSION,ANY_VERSION); + List listOfCompatibleVersionInfoGq = Arrays.asList(baseAnyIntExpBoardAndFw); + + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.VBATT, new SensorDetails(false, Shimmer3.GuiLabelSensors.BATTERY)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL, new SensorDetails(false, Shimmer3.GuiLabelSensors.ACCEL_WR)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.GSR, new SensorDetails(false, Shimmer3.GuiLabelSensors.GSR)); + mSensorMap.put(Configuration.Shimmer3.SensorMapKey.PPG_A13, new SensorDetails(false, Shimmer3.GuiLabelSensors.PPG_A13)); + + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.VBATT).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGq; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGq; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGq; + + // Associated config options for each channel (currently used for the ChannelTileMap) + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.VBATT).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_VBATT); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_PPG); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RANGE, + Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_LSM303DLHC_ACCEL); + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mListOfConfigOptionKeysAssociated = Arrays.asList( + Configuration.Shimmer3.GuiLabelConfig.GSR_RANGE, + Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_GSR); + + //Sensor Grouping for Configuration Panel 'tile' generation. + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.BATTERY_MONITORING, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.VBATT))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.WIDE_RANGE_ACCEL, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL))); + mSensorTileMap.put(Configuration.Shimmer3.GuiLabelSensorTiles.GSR, new SensorTileDetails( + Arrays.asList(Configuration.Shimmer3.SensorMapKey.GSR, + Configuration.Shimmer3.SensorMapKey.PPG_A12))); + + // ChannelTiles that have compatibility considerations (used to auto generate tiles in GUI) + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.BATTERY_MONITORING).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGq; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.WIDE_RANGE_ACCEL).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGq; + mSensorTileMap.get(Configuration.Shimmer3.GuiLabelSensorTiles.GSR).mListOfCompatibleVersionInfo = listOfCompatibleVersionInfoGq; + + // For loop to automatically inherit associated channel configuration options from ChannelMap in the ChannelTileMap + for (String channelGroup : mSensorTileMap.keySet()) { + // Ok to clear here because variable is initiated in the class + mSensorTileMap.get(channelGroup).mListOfConfigOptionKeysAssociated.clear(); + for (Integer channel : mSensorTileMap.get(channelGroup).mListOfSensorMapKeysAssociated) { + if(mSensorMap.containsKey(channel)){ + List associatedConfigOptions = mSensorMap.get(channel).mListOfConfigOptionKeysAssociated; + if (associatedConfigOptions != null) { + for (String configOption : associatedConfigOptions) { + // do not add duplicates + if (!(mSensorTileMap.get(channelGroup).mListOfConfigOptionKeysAssociated.contains(configOption))) { + mSensorTileMap.get(channelGroup).mListOfConfigOptionKeysAssociated.add(configOption); + } + } + } + } + } + } + + // Assemble the channel configuration options map + mConfigOptionsMap = new HashMap(); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_USER_ASSIGNED_NAME, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoGq)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_SAMPLING_RATE, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SHIMMER_MAC_FROM_INFOMEM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.CONFIG_TIME, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoGq)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_NAME, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoGq)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.EXPERIMENT_ID, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.TEXTFIELD, + listOfCompatibleVersionInfoGq)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofAccelRange, + Configuration.Shimmer3.ListofLSM303DLHCAccelRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + if(mLowPowerAccelWR) { + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCAccelRateLpm, + Configuration.Shimmer3.ListofLSM303DLHCAccelRateLpmConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + } + else { + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_RATE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofLSM303DLHCAccelRate, + Configuration.Shimmer3.ListofLSM303DLHCAccelRateConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + } + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.GSR_RANGE, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListofGSRRange, + Configuration.Shimmer3.ListofGSRRangeConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX, + listOfCompatibleVersionInfoGq)); + + mConfigOptionsMap.put(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_GSR, + new SensorConfigOptionDetails(Configuration.Shimmer3Gq.ListofSamplingRateDividers, + Configuration.Shimmer3Gq.ListofSamplingRateDividersValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + mConfigOptionsMap.put(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_LSM303DLHC_ACCEL, + new SensorConfigOptionDetails(Configuration.Shimmer3Gq.ListofSamplingRateDividers, + Configuration.Shimmer3Gq.ListofSamplingRateDividersValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + mConfigOptionsMap.put(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_PPG, + new SensorConfigOptionDetails(Configuration.Shimmer3Gq.ListofSamplingRateDividers, + Configuration.Shimmer3Gq.ListofSamplingRateDividersValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + mConfigOptionsMap.put(Configuration.Shimmer3Gq.GuiLabelConfig.SAMPLING_RATE_DIVIDER_VBATT, + new SensorConfigOptionDetails(Configuration.Shimmer3Gq.ListofSamplingRateDividers, + Configuration.Shimmer3Gq.ListofSamplingRateDividersValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_INTEGER, + new SensorConfigOptionDetails(Configuration.Shimmer3.ListOfOnOff, + Configuration.Shimmer3.ListOfOnOffConfigValues, + SensorConfigOptionDetails.GUI_COMPONENT_TYPE.COMBOBOX)); + + //General Config + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.USER_BUTTON_START, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoGq)); + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.SINGLE_TOUCH_START, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX,listOfCompatibleVersionInfoGq)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.LSM303DLHC_ACCEL_LPM, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX)); + + mConfigOptionsMap.put(Configuration.Shimmer3.GuiLabelConfig.INT_EXP_BRD_POWER_BOOLEAN, + new SensorConfigOptionDetails(SensorConfigOptionDetails.GUI_COMPONENT_TYPE.CHECKBOX)); + } + } + } + + + /** + * Used to convert from the enabledSensors long variable read from the + * Shimmer to the set enabled status of the relative entries in the Sensor + * Map. Used in Consensys for dynamic GUI generation to configure a Shimmer. + * + */ + public void sensorMapUpdateWithEnabledSensors() { + + if((mEnabledSensors != 0) && (mSensorMap != null)) { + + if (mHardwareVersion == HW_ID.SHIMMER_3) { + + for(Integer sensorMapKey:mSensorMap.keySet()) { + boolean skipKey = false; + + // Skip if ExG channels here -> handle them after for loop. + if((sensorMapKey==Configuration.Shimmer3.SensorMapKey.ECG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EMG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_TEST) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION)) { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + skipKey = true; + } + // Handle derived sensors based on int adc channels (e.g. PPG vs. A12/A13) + else if(((sensorMapKey==Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14))){ + + //Check if a derived channel is enabled, if it is ignore disable and skip + innerloop: + for(Integer conflictKey:mSensorMap.get(sensorMapKey).mListOfSensorMapKeysConflicting) { + if(mSensorMap.get(conflictKey).isDerivedChannel()) { + if((mDerivedSensors&mSensorMap.get(conflictKey).mDerivedSensorBitmapID) == mSensorMap.get(conflictKey).mDerivedSensorBitmapID) { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + skipKey = true; + break innerloop; + } + } + } + } + + // Process remaining channels + if(!skipKey) { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + // Check if this sensor is a derived sensor + if(mSensorMap.get(sensorMapKey).isDerivedChannel()) { + //Check if all associated derived channels are enabled + if((mDerivedSensors&mSensorMap.get(sensorMapKey).mDerivedSensorBitmapID) == mSensorMap.get(sensorMapKey).mDerivedSensorBitmapID) { + //TODO comment + if((mEnabledSensors & mSensorMap.get(sensorMapKey).mSensorBitmapIDSDLogHeader) == mSensorMap.get(sensorMapKey).mSensorBitmapIDSDLogHeader) { + mSensorMap.get(sensorMapKey).mIsEnabled = true; + } + else { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + } + } + else { + //System.out.println("Derived Channel - " + mSensorMap.get(sensorMapKey).mLabel + " no associated required keys:"); + } + } + // This is not a derived sensor + else { + //Check if sensor's bit in sensor bitmap is enabled + if((mEnabledSensors & mSensorMap.get(sensorMapKey).mSensorBitmapIDSDLogHeader) == mSensorMap.get(sensorMapKey).mSensorBitmapIDSDLogHeader) { + mSensorMap.get(sensorMapKey).mIsEnabled = true; + } + } + } + } + + // Now that all main sensor channels have been parsed, deal with + // sensor channels that have special conditions. E.g. deciding + // what type of signal the ExG is configured for or what derived + // channel is enabled like whether PPG is on ADC12 or ADC13 + + //Handle ExG sensors + if((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled) + ||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIsEnabled) + ||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled) + ||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIsEnabled)) { + if(isEXGUsingDefaultRespirationConfiguration()) { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIsEnabled = true; + } + else if(isEXGUsingDefaultECGConfiguration()) { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIsEnabled = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIsEnabled = false; + } + else if(isEXGUsingDefaultEMGConfiguration()) { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIsEnabled = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIsEnabled = false; + } + else if(isEXGUsingDefaultTestSignalConfiguration()){ + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIsEnabled = true; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIsEnabled = false; + } + else { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIsEnabled = false; + } + } + + // Set the ExG resolution variable based on which channels are + // enabled in the sensor map + if((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled) + ||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIsEnabled)) { + mExGResolution = 0; + } + else if((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled) + ||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIsEnabled)) { + mExGResolution = 1; + } + + // Handle PPG sensors so that it appears in Consensys as a + // single PPG channel with a selectable ADC based on different + // hardware versions. + + //Used for Shimmer GSR hardware + if((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mIsEnabled)||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mIsEnabled)) { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_DUMMY).mIsEnabled = true; + if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A12).mIsEnabled) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG_A12, Configuration.Shimmer3.SensorMapKey.PPG_DUMMY); + mPpgAdcSelectionGsrBoard = Configuration.Shimmer3.ListOfPpgAdcSelectionConfigValues[1]; // PPG_A12 + } + else if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_A13).mIsEnabled) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG_A13, Configuration.Shimmer3.SensorMapKey.PPG_DUMMY); + mPpgAdcSelectionGsrBoard = Configuration.Shimmer3.ListOfPpgAdcSelectionConfigValues[0]; // PPG_A13 + } + } + else { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_DUMMY).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG_DUMMY).resetMapKeyLists(); + } + //Used for Shimmer Proto3 Deluxe hardware + if((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mIsEnabled)||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mIsEnabled)) { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY).mIsEnabled = true; + if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A12).mIsEnabled) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG1_A12, Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY); + mPpg1AdcSelectionProto3DeluxeBoard = Configuration.Shimmer3.ListOfPpg1AdcSelectionConfigValues[1]; // PPG1_A12 + } + else if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_A13).mIsEnabled) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG1_A13, Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY); + mPpg1AdcSelectionProto3DeluxeBoard = Configuration.Shimmer3.ListOfPpg1AdcSelectionConfigValues[0]; // PPG1_A13 + } + } + else { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY).resetMapKeyLists(); + } + //Used for Shimmer Proto3 Deluxe hardware + if((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mIsEnabled)||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mIsEnabled)) { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY).mIsEnabled = true; + if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A1).mIsEnabled) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG2_A1, Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY); + mPpg2AdcSelectionProto3DeluxeBoard = Configuration.Shimmer3.ListOfPpg2AdcSelectionConfigValues[0]; // PPG2_A1 + } + else if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_A14).mIsEnabled) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG2_A14, Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY); + mPpg2AdcSelectionProto3DeluxeBoard = Configuration.Shimmer3.ListOfPpg2AdcSelectionConfigValues[1]; // PPG2_A14 + } + } + else { + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY).mIsEnabled = false; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY).resetMapKeyLists(); + } + } + else if (mHardwareVersion == HW_ID.SHIMMER_GQ) { + + } + + } + } + + /** + * Used to changed the enabled state of a sensor in the sensormap. This is + * only used in Consensys for dynamic configuration of a Shimmer. This + * method deals with everything assciated with enabling a sensor such as: + * 1) dealing with conflicting sensors + * 2) dealing with other required sensors for the chosen sensor + * 3) determining whether expansion board power is required + * 4) setting default settings for disabled sensors + * 5) etc. + * + * @param sensorMapKey the sensormap key of the sensor to be enabled/disabled + * @param state the sensor state to set + * @return a boolean indicating if the sensors state was successfully changed + */ + public boolean setSensorEnabledState(int sensorMapKey, boolean state) { + + if(mSensorMap!=null) { + + if (mHardwareVersion == HW_ID.SHIMMER_3){ + + // Special case for Dummy entries in the Sensor Map + if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.PPG_DUMMY) { + mSensorMap.get(sensorMapKey).mIsEnabled = state; + if(Configuration.Shimmer3.ListOfPpgAdcSelection[mPpgAdcSelectionGsrBoard].contains("A12")) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG_A12, sensorMapKey); + sensorMapKey = Configuration.Shimmer3.SensorMapKey.PPG_A12; + } + else { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG_A13, sensorMapKey); + sensorMapKey = Configuration.Shimmer3.SensorMapKey.PPG_A13; + } + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.PPG1_DUMMY) { + mSensorMap.get(sensorMapKey).mIsEnabled = state; + if(Configuration.Shimmer3.ListOfPpg1AdcSelection[mPpg1AdcSelectionProto3DeluxeBoard].contains("A12")) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG1_A12, sensorMapKey); + sensorMapKey = Configuration.Shimmer3.SensorMapKey.PPG1_A12; + } + else { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG1_A13, sensorMapKey); + sensorMapKey = Configuration.Shimmer3.SensorMapKey.PPG1_A13; + } + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.PPG2_DUMMY) { + mSensorMap.get(sensorMapKey).mIsEnabled = state; + if(Configuration.Shimmer3.ListOfPpg2AdcSelection[mPpg2AdcSelectionProto3DeluxeBoard].contains("A14")) { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG2_A14, sensorMapKey); + sensorMapKey = Configuration.Shimmer3.SensorMapKey.PPG2_A14; + } + else { + copySensorMapSensorDetails(Configuration.Shimmer3.SensorMapKey.PPG2_A1, sensorMapKey); + sensorMapKey = Configuration.Shimmer3.SensorMapKey.PPG2_A1; + } + } + + // Automatically handle required channels for each sensor + if(mSensorMap.get(sensorMapKey).mListOfSensorMapKeysRequired != null) { + for(Integer i:mSensorMap.get(sensorMapKey).mListOfSensorMapKeysRequired) { + mSensorMap.get(i).mIsEnabled = state; + } + } + + // Unique cases for Shimmer3 ExG + if((sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG1_16BIT) + ||(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG2_16BIT)) { + mExGResolution = 0; + } + else if((sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG1_24BIT) + ||(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG2_24BIT)) { + mExGResolution = 1; + } + else if((sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION) + || (sensorMapKey == Configuration.Shimmer3.SensorMapKey.ECG) + || (sensorMapKey == Configuration.Shimmer3.SensorMapKey.EMG) + || (sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG_TEST)) { + + // If ExG sensor enabled, set default settings for that + // sensor. Otherwise set the default ECG configuration. + if(state) { + if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION) { + setDefaultRespirationConfiguration(); + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.ECG) { + setDefaultECGConfiguration(); + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EMG) { + setDefaultEMGConfiguration(); + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG_TEST) { + setEXGTestSignal(); + } + } + else { + setDefaultECGConfiguration(); + } + + if((sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION) + ||(sensorMapKey == Configuration.Shimmer3.SensorMapKey.ECG) + ||(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EXG_TEST)) { + if(mExGResolution == 0) {// 16-bit + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled = state; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIsEnabled = state; + } + else { // 24-bit + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled = state; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIsEnabled = state; + } + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.EMG) { + if(mExGResolution == 0) {// 16-bit + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled = state; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIsEnabled = false; + } + else { // 24-bit + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled = state; + mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIsEnabled = false; + } + } + + } + + } + else if (mHardwareVersion == HW_ID.SHIMMER_GQ) { + + } + + + //Set sensor state + mSensorMap.get(sensorMapKey).mIsEnabled = state; + + + + sensorMapConflictCheckandCorrect(sensorMapKey); + setDefaultConfigForSensor(sensorMapKey, mSensorMap.get(sensorMapKey).mIsEnabled); + + // Automatically control internal expansion board power + checkIfInternalExpBrdPowerIsNeeded(); + + if(mSensorMap.get(sensorMapKey).mIsEnabled == state) { + return true; + } + else { + return false; + } + + } + else { + return false; + } + } + + /** + * Method to set force defaults for disabled sensors. Need to ensure + * consistency across all configured Shimmers. Without the below, if a + * Shimmer is read from and then configured without changing any of the + * configuration, the configuration will not be checked. Another application + * could have saved incorrect configuration to the Shimmer. + * + */ + public void checkShimmerConfigurationBeforeConfiguring() { + + if (mHardwareVersion == HW_ID.SHIMMER_3){ + + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL).mIsEnabled) { + setDefaultLsm303dlhcAccelSensorConfig(false); + } + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG).mIsEnabled) { + setDefaultLsm303dlhcMagSensorConfig(false); + } + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO).mIsEnabled){ + setDefaultMpu9150GyroSensorConfig(false); + } + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_ACCEL).mIsEnabled){ + setDefaultMpu9150AccelSensorConfig(false); + } + + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE).mIsEnabled) { + setDefaultBmp180PressureSensorConfig(false); + } + if(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.GSR).mIsEnabled) { + setDefaultGsrSensorConfig(false); + } + if((!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.ECG).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_TEST).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EMG).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIsEnabled)) { +// if(!checkIfOtherExgChannelEnabled()) { + setDefaultECGConfiguration(); +// } + } + if((!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_HEADING).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_TAP).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MOTION_ORIENT).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG).mIsEnabled) + &&(!mSensorMap.get(Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW).mIsEnabled)) { +// if(!checkIfOtherMplChannelEnabled()) { + setDefaultMpu9150MplSensorConfig(false); +// } + } + + checkIfInternalExpBrdPowerIsNeeded(); + } + + } + + /**Automatically control internal expansion board power based on sensor map + * + */ + private void checkIfInternalExpBrdPowerIsNeeded(){ + + if (mHardwareVersion == HW_ID.SHIMMER_3){ + for(Integer channelKey:mSensorMap.keySet()) { + if(mSensorMap.get(channelKey).mIsEnabled && mSensorMap.get(channelKey).mIntExpBoardPowerRequired) { + mInternalExpPower = 1; + break; + } + else { + // Exception for Int ADC sensors + //TODO need to check HW version?? + if(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A1).mIsEnabled + ||mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A12).mIsEnabled + ||mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A13).mIsEnabled + ||mSensorMap.get(Configuration.Shimmer3.SensorMapKey.INT_EXP_ADC_A14).mIsEnabled){ + + } + else { + mInternalExpPower = 0; + } + } + } + } + } + + + private void copySensorMapSensorDetails(int keyFrom, int keyTo) { + if(mSensorMap!=null) { + if(mSensorMap.containsKey(keyFrom)&&mSensorMap.containsKey(keyTo)) { + mSensorMap.get(keyTo).mListOfCompatibleVersionInfo = mSensorMap.get(keyFrom).mListOfCompatibleVersionInfo; + mSensorMap.get(keyTo).mListOfSensorMapKeysRequired = mSensorMap.get(keyFrom).mListOfSensorMapKeysRequired; + mSensorMap.get(keyTo).mListOfSensorMapKeysConflicting = mSensorMap.get(keyFrom).mListOfSensorMapKeysConflicting; +// mSensorMap.get(keyTo).mIntExpBoardPowerRequired = mSensorMap.get(keyFrom).mIntExpBoardPowerRequired; + mSensorMap.get(keyTo).mListOfConfigOptionKeysAssociated = mSensorMap.get(keyFrom).mListOfConfigOptionKeysAssociated; + +// mSensorMap.get(keyTo).mSensorBitmapIDStreaming = mSensorMap.get(keyFrom).mSensorBitmapIDStreaming; +// mSensorMap.get(keyTo).mSensorBitmapIDSDLogHeader = mSensorMap.get(keyFrom).mSensorBitmapIDSDLogHeader; +// mSensorMap.get(keyTo).mDerivedChannelBitmapBitShift = mSensorMap.get(keyFrom).mDerivedChannelBitmapBitShift; +// mSensorMap.get(keyTo).mDerivedChannelBitmapMask = mSensorMap.get(keyFrom).mDerivedChannelBitmapMask; + } + } + } + + //TODO improve this method - was changed at the last minute and is not fully operational + public boolean checkIfVersionCompatible(List listOfCompatibleVersionInfo) { + if(listOfCompatibleVersionInfo == null) { + return true; + } + + for(ShimmerVerObject compatibleVersionInfo:listOfCompatibleVersionInfo) { + + boolean compatible = true; + + boolean checkHardwareVersion = false; + boolean checkExpansionBoardId = false; + boolean checkFirmwareIdentifier = false; + boolean checkFirmwareVersionMajor = false; + boolean checkFirmwareVersionMinor = false; + boolean checkFirmwareVersionInternal = false; + + if(compatibleVersionInfo.mHardwareVersion!=ANY_VERSION) { + checkHardwareVersion = true; + } + if(compatibleVersionInfo.mShimmerExpansionBoardId!=ANY_VERSION) { + checkExpansionBoardId = true; + } + if(compatibleVersionInfo.mFirmwareIdentifier!=ANY_VERSION) { + checkFirmwareIdentifier = true; + } + if(compatibleVersionInfo.mFirmwareVersionMajor!=ANY_VERSION) { + checkFirmwareVersionMajor = true; + } + if(compatibleVersionInfo.mFirmwareVersionMinor!=ANY_VERSION) { + checkFirmwareVersionMinor = true; + } + if(compatibleVersionInfo.mFirmwareVersionInternal!=ANY_VERSION) { + checkFirmwareVersionInternal = true; + } + + if((compatible)&&(checkHardwareVersion)) { + if(mHardwareVersion != compatibleVersionInfo.mHardwareVersion) { + compatible = false; + } + } + if((compatible)&&(checkExpansionBoardId)) { + if(mExpansionBoardId != compatibleVersionInfo.mShimmerExpansionBoardId) { + compatible = false; + } + } +// if((compatible)&&(checkFirmwareIdentifier)) { +// if(mFirmwareIdentifier != compatibleVersionInfo.mFirmwareIdentifier) { +// compatible = false; +// } +// } + +// if((compatible)&&(checkFirmwareVersionMajor)) { +// if(mFirmwareVersionMajor < compatibleVersionInfo.mFirmwareVersionMajor) { +// compatible = false; +// } +// if((compatible)&&(checkFirmwareVersionMinor)) { +// if(mFirmwareVersionMinor < compatibleVersionInfo.mFirmwareVersionMinor) { +// compatible = false; +// } +// } +// if((compatible)&&(checkFirmwareVersionInternal)) { +// if(mFirmwareVersionInternal < compatibleVersionInfo.mFirmwareVersionInternal) { +// compatible = false; +// } +// } +// } +// else if((compatible)&&(checkFirmwareVersionMinor)) { +// if(mFirmwareVersionMinor < compatibleVersionInfo.mFirmwareVersionMinor) { +// compatible = false; +// } +// if((compatible)&&(checkFirmwareVersionInternal)) { +// if(mFirmwareVersionInternal < compatibleVersionInfo.mFirmwareVersionInternal) { +// compatible = false; +// } +// } +// } +// else if((compatible)&&(checkFirmwareVersionInternal)) { +// if(mFirmwareVersionInternal < compatibleVersionInfo.mFirmwareVersionInternal) { +// compatible = false; +// } +// } + + if(checkFirmwareVersionMajor){ + // Using the tree structure below each of the FW Major, Minor or Internal Release variables can be ignored + if((compatible)&&(!Util.compareVersions(mFirmwareIdentifier, + mFirmwareVersionMajor, + mFirmwareVersionMinor, + mFirmwareVersionInternal, + compatibleVersionInfo.mFirmwareIdentifier, + compatibleVersionInfo.mFirmwareVersionMajor, + compatibleVersionInfo.mFirmwareVersionMinor, + compatibleVersionInfo.mFirmwareVersionInternal))){ + compatible = false; + } + } + + if(compatible) { + return true; + } + } + return false; + } + + + public List sensorMapConflictCheck(Integer key){ + List listOfChannelConflicts = new ArrayList(); + + //TODO: handle Shimmer2/r exceptions which involve get5VReg(), getPMux() and writePMux() + + if (mHardwareVersion == HW_ID.SHIMMER_3){ + if(mSensorMap.get(key).mListOfSensorMapKeysConflicting != null) { + for(Integer sensorMapKey:mSensorMap.get(key).mListOfSensorMapKeysConflicting) { + if(mSensorMap.get(sensorMapKey) != null) { + if(mSensorMap.get(sensorMapKey).mIsEnabled == true) { + listOfChannelConflicts.add(sensorMapKey); + } + } + } + } + } + + if(listOfChannelConflicts.isEmpty()) { + return null; + } + else { + return listOfChannelConflicts; + } + } + + /** + * @param key This takes in a single sensor map key to check for conflicts and correct + * @return enabledSensors This returns the new set of enabled sensors, where any sensors which conflicts with sensorToCheck is disabled on the bitmap, so sensorToCheck can be accomodated (e.g. for Shimmer2 using ECG will disable EMG,GSR,..basically any daughter board) + * @return boolean + * + */ + public void sensorMapConflictCheckandCorrect(int key){ + + if(mSensorMap.get(key) != null) { + if(mSensorMap.get(key).mListOfSensorMapKeysConflicting != null) { + for(Integer sensorMapKey:mSensorMap.get(key).mListOfSensorMapKeysConflicting) { + if(mSensorMap.get(sensorMapKey) != null) { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + if(mSensorMap.get(sensorMapKey).isDerivedChannel()) { + mDerivedSensors &= ~mSensorMap.get(sensorMapKey).mDerivedSensorBitmapID; + } + setDefaultConfigForSensor(sensorMapKey, mSensorMap.get(sensorMapKey).mIsEnabled); + } + } + } + } + sensorMapCheckandCorrectSensorDependencies(); + sensorMapCheckandCorrectHwDependencies(); + } + + + private void sensorMapCheckandCorrectSensorDependencies() { + //Cycle through any required sensors and update sensorMap channel enable values + for(Integer sensorMapKey:mSensorMap.keySet()) { + if(mSensorMap.get(sensorMapKey).mListOfSensorMapKeysRequired != null) { + for(Integer requiredSensorKey:mSensorMap.get(sensorMapKey).mListOfSensorMapKeysRequired) { + if(mSensorMap.get(requiredSensorKey).mIsEnabled == false) { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + if(mSensorMap.get(sensorMapKey).isDerivedChannel()) { + mDerivedSensors &= ~mSensorMap.get(sensorMapKey).mDerivedSensorBitmapID; + } + setDefaultConfigForSensor(sensorMapKey, mSensorMap.get(sensorMapKey).mIsEnabled); + break; + } + } + } + + if (mHardwareVersion == HW_ID.SHIMMER_3){ + //Exceptions for Shimmer3 ExG + + // If ECG or ExG_Test (i.e., two ExG chips) + if(((sensorMapKey==Configuration.Shimmer3.SensorMapKey.ECG)||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_TEST)||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION))&&(mSensorMap.get(sensorMapKey).mIsEnabled)) { + if(!(((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled)&&(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_16BIT).mIsEnabled)) + ||((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled)&&(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG2_24BIT).mIsEnabled)))){ + mSensorMap.get(sensorMapKey).mIsEnabled = false; + } + else { + + } + } + // Else if EMG (i.e., one ExG chip) + else if((sensorMapKey==Configuration.Shimmer3.SensorMapKey.EMG)&&(mSensorMap.get(sensorMapKey).mIsEnabled == true)) { + if(!((mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_16BIT).mIsEnabled)||(mSensorMap.get(Configuration.Shimmer3.SensorMapKey.EXG1_24BIT).mIsEnabled))){ + mSensorMap.get(sensorMapKey).mIsEnabled = false; + } + } + } + + } + } + + + private void sensorMapCheckandCorrectHwDependencies() { + for(Integer sensorMapKey:mSensorMap.keySet()) { + if(mSensorMap.get(sensorMapKey).mListOfCompatibleVersionInfo != null) { + if(!checkIfVersionCompatible(mSensorMap.get(sensorMapKey).mListOfCompatibleVersionInfo)) { + mSensorMap.get(sensorMapKey).mIsEnabled = false; + if(mSensorMap.get(sensorMapKey).isDerivedChannel()) { + mDerivedSensors &= ~mSensorMap.get(sensorMapKey).mDerivedSensorBitmapID; + } + setDefaultConfigForSensor(sensorMapKey, mSensorMap.get(sensorMapKey).mIsEnabled); + } + } + } + } + +// private void setDefaultConfigForDisabledSensors() { +// for(Integer sensorMapKey:mSensorMap.keySet()) { +// if(mSensorMap.get(sensorMapKey).mIsEnabled == false) { +// setDefaultConfigForSensor(sensorMapKey, mSensorMap.get(sensorMapKey).mIsEnabled); +// } +// } +// } + + //TODO set defaults when ").mIsEnabled = false)" is set manually in the code + private void setDefaultConfigForSensor(int sensorMapKey, boolean state) { + if(sensorMapKey==Configuration.Shimmer3.SensorMapKey.LSM303DLHC_ACCEL) { + setDefaultLsm303dlhcAccelSensorConfig(state); + } + else if(sensorMapKey==Configuration.Shimmer3.SensorMapKey.LSM303DLHC_MAG) { + setDefaultLsm303dlhcMagSensorConfig(state); + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.MPU9150_GYRO){ + setDefaultMpu9150GyroSensorConfig(state); + } + else if(sensorMapKey == Configuration.Shimmer3.SensorMapKey.MPU9150_ACCEL){ + setDefaultMpu9150AccelSensorConfig(state); + } + + else if(sensorMapKey==Configuration.Shimmer3.SensorMapKey.BMP180_PRESSURE) { + setDefaultBmp180PressureSensorConfig(state); + } + else if(sensorMapKey==Configuration.Shimmer3.SensorMapKey.GSR) { + setDefaultGsrSensorConfig(state); + } + else if((sensorMapKey==Configuration.Shimmer3.SensorMapKey.ECG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_TEST) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EMG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG1_16BIT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG2_16BIT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG1_24BIT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG2_24BIT)) { + if(!checkIfOtherExgChannelEnabled()) { + setDefaultECGConfiguration(); + } + } + + else if((sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_HEADING) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_TAP) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MOTION_ORIENT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW)) { + if(!checkIfOtherMplChannelEnabled()) { + setDefaultMpu9150MplSensorConfig(state); + } + } + + } + + private void setDefaultBmp180PressureSensorConfig(boolean state) { + mPressureResolution = 0; + } + + private void setDefaultLsm303dlhcAccelSensorConfig(boolean state) { + if(state) { + setLowPowerAccelWR(false); + } + else { + mAccelRange = 0; + setLowPowerAccelWR(true); +// setLSM303AccelRateFromFreq(mShimmerSamplingRate); + } + } + + private void setDefaultLsm303dlhcMagSensorConfig(boolean state) { + if(state) { + setLowPowerMag(false); + } + else { + mMagRange=1; + setLowPowerMag(true); +// setLSM303MagRateFromFreq(mShimmerSamplingRate); + } + } + + private void setDefaultGsrSensorConfig(boolean state) { + if(state) { + } + else { + mGSRRange=4; + } + } + + private void setDefaultMpu9150GyroSensorConfig(boolean state) { + if(state) { + setLowPowerGyro(false); + } + else { + mGyroRange=1; + setLowPowerGyro(true); +// setMPU9150GyroAccelRateFromFreq(mShimmerSamplingRate); + } + } + + private void setDefaultMpu9150AccelSensorConfig(boolean state) { + mMPU9150AccelRange=0; + + } + + private void setDefaultMpu9150MplSensorConfig(boolean state) { + mMPU9150DMP = 0; + mMPU9150LPF = 0; + mMPU9150MotCalCfg = 0; + mMPU9150MPLSamplingRate = 0; + mMPU9150MagSamplingRate = 0; + mMPLSensorFusion = 0; + mMPLGyroCalTC = 0; + mMPLVectCompCal = 0; + mMPLMagDistCal = 0; + mMPLEnable = 0; + } + + private boolean checkIfOtherMplChannelEnabled() { + for(Integer sensorMapKey:mSensorMap.keySet()) { + if(mSensorMap.get(sensorMapKey).mIsEnabled) { + if((sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_9DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_6DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_EULER_9DOF) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_HEADING) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_PEDOMETER) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_TAP) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MOTION_ORIENT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_GYRO) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_ACCEL) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_MAG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.MPU9150_MPL_QUAT_6DOF_RAW)) { + return true; + } + } + } + return false; + } + + private boolean checkIfOtherExgChannelEnabled() { + for(Integer sensorMapKey:mSensorMap.keySet()) { + if(mSensorMap.get(sensorMapKey).mIsEnabled) { + if((sensorMapKey==Configuration.Shimmer3.SensorMapKey.ECG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_TEST) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EMG) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG_RESPIRATION) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG1_16BIT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG2_16BIT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG1_24BIT) + ||(sensorMapKey==Configuration.Shimmer3.SensorMapKey.EXG2_24BIT)) { + return true; + } + } + } + return false; + } + + + /** + * @return the InfoMem byte size. HW and FW version needs to be set first for this to operate correctly. + */ + public int getExpectedInfoMemByteLength() { + InfoMemLayout iML = new InfoMemLayout(mFirmwareIdentifier, mFirmwareVersionMajor, mFirmwareVersionMinor, mFirmwareVersionInternal); + return iML.mInfoMemSize; + } + + /** + * @return the mConfigTime + */ + public long getConfigTime() { + return mConfigTime; + } + + /** + * @return the mConfigTime in a parsed String format (yyyy-MM-dd hh:MM:ss) + */ + public String getConfigTimeParsed() { + return Util.convertSecondsToDateString(mConfigTime); + } + + /** + * @return the mBufferSize + */ + public int getBufferSize() { + return mBufferSize; + } + + /** + * @return the mMPU9150AccelRange + */ + public int getMPU9150AccelRange() { + return mMPU9150AccelRange; + } + + /** + * @return the mMPU9150GyroAccelRate + */ + public int getMPU9150GyroAccelRate() { + return mMPU9150GyroAccelRate; + } + + /** + * @return the mMPU9150MotCalCfg + */ + public int getMPU9150MotCalCfg() { + return mMPU9150MotCalCfg; + } + /** + * @return the mMPU9150LPF + */ + public int getMPU9150LPF() { + return mMPU9150LPF; + } + + /** + * @return the mMPU9150MPLSamplingRate + */ + public int getMPU9150MPLSamplingRate() { + return mMPU9150MPLSamplingRate; + } + + /** + * @return the mMPU9150MagSamplingRate + */ + public int getMPU9150MagSamplingRate() { + return mMPU9150MagSamplingRate; + } + + /** + * @return the mMasterShimmer + */ + public int getMasterShimmer() { + return mMasterShimmer; + } + + /** + * @return the mSingleTouch + */ + public int getSingleTouch() { + return mSingleTouch; + } + + /** + * @return the mTCXO + */ + public int getTCXO() { + return mTCXO; + } + + /** + * @return the mExperimentName + */ + public String getExperimentName() { + return mExperimentName; + } + + /** + * @return the mExperimentNumberOfShimmers + */ + public int getExperimentNumberOfShimmers() { + return mExperimentNumberOfShimmers; + } + + /** + * @return the mExperimentDurationEstimated + */ + public int getExperimentDurationEstimated() { + return mExperimentDurationEstimated; + } + + /** + * @return the mExperimentDurationMaximum + */ + public int getExperimentDurationMaximum() { + return mExperimentDurationMaximum; + } + + /** + * @return the mLSM303DigitalAccelLPM + */ + public boolean isLSM303DigitalAccelLPM() { + return mLowPowerAccelWR; + } + + /** + * @return true if ExG respiration detection frequency is 32kHz and false if 64kHz + */ + public boolean isExgRespirationDetectFreq32kHz() { + if(mEXG2RespirationDetectFreq==0) + return true; + else + return false; + } + + /** + * @return the mLSM303DigitalAccelHRM + */ + public boolean isLSM303DigitalAccelHRM() { + return mHighResAccelWR; + } + +// /** +// * @return the mLowPowerMag +// */ +// public boolean ismLowPowerMag() { +// return mLowPowerMag; +// } +// +// /** +// * @return the mLowPowerGyro +// */ +// public boolean ismLowPowerGyro() { +// return mLowPowerGyro; +// } + + /** + * @return the mShimmerUserAssignedName + */ + public String getShimmerUserAssignedName() { + return mShimmerUserAssignedName; + } + + /** + * @return the mLSM303MagRate + */ + public int getLSM303MagRate() { + return mLSM303MagRate; + } + + /** + * @return the mLSM303DigitalAccelRate + */ + public int getLSM303DigitalAccelRate() { + return mLSM303DigitalAccelRate; + } + + /** + * @return the mMacIdFromInfoMem + */ + public String getMacIdFromInfoMem() { + return mMacIdFromInfoMem; + } + + /** + * @return the mExperimentId + */ + public int getExperimentId() { + return mExperimentId; + } + + /** + * @return the syncNodesList + */ + public List getSyncNodesList() { + return syncNodesList; + } + + + /** + * @return the mSyncBroadcastInterval + */ + public int getSyncBroadcastInterval() { + return mSyncBroadcastInterval; + } + + + /** + * @return the mSyncWhenLogging + */ + public int getSyncWhenLogging() { + return mSyncWhenLogging; + } + + + /** + * @return the mBluetoothBaudRate + */ + public int getBluetoothBaudRate() { + return mBluetoothBaudRate; + } + + + /** + * @return the mExGResolution + */ + public int getExGResolution() { + return mExGResolution; + } + + /** + * @return the mShimmerVersion + */ + public int getHardwareVersion() { + return mHardwareVersion; + } + + /** + * @return the mSensorMap + */ + public TreeMap getSensorMap() { + return mSensorMap; + } + + /** + * @return the mConfigOptionsMap + */ + public HashMap getConfigOptionsMap() { + return mConfigOptionsMap; + } + + /** + * @return the mChannelTileMap + */ + public LinkedHashMap getChannelTileMap() { + return mSensorTileMap; + } + + + /** + * @return the mEXG1RateSetting + */ + public int getEXG1RateSetting() { + return mEXG1RateSetting; + } + + + /** + * @return the mEXG1CH1GainSetting + */ + public int getEXG1CH1GainSetting() { + return mEXG1CH1GainSetting; + } + + + /** + * @return the mEXG1CH2GainSetting + */ + public int getEXG1CH2GainSetting() { + return mEXG1CH2GainSetting; + } + + + + /** + * @return the mEXG2RateSetting + */ + public int getEXG2RateSetting() { + return mEXG2RateSetting; + } + + + /** + * @return the mEXG2CH1GainSetting + */ + public int getEXG2CH1GainSetting() { + return mEXG2CH1GainSetting; + } + + + /** + * @return the mEXG2CH2GainSetting + */ + public int getEXG2CH2GainSetting() { + return mEXG2CH2GainSetting; + } + + + /** + * @return the mEXGReferenceElectrode + */ + public int getEXGReferenceElectrode() { + return mEXGReferenceElectrode; + } + + + /** + * @return the mEXG1LeadOffCurrentMode + */ + public int getEXG1LeadOffCurrentMode() { + return mEXG1LeadOffCurrentMode; + } + + + /** + * @return the mEXG2LeadOffCurrentMode + */ + public int getEXG2LeadOffCurrentMode() { + return mEXG2LeadOffCurrentMode; + } + + + /** + * @return the mEXG1Comparators + */ + public int getEXG1Comparators() { + return mEXG1Comparators; + } + + + /** + * @return the mEXG2Comparators + */ + public int getEXG2Comparators() { + return mEXG2Comparators; + } + + + /** + * @return the mEXGRLDSense + */ + public int getEXGRLDSense() { + return mEXGRLDSense; + } + + + /** + * @return the mEXG1LeadOffSenseSelection + */ + public int getEXG1LeadOffSenseSelection() { + return mEXG1LeadOffSenseSelection; + } + + + /** + * @return the mEXG2LeadOffSenseSelection + */ + public int getEXG2LeadOffSenseSelection() { + return mEXG2LeadOffSenseSelection; + } + + + /** + * @return the mEXGLeadOffDetectionCurrent + */ + public int getEXGLeadOffDetectionCurrent() { + return mEXGLeadOffDetectionCurrent; + } + + + /** + * @return the mEXGLeadOffComparatorTreshold + */ + public int getEXGLeadOffComparatorTreshold() { + return mEXGLeadOffComparatorTreshold; + } + + + /** + * @return the mEXG2RespirationDetectState + */ + public int getEXG2RespirationDetectState() { + return mEXG2RespirationDetectState; + } + + + /** + * @return the mEXG2RespirationDetectFreq + */ + public int getEXG2RespirationDetectFreq() { + return mEXG2RespirationDetectFreq; + } + + + /** + * @return the mEXG2RespirationDetectPhase + */ + public int getEXG2RespirationDetectPhase() { + return mEXG2RespirationDetectPhase; + } + + public double getShimmerSamplingRate(){ + return mShimmerSamplingRate; + } + + + /** + * @return the mFirmwareIdentifier + */ + public int getFirmwareIdentifier() { + return mFirmwareIdentifier; + } + + public double getPressTempAC1(){ + return AC1; + } + + public double getPressTempAC2(){ + return AC2; + } + + public double getPressTempAC3(){ + return AC3; + } + + public double getPressTempAC4(){ + return AC4; + } + + public double getPressTempAC5(){ + return AC5; + } + + public double getPressTempAC6(){ + return AC6; + } + + public double getPressTempB1(){ + return B1; + } + + public double getPressTempB2(){ + return B2; + } + + public double getPressTempMB(){ + return MB; + } + + public double getPressTempMC(){ + return MC; + } + + public double getPressTempMD(){ + return MD; + } + + + /** + * @return the mDerivedSensors + */ + public long getDerivedSensors() { + return mDerivedSensors; + } + + public boolean isUsingConfigFromInfoMem() { + return mShimmerUsingConfigFromInfoMem; + } + + /** + * @return the mPpgAdcSelectionGsrBoard + */ + public int getPpgAdcSelectionGsrBoard() { + return mPpgAdcSelectionGsrBoard; + } + + /** + * @return the mPpg1AdcSelectionProto3DeluxeBoard + */ + public int getPpg1AdcSelectionProto3DeluxeBoard() { + return mPpg1AdcSelectionProto3DeluxeBoard; + } + + /** + * @return the mPpg2AdcSelectionProto3DeluxeBoard + */ + public int getPpg2AdcSelectionProto3DeluxeBoard() { + return mPpg2AdcSelectionProto3DeluxeBoard; + } + + /** + * @return the mMacIdFromUart + */ + public String getMacIdFromUart() { + return mMacIdFromUart; + } + + /** + * @return the mMacIdFromUartParsed + */ + public String getMacIdFromUartParsed() { + return mMacIdFromUartParsed; + } + + /** + * @return the mSamplingDividerVBatt + */ + public int getSamplingDividerVBatt() { + return mSamplingDividerVBatt; + } + + /** + * @return the mSamplingDividerGsr + */ + public int getSamplingDividerGsr() { + return mSamplingDividerGsr; + } + + /** + * @return the mMPU9150GyroAccelRate in Hz + */ + public double getMPU9150GyroAccelRateInHz() { + // Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or 7), and 1kHz when the DLPF is enabled + double numerator = 1000.0; + if(mMPU9150LPF == 0) { + numerator = 8000.0; + } + + if(mMPU9150GyroAccelRate == 0) { + return numerator; + } + else { + return (numerator / mMPU9150GyroAccelRate); + } + } + + + /** + * @return the mSamplingDividerPpg + */ + public int getSamplingDividerPpg() { + return mSamplingDividerPpg; + } + + /** + * @return the mSamplingDividerLsm303dlhcAccel + */ + public int getSamplingDividerLsm303dlhcAccel() { + return mSamplingDividerLsm303dlhcAccel; + } + + /** + * @return the mHighResAccelWR + */ + public boolean isHighResAccelWR() { + return mHighResAccelWR; + } + + /** + * @return the mLowPowerAccelWR + */ + public boolean isLowPowerAccelWR() { + return mLowPowerAccelWR; + } + + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerVerDetails.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerVerDetails.java new file mode 100644 index 00000000..04835f75 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerVerDetails.java @@ -0,0 +1,102 @@ +package com.shimmerresearch.driver; + +import java.io.Serializable; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +/** + * Holds Shimmer Hardware and Firmware version details. + * + * @author Mark Nolan + * + */ +public class ShimmerVerDetails implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -7940733886215010795L; + + public final static int EXP_BRD_NONE_ID = 255; + public static final String EXP_BRD_NONE = "None"; + + public final static class HW_ID { + public final static int SHIMMER_1 = 0; + public final static int SHIMMER_2 = 1; + public final static int SHIMMER_2R = 2; + public final static int SHIMMER_3 = 3; + public final static int SHIMMER_SR30 = 4; +// public final static int DCU_SWEATSENSOR = 4; + public final static int SHIMMER_GQ = 5; + } + + public static final Map mMapOfShimmerRevisions; + static { + Map aMap = new TreeMap(); + aMap.put(HW_ID.SHIMMER_1, "Shimmer1"); + aMap.put(HW_ID.SHIMMER_2, "Shimmer2"); + aMap.put(HW_ID.SHIMMER_2R, "Shimmer2r"); + aMap.put(HW_ID.SHIMMER_3, "Shimmer3"); + aMap.put(HW_ID.SHIMMER_SR30, "Shimmer SR30"); + aMap.put(HW_ID.SHIMMER_GQ, "ShimmerGQ"); +// aMap.put(HW_ID.DCU_SWEATSENSOR, "DCU_SWEATSENSOR"); + mMapOfShimmerRevisions = Collections.unmodifiableMap(aMap); + } + + public static final class HW_ID_SR_CODES { + public final static int EXP_BRD_BR_AMP = 8; + public final static int EXP_BRD_BR_AMP_UNIFIED = 49; + public final static int EXP_BRD_GSR = 14; + public final static int EXP_BRD_GSR_UNIFIED = 48; + public final static int EXP_BRD_PROTO3_MINI = 36; + public final static int EXP_BRD_EXG = 37; + public final static int EXP_BRD_EXG_UNIFIED = 47; + public final static int EXP_BRD_PROTO3_DELUXE = 38; + public final static int EXP_BRD_HIGH_G_ACCEL = 44; + public final static int EXP_BRD_GPS = 46; + public final static int BASE15U = 41; + public final static int BASE6U = 42; + } + + public static final Map mMapOfShimmmerHardware; + static { + Map aMap = new TreeMap(); + aMap.put(HW_ID_SR_CODES.EXP_BRD_BR_AMP, "Bridge Amplifier+"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_BR_AMP_UNIFIED, "Bridge Amplifier+"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_GSR, "GSR+"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_GSR_UNIFIED, "GSR+"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_PROTO3_MINI, "PROTO3 Mini"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_EXG, "ECG/EMG"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED, "ECG/EMG/Resp"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_PROTO3_DELUXE, "PROTO3 Deluxe"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_HIGH_G_ACCEL, "High-g Accel"); + aMap.put(HW_ID_SR_CODES.EXP_BRD_GPS, "GPS"); + aMap.put(HW_ID_SR_CODES.BASE15U, "Base15U"); + aMap.put(HW_ID_SR_CODES.BASE6U, "Base6U"); + mMapOfShimmmerHardware = Collections.unmodifiableMap(aMap); + } + + public final static class FW_ID { + public final static class SHIMMER3 { + public final static int BOILER_PLATE = 0; + public final static int BTSTREAM = 1; + public final static int SDLOG = 2; + public final static int LOGANDSTREAM = 3; + public final static int DCU_SWEATSENSOR = 4; + public final static int GQ_GSR = 5; + public final static int GPIO_TEST = 6; + } + + public final static class BASES { + public final static int BASE15U_REV2 = 0; + public final static int BASE15U_REV4 = 1; + public final static int BASE6U = 2; + } + + public final static class SHIMMER_GQ { + public final static int GQ_GSR = 0; + } + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerVerObject.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerVerObject.java new file mode 100644 index 00000000..c1598333 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/ShimmerVerObject.java @@ -0,0 +1,161 @@ +package com.shimmerresearch.driver; + +import java.io.Serializable; + +import com.shimmerresearch.driver.ShimmerVerDetails.HW_ID; +import com.shimmerresearch.driver.ShimmerVerDetails.FW_ID; + +/** + * Holds HW, FW and expansion board infomation. Used for docked Shimmers current + * info and also for the purposes of compatible version checking. + * + * @author Mark Nolan + * + */ +public class ShimmerVerObject implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -1966526754185423783L; + + public int mHardwareVersion = 0; + public String mHardwareVersionParsed = ""; + + public int mFirmwareIdentifier = 0; + public int mFirmwareVersionMajor = 0; + public int mFirmwareVersionMinor = 0; + public int mFirmwareVersionInternal = 0; + public int mFirmwareVersionCode = 0; + public String mFirmwareIdentifierParsed = ""; + public String mFirmwareVersionParsed = ""; + + public int mShimmerExpansionBoardId = 0; + + /** + * Used specifically for compatible version checking + * + * @param hardwareVersion + * @param firmwareIdentifier + * @param firmwareVersionMajor + * @param firmwareVersionMinor + * @param firmwareVersionInternal + * @param shimmerExpansionBoardId + */ + public ShimmerVerObject(int hardwareVersion, + int firmwareIdentifier, + int firmwareVersionMajor, + int firmwareVersionMinor, + int firmwareVersionInternal, + int shimmerExpansionBoardId) { + + mHardwareVersion = hardwareVersion; + mFirmwareIdentifier = firmwareIdentifier; + mFirmwareVersionMajor = firmwareVersionMajor; + mFirmwareVersionMinor = firmwareVersionMinor; + mFirmwareVersionInternal = firmwareVersionInternal; + mShimmerExpansionBoardId = shimmerExpansionBoardId; + + parseVerDetails(); + } + + /** + * Used specifically when finding the current information from a docked + * Shimmer through the dock's UART communication channel. + + * @param hardwareVersion + * @param firmwareIdentifier + * @param firmwareVersionMajor + * @param firmwareVersionMinor + * @param firmwareVersionInternal + */ + public ShimmerVerObject( + int hardwareVersion, + int firmwareIdentifier, + int firmwareVersionMajor, + int firmwareVersionMinor, + int firmwareVersionInternal) { + + mHardwareVersion = hardwareVersion; + mFirmwareIdentifier = firmwareIdentifier; + mFirmwareVersionMajor = firmwareVersionMajor; + mFirmwareVersionMinor = firmwareVersionMinor; + mFirmwareVersionInternal = firmwareVersionInternal; + + parseVerDetails(); + } + + + /** + * Empty constructor used when finding the current information from a docked + * Shimmer through the dock's UART communication channel. + * + */ + public ShimmerVerObject() { + // TODO Auto-generated constructor stub + } + + + private void parseVerDetails() { + if (ShimmerVerDetails.mMapOfShimmerRevisions.containsKey(mHardwareVersion)) { + mHardwareVersionParsed = ShimmerVerDetails.mMapOfShimmerRevisions.get(mHardwareVersion); + } else { + mHardwareVersionParsed = "Unknown"; + } + + if (mFirmwareIdentifier == FW_ID.SHIMMER3.BOILER_PLATE) { + mFirmwareIdentifierParsed = "Boilerplate"; + } else if (mFirmwareIdentifier == FW_ID.SHIMMER3.BTSTREAM) { + mFirmwareIdentifierParsed = "BtStream"; + + if ((mFirmwareVersionMajor == 0 && mFirmwareVersionMinor == 1) + || (mFirmwareVersionMajor == 1 && mFirmwareVersionMinor == 2 && mHardwareVersion == HW_ID.SHIMMER_2R)) + mFirmwareVersionCode = 1; + else if (mFirmwareVersionMajor == 0 && mFirmwareVersionMinor == 2) + mFirmwareVersionCode = 2; + else if (mFirmwareVersionMajor == 0 && mFirmwareVersionMinor == 3) + mFirmwareVersionCode = 3; + else if (mFirmwareVersionMajor == 0 && mFirmwareVersionMinor == 4) + mFirmwareVersionCode = 4; + else + // if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==5) + mFirmwareVersionCode = 5; + + } else if (mFirmwareIdentifier == FW_ID.SHIMMER3.SDLOG) { + mFirmwareIdentifierParsed = "SDLog"; + + // TODO + mFirmwareVersionCode = 6; + + // if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==1) + // mFirmwareVersionCode = 3; + // else if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==2) + // mFirmwareVersionCode = 4; + // else if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==3) + // mFirmwareVersionCode = 5; + + } else if (mFirmwareIdentifier == FW_ID.SHIMMER3.LOGANDSTREAM) { + mFirmwareIdentifierParsed = "LogAndStream"; + + if (mFirmwareVersionMajor == 0 && mFirmwareVersionMinor == 1) + mFirmwareVersionCode = 3; + else if (mFirmwareVersionMajor == 0 && mFirmwareVersionMinor == 2) + mFirmwareVersionCode = 4; + else + // if(mFirmwareVersionMajor==0 && mFirmwareVersionMinor==3) + mFirmwareVersionCode = 5; + } else if (mFirmwareIdentifier == FW_ID.SHIMMER3.GQ_GSR) { + mFirmwareIdentifierParsed = "GQ GSR"; + + // TODO + mFirmwareVersionCode = 7; + } else { + mFirmwareIdentifierParsed = "Unknown"; + } + + mFirmwareVersionParsed = mFirmwareIdentifierParsed + " v" + + mFirmwareVersionMajor + "." + mFirmwareVersionMinor + "." + + mFirmwareVersionInternal; + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Util.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Util.java new file mode 100644 index 00000000..95390956 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/driver/Util.java @@ -0,0 +1,233 @@ +package com.shimmerresearch.driver; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +/** Utility class with commonly useful methods + * + * @author Mark Nolan + * + */ +public class Util { + + public String mParentClassName = "UpdateCheck"; + + public Boolean mVerboseMode = true; + + public Util(String parentClassName, Boolean verboseMode){ + this.mParentClassName = parentClassName; + this.mVerboseMode = verboseMode; + } + + public void consolePrintLn(String message) { + if(mVerboseMode) { + Calendar rightNow = Calendar.getInstance(); + String rightNowString = "[" + String.format("%02d",rightNow.get(Calendar.HOUR_OF_DAY)) + + ":" + String.format("%02d",rightNow.get(Calendar.MINUTE)) + + ":" + String.format("%02d",rightNow.get(Calendar.SECOND)) + + ":" + String.format("%03d",rightNow.get(Calendar.MILLISECOND)) + "]"; + System.out.println(rightNowString + " " + mParentClassName + ": " + message); + } + } + public void consolePrint(String message) { + if(mVerboseMode) { + System.out.print(message); + } + } + + public void setVerboseMode(boolean verboseMode) { + mVerboseMode = verboseMode; + } + + public static String convertSecondsToDateString(long seconds) { + return convertMilliSecondsToDateString(seconds * 1000); + } + + public static String convertMilliSecondsToDateString(long milliSeconds) { + Calendar cal = Calendar.getInstance(); + + cal.setTimeInMillis(milliSeconds); + int dayIndex = cal.get(Calendar.DAY_OF_MONTH); + String dayString = getDayOfMonthSuffix(dayIndex); + + int monthIndex = cal.get(Calendar.MONTH); + String monthString = ""; + + switch(monthIndex){ + + case(0): + monthString = "Jan"; + break; + case(1): + monthString = "Feb"; + break; + case(2): + monthString = "Mar"; + break; + case(3): + monthString = "Apr"; + break; + case(4): + monthString = "May"; + break; + case(5): + monthString = "June"; + break; + case(6): + monthString = "July"; + break; + case(7): + monthString = "Aug"; + break; + case(8): + monthString = "Sept"; + break; + case(9): + monthString = "Oct"; + break; + case(10): + monthString = "Nov"; + break; + case(11): + monthString = "Dec"; + break; + default: + break; + } + DateFormat dfLocal = new SimpleDateFormat("//yyyy HH:mm:ss"); + String timeString = dfLocal.format(new Date(milliSeconds)); + timeString = timeString.replaceFirst("//", dayIndex + dayString + " " + monthString + " "); + return timeString; + } + + private static String getDayOfMonthSuffix(final int n) { + if (n >= 11 && n <= 13) { + return "th"; + } + switch (n % 10) { + case 1: return "st"; + case 2: return "nd"; + case 3: return "rd"; + default: return "th"; + } + } + + + public static String convertBytes(double bytes){ + + bytes = (double)((bytes) / 1024 / 1024 / 1024); + + String mFormattedBytesTxt = " GB"; + + if(bytes < 0.001){ + bytes = bytes * 1024 * 1024; + mFormattedBytesTxt = " KB"; + } + + else if (bytes < 1.0) { + bytes = bytes * 1024; + mFormattedBytesTxt = " MB"; + } + mFormattedBytesTxt = String.format("%.2f", bytes) + mFormattedBytesTxt; + return mFormattedBytesTxt; + + } + + public static boolean isNumeric(String str){ + if(str==null) { + return false; + } + if(str.isEmpty()) { + return false; + } + + for (char c : str.toCharArray()){ + if (!Character.isDigit(c)) return false; + } + return true; + } + + + public static boolean isAsciiPrintable(char ch) { + return ch >= 32 && ch < 127; + } + + final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); + public static String bytesToHex(byte[] bytes) { + char[] hexChars = new char[bytes.length * 2]; + for ( int j = 0; j < bytes.length; j++ ) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + public static byte[] hexStringToByteArray(String s) { + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i+1), 16)); + } + return data; + } + + + /**Returns true if FW ID is the same and "this" version is greater or equal then comparison version + * @param thisFwIdent + * @param thisMajor + * @param thisMinor + * @param thisInternal + * @param compFwIdent + * @param compMajor + * @param compMinor + * @param compInternal + * @return + */ + public static boolean compareVersions(int thisFwIdent, int thisMajor, int thisMinor, int thisInternal, + int compFwIdent, int compMajor, int compMinor, int compInternal) { + + if (thisFwIdent==compFwIdent){ + if ((thisMajor>compMajor) + ||(thisMajor==compMajor && thisMinor>compMinor) + ||(thisMajor==compMajor && thisMinor==compMinor && thisInternal>=compInternal)){ + return true; // if FW ID is the same and version is greater or equal + } + } + return false; // if less or not the same FW ID + } + + public static String convertDuration(int duration){ + + double totalSecs = duration/1000; //convert from miliseconds to seconds + int hours = (int) (totalSecs / 3600); + int minutes = (int) ((totalSecs % 3600) / 60); + int seconds = (int) (totalSecs % 60); + String timeString = String.format("%02d:%02d:%02d", hours, minutes, seconds); + + return timeString; + } + + + public String fromMilToDate(double miliseconds){ + + long mili = (long) miliseconds; + Date date = new Date(mili); + DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss"); + return formatter.format(date); + } + + + public String fromSecondsToDate(String seconds){ + + double miliseconds = 1000*Double.valueOf(seconds); + long mili = (long) miliseconds; + Date date = new Date(mili); + DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss"); + return formatter.format(date); + } + +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/tools/ArrayUtils.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/tools/ArrayUtils.java new file mode 100644 index 00000000..2706d111 --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/tools/ArrayUtils.java @@ -0,0 +1,16 @@ +package com.shimmerresearch.tools; + +public class ArrayUtils +{ + public static void reverse(byte[] a) + { + int n = a.length; + int i, k; + byte t; + for (i = 0; i < n / 2; i++) { + t = a[i]; + a[i] = a[n - i - 1]; + a[n - i - 1] = t; + } + } +} diff --git a/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/tools/Logging.java b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/tools/Logging.java new file mode 100644 index 00000000..a104dd4b --- /dev/null +++ b/SensorLib/sls-shimmer/src/main/java/com/shimmerresearch/tools/Logging.java @@ -0,0 +1,255 @@ +/*Rev 0.2 + * + * Copyright (c) 2010, Shimmer Research, Ltd. + * All rights reserved + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Shimmer Research, Ltd. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * @author Jong Chern Lim + * + * Changes since 0.1 + * - Added method to get outputFile + * + */ + + +package com.shimmerresearch.tools; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; + +import android.os.Environment; +import android.util.Log; + +import com.google.common.collect.Multimap; +import com.shimmerresearch.driver.FormatCluster; +import com.shimmerresearch.driver.ObjectCluster; + + +public class Logging { + boolean mFirstWrite=true; + String[] mSensorNames; + String[] mSensorFormats; + String[] mSensorUnits; + String mFileName=""; + BufferedWriter writer=null; + File outputFile; + String mDelimiter=","; //default is comma + + /** + * @param myName is the file name which will be used + */ + public Logging(String myName){ + mFileName=myName; + File root = Environment.getExternalStorageDirectory(); + Log.d("AbsolutePath", root.getAbsolutePath()); + outputFile = new File(root, mFileName+".dat"); + } + + public Logging(String myName,String delimiter){ + mFileName=myName; + mDelimiter=delimiter; + File root = Environment.getExternalStorageDirectory(); + Log.d("AbsolutePath", root.getAbsolutePath()); + outputFile = new File(root, mFileName+".dat"); + } + + /** + * @param myName + * @param delimiter + * @param folderName will create a new folder if it does not exist + */ + public Logging(String myName,String delimiter, String folderName){ + mFileName=myName; + mDelimiter=delimiter; + + File root = new File(Environment.getExternalStorageDirectory() + "/"+folderName); + + if(!root.exists()) + { + if(root.mkdir()); //directory is created; + } + outputFile = new File(root, mFileName+".dat"); + } + + + /** + * This function takes an object cluster and logs all the data within it. User should note that the function will write over prior files with the same name. + * @param objectClusterLog data which will be written into the file + */ + public void logData(ObjectCluster objectCluster){ + ObjectCluster objectClusterLog = objectCluster; + try { + + + + + if (mFirstWrite==true) { + writer = new BufferedWriter(new FileWriter(outputFile,true)); + + //First retrieve all the unique keys from the objectClusterLog + Multimap m = objectClusterLog.mPropertyCluster; + + int size = m.size(); + System.out.print(size); + mSensorNames=new String[size]; + mSensorFormats=new String[size]; + mSensorUnits=new String[size]; + int i=0; + int p=0; + for(String key : m.keys()) { + //first check that there are no repeat entries + + if(compareStringArray(mSensorNames, key) == true) { + for(FormatCluster formatCluster : m.get(key)) { + mSensorFormats[p]=formatCluster.mFormat; + mSensorUnits[p]=formatCluster.mUnits; + //Log.d("Shimmer",key + " " + mSensorFormats[p] + " " + mSensorUnits[p]); + p++; + } + + } + + mSensorNames[i]=key; + i++; + } + + + // write header to a file + + writer = new BufferedWriter(new FileWriter(outputFile,false)); + + for (int k=0;k dataFormats = objectClusterLog.mPropertyCluster.get(mSensorNames[r]); + FormatCluster formatCluster = (FormatCluster) returnFormatCluster(dataFormats,mSensorFormats[r],mSensorUnits[r]); // retrieve the calibrated data +// Log.d("Shimmer","Data : " +mSensorNames[r] + formatCluster.mData + " "+ formatCluster.mUnits); + writer.write(Double.toString(formatCluster.mData)); + writer.write(mDelimiter); + } + writer.newLine(); + + + } + catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + Log.d("Shimmer","Error with bufferedwriter"); + } + } + + public void closeFile(){ + if (writer != null){ + try { + writer.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + + public String getName(){ + return mFileName; + } + + public File getOutputFile(){ + return outputFile; + } + + public String getAbsoluteName(){ + return outputFile.getAbsolutePath(); + } + + private boolean compareStringArray(String[] stringArray, String string){ + boolean uniqueString=true; + int size = stringArray.length; + for (int i=0;i collectionFormatCluster, String format, String units){ + Iterator iFormatCluster=collectionFormatCluster.iterator(); + FormatCluster formatCluster; + FormatCluster returnFormatCluster = null; + + while(iFormatCluster.hasNext()){ + formatCluster=(FormatCluster)iFormatCluster.next(); + if (formatCluster.mFormat==format && formatCluster.mUnits==units){ + returnFormatCluster=formatCluster; + } + } + return returnFormatCluster; + } + +} + + diff --git a/SensorLib/sls-shimmer/src/main/java/de/fau/sensorlib/sensors/ShimmerSensor.java b/SensorLib/sls-shimmer/src/main/java/de/fau/sensorlib/sensors/ShimmerSensor.java index 470bfad2..ba0c6739 100644 --- a/SensorLib/sls-shimmer/src/main/java/de/fau/sensorlib/sensors/ShimmerSensor.java +++ b/SensorLib/sls-shimmer/src/main/java/de/fau/sensorlib/sensors/ShimmerSensor.java @@ -11,12 +11,12 @@ import android.content.Context; import android.os.Handler; import android.os.Message; -import android.support.annotation.NonNull; +import androidx.annotation.NonNull; import android.util.Log; import com.shimmerresearch.driver.FormatCluster; import com.shimmerresearch.driver.ObjectCluster; -import com.shimmerresearch.driver.Shimmer; +import com.shimmerresearch.android.Shimmer; import java.util.Collection; @@ -60,6 +60,21 @@ public ShimmerDataFrame(AbstractSensor fromSensor, double timestamp) { super(fromSensor, timestamp); } + public ShimmerDataFrame(AbstractSensor fromSensor, double timestamp, double emg, double[] accel, double [] gyro, double[] ecg) { + super(fromSensor, timestamp); + this.ecg = ecg[0]; + this.emg = emg; + this.ax = accel[0]; + this.ay = accel[1]; + this.az = accel[2]; + this.gx = gyro[0]; + this.gy = gyro[1]; + this.gz = gyro[2]; + this.ecgRA = ecg[0]; + this.ecgLA = ecg[1]; + this.isTwoChannelEcg = ecg.length == 2; + } + @Override public double getEcgSample() { if (isTwoChannelEcg) { @@ -320,7 +335,7 @@ public void startStreaming() { @Override public String getDeviceName() { if (shimmer == null) - return getDeviceName(); + return mDeviceName; return shimmer.getDeviceName(); } @@ -429,7 +444,7 @@ private ShimmerDataFrame parseDataMessage(Message msg) { } @Override - public boolean requestSamplingRateChange(double toSamplingRate) { + public boolean requestSamplingRateChange(double toSamplingRate) throws SensorException { // if we are streaming we can't change the sampling rate if (getState().ordinal() >= SensorState.STREAMING.ordinal()) return false; diff --git a/SensorLib/sls-simblee/build.gradle b/SensorLib/sls-simblee/build.gradle index d238cabd..89dac964 100644 --- a/SensorLib/sls-simblee/build.gradle +++ b/SensorLib/sls-simblee/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { @@ -24,7 +24,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' } diff --git a/SensorLib/sls-smartband2/build.gradle b/SensorLib/sls-smartband2/build.gradle index 625f42c7..a0d3a2fc 100644 --- a/SensorLib/sls-smartband2/build.gradle +++ b/SensorLib/sls-smartband2/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' version = '1.0' @@ -25,7 +25,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' } diff --git a/SensorLib/sls-smartwatch/build.gradle b/SensorLib/sls-smartwatch/build.gradle index d4977c94..fadfcc26 100644 --- a/SensorLib/sls-smartwatch/build.gradle +++ b/SensorLib/sls-smartwatch/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' android { @@ -24,7 +24,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' implementation 'com.google.android.gms:play-services-wearable:15.0.1' } diff --git a/SensorLib/sls-tek/build.gradle b/SensorLib/sls-tek/build.gradle index a191517f..219eb1c0 100644 --- a/SensorLib/sls-tek/build.gradle +++ b/SensorLib/sls-tek/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'com.github.dcendents.android-maven' -group='com.github.mad-lab-fau' +group='com.github.mad-lab-fau.SensorLib' version = '1.0' @@ -25,7 +25,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(path: ':sensorlib') - implementation 'com.android.support:appcompat-v7:27.1.1' + implementation 'androidx.appcompat:appcompat:1.0.0' } tasks.create(name: 'copyApk', type: Copy) {