From ea7cf0cf158b66643edd0481484da808f0e0f3fb Mon Sep 17 00:00:00 2001 From: Aleksandar Date: Fri, 30 Apr 2021 12:17:37 +0200 Subject: [PATCH 1/6] Added logic for detecting HUMAN hardware --- .idea/compiler.xml | 6 +++ .idea/jarRepositories.xml | 40 +++++++++++++++++++ .idea/misc.xml | 2 +- .idea/modules.xml | 4 +- .idea/runConfigurations.xml | 1 + app/build.gradle | 4 +- .../main/cpp/byb/SampleStreamProcessor.cpp | 2 +- app/src/main/cpp/byb/SampleStreamUtils.cpp | 5 +++ .../main/cpp/byb/includes/SampleStreamUtils.h | 6 ++- .../java/com/backyardbrains/dsp/Filters.java | 5 ++- .../dsp/usb/AbstractUsbSignalSource.java | 6 ++- .../dsp/usb/UsbSignalSource.java | 2 + .../ui/RecordScopeFragment.java | 12 ++++-- .../utils/SampleStreamUtils.java | 2 + .../utils/SpikerBoxHardwareType.java | 10 ++++- app/src/main/res/values/strings.xml | 1 + local.properties | 6 +-- 17 files changed, 96 insertions(+), 18 deletions(-) create mode 100644 .idea/compiler.xml create mode 100644 .idea/jarRepositories.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..dbc0164 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 23cea1a..efb0930 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -39,7 +39,7 @@ - + diff --git a/.idea/modules.xml b/.idea/modules.xml index a472893..0c37eca 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,8 +2,8 @@ - - + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml index 7f68460..e497da9 100644 --- a/.idea/runConfigurations.xml +++ b/.idea/runConfigurations.xml @@ -3,6 +3,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 27732a8..59e816a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,12 +2,12 @@ apply plugin: 'com.android.application' //apply plugin: 'io.fabric' android { - compileSdkVersion 28 + compileSdkVersion 30 defaultConfig { applicationId "com.backyardbrains" minSdkVersion 19 - targetSdkVersion 28 + targetSdkVersion 30 versionCode 89 versionName '1.8.3.1' @@ -109,6 +109,8 @@ dependencies { implementation "androidx.legacy:legacy-support-v4:$androidXLegacySupportV4Version" implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion" implementation "androidx.room:room-runtime:$roomVersion" + implementation 'com.google.firebase:firebase-crashlytics:17.2.1' + implementation 'com.google.firebase:firebase-analytics:17.5.0' annotationProcessor "androidx.room:room-compiler:$roomVersion" // material design diff --git a/app/src/main/cpp/byb/SampleStreamProcessor.cpp b/app/src/main/cpp/byb/SampleStreamProcessor.cpp index edf5528..27acafe 100644 --- a/app/src/main/cpp/byb/SampleStreamProcessor.cpp +++ b/app/src/main/cpp/byb/SampleStreamProcessor.cpp @@ -111,7 +111,13 @@ namespace backyardbrains { msb = msb & REMOVER; msb = msb << 7u; lsb = lsb & REMOVER; - sample = (short) (((msb | lsb) - 512) * 30); //TODO 2^14/2 bez 30 + sample = (short) (((msb | lsb) + - + backyardbrains::utils::SampleStreamUtils::getResolution( + hardwareType)) + * + backyardbrains::utils::SampleStreamUtils::getResolutionMultiplier( + hardwareType)); // calculate average sample average = 0.0001 * sample + 0.9999 * average; @@ -217,8 +223,8 @@ namespace backyardbrains { __android_log_print(ANDROID_LOG_DEBUG, TAG, "ESCAPE SEQUENCE MESSAGE %s AT %d", message.c_str(), sampleIndex); if (backyardbrains::utils::SampleStreamUtils::isHardwareTypeMsg(message)) { - listener->onSpikerBoxHardwareTypeDetected( - backyardbrains::utils::SampleStreamUtils::getHardwareType(message)); + hardwareType = backyardbrains::utils::SampleStreamUtils::getHardwareType(message); + listener->onSpikerBoxHardwareTypeDetected(hardwareType); } else if (backyardbrains::utils::SampleStreamUtils::isSampleRateAndNumOfChannelsMsg(message)) { const int sampleRate = backyardbrains::utils::SampleStreamUtils::getMaxSampleRate(message); const int channelCount = backyardbrains::utils::SampleStreamUtils::getChannelCount(message); diff --git a/app/src/main/cpp/byb/SampleStreamUtils.cpp b/app/src/main/cpp/byb/SampleStreamUtils.cpp index 095de5e..d45c8a1 100644 --- a/app/src/main/cpp/byb/SampleStreamUtils.cpp +++ b/app/src/main/cpp/byb/SampleStreamUtils.cpp @@ -9,7 +9,8 @@ namespace backyardbrains { namespace utils { const std::string SampleStreamUtils::HARDWARE_TYPE_PREFIX = "HWT:"; - const std::string SampleStreamUtils::HARDWARE_TYPE_PLANT = SampleStreamUtils::HARDWARE_TYPE_PREFIX + "PLANTSS;"; + const std::string SampleStreamUtils::HARDWARE_TYPE_PLANT = + SampleStreamUtils::HARDWARE_TYPE_PREFIX + "PLANTSS;"; const std::string SampleStreamUtils::HARDWARE_TYPE_MUSCLE = SampleStreamUtils::HARDWARE_TYPE_PREFIX + "MUSCLESS;"; const std::string SampleStreamUtils::HARDWARE_TYPE_HEART_AND_BRAIN_6CH = @@ -27,20 +28,25 @@ namespace backyardbrains { const std::string SampleStreamUtils::EVENT_PREFIX = "EVNT:"; const std::string SampleStreamUtils::EXPANSION_BOARD_TYPE_PREFIX = "BRD:"; - //TODO humans here - bool SampleStreamUtils::isHardwareTypeMsg(std::string message) { return message.compare(0, HARDWARE_TYPE_PREFIX.length(), HARDWARE_TYPE_PREFIX) == 0; } int SampleStreamUtils::getHardwareType(std::string message) { - if (std::strcmp(HARDWARE_TYPE_PLANT.c_str(), message.c_str()) == 0) return PLANT_HARDWARE; - if (std::strcmp(HARDWARE_TYPE_MUSCLE.c_str(), message.c_str()) == 0) return MUSCLE_HARDWARE; - if (std::strcmp(HARDWARE_TYPE_HEART_AND_BRAIN_6CH.c_str(), message.c_str()) == 0) return HEART_HARDWARE; - if (std::strcmp(HARDWARE_TYPE_HEART_AND_BRAIN.c_str(), message.c_str()) == 0) return HEART_HARDWARE; - if (std::strcmp(HARDWARE_TYPE_HUMANS.c_str(), message.c_str()) == 0) return HUMANS_HARDWARE; - if (message.find(HARDWARE_TYPE_NEURON_PRO) != std::string::npos) return NEURON_PRO_HARDWARE; - if (message.find(HARDWARE_TYPE_MUSCLE_PRO) != std::string::npos) return MUSCLE_PRO_HARDWARE; + if (std::strcmp(HARDWARE_TYPE_PLANT.c_str(), message.c_str()) == 0) + return PLANT_HARDWARE; + if (std::strcmp(HARDWARE_TYPE_MUSCLE.c_str(), message.c_str()) == 0) + return MUSCLE_HARDWARE; + if (std::strcmp(HARDWARE_TYPE_HEART_AND_BRAIN_6CH.c_str(), message.c_str()) == 0) + return HEART_HARDWARE; + if (std::strcmp(HARDWARE_TYPE_HEART_AND_BRAIN.c_str(), message.c_str()) == 0) + return HEART_HARDWARE; + if (std::strcmp(HARDWARE_TYPE_HUMANS.c_str(), message.c_str()) == 0) + return HUMANS_HARDWARE; + if (message.find(HARDWARE_TYPE_NEURON_PRO) != std::string::npos) + return NEURON_PRO_HARDWARE; + if (message.find(HARDWARE_TYPE_MUSCLE_PRO) != std::string::npos) + return MUSCLE_PRO_HARDWARE; return UNKNOWN_HARDWARE; } @@ -77,7 +83,8 @@ namespace backyardbrains { } bool SampleStreamUtils::isExpansionBoardTypeMsg(std::string message) { - return message.compare(0, EXPANSION_BOARD_TYPE_PREFIX.length(), EXPANSION_BOARD_TYPE_PREFIX) == 0; + return message.compare(0, EXPANSION_BOARD_TYPE_PREFIX.length(), + EXPANSION_BOARD_TYPE_PREFIX) == 0; } int SampleStreamUtils::getExpansionBoardType(std::string message) { @@ -87,5 +94,19 @@ namespace backyardbrains { message = message.replace(found, message.length() - found, ""); return std::stoi(message); } + + int SampleStreamUtils::getResolution(int hardwareType) { + if (hardwareType == HUMANS_HARDWARE) { + return 8192; //(2^14)/2 + } + return 512; //(2^10)/2 + } + + int SampleStreamUtils::getResolutionMultiplier(int hardwareType) { + if (hardwareType == HUMANS_HARDWARE) { + return 1; + } + return 30; + } } } \ No newline at end of file diff --git a/app/src/main/cpp/byb/includes/SampleStreamProcessor.h b/app/src/main/cpp/byb/includes/SampleStreamProcessor.h index 28c69d8..f5f58a2 100644 --- a/app/src/main/cpp/byb/includes/SampleStreamProcessor.h +++ b/app/src/main/cpp/byb/includes/SampleStreamProcessor.h @@ -115,6 +115,8 @@ namespace backyardbrains { byte msb; // Average signal which we use to avoid signal offset double average; + + int hardwareType = -1; }; } } diff --git a/app/src/main/cpp/byb/includes/SampleStreamUtils.h b/app/src/main/cpp/byb/includes/SampleStreamUtils.h index 78f9966..9e73b7b 100644 --- a/app/src/main/cpp/byb/includes/SampleStreamUtils.h +++ b/app/src/main/cpp/byb/includes/SampleStreamUtils.h @@ -87,6 +87,10 @@ namespace backyardbrains { */ static int getExpansionBoardType(std::string message); + static int getResolution(int hardwareType); + + static int getResolutionMultiplier(int hardwareType); + private: // Hardware type SpikerBox reply message prefix. static const std::string HARDWARE_TYPE_PREFIX; diff --git a/app/src/main/java/com/backyardbrains/dsp/Filters.java b/app/src/main/java/com/backyardbrains/dsp/Filters.java index d7baece..bd8b7e0 100644 --- a/app/src/main/java/com/backyardbrains/dsp/Filters.java +++ b/app/src/main/java/com/backyardbrains/dsp/Filters.java @@ -30,6 +30,10 @@ public class Filters { private static final double FREQ_CUTOFF_50HZ = 50d; // 60Hz cut-off frequency private static final double FREQ_CUTOFF_60HZ = 60d; + // Low cut-off frequency for Human PRO + private static final double FREQ_LOW_CUTOFF_HUMAN_PRO = 1d; + // High cut-off frequency for Human PRO + private static final double FREQ_HIGH_CUTOFF_HUMAN_PRO = 2500d; /** * Predefined filter configured for EKG. @@ -56,8 +60,11 @@ public class Filters { */ public static final BandFilter FILTER_BAND_NEURON_PRO = new BandFilter(FREQ_LOW_CUTOFF_NEURON_PRO, FREQ_HIGH_CUTOFF_NEURON_PRO); - - //TODO 1 2500 + /** + * Predefined filter configured for Human Pro. + */ + public static final BandFilter FILTER_BAND_HUMAN_PRO = + new BandFilter(FREQ_LOW_CUTOFF_HUMAN_PRO, FREQ_HIGH_CUTOFF_HUMAN_PRO); /** * Predefined notch filter that cuts-off 50Hz frequency */ diff --git a/app/src/main/java/com/backyardbrains/dsp/usb/SerialSignalSource.java b/app/src/main/java/com/backyardbrains/dsp/usb/SerialSignalSource.java index 788b2bc..cbc937e 100644 --- a/app/src/main/java/com/backyardbrains/dsp/usb/SerialSignalSource.java +++ b/app/src/main/java/com/backyardbrains/dsp/usb/SerialSignalSource.java @@ -4,11 +4,14 @@ import android.hardware.usb.UsbDeviceConnection; import androidx.annotation.NonNull; import com.backyardbrains.utils.SampleStreamUtils; +import com.backyardbrains.utils.SpikerBoxHardwareType; import com.felhr.usbserial.UsbSerialDevice; import com.felhr.usbserial.UsbSerialInterface; import java.util.Locale; import static com.backyardbrains.utils.LogUtils.makeLogTag; +import static com.backyardbrains.utils.SampleStreamUtils.SAMPLE_RATE_5000; +import static com.backyardbrains.utils.SampleStreamUtils.SPIKER_BOX_PRO_CHANNEL_COUNT; /** * Implementation of {@link AbstractUsbSignalSource} capable of USB serial communication with BYB hardware. @@ -132,6 +135,11 @@ private SerialSignalSource(@NonNull UsbDevice device, @NonNull UsbDeviceConnecti usbBuffer = new SerialBuffer(); serialDevice = UsbSerialDevice.createUsbSerialDevice(device, connection); + + if (getHardwareType() == SpikerBoxHardwareType.HUMAN_PRO) { + setSampleRate(SAMPLE_RATE_5000); + setChannelCount(SPIKER_BOX_PRO_CHANNEL_COUNT); + } } /** diff --git a/app/src/main/java/com/backyardbrains/ui/RecordScopeFragment.java b/app/src/main/java/com/backyardbrains/ui/RecordScopeFragment.java index 237eea4..b2e5118 100644 --- a/app/src/main/java/com/backyardbrains/ui/RecordScopeFragment.java +++ b/app/src/main/java/com/backyardbrains/ui/RecordScopeFragment.java @@ -434,7 +434,7 @@ public void onSpikerBoxBoardTypeDetectionEvent(SpikerBoxHardwareTypeDetectionEve break; case SpikerBoxHardwareType.HUMAN_PRO: spikerBoxBoard = getString(R.string.board_type_human_pro); - //filter = Filters.FILTER_BAND_NEURON_PRO; //TODO + filter = Filters.FILTER_BAND_HUMAN_PRO; break; default: case SpikerBoxHardwareType.UNKNOWN: diff --git a/app/src/main/java/com/backyardbrains/view/FilterSettingsView.java b/app/src/main/java/com/backyardbrains/view/FilterSettingsView.java index 0d632ed..a067b51 100644 --- a/app/src/main/java/com/backyardbrains/view/FilterSettingsView.java +++ b/app/src/main/java/com/backyardbrains/view/FilterSettingsView.java @@ -38,8 +38,8 @@ public class FilterSettingsView extends ConstraintLayout { private static final String TAG = makeLogTag(FilterSettingsView.class); static final BandFilter[] FILTERS = new BandFilter[] { - Filters.FILTER_BAND_HEART, Filters.FILTER_BAND_BRAIN, Filters.FILTER_BAND_MUSCLE, Filters.FILTER_BAND_PLANT, - Filters.FILTER_BAND_NEURON_PRO + Filters.FILTER_BAND_HEART, Filters.FILTER_BAND_BRAIN, Filters.FILTER_BAND_MUSCLE, + Filters.FILTER_BAND_PLANT, Filters.FILTER_BAND_NEURON_PRO, Filters.FILTER_BAND_HUMAN_PRO }; private static final BandFilter NO_FILTER = new BandFilter(Filters.FREQ_NO_CUT_OFF, Filters.FREQ_NO_CUT_OFF); @@ -58,7 +58,7 @@ public class FilterSettingsView extends ConstraintLayout { @BindViews({ R.id.btn_filter_heart, R.id.btn_filter_brain, R.id.btn_filter_muscle, R.id.btn_filter_plant, - R.id.btn_filter_neuro + R.id.btn_filter_neuro, R.id.btn_filter_human }) List