From fe55d5731117bd565072d45005e2535985049d4d Mon Sep 17 00:00:00 2001 From: brentfpage Date: Thu, 16 Apr 2026 23:25:25 -0700 Subject: [PATCH 01/21] files for imgui android app --- Android_App/app/build.gradle.kts | 56 + Android_App/app/proguard-rules.pro | 21 + Android_App/app/src/main/AndroidManifest.xml | 28 + .../assets/firmware/labrafirm_0007_02.hex | 753 +++++ .../src/main/assets/font/Greek_uc_delta.svg | 4 + .../app/src/main/assets/font/Readme.txt | 12 + .../app/src/main/assets/font/greek_delta.ttf | Bin 0 -> 1168 bytes Android_App/app/src/main/assets/font/mm.svg | 2 + .../app/src/main/assets/font/pulse.svg | 3 + .../assets/font/settings-gear-svgrepo-com.svg | 30 + .../src/main/assets/font/svg(2)-converted.svg | 1 + .../src/main/assets/font/waveform-glyphs3.ttf | Bin 0 -> 2532 bytes Android_App/app/src/main/cpp/CMakeLists.txt | 97 + .../app/src/main/cpp/cmake/FindSDL3.cmake | 220 ++ .../src/main/cpp/deps/librador/i2cdecoder.cpp | 214 ++ .../src/main/cpp/deps/librador/i2cdecoder.h | 82 + .../cpp/deps/librador/isobufferbuffer.cpp | 101 + .../main/cpp/deps/librador/isobufferbuffer.h | 53 + .../src/main/cpp/deps/librador/librador.cpp | 406 +++ .../app/src/main/cpp/deps/librador/librador.h | 89 + .../src/main/cpp/deps/librador/librador.pro | 62 + .../libusb/android/arm64-v8a/libusb1.0.so | Bin 0 -> 105136 bytes .../libusb/android/armeabi-v7a/libusb1.0.so | Bin 0 -> 70956 bytes .../librador/librador_deps/libusb/libusb.h | 2453 +++++++++++++++++ .../main/cpp/deps/librador/librador_global.h | 22 + .../cpp/deps/librador/librador_internal.h | 26 + .../app/src/main/cpp/deps/librador/logging.h | 11 + .../main/cpp/deps/librador/logging_internal.h | 26 + .../src/main/cpp/deps/librador/o1buffer.cpp | 451 +++ .../app/src/main/cpp/deps/librador/o1buffer.h | 90 + .../cpp/deps/librador/uartstyledecoder.cpp | 241 ++ .../main/cpp/deps/librador/uartstyledecoder.h | 86 + .../main/cpp/deps/librador/usbcallhandler.cpp | 935 +++++++ .../main/cpp/deps/librador/usbcallhandler.h | 182 ++ Android_App/app/src/main/cpp/inputs_ui.cpp | 220 ++ Android_App/app/src/main/cpp/inputs_ui.h | 25 + .../app/src/main/cpp/logic_decode_ui.cpp | 327 +++ .../app/src/main/cpp/logic_decode_ui.h | 73 + Android_App/app/src/main/cpp/main.cpp | 340 +++ Android_App/app/src/main/cpp/plot_ui.cpp | 224 ++ Android_App/app/src/main/cpp/plot_ui.h | 34 + Android_App/app/src/main/cpp/psu_ui.cpp | 69 + Android_App/app/src/main/cpp/psu_ui.h | 17 + .../app/src/main/cpp/settings_panel.cpp | 265 ++ Android_App/app/src/main/cpp/settings_panel.h | 27 + Android_App/app/src/main/cpp/sig_gen_ui.cpp | 134 + Android_App/app/src/main/cpp/sig_gen_ui.h | 39 + Android_App/app/src/main/cpp/trigger_ui.cpp | 218 ++ Android_App/app/src/main/cpp/trigger_ui.h | 17 + Android_App/app/src/main/cpp/ui_tile.cpp | 52 + Android_App/app/src/main/cpp/ui_tile.h | 23 + .../app/src/main/cpp/virtual_transform_ui.cpp | 96 + .../app/src/main/cpp/virtual_transform_ui.h | 25 + .../com/EspoTek/Labrador/MainActivity.java | 309 +++ .../res/drawable/ic_launcher_background.xml | 170 ++ .../res/drawable/ic_launcher_foreground.xml | 30 + .../app/src/main/res/layout/activity_main.xml | 19 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 + .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 2898 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1772 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 3918 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 5914 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 7778 bytes .../app/src/main/res/values-night/themes.xml | 16 + .../app/src/main/res/values/colors.xml | 10 + .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/themes.xml | 16 + .../app/src/main/res/xml/backup_rules.xml | 13 + .../main/res/xml/data_extraction_rules.xml | 19 + .../app/src/main/res/xml/device_filter.xml | 6 + Android_App/build.gradle.kts | 4 + Android_App/gradle.properties | 21 + Android_App/gradle/libs.versions.toml | 20 + Android_App/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 45457 bytes .../gradle/wrapper/gradle-wrapper.properties | 9 + Android_App/gradlew | 251 ++ Android_App/settings.gradle.kts | 23 + 83 files changed, 9933 insertions(+) create mode 100644 Android_App/app/build.gradle.kts create mode 100644 Android_App/app/proguard-rules.pro create mode 100644 Android_App/app/src/main/AndroidManifest.xml create mode 100644 Android_App/app/src/main/assets/firmware/labrafirm_0007_02.hex create mode 100644 Android_App/app/src/main/assets/font/Greek_uc_delta.svg create mode 100644 Android_App/app/src/main/assets/font/Readme.txt create mode 100644 Android_App/app/src/main/assets/font/greek_delta.ttf create mode 100644 Android_App/app/src/main/assets/font/mm.svg create mode 100644 Android_App/app/src/main/assets/font/pulse.svg create mode 100644 Android_App/app/src/main/assets/font/settings-gear-svgrepo-com.svg create mode 100644 Android_App/app/src/main/assets/font/svg(2)-converted.svg create mode 100644 Android_App/app/src/main/assets/font/waveform-glyphs3.ttf create mode 100644 Android_App/app/src/main/cpp/CMakeLists.txt create mode 100644 Android_App/app/src/main/cpp/cmake/FindSDL3.cmake create mode 100644 Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp create mode 100644 Android_App/app/src/main/cpp/deps/librador/i2cdecoder.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.cpp create mode 100644 Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador.cpp create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador.pro create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/android/arm64-v8a/libusb1.0.so create mode 100755 Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/android/armeabi-v7a/libusb1.0.so create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/libusb.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador_global.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/librador_internal.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/logging.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/logging_internal.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp create mode 100644 Android_App/app/src/main/cpp/deps/librador/o1buffer.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp create mode 100644 Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.h create mode 100644 Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp create mode 100644 Android_App/app/src/main/cpp/deps/librador/usbcallhandler.h create mode 100644 Android_App/app/src/main/cpp/inputs_ui.cpp create mode 100644 Android_App/app/src/main/cpp/inputs_ui.h create mode 100644 Android_App/app/src/main/cpp/logic_decode_ui.cpp create mode 100644 Android_App/app/src/main/cpp/logic_decode_ui.h create mode 100644 Android_App/app/src/main/cpp/main.cpp create mode 100644 Android_App/app/src/main/cpp/plot_ui.cpp create mode 100644 Android_App/app/src/main/cpp/plot_ui.h create mode 100644 Android_App/app/src/main/cpp/psu_ui.cpp create mode 100644 Android_App/app/src/main/cpp/psu_ui.h create mode 100644 Android_App/app/src/main/cpp/settings_panel.cpp create mode 100644 Android_App/app/src/main/cpp/settings_panel.h create mode 100644 Android_App/app/src/main/cpp/sig_gen_ui.cpp create mode 100644 Android_App/app/src/main/cpp/sig_gen_ui.h create mode 100644 Android_App/app/src/main/cpp/trigger_ui.cpp create mode 100644 Android_App/app/src/main/cpp/trigger_ui.h create mode 100644 Android_App/app/src/main/cpp/ui_tile.cpp create mode 100644 Android_App/app/src/main/cpp/ui_tile.h create mode 100644 Android_App/app/src/main/cpp/virtual_transform_ui.cpp create mode 100644 Android_App/app/src/main/cpp/virtual_transform_ui.h create mode 100644 Android_App/app/src/main/java/com/EspoTek/Labrador/MainActivity.java create mode 100644 Android_App/app/src/main/res/drawable/ic_launcher_background.xml create mode 100644 Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 Android_App/app/src/main/res/layout/activity_main.xml create mode 100644 Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 Android_App/app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 Android_App/app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 Android_App/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 Android_App/app/src/main/res/values-night/themes.xml create mode 100644 Android_App/app/src/main/res/values/colors.xml create mode 100644 Android_App/app/src/main/res/values/strings.xml create mode 100644 Android_App/app/src/main/res/values/themes.xml create mode 100644 Android_App/app/src/main/res/xml/backup_rules.xml create mode 100644 Android_App/app/src/main/res/xml/data_extraction_rules.xml create mode 100644 Android_App/app/src/main/res/xml/device_filter.xml create mode 100644 Android_App/build.gradle.kts create mode 100644 Android_App/gradle.properties create mode 100644 Android_App/gradle/libs.versions.toml create mode 100644 Android_App/gradle/wrapper/gradle-wrapper.jar create mode 100644 Android_App/gradle/wrapper/gradle-wrapper.properties create mode 100755 Android_App/gradlew create mode 100644 Android_App/settings.gradle.kts diff --git a/Android_App/app/build.gradle.kts b/Android_App/app/build.gradle.kts new file mode 100644 index 000000000..324964038 --- /dev/null +++ b/Android_App/app/build.gradle.kts @@ -0,0 +1,56 @@ +plugins { + alias(libs.plugins.android.application) +} + +android { + namespace = "org.labrador.imgui.android" + compileSdk { + version = release(36) + } + + defaultConfig { + applicationId = "org.labrador.imgui.android" + minSdk = 25 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + ndk { + abiFilters.add("arm64-v8a") + abiFilters.add("armeabi-v7a") + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + externalNativeBuild { + cmake { + path = file("src/main/cpp/CMakeLists.txt") + version = "3.22.1" + } + } + sourceSets { + getByName("main") { + java { + directories.add("src/main/cpp/deps/SDL/android-project/app/src/main/java") + } + } + } + aaptOptions{ + ignoreAssetsPattern = "!pulse.svg:!svg(2)-converted.svg:!settings-gear-svgrepo-com.svg:!mm.svg:!Greek_uc_delta.svg:!Readme.txt"; + } +} + +dependencies { + implementation("com.google.android.material:material:1.2.1") + implementation("com.android.support.constraint:constraint-layout:1.0.2") + implementation("androidx.appcompat:appcompat:1.7.1") +// implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) + //implementation("androidx.appcompat:appcompat:1.0.2") +} diff --git a/Android_App/app/proguard-rules.pro b/Android_App/app/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/Android_App/app/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 \ No newline at end of file diff --git a/Android_App/app/src/main/AndroidManifest.xml b/Android_App/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..f8f3c033b --- /dev/null +++ b/Android_App/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Android_App/app/src/main/assets/firmware/labrafirm_0007_02.hex b/Android_App/app/src/main/assets/firmware/labrafirm_0007_02.hex new file mode 100644 index 000000000..ad704b552 --- /dev/null +++ b/Android_App/app/src/main/assets/firmware/labrafirm_0007_02.hex @@ -0,0 +1,753 @@ +:1000000028C1000042C1000040C100003EC1000004 +:100010003CC100003AC100000C94340A0C94640AFC +:1000200034C1000032C1000030C100002EC1000008 +:100030002CC100002AC1000028C1000026C1000018 +:1000400024C1000022C1000020C100001EC1000028 +:100050001CC100001AC1000018C1000016C1000038 +:100060000C94610B0C946C0B10C100000EC10000CD +:100070000CC100000AC1000008C1000006C1000058 +:1000800004C1000002C1000000C10000FEC0000069 +:10009000FCC00000FAC00000F8C00000F6C000007C +:1000A000F4C00000F2C00000F0C00000EEC000008C +:1000B000ECC00000EAC00000E8C00000E6C000009C +:1000C000E4C00000E2C00000E0C00000DEC00000AC +:1000D000DCC00000DAC00000D8C00000D6C00000BC +:1000E000D4C00000D2C00000D0C00000CEC00000CC +:1000F000CCC00000CAC00000C8C00000C6C00000DC +:10010000C4C00000C2C00000C0C00000BEC00000EB +:10011000BCC00000BAC00000B8C000007EC400002F +:10012000B4C00000B2C00000B0C00000AEC000000B +:10013000ACC00000AAC00000A8C00000A6C000001B +:10014000A4C00000A2C00000A0C000000C94D60A09 +:100150009CC000009AC0000098C0000096C000003B +:1001600094C0000092C0000090C000008EC000004B +:100170008CC000008AC0000088C0000086C000005B +:1001800084C0000082C0000080C000007EC000006B +:100190007CC000007AC0000078C0000076C000007B +:1001A00074C0000072C0000070C000006EC000008B +:1001B0006CC000006AC0000068C0000066C000009B +:1001C00064C0000062C0000060C000005EC00000AB +:1001D0005CC000005AC0000058C0000056C00000BB +:1001E00054C0000052C0000050C000004EC00000CB +:1001F0004CC000000C946E150C941C1606040804E8 +:100200000A040C040E041004120414042604280426 +:100210002A042C042E04330430043204380D5E0DFD +:10022000850DCD0DD60DDB0D2E0E330E520E590E53 +:10023000610E650E650E650E650E650E650E650E2A +:10024000AA0DE70DF10DFB0D090E0B0E0D0E170E8D +:10025000210E11241FBECFEFCDBFDFE2DEBF10E2C3 +:10026000A0E0B0E2EAE5FEE202C005900D92AA39F4 +:10027000B107D9F72BE2AAE9B0E201C01D92A03E76 +:10028000B207E1F779D20C942B17BACE84E08093B1 +:1002900056008CE18AD3809363008BEB80936600D9 +:1002A00080E88093650081E08093600088ED84BFE2 +:1002B0001092410083E08093500080915100833080 +:1002C000E1F78091500081608093500088E1809335 +:1002D00055008091510080FFFCCF809150008061DB +:1002E000809350008091510084FFFCCF88ED84BF43 +:1002F00084E0809340000895E0E7F0E085818E7F00 +:100300008583E0E0FAE08FEB9DE586A397A380EE7E +:100310009EE280A391A382E0808308958091200AC9 +:100320009091210A813E2EE2920718F020918221BD +:1003300006C0803E2EE2920721F020917F2120937B +:100340006A0020910520222321F080910520815010 +:1003500033C0885F9A42813D974080F110929A2085 +:1003600080919B2090919C20A0919D20B0919E20F7 +:100370000196A11DB11D80939B2090939C20A0937A +:100380009D20B0939E2080919B2090919C20A091D5 +:100390009D20B0919E20892F9A2FAB2FBB27809351 +:1003A000A22180919B2090919C20A0919D20B091B2 +:1003B0009E208093A12186E08093052080910720D4 +:1003C000909108200196B1F480910A208F3F91F01E +:1003D00080910620811106C0809106208150809373 +:1003E00006200895809114019091150180930720B3 +:1003F000909308200895009709F45EC00CF457C04C +:1004000040E020916B0030E02093802130938121E7 +:1004100020918021309181213695322F22273795E6 +:100420002795209380213093812150916A0020915B +:10043000802130918121250F311D2093802130931F +:1004400081210000209180213091812128173907D6 +:1004500028F410928021109281210895209180210A +:1004600030918121280F391F2115304238F08FEF4C +:100470009FE1809380219093812108952091802194 +:1004800030918121442329F0A901481B590BCA014D +:1004900002C0820F931F80938021909381218091CD +:1004A0008021909181218F7780936A0008959195A2 +:1004B0008195910941E0A5CF0895CF93DF93C09135 +:1004C000200AD091210A80910320909104209E015E +:1004D000281B390B209383213093842180919A200B +:1004E00081114BC080918321909184218E3C9F4F3C +:1004F000D4F480918321909184218B369F4F9CF07E +:1005000080910220882321F080910220815008C030 +:1005100080916A008093822181E080939A208CE010 +:10052000809302202AC08CE0809302208091832156 +:10053000909184218A369F4F1CF08FEF9FEF02C06D +:1005400081E090E080937D2190937E2180918321B2 +:100550009091842120917D2130917E2160E370E093 +:100560000E940217261B370B20937D2130937E219A +:1005700080917D2190917E213EDF80919A20813073 +:1005800029F58091832190918421C39794F08091E3 +:100590000220882331F08091022081508093022034 +:1005A00015C080916A0080937F2183E080939A2018 +:1005B0000DC08091832190918421873991051CF48D +:1005C00081E090E002C08FEF9FEF15DFC093032022 +:1005D000D0930420DF91CF9108958617970779F083 +:1005E0006817790728F49C01261B370BB90109C04D +:1005F0008617970718F4681B790B03C0089560E00D +:1006000070E0CB010895CF93DF938091002090910B +:100610000120892B51F080910020909101200197B9 +:10062000809300209093012043C080E490E0809369 +:10063000002090930120809107209091082001963E +:10064000B9F1809114019091150120910A20263072 +:1006500018F467E771E002C06EEE72E00E94EE16D9 +:10066000EC0180910720909108208C179D0758F489 +:100670006091072070910820CE01AFDF029718F03B +:1006800080EC9DE511C08091072090910820C8174B +:10069000D90770F46091072070910820CE019DDF8A +:1006A000029730F08FEB9DE58093360A9093370ADE +:1006B000DF91CF910895AC01460F571F861B970B12 +:1006C0002091200A3091210A24173507C8F720917C +:1006D000200A3091210A8217930790F70895E0E8E5 +:1006E000F6E08FE0808385E0848308951F93CF93A5 +:1006F000DF93C0E4D0E0198180E4898340E250E0D8 +:1007000068EB7BE280E290E00E94C8101983DF91E1 +:10071000CF911F9108951F93CF93DF93C0E4D0E052 +:10072000198180E489838BEB95E20E94FE1081E0C1 +:100730000E9410111983DF91CF911F9108950895A0 +:100740000F931F932091A4208EEE92E0289FA0018A +:10075000299F500D112444525A4D00EA13E02EEE09 +:1007600032E060E081E80E94AB141F910F91089580 +:100770001CBEEEEFF0E40994B9DF8091B82B88231A +:1007800069F080E2E8EBFBE2ABEBB5E201900D92A1 +:100790008A95E1F71092BB25BEDFEADF87E0809300 +:1007A000A200789473DDCBDF0E94C70C49D16CD1D5 +:1007B00060E080E003D1EFD08CE0E3D0B5D659D72C +:1007C00072D78DDF60E870E28EE891E20E94241714 +:1007D0000000000000000000000000000000000019 +:1007E00000000000000000000000000080919F2039 +:1007F000882371F3E091BA238E2F90E08830910521 +:10080000A0F4FC01E250FF4F0C94151768D10DC005 +:10081000FCD10BC0B9D209C06ED307C02DD405C01E +:10082000EDD403C0ECD401C084D510929F20D0CF6A +:1008300008950895E0910A208E2F90E08830910568 +:1008400090F4FC01EA5FFE4F0C941517DDD10BC04C +:100850009AD209C04FD307C00ED405C0CED403C06E +:1008600067D501C000D680911401809397218091B3 +:100870001501809398218091240180939921809182 +:10088000250180939A218091200A8093A321809151 +:10089000210A8093A421809114019091150186343E +:1008A000914080F08091140190911501893A914016 +:1008B00048F480911401909115018093D82B909366 +:1008C000D92B00008091A220882339F015DD1092E9 +:1008D000A22081E08093A12008958091A120882307 +:1008E00041F080919A20833019F418DD8CDE01C02C +:1008F000E4DD8091A020882351F080911401909133 +:1009000015018093D82B9093D92B1092A020909111 +:10091000A42081E0911180E08093A42008950F939A +:100920001F9381E08093A7208093A22000EA13E028 +:100930002DE730E04CED55E260E081E80E94AB1419 +:1009400081E01F910F9108951092A720089581E0F2 +:10095000089581E0089510922002982F9C71936869 +:100960009093200287FF03C080E192E002C080E004 +:1009700090E0892B8093210210922202109226028D +:100980000895E0E0F2E010AA836880AB80E181ABDB +:1009900012AA16AA0895E0E0F2E010A683E880A764 +:1009A0008FE281A712A616A60895AAECB1E092E004 +:1009B0009C93E82FF0E084911C920895909171002F +:1009C0009D7F9093710010920002623011F09CE1C3 +:1009D00001C09EE19093010290E490930202811184 +:1009E00002C080E401C080EC80930302613011F00A +:1009F00084E001C083E08093040280E2D6DF80932C +:100A00000C0281E2D2DF80930D0210921802109244 +:100A1000190281E080930002BECF1F920F920FB6A1 +:100A20000F9211248F93000000000000000081E06D +:100A3000809323028F910F900FBE0F901F901895F7 +:100A4000CF93DF93E0E7F0E082818B7F8283C0E287 +:100A5000D3E08DE0888380E4898389E08A8383E31F +:100A6000A4DF888782E3A1DF898787E39EDF8A8707 +:100A700086E39BDF8B87E0E2F6E080818360808302 +:100A80001482DF91CF910895E0E7F0E080818E7FBE +:100A9000808380E8809300010895E0E0F1E0108A0F +:100AA00080E4808B10A280A310AA80ABE0E4F1E088 +:100AB000108280831092A6201092A5201092A4206C +:100AC00010928C2110928D2110928A2110928B21EC +:100AD00008958093BA2381E080939F200895109217 +:100AE0000A20DBDF80910920811105C081E080931D +:100AF000360184E003C01092360184E28093300115 +:100B00001092310149E54093320122E020933301F4 +:100B100080910C2090910D208093340190933501A9 +:100B20008BEB93E2809338019093390110923A0154 +:100B30008BE380933C0183E080933D0110923E0162 +:100B4000909130019068909330011092460134E208 +:100B50003093400110924101409342018093430140 +:100B600040910E2050910F20409344015093450135 +:100B70004AEA51E2409348015093490110924A01D8 +:100B800099E390934C0180934D0110924E01909106 +:100B900040019068909340011092100190E490936E +:100BA000100194E0909310018093110185E98093E6 +:100BB000120180E18093130187E791E08093140193 +:100BC00090931501309318012093190110921A0186 +:100BD0008CED95E280931C0190931D0110921E01F3 +:100BE00068EC70E084EF91E066DD88EC90E0809343 +:100BF00007209093082081E08093062080911001C7 +:100C000080688093100108950895CF93C1E0C09348 +:100C10000A2043DF1092300180E48093300194E099 +:100C20009093300110923101109232018BE4809345 +:100C300033011092340110923501109236012BE0ED +:100C400030E2209338013093390110923A0180EA62 +:100C500080933C0188E080933D0110923E01809199 +:100C60003001806A8093300185E58093A0088093ED +:100C7000A00880910920811105C0C093460190937E +:100C8000400105C01092460184E280934001109219 +:100C9000410189E58093420122E020934301809144 +:100CA0000C2090910D2080934401909345018BEB93 +:100CB00093E2809348019093490110924A018BE39B +:100CC00080934C0183E080934D0110924E019091EE +:100CD000400190689093400134E03093200180936C +:100CE000210195E9909322014BE44093230147E7CA +:100CF00051E0409324015093250160EA609328015C +:100D000068E06093290110922A016AEC78E260930E +:100D10002C0170932D0110922E01309310018093BD +:100D200011019093120180E180931301409314010B +:100D30005093150184E280931801209319011092B9 +:100D40001A018CED95E280931C0190931D01109285 +:100D50001E0168EC70E084EF91E0ADDC88EC90E07F +:100D6000809307209093082081E080930620809153 +:100D70002001806880932001809110018068809319 +:100D80001001CF910895089582E080930A2085DEB6 +:100D900080910920811105C081E08093360184E0B3 +:100DA00003C01092360184E2809330011092310129 +:100DB00039E53093320192E09093330140910C2059 +:100DC00050910D2040933401509335014BEB53E289 +:100DD000409338015093390110923A018BE380938C +:100DE0003C0183E080933D0110923E01209130014F +:100DF0002068209330011092460174E27093400104 +:100E000010924101309342018093430120910E20C2 +:100E100030910F2020934401309345012AEA31E2BA +:100E2000209348013093490110924A0129E320930D +:100E30004C0180934D0110924E0120914001206899 +:100E4000209340011092100120E42093100164E0EF +:100E5000609310018093110155E95093120140E114 +:100E60004093130127E731E02093140130931501DB +:100E7000709318019093190110921A01ECEDF5E2AC +:100E8000E0931C01F0931D0110921E01609320015C +:100E90008093210150932201409323012093240148 +:100EA0003093250184E380932801909329011092C7 +:100EB0002A018AEC98E280932C0190932D011092E4 +:100EC0002E0168EC70E084EF91E0F5DB88EC90E0B7 +:100ED000809307209093082081E0809306208091E2 +:100EE00010018068809310018091200180688093B8 +:100EF00020010895089583E080930A20CEDD80913B +:100F00000920811105C081E08093460184E003C07F +:100F10001092460184E2809340011092410129E53C +:100F20002093420182E08093430180910C209091B4 +:100F30000D2080934401909345018BEB93E28093C5 +:100F400048019093490110924A018BE380934C0130 +:100F500083E080934D0110924E0190914001906882 +:100F6000909340011092360194E2909330011092D8 +:100F70003101209332018093330120910E20309172 +:100F80000F2020933401309335012AEA31E2209377 +:100F900038013093390110923A0199E390933C0162 +:100FA00080933D0110923E019091300190689093A2 +:100FB00030011092200160E46093200154E05093CE +:100FC000200110922101109222014BE44093230151 +:100FD0001092240110922501109226012BE030E29C +:100FE000209328013093290110922A0130EA30938E +:100FF0002C0128E020932D0110922E0190912001C8 +:10100000906A9093200195E59093A00810921001AA +:1010100060931001509310018093110185E9809332 +:1010200012014093130187E791E08093140190939C +:101030001501309318012093190110921A018CEDBB +:1010400095E280931C0190931D0110921E0168ECA3 +:1010500070E084EF91E02FDB88EC90E08093072034 +:101060009093082081E08093062080911001806891 +:101070008093100108950895CF93C4E0C0930A208F +:101080000CDD1092300180E480933001C093300178 +:1010900010923101109232018BE48093330110924F +:1010A000340110923501109236018BE090E280936A +:1010B00038019093390110923A0180EA80933C0103 +:1010C00088E080933D0110923E0180913001806A5A +:1010D0008093300185E58093A008809109208111DB +:1010E00006C081E080934601C093400105C0109284 +:1010F000460184E2809340011092410189E580938A +:10110000420182E08093430180910C2090910D2058 +:1011100080934401909345018BEB93E280934801C7 +:101120009093490110924A018BE380934C0183E034 +:1011300080934D0110924E019091400190689093E0 +:10114000400154E0509310018093110145E9409310 +:1011500012019BE49093130127E731E020931401DF +:101160003093150190EA9093180198E0909319013B +:1011700010921A016CED75E260931C0170931D01D1 +:1011800010921E015093200180932101409322016F +:101190008AE480932301209324013093250183EC7A +:1011A000809328019093290110922A018AEC98E2F9 +:1011B00080932C0190932D0110922E0168EC70E029 +:1011C00084EF91E078DA88EC90E0809307209093A8 +:1011D000082081E080930620809110018068809330 +:1011E000100180912001806880932001809110017E +:1011F000806180931001CF9108950895FFCF86E01C +:1012000080930A204ADC1092360194E290933001D8 +:101210001092310189E58093320183E0809333019C +:1012200020910E2030910F2020933401309335010E +:101230002AEA31E2209338013093390110923A01C1 +:1012400029E320933C0180933D0110923E0180915F +:10125000300180688093300180910920811107C09E +:1012600081E08093460184E08093400104C01092A5 +:101270004601909340011092410189E5809342011B +:1012800092E09093430120910C2030910D20209307 +:101290004401309345012BEB33E220934801309316 +:1012A000490110924A018BE380934C0183E08093C3 +:1012B0004D0110924E018091400180688093400161 +:1012C0001092100180E48093100184E28093100159 +:1012D0001092110125E92093120120E120931301BE +:1012E0002CED35E020931401309315018093180103 +:1012F0009093190110921A018CED95E280931C01D4 +:1013000090931D0110921E0168EC70E084EF91E053 +:10131000D2D980E991E0809307209093082081E062 +:1013200080930620809110018068809310010895B9 +:10133000089587E080930A20B0DB1092360194E292 +:10134000909330011092310189E58093320183E05E +:101350008093330120910E2030910F20209334018F +:10136000309335012AEA31E2209338013093390174 +:1013700010923A0129E320933C0180933D011092A1 +:101380003E01809130018068809330018091092076 +:10139000811107C081E08093460184E08093400181 +:1013A00004C010924601909340011092410189E5DA +:1013B0008093420192E09093430120910C20309160 +:1013C0000D2020934401309345012BEB33E2209311 +:1013D00048013093490110924A018BE380934C01FC +:1013E00083E080934D0110924E018091400180680E +:1013F000809340011092100180E48093100185E2F7 +:10140000809310011092110185E98093120180E10F +:10141000809313012CED35E02093140130931501D6 +:1014200084E2809318019093190110921A018CEDB7 +:1014300095E280931C0190931D0110921E0168ECAF +:1014400070E084EF91E037D980E991E08093072044 +:101450009093082081E0809306208091100180689D +:1014600080931001089508951F920F920FB60F9266 +:1014700011248F939F9381E08093030110921001B8 +:1014800084E08093100187E791E0809314019093AA +:1014900015018091A420811103C08EEE92E002C05C +:1014A00080E090E084529A4D80931C0190931D013E +:1014B000809110018068809310019F918F910F900F +:1014C0000FBE0F901F9018951F920F920FB60F929C +:1014D00011248F939F9382E0809303011092200147 +:1014E00084E08093200187E791E08093240190932A +:1014F00025018091A420811103C085E694E002C0FB +:1015000087E791E084529A4D80932C0190932D01AE +:10151000809120018068809320019F918F910F908E +:101520000FBE0F901F901895E0E7F0E083818C7F4D +:10153000838384818C7F848380818D7F8083E0E8B6 +:10154000F1E080EC8283128688EC81831186A0E032 +:10155000B8E034E03C9323E011962C931197149655 +:101560001C92149785ED91E096968D939C93979796 +:1015700016961C921697E0E4F8E0308321831482DB +:1015800086A397A31682E0E6F6E0808180618083DF +:10159000E0E4F9E083E18183148282E08683A6A3FC +:1015A000B7A310A611A681E0808308951F920F9221 +:1015B0000FB60F9211242F933F934F935F938F9306 +:1015C0009F93CF93DF931F92CDB7DEB78FEF8093BA +:1015D0004C0980910A20873031F480912C02898354 +:1015E00090912D0202C090912C028091A320891B22 +:1015F000209168093091690982308CF02A3F374088 +:1016000070F4209168093091690989301CF481E0F7 +:1016100090E002C086E090E0820F931F18C02091F6 +:101620006809309169098F3FB4F42730310598F08B +:101630002091680930916909883F1CF081E090E0B1 +:1016400002C086E090E0A901481B590BCA018093B3 +:101650007809909379090F90DF91CF919F918F91A5 +:101660005F914F913F912F910F900FBE0F901F9060 +:101670001895E0E7F0E083818F7E8383E0E4F6E075 +:1016800080818A6A80838FEF848388E5828BE0EA99 +:10169000F8E080E3838384EC858387E08683178288 +:1016A00088E184830895E0E7F0E08381877F838386 +:1016B000E0ECF8E0118288E58093550680E68083AF +:1016C00008951F920F920FB60F92112400000F90F1 +:1016D0000FBE0F901F9018951F920F920FB60F928A +:1016E00011248F93EF93FF93E0EAF8E080818083E9 +:1016F000FF91EF918F910F900FBE0F901F90189553 +:101700009FB7F894A0E5B0E016968C911697897F64 +:1017100016968C931697E0E6F0E080E885838BEBD5 +:10172000868316968C911697846016968C9380818A +:10173000816080839FBF08959FB7F894E82FF0E001 +:10174000E059FF4F60958081682360839FBF0895B3 +:10175000CF93863011F0C0E001C0C8E18091510004 +:1017600081FD0DC09FB7F8948091500082608093F6 +:1017700050009FBF8091510081FFFCCFC1DF6C2FD3 +:10178000636084E490E0E9D460E480E0CF91D4CF5A +:101790008091A82008958091A820813009F4D4C8B0 +:1017A0000895F0D0FC0183818093A820811101C0AD +:1017B000B6C881E008959091AA23892F807697FF7B +:1017C00007C0803491F48091AB2381110EC0C1C851 +:1017D000803459F48091AB23811107C08091B023EC +:1017E0009091B123892B09F0B2C880E008958091CF +:1017F000AC238F770C9435149091B020911102C0D6 +:1018000080E00895E091AD20F091AE200190F0814C +:10181000E02D94818917A0F7E093AB20F093AC20E2 +:10182000228133812E0F3F1FE217F30798F4918135 +:10183000943061F49281891309C09381691306C0C1 +:10184000E093AB20F093AC2081E008959081E90F04 +:10185000F11DEACFE093AB20F093AC20D1CFE09123 +:10186000AD20F091AE200190F081E02D22813381F6 +:101870002E0F3F1FFC014081E40FF11DE217F3071B +:1018800048F48181843031F0853039F08081E80F6F +:10189000F11DF4CF80E090E00895CF0108951F93EB +:1018A000CF93DF93182FA8DF882339F1C091AB20A5 +:1018B000D091AC20CE01D3DFEC01892B41F04C81DB +:1018C0005D816B818A81DED78111F4CF16C0E091F2 +:1018D000AD20F091AE2092818381E92FF82FE10FA6 +:1018E000F11DE10FF11D0190F081E02D0190F081DB +:1018F000E02DDF91CF911F91099480E0DF91CF918E +:101900001F910895EF92FF921F93CF93DF93C82FFB +:1019100060E072DF811102C010E02DC0E091AD20C7 +:10192000F091AE2092818381E92FF82FEC0FF11D09 +:10193000EC0FF11DE080F180D7011696ED91FC913E +:1019400017970995682F8C2F57DF182F882321F3BD +:10195000C091AB20D091AC20CE0181DFEC01892B6E +:1019600021F08A810E945515F7CFD7011296ED918B +:10197000FC9113970995812FDF91CF911F91FF90D3 +:10198000EF9008958091AB209091AC2008950FC7FF +:10199000CF938091B020882311F0C0E008C010924E +:1019A000B0201092B4201092B520CF910895E0910C +:1019B000AD20F091AE200190F081E02D8481C81718 +:1019C00070F78C2F9FDFCF5FF2CFCF938091B02045 +:1019D0008823F1F0C0E0E091AD20F091AE20A0812D +:1019E000B18114968C91C81798F492818381E92F64 +:1019F000F82FEC0FF11DEC0FF11D0190F081E02D9F +:101A00000084F185E02D309709F00995CF5FE3CF91 +:101A1000CF9108950F931F93CF93DF931092B42328 +:101A20001092B5231092B6231092B7231092B823C8 +:101A30001092B9238091AA2387FF07C02091B02379 +:101A40003091B123232B09F482C38076803409F0CE +:101A50003CC1E091AB238E2F90E0FC01E05AF109EC +:101A6000E331F10508F031C1E25FFE4F0C94151728 +:101A700081E08093A020809107209091082080939E +:101A80009B21809107209091082090939C21809128 +:101A9000822180939D2180917F2180939E2180913E +:101AA0006A0080939F2180916B008093A0216091B8 +:101AB000B0237091B1238EE891E201C11092000829 +:101AC0008091AC239091AD23809336089093370892 +:101AD0008091AE238F70809300086091B023709145 +:101AE000B1238AEA91E2C7D68091B0239091B123C5 +:101AF00020910E2030910F208217930709F4F2C233 +:101B000080930E2090930F2045C081E080930920A0 +:101B1000109240088091AC239091AD238093760879 +:101B2000909377088091AE238F70809340086091E6 +:101B3000B0237091B1238BEB93E29DD68091B023BB +:101B40009091B12320910C2030910D2082179307A2 +:101B5000E9F4C8C210920920109240088091AC2389 +:101B60009091AD2380937608909377088091AE236F +:101B70008F70809340086091B0237091B1238BEBFC +:101B800093E279D68091B0239091B12380930C2079 +:101B900090930D2080910A205EC0109268091092E7 +:101BA00069098091AC238093A3209CC28091AC23CF +:101BB0008093240697C2E091AC23F091AD23E830E6 +:101BC000F10508F082C0EF5DFE4F0C94151760E040 +:101BD00080E00E94DE048091AE230E94AB0480E08E +:101BE0003AC060E080E00E94DE048091AE230E9453 +:101BF000AB0481E030C061E081E00E94DE048091AE +:101C0000AE230E94AB048091AF230E94C10482E006 +:101C100022C083E020C084E01EC060E080E00E941B +:101C2000DE048091AE230E94AB0485E014C061E025 +:101C300080E00E94DE048091AE230E94AB0486E027 +:101C40000AC062E080E00E94DE048091AE238068DA +:101C50000E94AB0487E00E94690544C28091AC23D6 +:101C6000809384063FC28091AC239091AD23892B51 +:101C700091F00E94760380E2E8EBFBE2ABEBB5E289 +:101C800001900D928A95E1F781E08093BB250E9437 +:101C90008B030E947603E9E7F0E091E088EDF89489 +:101CA00084BF90836091B0237091B1238AE890E261 +:101CB00006C06091B0237091B12389E890E2DBD532 +:101CC00011C20E948F0481110DC28091AA23982F06 +:101CD000907609F0C9C187FFFBC02091B0233091F5 +:101CE000B1232115310509F4BFC18F7109F09EC0E0 +:101CF0008091AB23863071F0883009F48EC0811159 +:101D0000B3C12230310509F0AFC162E070E084EB6D +:101D100090E2D5CF8091AC239091AD23292F33272A +:101D200022303105A1F060F42130310509F09CC169 +:101D300080911A2090911B20DC016C9170E05BC0B7 +:101D40002330310589F12F30310509F18DC1E09142 +:101D50001A20F0911B202189821708F085C199274C +:101D6000880F991F880F991FE0911C20F0911D206A +:101D7000E80FF91F80819181FC01628173817BD51D +:101D8000E091B223F091B32382E0818335C080914A +:101D90001E2090911F20009709F466C1DC01129665 +:101DA0006D917C91139727C099278130910569F037 +:101DB00038F0029709F058C168E08AE690E208C05E +:101DC00064E070E08CE790E216C067E083E790E2A1 +:101DD000282FAAE5B0E2FC01819190E08D939D93BC +:101DE0008E2F821B8617C0F3660F6E5F609358209C +:101DF00070E088E590E23FD58091B0239091B123C7 +:101E00002091B4233091B5238217930708F06AC15B +:101E10008093B4239093B52365C12130310509F037 +:101E200023C161E070E080EB90E249CF8130C1F5E1 +:101E30008091AB238A3009F017C12130310509F0B8 +:101E400013C18091B020882309F40EC1C091AE2344 +:101E5000D091AF230091AD201091AE20D801ED912B +:101E6000FC918481C81708F0FFC060E08C2FC4DCAF +:101E7000882309F4F9C0DD27CC0FDD1FF80182812A +:101E80009381C80FD91FE881F9810680F781E02D81 +:101E900009958093B22061E070E082EB90E20FCF71 +:101EA000823009F0E1C08091AB238111DDC0223086 +:101EB000310509F0D9C08091AE232DD590E08093F3 +:101EC000A9209093AA2062E070E089EA90E2F7CE20 +:101ED0008F7109F07DC08091AB23833009F4C4C0B9 +:101EE00018F48130A1F0C0C0853019F0893039F183 +:101EF000BBC08091B0239091B123892B09F0B4C06D +:101F000087EF9BE08093B6239093B723EBC080913B +:101F1000B0239091B123892B09F0A6C08091AC2306 +:101F20009091AD23019709F09FC08091B4209091CA +:101F3000B5208D7F8093B4209093B520D3C080913D +:101F4000B0239091B123892B09F08EC091D48823BE +:101F500009F48AC02091AC233091AD233327E0915E +:101F60001A20F0911B20818990E08217930708F4D2 +:101F70007BC00EDD8091AC239091AD238093B02087 +:101F8000882309F4AFC099278150904C880F991F7E +:101F9000880F991F20911C2030911D20820F931FC4 +:101FA0008093AD209093AE20C0E0E091AD20F09101 +:101FB000AE200190F081E02D8481C81708F092C016 +:101FC00060E08C2F6CDC882309F44EC0CF5FEDCF2E +:101FD0008130E9F48091AB238B3009F045C08091CA +:101FE000B0239091B123892B09F03EC08091B0209D +:101FF000882309F439C0C091AE23D091AC238C2F33 +:1020000081DC882389F16D2F8C2F49DC2BC0823035 +:1020100059F58091AB23813019F0833089F024C0C9 +:102020008091B0239091B123892BF1F48091AC235E +:102030009091AD23892BC1F48091AE2373D412C04B +:102040008091B0239091B123892B71F48091AC23BE +:102050009091AD23892B41F48091AE23F6D48091E9 +:10206000AE232CD581113EC08091AA238F7181307F +:10207000D9F58091B020882309F469C0C091AE23BE +:10208000D091AF230091AD201091AE20D801ED91F9 +:10209000FC918481C81708F05AC060E08C2FACDB3B +:1020A000882311F1FE01FF27EE0FFF1FD8011296C2 +:1020B0008D919C911397E80FF91F00811181D80130 +:1020C0001696ED91FC9117970995682F8C2F94DB4C +:1020D000882351F0D8011496ED91FC91159709953C +:1020E000882311F081E034C08091AA238F7182305F +:1020F00071F58091B020882351F1C0E0E091AD20CE +:10210000F091AE20A081B18114968C91C817F8F49B +:1021100092818381E92FF82FEC0FF11DEC0FF11D57 +:1021200000811181D8011696ED91FC9117970995C0 +:10213000682F8C2F61DB882351F0D8011496ED9124 +:10214000FC91159709958111CDCFCF5FD7CF80E056 +:10215000DF91CF911F910F9108951BBEFC0128EDD7 +:1021600024BF608308958091CF0187FDFCCF08953F +:102170001F93CF93DF93C0ECD1E01A858A8761E08B +:102180008BEC91E0EADF1A87DF91CF911F910895E0 +:10219000CF92DF92EF92FF920F931F93CF93DF9333 +:1021A0008C017B016A01DFDFCCECD1E088818860A3 +:1021B0008883B801705FA601C7013DD68881877FFB +:1021C0008883DF91CF911F910F91FF90EF90DF9067 +:1021D000CF900895CF93DF93C82FD62FC4DFACECF8 +:1021E000B1E08C9188608C93EC2FF0E0F05FD083AD +:1021F0008C91877F8C93DF91CF9108950F931F93DC +:10220000CF938C01B0DFC0E0F80161918F018C2F7A +:10221000E1DFCF5FC032C1F7CF911F910F910895D9 +:10222000CF93C82FA0DF20E2C29FC0011124E0ECB1 +:10223000F1E012829183808385E3CF9199CF409121 +:10224000CA01E62FF72F8093CA0184914093CA01F7 +:102250000895E82FF0E0E652F44D80818F3F09F4B5 +:10226000FFCF9FB7F89480818F5F80839FBF0895D1 +:10227000E82FF0E0E652F44D8081811101C0FFCFDC +:102280009FB7F8948081815080839FBF0895CF933A +:10229000C82F80917C21C11105C0882339F081E0CD +:1022A000E7DF04C0811102C081E0D3DFC0937C214D +:1022B000CF910895282F2F70082E000C990B392FDD +:1022C000331F3327331F832F90E0820F911D820F1E +:1022D000911D23E0880F991F2A95E1F7885A9E4D9A +:1022E00008950F93E8ECF4E080818F7D80838081F6 +:1022F0008F7D8083E0E6F1E202E005931092622197 +:102300001092632100E2069300E40693E8E5F1E20F +:1023100000E2069300E40693EAEAF3E214861586E7 +:10232000168617861286138610924D210F910895F6 +:102330000F9385E080934D21E1E6F1E204E00593FF +:10234000E9E5F1E204E005930F9108950F9383E02E +:1023500080934D211092622110926321E0E6F1E218 +:1023600002E006930F910895E091B623F091B72310 +:10237000309709F009940895282F2F70082E000C2B +:10238000990B392F331F3327331F832F90E0820F90 +:10239000911D820F911D029749E0489F9001499F2E +:1023A000300D1124C90189509F4D0895AF92BF92FD +:1023B000DF92EF92FF920F931F93CF93DF93D82E6C +:1023C000DBDFEC018D2D76DF7C01DC011196EC91D9 +:1023D000E770E150E73040F4F0E0EE0FFF1FE45704 +:1023E000FF4D0081118102C008E010E02D813E8187 +:1023F0008B819C814881D7FE4AC0F7016681778135 +:10240000260F371F2D833E8328173907A1F1BC0102 +:10241000621B730B9B01211574E0370738F02FEF17 +:1024200033E0C901B801DAD4281B390B41FF0AC0D7 +:10243000C901B801D3D4AC0191E0452B09F090E07B +:10244000892F01C080E0988180FB91F99883D701A2 +:1024500016961D921C92179712962D933C931397E4 +:1024600029813A818D819E81820F931F14968D93CD +:102470009C93159708C041FF78C04D7F4883168212 +:10248000178212821382F70102E0069385C0D701FA +:102490001296AD90BC90139742FF0FC0E981FA816C +:1024A000B8019CD4B0E4DB9EB001112469587F4D83 +:1024B000AC01CF01820F931FBED42D813E812A0D26 +:1024C0003B1D2D833E838B819C818217930710F4E3 +:1024D0008D839E83F70126813781A216B30609F00A +:1024E00044C02D813E818217930709F43EC0AC01A0 +:1024F000421B530B9A01211554E0350750F02FEF82 +:1025000033E0C901B8016AD4B901681B790BCB016A +:1025100007C0C901B80162D4D901A81BB90BCD010C +:10252000F701128213828017910798F488818460E2 +:102530008883F0E4DF9EC001112489589F4DD701A4 +:1025400014968D939C93159716960D931C9317973D +:102550009ACF49815A812D813E81240F351FF70181 +:1025600024833583868397838ECF888180FF14C030 +:102570008E7F8883EF81F885309771F06D817E8141 +:102580004D2D80E0DF91CF911F910F91FF90EF9043 +:10259000DF90BF90AF900994DF91CF911F910F9181 +:1025A000FF90EF90DF90BF90AF9008950F93CF937F +:1025B000DF9380914D21833029F4D6DEDF91CF91D6 +:1025C0000F918FCE2091492130914A21C091B4239F +:1025D000D091B523C21BD30B61F580914B21909113 +:1025E0004C21820F931F80934B2190934C2120917B +:1025F000B0233091B1238217930721F08091B62048 +:10260000882331F084E080934D21E8E5F1E236C083 +:10261000E091B823F091B923309799F00995882378 +:1026200081F01092492110924A21C091B423D09197 +:10263000B523C034D10528F01092B620C0E4D0E014 +:1026400003C081E08093B620C0936221D0936321C0 +:102650008091492190914A212091B2233091B32356 +:10266000280F391F2093642130936521C80FD91F8B +:10267000C0934921D0934A21E0E6F1E202E00693BB +:10268000DF91CF910F9108950F93CF938091CC0458 +:1026900080FF63C021E02093CC0488E591E2FC0137 +:1026A00000E80693E0E6F1E200E806932093CA040E +:1026B000FC0100E1069380914D21882329F083508D +:1026C000823008F451DE0DDE80915A2190915B2119 +:1026D000089709F044C088E0E9E0F1E2AAEAB3E231 +:1026E00001900D928A95E1F78091C80480628093F1 +:1026F000C8048091C80480628093C8048BD9C82F15 +:10270000811102C015DE2BC08091AA2387FF0DC066 +:1027100010924B2110924C211092492110924A2183 +:1027200082E080934D2142DF1BC08091B0239091C5 +:10273000B123892B11F40ADE13C010924B211092A1 +:102740004C211092492110924A2181E080934D2121 +:10275000E8E5F1E202E0069303C0C0E001C0C1E099 +:102760008C2FCF910F910895CF93CFB7F89481E03C +:102770008EDDEAECF4E080E4808380E28083E1ECAB +:10278000F4E0808181608083A9ECB4E08C91826068 +:102790008C93E8ECF4E08081806480838C9181608C +:1027A0008C93808180688083CFBFCF910895CF9331 +:1027B0001092600080E30E94A80B8091C0048064A6 +:1027C0008093C00481E080936000CFB7F8941092AA +:1027D00059211092612110926921109271218091EA +:1027E000F7208E7F8093F720809100218E7F809349 +:1027F00000216AE170E082E022DD8F3F09F48FE181 +:102800008093FA046BE170E082E019DD8F3F09F4F8 +:102810008FE18093FB048091C00481608093C004A9 +:102820008091C00480688093C0048091C00480615E +:102830008093C00488E591E28093C6049093C70416 +:102840008091C00480628093C0048FEF8093C504A0 +:102850008091C80482608093C80410927C2185E036 +:10286000F8DC82DFCFBFCF9108958093C304089531 +:102870008091C3040895EAEAF3E280879187628732 +:10288000738708951F93CF93DF93162FEA0112DD0C +:10289000FC018181807CD1F5612F6370613019F07A +:1028A00020F080E803C080EC01C080E4C038D1058E +:1028B000E1F050F4C032D105A1F0C034D10599F057 +:1028C0006097C9F491E018C0C11592E0D90779F07A +:1028D000CF3F93E0D90769F0C115D14061F495E08D +:1028E0000BC092E009C093E007C094E005C096E0F9 +:1028F00003C097E001C090E0118226E02083982B6E +:10290000918381818062818381E001C080E0DF91D9 +:10291000CF911F910895CEDCFC01818182FB882735 +:1029200080F90895CF93C82FC5DCFC01818182FF17 +:102930000FC081818B7F81838C2F1EDDFC019081F4 +:1029400090FF06C09E7F90830780F085E02D09955B +:1029500081E0CF910895AF92BF92CF92DF92EF9234 +:10296000FF920F931F93CF93DF93D82EC62E5A0159 +:10297000790102DDEC018D2D9DDC9C01DC011196BD +:102980008C911197807C09F454C011968C91119709 +:10299000807C803C21F011968C9182FD4AC09FB7CB +:1029A000F894888180FF02C09FBF43C08160888304 +:1029B0009FBFA982BA82EB82FC821D821E820F8396 +:1029C000188791E0C11004C0E114F10409F090E00F +:1029D000888190FB81F98B7F8883D7FE02C0F90143 +:1029E00022C0D90111968C911197807C803CC1F452 +:1029F0001196EC91E770E150E73040F4F0E0EE0F13 +:102A0000FF1FE457FF4D6081718102C068E070E0F4 +:102A1000C701E4D1892B21F088818E7F888309C08A +:102A2000F90112821382168217828D2DBFDC81E09C +:102A300001C080E0DF91CF911F910F91FF90EF9047 +:102A4000DF90CF90BF90AF900895EF92FF920F93D9 +:102A5000CF93C82F2FDC7C018C2F8EDCDC01F7019B +:102A600002E005939C9190FF1BC09E7F9C9317965C +:102A7000ED91FC911897309799F0D701C7FF05C0E9 +:102A800016966D917C91179704C012966D917C916A +:102A900013974C2F81E0CF910F91FF90EF90099405 +:102AA000CF910F91FF90EF900895CF93C82FCDDF76 +:102AB0008C2F00DCFC011182CF9108950F93CF93EE +:102AC000C82FF8DBFC0181818460818301E00693DB +:102AD0008C2FBBDF81E0CF910F9108951F920F9251 +:102AE0000FB60F9211240F932F933F934F935F9341 +:102AF0006F937F938F939F93AF93BF93EF93FF93C6 +:102B00008091CB0487FF08C080E88093CA040E94AC +:102B1000E50C0E941A047EC08091CB0482FF18C08D +:102B200084E08093CA048091602186FF73C0809105 +:102B3000CC0481FD6FC0A8DD81116CC080914D2156 +:102B4000813011F403DC66C0843009F063C021C019 +:102B50008091CB0481FF26C082E08093CA048091DB +:102B6000582186FF57C08091CC0481FD53C08CDD75 +:102B7000811150C080914D21823041F484E08093D6 +:102B80004D21E8E5F1E202E0069344C0833009F00C +:102B900041C0E1E6F1E204E00593E9E5F1E204E099 +:102BA000059338C08091CB0484FF1DC080E18093E1 +:102BB000CA040E94C80C1092C3041092592196E0D6 +:102BC0009093582183E4809359211092612190932E +:102BD00060218093612189E091E280935C21909350 +:102BE0005D217FDB17C08091CB0486FF08C080E4A5 +:102BF0008093CA0480E04BDB0E9418040BC08091D4 +:102C0000CB0485FF07C080E28093CA0481E03FDBEC +:102C10000E941904FF91EF91BF91AF919F918F9105 +:102C20007F916F915F914F913F912F910F910F90F5 +:102C30000FBE0F901F9018951F920F920FB60F9214 +:102C400011240F931F932F933F934F935F936F9391 +:102C50007F938F939F93AF93BF93CF93DF93EF9324 +:102C6000FF938091CC0481FF1AC082E08093CC0452 +:102C70008091C5048195880FE8E5F1E2E81BF10930 +:102C8000208131812855314283E0369527958A95F8 +:102C9000E1F7822F869520FD06C0C0E005C0F4DC78 +:102CA000882319F386C0C0E8C80F8C2F03DBFC0112 +:102CB000208125FF7EC000E20693C11174C080917F +:102CC0004D21843019F450DB0CDB73C000915A2184 +:102CD00010915B218091B4239091B523C09149213B +:102CE000D0914A2198012C0F3D1F8217930718F4A9 +:102CF0008C010C1B1D0B8091B2239091B323A80172 +:102D000069E071E28C0F9D1F96D0C00FD11FC09358 +:102D10004921D0934A210034110569F480914B2157 +:102D200090914C218C0F9D1F2091B0233091B123A5 +:102D30008217930788F0C093B423D093B523E09112 +:102D4000B823F091B923309729F00995811102C079 +:102D5000EFDA2FC0FBDA2DC08091B4239091B52318 +:102D6000C817D907D9F4E091B823F091B923309767 +:102D700079F30995882361F320914B2130914C21FF +:102D80008091492190914A21820F931F80934B217A +:102D900090934C211092492110924A21E8E5F1E2EA +:102DA00002E0069306C0C03811F400DC02C08C2F8C +:102DB000FDDAFF91EF91DF91CF91BF91AF919F919C +:102DC0008F917F916F915F914F913F912F911F91C3 +:102DD0000F910F900FBE0F901F901895AA1BBB1B51 +:102DE00051E107C0AA1FBB1FA617B70710F0A61B0B +:102DF000B70B881F991F5A95A9F780959095BC012C +:102E0000CD01089597FB072E16F4009406D077FDA8 +:102E100008D0E4DF07FC05D03EF4909581959F4FE4 +:102E20000895709561957F4F0895EE0FFF1F0590EF +:102E3000F491E02D0994FB01DC0102C001900D9298 +:102E400041505040D8F70895FB01DC0101900D92EC +:0A2E50000020E1F70895F894FFCF89 +:102E5A0040000CE02E0AFFFFFF01FF5580008000B2 +:102E6A00D10BCB0BDB0BC80B000044202020000049 +:102E7A0028202420102000000902190001010080E6 +:102E8A00FA0904000001FFFFFF0007058101FF03A3 +:102E9A00010000001201000200000040EB0394BA96 +:102EAA00000201020001000000030000000000000F +:102EBA00000000000000000000004C6162726164C2 +:102ECA006F72004573706F54656B00000403090448 +:102EDA006465627567313233000207001000200012 +:0A2EEA004000800000010002FF0319 +:00000001FF diff --git a/Android_App/app/src/main/assets/font/Greek_uc_delta.svg b/Android_App/app/src/main/assets/font/Greek_uc_delta.svg new file mode 100644 index 000000000..1c6850e5a --- /dev/null +++ b/Android_App/app/src/main/assets/font/Greek_uc_delta.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Android_App/app/src/main/assets/font/Readme.txt b/Android_App/app/src/main/assets/font/Readme.txt new file mode 100644 index 000000000..7d479d2da --- /dev/null +++ b/Android_App/app/src/main/assets/font/Readme.txt @@ -0,0 +1,12 @@ +Note: this readme and the .svg files in this directory are excluded from the assets that are included in the app. This is done via the aaptOptions in /app/build.gradle.kts + +waveform-glyphs3 resources: + +https://www.sinwaver.com/ (have to hack it a bit to get a wider stroke) +https://boxy-svg.com/app/ (handy online svg editor) +https://10015.io/tools/svg-stroke-to-fill-converter ( apply to the waveform from sinwaver) + +greek delta from wiki commons https://commons.wikimedia.org/wiki/File:Greek_uc_delta.svg + +load the .svg's into https://icomoon.io/app/#/select to generate the font + diff --git a/Android_App/app/src/main/assets/font/greek_delta.ttf b/Android_App/app/src/main/assets/font/greek_delta.ttf new file mode 100644 index 0000000000000000000000000000000000000000..afac6271541625038a829cca4078ba7c6e13acc3 GIT binary patch literal 1168 zcmb7D&ubGw7=5$5Nz+8yh{03|GJ?`xx=l^77JKki?4hVpdQxxI>hzI=( zs^0u33f_9~;K`E*^&ogFh(hruC|+uOyF0PXNjhO>-h1c?$Bl*sQmRy*LFCy(Zg)9N+mO`IX`k~f>SRX1lAE|Tw&Uyg*4 z^F|ubCde-|-A*?{K)%SK(DG{*rf{A7Ciw~1>ITSQl>9Ea^eoptSuC->_L!bO0>9ni zKG}?@zJzW-JVT1>FSU16wv$4)=zl3j`A2;P1f#|W8Y^qS{6ZX};{K~KgSL`!I(WOM zL`6*I#Ga6Ok$?E+y_nEm9C%aW^Pfpx8$;Q@-P?8Vk1zg2E;;Mh-;WBB%V3V(_)VkT z#Em&gWHRb`0?T*Z@TQNTIO#ThA#D9?fOVFECQ9px*cccrk#oL36#)Nd(l z5WiJ8#aCNaI8FVj!daZfujtN=Q7V!v3D#I^S7DvHrLaN#N#PVudzI*rS7+{KE17_vjNC#(x1qG^9xY literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/assets/font/mm.svg b/Android_App/app/src/main/assets/font/mm.svg new file mode 100644 index 000000000..c53dc66d3 --- /dev/null +++ b/Android_App/app/src/main/assets/font/mm.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Android_App/app/src/main/assets/font/pulse.svg b/Android_App/app/src/main/assets/font/pulse.svg new file mode 100644 index 000000000..cb2de128c --- /dev/null +++ b/Android_App/app/src/main/assets/font/pulse.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Android_App/app/src/main/assets/font/settings-gear-svgrepo-com.svg b/Android_App/app/src/main/assets/font/settings-gear-svgrepo-com.svg new file mode 100644 index 000000000..7d6026be4 --- /dev/null +++ b/Android_App/app/src/main/assets/font/settings-gear-svgrepo-com.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/assets/font/svg(2)-converted.svg b/Android_App/app/src/main/assets/font/svg(2)-converted.svg new file mode 100644 index 000000000..105fb5a34 --- /dev/null +++ b/Android_App/app/src/main/assets/font/svg(2)-converted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Android_App/app/src/main/assets/font/waveform-glyphs3.ttf b/Android_App/app/src/main/assets/font/waveform-glyphs3.ttf new file mode 100644 index 0000000000000000000000000000000000000000..092b537f6f7b32bec917e5979fa5f7f0aa12f162 GIT binary patch literal 2532 zcmb7GTW=dh6h5=F>)rMGvTLusPU<*ouj5T~_azsSrYX=?I2Tp)5?UhKx~c0Fk~neF zo5VwrsBS{nOh3B#!dIN@-;YdlhBYOO^Qx zr})G7zC-yufN*oJTsoP*{)PY`ny4R`L&Eo|^exJVQBKb-te$U13FSAjG3TqZCHfn; z6XlOl4lR__ ztM}x0$P<~_Z7KxA-dc76+^4+5)mvbD(I}<^m^W7AsH^wXv5Er^L&$qU0uFx!%=>ix z@%p+m%DfK_ChNZ#JdWEuF9Cv9!3Kw(Ie@|E923{>e>q$+0Dl|pc=YeXJ=1Z2@|vY3 zu^Egc`zh8WR&soKnS5BQ^{myDwH5w0R(M3|<41IPd6~Y0%`#5q_!W{kUj>B#5j|p~ zVSUQ(Asdf{On?|sBjGmKC&=JV=NVwV)383e#R^p$lh~P*NZ&ShB{WU5BhjXp3VLfn zmn13J9#MB0F;$biilT^WkaAvcT+;%X7gPRpz}N2gW)z?8)5GD;ZOzsTW64O`FGl=Y zINTNAW+^)L_eQmlz>P+`rqYpu;qUa*hf>Zq;w=-sy`wkJrib?^ydd^k&6fs-nk1eO zDtN7s*wplV+G?46tyvCJN+_pEQbuh`v`&xg*#F6;J~K^;&mW4%r$=`j*w(}AiXyj% zrR&-9<&2T^Q0G{REHBax+(!x`gu#R{I0~QPo?{)!4(U% z9>L~l>iE#ac-2fM&1xeShA~DG;oHpk-s1E=zsSjf-Gh-3FA!eN8vbEDJB)z|vVP>) z@jXU_=#kx%`Zhky8@xiy8B!^QvZ&)jd zI*?6?`DE-UDP(No9*wQ%rhaTV=%1MA$4YJvg)!b3ql5**Q6B#|nnOi|T}1KV&Quh3X07!? z8XNdzz#ZWP4)ir`th7zrw9>V^PsHQK=G={#XW5#3cr3W%Pf#$^SnfRtJD|}!Z#};J z>^64_j;UKp>|2VrLgU7-s~J_-Z^(F~<5zSKDsaSx&Wm?@0`|fK@+)^2ZP}TV;B&lR zSZR231h)ymm##0uzSS<~aKtSaQ{-QEF^~9;iv>KxeJ=JO|CWor&*~J1xVZ_BA. This is done for portability +# reasons because not all systems place things in SDL3/ (see FreeBSD). + +#============================================================================= +# Copyright 2003-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# Modified by sfalexrog to accomodate Android builds. SDL3_LIBRARY +# will be a target which you'll want to link against. It will be built +# statically, mostly because that would save you from needing to +# also add SDL3MAIN_LIBRARY to your target, and will not require you to +# add SDL_android_main.c to your source sets. +# You can override this behavior by changing this file, but as far as +# I know having multiple shared libraries don't really give you any +# benefit on Android. +# +# Modified by brentfpage: SDL2->SDL3 +# specified set(SDL_STATIC ON) in the if(ANDROID) block +# also, in app/src/main/cpp/CMakeLists.txt, instead of using the convenience +# variable ${SDL3_LIBRARY} in target_link_libraries(native-plasma ... +# ${SDL3_LIBRARY}$ ) I hard-coded the value SDL3-static, as in +# target_link_libraries(native-plasma ... SDL3-static ) + +if (ANDROID) + set(_SDL_SOURCE_SEARCH_PATHS + SDL + deps/SDL + external/SDL + libs/SDL + ) + + # This is a hack to allow find_path to actually search for headers and sources + set(_SDL_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ${CMAKE_FIND_ROOT_PATH_MODE_INCLUDE}) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE "NEVER") + set(SDL_STATIC ON) + + find_path(_SDL3_SOURCE_DIR SDL.c + HINTS + ${_SDL_SOURCE_SEARCH_PATHS} + PATH_SUFFIXES src + PATHS ${_SDL_SOURCE_SEARCH_PATHS} + ) + + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ${_SDL_CMAKE_FIND_ROOT_PATH_MODE_INCLUDE}) + + if (${_SDL3_SOURCE_DIR} STREQUAL "_SDL3_SOURCE_DIR-NOTFOUND") + message(FATAL_ERROR "Could not find SDL3 source directory, cannot continue") + endif() + + get_filename_component(_SDL3_PROJECT_DIR ${_SDL3_SOURCE_DIR} DIRECTORY) + + add_subdirectory(${_SDL3_PROJECT_DIR}) + + # You can't directly specify a target in target_link_libraries + # in ${}, but you can't specify a variable name without ${}, + # so here's a little hack to make ${target_name} behave like + # it should. + set(SDL3_LIBRARY SDL3 SDL3main) + set(SDL3_INCLUDE_DIR ${_SDL3_PROJECT_DIR}/include) + + +else() + + SET(SDL3_SEARCH_PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local + /usr + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt + ) + + FIND_PATH(SDL3_INCLUDE_DIR SDL.h + HINTS + $ENV{SDL3DIR} + PATH_SUFFIXES include/SDL3 include + PATHS ${SDL3_SEARCH_PATHS} + ) + + FIND_LIBRARY(SDL3_LIBRARY_TEMP + NAMES SDL3 + HINTS + $ENV{SDL3DIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL3_SEARCH_PATHS} + ) + + IF(NOT SDL3_BUILDING_LIBRARY) + IF(NOT ${SDL3_INCLUDE_DIR} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL3main. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL3main for compatibility even though they don't + # necessarily need it. + FIND_LIBRARY(SDL3MAIN_LIBRARY + NAMES SDL3main + HINTS + $ENV{SDL3DIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL3_SEARCH_PATHS} + ) + ENDIF(NOT ${SDL3_INCLUDE_DIR} MATCHES ".framework") + ENDIF(NOT SDL3_BUILDING_LIBRARY) + + # SDL3 may require threads on your system. + # The Apple build may not need an explicit flag because one of the + # frameworks may already provide it. + # But for non-OSX systems, I will use the CMake Threads package. + IF(NOT APPLE) + FIND_PACKAGE(Threads) + ENDIF(NOT APPLE) + + # MinGW needs an additional library, mwindows + # It's total link flags should look like -lmingw32 -lSDL3main -lSDL3 -lmwindows + # (Actually on second look, I think it only needs one of the m* libraries.) + IF(MINGW) + SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") + ENDIF(MINGW) + + IF(SDL3_LIBRARY_TEMP) + # For SDL3main + IF(NOT SDL3_BUILDING_LIBRARY) + IF(SDL3MAIN_LIBRARY) + SET(SDL3_LIBRARY_TEMP ${SDL3MAIN_LIBRARY} ${SDL3_LIBRARY_TEMP}) + ENDIF(SDL3MAIN_LIBRARY) + ENDIF(NOT SDL3_BUILDING_LIBRARY) + + # For OS X, SDL3 uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + IF(APPLE) + SET(SDL3_LIBRARY_TEMP ${SDL3_LIBRARY_TEMP} "-framework Cocoa") + ENDIF(APPLE) + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + IF(NOT APPLE) + SET(SDL3_LIBRARY_TEMP ${SDL3_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(NOT APPLE) + + # For MinGW library + IF(MINGW) + SET(SDL3_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL3_LIBRARY_TEMP}) + ENDIF(MINGW) + + # Set the final string here so the GUI reflects the final state. + SET(SDL3_LIBRARY ${SDL3_LIBRARY_TEMP} CACHE STRING "Where the SDL3 Library can be found") + # Set the temp variable to INTERNAL so it is not seen in the CMake GUI + SET(SDL3_LIBRARY_TEMP "${SDL3_LIBRARY_TEMP}" CACHE INTERNAL "") + ENDIF(SDL3_LIBRARY_TEMP) + + INCLUDE(FindPackageHandleStandardArgs) + + FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL3 REQUIRED_VARS SDL3_LIBRARY SDL3_INCLUDE_DIR) +endif() diff --git a/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp b/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp new file mode 100644 index 000000000..d9f362699 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp @@ -0,0 +1,214 @@ +#include "i2cdecoder.h" + +using namespace i2c; + +i2cDecoder::i2cDecoder(o1buffer* sda_in, o1buffer* scl_in) : + m_serialBuffer{I2C_BUFFER_LENGTH}, + sda(sda_in), + scl(scl_in) +{ +} + +void i2cDecoder::reset() +{ + LOGI("Resetting I2C"); + + if (sda->mostRecentAddress != scl->mostRecentAddress) + { + // Perhaps the data could be saved, but just resetting them seems much safer + sda->reset(true); + scl->reset(true); + } + + serialPtr_bit = sda->mostRecentAddress * 8; + + { + std::lock_guard lock(mutex); + + m_serialBuffer.clear(); + } +} + + +void i2cDecoder::run() +{ + if(!m_decode_on) + return; + + while (serialDistance(sda) > SERIAL_DELAY * sda->m_samples_per_second * 8) + { + updateBitValues(); + runStateMachine(); + serialPtr_bit ++; + if (serialPtr_bit >= (sda->m_bufferLen * 8)) + serialPtr_bit -= (sda->m_bufferLen * 8); + } +} + +int i2cDecoder::serialDistance(o1buffer* buffer) +{ + int back_bit = buffer->mostRecentAddress * 8; + int bufferEnd_bit = buffer->m_bufferLen * 8; + if (back_bit >= serialPtr_bit) + return back_bit - serialPtr_bit; + else + return bufferEnd_bit - serialPtr_bit + back_bit; +} + +void i2cDecoder::updateBitValues(){ + previousSdaValue = currentSdaValue; + previousSclValue = currentSclValue; + + int coord_byte = serialPtr_bit/8; + int coord_bit = serialPtr_bit - (8*coord_byte); + unsigned char dataByteSda = sda->get(coord_byte); + unsigned char dataByteScl = scl->get(coord_byte); + unsigned char mask = (0x01 << coord_bit); + currentSdaValue = dataByteSda & mask; + currentSclValue = dataByteScl & mask; +} + +void i2cDecoder::runStateMachine() +{ + edge sdaEdge = edgeDetection(currentSdaValue, previousSdaValue); + edge sclEdge = edgeDetection(currentSclValue, previousSclValue); + + if ((sdaEdge == edge::rising) && (sclEdge == edge::falling)) // INVALID STATE TRANSITION + { + state = transmissionState::unknown; + LOGW("Dumping I2C state and aborting..."); + for (int i=31; i>=0; i--) + LOGI("%02x\t%02x", sda->get(serialPtr_bit/8 - i) & 0xFF, scl->get(serialPtr_bit/8 - i) & 0xFF); + throw std::runtime_error("unknown i2c transmission state"); + return; + } + + if ((sdaEdge == edge::rising) && (sclEdge == edge::held_high)) // START + { + stopCondition(); + return; + } + + if ((sdaEdge == edge::falling) && (sclEdge == edge::held_high)) // STOP + { + startCondition(); + return; + } + + switch (state) + { + case transmissionState::idle: + return; + case transmissionState::address: + decodeAddress(sdaEdge, sclEdge); + break; + case transmissionState::data: + decodeData(sdaEdge, sclEdge); + break; + } +} + +edge i2cDecoder::edgeDetection(uint8_t current, uint8_t prev) +{ + if (current && prev) + return edge::held_high; + if (!current && !prev) + return edge::held_low; + if (current && !prev) + return edge::rising; + if (!current && prev) + return edge::falling; + + throw std::runtime_error("i2c Edge Detection critical failure"); +} + +void i2cDecoder::decodeAddress(edge sdaEdge, edge sclEdge) +{ + // Read in the next bit. + if (sclEdge == edge::rising && sdaEdge == edge::held_high && currentBitIndex++ < addressBitStreamLength) + currentBitStream = (currentBitStream << 1) | 0x0001; + else if (sclEdge == edge::rising && sdaEdge == edge::held_low && currentBitIndex++ < addressBitStreamLength) + currentBitStream = (currentBitStream << 1) & 0xFFFE; + else + return; + + if (currentBitIndex == addressBitStreamLength) + { + LOGI("Finished Address Decode"); + if (currentBitStream & 0b0000000000000010) + m_serialBuffer.insert("READ: "); + else + m_serialBuffer.insert("WRITE: "); + + m_serialBuffer.insert_hex((uint8_t)((currentBitStream & 0b0000000111111100) >> 2)); + m_serialBuffer.insert(' '); + + if (currentBitStream & 0b0000000000000001) + m_serialBuffer.insert("(NACK)"); + + consoleStateInvalid = true; + + // Prepare for next bit + currentBitIndex = 0; + currentBitStream = 0x0000; + state = transmissionState::data; + } +} + +void i2cDecoder::decodeData(edge sdaEdge, edge sclEdge) +{ + // Read in the next bit. + if (sclEdge == edge::rising && sdaEdge == edge::held_high && currentBitIndex++ < dataBitStreamLength) + currentBitStream = (currentBitStream << 1) | 0x0001; + else if (sclEdge == edge::rising && sdaEdge == edge::held_low && currentBitIndex++ < dataBitStreamLength) + currentBitStream = (currentBitStream << 1) & 0xFFFE; + else + return; + + if (currentBitIndex == dataBitStreamLength) + { + LOGI("Finished Data byte Decode"); + + m_serialBuffer.insert_hex((uint8_t)((currentBitStream & 0b0000000111111110) >> 1)); + m_serialBuffer.insert(' '); + + if (currentBitStream & 0b0000000000000001) + m_serialBuffer.insert("(NACK)"); + + consoleStateInvalid = true; + + // Prepare for next bit + currentBitIndex = 0; + currentBitStream = 0x0000; + } +} + +void i2cDecoder::startCondition() +{ + currentBitIndex = 0; + currentBitStream = 0x0000; + state = transmissionState::address; + LOGI("I2C START"); +} + +void i2cDecoder::stopCondition() +{ + state = transmissionState::idle; + m_serialBuffer.insert('\n'); + LOGI("I2C STOP"); +} + +char * i2cDecoder::getString() +{ + memcpy(convertedStream_string, m_serialBuffer.begin(), sizeof(char) * m_serialBuffer.size()); + convertedStream_string[m_serialBuffer.size()] = '\0'; + return convertedStream_string; +} + +void i2cDecoder::setIsDecoding(bool new_decode_on) +{ + if(new_decode_on && !m_decode_on) + m_serialBuffer.clear(); + reset(); + m_decode_on = new_decode_on; +} diff --git a/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.h b/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.h new file mode 100644 index 000000000..7e96f88b3 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.h @@ -0,0 +1,82 @@ +#ifndef I2CDECODER_H +#define I2CDECODER_H + +#include "o1buffer.h" +#include "isobufferbuffer.h" +#include "logging_internal.h" + +#include + +#define SERIAL_BUFFER_LENGTH 8192 + + +namespace i2c +{ + +enum class transmissionState: uint8_t +{ + unknown, + idle, + address, + data +}; + +enum class edge: uint8_t +{ + rising, + falling, + held_high, + held_low +}; + +constexpr uint8_t addressBitStreamLength = 9; +constexpr uint8_t dataBitStreamLength = 9; +constexpr uint32_t I2C_BUFFER_LENGTH = 4096; +constexpr double SERIAL_DELAY = 0.01; + +class i2cDecoder +{ + char convertedStream_string[SERIAL_BUFFER_LENGTH + 1]; + +public: + explicit i2cDecoder(o1buffer* sda_in, o1buffer* scl_in); + // misc + o1buffer* sda; + o1buffer* scl; + isoBufferBuffer m_serialBuffer; + std::mutex mutex; + + // State vars + uint8_t currentSdaValue = 0; + uint8_t previousSdaValue = 0; + uint8_t currentSclValue = 0; + uint8_t previousSclValue = 0; + uint64_t serialPtr_bit = 0; + transmissionState state = transmissionState::unknown; + bool consoleStateInvalid; + + // Data Transmission + uint8_t currentBitIndex = 0; + uint16_t currentBitStream; + + // Member functions + void updateBitValues(); + void runStateMachine(); + void run(); + int serialDistance(o1buffer* buffer); + edge edgeDetection(uint8_t current, uint8_t prev); + void decodeAddress(edge sdaEdge, edge sclEdge); + void decodeData(edge sdaEdge, edge sclEdge); + void startCondition(); + void stopCondition(); + void reset(); + + void setIsDecoding(bool new_decode_on); + char * getString(); + + bool m_decode_on = false; +}; + +} // Namespace i2c + +#endif // UARTSTYLEDECODER_H diff --git a/Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.cpp b/Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.cpp new file mode 100644 index 000000000..542b5afd9 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.cpp @@ -0,0 +1,101 @@ +#include "isobufferbuffer.h" +#include +#define LOG_TAG "librador" +#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG, __VA_ARGS__) + +/* isoBufferBuffer is implemented as two consecutive, duplicate, + * ring buffers. the effect of this is that we are able to hand + * out pointers to pieces of contiguous memory representing the + * last N inserted elements (for some N <= capacity()) even + * when we looped back to the begining of the ring buffer less + * than N insertions ago + * + * There are some differences with the original implementation + * functionality-wise. + * Where the original implementation allowed queries half as + * long as the length passed in, and allocated a buffer 1.5 times + * the length passed in, this version allows queries of length up + * to the length passed into the constructor and allocates a + * buffer 2 times the length passed in. + * Overall, this means that in contrast to the original + * implementation which only allowed queries up to a third as + * long as the allocated buffer, we can now do queries as long as + * half of the allocated buffer, which is a notable improvement. + */ + +isoBufferBuffer::isoBufferBuffer(uint32_t length) + : m_data(std::make_unique(length*2)) + , m_capacity(length) +{ +} + +// Adds a character to the end of the buffer +void isoBufferBuffer::insert(char c) +{ + char* dataPtr = m_data.get(); + + // Add character to first half of the buffer + dataPtr[m_top] = c; + // Then to the second + dataPtr[m_top+m_capacity] = c; + + // Loop the buffer index if necessary and update size accordingly + m_top = (m_top + 1) % m_capacity; + m_size = std::min(m_size + 1, m_capacity); +} + +void isoBufferBuffer::insert(char const * s) +{ + while (*s != '\0') + insert(*s++); +} + +void isoBufferBuffer::insert(std::string const & s) +{ + for (char c : s) + insert(c); +} + +void isoBufferBuffer::insert_hex(uint8_t x) +{ + char str[5]; + snprintf(str, sizeof str, "0x%02hhx", x); + insert((char const *)str); +} + +char const* isoBufferBuffer::query(uint32_t count) const +{ + if (count > m_capacity) + LOGF("isoBufferBuffer::query : you may not request more items than the capacity of the buffer"); + + if (count > m_size) + LOGF("isoBufferBuffer::query : you may not request more items than inserted"); + + return end() - count; +} + +void isoBufferBuffer::clear() +{ + m_top = 0; + m_size = 0; +} + +char const * isoBufferBuffer::begin() const +{ + return m_data.get() + m_top - m_size + m_capacity; +} + +char const * isoBufferBuffer::end() const +{ + return m_data.get() + m_top + m_capacity; +} + +uint32_t isoBufferBuffer::size() const +{ + return m_size; +} + +uint32_t isoBufferBuffer::capacity() const +{ + return m_capacity; +} diff --git a/Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.h b/Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.h new file mode 100644 index 000000000..2d3bf4b3e --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/isobufferbuffer.h @@ -0,0 +1,53 @@ +#ifndef ISOBUFFERBUFFER_H +#define ISOBUFFERBUFFER_H + +#include +#include +#include + +/** @file isobufferbuffer.h + * @brief This module implements a data structure that allows + * insertion of single characters and a view of the last N + * inserted characters in constant time. + * + * To obtain such complexity, a double ring buffer is used. + * That is, two identical ring buffers are mantained adjacent + * in memory. If we always return a pointer to the beginning of a + * range that ends in the second buffer, we will always return a + * valid address(*), even when the requested length is greater + * than the current position being inserted into in the buffer. + * + * (*) By valid address I mean that both the addresses that + * represent the beginning and end of the requested query result + * are within the allocated buffer. + */ +class isoBufferBuffer +{ +public: + isoBufferBuffer(uint32_t length); + ~isoBufferBuffer() = default; + + void insert(char c); + void insert(char const * s); + void insert(std::string const & s); + void insert_hex(uint8_t x); + + char const * query(uint32_t length) const; + // TODO?: add ability to get a copy of the content + // (e.g. return std::string or Qstring) + + void clear(); + + char const * begin() const; + char const * end() const; + + uint32_t size() const; + uint32_t capacity() const; +private: + std::unique_ptr m_data; + uint32_t m_capacity; + uint32_t m_size = 0; + uint32_t m_top = 0; +}; + +#endif // ISOBUFFERBUFFER_H diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.cpp b/Android_App/app/src/main/cpp/deps/librador/librador.cpp new file mode 100644 index 000000000..1964dc57e --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/librador.cpp @@ -0,0 +1,406 @@ +#include "librador.h" +#include "librador_internal.h" +#include "logging_internal.h" + +#define _USE_MATH_DEFINES + +#include +#include +#include +#include + +JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *env, jobject thisobject, jboolean is_plugged_in, jint file_descriptor, jboolean bootloader_mode) +{ + if(!internal_librador_object) + { + librador_init(); + } + internal_librador_object->usb_driver->respondToStartupOrUsbStateChange((bool) is_plugged_in, (int) file_descriptor, (bool) bootloader_mode); + return; +} + +JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeInitiateFirmwareFlash(JNIEnv *env, jobject thisobject) +{ + internal_librador_object->usb_driver->initiateFirmwareFlash(); + return; +} + +Librador::Librador() +{ + usb_driver = new usbCallHandler(LABRADOR_VID, LABRADOR_PID); +} + +int librador_init(){ + if(internal_librador_object){ + //Object already initialised + return 1; + } + + internal_librador_object = new Librador(); + if(!internal_librador_object){ + //Object initialisation failed + return -1; + } else { + //good, fresh initialisation + return 0; + } +} + +int librador_exit(){ + CHECK_API_INITIALISED + if(!internal_librador_object){ + //Object not yet initialised + return 1; + } + + delete internal_librador_object; + internal_librador_object = nullptr; + //Object deleted + return 0; +} + +int librador_avr_debug(){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->avrDebug(); +} + +std::vector * librador_get_analog_data(int channel, double timeWindow_seconds, int numToGet, double delay_seconds, int filter_mode) +{ + VECTOR_API_INIT_CHECK + VECTOR_USB_INIT_CHECK + + double samples_per_second = internal_librador_object->usb_driver->get_samples_per_second(); + + if(samples_per_second == 0){ + return nullptr; + } + + double interval_samples = timeWindow_seconds * samples_per_second / (numToGet-1); + int delay_samples = round(delay_seconds * samples_per_second); +// int numToGet = round(timeWindow_seconds * samples_per_second)/interval_samples; + + return internal_librador_object->usb_driver->getMany_double(channel, numToGet, interval_samples, delay_samples, filter_mode); +} + +// int librador_setTriggerType(int channel, o1buffer::TriggerType trigger_type) +// { +// CHECK_API_INITIALISED +// return internal_librador_object->usb_driver->setTriggerType(channel, trigger_type); +// } + +std::vector librador_get_time_array(double delay, double timeWindow_seconds, int n_samples) { + std::vector time_array(n_samples,0); + double sample_period = timeWindow_seconds / (n_samples - 1); + double* data = time_array.data(); + for(int i=0; i < n_samples; i++) { + data[i] = -delay - i * sample_period; + } + return time_array; +} + + +std::vector * librador_get_digital_data(int channel, double timeWindow_seconds, int numToGet, double delay_seconds){ + VECTOR_API_INIT_CHECK + VECTOR_USB_INIT_CHECK + + double subsamples_per_second = internal_librador_object->usb_driver->get_samples_per_second() * 8; + + if(subsamples_per_second == 0){ + return nullptr; + } + + double interval_subsamples = timeWindow_seconds * subsamples_per_second / (numToGet-1); + int delay_subsamples = round(delay_seconds * subsamples_per_second); +// int numToGet = round(timeWindow_seconds * subsamples_per_second)/interval_subsamples; + + LIBRADOR_LOG(LOG_DEBUG, "interval_subsamples = %d\ndelay_subsamples = %d\nnumToGet=%d\n", interval_subsamples, delay_subsamples, numToGet); + + return internal_librador_object->usb_driver->getMany_singleBit(channel, numToGet, interval_subsamples, delay_subsamples); +} + + +std::vector * librador_get_analog_data_sincelast(int channel, double timeWindow_max_seconds, double sample_rate_hz, double delay_seconds, int filter_mode) +{ + VECTOR_API_INIT_CHECK + VECTOR_USB_INIT_CHECK + + double samples_per_second = internal_librador_object->usb_driver->get_samples_per_second(); + + if(samples_per_second == 0){ + return nullptr; + } + + int interval_samples = round(samples_per_second / sample_rate_hz); + int feasible_window_end = round(delay_seconds * samples_per_second); + int feasible_window_begin = round((delay_seconds + timeWindow_max_seconds) * samples_per_second); + + return internal_librador_object->usb_driver->getMany_sincelast(channel, feasible_window_begin, feasible_window_end, interval_samples, filter_mode); + +} + +int librador_update_signal_gen_settings(int channel, unsigned char *sampleBuffer, int numSamples, double usecs_between_samples, double amplitude_v, double offset_v){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + int error = internal_librador_object->usb_driver->update_function_gen_settings(channel, sampleBuffer, numSamples, usecs_between_samples, amplitude_v, offset_v); + if(error){ + return error-1000; + } else return internal_librador_object->usb_driver->send_function_gen_settings(channel); +} + +int librador_set_power_supply_voltage(double voltage){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->set_psu_voltage(voltage); +} + +int librador_set_device_mode(int mode){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->set_device_mode(mode); +} + +int librador_set_oscilloscope_gain(double gain){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->set_gain(gain); +} + +int librador_set_paused(int channel, bool is_paused){ + CHECK_API_INITIALISED + return internal_librador_object->usb_driver->setPaused(channel, is_paused); +} + +bool librador_get_paused(int channel){ + CHECK_API_INITIALISED + return internal_librador_object->usb_driver->getPaused(channel); +} + +int librador_set_digital_out(int channel, bool state_on){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + static uint8_t channelStates[4] = {0, 0, 0, 0}; + channel--; + if((channel < 0) || (channel > 3)){ + return -1000; //Invalid Channel + } + channelStates[channel] = state_on ? 1 : 0; + + return internal_librador_object->usb_driver->set_digital_state((channelStates [0] | channelStates[1] << 1 | channelStates[2] << 2 | channelStates[3] << 3)); +} + +int librador_reset_device(){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->reset_device(false); +} + +int librador_jump_to_bootloader(){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->reset_device(true); +} + +uint16_t librador_get_device_firmware_version(){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->get_firmware_version(); +} + +uint8_t librador_get_device_firmware_variant(){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return internal_librador_object->usb_driver->get_firmware_variant(); +} + +int round_to_log2(double in){ + //Round down to the nearest power of 2. + return round(pow(2, floor(log2(in)))); +} + +unsigned char generator_sin(double x) +{ + //Offset of 1 and divided by 2 shifts range from -1:1 to 0:1. We've got to return an unsigned char, after all! + return (unsigned char)round(255.0 * ((sin(x)+1)/2)); +} + +unsigned char generator_square(double x) +{ + return (x > M_PI) ? 255 : 0; +} + +unsigned char generator_sawtooth(double x) +{ + return round(255.0 * (x/(2.0*M_PI))); +} + +unsigned char generator_triangle(double x) +{ + if(x <= M_PI){ + return round(255.0 * (x/M_PI)); + } else { + return round(255.0 * (1 -((x - M_PI)/M_PI))); + } +} + +int send_convenience_waveform(int channel, double frequency_Hz, double amplitude_v, double offset_v, unsigned char (*sample_generator)(double)) +{ + if((amplitude_v + offset_v) > 9.6){ + return -1; + //Voltage range too high + } + if((amplitude_v < 0) | (offset_v < 0)){ + return -2; + //Negative voltage + } + + if((channel != 1) && (channel != 2)){ + return -3; + //Invalid channel + } + int num_samples = fmin(1000000.0/frequency_Hz, 512); + //The maximum number of samples that Labrador's buffer holds is 512. + //The minimum time between samples is 1us. Using T=1/f, this gives a maximum sample number of 10^6/f. + num_samples = 2*(num_samples / 2); + //Square waves need an even number. Others don't care. + double usecs_between_samples = 1000000.0/((double)num_samples * frequency_Hz); + //Again, from T=1/f. + unsigned char* sampleBuffer = (unsigned char*)malloc(num_samples); + + int i; + double x_temp; + for(i=0; i< num_samples; i++){ + x_temp = (double)i * (2.0*M_PI/(double)num_samples); + //Generate points at interval 2*pi/num_samples. + sampleBuffer[i] = sample_generator(x_temp); + } + + librador_update_signal_gen_settings(channel, sampleBuffer, num_samples, usecs_between_samples, amplitude_v, offset_v); + + free(sampleBuffer); + return 0; +} + +int librador_send_sin_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_sin); +} + +int librador_send_square_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_square); +} + +int librador_send_triangle_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_triangle); +} + +int librador_send_sawtooth_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_sawtooth); +} + +int librador_send_wave(int wf, int channel, double frequency_Hz, double amplitude_v, double offset_v){ + CHECK_API_INITIALISED + CHECK_USB_INITIALISED + switch(wf) + { + case 0: + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_sin); + case 1: + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_square); + case 2: + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_triangle); + case 3: + return send_convenience_waveform(channel, frequency_Hz, amplitude_v, offset_v, generator_sawtooth); + }; + return -4; +} + + + +/* +int librador_synchronise_begin(){ + CHECK_API_INITIALISED + return internal_librador_object->usb_driver->set_synchronous_pause_state(true); +} + +int librador_synchronise_end(){ + CHECK_API_INITIALISED + return internal_librador_object->usb_driver->set_synchronous_pause_state(false); +} +*/ + +static void std_logger(void * userdata, const int level, const char * format, va_list ap); +static librador_logger_p _librador_global_logger = std_logger; +static void * _librador_global_userdata = nullptr; + +void librador_global_logger(const int level, const char * format, ...){ + va_list args; + va_start(args, format); + if (_librador_global_logger) + _librador_global_logger(_librador_global_userdata, level, format, args); + va_end(args); +} + +void librador_logger_set(void * userdata, librador_logger_p logger){ + _librador_global_logger = logger ? logger : std_logger; + _librador_global_userdata = userdata; +} + +librador_logger_p librador_logger_get(void){ + return _librador_global_logger; +} + +void * librador_logger_get_userdata(void){ + return _librador_global_userdata; +} + +static void std_logger(void * userdata, const int level, const char * format, va_list ap){ + vfprintf((level > LOG_ERROR) ? stdout : stderr , format, ap); +} + +void librador_set_trigger_settings(int channel, o1buffer::trigger_settings new_trigger_settings) +{ + return internal_librador_object->usb_driver->setTriggerSettings(channel, new_trigger_settings); +} + +void librador_set_virtual_transform_settings(int channel, o1buffer::virtual_transform_settings new_virtual_transform_settings) +{ + return internal_librador_object->usb_driver->setVirtualTransformSettings(channel, new_virtual_transform_settings); +} + +char * librador_get_uart_string(int channel, bool* parity_check) +{ + return internal_librador_object->usb_driver->getUart_String(channel, parity_check); +} + +void librador_set_uart_decode_settings(int ch, UartSettings new_settings) { + internal_librador_object->usb_driver->setUartDecodeSettings(ch, new_settings); +} + +char * librador_get_i2c_string() +{ + return internal_librador_object->usb_driver->getI2c_String(); +} + +void librador_set_i2c_is_decoding(bool new_decode_on) +{ + internal_librador_object->usb_driver->setI2cIsDecoding(new_decode_on); +} + +bool librador_is_connected() +{ + return internal_librador_object->usb_driver->connected; +} + +bool librador_iso_thread_is_active() +{ + return internal_librador_object->usb_driver->isoThreadIsActive(); +} + diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.h b/Android_App/app/src/main/cpp/deps/librador/librador.h new file mode 100644 index 000000000..d5cf7ca0f --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/librador.h @@ -0,0 +1,89 @@ +#ifndef LIBRADOR_H +#define LIBRADOR_H + +#include "librador_global.h" +#include +#include "usbcallhandler.h" +#include "logging.h" +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *, jobject, jboolean, jint, jboolean); +JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeInitiateFirmwareFlash(JNIEnv *, jobject); +#ifdef __cplusplus +} +#endif + +LIBRADORSHARED_EXPORT int librador_init(); +LIBRADORSHARED_EXPORT int librador_exit(); +LIBRADORSHARED_EXPORT int librador_reset_usb(); +//Control +//a0 +LIBRADORSHARED_EXPORT int librador_avr_debug(); +//a1 +LIBRADORSHARED_EXPORT int librador_update_signal_gen_settings(int channel, unsigned char* sampleBuffer, int numSamples, double usecs_between_samples, double amplitude_v, double offset_v); +LIBRADORSHARED_EXPORT int librador_send_sin_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v); +LIBRADORSHARED_EXPORT int librador_send_square_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v); +LIBRADORSHARED_EXPORT int librador_send_sawtooth_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v); +LIBRADORSHARED_EXPORT int librador_send_triangle_wave(int channel, double frequency_Hz, double amplitude_v, double offset_v); +LIBRADORSHARED_EXPORT int librador_send_wave(int wf, int channel, double frequency_Hz, double amplitude_v, double offset_v); +//a2 +////As above +//a3 +LIBRADORSHARED_EXPORT int librador_set_power_supply_voltage(double voltage); +//a4 +///As above, a1 and a2 +//a5 +LIBRADORSHARED_EXPORT int librador_set_device_mode(int mode); +LIBRADORSHARED_EXPORT int librador_set_oscilloscope_gain(double gain); +LIBRADORSHARED_EXPORT bool librador_get_paused(int channel); +LIBRADORSHARED_EXPORT int librador_set_paused(int channel, bool is_paused); +//a6 +LIBRADORSHARED_EXPORT int librador_set_digital_out(int channel, bool state_on); +//a7 +LIBRADORSHARED_EXPORT int librador_reset_device(); +LIBRADORSHARED_EXPORT int librador_jump_to_bootloader(); +//a8 +LIBRADORSHARED_EXPORT uint16_t librador_get_device_firmware_version(); +//a9 +LIBRADORSHARED_EXPORT uint8_t librador_get_device_firmware_variant(); +//aa +//LIBRADORSHARED_EXPORT int librador_kickstart_isochronous_loop(); + +LIBRADORSHARED_EXPORT std::vector * librador_get_analog_data(int channel, double timeWindow_seconds, int numToGet, double delay_seconds, int filter_mode); +LIBRADORSHARED_EXPORT std::vector * librador_get_analog_data_sincelast(int channel, double timeWindow_max_seconds, double sample_rate_hz, double delay_seconds, int filter_mode); +LIBRADORSHARED_EXPORT std::vector * librador_get_digital_data(int channel, double timeWindow_seconds, int numToGet, double delay_seconds); + +LIBRADORSHARED_EXPORT std::vector librador_get_time_array(double delay, double timeWindow_seconds, int n_samples); + +//TODO: flashFirmware(); + + +/* + * Should never be unsynchronised... Hide these ones +LIBRADORSHARED_EXPORT int librador_synchronise_begin(); +LIBRADORSHARED_EXPORT int librador_synchronise_end(); +*/ + +typedef void (*librador_logger_p)(void * userdata, const int level, const char * format, va_list); + +LIBRADORSHARED_EXPORT void librador_logger_set(void * userdata, librador_logger_p logger); +LIBRADORSHARED_EXPORT librador_logger_p librador_logger_get(void); +LIBRADORSHARED_EXPORT void * librador_logger_get_userdata(void); + +LIBRADORSHARED_EXPORT void librador_set_trigger_settings(int ch, o1buffer::trigger_settings new_trigger_settings); +LIBRADORSHARED_EXPORT void librador_set_virtual_transform_settings(int ch, o1buffer::virtual_transform_settings new_virtual_transform_settings); + +LIBRADORSHARED_EXPORT void librador_set_uart_decode_settings(int ch, UartSettings new_settings); +LIBRADORSHARED_EXPORT void librador_set_i2c_is_decoding(bool new_decode_on); +LIBRADORSHARED_EXPORT char * librador_get_uart_string(int ch, bool* parity_check); +LIBRADORSHARED_EXPORT char * librador_get_i2c_string(); + +LIBRADORSHARED_EXPORT int librador_init_libusb(); +LIBRADORSHARED_EXPORT bool librador_iso_thread_is_active(); +#endif // LIBRADOR_H diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.pro b/Android_App/app/src/main/cpp/deps/librador/librador.pro new file mode 100644 index 000000000..ef993fb52 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/librador.pro @@ -0,0 +1,62 @@ +QT += widgets +QT -= gui + +win32: TARGET = librador +else: TARGET = rador +TEMPLATE = lib + +DEFINES += LIBRADOR_LIBRARY + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + librador.cpp \ + o1buffer.cpp \ + usbcallhandler.cpp + +HEADERS += \ + librador.h \ + librador_global.h \ + librador_internal.h \ + logging.h \ + logging_internal.h \ + o1buffer.h \ + usbcallhandler.h + +unix { + target.path = /usr/lib + INSTALLS += target +} + +unix:!android:!macx { + DEFINES += PLATFORM_LINUX + + #libusb include + CONFIG += link_pkgconfig + PKGCONFIG += libusb-1.0 +} + +macx { + DEFINES += PLATFORM_MAC + + #libusb include + INCLUDEPATH += $$system(brew --prefix)/include/libusb-1.0 + LIBS += -L$$system(brew --prefix)/lib -lusb-1.0 +} + +win32 { + DEFINES += PLATFORM_WINDOWS + + #libusb include + INCLUDEPATH += ../libusb + LIBS += -L$$PWD/../libusb -llibusb-1.0 +} diff --git a/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/android/arm64-v8a/libusb1.0.so b/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/android/arm64-v8a/libusb1.0.so new file mode 100644 index 0000000000000000000000000000000000000000..f7c15b2c95fbf94ceaf56e86f6f830e50c8b62a9 GIT binary patch literal 105136 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 literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/android/armeabi-v7a/libusb1.0.so b/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/android/armeabi-v7a/libusb1.0.so new file mode 100755 index 0000000000000000000000000000000000000000..dc3df24b019b557165e39f65a875be55e496ba41 GIT binary patch literal 70956 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 literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/libusb.h b/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/libusb.h new file mode 100644 index 000000000..8542c6ac7 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb/libusb.h @@ -0,0 +1,2453 @@ +/* + * Public libusb header file + * Copyright © 2001 Johannes Erdfelt + * Copyright © 2007-2008 Daniel Drake + * Copyright © 2012 Pete Batard + * Copyright © 2012-2023 Nathan Hjelm + * Copyright © 2014-2020 Chris Dickens + * For more information, please visit: https://libusb.info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_H +#define LIBUSB_H + +#if defined(_MSC_VER) +#pragma warning(push) +/* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */ +#pragma warning(disable:4200) +/* on MS environments, the inline keyword is available in C++ only */ +#if !defined(__cplusplus) +#define inline __inline +#endif +/* ssize_t is also not available */ +#ifndef _SSIZE_T_DEFINED +#define _SSIZE_T_DEFINED +#include +typedef SSIZE_T ssize_t; +#endif /* _SSIZE_T_DEFINED */ +#endif /* _MSC_VER */ + +#include +#include +#include +#if !defined(_MSC_VER) +#include +#endif +#include + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define LIBUSB_FLEXIBLE_ARRAY /* [] - valid C99 code */ +#else +#define LIBUSB_FLEXIBLE_ARRAY 0 /* [0] - non-standard, but usually working code */ +#endif /* __STDC_VERSION__ */ + +/* 'interface' might be defined as a macro on Windows, so we need to + * undefine it so as not to break the current libusb API, because + * libusb_config_descriptor has an 'interface' member + * As this can be problematic if you include windows.h after libusb.h + * in your sources, we force windows.h to be included first. */ +#if defined(_WIN32) || defined(__CYGWIN__) +#include +#if defined(interface) +#undef interface +#endif +#endif /* _WIN32 || __CYGWIN__ */ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated ("Use " #f " instead"))) +#elif defined(__GNUC__) && (__GNUC__ >= 3) +#define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define LIBUSB_DEPRECATED_FOR(f) __declspec(deprecated("Use " #f " instead")) +#else +#define LIBUSB_DEPRECATED_FOR(f) +#endif /* __GNUC__ */ + +#if defined(__GNUC__) +#define LIBUSB_PACKED __attribute__ ((packed)) +#else +#define LIBUSB_PACKED +#endif /* __GNUC__ */ + +/** \def LIBUSB_CALL + * \ingroup libusb_misc + * libusb's Windows calling convention. + * + * Under Windows, the selection of available compilers and configurations + * means that, unlike other platforms, there is not one true calling + * convention (calling convention: the manner in which parameters are + * passed to functions in the generated assembly code). + * + * Matching the Windows API itself, libusb uses the WINAPI convention (which + * translates to the stdcall convention) and guarantees that the + * library is compiled in this way. The public header file also includes + * appropriate annotations so that your own software will use the right + * convention, even if another convention is being used by default within + * your codebase. + * + * The one consideration that you must apply in your software is to mark + * all functions which you use as libusb callbacks with this LIBUSB_CALL + * annotation, so that they too get compiled for the correct calling + * convention. + * + * On non-Windows operating systems, this macro is defined as nothing. This + * means that you can apply it to your code without worrying about + * cross-platform compatibility. + */ +/* LIBUSB_CALL must be defined on both definition and declaration of libusb + * functions. You'd think that declaration would be enough, but cygwin will + * complain about conflicting types unless both are marked this way. + * The placement of this macro is important too; it must appear after the + * return type, before the function name. See internal documentation for + * API_EXPORTED. + */ +#if defined(_WIN32) || defined(__CYGWIN__) +#define LIBUSB_CALL WINAPI +#define LIBUSB_CALLV WINAPIV +#else +#define LIBUSB_CALL +#define LIBUSB_CALLV +#endif /* _WIN32 || __CYGWIN__ */ + +/** \def LIBUSB_API_VERSION + * \ingroup libusb_misc + * libusb's API version. + * + * Since version 1.0.18, to help with feature detection, libusb defines + * a LIBUSB_API_VERSION macro that gets increased every time there is a + * significant change to the API, such as the introduction of a new call, + * the definition of a new macro/enum member, or any other element that + * libusb applications may want to detect at compilation time. + * + * Between versions 1.0.13 and 1.0.17 (inclusive) the older spelling of + * LIBUSBX_API_VERSION was used. + * + * The macro is typically used in an application as follows: + * \code + * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234) + * // Use one of the newer features from the libusb API + * #endif + * \endcode + * + * Internally, LIBUSB_API_VERSION is defined as follows: + * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) + * + * The incremental component has changed as follows: + *
    + *
  • libusbx version 1.0.13: LIBUSBX_API_VERSION = 0x01000100 + *
  • libusbx version 1.0.14: LIBUSBX_API_VERSION = 0x010000FF + *
  • libusbx version 1.0.15: LIBUSBX_API_VERSION = 0x01000101 + *
  • libusbx version 1.0.16: LIBUSBX_API_VERSION = 0x01000102 + *
  • libusbx version 1.0.17: LIBUSBX_API_VERSION = 0x01000102 + *
  • libusb version 1.0.18: LIBUSB_API_VERSION = 0x01000102 + *
  • libusb version 1.0.19: LIBUSB_API_VERSION = 0x01000103 + *
  • libusb version 1.0.20: LIBUSB_API_VERSION = 0x01000104 + *
  • libusb version 1.0.21: LIBUSB_API_VERSION = 0x01000105 + *
  • libusb version 1.0.22: LIBUSB_API_VERSION = 0x01000106 + *
  • libusb version 1.0.23: LIBUSB_API_VERSION = 0x01000107 + *
  • libusb version 1.0.24: LIBUSB_API_VERSION = 0x01000108 + *
  • libusb version 1.0.25: LIBUSB_API_VERSION = 0x01000109 + *
  • libusb version 1.0.26: LIBUSB_API_VERSION = 0x01000109 + *
  • libusb version 1.0.27: LIBUSB_API_VERSION = 0x0100010A + *
  • libusb version 1.0.28: LIBUSB_API_VERSION = 0x0100010A + *
  • libusb version 1.0.29: LIBUSB_API_VERSION = 0x0100010B + *
  • libusb version 1.0.30: LIBUSB_API_VERSION = 0x0100010C + *
+ */ +#define LIBUSB_API_VERSION 0x0100010C + +/** \def LIBUSBX_API_VERSION + * \ingroup libusb_misc + * + * This is the older spelling, kept for backwards compatibility of code + * needing to test for older library versions where the newer spelling + * did not exist. */ +#define LIBUSBX_API_VERSION LIBUSB_API_VERSION + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * \ingroup libusb_misc + * Convert a 16-bit value from host-endian to little-endian format. On + * little endian systems, this function does nothing. On big endian systems, + * the bytes are swapped. + * \param x the host-endian value to convert + * \returns the value in little-endian byte order + */ +static inline uint16_t libusb_cpu_to_le16(uint16_t x) +{ + union { + uint8_t b8[2]; + uint16_t b16; + } _tmp; + _tmp.b8[1] = (uint8_t) (x >> 8); + _tmp.b8[0] = (uint8_t) (x & 0xff); + return _tmp.b16; +} + +/** \def libusb_le16_to_cpu + * \ingroup libusb_misc + * Convert a 16-bit value from little-endian to host-endian format. On + * little endian systems, this function does nothing. On big endian systems, + * the bytes are swapped. + * \param x the little-endian value to convert + * \returns the value in host-endian byte order + */ +#define libusb_le16_to_cpu libusb_cpu_to_le16 + +/* standard USB stuff */ + +/** \ingroup libusb_desc + * Device and/or Interface Class codes */ +enum libusb_class_code { + /** In the context of a \ref libusb_device_descriptor "device descriptor", + * this bDeviceClass value indicates that each interface specifies its + * own class information and all interfaces operate independently. + */ + LIBUSB_CLASS_PER_INTERFACE = 0x00, + + /** Audio class */ + LIBUSB_CLASS_AUDIO = 0x01, + + /** Communications class */ + LIBUSB_CLASS_COMM = 0x02, + + /** Human Interface Device class */ + LIBUSB_CLASS_HID = 0x03, + + /** Physical */ + LIBUSB_CLASS_PHYSICAL = 0x05, + + /** Image class */ + LIBUSB_CLASS_IMAGE = 0x06, + LIBUSB_CLASS_PTP = 0x06, /* legacy name from libusb-0.1 usb.h */ + + /** Printer class */ + LIBUSB_CLASS_PRINTER = 0x07, + + /** Mass storage class */ + LIBUSB_CLASS_MASS_STORAGE = 0x08, + + /** Hub class */ + LIBUSB_CLASS_HUB = 0x09, + + /** Data class */ + LIBUSB_CLASS_DATA = 0x0a, + + /** Smart Card */ + LIBUSB_CLASS_SMART_CARD = 0x0b, + + /** Content Security */ + LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, + + /** Video */ + LIBUSB_CLASS_VIDEO = 0x0e, + + /** Personal Healthcare */ + LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, + + /** Diagnostic Device */ + LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, + + /** Wireless class */ + LIBUSB_CLASS_WIRELESS = 0xe0, + + /** Miscellaneous class */ + LIBUSB_CLASS_MISCELLANEOUS = 0xef, + + /** Application class */ + LIBUSB_CLASS_APPLICATION = 0xfe, + + /** Class is vendor-specific */ + LIBUSB_CLASS_VENDOR_SPEC = 0xff +}; + +/** \ingroup libusb_desc + * Descriptor types as defined by the USB specification. */ +enum libusb_descriptor_type { + /** Device descriptor. See libusb_device_descriptor. */ + LIBUSB_DT_DEVICE = 0x01, + + /** Configuration descriptor. See libusb_config_descriptor. */ + LIBUSB_DT_CONFIG = 0x02, + + /** String descriptor */ + LIBUSB_DT_STRING = 0x03, + + /** Interface descriptor. See libusb_interface_descriptor. */ + LIBUSB_DT_INTERFACE = 0x04, + + /** Endpoint descriptor. See libusb_endpoint_descriptor. */ + LIBUSB_DT_ENDPOINT = 0x05, + + /** Interface Association Descriptor. + * See libusb_interface_association_descriptor */ + LIBUSB_DT_INTERFACE_ASSOCIATION = 0x0b, + + /** BOS descriptor */ + LIBUSB_DT_BOS = 0x0f, + + /** Device Capability descriptor */ + LIBUSB_DT_DEVICE_CAPABILITY = 0x10, + + /** HID descriptor */ + LIBUSB_DT_HID = 0x21, + + /** HID report descriptor */ + LIBUSB_DT_REPORT = 0x22, + + /** Physical descriptor */ + LIBUSB_DT_PHYSICAL = 0x23, + + /** Hub descriptor */ + LIBUSB_DT_HUB = 0x29, + + /** SuperSpeed Hub descriptor */ + LIBUSB_DT_SUPERSPEED_HUB = 0x2a, + + /** SuperSpeed Endpoint Companion descriptor */ + LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30 +}; + +/* Descriptor sizes per descriptor type */ +#define LIBUSB_DT_DEVICE_SIZE 18 +#define LIBUSB_DT_CONFIG_SIZE 9 +#define LIBUSB_DT_INTERFACE_SIZE 9 +#define LIBUSB_DT_ENDPOINT_SIZE 7 +#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ +#define LIBUSB_DT_HUB_NONVAR_SIZE 7 +#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6 +#define LIBUSB_DT_BOS_SIZE 5 +#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3 +#define LIBUSB_DT_INTERFACE_ASSOCIATION_SIZE 8 + +/* BOS descriptor sizes */ +#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 +#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 +#define LIBUSB_BT_SSPLUS_USB_DEVICE_CAPABILITY_SIZE 12 +#define LIBUSB_BT_CONTAINER_ID_SIZE 20 +#define LIBUSB_BT_PLATFORM_DESCRIPTOR_MIN_SIZE 20 + +/* We unwrap the BOS => define its max size */ +#define LIBUSB_DT_BOS_MAX_SIZE \ + (LIBUSB_DT_BOS_SIZE + \ + LIBUSB_BT_USB_2_0_EXTENSION_SIZE + \ + LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE + \ + LIBUSB_BT_CONTAINER_ID_SIZE) + +#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ +#define LIBUSB_ENDPOINT_DIR_MASK 0x80 + +/** \ingroup libusb_desc + * Endpoint direction. Values for bit 7 of the + * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. + */ +enum libusb_endpoint_direction { + /** Out: host-to-device */ + LIBUSB_ENDPOINT_OUT = 0x00, + + /** In: device-to-host */ + LIBUSB_ENDPOINT_IN = 0x80 +}; + +#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ + +/** \ingroup libusb_desc + * Endpoint transfer type. Values for bits 0:1 of the + * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. + */ +enum libusb_endpoint_transfer_type { + /** Control endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_CONTROL = 0x0, + + /** Isochronous endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS = 0x1, + + /** Bulk endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK = 0x2, + + /** Interrupt endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT = 0x3 +}; + +/** \ingroup libusb_misc + * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ +enum libusb_standard_request { + /** Request status of the specific recipient */ + LIBUSB_REQUEST_GET_STATUS = 0x00, + + /** Clear or disable a specific feature */ + LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, + + /* 0x02 is reserved */ + + /** Set or enable a specific feature */ + LIBUSB_REQUEST_SET_FEATURE = 0x03, + + /* 0x04 is reserved */ + + /** Set device address for all future accesses */ + LIBUSB_REQUEST_SET_ADDRESS = 0x05, + + /** Get the specified descriptor */ + LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, + + /** Used to update existing descriptors or add new descriptors */ + LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, + + /** Get the current device configuration value */ + LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, + + /** Set device configuration */ + LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, + + /** Return the selected alternate setting for the specified interface */ + LIBUSB_REQUEST_GET_INTERFACE = 0x0a, + + /** Select an alternate interface for the specified interface */ + LIBUSB_REQUEST_SET_INTERFACE = 0x0b, + + /** Set then report an endpoint's synchronization frame */ + LIBUSB_REQUEST_SYNCH_FRAME = 0x0c, + + /** Sets both the U1 and U2 Exit Latency */ + LIBUSB_REQUEST_SET_SEL = 0x30, + + /** Delay from the time a host transmits a packet to the time it is + * received by the device. */ + LIBUSB_SET_ISOCH_DELAY = 0x31 +}; + +/** \ingroup libusb_misc + * Request type bits of the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control + * transfers. */ +enum libusb_request_type { + /** Standard */ + LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), + + /** Class */ + LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), + + /** Vendor */ + LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), + + /** Reserved */ + LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) +}; + +/** \ingroup libusb_misc + * Recipient bits of the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control + * transfers. Values 4 through 31 are reserved. */ +enum libusb_request_recipient { + /** Device */ + LIBUSB_RECIPIENT_DEVICE = 0x00, + + /** Interface */ + LIBUSB_RECIPIENT_INTERFACE = 0x01, + + /** Endpoint */ + LIBUSB_RECIPIENT_ENDPOINT = 0x02, + + /** Other */ + LIBUSB_RECIPIENT_OTHER = 0x03 +}; + +#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0c + +/** \ingroup libusb_desc + * Synchronization type for isochronous endpoints. Values for bits 2:3 of the + * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in + * libusb_endpoint_descriptor. + */ +enum libusb_iso_sync_type { + /** No synchronization */ + LIBUSB_ISO_SYNC_TYPE_NONE = 0x0, + + /** Asynchronous */ + LIBUSB_ISO_SYNC_TYPE_ASYNC = 0x1, + + /** Adaptive */ + LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 0x2, + + /** Synchronous */ + LIBUSB_ISO_SYNC_TYPE_SYNC = 0x3 +}; + +#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 + +/** \ingroup libusb_desc + * Usage type for isochronous endpoints. Values for bits 4:5 of the + * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in + * libusb_endpoint_descriptor. + */ +enum libusb_iso_usage_type { + /** Data endpoint */ + LIBUSB_ISO_USAGE_TYPE_DATA = 0x0, + + /** Feedback endpoint */ + LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 0x1, + + /** Implicit feedback Data endpoint */ + LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 0x2 +}; + +/** \ingroup libusb_desc + * Supported speeds (wSpeedSupported) bitfield. Indicates what + * speeds the device supports. + */ +enum libusb_supported_speed { + /** Low speed operation supported (1.5MBit/s). */ + LIBUSB_LOW_SPEED_OPERATION = (1 << 0), + + /** Full speed operation supported (12MBit/s). */ + LIBUSB_FULL_SPEED_OPERATION = (1 << 1), + + /** High speed operation supported (480MBit/s). */ + LIBUSB_HIGH_SPEED_OPERATION = (1 << 2), + + /** Superspeed operation supported (5000MBit/s). */ + LIBUSB_SUPER_SPEED_OPERATION = (1 << 3) +}; + +/** \ingroup libusb_desc + * Masks for the bits of the + * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field + * of the USB 2.0 Extension descriptor. + */ +enum libusb_usb_2_0_extension_attributes { + /** Supports Link Power Management (LPM) */ + LIBUSB_BM_LPM_SUPPORT = (1 << 1) +}; + +/** \ingroup libusb_desc + * Masks for the bits of the + * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field + * field of the SuperSpeed USB Device Capability descriptor. + */ +enum libusb_ss_usb_device_capability_attributes { + /** Supports Latency Tolerance Messages (LTM) */ + LIBUSB_BM_LTM_SUPPORT = (1 << 1) +}; + +/** \ingroup libusb_desc + * USB capability types + */ +enum libusb_bos_type { + /** Wireless USB device capability */ + LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 0x01, + + /** USB 2.0 extensions */ + LIBUSB_BT_USB_2_0_EXTENSION = 0x02, + + /** SuperSpeed USB device capability */ + LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 0x03, + + /** Container ID type */ + LIBUSB_BT_CONTAINER_ID = 0x04, + + /** Platform descriptor */ + LIBUSB_BT_PLATFORM_DESCRIPTOR = 0x05, + + /** SuperSpeedPlus device capability */ + LIBUSB_BT_SUPERSPEED_PLUS_CAPABILITY = 0x0A, +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB device descriptor. This + * descriptor is documented in section 9.6.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_device_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this + * context. */ + uint8_t bDescriptorType; + + /** USB specification release number in binary-coded decimal. A value of + * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ + uint16_t bcdUSB; + + /** USB-IF class code for the device. See \ref libusb_class_code. */ + uint8_t bDeviceClass; + + /** USB-IF subclass code for the device, qualified by the bDeviceClass + * value */ + uint8_t bDeviceSubClass; + + /** USB-IF protocol code for the device, qualified by the bDeviceClass and + * bDeviceSubClass values */ + uint8_t bDeviceProtocol; + + /** Maximum packet size for endpoint 0 */ + uint8_t bMaxPacketSize0; + + /** USB-IF vendor ID */ + uint16_t idVendor; + + /** USB-IF product ID */ + uint16_t idProduct; + + /** Device release number in binary-coded decimal */ + uint16_t bcdDevice; + + /** Index of string descriptor describing manufacturer */ + uint8_t iManufacturer; + + /** Index of string descriptor describing product */ + uint8_t iProduct; + + /** Index of string descriptor containing device serial number */ + uint8_t iSerialNumber; + + /** Number of possible configurations */ + uint8_t bNumConfigurations; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB endpoint descriptor. This + * descriptor is documented in section 9.6.6 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_endpoint_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in + * this context. */ + uint8_t bDescriptorType; + + /** The address of the endpoint described by this descriptor. Bits 0:3 are + * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, + * see \ref libusb_endpoint_direction. */ + uint8_t bEndpointAddress; + + /** Attributes which apply to the endpoint when it is configured using + * the bConfigurationValue. Bits 0:1 determine the transfer type and + * correspond to \ref libusb_endpoint_transfer_type. Bits 2:3 are only used + * for isochronous endpoints and correspond to \ref libusb_iso_sync_type. + * Bits 4:5 are also only used for isochronous endpoints and correspond to + * \ref libusb_iso_usage_type. Bits 6:7 are reserved. */ + uint8_t bmAttributes; + + /** Maximum packet size this endpoint is capable of sending/receiving. */ + uint16_t wMaxPacketSize; + + /** Interval for polling endpoint for data transfers. */ + uint8_t bInterval; + + /** For audio devices only: the rate at which synchronization feedback + * is provided. */ + uint8_t bRefresh; + + /** For audio devices only: the address if the synch endpoint */ + uint8_t bSynchAddress; + + /** Extra descriptors. If libusb encounters unknown endpoint descriptors, + * it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. Must be non-negative. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB interface association descriptor. + * This descriptor is documented in section 9.6.4 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_interface_association_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE_ASSOCIATION + * LIBUSB_DT_INTERFACE_ASSOCIATION in this context. */ + uint8_t bDescriptorType; + + /** Interface number of the first interface that is associated + * with this function */ + uint8_t bFirstInterface; + + /** Number of contiguous interfaces that are associated with + * this function */ + uint8_t bInterfaceCount; + + /** USB-IF class code for this function. + * A value of zero is not allowed in this descriptor. + * If this field is 0xff, the function class is vendor-specific. + * All other values are reserved for assignment by the USB-IF. + */ + uint8_t bFunctionClass; + + /** USB-IF subclass code for this function. + * If this field is not set to 0xff, all values are reserved + * for assignment by the USB-IF + */ + uint8_t bFunctionSubClass; + + /** USB-IF protocol code for this function. + * These codes are qualified by the values of the bFunctionClass + * and bFunctionSubClass fields. + */ + uint8_t bFunctionProtocol; + + /** Index of string descriptor describing this function */ + uint8_t iFunction; +}; + +/** \ingroup libusb_desc + * Structure containing an array of 0 or more interface association + * descriptors + */ +struct libusb_interface_association_descriptor_array { + /** Array of interface association descriptors. The size of this array + * is determined by the length field. + */ + const struct libusb_interface_association_descriptor *iad; + + /** Number of interface association descriptors contained. Read-only. */ + int length; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB interface descriptor. This + * descriptor is documented in section 9.6.5 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_interface_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE + * in this context. */ + uint8_t bDescriptorType; + + /** Number of this interface */ + uint8_t bInterfaceNumber; + + /** Value used to select this alternate setting for this interface */ + uint8_t bAlternateSetting; + + /** Number of endpoints used by this interface (excluding the control + * endpoint). */ + uint8_t bNumEndpoints; + + /** USB-IF class code for this interface. See \ref libusb_class_code. */ + uint8_t bInterfaceClass; + + /** USB-IF subclass code for this interface, qualified by the + * bInterfaceClass value */ + uint8_t bInterfaceSubClass; + + /** USB-IF protocol code for this interface, qualified by the + * bInterfaceClass and bInterfaceSubClass values */ + uint8_t bInterfaceProtocol; + + /** Index of string descriptor describing this interface */ + uint8_t iInterface; + + /** Array of endpoint descriptors. This length of this array is determined + * by the bNumEndpoints field. */ + const struct libusb_endpoint_descriptor *endpoint; + + /** Extra descriptors. If libusb encounters unknown interface descriptors, + * it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. Must be non-negative. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A collection of alternate settings for a particular USB interface. + */ +struct libusb_interface { + /** Array of interface descriptors. The length of this array is determined + * by the num_altsetting field. */ + const struct libusb_interface_descriptor *altsetting; + + /** The number of alternate settings that belong to this interface. + * Must be non-negative. */ + int num_altsetting; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB configuration descriptor. This + * descriptor is documented in section 9.6.3 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_config_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG + * in this context. */ + uint8_t bDescriptorType; + + /** Total length of data returned for this configuration */ + uint16_t wTotalLength; + + /** Number of interfaces supported by this configuration */ + uint8_t bNumInterfaces; + + /** Identifier value for this configuration */ + uint8_t bConfigurationValue; + + /** Index of string descriptor describing this configuration */ + uint8_t iConfiguration; + + /** Configuration characteristics */ + uint8_t bmAttributes; + + /** Maximum power consumption of the USB device from this bus in this + * configuration when the device is fully operation. Expressed in units + * of 2 mA when the device is operating in high-speed mode and in units + * of 8 mA when the device is operating in super-speed mode. */ + uint8_t MaxPower; + + /** Array of interfaces supported by this configuration. The length of + * this array is determined by the bNumInterfaces field. */ + const struct libusb_interface *interface; + + /** Extra descriptors. If libusb encounters unknown configuration + * descriptors, it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. Must be non-negative. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A structure representing the superspeed endpoint companion + * descriptor. This descriptor is documented in section 9.6.7 of + * the USB 3.0 specification. All multiple-byte fields are represented in + * host-endian format. + */ +struct libusb_ss_endpoint_companion_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in + * this context. */ + uint8_t bDescriptorType; + + /** The maximum number of packets the endpoint can send or + * receive as part of a burst. */ + uint8_t bMaxBurst; + + /** In bulk EP: bits 4:0 represents the maximum number of + * streams the EP supports. In isochronous EP: bits 1:0 + * represents the Mult - a zero based value that determines + * the maximum number of packets within a service interval */ + uint8_t bmAttributes; + + /** The total number of bytes this EP will transfer every + * service interval. Valid only for periodic EPs. */ + uint16_t wBytesPerInterval; +}; + +/** \ingroup libusb_desc + * A generic representation of a BOS Device Capability descriptor. It is + * advised to check bDevCapabilityType and call the matching + * libusb_get_*_descriptor function to get a structure fully matching the type. + */ +struct libusb_bos_dev_capability_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Device Capability type */ + uint8_t bDevCapabilityType; + + /** Device Capability data (bLength - 3 bytes) */ + uint8_t dev_capability_data[LIBUSB_FLEXIBLE_ARRAY]; +}; + +/** \ingroup libusb_desc + * A structure representing the Binary Device Object Store (BOS) descriptor. + * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_bos_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS + * in this context. */ + uint8_t bDescriptorType; + + /** Length of this descriptor and all of its sub descriptors */ + uint16_t wTotalLength; + + /** The number of separate device capability descriptors in + * the BOS */ + uint8_t bNumDeviceCaps; + + /** bNumDeviceCap Device Capability Descriptors */ + struct libusb_bos_dev_capability_descriptor *dev_capability[LIBUSB_FLEXIBLE_ARRAY]; +}; + +/** \ingroup libusb_desc + * A structure representing the USB 2.0 Extension descriptor + * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_usb_2_0_extension_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_bos_type::LIBUSB_BT_USB_2_0_EXTENSION + * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ + uint8_t bDevCapabilityType; + + /** Bitmap encoding of supported device level features. + * A value of one in a bit location indicates a feature is + * supported; a value of zero indicates it is not supported. + * See \ref libusb_usb_2_0_extension_attributes. */ + uint32_t bmAttributes; +}; + +/** \ingroup libusb_desc + * A structure representing the SuperSpeed USB Device Capability descriptor + * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_ss_usb_device_capability_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_bos_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ + uint8_t bDevCapabilityType; + + /** Bitmap encoding of supported device level features. + * A value of one in a bit location indicates a feature is + * supported; a value of zero indicates it is not supported. + * See \ref libusb_ss_usb_device_capability_attributes. */ + uint8_t bmAttributes; + + /** Bitmap encoding of the speed supported by this device when + * operating in SuperSpeed mode. See \ref libusb_supported_speed. */ + uint16_t wSpeedSupported; + + /** The lowest speed at which all the functionality supported + * by the device is available to the user. For example if the + * device supports all its functionality when connected at + * full speed and above then it sets this value to 1. */ + uint8_t bFunctionalitySupport; + + /** U1 Device Exit Latency. */ + uint8_t bU1DevExitLat; + + /** U2 Device Exit Latency. */ + uint16_t bU2DevExitLat; +}; + +/** \ingroup libusb_desc + * enum used in \ref libusb_ssplus_sublink_attribute + */ +enum libusb_superspeedplus_sublink_attribute_sublink_type { + LIBUSB_SSPLUS_ATTR_TYPE_SYM = 0, + LIBUSB_SSPLUS_ATTR_TYPE_ASYM = 1, +}; + +/** \ingroup libusb_desc + * enum used in \ref libusb_ssplus_sublink_attribute + */ +enum libusb_superspeedplus_sublink_attribute_sublink_direction { + LIBUSB_SSPLUS_ATTR_DIR_RX = 0, + LIBUSB_SSPLUS_ATTR_DIR_TX = 1, +}; + +/** \ingroup libusb_desc + * enum used in \ref libusb_ssplus_sublink_attribute + * Bit = Bits per second + * Kb = Kbps + * Mb = Mbps + * Gb = Gbps + */ +enum libusb_superspeedplus_sublink_attribute_exponent { + LIBUSB_SSPLUS_ATTR_EXP_BPS = 0, + LIBUSB_SSPLUS_ATTR_EXP_KBS = 1, + LIBUSB_SSPLUS_ATTR_EXP_MBS = 2, + LIBUSB_SSPLUS_ATTR_EXP_GBS = 3, +}; + +/** \ingroup libusb_desc + * enum used in \ref libusb_ssplus_sublink_attribute + */ +enum libusb_superspeedplus_sublink_attribute_link_protocol { + LIBUSB_SSPLUS_ATTR_PROT_SS = 0, + LIBUSB_SSPLUS_ATTR_PROT_SSPLUS = 1, +}; + +/** \ingroup libusb_desc + * Expose \ref libusb_ssplus_usb_device_capability_descriptor.sublinkSpeedAttributes + */ +struct libusb_ssplus_sublink_attribute { + /** Sublink Speed Attribute ID (SSID). + This field is an ID that uniquely identifies the speed of this sublink */ + uint8_t ssid; + + /** This field defines the + base 10 exponent times 3, that shall be applied to the + mantissa. */ + enum libusb_superspeedplus_sublink_attribute_exponent exponent; + + /** This field identifies whether the + Sublink Speed Attribute defines a symmetric or + asymmetric bit rate.*/ + enum libusb_superspeedplus_sublink_attribute_sublink_type type; + + /** This field indicates if this + Sublink Speed Attribute defines the receive or + transmit bit rate. */ + enum libusb_superspeedplus_sublink_attribute_sublink_direction direction; + + /** This field identifies the protocol + supported by the link. */ + enum libusb_superspeedplus_sublink_attribute_link_protocol protocol; + + /** This field defines the mantissa that shall be applied to the exponent when + calculating the maximum bit rate. */ + uint16_t mantissa; +}; + +/** \ingroup libusb_desc + * A structure representing the SuperSpeedPlus descriptor + * This descriptor is documented in section 9.6.2.5 of the USB 3.1 specification. + */ +struct libusb_ssplus_usb_device_capability_descriptor { + /** Sublink Speed Attribute Count */ + uint8_t numSublinkSpeedAttributes; + + /** Sublink Speed ID Count */ + uint8_t numSublinkSpeedIDs; + + /** Unique ID to indicates the minimum lane speed */ + uint8_t ssid; + + /** This field indicates the minimum receive lane count.*/ + uint8_t minRxLaneCount; + + /** This field indicates the minimum transmit lane count*/ + uint8_t minTxLaneCount; + + /** Array size is \ref libusb_ssplus_usb_device_capability_descriptor.numSublinkSpeedAttributes */ + struct libusb_ssplus_sublink_attribute sublinkSpeedAttributes[]; +}; + +/** \ingroup libusb_desc + * A structure representing the Container ID descriptor. + * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. + * All multiple-byte fields, except UUIDs, are represented in host-endian format. + */ +struct libusb_container_id_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_bos_type::LIBUSB_BT_CONTAINER_ID + * LIBUSB_BT_CONTAINER_ID in this context. */ + uint8_t bDevCapabilityType; + + /** Reserved field */ + uint8_t bReserved; + + /** 128 bit UUID */ + uint8_t ContainerID[16]; +}; + +/** \ingroup libusb_desc + * A structure representing a Platform descriptor. + * This descriptor is documented in section 9.6.2.4 of the USB 3.2 specification. + */ +struct libusb_platform_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_bos_type::LIBUSB_BT_PLATFORM_DESCRIPTOR + * LIBUSB_BT_CONTAINER_ID in this context. */ + uint8_t bDevCapabilityType; + + /** Reserved field */ + uint8_t bReserved; + + /** 128 bit UUID */ + uint8_t PlatformCapabilityUUID[16]; + + /** Capability data (bLength - 20) */ + uint8_t CapabilityData[LIBUSB_FLEXIBLE_ARRAY]; +}; + +/** \ingroup libusb_asyncio + * Setup packet for control transfers. */ +#if defined(_MSC_VER) || defined(__WATCOMC__) +#pragma pack(push, 1) +#endif +struct libusb_control_setup { + /** Request type. Bits 0:4 determine recipient, see + * \ref libusb_request_recipient. Bits 5:6 determine type, see + * \ref libusb_request_type. Bit 7 determines data transfer direction, see + * \ref libusb_endpoint_direction. + */ + uint8_t bmRequestType; + + /** Request. If the type bits of bmRequestType are equal to + * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD + * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to + * \ref libusb_standard_request. For other cases, use of this field is + * application-specific. */ + uint8_t bRequest; + + /** Value. Varies according to request */ + uint16_t wValue; + + /** Index. Varies according to request, typically used to pass an index + * or offset */ + uint16_t wIndex; + + /** Number of bytes to transfer */ + uint16_t wLength; +} LIBUSB_PACKED; +#if defined(_MSC_VER) || defined(__WATCOMC__) +#pragma pack(pop) +#endif + +#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) + +/* libusb */ + +struct libusb_context; +struct libusb_device; +struct libusb_device_handle; + +/** \ingroup libusb_lib + * Structure providing the version of the libusb runtime + */ +struct libusb_version { + /** Library major version. */ + uint16_t major; + + /** Library minor version. */ + uint16_t minor; + + /** Library micro version. */ + uint16_t micro; + + /** Library nano version. */ + uint16_t nano; + + /** Library release candidate suffix string, e.g. "-rc4". */ + const char *rc; + + /** For ABI compatibility only. */ + const char *describe; +}; + +/** \ingroup libusb_lib + * Structure representing a libusb session. The concept of individual libusb + * sessions allows for your program to use two libraries (or dynamically + * load two modules) which both independently use libusb. This will prevent + * interference between the individual libusb users - for example + * libusb_set_option() will not affect the other user of the library, and + * libusb_exit() will not destroy resources that the other user is still + * using. + * + * Sessions are created by libusb_init_context() and destroyed through libusb_exit(). + * If your application is guaranteed to only ever include a single libusb + * user (i.e. you), you do not have to worry about contexts: pass NULL in + * every function call where a context is required, and the default context + * will be used. Note that libusb_set_option(NULL, ...) is special, and adds + * an option to a list of default options for new contexts. + * + * For more information, see \ref libusb_contexts. + */ +typedef struct libusb_context libusb_context; + +/** \ingroup libusb_dev + * Structure representing a USB device detected on the system. This is an + * opaque type for which you are only ever provided with a pointer, usually + * originating from libusb_get_device_list() or libusb_hotplug_register_callback(). + * + * Certain operations can be performed on a device, but in order to do any + * I/O you will have to first obtain a device handle using libusb_open(). + * + * Devices are reference counted with libusb_ref_device() and + * libusb_unref_device(), and are freed when the reference count reaches 0. + * New devices presented by libusb_get_device_list() have a reference count of + * 1, and libusb_free_device_list() can optionally decrease the reference count + * on all devices in the list. libusb_open() adds another reference which is + * later destroyed by libusb_close(). + */ +typedef struct libusb_device libusb_device; + + +/** \ingroup libusb_dev + * Structure representing a handle on a USB device. This is an opaque type for + * which you are only ever provided with a pointer, usually originating from + * libusb_open(). + * + * A device handle is used to perform I/O and other operations. When finished + * with a device handle, you should call libusb_close(). + */ +typedef struct libusb_device_handle libusb_device_handle; + +/** \ingroup libusb_dev + * Speed codes. Indicates the speed at which the device is operating. + */ +enum libusb_speed { + /** The OS doesn't report or know the device speed. */ + LIBUSB_SPEED_UNKNOWN = 0, + + /** The device is operating at low speed (1.5MBit/s). */ + LIBUSB_SPEED_LOW = 1, + + /** The device is operating at full speed (12MBit/s). */ + LIBUSB_SPEED_FULL = 2, + + /** The device is operating at high speed (480MBit/s). */ + LIBUSB_SPEED_HIGH = 3, + + /** The device is operating at super speed (5000MBit/s). */ + LIBUSB_SPEED_SUPER = 4, + + /** The device is operating at super speed plus (10000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS = 5, + + /** The device is operating at super speed plus x2 (20000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS_X2 = 6, +}; + +/** \ingroup libusb_misc + * Error codes. Most libusb functions return 0 on success or one of these + * codes on failure. + * You can call libusb_error_name() to retrieve a string representation of an + * error code or libusb_strerror() to get an end-user suitable description of + * an error code. + */ +enum libusb_error { + /** Success (no error) */ + LIBUSB_SUCCESS = 0, + + /** Input/output error */ + LIBUSB_ERROR_IO = -1, + + /** Invalid parameter */ + LIBUSB_ERROR_INVALID_PARAM = -2, + + /** Access denied (insufficient permissions) */ + LIBUSB_ERROR_ACCESS = -3, + + /** No such device (it may have been disconnected) */ + LIBUSB_ERROR_NO_DEVICE = -4, + + /** Entity not found */ + LIBUSB_ERROR_NOT_FOUND = -5, + + /** Resource busy */ + LIBUSB_ERROR_BUSY = -6, + + /** Operation timed out */ + LIBUSB_ERROR_TIMEOUT = -7, + + /** Overflow */ + LIBUSB_ERROR_OVERFLOW = -8, + + /** Pipe error */ + LIBUSB_ERROR_PIPE = -9, + + /** System call interrupted (perhaps due to signal) */ + LIBUSB_ERROR_INTERRUPTED = -10, + + /** Insufficient memory */ + LIBUSB_ERROR_NO_MEM = -11, + + /** Operation not supported or unimplemented on this platform */ + LIBUSB_ERROR_NOT_SUPPORTED = -12, + + /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the + message strings in strerror.c when adding new error codes here. */ + + /** Other error */ + LIBUSB_ERROR_OTHER = -99 +}; + +/* Total number of error codes in enum libusb_error */ +#define LIBUSB_ERROR_COUNT 14 + +/** \ingroup libusb_asyncio + * Transfer type */ +enum libusb_transfer_type { + /** Control transfer */ + LIBUSB_TRANSFER_TYPE_CONTROL = 0U, + + /** Isochronous transfer */ + LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1U, + + /** Bulk transfer */ + LIBUSB_TRANSFER_TYPE_BULK = 2U, + + /** Interrupt transfer */ + LIBUSB_TRANSFER_TYPE_INTERRUPT = 3U, + + /** Bulk stream transfer */ + LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4U +}; + +/** \ingroup libusb_asyncio + * Transfer status codes */ +enum libusb_transfer_status { + /** Transfer completed without error. Note that this does not indicate + * that the entire amount of requested data was transferred. */ + LIBUSB_TRANSFER_COMPLETED, + + /** Transfer failed */ + LIBUSB_TRANSFER_ERROR, + + /** Transfer timed out */ + LIBUSB_TRANSFER_TIMED_OUT, + + /** Transfer was cancelled */ + LIBUSB_TRANSFER_CANCELLED, + + /** For bulk/interrupt endpoints: halt condition detected (endpoint + * stalled). For control endpoints: control request not supported. */ + LIBUSB_TRANSFER_STALL, + + /** Device was disconnected */ + LIBUSB_TRANSFER_NO_DEVICE, + + /** Device sent more data than requested */ + LIBUSB_TRANSFER_OVERFLOW + + /* NB! Remember to update libusb_error_name() + when adding new status codes here. */ +}; + +/** \ingroup libusb_asyncio + * libusb_transfer.flags values */ +enum libusb_transfer_flags { + /** Report short frames as errors */ + LIBUSB_TRANSFER_SHORT_NOT_OK = (1U << 0), + + /** Automatically free() transfer buffer during libusb_free_transfer(). + * Note that buffers allocated with libusb_dev_mem_alloc() should not + * be attempted freed in this way, since free() is not an appropriate + * way to release such memory. */ + LIBUSB_TRANSFER_FREE_BUFFER = (1U << 1), + + /** Automatically call libusb_free_transfer() after callback returns. + * If this flag is set, it is illegal to call libusb_free_transfer() + * from your transfer callback, as this will result in a double-free + * when this flag is acted upon. */ + LIBUSB_TRANSFER_FREE_TRANSFER = (1U << 2), + + /** Terminate transfers that are a multiple of the endpoint's + * wMaxPacketSize with an extra zero length packet. This is useful + * when a device protocol mandates that each logical request is + * terminated by an incomplete packet (i.e. the logical requests are + * not separated by other means). + * + * This flag only affects host-to-device transfers to bulk and interrupt + * endpoints. In other situations, it is ignored. + * + * This flag only affects transfers with a length that is a multiple of + * the endpoint's wMaxPacketSize. On transfers of other lengths, this + * flag has no effect. Therefore, if you are working with a device that + * needs a ZLP whenever the end of the logical request falls on a packet + * boundary, then it is sensible to set this flag on every + * transfer (you do not have to worry about only setting it on transfers + * that end on the boundary). + * + * This flag is currently only supported on Linux. + * On other systems, libusb_submit_transfer() will return + * \ref LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this + * flag is set. + * + * Available since libusb-1.0.9. + */ + LIBUSB_TRANSFER_ADD_ZERO_PACKET = (1U << 3) +}; + +/** \ingroup libusb_asyncio + * Isochronous packet descriptor. */ +struct libusb_iso_packet_descriptor { + /** Length of data to request in this packet */ + unsigned int length; + + /** Amount of data that was actually transferred */ + unsigned int actual_length; + + /** Status code for this packet */ + enum libusb_transfer_status status; +}; + +struct libusb_transfer; + +/** \ingroup libusb_asyncio + * Asynchronous transfer callback function type. When submitting asynchronous + * transfers, you pass a pointer to a callback function of this type via the + * \ref libusb_transfer::callback "callback" member of the libusb_transfer + * structure. libusb will call this function later, when the transfer has + * completed or failed. See \ref libusb_asyncio for more information. + * \param transfer The libusb_transfer struct the callback function is being + * notified about. + */ +typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); + +/** \ingroup libusb_asyncio + * The generic USB transfer structure. The user populates this structure and + * then submits it in order to request a transfer. After the transfer has + * completed, the library populates the transfer with the results and passes + * it back to the user. + */ +struct libusb_transfer { + /** Handle of the device that this transfer will be submitted to */ + libusb_device_handle *dev_handle; + + /** A bitwise OR combination of \ref libusb_transfer_flags. */ + uint8_t flags; + + /** Address of the endpoint where this transfer will be sent. */ + unsigned char endpoint; + + /** Type of the transfer from \ref libusb_transfer_type */ + unsigned char type; + + /** Timeout for this transfer in milliseconds. A value of 0 indicates no + * timeout. */ + unsigned int timeout; + + /** The status of the transfer. Read-only, and only for use within + * transfer callback function. + * + * If this is an isochronous transfer, this field may read COMPLETED even + * if there were errors in the frames. Use the + * \ref libusb_iso_packet_descriptor::status "status" field in each packet + * to determine if errors occurred. */ + enum libusb_transfer_status status; + + /** Length of the data buffer. Must be non-negative. */ + int length; + + /** Actual length of data that was transferred. Read-only, and only for + * use within transfer callback function. Not valid for isochronous + * endpoint transfers. */ + int actual_length; + + /** Callback function. This will be invoked when the transfer completes, + * fails, or is cancelled. */ + libusb_transfer_cb_fn callback; + + /** User context data. Useful for associating specific data to a transfer + * that can be accessed from within the callback function. + * + * This field may be set manually or is taken as the `user_data` parameter + * of the following functions: + * - libusb_fill_bulk_transfer() + * - libusb_fill_bulk_stream_transfer() + * - libusb_fill_control_transfer() + * - libusb_fill_interrupt_transfer() + * - libusb_fill_iso_transfer() */ + void *user_data; + + /** Data buffer */ + unsigned char *buffer; + + /** Number of isochronous packets. Only used for I/O with isochronous + * endpoints. Must be non-negative. */ + int num_iso_packets; + + /** Isochronous packet descriptors, for isochronous transfers only. */ + struct libusb_iso_packet_descriptor iso_packet_desc[LIBUSB_FLEXIBLE_ARRAY]; +}; + +/** \ingroup libusb_misc + * Capabilities supported by an instance of libusb on the current running + * platform. Test if the loaded library supports a given capability by calling + * \ref libusb_has_capability(). + */ +enum libusb_capability { + /** The libusb_has_capability() API is available. */ + LIBUSB_CAP_HAS_CAPABILITY = 0x0000U, + + /** Hotplug support is available on this platform. */ + LIBUSB_CAP_HAS_HOTPLUG = 0x0001U, + + /** The library can access HID devices without requiring user intervention. + * Note that before being able to actually access an HID device, you may + * still have to call additional libusb functions such as + * \ref libusb_detach_kernel_driver(). */ + LIBUSB_CAP_HAS_HID_ACCESS = 0x0100U, + + /** The library supports detaching of the default USB driver, using + * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ + LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101U +}; + +/** \ingroup libusb_lib + * Log message levels. + */ +enum libusb_log_level { + /** (0) : No messages ever emitted by the library (default) */ + LIBUSB_LOG_LEVEL_NONE = 0, + + /** (1) : Error messages are emitted */ + LIBUSB_LOG_LEVEL_ERROR = 1, + + /** (2) : Warning and error messages are emitted */ + LIBUSB_LOG_LEVEL_WARNING = 2, + + /** (3) : Informational, warning and error messages are emitted */ + LIBUSB_LOG_LEVEL_INFO = 3, + + /** (4) : All messages are emitted */ + LIBUSB_LOG_LEVEL_DEBUG = 4 +}; + +/** \ingroup libusb_lib + * Log callback mode. + * + * Since version 1.0.23, \ref LIBUSB_API_VERSION >= 0x01000107 + * + * \see libusb_set_log_cb() + */ +enum libusb_log_cb_mode { + /** Callback function handling all log messages. */ + LIBUSB_LOG_CB_GLOBAL = (1 << 0), + + /** Callback function handling context related log messages. */ + LIBUSB_LOG_CB_CONTEXT = (1 << 1) +}; + +/** \ingroup libusb_lib + * Available option values for libusb_set_option() and libusb_init_context(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * This option must be provided an argument of type \ref libusb_log_level. + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this option does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this option does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this option + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL = 0, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set at initialization with libusb_init_context() + * otherwise unspecified behavior may occur. + * + * Only valid on Windows. Ignored on all other platforms. + */ + LIBUSB_OPTION_USE_USBDK = 1, + + /** Do not scan for devices + * + * With this option set, libusb will skip scanning devices in + * libusb_init_context(). + * + * Hotplug functionality will also be deactivated. + * + * The option is useful in combination with libusb_wrap_sys_device(), + * which can access a device directly without prior device scanning. + * + * This is typically needed on Android, where access to USB devices + * is limited. + * + * This option should only be used with libusb_init_context() + * otherwise unspecified behavior may occur. + * + * Only valid on Linux. Ignored on all other platforms. + */ + LIBUSB_OPTION_NO_DEVICE_DISCOVERY = 2, + +#define LIBUSB_OPTION_WEAK_AUTHORITY LIBUSB_OPTION_NO_DEVICE_DISCOVERY + + /** Set the context log callback function. + * + * Set the log callback function either on a context or globally. This + * option must be provided an argument of type \ref libusb_log_cb. + * Using this option with a NULL context is equivalent to calling + * libusb_set_log_cb() with mode \ref LIBUSB_LOG_CB_GLOBAL. + * Using it with a non-NULL context is equivalent to calling + * libusb_set_log_cb() with mode \ref LIBUSB_LOG_CB_CONTEXT. + */ + LIBUSB_OPTION_LOG_CB = 3, + + LIBUSB_OPTION_MAX = 4 +}; + +/** \ingroup libusb_desc + * The device string type. + */ +enum libusb_device_string_type { + LIBUSB_DEVICE_STRING_MANUFACTURER, + LIBUSB_DEVICE_STRING_PRODUCT, + LIBUSB_DEVICE_STRING_SERIAL_NUMBER, + LIBUSB_DEVICE_STRING_COUNT /* The total number of string types. */ +}; + +/** \ingroup libusb_desc + * The maximum length for a device string descriptor in UTF-8. + * + * 255 max descriptor length with 2 byte header + * => 253 bytes UTF-16LE, no null termination (USB 2.0 9.6.7) + * => 126.5 codepoints + * => 126 * 3 + 1 + * => 382 bytes + * + * Stay with 256 * 2/3 = 384 to be safe. + */ +#define LIBUSB_DEVICE_STRING_BYTES_MAX (384U) + +/** \ingroup libusb_lib + * Callback function for handling log messages. + * \param ctx the context which is related to the log message, or NULL if it + * is a global log message + * \param level the log level, see \ref libusb_log_level for a description + * \param str the log message + * + * Since version 1.0.23, \ref LIBUSB_API_VERSION >= 0x01000107 + * + * \see libusb_set_log_cb() + */ +typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, + enum libusb_log_level level, const char *str); + +/** \ingroup libusb_lib + * Structure used for setting options through \ref libusb_init_context. + * + */ +struct libusb_init_option { + /** Which option to set */ + enum libusb_option option; + /** An integer value used by the option (if applicable). */ + union { + int ival; + libusb_log_cb log_cbval; + } value; +}; + +int LIBUSB_CALL libusb_init(libusb_context **ctx); +int LIBUSB_CALL libusb_init_context(libusb_context **ctx, const struct libusb_init_option options[], int num_options); +void LIBUSB_CALL libusb_exit(libusb_context *ctx); +void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); +/* may be deprecated in the future in favor of lubusb_init_context()+libusb_set_option() */ +void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); +const struct libusb_version * LIBUSB_CALL libusb_get_version(void); +int LIBUSB_CALL libusb_has_capability(uint32_t capability); +const char * LIBUSB_CALL libusb_error_name(int error_code); +int LIBUSB_CALL libusb_setlocale(const char *locale); +const char * LIBUSB_CALL libusb_strerror(int errcode); + +ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, + libusb_device ***list); +void LIBUSB_CALL libusb_free_device_list(libusb_device **list, + int unref_devices); +libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); +void LIBUSB_CALL libusb_unref_device(libusb_device *dev); + +int LIBUSB_CALL libusb_get_device_string(libusb_device *dev, + enum libusb_device_string_type string_type, char *data, int length); +int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, + int *config); +int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, + struct libusb_device_descriptor *desc); +int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, + struct libusb_config_descriptor **config); +int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, + uint8_t config_index, struct libusb_config_descriptor **config); +int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, + uint8_t bConfigurationValue, struct libusb_config_descriptor **config); +void LIBUSB_CALL libusb_free_config_descriptor( + struct libusb_config_descriptor *config); +int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( + libusb_context *ctx, + const struct libusb_endpoint_descriptor *endpoint, + struct libusb_ss_endpoint_companion_descriptor **ep_comp); +void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( + struct libusb_ss_endpoint_companion_descriptor *ep_comp); +int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, + struct libusb_bos_descriptor **bos); +void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); +int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( + libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension); +void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor( + struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension); +int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor( + libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap); +void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor( + struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap); +int LIBUSB_CALL libusb_get_ssplus_usb_device_capability_descriptor( + libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_ssplus_usb_device_capability_descriptor **ssplus_usb_device_cap); +void LIBUSB_CALL libusb_free_ssplus_usb_device_capability_descriptor( + struct libusb_ssplus_usb_device_capability_descriptor *ssplus_usb_device_cap); +int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_container_id_descriptor **container_id); +void LIBUSB_CALL libusb_free_container_id_descriptor( + struct libusb_container_id_descriptor *container_id); +int LIBUSB_CALL libusb_get_platform_descriptor(libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_platform_descriptor **platform_descriptor); +void LIBUSB_CALL libusb_free_platform_descriptor( + struct libusb_platform_descriptor *platform_descriptor); +unsigned long LIBUSB_CALL libusb_get_session_data(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev); +int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len); +LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers) +int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *path, uint8_t path_length); +libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); +int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); +int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, + unsigned char endpoint); +int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, + unsigned char endpoint); +int LIBUSB_CALL libusb_get_max_alt_packet_size(libusb_device *dev, + int interface_number, int alternate_setting, unsigned char endpoint); + +int LIBUSB_CALL libusb_get_interface_association_descriptors(libusb_device *dev, + uint8_t config_index, struct libusb_interface_association_descriptor_array **iad_array); +int LIBUSB_CALL libusb_get_active_interface_association_descriptors(libusb_device *dev, + struct libusb_interface_association_descriptor_array **iad_array); +void LIBUSB_CALL libusb_free_interface_association_descriptors( + struct libusb_interface_association_descriptor_array *iad_array); + +int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle); +int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); +void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); +libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); + +int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, + int configuration); +int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, + int interface_number); + +libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( + libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); + +int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, + int interface_number, int alternate_setting); +int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, + unsigned char endpoint); +int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); + +int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints); +int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, + unsigned char *endpoints, int num_endpoints); + +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length); +int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length); + +int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( + libusb_device_handle *dev_handle, int enable); + +int LIBUSB_CALL libusb_endpoint_supports_raw_io(libusb_device_handle* dev_handle, + uint8_t endpoint); +int LIBUSB_CALL libusb_endpoint_set_raw_io(libusb_device_handle *dev_handle, + uint8_t endpoint, int enable); +int LIBUSB_CALL libusb_get_max_raw_io_transfer_size( + libusb_device_handle *dev_handle, + uint8_t endpoint); + +/* async I/O */ + +/** \ingroup libusb_asyncio + * Get the data section of a control transfer. This convenience function is here + * to remind you that the data does not start until 8 bytes into the actual + * buffer, as the setup packet comes first. + * + * Calling this function only makes sense from a transfer callback function, + * or situations where you have already allocated a suitably sized buffer at + * transfer->buffer. + * + * \param transfer a transfer + * \returns pointer to the first byte of the data section + */ +static inline unsigned char *libusb_control_transfer_get_data( + struct libusb_transfer *transfer) +{ + return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; +} + +/** \ingroup libusb_asyncio + * Get the control setup packet of a control transfer. This convenience + * function is here to remind you that the control setup occupies the first + * 8 bytes of the transfer data buffer. + * + * Calling this function only makes sense from a transfer callback function, + * or situations where you have already allocated a suitably sized buffer at + * transfer->buffer. + * + * \param transfer a transfer + * \returns a casted pointer to the start of the transfer data buffer + */ +static inline struct libusb_control_setup *libusb_control_transfer_get_setup( + struct libusb_transfer *transfer) +{ + return (struct libusb_control_setup *)(void *)transfer->buffer; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the setup packet (first 8 bytes of the data + * buffer) for a control transfer. The wIndex, wValue and wLength values should + * be given in host-endian byte order. + * + * \param buffer buffer to output the setup packet into + * This pointer must be aligned to at least 2 bytes boundary. + * \param bmRequestType see the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field of + * \ref libusb_control_setup + * \param bRequest see the + * \ref libusb_control_setup::bRequest "bRequest" field of + * \ref libusb_control_setup + * \param wValue see the + * \ref libusb_control_setup::wValue "wValue" field of + * \ref libusb_control_setup + * \param wIndex see the + * \ref libusb_control_setup::wIndex "wIndex" field of + * \ref libusb_control_setup + * \param wLength see the + * \ref libusb_control_setup::wLength "wLength" field of + * \ref libusb_control_setup + */ +static inline void libusb_fill_control_setup(unsigned char *buffer, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + uint16_t wLength) +{ + struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *)buffer; + setup->bmRequestType = bmRequestType; + setup->bRequest = bRequest; + setup->wValue = libusb_cpu_to_le16(wValue); + setup->wIndex = libusb_cpu_to_le16(wIndex); + setup->wLength = libusb_cpu_to_le16(wLength); +} + +struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); +int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); +int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); +void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); +void LIBUSB_CALL libusb_transfer_set_stream_id( + struct libusb_transfer *transfer, uint32_t stream_id); +uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( + struct libusb_transfer *transfer); + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a control transfer. + * + * If you pass a transfer buffer to this function, the first 8 bytes will + * be interpreted as a control setup packet, and the wLength field will be + * used to automatically populate the \ref libusb_transfer::length "length" + * field of the transfer. Therefore the recommended approach is: + * -# Allocate a suitably sized data buffer (including space for control setup) + * -# Call libusb_fill_control_setup() + * -# If this is a host-to-device transfer with a data stage, put the data + * in place after the setup packet + * -# Call this function + * -# Call libusb_submit_transfer() + * + * It is also legal to pass a NULL buffer to this function, in which case this + * function will not attempt to populate the length field. Remember that you + * must then populate the buffer and length fields later. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param buffer data buffer. If provided, this function will interpret the + * first 8 bytes as a setup packet and infer the transfer length from that. + * This pointer must be aligned to at least 2 bytes boundary. + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_control_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, + unsigned int timeout) +{ + struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *)buffer; + transfer->dev_handle = dev_handle; + transfer->endpoint = 0; + transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; + transfer->timeout = timeout; + transfer->buffer = buffer; + if (setup) + transfer->length = (int) (LIBUSB_CONTROL_SETUP_SIZE + + libusb_le16_to_cpu(setup->wLength)); + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a bulk transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, + void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_BULK; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a bulk transfer using bulk streams. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param stream_id bulk stream id for this transfer + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_bulk_stream_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, uint32_t stream_id, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, + void *user_data, unsigned int timeout) +{ + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, + length, callback, user_data, timeout); + transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; + libusb_transfer_set_stream_id(transfer, stream_id); +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for an interrupt transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_interrupt_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *buffer, int length, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for an isochronous transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param num_iso_packets the number of isochronous packets + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, int num_iso_packets, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->num_iso_packets = num_iso_packets; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Convenience function to set the length of all packets in an isochronous + * transfer, based on the num_iso_packets field in the transfer structure. + * + * \param transfer a transfer + * \param length the length to set in each isochronous packet descriptor + * \see libusb_get_max_packet_size() + */ +static inline void libusb_set_iso_packet_lengths( + struct libusb_transfer *transfer, unsigned int length) +{ + int i; + + for (i = 0; i < transfer->num_iso_packets; i++) + transfer->iso_packet_desc[i].length = length; +} + +/** \ingroup libusb_asyncio + * Convenience function to locate the position of an isochronous packet + * within the buffer of an isochronous transfer. + * + * This is a thorough function which loops through all preceding packets, + * accumulating their lengths to find the position of the specified packet. + * Typically you will assign equal lengths to each packet in the transfer, + * and hence the above method is sub-optimal. You may wish to use + * libusb_get_iso_packet_buffer_simple() instead. + * + * \param transfer a transfer + * \param packet the packet to return the address of + * \returns the base address of the packet buffer inside the transfer buffer, + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer_simple() + */ +static inline unsigned char *libusb_get_iso_packet_buffer( + struct libusb_transfer *transfer, unsigned int packet) +{ + int i; + size_t offset = 0; + int _packet; + + /* oops..slight bug in the API. packet is an unsigned int, but we use + * signed integers almost everywhere else. range-check and convert to + * signed to avoid compiler warnings. FIXME for libusb-2. */ + if (packet > INT_MAX) + return NULL; + _packet = (int) packet; + + if (_packet >= transfer->num_iso_packets) + return NULL; + + for (i = 0; i < _packet; i++) + offset += transfer->iso_packet_desc[i].length; + + return transfer->buffer + offset; +} + +/** \ingroup libusb_asyncio + * Convenience function to locate the position of an isochronous packet + * within the buffer of an isochronous transfer, for transfers where each + * packet is of identical size. + * + * This function relies on the assumption that every packet within the transfer + * is of identical size to the first packet. Calculating the location of + * the packet buffer is then just a simple calculation: + * buffer + (packet_size * packet) + * + * Do not use this function on transfers other than those that have identical + * packet lengths for each packet. + * + * \param transfer a transfer + * \param packet the packet to return the address of + * \returns the base address of the packet buffer inside the transfer buffer, + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer() + */ +static inline unsigned char *libusb_get_iso_packet_buffer_simple( + struct libusb_transfer *transfer, unsigned int packet) +{ + int _packet; + + /* oops..slight bug in the API. packet is an unsigned int, but we use + * signed integers almost everywhere else. range-check and convert to + * signed to avoid compiler warnings. FIXME for libusb-2. */ + if (packet > INT_MAX) + return NULL; + _packet = (int) packet; + + if (_packet >= transfer->num_iso_packets) + return NULL; + + return transfer->buffer + ((int) transfer->iso_packet_desc[0].length * _packet); +} + +/* sync I/O */ + +int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout); + +int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, + int *transferred, unsigned int timeout); + +int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, + int *transferred, unsigned int timeout); + +/** \ingroup libusb_desc + * Retrieve a descriptor from the default control pipe. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. + * + * \param dev_handle a device handle + * \param desc_type the descriptor type, see \ref libusb_descriptor_type + * \param desc_index the index of the descriptor to retrieve + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + */ +static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, + uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) +{ + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), + 0, data, (uint16_t) length, 1000); +} + +/** \ingroup libusb_desc + * Retrieve a descriptor from a device. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. The string returned is Unicode, as + * detailed in the USB specifications. + * + * \param dev_handle a device handle + * \param desc_index the index of the descriptor to retrieve + * \param langid the language ID for the string descriptor + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + * \see libusb_get_string_descriptor_ascii() + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, + uint8_t desc_index, uint16_t langid, unsigned char *data, int length) +{ + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), + langid, data, (uint16_t) length, 1000); +} + +int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, + uint8_t desc_index, unsigned char *data, int length); + +/* polling and timeouts */ + +int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); +void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); +void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); +int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); +int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); +void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx); +void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); +void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); +int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); + +int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv); +int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, + struct timeval *tv, int *completed); +int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); +int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); +int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, + struct timeval *tv); +int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); +int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, + struct timeval *tv); + +/** \ingroup libusb_poll + * File descriptor for polling + */ +struct libusb_pollfd { + /** Numeric file descriptor */ + int fd; + + /** Event flags to poll for from . POLLIN indicates that you + * should monitor this file descriptor for becoming ready to read from, + * and POLLOUT indicates that you should monitor this file descriptor for + * nonblocking write readiness. */ + short events; +}; + +/** \ingroup libusb_poll + * Callback function, invoked when a new file descriptor should be added + * to the set of file descriptors monitored for events. + * \param fd the new file descriptor + * \param events events to monitor for, see \ref libusb_pollfd for a + * description + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, + void *user_data); + +/** \ingroup libusb_poll + * Callback function, invoked when a file descriptor should be removed from + * the set of file descriptors being monitored for events. After returning + * from this callback, do not use that file descriptor again. + * \param fd the file descriptor to stop monitoring + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); + +const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( + libusb_context *ctx); +void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds); +void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, + libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, + void *user_data); + +/** \ingroup libusb_hotplug + * Callback handle. + * + * Callbacks handles are generated by libusb_hotplug_register_callback() + * and can be used to deregister callbacks. Callback handles are unique + * per libusb_context and it is safe to call libusb_hotplug_deregister_callback() + * on an already deregistered callback. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * For more information, see \ref libusb_hotplug. + */ +typedef int libusb_hotplug_callback_handle; + +/** \ingroup libusb_hotplug + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * Hotplug events */ +typedef enum { + /** A device has been plugged in and is ready to use */ + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = (1 << 0), + + /** A device has left and is no longer available. + * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. + * It is safe to call libusb_get_device_descriptor on a device that has left */ + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = (1 << 1) +} libusb_hotplug_event; + +/** \ingroup libusb_hotplug + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * Hotplug flags */ +typedef enum { + /** Arm the callback and fire it for all matching currently attached devices. */ + LIBUSB_HOTPLUG_ENUMERATE = (1 << 0) +} libusb_hotplug_flag; + +/** \ingroup libusb_hotplug + * Convenience macro when not using any flags */ +#define LIBUSB_HOTPLUG_NO_FLAGS 0 + +/** \ingroup libusb_hotplug + * Wildcard matching for hotplug events */ +#define LIBUSB_HOTPLUG_MATCH_ANY -1 + +/** \ingroup libusb_hotplug + * Hotplug callback function type. When requesting hotplug event notifications, + * you pass a pointer to a callback function of this type. + * + * This callback may be called by an internal event thread and as such it is + * recommended the callback do minimal processing before returning. + * + * libusb will call this function later, when a matching event had happened on + * a matching device. See \ref libusb_hotplug for more information. + * + * It is safe to call either libusb_hotplug_register_callback() or + * libusb_hotplug_deregister_callback() from within a callback function. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param ctx context of this notification + * \param device libusb_device this event occurred on + * \param event event that occurred + * \param user_data user data provided when this callback was registered + * \returns bool whether this callback is finished processing events. + * returning 1 will cause this callback to be deregistered + */ +typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, + libusb_device *device, libusb_hotplug_event event, void *user_data); + +/** \ingroup libusb_hotplug + * Register a hotplug callback function + * + * Register a callback with the libusb_context. The callback will fire + * when a matching event occurs on a matching device. The callback is + * armed until either it is deregistered with libusb_hotplug_deregister_callback() + * or the supplied callback returns 1 to indicate it is finished processing events. + * + * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be + * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices + * already plugged into the machine. Note that libusb modifies its internal + * device list from a separate thread, while calling hotplug callbacks from + * libusb_handle_events(), so it is possible for a device to already be present + * on, or removed from, its internal device list, while the hotplug callbacks + * still need to be dispatched. This means that when using \ref + * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival + * of the same device, once from libusb_hotplug_register_callback() and once + * from libusb_handle_events(); and/or your callback may be called for the + * removal of a device for which an arrived call was never made. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param[in] ctx context to register this callback with + * \param[in] events bitwise or of hotplug events that will trigger this callback. + * See \ref libusb_hotplug_event + * \param[in] flags bitwise or of hotplug flags that affect registration. + * See \ref libusb_hotplug_flag + * \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] cb_fn the function to be invoked on a matching event/device + * \param[in] user_data user data to pass to the callback function + * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) + * \returns \ref LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure + */ +int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, + int events, int flags, + int vendor_id, int product_id, int dev_class, + libusb_hotplug_callback_fn cb_fn, void *user_data, + libusb_hotplug_callback_handle *callback_handle); + +/** \ingroup libusb_hotplug + * Deregisters a hotplug callback. + * + * Deregister a callback from a libusb_context. This function is safe to call from within + * a hotplug callback. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param[in] ctx context this callback is registered with + * \param[in] callback_handle the handle of the callback to deregister + */ +void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle); + +/** \ingroup libusb_hotplug + * Gets the user_data associated with a hotplug callback. + * + * Since version v1.0.24 \ref LIBUSB_API_VERSION >= 0x01000108 + * + * \param[in] ctx context this callback is registered with + * \param[in] callback_handle the handle of the callback to get the user_data of + */ +void * LIBUSB_CALL libusb_hotplug_get_user_data(libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle); + +int LIBUSB_CALLV libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Android_App/app/src/main/cpp/deps/librador/librador_global.h b/Android_App/app/src/main/cpp/deps/librador/librador_global.h new file mode 100644 index 000000000..929e6c720 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/librador_global.h @@ -0,0 +1,22 @@ +#ifndef LIBRADOR_GLOBAL_H +#define LIBRADOR_GLOBAL_H + +#ifdef FORCE_COMPILATION_FOR_QT5 + #include +#else + #if defined(_WIN32) || defined(_WIN64) + #define Q_DECL_EXPORT __declspec(dllexport) + #define Q_DECL_IMPORT + #else + #define Q_DECL_EXPORT + #define Q_DECL_IMPORT + #endif +#endif + +#if defined(LIBRADOR_LIBRARY) +# define LIBRADORSHARED_EXPORT Q_DECL_EXPORT +#else +# define LIBRADORSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // LIBRADOR_GLOBAL_H diff --git a/Android_App/app/src/main/cpp/deps/librador/librador_internal.h b/Android_App/app/src/main/cpp/deps/librador/librador_internal.h new file mode 100644 index 000000000..29dad6741 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/librador_internal.h @@ -0,0 +1,26 @@ +#ifndef LIBRADOR_INTERNAL_H +#define LIBRADOR_INTERNAL_H + +#endif // LIBRADOR_INTERNAL_H + +#define LABRADOR_VID 0x03eb +#define LABRADOR_PID 0xba94 + +#define CHECK_API_INITIALISED if(!internal_librador_object) return -420; +#define CHECK_USB_INITIALISED if(!internal_librador_object->usb_driver->connected) return -421; + +#define VECTOR_API_INIT_CHECK if(!internal_librador_object) return nullptr; +#define VECTOR_USB_INIT_CHECK if(!internal_librador_object->usb_driver->connected) return nullptr; + + +class usbCallHandler; + +class Librador +{ + +public: + Librador(); + usbCallHandler *usb_driver = nullptr; +}; + +Librador *internal_librador_object = nullptr; diff --git a/Android_App/app/src/main/cpp/deps/librador/logging.h b/Android_App/app/src/main/cpp/deps/librador/logging.h new file mode 100644 index 000000000..972cfc170 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/logging.h @@ -0,0 +1,11 @@ +#ifndef LOGGING_H +#define LOGGING_H + +enum { + LOG_NONE = 0, + LOG_ERROR, + LOG_WARNING, + LOG_DEBUG, +}; + +#endif // LOGGING_H diff --git a/Android_App/app/src/main/cpp/deps/librador/logging_internal.h b/Android_App/app/src/main/cpp/deps/librador/logging_internal.h new file mode 100644 index 000000000..3e757b709 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/logging_internal.h @@ -0,0 +1,26 @@ +#ifndef LOGGING_INTERNAL_H +#define LOGGING_INTERNAL_H + +#include "logging.h" +#include +#define LOG_TAG "librador" +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) +#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) + +#ifdef LIBRADOR_ENABLE_LOGGING + #define LIBRADOR_LOG(level, ...) \ + do \ + { \ + librador_global_logger(level, __VA_ARGS__); \ + } while (0) +#else + #define LIBRADOR_LOG(level, ...) \ + do \ + { \ + /* Logging is disabled */ \ + } while (0) +#endif // LIBRADOR_DISABLE_LOGGING + +void librador_global_logger(const int level, const char* format, ...); + +#endif // LOGGING_INTERNAL_H diff --git a/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp b/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp new file mode 100644 index 000000000..ffa99aa5d --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp @@ -0,0 +1,451 @@ +#include "o1buffer.h" +#include "logging_internal.h" +#include +#include +#include + +#include "uartstyledecoder.h" + + +//TODO: incorporate mostRecentAddressPaused into getSinceLast? +//TODO: triggering is finicky when the trigger level is ~0 b/c m_triggerSensitivity becomes too small? +std::mutex buffer_related_settings_mutex; + +//o1buffer is an object that has o(1) access times for its elements. +//At the moment it's basically an array, but I'm keeping it as an object so it can be changed to something more memory efficient later. +//See isobuffer in github.com/espotek-org/labrador for an example of a much more compact (RAM-wise) buffer. +o1buffer::o1buffer(double sps) +{ + buffer = (int *) (malloc(sizeof(int)*NUM_SAMPLES_PER_CHANNEL)); + buffer_paused = (int *) (malloc(sizeof(int)*NUM_SAMPLES_PER_CHANNEL)); + m_is_triggered = (bool *) (malloc(sizeof(bool)*NUM_SAMPLES_PER_CHANNEL)); + m_samples_per_second = sps; + m_uart_decoder = new uartStyleDecoder(this); +} + +o1buffer::~o1buffer(){ + free(buffer); + free(buffer_paused); + free(m_is_triggered); + delete m_uart_decoder; +} + +int o1buffer::reset(bool hard){ + mostRecentAddress = 0; + stream_index_at_last_call = 0; + if(hard){ + for (int i=0; i= NUM_SAMPLES_PER_CHANNEL){ + address = address % NUM_SAMPLES_PER_CHANNEL; + } + if(address<0){ + LIBRADOR_LOG(LOG_ERROR, "ERROR: o1buffer::add was given a negative address\n"); + } + //Assign the value + buffer[address] = value; + updateMostRecentAddress(address); +} + +int o1buffer::addVector(int *firstElement, int numElements){ + int currentAddress = mostRecentAddress; + + buffer_related_settings_mutex.lock(); + for(int i=0; i< numElements; i++){ + add(firstElement[i], currentAddress); + checkTriggered(currentAddress); + currentAddress = (currentAddress + 1) % NUM_SAMPLES_PER_CHANNEL; + } + buffer_related_settings_mutex.unlock(); + return 0; +} + +int o1buffer::addVector(char *firstElement, int numElements){ + int currentAddress = mostRecentAddress; + + buffer_related_settings_mutex.lock(); + for(int i=0; i< numElements; i++){ + add(firstElement[i], currentAddress); + checkTriggered(currentAddress); + currentAddress = (currentAddress + 1) % NUM_SAMPLES_PER_CHANNEL; + } + buffer_related_settings_mutex.unlock(); + + return 0; +} + +int o1buffer::addVector(unsigned char *firstElement, int numElements){ + int currentAddress = mostRecentAddress; + + buffer_related_settings_mutex.lock(); + for(int i=0; i< numElements; i++){ + add(firstElement[i], currentAddress); + checkTriggered(currentAddress); + currentAddress = (currentAddress + 1) % NUM_SAMPLES_PER_CHANNEL; + } + buffer_related_settings_mutex.unlock(); + return 0; +} + +int o1buffer::addVector(short *firstElement, int numElements){ + int currentAddress = mostRecentAddress; + + buffer_related_settings_mutex.lock(); + for(int i=0; i< numElements; i++){ + #ifdef MULTIMETER_INVERT + add(-firstElement[i] >> 4, currentAddress); + #else + add(firstElement[i] >> 4, currentAddress); + #endif + checkTriggered(currentAddress); + currentAddress = (currentAddress + 1) % NUM_SAMPLES_PER_CHANNEL; + } + buffer_related_settings_mutex.unlock(); + return 0; +} + + +int o1buffer::get(int address){ + int *read_buffer; + if(m_virtual_transform_settings.is_paused) { + read_buffer = buffer_paused; + } else { + read_buffer = buffer; + } + + //Ensure that the address is not too high. + if(address >= NUM_SAMPLES_PER_CHANNEL){ + address = address % NUM_SAMPLES_PER_CHANNEL; + } + if(address<0){ + LIBRADOR_LOG(LOG_ERROR, "ERROR: o1buffer::get was given a negative address\n"); + } + //Return the value + return read_buffer[address]; +} + +inline void o1buffer::updateMostRecentAddress(int newAddress){ + mostRecentAddress = newAddress; +} + +//This function places samples in a buffer than can be plotted on the streamingDisplay. +//A small delay, is added in case the packets arrive out of order. +std::vector *o1buffer::getMany_double(int numToGet, double interval_samples, int delay_samples, int filter_mode, double scope_gain, bool twelve_bit_multimeter){ + //Resize the vector + convertedStream_double.resize(numToGet); + + //Copy raw samples out. + int tempAddress; + double window_mean; + + if(m_virtual_transform_settings.is_ac) + { + tempAddress = (m_virtual_transform_settings.is_paused ? mostRecentAddressPaused : mostRecentAddress) - delay_samples - round(interval_samples*numToGet/2.); + if(tempAddress < 0) + tempAddress += NUM_SAMPLES_PER_CHANNEL; + window_mean = get_filtered_sample(tempAddress, 1, round(interval_samples * numToGet), scope_gain, twelve_bit_multimeter); + m_ac_offset_adc_units = inverseSampleConvert(window_mean + (twelve_bit_multimeter ? 0 : voltage_ref), scope_gain, twelve_bit_multimeter); + } else { + m_ac_offset_adc_units = 0; + } + + for(int i=0;i *o1buffer::getMany_singleBit(int numToGet, double interval_subsamples, int delay_subsamples){ + //Resize the vector + convertedStream_double.resize(numToGet); + + //Copy raw samples out. + int tempAddress; + int subsample_current_delay; + uint8_t mask; + double *data = convertedStream_double.data(); + int tempInt; + + for(int i=0;i *o1buffer::getSinceLast(int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode, double scope_gain, bool twelve_bit_multimeter){ + + //Calculate what sample the feasible window begins at + //printf_debugging("o1buffer::getSinceLast()\n") + int feasible_start_point = mostRecentAddress - feasible_window_begin; + if(feasible_start_point < 0){ + feasible_start_point += NUM_SAMPLES_PER_CHANNEL; + } + + //Work out whether or not we're starting from the feasible window or the last point + int actual_start_point; + if(distanceFromMostRecentAddress(feasible_start_point) > distanceFromMostRecentAddress(stream_index_at_last_call + interval_samples)){ + actual_start_point = stream_index_at_last_call + interval_samples; + } else { + actual_start_point = feasible_start_point; + } + + //Work out how much we're copying + int actual_sample_distance = distanceFromMostRecentAddress(actual_start_point) - distanceFromMostRecentAddress(mostRecentAddress - feasible_window_end); + int numToGet = actual_sample_distance/interval_samples; + //printf_debugging("Fetching %d samples, starting at index %d with interval %d\n", numToGet, actual_start_point, interval_samples); + + //Set up the buffer + convertedStream_double.resize(numToGet); + + //Copy raw samples out. + int tempAddress = stream_index_at_last_call; + for(int i=0;i= NUM_SAMPLES_PER_CHANNEL){ + tempAddress -= NUM_SAMPLES_PER_CHANNEL; + } + double *data = convertedStream_double.data(); + if(m_virtual_transform_settings.is_ac) + data[numToGet-1-i] = m_virtual_transform_settings.gain * (get_filtered_sample(tempAddress, 0, interval_samples, scope_gain, twelve_bit_multimeter) - get_filtered_sample(tempAddress, 1, actual_sample_distance, scope_gain, twelve_bit_multimeter)) + m_virtual_transform_settings.offset; + else + data[numToGet-1-i] = m_virtual_transform_settings.gain * get_filtered_sample(tempAddress, filter_mode, interval_samples, scope_gain, twelve_bit_multimeter) + m_virtual_transform_settings.offset; + //convertedStream_double.replace(i, buffer[tempAddress]); + } + + //update stream_index_at_last_call for next call + stream_index_at_last_call = tempAddress; + + return &convertedStream_double; +} + +int o1buffer::distanceFromMostRecentAddress(int index){ + //Standard case. buffer[NUM_SAMPLES_PER_CHANNEL] not crossed between most recent and index's sample writes. + if(index < mostRecentAddress){ + return mostRecentAddress - index; + } + + //Corner case. buffer[NUM_SAMPLES_PER_CHANNEL] boundary has been crossed. + if(index > mostRecentAddress){ + //Two areas. 0 to mostRecentAddress, and index to the end of the buffer. + return mostRecentAddress + (NUM_SAMPLES_PER_CHANNEL - index); + } + + //I guess the other corner case is when the addresses are the same. + return 0; +} + +//replace with get_filtered_sample +double o1buffer::get_filtered_sample(int index, int filter_type, int filter_size, double scope_gain, bool twelve_bit_multimeter){ + double accum = 0; + int currentPos = index - (filter_size / 2); + int end = currentPos + filter_size; + int *read_buffer; + if(m_virtual_transform_settings.is_paused) { + read_buffer = buffer_paused; + } else { + read_buffer = buffer; + } + + switch(filter_type){ + case 0: //No filter +// buffer[index]; + return sampleConvert(read_buffer[index], scope_gain, twelve_bit_multimeter); + case 1: //Moving Average filter + if(currentPos < 0){ + currentPos += NUM_SAMPLES_PER_CHANNEL; + } + if(end >= NUM_SAMPLES_PER_CHANNEL){ + end -= NUM_SAMPLES_PER_CHANNEL; + } + while(currentPos != end){ + accum += read_buffer[currentPos]; + currentPos = (currentPos + 1) % NUM_SAMPLES_PER_CHANNEL; + } + return sampleConvert(accum/((double)filter_size), scope_gain, twelve_bit_multimeter); + break; + default: //Default to "no filter" + return read_buffer[index]; + } +} + +double o1buffer::sampleConvert(int sample, double scope_gain, bool twelve_bit_multimeter) const { + double voltageLevel; + double TOP; + + if(twelve_bit_multimeter){ + TOP = 2048; + } else TOP = 128; + + voltageLevel = ((double)sample * (vcc/2)) / (frontendGain * scope_gain * TOP); + if (!twelve_bit_multimeter) voltageLevel += voltage_ref; + + return voltageLevel; +} + +short o1buffer::inverseSampleConvert(double voltageLevel, double scope_gain, bool twelve_bit_multimeter) const { + double TOP; + + if(twelve_bit_multimeter){ + TOP = 2048; + } else TOP = 128; + + if (!twelve_bit_multimeter) voltageLevel -= voltage_ref; + + short sample = round( (voltageLevel * (frontendGain * scope_gain * TOP)) / (vcc/2) ); + + return sample; +} + +// gets called by setsettingsforchannel in usbcallhandler.h +void o1buffer::resetTrigger(double scope_gain, bool twelve_bit_multimeter) +{ + double TOP; + + if(twelve_bit_multimeter){ + TOP = 2048; + } else TOP = 128; + + // user sets m_trigger_settings.trigger_level based on what they see in the waveform that includes virtual transforms; these transforms are compensated for in actual_trigger_level + double actual_trigger_level = (m_trigger_settings.trigger_level - m_virtual_transform_settings.offset)/m_virtual_transform_settings.gain; + + short new_triggerLevelADC = inverseSampleConvert(actual_trigger_level, scope_gain, twelve_bit_multimeter); + buffer_related_settings_mutex.lock(); + memset(m_is_triggered, false, sizeof(bool) * NUM_SAMPLES_PER_CHANNEL); + m_triggerSeekState = TriggerSeekState::Invalid; + m_triggerLevelADC = new_triggerLevelADC; + m_triggerSensitivity = static_cast((1 + abs(actual_trigger_level * kTriggerSensitivityMultiplier )) * TOP / 128.); + buffer_related_settings_mutex.unlock(); + + LOGI("Trigger Level: %d", m_triggerLevelADC); + LOGI("Trigger sensitivity: %d", m_triggerSensitivity); +} + + +void o1buffer::checkTriggered(int mostRecentAddress) { + if (m_trigger_settings.trigger_type == TriggerType::Disabled) + return; + m_is_triggered[mostRecentAddress] = false; + + if (buffer[mostRecentAddress] >= ((m_triggerLevelADC + m_ac_offset_adc_units) + m_triggerSensitivity)) + { + // Rising Edge + if((m_triggerSeekState == TriggerSeekState::BelowTriggerLevel) && (m_trigger_settings.trigger_type == TriggerType::Rising)) + m_is_triggered[mostRecentAddress] = true; + m_triggerSeekState = TriggerSeekState::AboveTriggerLevel; + } + else if (buffer[mostRecentAddress] < ((m_triggerLevelADC + m_ac_offset_adc_units) - m_triggerSensitivity)) + { + // Falling Edge + if((m_triggerSeekState == TriggerSeekState::AboveTriggerLevel) && (m_trigger_settings.trigger_type == TriggerType::Falling)) + m_is_triggered[mostRecentAddress] = true; + m_triggerSeekState = TriggerSeekState::BelowTriggerLevel; + } +} + +int o1buffer::getDelayIncludingFromTrigger(int delay_samples, int window_samples, bool* single_shot_reached, int* trigger_delay_out) { + int tempAddress = mostRecentAddress - delay_samples; + if((m_trigger_settings.trigger_type == TriggerType::Disabled) || (m_virtual_transform_settings.is_paused)) + return delay_samples; +// for (int i=0; i<(NUM_SAMPLES_PER_CHANNEL - delay_samples - window_samples); i++) { + for (int trigger_delay=0; trigger_delayUartDecode(); +} + +void o1buffer::setUartDecodeSettings(UartSettings new_settings) +{ + m_uart_decoder->setSettings(new_settings); +} + +char * o1buffer::getUart_String(bool* parity_check) +{ + return m_uart_decoder->getString(parity_check); +} diff --git a/Android_App/app/src/main/cpp/deps/librador/o1buffer.h b/Android_App/app/src/main/cpp/deps/librador/o1buffer.h new file mode 100644 index 000000000..d84726725 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/o1buffer.h @@ -0,0 +1,90 @@ +#ifndef O1BUFFER_H +#define O1BUFFER_H + +#include +#include +#include +#include + +#define NUM_SAMPLES_PER_CHANNEL (375000 * 10) //10 seconds of samples at 375ksps! +#define MULTIMETER_INVERT + +class uartStyleDecoder; +struct UartSettings; + +class o1buffer +{ +public: + enum TriggerType {Disabled, Rising, Falling}; + struct trigger_settings { + TriggerType trigger_type = TriggerType::Disabled; + float trigger_level = 0.f; + bool is_single_shot = false; + bool operator==(const trigger_settings& other) const{ + return (trigger_type == other.trigger_type) && (trigger_level == other.trigger_level) && (is_single_shot == other.is_single_shot); + } + }; + struct virtual_transform_settings { + float offset = 0.f; + int gain = 1; + bool is_ac = false; + bool is_paused = false; + bool operator==(const virtual_transform_settings& other) const{ + return (offset == other.offset) && (gain == other.gain) && (is_ac == other.is_ac) && (is_paused == other.is_paused); + } + }; + o1buffer(double sps); + ~o1buffer(); + int reset(bool hard); + void add(int value, int address); + int addVector(int *firstElement, int numElements); + int addVector(char *firstElement, int numElements); + int addVector(unsigned char *firstElement, int numElements); + int addVector(short *firstElement, int numElements); + int get(int address); + int mostRecentAddress = 0; + int mostRecentAddressPaused = 0; + int stream_index_at_last_call = 0; + int distanceFromMostRecentAddress(int index); + void resetTrigger(double scope_gain, bool twelve_bit_multimeter); + std::vector *getMany_double(int numToGet, double interval_samples, int delay_sample, int filter_mode, double scope_gain, bool twelve_bit_multimeter); + std::vector *getMany_singleBit(int numToGet, double interval_subsamples, int delay_subsamples); + std::vector *getSinceLast(int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode, double scope_gain, bool twelve_bit_multimeter); + double vcc = 3.3; + double frontendGain = (75.0/1075.0); + double voltage_ref = 1.65; + int setPaused(bool is_paused, int mostRecentAddressDelta = 0, bool hard = false); + bool getPaused(); + bool setTriggerSettings(trigger_settings new_trigger_settings); + bool setVirtualTransformSettings(virtual_transform_settings new_virtual_transform_settings); + void setUartDecodeSettings(UartSettings new_settings); + bool isTriggeringEnabled(); + int getDelayIncludingFromTrigger(int delay_samples, int window_samples, bool* single_shot_reached = NULL, int* trigger_delay_out = NULL); + double m_samples_per_second; + int m_bufferLen = NUM_SAMPLES_PER_CHANNEL; + void UartDecode(); + char * getUart_String(bool* parity_check); +private: + trigger_settings m_trigger_settings; + virtual_transform_settings m_virtual_transform_settings; + int *buffer; + int *buffer_paused; + bool *m_is_triggered; + std::vector convertedStream_double; + std::vector convertedStream_digital; + void updateMostRecentAddress(int newAddress); + double get_filtered_sample(int index, int filter_type, int filter_size, double scope_gain, bool twelve_bit_multimeter); + double sampleConvert(int sample, double scope_gain, bool twelve_bit_multimeter) const; + short inverseSampleConvert(double voltageLevel, double scope_gain, bool twelve_bit_multimeter) const; + enum TriggerSeekState {Invalid, AboveTriggerLevel, BelowTriggerLevel}; + TriggerSeekState m_triggerSeekState = TriggerSeekState::Invalid; + short m_triggerLevelADC; + short m_triggerSensitivity; + const double kTriggerSensitivityMultiplier = 4; + void checkTriggered(int mostRecentAddress); + int m_ac_offset_adc_units = 0; + void computeTriggerLevel(); + uartStyleDecoder* m_uart_decoder = NULL; +}; + +#endif // O1BUFFER_H diff --git a/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp b/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp new file mode 100644 index 000000000..3a304507c --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp @@ -0,0 +1,241 @@ +#include "uartstyledecoder.h" +#include + +uartStyleDecoder::uartStyleDecoder(o1buffer *parent) : + m_serialBuffer{SERIAL_BUFFER_LENGTH}, + m_parent(parent) +{ +} + + +void uartStyleDecoder::UartDecode() +{ + if(!m_settings.decode_on) + return; + if(switched_on) { + m_serialBuffer.clear(); + // Begin decoding SAMPLE_DELAY seconds in the past. + serialPtr_bit = (int)(m_parent->mostRecentAddress * 8 - SERIAL_DELAY * m_parent->m_samples_per_second * 8 + m_parent->m_bufferLen * 8) % (m_parent->m_bufferLen*8); + switched_on = false; + } + double dist_seconds = (double)serialDistance()/(8 * m_parent->m_samples_per_second); + double bitPeriod_seconds = 1.0 / m_settings.baudRate; + + // Used to check for wire disconnects. You should get at least one "1" for a stop bit. + allZeroes = true; + + while(dist_seconds > (bitPeriod_seconds + SERIAL_DELAY)) + { + // Read next uart bit + bool uart_bit = getNextUartBit(); + + if (uart_bit == 1) + allZeroes = false; + + // Process it + if (uartTransmitting) + { + decodeNextUartBit(uart_bit); + } + else + { + // Uart starts transmitting after start bit (logic low). + uartTransmitting = uart_bit == false; + jitterCompensationNeeded = true; + } + + // Update the pointer, accounting for jitter + updateSerialPtr(uart_bit); + // Calculate stopping condition + dist_seconds = (double)serialDistance()/(8*m_parent->m_samples_per_second); + } + + //Not a single stop bit, or idle bit, in the whole stream. Wire must be disconnected. + if (allZeroes) + { + LOGW("Wire Disconnect detected!"); + } +} + +int uartStyleDecoder::serialDistance() const +{ + int back_bit = m_parent->mostRecentAddress * 8; + int bufferEnd_bit = (m_parent->m_bufferLen-1) * 8; + if (back_bit >= serialPtr_bit) + return back_bit - serialPtr_bit; + else + return bufferEnd_bit - serialPtr_bit + back_bit; +} + +void uartStyleDecoder::updateSerialPtr(bool current_bit) +{ + if (jitterCompensationNeeded && uartTransmitting) + jitterCompensationNeeded = jitterCompensationProcedure(current_bit); + + int distance_between_bits = (8*m_parent->m_samples_per_second)/ m_settings.baudRate; + if (uartTransmitting) + serialPtr_bit += distance_between_bits; + else + serialPtr_bit += (distance_between_bits - 1); //Less than one baud period so that it will always see that start bit. + + if (serialPtr_bit >= (m_parent->m_bufferLen * 8)) + serialPtr_bit -= (m_parent->m_bufferLen * 8); +} + +bool uartStyleDecoder::getNextUartBit() const +{ + int bitIndex = serialPtr_bit; + + int coord_byte = bitIndex/8; + int coord_bit = bitIndex - (8*coord_byte); + uint8_t dataByte = m_parent->get(coord_byte); + uint8_t mask = (0x01 << coord_bit); + return dataByte & mask; +} + +void uartStyleDecoder::decodeNextUartBit(bool bitValue) +{ + if (dataBit_current == parityIndex) + { + parityCheckFailed = !isParityCorrect(currentUartSymbol, bitValue); + dataBit_current++; + } + else if (dataBit_current < dataBit_max) + { + currentUartSymbol |= (bitValue << dataBit_current); + dataBit_current++; + } + else + { + char decodedDatabit = currentUartSymbol; + +// if (parityCheckFailed) +// { +// m_serialBuffer.insert("\n\n"); +// } + + // Start + body of escape code + if(decodedDatabit == 0x1b || (escape_code_started && !((decodedDatabit >= 'A' && decodedDatabit <= 'Z') || (decodedDatabit >= 'a' && decodedDatabit <= 'z')))) + { + escape_code_started = true; + } + // End of escape code + else if(escape_code_started && ((decodedDatabit >= 'A' && decodedDatabit <= 'Z') || (decodedDatabit >= 'a' && decodedDatabit <= 'z'))) + { + escape_code_started = false; + } + else + { + if (m_hexDisplay) + { + m_serialBuffer.insert_hex(decodedDatabit); + m_serialBuffer.insert(" "); + } + else + { + if(decodedDatabit=='\0') { + if(!allZeroes) + m_serialBuffer.insert("\\0"); //insert escaped null terminator in place of null terminator + } else { + m_serialBuffer.insert(decodedDatabit); + } + } + } + + currentUartSymbol = 0; + dataBit_current = 0; + uartTransmitting = false; + } +} + +//This function compensates for jitter by, when the current bit is a "1", and the last bit was a zero, setting the pointer +//to the sample at the midpoint between this bit and the last. +bool uartStyleDecoder::jitterCompensationProcedure(bool current_bit) +{ + + //We only run when the current bit is a "1", to prevent slowdown when there are long breaks between transmissions. + if (current_bit == false) + return true; + + //Can't be bothered dealing with the corner case where the serial pointer is at the very start of the buffer. + //Just return and try again next time. + int left_coord = serialPtr_bit - (8*m_parent->m_samples_per_second)/ m_settings.baudRate; + LOGI("left_coord = %d", left_coord); + if (left_coord < 0) + return true; //Don't want to read out of bounds!! + + //The usual case, when transmitting anyway. + uint8_t left_byte = (m_parent->get(left_coord/8) & 0xff); + //Only run when a zero is detected in the leftmost symbol. + if (left_byte != 0xff) + { + //Step back, one sample at a time, to the 0->1 transition point + bool temp_bit = 1; + while(temp_bit) + { + temp_bit = getNextUartBit(); + serialPtr_bit--; + } + //Jump the pointer forward by half a uart bit period, and return "done!". + serialPtr_bit += (8*m_parent->m_samples_per_second/ m_settings.baudRate)/2; + return false; + } + return true; +} + +char uartStyleDecoder::decodeBaudot(short symbol) const +{ + return 'a'; +} + +bool uartStyleDecoder::isParityCorrect(unsigned short bitField, bool bitValue) const +{ + assert(m_settings.parity != UartParity::None); + bitField |= (bitValue << parityIndex); + + return parityOf(bitField) == m_settings.parity; +} + +UartParity uartStyleDecoder::parityOf(unsigned short bitField) const +{ + bool result = false; + + for (uint32_t mask = 1 << dataBit_max; mask != 0; mask >>= 1) + result ^= static_cast(bitField & mask); + + return result ? UartParity::Odd : UartParity::Even; +} + +void uartStyleDecoder::setSettings(UartSettings new_settings) +{ + if(new_settings.decode_on && !m_settings.decode_on) { + switched_on = true; + } else if (!new_settings.decode_on) { + switched_on = false; + uartTransmitting = false; + escape_code_started = false; + } + + switch(new_settings.parity) + { + case UartParity::None: + parityIndex = UINT_MAX; + break; + case UartParity::Even: + case UartParity::Odd: + parityIndex = dataBit_max; + } + m_settings = new_settings; +} + +char * uartStyleDecoder::getString(bool* parity_check) +{ + if(m_settings.parity == UartParity::None) { + *parity_check = true; + } else { + *parity_check = !parityCheckFailed; + } + memcpy(convertedStream_string, m_serialBuffer.begin(), sizeof(char) * m_serialBuffer.size()); + convertedStream_string[m_serialBuffer.size()] = '\0'; + return convertedStream_string; +} diff --git a/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.h b/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.h new file mode 100644 index 000000000..b175c30f9 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.h @@ -0,0 +1,86 @@ +#ifndef UARTSTYLEDECODER_H +#define UARTSTYLEDECODER_H + +#include "isobufferbuffer.h" +#include "logging_internal.h" +#include "o1buffer.h" +#include +#include +#include +#include + +#define SERIAL_BUFFER_LENGTH 8192 + +constexpr double SERIAL_DELAY = 0.01; //100 baud? + +enum class UartParity : uint8_t +{ + None, + Even, + Odd +}; +struct UartSettings { + bool decode_on = false; + double baudRate = 300; + UartParity parity = UartParity::None; +}; + +class uartStyleDecoder +{ +public: + explicit uartStyleDecoder(o1buffer *parent); +private: + o1buffer *m_parent; + + // Indicates the current bit being decoded. + int serialPtr_bit; + + bool allZeroes = false; + bool uartTransmitting = false; + bool newUartSymbol = false; + uint32_t dataBit_current = 0; + uint32_t parityIndex = UINT_MAX; + uint32_t dataBit_max = 8; + unsigned short currentUartSymbol = 0; + bool jitterCompensationNeeded = true; + + void updateSerialPtr(bool current_bit); + bool getNextUartBit() const; + void decodeNextUartBit(bool bitValue); + bool jitterCompensationProcedure(bool current_bit); + + bool m_hexDisplay = false; + bool escape_code_started = false; + + char convertedStream_string[SERIAL_BUFFER_LENGTH + 1]; + isoBufferBuffer m_serialBuffer; + + bool switched_on = false; +public: + +// QTimer m_updateTimer; // IMPORTANT: must be after m_serialBuffer. construction / destruction order matters + void UartDecode(); + int serialDistance() const; + + void wireDisconnected(int ch); + + void updateConsole(); + + void setSettings(UartSettings new_settings); + + char * getString(bool* parity_check); +private: + char decodeDatabit(int mode, short symbol) const; + char decodeBaudot(short symbol) const; + + std::mutex mutex; + + bool isParityCorrect(unsigned short bitField, bool bitValue) const; + UartParity parityOf(unsigned short bitField) const; + + bool parityCheckFailed = false; + + UartSettings m_settings; +}; + +#endif // UARTSTYLEDECODER_H diff --git a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp new file mode 100644 index 000000000..4e1a07a4c --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp @@ -0,0 +1,935 @@ +#include "usbcallhandler.h" +//#include + +#include +#include "logging_internal.h" +#include "uartstyledecoder.h" + +#include +#include + +#include +#include +#include "SDL_android.h" + +void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){ + //Thread mutex?? + //printf("Copy the data...\n"); + usbCallHandler *usb_driver = (usbCallHandler *)transfer->user_data; + if(transfer->status==LIBUSB_TRANSFER_COMPLETED) + { + usb_driver->buffer_read_write_mutex.lock(); + for(int i=0;inum_iso_packets;i++){ + unsigned char *packetPointer = libusb_get_iso_packet_buffer_simple(transfer, i); + //TODO: a switch statement here to handle all the modes. + switch(usb_driver->deviceMode){ + case 0: + usb_driver->internal_o1_buffer_375_CHA->addVector((char*) packetPointer, 375); + break; + case 1: + usb_driver->internal_o1_buffer_375_CHA->addVector((char*) packetPointer, 375); + usb_driver->internal_o1_buffer_375_CHB->addVector((unsigned char*) &packetPointer[375], 375); + break; + case 2: + usb_driver->internal_o1_buffer_375_CHA->addVector((char*) packetPointer, 375); + usb_driver->internal_o1_buffer_375_CHB->addVector((char*) &packetPointer[375], 375); + break; + case 3: + usb_driver->internal_o1_buffer_375_CHA->addVector((unsigned char*) packetPointer, 375); + break; + case 4: + usb_driver->internal_o1_buffer_375_CHA->addVector((unsigned char*) packetPointer, 375); + usb_driver->internal_o1_buffer_375_CHB->addVector((unsigned char*) &packetPointer[375], 375); + break; + case 6: + usb_driver->internal_o1_buffer_750->addVector((char*) packetPointer, 750); + break; + case 7: + usb_driver->internal_o1_buffer_375_CHA->addVector((short*) packetPointer, 375); + break; + } + } + usb_driver->buffer_read_write_mutex.unlock(); + } + + //printf("Re-arm the endpoint...\n"); + if(!usb_driver->is_iso_thread_shutdown_requested()){ + int error = libusb_submit_transfer(transfer); + if(error){ + LOGW("Error re-arming the endpoint!\n"); + usb_driver->begin_iso_thread_shutdown(); + usb_driver->decrement_remaining_transfers(); + LOGW("Transfer not being rearmed! %d armed transfers remaining\n", usb_driver->iso_thread_shutdown_remaining_transfers); + } + } else { + usb_driver->decrement_remaining_transfers(); + LOGW("Transfer not being rearmed! %d armed transfers remaining\n", usb_driver->iso_thread_shutdown_remaining_transfers); + } + return; +} + +int usbCallHandler::begin_iso_thread_shutdown(){ + iso_thread_shutdown_mutex.lock(); + iso_thread_shutdown_requested = true; + iso_thread_shutdown_mutex.unlock(); + return 0; +} + +bool usbCallHandler::is_iso_thread_shutdown_requested(){ + bool tempReturn; + iso_thread_shutdown_mutex.lock(); + tempReturn = iso_thread_shutdown_requested; + iso_thread_shutdown_mutex.unlock(); + return tempReturn; +} + +int usbCallHandler::decrement_remaining_transfers(){ + iso_thread_shutdown_mutex.lock(); + iso_thread_shutdown_remaining_transfers--; + iso_thread_shutdown_mutex.unlock(); + return 0; +} + +bool usbCallHandler::safe_to_exit_thread(){ + bool tempReturn; + iso_thread_shutdown_mutex.lock(); + tempReturn = (iso_thread_shutdown_remaining_transfers == 0); + iso_thread_shutdown_mutex.unlock(); + return tempReturn; +} + + +// it makes sense to call this iso_polling_function because we only use libusb's asynchronous API for isochronous transfers +void usbCallHandler::iso_polling_function(libusb_context *ctx){ + LOGI("iso_polling_function thread spawned\n"); + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0;//ISO_PACKETS_PER_CTX*4000; + while(!safe_to_exit_thread()){ + //printf("iso_polling_function begin loop\n"); + if(libusb_event_handling_ok(ctx)){ + libusb_handle_events_timeout(ctx, &tv); + } + } + get_set_iso_thread_active_mutex.lock(); + iso_thread_active = false; + get_set_iso_thread_active_mutex.unlock(); + LOGI("iso_polling_function thread finished\n"); +} + +usbCallHandler::usbCallHandler(unsigned short VID_in, unsigned short PID_in) +{ + VID = VID_in; + PID = PID_in; + + for(int k=0; kjoin(); + LIBRADOR_LOG(LOG_DEBUG, "USB polling thread stopped.\n"); + delete iso_polling_thread; + + for (int i=0; iGetObjectClass(MainActivityObject)); + jfieldID bootloader_mode_allowedID = env->GetFieldID(MainActivity, "bootloader_mode_allowed", "Z"); + env->SetBooleanField(MainActivityObject, bootloader_mode_allowedID, allowed); + LOGI("bootloader_mode_allowed set"); +} + +// call sequence: usbcallhandler.cpp(requestFirmwareFlash) -> MainActivity.java -> librador -> here, all just to get a dialog window before reset_device (below) triggers a usb permission request +void usbCallHandler::initiateFirmwareFlash() +{ + set_bootloader_mode_allowed(true); + reset_device(true); // will trigger respondToStartupOrUsbStateChange with the device in bootloader mode. + connected = false; + libusb_release_interface(handle, 0); + libusb_close(handle); + libusb_exit(ctx); + ctx = nullptr; + handle= nullptr; +} + +//Initialise libusb +int usbCallHandler::init_libusb(){ + if(ctx){ + LOGI("There is already a libusb context!\n"); + return 1; + } else LOGI("libusb context is null\n"); + struct libusb_init_option libusb_options[2] = { + {.option = LIBUSB_OPTION_NO_DEVICE_DISCOVERY}, + {.option = LIBUSB_OPTION_LOG_LEVEL, .value = {.ival = 3}} + }; + int error = libusb_init_context(&ctx, libusb_options, 2); + if(error){ + LOGW("libusb_init FAILED\n"); + return -1; + } else { + LOGI("Libusb context initialised\n"); + return 0; + } +} + +int usbCallHandler::setup_usb_control(int file_descriptor){ + LOGI("usbCallHandler::setup_usb_control()\n"); + //Get a handle on the Labrador device + libusb_wrap_sys_device(ctx, file_descriptor, &handle); + + if(!handle){ + LOGI("DEVICE NOT FOUND\n"); + return -2; + } + LOGI("Device found!!\n"); + + if(libusb_kernel_driver_active(handle, 0)) { + LOGI("KERNEL DRIVER ACTIVE"); + } else { + LOGI("KERNEL DRIVER INACTIVE"); + } + if(libusb_kernel_driver_active(handle, 0)){ + libusb_detach_kernel_driver(handle, 0); + } + + //Claim the interface + int error = libusb_claim_interface(handle, 0); + if(error){ + LOGW("libusb_claim_interface FAILED\n"); + libusb_close(handle); + handle = nullptr; + return -3; + } else LOGI("Interface claimed!\n"); + return 0; +} + +// should only be called if iso_polling_thread is not active. This means either the thread has never been set up OR it was previously set up but has exited iso_polling_function. +int usbCallHandler::setup_usb_iso(){ + LOGI("usbCallHandler::setup_usb_iso()\n"); + if(iso_polling_thread) { + LOGI("iso polling thead already exists"); + return -1; + } else { + LOGI("creating iso polling thread"); + + alloc_iso_transfers(); + + int error = submit_iso_transfers(); + if(error) { + return error; + LOGW("setup_usb_iso failed\n"); + } + iso_polling_thread = new std::thread(&usbCallHandler::iso_polling_function, this, ctx); + iso_thread_active = true; + } + return 0; +} + +void usbCallHandler::alloc_iso_transfers(){ + for(int n=0;n 1 ms (amount of data per packet) * NUM_PACKETS_PER_CTX * NUM_FUTURE_CTX + libusb_set_iso_packet_lengths(isoCtx[k][n], ISO_PACKET_SIZE); + } + } +} + +int usbCallHandler::submit_iso_transfers(){ + for(int n=0;ntrfcntH0 << 8) + udsPtr->trfcntL0; + uint16_t trfcnt1 = (udsPtr->trfcntH1 << 8) + udsPtr->trfcntL1; + uint16_t medianTrfcnt = (udsPtr->medianTrfcntH << 8) + udsPtr->medianTrfcntL; + uint16_t outOfRange = (udsPtr->outOfRangeH << 8) + udsPtr->outOfRangeL; + uint16_t counter = (udsPtr->counterH << 8) + udsPtr->counterL; + uint16_t dma_ch0_cnt = (udsPtr->dma_ch0_cntH << 8) + udsPtr->dma_ch0_cntL; + uint16_t dma_ch1_cnt = (udsPtr->dma_ch1_cntH << 8) + udsPtr->dma_ch1_cntL; + + LIBRADOR_LOG(LOG_DEBUG, "%s", udsPtr->header); + LIBRADOR_LOG(LOG_DEBUG, "trfcnt0 = %d\n", trfcnt0); + LIBRADOR_LOG(LOG_DEBUG, "trfcnt1 = %d\n", trfcnt1); + LIBRADOR_LOG(LOG_DEBUG, "medianTrfcnt = %d\n", medianTrfcnt); + LIBRADOR_LOG(LOG_DEBUG, "outOfRange = %d\n", outOfRange); + LIBRADOR_LOG(LOG_DEBUG, "counter = %d\n", counter); + LIBRADOR_LOG(LOG_DEBUG, "calValNeg = %d\n", udsPtr->calValNeg); + LIBRADOR_LOG(LOG_DEBUG, "calValPos = %d\n", udsPtr->calValPos); + LIBRADOR_LOG(LOG_DEBUG, "CALA = %d\n", udsPtr->CALA); + LIBRADOR_LOG(LOG_DEBUG, "CALB = %d\n", udsPtr->CALB); + LIBRADOR_LOG(LOG_DEBUG, "dma_ch0_cnt = %d\n", dma_ch0_cnt); + LIBRADOR_LOG(LOG_DEBUG, "dma_ch1_cnt = %d\n", dma_ch1_cnt); + + return 0; +} + +std::vector* usbCallHandler::getMany_double(int channel, int numToGet, double interval_samples, int delay_sample, int filter_mode){ +std::vector* temp_to_return = nullptr; + +buffer_read_write_mutex.lock(); + int delay_including_trigger; + bool single_shot_reached = false; + int trigger_delay = 0; + switch(deviceMode){ + case 0: + if(channel == 1) { + delay_including_trigger = internal_o1_buffer_375_CHA->getDelayIncludingFromTrigger(delay_sample, round(interval_samples * numToGet)); + temp_to_return = internal_o1_buffer_375_CHA->getMany_double(numToGet, interval_samples, delay_including_trigger, filter_mode, current_scope_gain, false); + } + break; + case 1: + if(channel == 1) { + delay_including_trigger = internal_o1_buffer_375_CHA->getDelayIncludingFromTrigger(delay_sample, round(interval_samples * numToGet), &single_shot_reached, &trigger_delay); + internal_o1_buffer_375_CHB->setPaused(single_shot_reached,-trigger_delay, true); // dont multiply trigger_delay by 8 b/c each sample of the buffer is 8 subsamples + temp_to_return = internal_o1_buffer_375_CHA->getMany_double(numToGet, interval_samples, delay_including_trigger, filter_mode, current_scope_gain, false); + } + break; + case 2: + if(internal_o1_buffer_375_CHA->isTriggeringEnabled() && ((channel==1) || ((channel == 2) && !internal_o1_buffer_375_CHB->getPaused()))) { + delay_including_trigger = internal_o1_buffer_375_CHA->getDelayIncludingFromTrigger(delay_sample, round(interval_samples * numToGet), &single_shot_reached, &trigger_delay); + internal_o1_buffer_375_CHB->setPaused(single_shot_reached,-trigger_delay,true); // only relevant when single-shot triggering + } else if (internal_o1_buffer_375_CHB->isTriggeringEnabled() && ((channel==2) || ((channel == 1) && !internal_o1_buffer_375_CHA->getPaused()))) { + delay_including_trigger = internal_o1_buffer_375_CHB->getDelayIncludingFromTrigger(delay_sample, round(interval_samples * numToGet), &single_shot_reached, &trigger_delay); + internal_o1_buffer_375_CHA->setPaused(single_shot_reached,-trigger_delay,true);// only relevant when single-shot triggering + } else { + delay_including_trigger = delay_sample; + } + if(channel == 1) temp_to_return = internal_o1_buffer_375_CHA->getMany_double(numToGet, interval_samples, delay_including_trigger, filter_mode, current_scope_gain, false); + else if (channel == 2) temp_to_return = internal_o1_buffer_375_CHB->getMany_double(numToGet, interval_samples, delay_including_trigger, filter_mode, current_scope_gain, false); + break; + case 6: + if(channel == 1){ + delay_including_trigger = internal_o1_buffer_750->getDelayIncludingFromTrigger(delay_sample, round(interval_samples * numToGet)); + temp_to_return = internal_o1_buffer_750->getMany_double(numToGet, interval_samples, delay_including_trigger, filter_mode, current_scope_gain, false); + } + break; + case 7: + if(channel == 1) { + delay_including_trigger = internal_o1_buffer_375_CHA->getDelayIncludingFromTrigger(delay_sample, round(interval_samples * numToGet)); + temp_to_return = internal_o1_buffer_375_CHA->getMany_double(numToGet, interval_samples, delay_including_trigger, filter_mode, current_scope_gain, true); + } + break; + } + buffer_read_write_mutex.unlock(); + return temp_to_return; +} + +std::vector * usbCallHandler::getMany_singleBit(int channel, int numToGet, double interval_subsamples, int delay_subsamples){ + std::vector* temp_to_return = nullptr; + + buffer_read_write_mutex.lock(); + switch(deviceMode){ + case 1: + if(channel == 2) + { + int delay_including_trigger; + if(internal_o1_buffer_375_CHA->isTriggeringEnabled()) { + bool single_shot_reached = false; + int trigger_delay = 0; + delay_including_trigger = internal_o1_buffer_375_CHA->getDelayIncludingFromTrigger(static_cast(round(delay_subsamples/8.)), round(interval_subsamples/8. * numToGet), &single_shot_reached, &trigger_delay) * 8; + internal_o1_buffer_375_CHB->setPaused(single_shot_reached,-trigger_delay, true); // dont multiply trigger_delay by 8 b/c each sample of the buffer is 8 subsamples + } else { + delay_including_trigger = delay_subsamples; + } + + temp_to_return = internal_o1_buffer_375_CHB->getMany_singleBit(numToGet, interval_subsamples, delay_including_trigger); + internal_o1_buffer_375_CHB->UartDecode(); + } + break; + case 3: + if(channel == 1) + { + temp_to_return = internal_o1_buffer_375_CHA->getMany_singleBit(numToGet, interval_subsamples, delay_subsamples); + internal_o1_buffer_375_CHA->UartDecode(); + } + break; + case 4: + if(channel == 1){ + temp_to_return = internal_o1_buffer_375_CHA->getMany_singleBit(numToGet, interval_subsamples, delay_subsamples); + internal_o1_buffer_375_CHA->UartDecode(); + } + else if (channel == 2){ + temp_to_return = internal_o1_buffer_375_CHB->getMany_singleBit(numToGet, interval_subsamples, delay_subsamples); + internal_o1_buffer_375_CHB->UartDecode(); + } + try + { + m_i2c_decoder->run(); + } + catch(...) + { + LOGI("Resetting I2C"); + m_i2c_decoder->reset(); + } + break; + } + buffer_read_write_mutex.unlock(); + return temp_to_return; +} + +char * usbCallHandler::getUart_String(int channel, bool* parity_check) +{ + char * temp_to_return = nullptr; + if(channel == 1) + temp_to_return = internal_o1_buffer_375_CHA->getUart_String(parity_check); + else if (channel == 2) + temp_to_return = internal_o1_buffer_375_CHB->getUart_String(parity_check); + return temp_to_return; +} + +std::vector *usbCallHandler::getMany_sincelast(int channel, int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode){ + std::vector* temp_to_return = nullptr; + buffer_read_write_mutex.lock(); + switch(deviceMode){ + case 0: + if(channel == 1) temp_to_return = internal_o1_buffer_375_CHA->getSinceLast(feasible_window_begin, feasible_window_end, interval_samples, filter_mode, current_scope_gain, false); + break; + case 1: + if(channel == 1) temp_to_return = internal_o1_buffer_375_CHA->getSinceLast(feasible_window_begin, feasible_window_end, interval_samples, filter_mode, current_scope_gain, false); + break; + case 2: + if(channel == 1) temp_to_return = internal_o1_buffer_375_CHA->getSinceLast(feasible_window_begin, feasible_window_end, interval_samples, filter_mode, current_scope_gain, false); + else if (channel == 2) temp_to_return = internal_o1_buffer_375_CHB->getSinceLast(feasible_window_begin, feasible_window_end, interval_samples, filter_mode, current_scope_gain, false); + break; + case 6: + if(channel == 1) temp_to_return = internal_o1_buffer_750->getSinceLast(feasible_window_begin, feasible_window_end, interval_samples, filter_mode, current_scope_gain, false); + break; + case 7: + if(channel == 1) temp_to_return = internal_o1_buffer_375_CHA->getSinceLast(feasible_window_begin, feasible_window_end, interval_samples, filter_mode, current_scope_gain, false); + break; + } + buffer_read_write_mutex.unlock(); + return temp_to_return; + +} + +int usbCallHandler::send_device_reset(){ + libusb_reset_device(handle); + return 0; +} + + +int usbCallHandler::set_device_mode(int mode){ + if((mode < 0) || (mode > MAX_SUPPORTED_DEVICE_MODE)){ + return -1; + } + deviceMode = mode; + send_control_transfer_with_error_checks(0x40, 0xa5, (mode == 5 ? 0 : mode), gainMask, 0, nullptr); + + send_function_gen_settings(1); + send_function_gen_settings(2); + + internal_o1_buffer_375_CHA->reset(false); + internal_o1_buffer_375_CHA->resetTrigger(current_scope_gain, deviceMode==7); + internal_o1_buffer_375_CHB->reset(false); + internal_o1_buffer_375_CHB->resetTrigger(current_scope_gain, deviceMode==7); + internal_o1_buffer_750->reset(false); + internal_o1_buffer_750->resetTrigger(current_scope_gain, deviceMode==7); + + return 0; +} + +int usbCallHandler::set_gain(double newGain){ + //See XMEGA_AU Manual, page 359. ADC.CTRL.GAIN. + if(newGain==0.5) gainMask = 0x07; + else if (newGain == 1) gainMask = 0x00; + else if (newGain == 2) gainMask = 0x01; + else if (newGain == 4) gainMask = 0x02; + else if (newGain == 8) gainMask = 0x03; + else if (newGain == 16) gainMask = 0x04; + else if (newGain == 32) gainMask = 0x05; + else if (newGain == 64) gainMask = 0x06; + else{ + LIBRADOR_LOG(LOG_ERROR, "Invalid gain value. Valid values are 0.1, 1, 2, 4, 8, 16, 32, 64\n"); + return -1; + } + + gainMask = gainMask << 2; + gainMask |= (gainMask << 8); + send_control_transfer_with_error_checks(0x40, 0xa5, deviceMode, gainMask, 0, nullptr); + current_scope_gain = newGain; + return 0; +} + +int usbCallHandler::update_function_gen_settings(int channel, unsigned char *sampleBuffer, int numSamples, double usecs_between_samples, double amplitude_v, double offset_v){ + + + //Parse the channel + fGenSettings *fGenSelected; + if(channel == 1){ + fGenSelected = &functionGen_CH1; + } else if (channel == 2){ + fGenSelected = &functionGen_CH2; + } else { + return -1; //Invalid channel + } + + //Update number of samples. + fGenSelected->numSamples = numSamples; + + //Does the output amplifier need to be enabled? + if ((amplitude_v+offset_v) > FGEN_LIMIT){ + amplitude_v = amplitude_v / 3; + offset_v = offset_v / 3; + if(channel == 1){ + fGenTriple |= 0b00000001; + } else { + fGenTriple |= 0b00000010; + } + } + else { + if(channel == 1){ + fGenTriple &= 0b11111110; + } else { + fGenTriple &= 0b11111101; + } + } + + //Fiddle with the waveform to deal with the fact that the Xmega has a minimum DAC output value. + double amplitude_sample = (amplitude_v * 255) / FGEN_LIMIT; + double offset_sample = (offset_v * 255) / FGEN_LIMIT; + if (offset_sample < FGEN_SAMPLE_MIN){ //If the offset is in the range where the XMEGA output cannot physically drive the signal that low... + if (amplitude_sample > FGEN_SAMPLE_MIN){ //And the amplitude of the signal can go above this minimum range + amplitude_sample -= FGEN_SAMPLE_MIN; //Then reduce the amplitude and add a small offset + } + else { + amplitude_sample = 0; + } + offset_sample = FGEN_SAMPLE_MIN; + } + + //Apply amplitude and offset scaling to all samples. + double tempDouble; + for (int i=0;isamples[i] = (uint8_t) tempDouble; + } + + //Calculate timer values + int validClockDivs[7] = {1, 2, 4, 8, 64, 256, 1024}; + + int clkSetting; + for(clkSetting = 0; clkSetting<7; clkSetting++){ + if ( ((XMEGA_MAIN_FREQ * usecs_between_samples)/(1000000 * validClockDivs[clkSetting])) < 65535) + break; + } + fGenSelected->timerPeriod = (usecs_between_samples * XMEGA_MAIN_FREQ) / (1000000 * validClockDivs[clkSetting]) - 0.5; + fGenSelected->clockDividerSetting = clkSetting + 1; + + return 0; +} + +int usbCallHandler::send_function_gen_settings(int channel){ + if(channel == 1){ + if(functionGen_CH1.numSamples == 0){ + return -1; //Channel not initialised + } + send_control_transfer_with_error_checks(0x40, 0xa2, functionGen_CH1.timerPeriod, functionGen_CH1.clockDividerSetting, functionGen_CH1.numSamples, functionGen_CH1.samples); + } else if (channel == 2){ + if(functionGen_CH2.numSamples == 0){ + return -1; //Channel not initialised + } + send_control_transfer_with_error_checks(0x40, 0xa1, functionGen_CH2.timerPeriod, functionGen_CH2.clockDividerSetting, functionGen_CH2.numSamples, functionGen_CH2.samples); + } else { + return -2; //Invalid channel + } + send_control_transfer_with_error_checks(0x40, 0xa4, fGenTriple, 0, 0, nullptr); + return 0; +} + +int usbCallHandler::set_psu_voltage(double voltage){ + double vinp = voltage/11; + double vinn = 0; + + uint8_t dutyPsu = (uint8_t) ((vinp - vinn)/vref_psu * gain_psu * PSU_ADC_TOP); + + + if ((dutyPsu>106) || (dutyPsu<21)){ + return -1; //Out of range + } + send_control_transfer_with_error_checks(0x40, 0xa3, dutyPsu, 0, 0, nullptr); + return 0; +} + +int usbCallHandler::set_digital_state(uint8_t digState){ + send_control_transfer_with_error_checks(0x40, 0xa6, digState, 0, 0, nullptr); + return 0; +} + +int usbCallHandler::reset_device(bool goToBootloader){ + LOGI("resetting device: unimportant error LIBUSB_ERROR_NO_DEVICE for send_control_transfer expected"); // only if goToBootloader? + send_control_transfer_with_error_checks(0x40, 0xa7, (goToBootloader ? 1 : 0), 0, 0, nullptr); + return 0; +} + +uint16_t usbCallHandler::get_firmware_version(){ + send_control_transfer_with_error_checks(0xc0, 0xa8, 0, 0, 2, nullptr); + return *((uint16_t *) inBuffer); +} + +uint8_t usbCallHandler::get_firmware_variant(){ + send_control_transfer_with_error_checks(0xc0, 0xa9, 0, 0, 1, nullptr); + return *((uint8_t *) inBuffer); +} + +double usbCallHandler::get_samples_per_second(){ + switch(deviceMode){ + case 0: + return (double)(375000.0); + case 1: + return (double)(375000.0); + case 2: + return (double)(375000.0); + case 3: + return (double)(375000.0); + case 4: + return (double)(375000.0); + case 6: + return (double)(750000.0); + case 7: + return (double)(375000.0); + default: + return 0; + } +} + +int usbCallHandler::set_synchronous_pause_state(bool newState){ + if(newState && !synchronous_pause_state){ + buffer_read_write_mutex.lock(); + synchronous_pause_state = true; + return 0; + } + + if(!newState && synchronous_pause_state){ + buffer_read_write_mutex.unlock(); + return 0; + } + + //Otherwise you don't want to do anything. You should never set the state twice. + return 1; +} + +int usbCallHandler::setPaused(int channel, bool is_paused) +{ + if(channel==1){ + if(deviceMode==6) + return internal_o1_buffer_750->setPaused(is_paused); + else + return internal_o1_buffer_375_CHA->setPaused(is_paused); + } else if (channel == 2){ + return internal_o1_buffer_375_CHB->setPaused(is_paused); + } + return 1; +} + +bool usbCallHandler::getPaused(int channel) +{ + if(channel==1){ + if(deviceMode==6) + return internal_o1_buffer_750->getPaused(); + else + return internal_o1_buffer_375_CHA->getPaused(); + } else if (channel == 2){ + return internal_o1_buffer_375_CHB->getPaused(); + } + return 1; +} + +void usbCallHandler::setTriggerSettings(int channel, o1buffer::trigger_settings new_trigger_settings) +{ + setSettingsForChannel(channel, new_trigger_settings, internal_o1_buffer_375_CHA, internal_o1_buffer_375_CHB, internal_o1_buffer_750, &o1buffer::setTriggerSettings); +} + +void usbCallHandler::setVirtualTransformSettings(int channel, o1buffer::virtual_transform_settings new_virtual_transform_settings) +{ + setSettingsForChannel(channel, new_virtual_transform_settings, internal_o1_buffer_375_CHA, internal_o1_buffer_375_CHB, internal_o1_buffer_750, &o1buffer::setVirtualTransformSettings); +} + +void usbCallHandler::setUartDecodeSettings(int channel, UartSettings new_settings) +{ + if(channel==1) + internal_o1_buffer_375_CHA->setUartDecodeSettings(new_settings); + else if (channel==2) + internal_o1_buffer_375_CHB->setUartDecodeSettings(new_settings); +} + char *usbCallHandler::getI2c_String() +{ + return m_i2c_decoder->getString(); +} + +void usbCallHandler::setI2cIsDecoding(bool new_decode_on){ + m_i2c_decoder->setIsDecoding(new_decode_on); +} + +bool usbCallHandler::isoThreadIsActive(){ + bool tempReturn; + get_set_iso_thread_active_mutex.lock(); + tempReturn = iso_thread_active; + get_set_iso_thread_active_mutex.unlock(); + return tempReturn; +} + +int usbCallHandler::flashFirmware(int file_descriptor){ + + libusb_device *device_ptr; + + init_libusb(); + int error = setup_usb_control(file_descriptor); + + JNIEnv *env = (JNIEnv *) SDL_GetAndroidJNIEnv(); + jobject MainActivityObject = (jobject) SDL_GetAndroidActivity(); + jclass MainActivity(env->GetObjectClass(MainActivityObject)); + + jfieldID asset_manager_id = env->GetFieldID(MainActivity, "mgr", "Landroid/content/res/AssetManager;"); + jobject mgr_java = (jobject)env->GetObjectField(MainActivityObject, asset_manager_id); + const char* external_filepath = SDL_GetAndroidExternalStoragePath(); + AAssetManager * mgr = AAssetManager_fromJava(env, mgr_java); + + const char* firmware_filename = "labrafirm_0007_02.hex"; + char apk_firmware_filepath[64]; + strcpy(apk_firmware_filepath, "firmware/"); + strcat(apk_firmware_filepath, firmware_filename); + + char firmware_copy_filepath[256]; + strcpy(firmware_copy_filepath, external_filepath); + strcat(firmware_copy_filepath, "/"); + strcat(firmware_copy_filepath, firmware_filename); + LOGI("firmware copy path: %s", firmware_copy_filepath); + + AAsset* asset = AAssetManager_open(mgr, apk_firmware_filepath, AASSET_MODE_STREAMING); + char buf[2048]; + int nb_read = 0; + FILE* out = fopen(firmware_copy_filepath, "w+"); + while ((nb_read = AAsset_read(asset, buf, 2048)) > 0) + fwrite(buf, nb_read, 1, out); + fclose(out); + AAsset_close(asset); + + LOGI("FLASHING %s", firmware_copy_filepath); + + //Set up interface to dfuprog + int exit_code; + char command[256]; + + //Run stage 1 + LOGI("\n\nFlashing Firmware, stage 1.\n\n"); + snprintf(command, sizeof command, "dfu-programmer atxmega32a4u erase --force --debug 300"); + exit_code = dfuprog_virtual_cmd(command, device_ptr, handle, ctx, 0); + if (exit_code) { + LOGW("ERROR ERASING FIRMWARE."); + } else { + LOGI("ERASED FIRMWARE."); + } + ctx = nullptr; + handle= nullptr; + + init_libusb(); + error = setup_usb_control(file_descriptor); + + //Run stage 2 + LOGI("\n\nFlashing Firmware, stage 2.\n\n"); + snprintf(command, sizeof command, "dfu-programmer atxmega32a4u flash %s --debug 300", firmware_copy_filepath); + exit_code = dfuprog_virtual_cmd(command, device_ptr, handle, ctx, 0); + if (exit_code) { + LOGW("\n\n\nERROR WRITING NEW FIRMWARE TO DEVICE.\n\n\n"); + //return exit_code+200; + } + ctx = nullptr; + handle= nullptr; + + init_libusb(); + error = setup_usb_control(file_descriptor); + + //Run stage 3 + LOGI("\n\nFlashing Firmware, stage 3.\n\n"); + dfu_launch(); + starting_after_flash = true; + return 0; +} + +void usbCallHandler::dfu_launch() { + LOGI("\n\n\nDFU LAUNCH.\n\n\n"); + int exit_code; + char command[256]; + libusb_device *device_ptr; + snprintf(command, sizeof command, "dfu-programmer atxmega32a4u launch"); + exit_code = dfuprog_virtual_cmd(command, device_ptr, handle, ctx, 0); + if (exit_code) { + LOGW("\n\n\n DFU LAUNCH ERROR\n\n\n"); + //return exit_code+300; + } + ctx = nullptr; + handle= nullptr; +} + +void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int file_descriptor, bool bootloader_mode){ + if(is_plugged_in) { + if(bootloader_mode) { + LOGI("found in bootloader mode"); + if(starting_after_flash) { + LOGI("startup after flash"); + starting_after_flash = false; + init_libusb(); + int error = setup_usb_control(file_descriptor); + set_bootloader_mode_allowed(false); + dfu_launch();// launch twice to clear eeprom flag after flashing + + JNIEnv *env = (JNIEnv *) SDL_GetAndroidJNIEnv(); + jobject MainActivityObject = (jobject) SDL_GetAndroidActivity(); + jclass MainActivity(env->GetObjectClass(MainActivityObject)); + jmethodID confirmFirmwareFlashID = env->GetMethodID(MainActivity, "confirmFirmwareFlash", "()V"); + env->CallVoidMethod(MainActivityObject,confirmFirmwareFlashID); + } else { + int flashRet = flashFirmware(file_descriptor); + LOGI("flashRet: %d", flashRet); + } + } else { + if(connected) { + return; + } + init_libusb(); + int control_setup_success = setup_usb_control(file_descriptor); + if(control_setup_success==0) { + connected = true; + uint16_t firmver = get_firmware_version(); + LOGI("BOARD IS RUNNING FIRMWARE VERSION 0x%04hx", firmver); + LOGI("EXPECTING FIRMWARE VERSION 0x%04hx", EXPECTED_FIRMWARE_VERSION); + + uint8_t variant = get_firmware_variant(); + LOGI("FIRMWARE VARIANT = 0x%02hx", variant); + LOGI("EXPECTED VARIANT = 0x%02hx", DEFINED_EXPECTED_VARIANT); + + if((firmver != EXPECTED_FIRMWARE_VERSION) || (variant != DEFINED_EXPECTED_VARIANT)){ + LOGI("Unexpected Firmware!!"); + + JNIEnv *env = (JNIEnv *) SDL_GetAndroidJNIEnv(); + jobject MainActivityObject = (jobject) SDL_GetAndroidActivity(); + jclass MainActivity(env->GetObjectClass(MainActivityObject)); + jmethodID requestFirmwareFlashID = env->GetMethodID(MainActivity, "requestFirmwareFlash", "()V"); + env->CallVoidMethod(MainActivityObject,requestFirmwareFlashID); + + return; + } else { + int iso_setup_success = setup_usb_iso(); + return; + } + } else { + connected = false; + if(handle){ + libusb_release_interface(handle, 0); + libusb_close(handle); + handle = nullptr; + } + return; + } + } + } else { + connected = false; + if(iso_polling_thread) { + begin_iso_thread_shutdown(); + iso_polling_thread->join(); + delete iso_polling_thread; + +// prepare for possible replug + iso_thread_shutdown_requested = false; + iso_polling_thread = nullptr; + iso_thread_shutdown_remaining_transfers = NUM_FUTURE_CTX; + for (int i=0; i +#include +#include +#include + +#define NUM_ISO_ENDPOINTS (1) +#define NUM_FUTURE_CTX (4) +#define ISO_PACKET_SIZE (750) +#define ISO_PACKETS_PER_CTX (33) +#define MAX_SUPPORTED_DEVICE_MODE (7) +#define FGEN_LIMIT (3.2) +#define FGEN_MAX_SAMPLES (512) +#define FGEN_SAMPLE_MIN (5.0) +#define XMEGA_MAIN_FREQ (48000000) +#define PSU_ADC_TOP (128) + +#define EXPECTED_FIRMWARE_VERSION 0x0007 +#define DEFINED_EXPECTED_VARIANT 2 + +//EVERYTHING MUST BE SENT ONE BYTE AT A TIME, HIGH AND LOW BYTES SEPARATE, IN ORDER TO AVOID ISSUES WITH ENDIANNESS. +typedef struct uds{ + volatile char header[9]; + volatile uint8_t trfcntL0; + volatile uint8_t trfcntH0; + volatile uint8_t trfcntL1; + volatile uint8_t trfcntH1; + volatile uint8_t medianTrfcntL; + volatile uint8_t medianTrfcntH; + volatile uint8_t calValNeg; + volatile uint8_t calValPos; + volatile uint8_t CALA; + volatile uint8_t CALB; + volatile uint8_t outOfRangeL; + volatile uint8_t outOfRangeH; + volatile uint8_t counterL; + volatile uint8_t counterH; + volatile uint8_t dma_ch0_cntL; + volatile uint8_t dma_ch0_cntH; + volatile uint8_t dma_ch1_cntL; + volatile uint8_t dma_ch1_cntH; + +} unified_debug; + +typedef struct fGenSettings{ + uint8_t samples[FGEN_MAX_SAMPLES]; + int numSamples = 0; + uint16_t timerPeriod = 0; + uint8_t clockDividerSetting = 0; +} fGenSettings; + +#define send_control_transfer_with_error_checks(A, B, C, D, E, F) \ + int temp_control_transfer_error_value = send_control_transfer(A,B,C,D,E,F); \ + if(temp_control_transfer_error_value < 0){ \ + return temp_control_transfer_error_value - 1000; \ + } + +class usbCallHandler +{ +public: + usbCallHandler(unsigned short VID_in, unsigned short PID_in); + ~usbCallHandler(); + int setup_usb_control(int file_descriptor); + int setup_usb_iso(); + void alloc_iso_transfers(); + int submit_iso_transfers(); + void delete_iso_thread(); + int send_control_transfer(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA); + int avrDebug(void); + int send_device_reset(); + double get_samples_per_second(); + std::vector *getMany_double(int channel, int numToGet, double interval_samples, int delay_sample, int filter_mode); + std::vector * getMany_singleBit(int channel, int numToGet, double interval_subsamples, int delay_subsamples); + std::vector *getMany_sincelast(int channel, int feasible_window_begin, int feasible_window_end, int interval_samples, int filter_mode); + bool connected = false; + //Control Commands + int set_device_mode(int mode); + int set_gain(double newGain); + int update_function_gen_settings(int channel, unsigned char* sampleBuffer, int numSamples, double usecs_between_samples, double amplitude_v, double offset_v); + int send_function_gen_settings(int channel); + int set_psu_voltage(double voltage); + int set_digital_state(uint8_t digState); + int reset_device(bool goToBootloader); + uint16_t get_firmware_version(); + uint8_t get_firmware_variant(); + int set_synchronous_pause_state(bool newState); + int setPaused(int channel, bool is_paused); + bool getPaused(int channel); + void setTriggerSettings(int channel, o1buffer::trigger_settings new_trigger_settings); + void setVirtualTransformSettings(int channel, o1buffer::virtual_transform_settings new_virtual_transform_settings); + template + void setSettingsForChannel(int ch, T channel_scope_settings, o1buffer* ch1_375, o1buffer* ch2_375, o1buffer* ch1_750, bool (o1buffer::*setSettings)(T)); + void setUartDecodeSettings(int channel, UartSettings new_settings); + char * getUart_String(int channel, bool* parity_check); + char * getI2c_String(); + void setI2cIsDecoding(bool new_decode_on); + bool isoThreadIsActive(); + int init_libusb(); + void respondToStartupOrUsbStateChange(bool is_plugged_in, int file_descriptor, bool bootloader_mode); + void set_bootloader_mode_allowed(bool allowed); + void initiateFirmwareFlash(); +private: + + unsigned short VID, PID; + libusb_context *ctx = nullptr; + libusb_device_handle *handle = nullptr; + unsigned char inBuffer[256]; + + //USBIso Vars + unsigned char pipeID[NUM_ISO_ENDPOINTS]; + libusb_transfer *isoCtx[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX]; + unsigned char dataBuffer[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX][ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX]; + std::thread *iso_polling_thread = nullptr; + //Control Vars + uint8_t fGenTriple = 0; + fGenSettings functionGen_CH1; + fGenSettings functionGen_CH2; + double gain_psu = 1; + double vref_psu = 1.65; + uint16_t gainMask = 0x0000; + double current_scope_gain = 1; + bool synchronous_pause_state = false; + i2c::i2cDecoder* m_i2c_decoder; + + bool starting_after_flash = false; + + int flashFirmware(int file_descriptor); + void closeDevice_cpp(); + int findDevice_cpp(); + void dfu_launch(); + + friend void isoCallback(struct libusb_transfer * transfer); + int deviceMode = 0; + + o1buffer *internal_o1_buffer_375_CHA; + o1buffer *internal_o1_buffer_375_CHB; + o1buffer *internal_o1_buffer_750; + + int begin_iso_thread_shutdown(); + bool is_iso_thread_shutdown_requested(); + int decrement_remaining_transfers(); + void iso_polling_function(libusb_context *ctx); + bool safe_to_exit_thread(); + + + bool iso_thread_shutdown_requested = false; + int iso_thread_shutdown_remaining_transfers = NUM_FUTURE_CTX; + bool iso_thread_active = false; + + std::mutex iso_thread_shutdown_mutex; + std::mutex buffer_read_write_mutex; + std::mutex get_set_iso_thread_active_mutex; +}; + +template +void usbCallHandler::setSettingsForChannel(int ch, T channel_scope_settings, o1buffer* ch1_375, o1buffer* ch2_375, o1buffer* ch1_750, bool (o1buffer::*setSettings)(T)) +{ + bool trigger_reset_needed; + if(ch==1) { + trigger_reset_needed = (ch1_375->*setSettings)(channel_scope_settings); + if(trigger_reset_needed) + ch1_375->resetTrigger(current_scope_gain, deviceMode==7); + trigger_reset_needed = (ch1_750->*setSettings)(channel_scope_settings); + if(trigger_reset_needed) + ch1_750->resetTrigger(current_scope_gain, deviceMode==7); + } else if (ch==2) { + trigger_reset_needed = (ch2_375->*setSettings)(channel_scope_settings); + if(trigger_reset_needed) + ch2_375->resetTrigger(current_scope_gain, deviceMode==7); + } +} +#endif // USBCALLHANDLER_H diff --git a/Android_App/app/src/main/cpp/inputs_ui.cpp b/Android_App/app/src/main/cpp/inputs_ui.cpp new file mode 100644 index 000000000..d64e38236 --- /dev/null +++ b/Android_App/app/src/main/cpp/inputs_ui.cpp @@ -0,0 +1,220 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "librador.h" +#include "custom_imgui.h" +#include +#include "imgui_internal.h" +#include "inputs_ui.h" + +ImVec2 center_text(float col_width, float text_width, ImGuiStyle& style) { + return ImGui::GetCursorScreenPos() + ImVec2((col_width - text_width)/2. - style.CellPadding.x, 0.0); // for centered text +} + +ImVec2 center_checkbox_delta(float full_col_width, ImGuiStyle& style) { + return ImVec2((full_col_width - CHECKBOX_SIZE)/2. - style.CellPadding.x, 0.0); // for centered checkbox +} + +void draw_rules(ImVec2 p0, double row_height, double header_row_height, double col_width) +{ + ImGuiStyle& style = ImGui::GetStyle(); + ImVec2 row1_col1_pos = p0 + ImVec2(col_width, header_row_height); + ImVec2 row1_col2_pos = row1_col1_pos + ImVec2(col_width,0); + ImVec2 row3_col2_pos = row1_col1_pos + ImVec2(col_width,2*row_height); + ImVec2 row4_col1_pos = row1_col1_pos + ImVec2(0.,3*row_height); + ImVec2 row4_col2_pos = row1_col1_pos + ImVec2(col_width,3*row_height); + ImVec2 row5_col2_pos = row1_col1_pos + ImVec2(col_width,4*row_height); + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddLine(row1_col1_pos, row4_col1_pos, IM_COL32(120, 120, 160, 255)); + draw_list->AddLine(row1_col2_pos, row3_col2_pos, IM_COL32(120, 120, 160, 255)); + draw_list->AddLine(row4_col2_pos, row5_col2_pos, IM_COL32(120, 120, 160, 255)); +} + +void inputsUI::draw(float width_pixels, inputsUI* inputs_ui) +{ + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::BeginGroup(); + standard_header(width_pixels); + if(!is_expanded) + { + ImGui::EndGroup(); + return; + } + ImVec2 start_pos = ImGui::GetCursorScreenPos(); + + bool mode_update = false; + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(style.CellPadding.x, style.CellPadding.y * 2));// if this line is active, make sure that the line that resets CellPadding at the end of this function is active as well + float header_row_height = ImGui::GetFontSize() + style.CellPadding.y*2; + float row_height = (ImGui::GetFontSize() + (style.FramePadding.y + style.CellPadding.y)*2); + float col_width; + if (ImGui::BeginTable("scope_mode", 3, ImGuiTableFlags_SizingStretchSame|ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg , ImVec2(width_pixels,0.f))) + { + ImGui::TableNextRow(); + int i = 0; + for(const char * ch_header : {"1","2","CH"}) + { + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(center_text(ImGui::GetColumnWidth() + 2*style.CellPadding.x, ImGui::CalcTextSize(ch_header).x, style)); + ImGui::Text("%s", ch_header); + col_width = ImGui::GetColumnWidth() + 2 * style.CellPadding.x; + i+=1; + ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ImGui::GetColorU32(ImGuiCol_TableHeaderBg) ); + } + + bool scope_checkbox_enable[2] = { + !logic_enable[1] && !mm, + scope_enable[0] && !(logic_enable[0]) && !scope750 + }; + bool logic_checkbox_enable[2] = { + !scope_enable[1] && !scope750 && !mm, + logic_enable[0] && !scope_enable[0] + }; + + bool checkbox_enable[2][2] = { + {scope_checkbox_enable[0], scope_checkbox_enable[1]}, + {logic_checkbox_enable[0], logic_checkbox_enable[1]} + }; + + bool* checkbox_bool[2][2] = { + {&scope_enable[0], &scope_enable[1]}, + {&logic_enable[0], &logic_enable[1]} + }; + const char * checkbox_label_base[2] = {"##enable_scope", "##enable_logic"}; + const char * glyphs[2] = {"\xee\xa4\x81","\xee\xa4\x80"};// includes custom glyphs defined in /font/waveform-glyphs3.ttf + const char * checkbox_label_suffix[2] = {"_ch1","_ch2"}; + char full_checkbox_label[32]{}; + for(int j=0; j<2; j++) + { + ImGui::TableNextRow(); + for(int ch : {1,2} ) + { + ImGui::TableNextColumn(); + strcpy(full_checkbox_label, checkbox_label_base[j]); + strcat(full_checkbox_label, checkbox_label_suffix[ch-1]); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + center_checkbox_delta(ImGui::GetColumnWidth() + 2*style.CellPadding.x, style)); + ImGui::BeginDisabled(!(checkbox_enable[j][ch-1])); + if((ImGui::custom_Checkbox(full_checkbox_label, checkbox_bool[j][ch-1]))||(*checkbox_bool[j][ch-1] && !checkbox_enable[j][ch-1])) { + mode_update = true; + changed = true; + } + *(checkbox_bool[j][ch-1]) &= checkbox_enable[j][ch-1]; + + ImGui::EndDisabled(); + } + + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(center_text(ImGui::GetColumnWidth() + 2*style.CellPadding.x, ImGui::CalcTextSize(glyphs[j]).x, style)); + ImGui::Text("%s",glyphs[j]); + } + ImGui::TableNextRow(0, row_height); + ImGui::TableNextRow(0, row_height); + ImGui::EndTable(); + } + ImVec2 saved_pos = ImGui::GetCursorScreenPos(); + ImVec2 p0 = ImGui::GetItemRectMin(); + ImVec2 end_pos = ImGui::GetItemRectMax(); + int real_height = (end_pos - start_pos).y; + draw_rules(p0, row_height, header_row_height, col_width); + ImVec2 row3_pos = p0 + ImVec2(style.CellPadding.x,header_row_height + 2*row_height + style.CellPadding.y);; + ImVec2 row4_pos = row3_pos + ImVec2(0.f,row_height); + + bool* checkbox_bool[2] = {&scope750, &mm}; + bool checkbox_enable[2] = {scope_enable[0] && !(scope_enable[1] || logic_enable[0]), (!scope_enable[0] && !scope_enable[1] && !logic_enable[0] && !logic_enable[1])}; + ImVec2 positions[2] = + { + row3_pos + center_checkbox_delta(col_width, style), + row4_pos + ImVec2(2 * col_width ,0.f) + center_checkbox_delta(col_width, style) + }; + const char* internal_labels[2] = {"##750 kHz","##multimeter Mode"}; + + for(int i = 0; i < 2; i++) + { + ImGui::SetCursorScreenPos(positions[i]); + ImGui::BeginDisabled(!checkbox_enable[i]); + if((ImGui::custom_Checkbox(internal_labels[i], checkbox_bool[i])) || (*checkbox_bool[i] && !checkbox_enable[i])) { + changed = true; + mode_update = true; + } + *checkbox_bool[i] &= checkbox_enable[i]; + ImGui::EndDisabled(); + } + ImGui::SetCursorScreenPos(row3_pos + ImVec2(col_width - style.CellPadding.x + (2*col_width - ImGui::CalcTextSize("750 kHz").x)/2.,2 * style.FramePadding.y - style.ItemSpacing.y)); + ImGui::Text("750 kHz"); + ImGui::PushFont(NULL, style.FontSizeBase * 1.3); + ImGui::SetCursorScreenPos(row4_pos + ImVec2(col_width - style.CellPadding.x - ImGui::CalcTextSize("\xee\xa4\x82").x/2.,0.f)); + ImGui::Text("\xee\xa4\x82"); + ImGui::PopFont(); + ImGui::PopStyleVar(); +// ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,{0.f,0.f}); +// ImGui::Dummy({0.f, saved_pos.y - ImGui::GetCursorScreenPos().y}); +// ImGui::PopStyleVar(); + ImGui::EndGroup(); + + if (mode_update) + update_device_mode(); +} + +bool inputsUI::ch_enabled(int ch) +{ + // for argument 'ch': 1==ChA ; 2==ChB, where ChA/B refer to plotted lines. Except in ScopeLogic and Multimeter modes, ChA is scope or logic Ch1 and ChB is scope or logic Ch2. + if(mode == Mode::ScopeLogic) + return true; + else if (mode == Mode::Multimeter) + return ch==1; + else + return scope_enable[ch-1]||logic_enable[ch-1]; + return false; +} + +bool inputsUI::changed_since_last() +{ + bool changed_temp = changed; + changed = false; + return changed_temp; +} + +bool inputsUI::logic_on() +{ + return (logic_enable[0] || logic_enable[1]); +} + +bool inputsUI::scopelogic_mode() +{ + return mode == Mode::ScopeLogic; +} + +int inputsUI::get_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(style.CellPadding.x, style.CellPadding.y * 2));// if this line is active, make sure that the line that resets CellPadding at the end of this function is active as well + style = ImGui::GetStyle(); + int height = 2 * style.ItemSpacing.y + ImGui::GetFontSize() + \ + ImGui::GetFontSize() + style.CellPadding.y*2 + \ + 4 * (ImGui::GetFontSize() + (style.CellPadding.y + style.FramePadding.y)*2); + + ImGui::PopStyleVar(); + return height; +} + +void inputsUI::update_device_mode() +{ + if(scope_enable[0] && !scope_enable[1] && !logic_enable[0] && !scope750) + mode = Mode::Ch1Scope; + else if (scope_enable[0] && logic_enable[0]) + mode = Mode::ScopeLogic; + else if (scope_enable[0] && scope_enable[1]) + mode = Mode::ScopeScope; + else if (logic_enable[0] && !logic_enable[1] && !scope_enable[0]) + mode = Mode::Ch1Logic; + else if (logic_enable[0] && logic_enable[1]) + mode = Mode::LogicLogic; + else if (!(scope_enable[0] || scope_enable[1] || logic_enable[0] || logic_enable[1] || mm)) + mode = Mode::None; + else if (scope750) + mode = Mode::Scope750; + else if (mm) + mode = Mode::Multimeter; + + librador_set_device_mode((int) mode); +} + diff --git a/Android_App/app/src/main/cpp/inputs_ui.h b/Android_App/app/src/main/cpp/inputs_ui.h new file mode 100644 index 000000000..4ed51e9fa --- /dev/null +++ b/Android_App/app/src/main/cpp/inputs_ui.h @@ -0,0 +1,25 @@ +#ifndef INPUTSUI_H +#define INPUTSUI_H + +#include "ui_tile.h" +class inputsUI : public UI_tile +{ + bool scope750 = false; + bool changed = false; +public: + inputsUI() : UI_tile("Inputs","Inputs",UI_tile::Width::singlet, 6) {}; + void update_device_mode(); + bool logic_enable[2] = {0,0}; + bool scope_enable[2] = {true,false}; + void draw(float width, inputsUI* inputs_ui = nullptr) override; + bool changed_since_last(); + bool ch_enabled(int ch); + enum Mode {Ch1Scope,ScopeLogic,ScopeScope,Ch1Logic,LogicLogic,None,Scope750,Multimeter}; + Mode mode = Mode::Ch1Scope; + bool mm = false; //multimeter + bool logic_on(); + bool scopelogic_mode(); + int get_height() override; +}; + +#endif // INPUTSUI_H diff --git a/Android_App/app/src/main/cpp/logic_decode_ui.cpp b/Android_App/app/src/main/cpp/logic_decode_ui.cpp new file mode 100644 index 000000000..71c264ec7 --- /dev/null +++ b/Android_App/app/src/main/cpp/logic_decode_ui.cpp @@ -0,0 +1,327 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "librador.h" +#include "custom_imgui.h" +#include "imgui_internal.h" +#include "logic_decode_ui.h" +#include "inputs_ui.h" + +float logicDecodeUI::draw_grabber(float grabber_height, const char * label, float* backlog, int ch, bool parity_check) +{ + ImGui::PushID(ch); + char chAB[2] = {'A', 'B'}; + ImGuiStyle& style = ImGui::GetStyle(); + ImVec2 init_pos = ImGui::GetCursorScreenPos(); + ImVec2 end_pos = init_pos + ImVec2(ImGui::GetContentRegionAvail().x,0.f); + ImGui::SetNextItemAllowOverlap(); + ImGui::InvisibleButton(label, ImVec2(-1, grabber_height - 2 * style.ItemSpacing.y)); + if (ImGui::IsItemActivated()) { + *backlog = 0.f; + } + ImVec2 p0 = ImGui::GetItemRectMin(); + ImVec2 p1 = ImGui::GetItemRectMax(); + float hcenter = (p0.x + p1.x)/2.; + float ycenter = (p0.y + p1.y)/2.; + float yspan = (p1.y - p0.y)/2.; + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddLine(ImVec2(hcenter - ImGui::GetFontSize(), ycenter - yspan/2),ImVec2(hcenter + ImGui::GetFontSize(), ycenter - yspan/2), IM_COL32(120, 120, 160, 255)); + draw_list->AddLine(ImVec2(hcenter - ImGui::GetFontSize(), ycenter),ImVec2(hcenter + ImGui::GetFontSize(), ycenter ), IM_COL32(120, 120, 160, 255)); + draw_list->AddLine(ImVec2(hcenter - ImGui::GetFontSize(), ycenter + yspan/2),ImVec2(hcenter + ImGui::GetFontSize(), ycenter + yspan/2), IM_COL32(120, 120, 160, 255)); + float return_val = 0.f; + if (ImGui::IsItemActive()) { + float mouse_delta = ImGui::GetIO().MouseDelta.y; + if( (*backlog==0) || ((mouse_delta > 0) == (*backlog > 0)) ) { + return_val = mouse_delta; + } else { + *backlog += mouse_delta; + } + } + + // uart settings + uart_settings* curr_ch_uart_settings = &both_ch_uart_settings[ch-1]; + ImGui::PushStyleColor(ImGuiCol_FrameBg, ImGui::GetColorU32(ImGuiCol_ChildBg,0)); + bool uart_changed = false; + ImGui::SetCursorScreenPos(init_pos); + ImVec2 positions[2] = {init_pos, end_pos + ImVec2(-ImGui::CalcTextSize("Even").x - 2 * style.FramePadding.x, 0.f)}; + const char ** uart_options_sublabels[2] = {baud_rate_labels, parity_labels}; + int sublabels_counts[2] = {IM_COUNTOF(baud_rate_labels), IM_COUNTOF(parity_labels)}; + int * curr_options_sel[2] = {&curr_ch_uart_settings->baud_idx_sel, &curr_ch_uart_settings->parity_idx_sel}; + ImGui::PushStyleVar(ImGuiStyleVar_DisabledAlpha,1.0); + for(int k: {0,1}) + { + ImGui::PushID(k); + ImGui::SetCursorScreenPos(positions[k]); + if(k==0) { + ImGui::PushItemWidth(ImGui::CalcTextSize(" A ").x + 2*style.FramePadding.x); + ImGui::LabelText("##console_ch_label"," %c ",chAB[ch-1]); + p0 = ImGui::GetItemRectMin() + style.FramePadding; + p1 = ImGui::GetItemRectMax() - style.FramePadding; + draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRect(p0, p1, IM_COL32(255, 255, 255, 255)); + ImGui::SameLine(); + } + + ImGui::PushItemWidth(ImGui::CalcTextSize(uart_options_sublabels[k][*curr_options_sel[k] + 1]).x + 2 * style.FramePadding.x); +#define POP_COLOR if(need_pop) {ImGui::PopStyleColor(); need_pop = false;} + + ImU32 label_col = IM_COL32(255,255,255,255); + + bool need_pop = false; + if(k==1 && !parity_check) { + label_col = IM_COL32(255,0,0,255); + ImGui::PushStyleColor(ImGuiCol_Text, label_col); + need_pop = true; + } + if(ImGui::BeginCombo("##uart_option_combo", uart_options_sublabels[k][*curr_options_sel[k] + 1], ImGuiComboFlags_NoArrowButton)) { + POP_COLOR + for(int n=0; n < sublabels_counts[k]; n++) { + if(ImGui::Selectable(uart_options_sublabels[k][n], *curr_options_sel[k]==(n-1), (n==0 ? ImGuiSelectableFlags_Disabled : ImGuiSelectableFlags_None))) { + uart_changed = true; + *curr_options_sel[k]=n-1; // n-1 because n=0 is the header + } + } + ImGui::EndCombo(); + } + POP_COLOR + p0 = ImGui::GetItemRectMin() + style.FramePadding; + p1 = ImGui::GetItemRectMax() - style.FramePadding; + draw_list = ImGui::GetWindowDrawList(); + draw_list->AddLine(ImVec2(p0.x,p1.y), p1, label_col); + ImGui::PopID(); + ImGui::SameLine(); + } + ImGui::PopStyleVar(); + ImGui::NewLine(); + ImGui::PopStyleColor(); + + if(uart_changed) + librador_set_uart_decode_settings(ch, + (UartSettings) + {.decode_on=curr_ch_uart_settings->decode_on, .baudRate=static_cast(baud_rates[curr_ch_uart_settings->baud_idx_sel]), .parity=parities[curr_ch_uart_settings->parity_idx_sel]}); + + ImGui::PopID(); //ch + return return_val; +} + +void logicDecodeUI::print_stream(int id, const char * text, bool *at_bottom, float window_content_width, float ch_console_height) +{ + ImGui::PushID(id); + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding); + if (ImGui::BeginChild("console",ImVec2(window_content_width, ch_console_height ), ImGuiChildFlags_AlwaysUseWindowPadding)) { + ImGui::TextWrapped("%s", text); + ImGuiContext& g = *ImGui::GetCurrentContext(); + ImGuiWindow* window = g.CurrentWindow; + + ImVec2 mouse_delta = ImGui::GetIO().MouseDelta; + bool scrolling = ImGui::ScrollWhenDraggingAnywhere(ImVec2(0.0f, -mouse_delta.y), ImGuiMouseButton_Left); + if(!scrolling && *at_bottom){ + ImGui::SetScrollY(window, ImGui::GetScrollMaxY()); + } + if (ImGui::GetScrollMaxY() == window->Scroll.y) + *at_bottom=true; + else + *at_bottom=false; + + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + ImGui::PopID(); +} + +float logicDecodeUI::get_grabber_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + return 2 * style.ItemSpacing.y + 2 * style.FramePadding.y + ImGui::GetFontSize(); +} + +void logicDecodeUI::draw_console(float window_content_width) +{ + ImGuiStyle& style = ImGui::GetStyle(); + bool parity_check; + float grabber_height = get_grabber_height(); + float y_avail = ImGui::GetContentRegionAvail().y; + if(protocol_sel == Protocol::UART) { + for(int i: {0,1}) { + ch_console_height[i] *= both_ch_uart_settings[i].decode_on; + } + for(int i:{1,0}) { + if(both_ch_uart_settings[i].decode_on) { + float clamped_console_height = fmin(ch_console_height[i], y_avail - ch_console_height[(i+1)%2] - grabber_height * (1 + both_ch_uart_settings[(i+1)%2].decode_on) - style.ItemSpacing.y); + clamped_console_height = fmax(clamped_console_height, 2 * grabber_height); + grabber2_backlog += ch_console_height[i] - clamped_console_height; // note: the grabber is only ever changing one of the console heights, so grabber2_backlog will only ever be incremented for one of the consoles + ch_console_height[i] = clamped_console_height; + } + } + if(both_ch_uart_settings[0].decode_on) + { + print_stream(1,librador_get_uart_string(1, &parity_check), &uart_ch_console_at_bottom[0], window_content_width, ch_console_height[0]); + } + float next_ch1_height = ch_console_height[1]; + if(both_ch_uart_settings[0].decode_on && both_ch_uart_settings[1].decode_on) + { + float console_sep_delta = draw_grabber(grabber_height, "chA_chB_splitter", &grabber1_backlog, 1, parity_check); + float clamped_console_sep_delta = fmin(console_sep_delta, (ch_console_height[1] - 2 * grabber_height)); + clamped_console_sep_delta = fmax(clamped_console_sep_delta, -(ch_console_height[0] - 2 * grabber_height)); + next_ch1_height -= clamped_console_sep_delta; + ch_console_height[0] += clamped_console_sep_delta; + grabber1_backlog += console_sep_delta - clamped_console_sep_delta; + } + if(both_ch_uart_settings[1].decode_on) + { + print_stream(2, librador_get_uart_string(2, &parity_check), &uart_ch_console_at_bottom[1], window_content_width, ch_console_height[1]); + ch_console_height[1] = next_ch1_height; + } + } else if(protocol_sel == Protocol::I2C) { + ch_console_height[1] = 0.f; + float clamped_console_height = fmin(ch_console_height[0], y_avail - grabber_height - style.ItemSpacing.y); + clamped_console_height = fmax(clamped_console_height, 2 * grabber_height); + grabber2_backlog += ch_console_height[0] - clamped_console_height; + ch_console_height[0] = clamped_console_height; + print_stream(3, librador_get_i2c_string(), &i2c_console_at_bottom, window_content_width, ch_console_height[0]); + } + float console_height_delta = draw_grabber(grabber_height, "plot_console_splitter", &grabber2_backlog, both_ch_uart_settings[1].decode_on ? 2 : 1, parity_check); + if(both_ch_uart_settings[1].decode_on) { + ch_console_height[1] += console_height_delta; + } else if (both_ch_uart_settings[0].decode_on || (protocol_sel == Protocol::I2C)) { + ch_console_height[0] += console_height_delta; + } +} + +bool logicDecodeUI::decoding_on() +{ + return both_ch_uart_settings[0].decode_on || both_ch_uart_settings[1].decode_on || protocol_sel == Protocol::I2C; +} + +void logicDecodeUI::draw(float width_pixels, inputsUI* inputs_ui) +{ + ImGuiStyle& style = ImGui::GetStyle(); + float grabber_height = get_grabber_height(); + ImGui::BeginGroup(); + standard_header(width_pixels); + if(!is_expanded) + { + ImGui::EndGroup(); + return; + } + + bool logic_enable[2]; + if(inputs_ui->scopelogic_mode()) { + logic_enable[0] = false; + logic_enable[1] = true; + } else { + memcpy(logic_enable, inputs_ui->logic_enable, 2 * sizeof(bool)); + } + bool i2c_changed = false; + bool uart_allowed = logic_enable[0] || logic_enable[1]; + bool i2c_allowed = logic_enable[0] && logic_enable[1] && !both_ch_uart_settings[0].decode_on && !both_ch_uart_settings[1].decode_on; + + + ImGui::BeginDisabled(!(logic_enable[0] || logic_enable[1])); //covers nearly entire fn. + + Protocol prots[2] = {Protocol::UART, Protocol::I2C}; + const char * labels[2] = {"UART", "I2C"}; + + bool open_ch_serial_settings = false; + char chAB[2] = {'A', 'B'}; + + ImGui::BeginGroup(); // for bounding rect + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,{0.f,0.f}); + ImGui::Dummy(ImVec2(width_pixels,0.f)); + ImGui::PopStyleVar(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2((width_pixels - ImGui::CalcTextSize("UART").x)/2.,style.FramePadding.y)); + ImGui::Text("UART"); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2( (width_pixels - ImGui::CalcTextSize("CH ACH B").x - style.ItemSpacing.x - 4 * style.FramePadding.x)/2., 0.f )); + for (int ch: {1,2}) + { + ImGui::BeginDisabled(!logic_enable[ch-1] || !(protocol_sel==Protocol::UART)); + char buf[20]; + sprintf(buf,"CH %c##serial_decode",chAB[ch-1]); + bool need_pop = false; + if(both_ch_uart_settings[ch-1].decode_on) { + ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_ButtonHovered)); + need_pop = true; + } + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_Button)); + if(ImGui::Button(buf)) { + both_ch_uart_settings[ch-1].decode_on = !both_ch_uart_settings[ch-1].decode_on; + if (both_ch_uart_settings[ch-1].decode_on) { + ch_console_height[ch-1] = init_console_height_per_ch - grabber_height; + } else { + ch_console_height[ch-1] = 0.f; + } + librador_set_uart_decode_settings(ch, + (UartSettings) + {.decode_on=both_ch_uart_settings[ch-1].decode_on, .baudRate=static_cast(baud_rates[both_ch_uart_settings[ch-1].baud_idx_sel]), .parity=parities[both_ch_uart_settings[ch-1].parity_idx_sel]}); + } + ImGui::PopStyleColor(); + if(need_pop) { + ImGui::PopStyleColor(); + } + ImGui::EndDisabled(); + ImGui::SameLine(); + } +// draw_list->AddLine(ImGui::GetCursorScreenPos(), ImGui::GetCursorScreenPos() + ImVec2(width_pixels,0.f), IM_COL32(90, 90, 120, 255)); +// +// ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2( (width_pixels - ImGui::CalcTextSize("I2C").x - style.ItemInnerSpacing.x - CHECKBOX_SIZE)/2., style.FramePadding.y )); +// ImGui::BeginDisabled(!i2c_allowed); +// if(ImGui::Checkbox("I2C", (bool *) &protocol_sel)) { +// i2c_changed = true; +// } +// ImGui::EndDisabled(); + + ImGui::EndGroup(); + ImVec2 p0 = ImGui::GetItemRectMin(); + ImVec2 p1 = ImGui::GetItemRectMax() + ImVec2(0.f,style.FramePadding.y); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255)); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2(0.f,style.FramePadding.y - style.ItemSpacing.y)); + ImGui::Dummy({0.f,0.f}); // prevents issue with this draw() command affecting the vertical alignment of whatever ui element comes after it + ImGui::EndGroup(); + + ImGui::EndDisabled(); //!logic_enable[0] && !logic_enable[1]); +// if(i2c_changed) +// { +// librador_set_i2c_is_decoding(protocol_sel == Protocol::I2C); +// if(protocol_sel == Protocol::I2C) +// ch_console_height[0] = init_console_height_per_ch - grabber_height; +// } +} + +void logicDecodeUI::update(inputsUI* inputs) +{ + bool logic_enable[2]; + if(inputs->scopelogic_mode()) { + logic_enable[0] = false; + logic_enable[1] = true; + } else { + memcpy(logic_enable, inputs->logic_enable, 2 * sizeof(bool)); + } + for (int ch : {1,2}) + { + uart_settings* curr_ch_uart_settings = &both_ch_uart_settings[ch-1]; + if((!logic_enable[ch-1] || !(protocol_sel==Protocol::UART)) && curr_ch_uart_settings->decode_on) + { + curr_ch_uart_settings->decode_on = false; + librador_set_uart_decode_settings(ch, + (UartSettings) + {.decode_on=curr_ch_uart_settings->decode_on, .baudRate=static_cast(baud_rates[curr_ch_uart_settings->baud_idx_sel]), .parity=parities[curr_ch_uart_settings->parity_idx_sel]}); + } + } + if((!logic_enable[0] || !logic_enable[1]) && (protocol_sel==Protocol::I2C)) + { + protocol_sel=Protocol::UART; //with ch_uart_settings->decode_on = false for both channels, so effectively disabling decoding; + librador_set_i2c_is_decoding(false); + } + +} + +int logicDecodeUI::get_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + int calc_height = 2 * style.ItemSpacing.y + ImGui::GetFontSize() + \ + style.FramePadding.y + ImGui::GetFontSize() + style.ItemSpacing.y + \ + 2 * style.FramePadding.y + ImGui::GetFontSize() + 2 * style.ItemSpacing.y; + return calc_height; +// 3 * style.FramePadding.y + ImGui::GetFontSize() + // for i2c checkbox +} diff --git a/Android_App/app/src/main/cpp/logic_decode_ui.h b/Android_App/app/src/main/cpp/logic_decode_ui.h new file mode 100644 index 000000000..662f9b379 --- /dev/null +++ b/Android_App/app/src/main/cpp/logic_decode_ui.h @@ -0,0 +1,73 @@ +#ifndef LOGICDECODEUI_H +#define LOGICDECODEUI_H + +#include "ui_tile.h" +#include "uartstyledecoder.h" + +class logicDecodeUI : public UI_tile +{ + enum class Protocol {UART, I2C}; + Protocol protocol_sel = Protocol::UART; + + static const int num_baud_options = 12; + const int baud_rates[num_baud_options] = { + 300, + 600, + 1200, + 2400, + 4800, + 9600, + 14400, + 19200, + 28800, + 38400, + 57600, + 115200 + }; + const char* baud_rate_labels[num_baud_options+1] = { + "Baud:", + "300", + "600", + "1200", + "2400", + "4800", + "9600", + "14400", + "19200", + "28800", + "38400", + "57600", + "115200"}; + + static const int num_parity_options = 3; + const UartParity parities[num_parity_options] = {UartParity::None, UartParity::Even, UartParity::Odd}; + const char* parity_labels[num_parity_options+1] = {"Parity:", "None", "Even", "Odd"}; + + struct uart_settings { + bool decode_on = false; + int baud_idx_sel = 0; + int parity_idx_sel = 0; + }; + + uart_settings both_ch_uart_settings[2]; + float ch_console_height[2] = {0.f, 0.f}; + bool draw_uart_settings(float grabber_height, float width_pixels); + float init_console_height_per_ch = 300.f; + float grabber_height; + float grabber1_backlog = 0.f; + float grabber2_backlog = 0.f; + float grabber_delta_tracker2 = 0.f; + float draw_grabber(float grabber_height, const char * label, float* backlog, int ch_idx, bool parity_check); + void print_stream(int id, const char * text, bool *at_bottom, float window_content_width, float ch_console_height); + bool uart_ch_console_at_bottom[2] = {true, true}; + bool i2c_console_at_bottom = true; + float get_grabber_height(); +public: + logicDecodeUI() : UI_tile("Logic Decoding", "Logic Dec.", UI_tile::Width::singlet, 4) {}; + bool decoding_on(); + void draw(float width, inputsUI* inputs_ui = nullptr) override; + void update(inputsUI* inputs_ui); + void draw_console(float window_content_width);//const char * from_librador_1, const char * from_librador_2 = nullptr); + int get_height() override; +}; +#endif // LOGICDECODEUI_H diff --git a/Android_App/app/src/main/cpp/main.cpp b/Android_App/app/src/main/cpp/main.cpp new file mode 100644 index 000000000..b749d9179 --- /dev/null +++ b/Android_App/app/src/main/cpp/main.cpp @@ -0,0 +1,340 @@ +// Dear ImGui: standalone example application for SDL3 + OpenGL +// (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan/Metal graphics context creation, etc.) + +// Learn about Dear ImGui: +// - FAQ https://dearimgui.com/faq +// - Getting Started https://dearimgui.com/getting-started +// - Documentation https://dearimgui.com/docs (same as your local docs/ folder). +// - Introduction, links and more at the top of imgui.cpp + +#include "librador.h" +#define IMGUI_DEFINE_MATH_OPERATORS +#include "implot.h" +#include "imgui.h" +#include "settings_panel.h" +#include "ui_tile.h" +#include "sig_gen_ui.h" +#include "inputs_ui.h" +#include "trigger_ui.h" +#include "virtual_transform_ui.h" +#include "psu_ui.h" +#include "logic_decode_ui.h" +#include "plot_ui.h" +#include "custom_imgui.h" +#include "imgui_impl_sdl3.h" +#include "imgui_impl_opengl3.h" +#include +#include +#include +// #include "SDL_android.h" +#include +#if defined(IMGUI_IMPL_OPENGL_ES2) +#include +#else +#include +#endif +#include "imgui_internal.h" +#include +#include +#include + + +// Main code +int main(int, char**) +{ + // Setup SDL + // [If using SDL_MAIN_USE_CALLBACKS: all code below until the main loop starts would likely be your SDL_AppInit() function] + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) + { + printf("Error: SDL_Init(): %s\n", SDL_GetError()); + return 1; + } + + // Decide GL+GLSL versions +#if defined(IMGUI_IMPL_OPENGL_ES2) + // GL ES 2.0 + GLSL 100 (WebGL 1.0) + const char* glsl_version = "#version 100"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); +#elif defined(IMGUI_IMPL_OPENGL_ES3) + // GL ES 3.0 + GLSL 300 es (WebGL 2.0) + const char* glsl_version = "#version 300 es"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); +#elif defined(__APPLE__) + // GL 3.2 Core + GLSL 150 + const char* glsl_version = "#version 150"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); +#else + // GL 3.0 + GLSL 130 + const char* glsl_version = "#version 130"; + SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); +#endif + + // Create window with graphics context + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()); + SDL_Rect bounds; + SDL_zero(bounds); + SDL_GetDisplayBounds(SDL_GetPrimaryDisplay(), &bounds); + + float pixel_6a_main_scale = 2.625; + float pixel_6a_dpi = 428.6; + + JNIEnv *env = (JNIEnv *) SDL_GetAndroidJNIEnv(); + jobject MainActivityObject = (jobject) SDL_GetAndroidActivity(); + jclass MainActivity(env->GetObjectClass(MainActivityObject)); + jmethodID getDpiID = env->GetMethodID(MainActivity, "getDpi", "()F"); + float dpi = (float) env->CallFloatMethod(MainActivityObject,getDpiID); + LOGI("dpi: %.2f", dpi); + SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; + SDL_Window* window = SDL_CreateWindow("main window", (int)bounds.w, (int)bounds.h, window_flags); + if (window == nullptr) + { + printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); + return 1; + } + SDL_GLContext gl_context = SDL_GL_CreateContext(window); + if (gl_context == nullptr) + { + printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError()); + return 1; + } + + SDL_GL_MakeCurrent(window, gl_context); + SDL_GL_SetSwapInterval(1); // Enable vsync + SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); + SDL_ShowWindow(window); + + // Setup Dear ImGui context + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImPlot::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + + SDL_PropertiesID propsIme = SDL_CreateProperties(); // for allowing specification of keyboard type (numeric, alpha, ...) + SDL_SetNumberProperty(propsIme, SDL_PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER, 2); + io.UserData = &propsIme; + + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsLight(); + + // Setup scaling + ImGuiStyle& style = ImGui::GetStyle(); +// style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again). +// style.FontScaleDpi = main_scale; // Set initial font scale. (in docking branch: using io.ConfigDpiScaleFonts=true automatically overrides this for every window depending on the current monitor) + + style.ScaleAllSizes( (pixel_6a_main_scale / pixel_6a_dpi) * dpi); // brentfpage : not scaling by a given device's main_scale because doing so doesn't actually bring about consistent sizing across devices. + style.FontScaleDpi = (pixel_6a_main_scale / pixel_6a_dpi) * dpi; // brentfpage : same for the font sizes + + style.FontSizeBase = 19.f; + style.WindowPadding = ImVec2(style.WindowPadding.x/2,style.WindowPadding.y/2); + + // Setup Platform/Renderer backends + ImGui_ImplSDL3_InitForOpenGL(window, gl_context); + ImGui_ImplOpenGL3_Init(glsl_version); + + // Load Fonts + // - If fonts are not explicitly loaded, Dear ImGui will call AddFontDefault() to select an embedded font: either AddFontDefaultVector() or AddFontDefaultBitmap(). + // This selection is based on (style.FontSizeBase * style.FontScaleMain * style.FontScaleDpi) reaching a small threshold. + // - You can load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - If a file cannot be loaded, AddFont functions will return a nullptr. Please handle those errors in your code (e.g. use an assertion, display an error and quit). + // - Read 'docs/FONTS.md' for more instructions and details. + // - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use FreeType for higher quality font rendering. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! + // - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details. + //style.FontSizeBase = 20.0f; + //io.Fonts->AddFontDefaultVector(); + //io.Fonts->AddFontDefaultBitmap(); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf"); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf"); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf"); + //IM_ASSERT(font != nullptr); + + ImFont* defaultFont = io.Fonts->AddFontDefault(); + + // for accessing android app resources + jfieldID asset_manager_id = env->GetFieldID(MainActivity, "mgr", "Landroid/content/res/AssetManager;"); + jobject mgr_java = (jobject)env->GetObjectField(MainActivityObject, asset_manager_id); + AAssetManager * mgr = AAssetManager_fromJava(env, mgr_java); + + ImFontConfig config; + config.MergeMode = true; + config.FontDataOwnedByAtlas = false; // prevents imperceptible crash when the app is closed +// https://stackoverflow.com/a/13317651/3474552 + + float glyph_y_offsets[2] = {3.f, 4.5f}; + char buf[2][2048]; + int fi = 0; + for (const char* filename: {"font/waveform-glyphs3.ttf","font/greek_delta.ttf"}) { + config.GlyphOffset = { 0.f, glyph_y_offsets[fi] }; + AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING); + int nb_read = 0; + nb_read = AAsset_read(asset, buf[fi], 2048); + ImFont* new_font = io.Fonts->AddFontFromMemoryTTF(buf[fi], nb_read, 13.f, &config); + AAsset_close(asset); + fi++; + } + + jmethodID getStatusBarHeightID = env->GetMethodID(MainActivity, "getStatusBarHeight", "()I"); + jmethodID getNavigationBarHeightID = env->GetMethodID(MainActivity, "getNavigationBarHeight", "()I"); + jmethodID getScreenWidth = env->GetMethodID(MainActivity, "getScreenWidth", "()I"); + jmethodID getScreenHeight = env->GetMethodID(MainActivity, "getScreenHeight", "()I"); + + int sw = (int) env->CallIntMethod(MainActivityObject,getScreenWidth); + int sh = (int) env->CallIntMethod(MainActivityObject,getScreenHeight); + int sbh = (int) env->CallIntMethod(MainActivityObject,getStatusBarHeightID); + int nbh = (int) env->CallIntMethod(MainActivityObject,getNavigationBarHeightID); + LOGI("screen width: %d", sw); + LOGI("screen height: %d", sh); + LOGI("status bar beight: %d", sbh); + LOGI("navigation bar beight: %d", nbh); + + // Our state + bool show_mainwindow = true; + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + + virtual_transform_ui.is_visible = true; + virtual_transform_ui.is_expanded = false; + virtual_transform_ui.next_is_expanded = false; + psu_ui.is_expanded = false; + psu_ui.is_visible = false; + plotUI plot_ui = plotUI(); + + // Main loop + bool done = false; + bool iso_thread_active = false; + bool need_board_init = true; + while (!done) + { + + // Poll and handle events (inputs, window resize, etc.) + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + // [If using SDL_MAIN_USE_CALLBACKS: call ImGui_ImplSDL3_ProcessEvent() from your SDL_AppEvent() function] + SDL_Event event; + while (SDL_PollEvent(&event)) + { + ImGui_ImplSDL3_ProcessEvent(&event); + if (event.type == SDL_EVENT_QUIT) + done = true; + if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window)) + done = true; + } + + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppIterate() function] + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + { + SDL_Delay(10); + continue; + } + + // will intentionally be zero sometimes; see MainActivity + int statusBarHeight = (int) env->CallIntMethod(MainActivityObject,getStatusBarHeightID); + int navigationBarHeight = (int) env->CallIntMethod(MainActivityObject,getNavigationBarHeightID); + + // Start the Dear ImGui frame + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplSDL3_NewFrame(); + ImGui::NewFrame(); + +// important to have this iso_thread_active check after the new frame starts. Otherwise, (board connected -> user puts phone to sleep -> user unplugs board -> user wakes phone) leads to a crash. The crash arises from the librador_get_(analog/digital)_data block below thinking iso_thread_active=true when it's not. + iso_thread_active = librador_iso_thread_is_active(); + if(!iso_thread_active) { + need_board_init = true; + } + if(need_board_init && iso_thread_active) { + inputs_ui.update_device_mode(); + sig_gen_ui.usb_send_data(1); + sig_gen_ui.usb_send_data(2); + psu_ui.usb_send_data(); + librador_set_oscilloscope_gain(4.); + need_board_init = false; + } + + ImGuiIO& io = ImGui::GetIO(); + + static bool landscape = io.DisplaySize.y < io.DisplaySize.x; + bool new_landscape = io.DisplaySize.y < io.DisplaySize.x; + bool orientation_changed = (landscape != new_landscape); + landscape = new_landscape; + + plot_ui.recompute_x_bounds(inputs_ui.changed_since_last(), inputs_ui.mode); + logic_decode_ui.update(&inputs_ui); + + ImGui::SetNextWindowPos(ImVec2(0.f,statusBarHeight)); + ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x,io.DisplaySize.y - statusBarHeight - navigationBarHeight)); + + ImGuiStyle& style = ImGui::GetStyle(); + + bool screen_keyboard_shown = SDL_ScreenKeyboardShown(window); + ImGui::Begin("MainWindow", + &show_mainwindow, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoMove | (screen_keyboard_shown ? ImGuiWindowFlags_NoMouseInputs : 0)); + float data_width; + float data_height; + do_settings_panel_layout(&data_width, &data_height, landscape, io.DisplaySize.y - statusBarHeight - navigationBarHeight - 2 * style.WindowPadding.y, dpi, pixel_6a_dpi); + + ImGui::BeginChild("data",ImVec2(data_width, data_height), 0, (screen_keyboard_shown ? ImGuiWindowFlags_NoMouseInputs : 0)); + { + if(logic_decode_ui.decoding_on()) { + logic_decode_ui.draw_console(data_width); + } + + plot_ui.draw(iso_thread_active, inputs_ui.mode, inputs_ui.ch_enabled(1), inputs_ui.ch_enabled(2), data_width, 0.); + + } + ImVec2 dataWindowBottomLeft = ImGui::GetWindowPos() + ImVec2(0.f,ImGui::GetWindowSize().y); + ImVec2 dataWindowBottomRight = ImGui::GetWindowPos() + ImGui::GetWindowSize(); + ImGui::EndChild(); + if(landscape) { + ImGui::SameLine(); + } + + draw_settings_panel(landscape, screen_keyboard_shown); + draw_collapse_button(landscape, dataWindowBottomLeft, dataWindowBottomRight); + draw_selector_popup(landscape, orientation_changed); + + ImGui::End(); + + // Rendering + ImGui::Render(); + glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); + glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + SDL_GL_SwapWindow(window); + } + + // Cleanup + // [If using SDL_MAIN_USE_CALLBACKS: all code below would likely be your SDL_AppQuit() function] + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplSDL3_Shutdown(); + ImPlot::DestroyContext(); + ImGui::DestroyContext(); + + SDL_GL_DestroyContext(gl_context); + SDL_DestroyProperties(propsIme); + SDL_DestroyWindow(window); + SDL_Quit(); + + return 0; +} diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp new file mode 100644 index 000000000..cf909a274 --- /dev/null +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -0,0 +1,224 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "implot.h" +#include "imgui_internal.h" +#include "implot_internal.h" +#include "plot_ui.h" +#include "librador.h" + +void plotUI::recompute_x_bounds(bool mode_changed, inputsUI::Mode mode) +{ + if(mode_changed) + { + if(mode==inputsUI::Mode::Scope750) { + time_window = std::min(5., time_window); + delay = std::min(5. - time_window, delay); + ImPlot::SetNextAxisLimits(ImAxis_X1, -(delay+time_window), -delay, ImPlotCond_Always); + x_constraint_min = -5.; + x_constraint_max = 0.; +// } else if (xy) { +// xmin = ymin; +// xmax = ymax; +// ImPlot::SetNextAxisLimits(ImAxis_X1, xmin, xmax, ImPlotCond_Always); +// x_constraint_min = -20.; +// x_constraint_max = 20.; + } else { + time_window = std::min(max_time_window_375khz, time_window); + delay = std::min(max_time_window_375khz - time_window, delay); + ImPlot::SetNextAxisLimits(ImAxis_X1, -(delay+time_window), -delay, ImPlotCond_Always); + x_constraint_min = -max_time_window_375khz; + x_constraint_max = 0.; + } + } else { +// if(!xy) { + delay = -xmax; + time_window = (xmax - xmin); +// } + } +} + +void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, bool chB_enabled, double data_width, double plot_height) +{ + std::vector *from_librador_chA; + std::vector *from_librador_chB; + std::vector blank_data{}; + std::vector time_array; + + if(iso_thread_active){ + time_array = librador_get_time_array(delay, time_window, GRAPH_SAMPLES); + switch(mode) { + case inputsUI::Mode::Ch1Scope: + from_librador_chA = librador_get_analog_data(1,time_window,GRAPH_SAMPLES,delay, 0); + break; + case inputsUI::Mode::ScopeLogic: + from_librador_chA = librador_get_analog_data(1,time_window,GRAPH_SAMPLES,delay, 0); + from_librador_chB = librador_get_digital_data(2,time_window,GRAPH_SAMPLES,delay); + break; + case inputsUI::Mode::ScopeScope: + from_librador_chA = librador_get_analog_data(1,time_window,GRAPH_SAMPLES,delay, 0); + from_librador_chB = librador_get_analog_data(2,time_window,GRAPH_SAMPLES,delay, 0); + break; + case inputsUI::Mode::Ch1Logic: + from_librador_chA = librador_get_digital_data(1,time_window,GRAPH_SAMPLES,delay); + break; + case inputsUI::Mode::LogicLogic: + from_librador_chA = librador_get_digital_data(1,time_window,GRAPH_SAMPLES,delay); + from_librador_chB = librador_get_digital_data(2,time_window,GRAPH_SAMPLES,delay); + break; + case inputsUI::Mode::None: + break; + case inputsUI::Mode::Scope750: + from_librador_chA = librador_get_analog_data(1,time_window,GRAPH_SAMPLES,delay, 0); + break; + case inputsUI::Mode::Multimeter: + from_librador_chA = librador_get_analog_data(1,time_window,GRAPH_SAMPLES,delay, 0); + break; + } + } else { + from_librador_chA = &blank_data; + from_librador_chB = &blank_data; + time_array = blank_data; + } + + ImGui::BeginChild("plot",ImVec2(data_width, plot_height)); + { + if (ImPlot::BeginPlot("##scope traces", ImGui::GetContentRegionAvail(),ImPlotFlags_NoMouseText)) { + ImPlot::SetupAxes("time (s)","volts"); + + ImPlot::SetupAxisFormat(ImAxis_X1, ImPlot::Formatter_Offset_Plus_Delta, (void*) "%g"); + ImPlot::SetupAxisFormat(ImAxis_Y1, ImPlot::Formatter_Offset_Plus_Delta, (void*) "%g"); + ImPlot::SetupAxisLimitsConstraints(ImAxis_X1, x_constraint_min, x_constraint_max); + ImPlot::SetupAxisLimitsConstraints(ImAxis_Y1, -max_voltage, max_voltage); + ImPlot::SetupAxesLimits(xmin, xmax, ymin, ymax, ImPlotCond_Once); + + ImPlotSpec spec = ImPlotSpec(); + spec.LineWeight = 2; + if(chA_enabled) + ImPlot::PlotLine("CH A", time_array.data(), from_librador_chA->data(), from_librador_chA->size(), spec); + if(chB_enabled) + ImPlot::PlotLine("CH B", time_array.data(), from_librador_chB->data(), from_librador_chB->size(), spec); + + ImGuiContext& g = *GImGui; + + if(ImPlot::IsAxisActivated(ImAxis_X1)) { + float mouse_down_clicked_val = ImPlot::getMouseDownClickedVal(ImAxis_X1); + cursor_drag_tool_toggle = fabs(x_ref_1 - mouse_down_clicked_val) > fabs(x_ref_2 - mouse_down_clicked_val); + } + + ImPlotDragToolFlags x1_drag_tool_flags = cursor_drag_tool_toggle ? ImPlotDragToolFlags_NoAxisInputs : 0; + ImPlotDragToolFlags x2_drag_tool_flags = cursor_drag_tool_toggle ? 0 : ImPlotDragToolFlags_NoAxisInputs; + + if(ImPlot::IsAxisClicked(ImAxis_X1)) { + if(!enable_x_ref_lines) { + x_ref_1 = ImPlot::getMouseDownClickedVal(ImAxis_X1); + x_ref_2 = ImPlot::getMouseDownClickedVal(ImAxis_X1); + } + enable_x_ref_lines = true; + if(g.IO.MouseClickedLastCount[0]==2) { + enable_x_ref_lines = false; + } + } + + if(enable_x_ref_lines) { + ImPlot::DragLineX(0,&x_ref_1,ImVec4(1,1,1,1), 1.f, x1_drag_tool_flags); + ImPlot::DragLineX(1,&x_ref_2,ImVec4(1,1,1,1), 1.f, x2_drag_tool_flags); + } + + if(ImPlot::IsAxisActivated(ImAxis_Y1)) { + float mouse_down_clicked_val = ImPlot::getMouseDownClickedVal(ImAxis_Y1); + cursor_drag_tool_toggle = fabs(y_ref_1 - mouse_down_clicked_val) > fabs(y_ref_2 - mouse_down_clicked_val); + } + + ImPlotDragToolFlags y1_drag_tool_flags = cursor_drag_tool_toggle ? ImPlotDragToolFlags_NoAxisInputs : 0; + ImPlotDragToolFlags y2_drag_tool_flags = cursor_drag_tool_toggle ? 0 : ImPlotDragToolFlags_NoAxisInputs; + + if(ImPlot::IsAxisClicked(ImAxis_Y1)) { + if(!enable_y_ref_lines) { + y_ref_1 = ImPlot::getMouseDownClickedVal(ImAxis_Y1); + y_ref_2 = ImPlot::getMouseDownClickedVal(ImAxis_Y1); + } + enable_y_ref_lines = true; + if(g.IO.MouseClickedLastCount[0]==2) { + enable_y_ref_lines = false; + } + } + + if(enable_y_ref_lines) { + ImPlot::DragLineY(0,&y_ref_1,ImVec4(1,1,1,1), 1.f, y1_drag_tool_flags); + ImPlot::DragLineY(1,&y_ref_2,ImVec4(1,1,1,1), 1.f, y2_drag_tool_flags); + } + + ImPlotRect axes_limits = ImPlot::GetPlotLimits(); + if(ImPlot::IsAxisLongPressed(ImAxis_X1)) { + ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetWindowSize()/2.,0,{0.5,0.5}); + ImGui::OpenPopup("select x lims"); + } + if(ImGui::BeginPopup("select x lims")) { + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::Text("X-axis limits:"); + ImGui::PushItemWidth(ImGui::CalcTextSize("-10.00 s").x + 2 * style.FramePadding.x); + ImGui::InputFloat("Min", &xmin, 0.f, 0.f, "%.2f s"); + float new_window = xmax - xmin; + float new_delay = fabs(-xmax); // fabs to prevent signed 0 + ImGui::InputFloat("Window", &new_window, 0.f, 0.f, "%.2f s"); + ImGui::InputFloat("Delay", &new_delay, 0.f, 0.f, "%.2f s"); + xmin = -new_delay - new_window; + xmax = -new_delay; + ImGui::EndPopup(); + } else { + xmin = axes_limits.X.Min; + xmax = axes_limits.X.Max; + } + + if(ImPlot::IsAxisLongPressed(ImAxis_Y1)) { + ImGui::SetNextWindowPos(ImGui::GetWindowPos() + ImGui::GetWindowSize()/2.,0,{0.5,0.5}); + ImGui::OpenPopup("select y lims"); + } + if(ImGui::BeginPopup("select y lims")) { + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::Text("Y-axis limits:"); + ImGui::PushItemWidth(ImGui::CalcTextSize("-20.00 V").x + 2 * style.FramePadding.x); + ImGui::InputFloat("Max", &ymax, 0.f, 0.f, "%.2f V"); + ImGui::InputFloat("Min", &ymin, 0.f, 0.f, "%.2f V"); + ImGui::EndPopup(); + } else { + ymin = axes_limits.Y.Min; + ymax = axes_limits.Y.Max; + } + + ImPlotPlot* mainplot = ImPlot::GetCurrentPlot(); + ImPlot::EndPlot(); + + ImPlot::SetNextAxisLimits(ImAxis_X1, xmin, xmax, ImPlotCond_Always); + ImPlot::SetNextAxisLimits(ImAxis_Y1, ymin, ymax, ImPlotCond_Always); + + if(enable_x_ref_lines || enable_y_ref_lines) { + ImGui::SetNextWindowBgAlpha(0.25f); + ImGuiStyle& style = ImGui::GetStyle(); + + ImPlotContext& gp = *GImPlot; + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, {2 * style.ItemSpacing.x, style.ItemSpacing.y}); + float ref_legend_width = (enable_x_ref_lines + enable_y_ref_lines) * ImGui::CalcTextSize("X1: -0.000").x + (enable_x_ref_lines && enable_y_ref_lines) * style.ItemSpacing.x + 2 * style.FramePadding.x; + float ref_legend_height = 3 * ImGui::GetFontSize() + 2 * style.FramePadding.y; + ImGui::SetCursorScreenPos(mainplot->PlotRect.Max - ImVec2(ref_legend_width, ref_legend_height) - gp.Style.LegendPadding ); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(ImGui::GetCursorScreenPos(), ImGui::GetCursorScreenPos() + ImVec2(ref_legend_width, ref_legend_height), ImGui::GetColorU32(ImGuiCol_WindowBg,.75)); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + style.FramePadding); + + ImGui::BeginGroup(); + if(enable_x_ref_lines) { + ImGui::Text("X1: %.3f\nX2: %.3f\n\xee\xa4\x84X: %.3f", fmin(x_ref_1,x_ref_2), fmax(x_ref_1,x_ref_2), fabs(x_ref_2 - x_ref_1)); + } + if(enable_x_ref_lines && enable_y_ref_lines) { + ImGui::SameLine(); + } + if(enable_y_ref_lines) { + ImGui::Text("Y1: %.3f\nY2: %.3f\n\xee\xa4\x84Y: %.3f", fmin(y_ref_1,y_ref_2), fmax(y_ref_1,y_ref_2), fabs(y_ref_2 - y_ref_1)); + } + ImGui::EndGroup(); + ImGui::PopStyleVar(); + } + + } + } + ImGui::EndChild(); +} diff --git a/Android_App/app/src/main/cpp/plot_ui.h b/Android_App/app/src/main/cpp/plot_ui.h new file mode 100644 index 000000000..61ae79839 --- /dev/null +++ b/Android_App/app/src/main/cpp/plot_ui.h @@ -0,0 +1,34 @@ +#ifndef PLOTUI_H +#define PLOTUI_H + +#include "inputs_ui.h" +#include + +#define GRAPH_SAMPLES 512 +class plotUI +{ + float xmin = -.5; + float xmax = 0.; + float ymin = -2.; + float ymax = 2.; + const double max_time_window_375khz = 10; + const double max_voltage = 20; + double x_constraint_min = -max_time_window_375khz; + double x_constraint_max = 0.; + + double x_ref_1; + double x_ref_2; + double y_ref_1; + double y_ref_2; + + bool cursor_drag_tool_toggle; // determines which of the two reference lines for a given axis is begin dragged + bool enable_x_ref_lines = false; + bool enable_y_ref_lines = false; + +public: + void recompute_x_bounds(bool mode_changed, inputsUI::Mode mode); + void draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, bool chB_enabled, double data_width, double plot_height); + double delay; + double time_window; +}; +#endif // PLOTUI_H diff --git a/Android_App/app/src/main/cpp/psu_ui.cpp b/Android_App/app/src/main/cpp/psu_ui.cpp new file mode 100644 index 000000000..7f7dea5ca --- /dev/null +++ b/Android_App/app/src/main/cpp/psu_ui.cpp @@ -0,0 +1,69 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "librador.h" +#include "custom_imgui.h" +#include +#include "imgui_internal.h" +#include "psu_ui.h" + +void psuUI::draw(float width_pixels, inputsUI* inputs_ui) +{ + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::BeginGroup(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2(0.f,style.ItemSpacing.y)); // combined with lines in main.cpp, effectively folds itemspacing.y into the group covering this ui_tile. + ImVec2 baseline_loc = ImGui::GetCursorScreenPos(); + + const float psu_button_width = style.FramePadding.x*2 + ImGui::CalcTextSize(" PSU ").x; + ImVec2 slider_loc = baseline_loc + ImVec2(psu_button_width + style.ItemInnerSpacing.x, 0.f); + float close_button_width = ImGui::GetFontSize() + style.FramePadding.x; + ImVec2 close_button_loc = baseline_loc + ImVec2(width_pixels - close_button_width, style.FramePadding.y ); + + ImGui::BeginGroup(); // for bounding rect + ButtonForSlider(" PSU ", "##psu_slider", ImVec2(psu_button_width,0.f)); + ImGui::SameLine(); + ImGui::SetCursorScreenPos(slider_loc); + ImGui::PushItemWidth(width_pixels - psu_button_width - 2 * style.ItemInnerSpacing.x - 1 - close_button_width); // -1 to give space for bounding rect + if(ImGui::custom_SliderFloat("##psu_slider", "V", &psu, 4.5f, 12.0f, "%.1f V", ImGuiSliderFlags_ClampOnInput) || ImGui::IsItemDeactivatedAfterEdit()) { + need_usb_send = true; + } + ImGui::SameLine(); + ImGui::EndGroup(); + + ImVec2 p0 = ImGui::GetItemRectMin(); + ImVec2 p1 = ImGui::GetItemRectMax(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255),0,0,2); + + if(ImGui::CloseButton(ImGui::GetID("psu_close"), close_button_loc)) { + is_expanded = false; + is_visible = false; + } + ImGui::SameLine(); + // mimic the spacing/cursor advancement that a standard Button(...) would generate + ImGui::SetCursorScreenPos(close_button_loc); + ImGui::Dummy({close_button_width,0.f}); + + ImGui::EndGroup(); + + if(need_usb_send) { + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + if(std::chrono::duration_cast(now - last_usb_send) > between_usb_sends_min) { + usb_send_data(); + last_usb_send = now; + need_usb_send = false; + } + } +} + +void psuUI::usb_send_data() +{ + librador_set_power_supply_voltage(psu); +} + +int psuUI::get_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + return 2 * style.CellPadding.y + 2 * style.FramePadding.y + style.ItemSpacing.y + ImGui::GetFontSize(); +} + + diff --git a/Android_App/app/src/main/cpp/psu_ui.h b/Android_App/app/src/main/cpp/psu_ui.h new file mode 100644 index 000000000..1ec0c9243 --- /dev/null +++ b/Android_App/app/src/main/cpp/psu_ui.h @@ -0,0 +1,17 @@ +#ifndef PSUUI_H +#define PSUUI_H + +#include "ui_tile.h" +class psuUI : public UI_tile +{ + const std::chrono::milliseconds between_usb_sends_min{100}; + float psu = 4.5f; + std::chrono::steady_clock::time_point last_usb_send; + bool need_usb_send = false; +public: + psuUI() : UI_tile("PSU", "PSU", UI_tile::Width::duplex, 1) {}; + void usb_send_data(); + void draw(float width, inputsUI* inputs_ui = nullptr) override; + int get_height() override; +}; +#endif // PSUUI_H diff --git a/Android_App/app/src/main/cpp/settings_panel.cpp b/Android_App/app/src/main/cpp/settings_panel.cpp new file mode 100644 index 000000000..46b76a304 --- /dev/null +++ b/Android_App/app/src/main/cpp/settings_panel.cpp @@ -0,0 +1,265 @@ +#include "settings_panel.h" + +inputsUI inputs_ui = inputsUI(); +triggerUI trigger_ui = triggerUI(); +virtualTransformUI virtual_transform_ui = virtualTransformUI(); +sigGenUI sig_gen_ui = sigGenUI(); +psuUI psu_ui = psuUI(); +logicDecodeUI logic_decode_ui = logicDecodeUI(); + +const int n_tiles = 6; +UI_tile* tiles[n_tiles] = {&inputs_ui, &trigger_ui, &virtual_transform_ui, &sig_gen_ui, &psu_ui, &logic_decode_ui}; + +float pixel_6a_screen_width = 1080.f; +float pixel_6a_setting_panel_aspect = 1.13; // width to height +float settings_height_max; +float adjustment; +float tile_singlet_width_pixels; +float settings_width; +bool row_col_tiling; +float col1_width, col2_width; +float tile_col_heights[2]; +int n_singlet_tiles_visible; +float singlet_tile_height_when_row_col_tiling; +float settings_height; + +bool maybe_clicked_background = false; +bool collapse_settings = false; + +ImVec2 settings_window_center; + +// singlet-width tiles are (tile_singlet_width_pixels + adjustment) wide +// duplex-width tiles are (2 * tile_singlet_width_pixels - adjustment) wide +// two-col tiling: two columns of tiles side-by-side, the one on the left containing singlet-width tiles and the one on the right containing duplex-width tiles +// row-col tiling: draw singlet-width tiles in the top row; below this row, draw duplex-width tiles in a column +void do_settings_panel_layout(float* data_width, float* data_height, bool landscape, int y_size, float dpi, float pixel_6a_dpi) { + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle& style = ImGui::GetStyle(); + + adjustment = 0.f; + // should compute these values only once, but there's no way to get the navigation/status bar heights in landscape mode when in portrait mode or vice-versa; it's necessary to wait until the device actually enters a given orientation to access the heights + // in landscape mode, allow scrolling the settings panel in the y direction, so there's no need to account for different y sizes across devices + if(landscape) { + settings_height_max = y_size; + *data_height = y_size; + tile_singlet_width_pixels = settings_height_max * pixel_6a_setting_panel_aspect / 3.f; + } else { + // if the current device's screen is smaller width-wise than the pixel 6a's screen, make sure the singlet-width tiles remain the same width in inches as on the pixel 6a. do this by transfering space from the duplex-width tiles (which aren't as space-constrained) + adjustment = ((pixel_6a_screen_width * dpi / pixel_6a_dpi) - static_cast(io.DisplaySize.x))/3.; + adjustment = adjustment < 0 ? 0 : adjustment; + tile_singlet_width_pixels = (io.DisplaySize.x - style.ItemSpacing.x - 2 * style.WindowPadding.x)/3.; + } + // col1 and grp1 contain singlet-width tiles, col2 and grp2 have duplex-width tiles + tile_col_heights[0] = 0.f; + tile_col_heights[1] = 0.f; + + n_singlet_tiles_visible = 0; + singlet_tile_height_when_row_col_tiling = 0.f; + for(int i=0; i < n_tiles; i++) { + if(tiles[i]->is_visible) { + float height = tiles[i]->next_is_expanded ? tiles[i]->get_height() : tiles[i]->get_collapsed_height(); + tile_col_heights[static_cast(tiles[i]->width)] += height; + if(tiles[i]->width == UI_tile::Width::singlet) { + singlet_tile_height_when_row_col_tiling = fmax(singlet_tile_height_when_row_col_tiling, height); + n_singlet_tiles_visible++; + } + } + } + + // these widths only relevent to two-col tiling + col1_width = (n_singlet_tiles_visible > 0) ? tile_singlet_width_pixels : 0; + col2_width = (tile_col_heights[1] > 0) ? 2 * tile_singlet_width_pixels : 0; + + row_col_tiling = (!landscape && (n_singlet_tiles_visible == 2) && ((tile_col_heights[1] + singlet_tile_height_when_row_col_tiling) < fmax(tile_col_heights[0], tile_col_heights[1]))) || \ + (landscape && (n_singlet_tiles_visible > 0) && ((tile_col_heights[1] + singlet_tile_height_when_row_col_tiling) < settings_height_max)); + + if(landscape) { + if(collapse_settings) { + *data_width = ImGui::GetContentRegionAvail().x; + } else { + if(row_col_tiling) { + if (tile_col_heights[1] > 0.f) { + settings_width = 2 * tile_singlet_width_pixels + style.ItemSpacing.x; + } else if (n_singlet_tiles_visible > 0) { + settings_width = tile_singlet_width_pixels + (n_singlet_tiles_visible == 2) * (tile_singlet_width_pixels + style.ItemSpacing.x); + } else { + settings_width = 0.f; + } + } else { + settings_width = col1_width + col2_width + ((col1_width>0)&&(col2_width>0)) * style.ItemSpacing.x; + float max_col_height = fmax(tile_col_heights[0], tile_col_heights[1]); + if(max_col_height > settings_height_max) { + settings_width += style.ScrollbarSize; + } + } + settings_width = fmax(settings_width, ImGui::GetFontSize() + 2 * style.FramePadding.x); + *data_width = ImGui::GetContentRegionAvail().x - style.ItemSpacing.x - settings_width; + } + } else { + settings_width = io.DisplaySize.x - 2 * style.WindowPadding.x; + *data_width = settings_width; + if(collapse_settings) { + *data_height = ImGui::GetContentRegionAvail().y; + } else { + if(row_col_tiling) { + settings_height = singlet_tile_height_when_row_col_tiling + tile_col_heights[1]; + } else { + settings_height = fmax(tile_col_heights[0], tile_col_heights[1]); + } + settings_height = fmax(settings_height, ImGui::GetFontSize() + 2 * style.ItemSpacing.y); + *data_height = ImGui::GetContentRegionAvail().y - settings_height; + } + } +} + +#define INDENTUP ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(0.f,style.ItemSpacing.y)); // remove gaps between ui_tile groups in order to avoid unwanted presses on the background that open the ui_tile selector popup. this ItemSpacing is added back in by the tiles within their BeginGroup()/EndGroup() wrappings. ImGuiContext.DebugShowGroupRects is very handy for debugging the groups + +void draw_settings_panel(bool landscape, bool screen_keyboard_shown) { + ImGuiIO& io = ImGui::GetIO(); + ImGuiStyle& style = ImGui::GetStyle(); + if(!landscape) { + INDENTUP + } + if(!collapse_settings) { + ImGui::BeginChild("settings",ImVec2(0.f, 0.f), 0, (screen_keyboard_shown ? ImGuiWindowFlags_NoMouseInputs : 0)); + settings_window_center = ImGui::GetWindowPos() + ImGui::GetWindowSize()/2.; + ImGuiContext& g = *GImGui; + ImVec2 settings_start_pos = ImGui::GetCursorScreenPos(); + ImGui::SetNextItemAllowOverlap(); + if(ImGui::InvisibleButton("open ui_tile selector", {0.f, 0.f})) { + maybe_clicked_background = true; + } + ImGui::SetCursorScreenPos(settings_start_pos); + + if(row_col_tiling) { + for(int grp : {0,1}) { + if(grp==1) + INDENTUP + ImGui::BeginGroup(); + bool first = true; + for(int i=0; iis_visible && (static_cast(tiles[i]->width) == grp)) { + if((grp==1)&&(!first)) { + INDENTUP + } + first = false; + tiles[i]->draw(tile_singlet_width_pixels + grp * (tile_singlet_width_pixels + style.ItemSpacing.x), &inputs_ui); + maybe_clicked_background &= !ImGui::IsItemHovered(); + // items in group 0 are stacked side-by-side; those in group 1 are stacked vertically + if(grp==0) { + ImGui::SameLine(); // seems to be invalidated after endgroup, which is convenient here + } + } + } + ImGui::EndGroup(); + } + } else { + for(int col : {0,1}) { + if(tile_col_heights[col] > 0) + { + ImGui::BeginGroup(); + bool first = true; + for(int i=0; iis_visible && (static_cast(tiles[i]->width) == col)) { + if(!first) + INDENTUP + first=false; + if(landscape) { + tiles[i]->draw((static_cast(tiles[i]->width) + 1) * tile_singlet_width_pixels, &inputs_ui); + } else { + tiles[i]->draw((static_cast(tiles[i]->width) + 1) * tile_singlet_width_pixels + (-2*static_cast(tiles[i]->width) + 1) * adjustment, &inputs_ui); + } + maybe_clicked_background &= !ImGui::IsItemHovered(); + } + } + ImGui::EndGroup(); + ImGui::SameLine(); + } + } + ImGui::NewLine(); + } + ImGui::EndChild(); + + } +} + +int get_selector_popup_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + return style.WindowPadding.y + style.WindowBorderSize + \ + style.ItemSpacing.y + ImGui::GetFontSize() + \ + style.ItemSpacing.y + style.SeparatorSize + \ + CHECKBOX_SIZE * n_tiles + style.ItemSpacing.y * (n_tiles - 1) + \ + style.WindowPadding.y + style.WindowBorderSize; +} + +int get_selector_popup_width() +{ + ImGuiStyle& style = ImGui::GetStyle(); + float text_width = 0; + for(int i = 0; i < n_tiles; i++) { + text_width = fmax(text_width, ImGui::CalcTextSize(tiles[i]->name).x); + } + return CHECKBOX_SIZE + style.ItemInnerSpacing.x + text_width + 2 * (style.WindowBorderSize + style.WindowPadding.x); +} + +void draw_selector_popup(bool landscape, bool orientation_changed) { + if(maybe_clicked_background || (orientation_changed && ImGui::IsPopupOpen("config_settings"))) { + ImVec2 main_window_bottom_right = ImGui::GetWindowPos() + ImGui::GetWindowSize(); + ImVec2 centered_selector_window_bottom_right = settings_window_center + ImVec2(get_selector_popup_width(), get_selector_popup_height())/2.; + if(\ + (landscape && (centered_selector_window_bottom_right.x > main_window_bottom_right.x)) || + (!landscape && (centered_selector_window_bottom_right.y > main_window_bottom_right.y))) { + ImVec2 edge_selector_window_pos = ImGui::GetWindowPos() + \ + ImVec2((ImGui::GetWindowSize().x - get_selector_popup_width()) * (landscape ? 1. : 0.5), (ImGui::GetWindowSize().y - get_selector_popup_height()) * (landscape ? 0.5 : 1)); + ImGui::SetNextWindowPos(edge_selector_window_pos,0,ImVec2(0.f,0.f)); + } else { + ImGui::SetNextWindowPos(settings_window_center,0,ImVec2(0.5f,0.5f)); + } + ImGui::OpenPopup("config_settings"); + maybe_clicked_background = false; + } + if(ImGui::BeginPopup("config_settings")) { + ImGui::Text("Select tiles"); + ImGui::Separator(); + for (int i=0; i< n_tiles; i++) { + if(ImGui::Checkbox(tiles[i]->name, &tiles[i]->is_visible)) { + if(tiles[i]->is_visible) + { + tiles[i]->next_is_expanded = true; + } + } + } + ImGui::EndPopup(); + } +} + +void draw_collapse_button(bool landscape, ImVec2 dataWindowBottomLeft, ImVec2 dataWindowBottomRight) { + ImGuiStyle& style = ImGui::GetStyle(); + ImGuiID collapse_id = ImGui::GetID("collapse"); + ImVec2 collapse_button_pos; + char label[36]; + if(landscape) { + if(collapse_settings) { + strcpy(label, " < "); + } else { + strcpy(label, " > "); + } + collapse_button_pos = dataWindowBottomRight - ImGui::CalcTextSize(" < ") - style.FramePadding * 2; + } else { + if(collapse_settings) { + strcpy(label, " ^ "); + } else { + strcpy(label, " v "); + } + collapse_button_pos = dataWindowBottomLeft - ImVec2(0.f,ImGui::CalcTextSize(" ^ ").y + style.FramePadding.y * 2); + } + ImGui::BeginChild("data"); // to append to the 'plot' child, need to re-enter into each of its parents + ImGui::BeginChild("plot"); + ImGui::SetCursorScreenPos(collapse_button_pos); + if(ImGui::custom_ButtonEx(label)) { + collapse_settings = !collapse_settings; + } + ImGui::EndChild(); + ImGui::EndChild(); +} diff --git a/Android_App/app/src/main/cpp/settings_panel.h b/Android_App/app/src/main/cpp/settings_panel.h new file mode 100644 index 000000000..d1bf6ec9a --- /dev/null +++ b/Android_App/app/src/main/cpp/settings_panel.h @@ -0,0 +1,27 @@ +#ifndef SETTINGSPANEL_H +#define SETTINGSPANEL_H + +#include "ui_tile.h" +#include "sig_gen_ui.h" +#include "inputs_ui.h" +#include "trigger_ui.h" +#include "virtual_transform_ui.h" +#include "psu_ui.h" +#include "logic_decode_ui.h" +#define IMGUI_DEFINE_MATH_OPERATORS +#include "custom_imgui.h" +#include "imgui.h" +#include "imgui_internal.h" + +extern inputsUI inputs_ui; +extern triggerUI trigger_ui; +extern virtualTransformUI virtual_transform_ui; +extern sigGenUI sig_gen_ui; +extern psuUI psu_ui; +extern logicDecodeUI logic_decode_ui; + +void do_settings_panel_layout(float* data_width, float* data_height, bool landscape, int y_size, float dpi, float pixel_6a_dpi); +void draw_settings_panel(bool landscape, bool screen_keyboard_shown); +void draw_selector_popup(bool landscape, bool orientation_changed); +void draw_collapse_button(bool landscape, ImVec2 dataWindowBottomLeft, ImVec2 dataWindowBottomRight); +#endif // SETTINGSPANEL_H diff --git a/Android_App/app/src/main/cpp/sig_gen_ui.cpp b/Android_App/app/src/main/cpp/sig_gen_ui.cpp new file mode 100644 index 000000000..d91f18e31 --- /dev/null +++ b/Android_App/app/src/main/cpp/sig_gen_ui.cpp @@ -0,0 +1,134 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "imgui_internal.h" +#include "librador.h" +#include "custom_imgui.h" +#include +#include "imgui_internal.h" +#include "sig_gen_ui.h" +#include "inputs_ui.h" + + +void sigGenUI::amp_or_min_slider_and_button(const char* slider_label, const char* button_label, float *amp_or_min, float *amp_or_min_delayed, float *min_or_amp, float *min_or_amp_delayed) { + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushItemWidth(-1); + if(ImGui::custom_SliderFloat(slider_label, "V", amp_or_min, 0.f, 9.6 - *min_or_amp_delayed, "%.2f V") || ImGui::IsItemDeactivatedAfterEdit()) { + need_usb_send = true; + if(ImGui::IsItemDeactivatedAfterEdit()) { + *amp_or_min = std::min(*amp_or_min, 9.6f); + *amp_or_min = std::max(*amp_or_min, 0.f); + *min_or_amp = std::min(*min_or_amp, 9.6f - *amp_or_min);//only can have an effect on manual input + *min_or_amp_delayed = *min_or_amp; + *amp_or_min_delayed = *amp_or_min; + } + } + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(style.CellPadding.x,0.f)); + ButtonForSlider(button_label, slider_label, ImVec2(ImGui::GetContentRegionAvail().x + style.CellPadding.x,0.f)); +} + +void sigGenUI::draw(float width_pixels, inputsUI* inputs_ui) +{ + bool ch2_disabled = inputs_ui->logic_on(); + ImGuiStyle& style = ImGui::GetStyle(); + if(ch2_disabled) { + both_ch_data[1] = ch_data(); + } + + ImGui::BeginGroup(); + standard_header(width_pixels); + if(!is_expanded) + { + ImGui::EndGroup(); + return; + } + + ImDrawList* draw_list; + ImVec2 p0; + ImVec2 p1; + + if (ImGui::BeginTable("sg_table", 2, ImGuiTableFlags_SizingStretchProp|ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg , ImVec2(width_pixels,0.f))) + { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.75f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.25f); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::RadioButton("CH1", &ch_sel, 1); ImGui::SameLine(); + ImGui::RadioButton("CH2", &ch_sel, 2); + ImGui::BeginDisabled(ch2_disabled && ch_sel == 2); + curr_ch_data = &both_ch_data[ch_sel-1]; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushItemWidth(-1); + if(ImGui::Combo("##combo3", &curr_ch_data->wf, wf_names, IM_COUNTOF(wf_names))) + need_usb_send = true; + + ImGui::TableNextColumn(); + ImGui::Text("Type"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushItemWidth(-1); + float freq_conv = curr_ch_data->freq / freq_slider_bases[curr_ch_data->slider_base]; + if(ImGui::custom_SliderFloat("##sg_freq_slider", freq_slider_suffixs[curr_ch_data->slider_base], &freq_conv, 0.0f, freq_slider_maxima[curr_ch_data->slider_base] / freq_slider_bases[curr_ch_data->slider_base], freq_slider_formats[curr_ch_data->slider_base]) + || ImGui::IsItemDeactivatedAfterEdit()) + { + need_usb_send = true; + curr_ch_data->freq = freq_conv * freq_slider_bases[curr_ch_data->slider_base]; + if(ImGui::IsItemDeactivatedAfterEdit()) { + curr_ch_data->freq = std::min(curr_ch_data->freq, freq_slider_maxima[n_bases-1]); + curr_ch_data->freq = std::max(curr_ch_data->freq, 0.f); + if(curr_ch_data->freq <= freq_slider_maxima[0]) { + curr_ch_data->slider_base = 0; + } else { + int i; + for(i=1;i= curr_ch_data->freq) && (freq_slider_maxima[i-1] < curr_ch_data->freq)) // find optimal freq scale to use for the slider given the value of the manually input freq. + break; + } + curr_ch_data->slider_base=i; + } + } + } + + ImGui::TableNextColumn(); + + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(style.CellPadding.x,0.f)); + if(ButtonForSlider("Freq.", "##sg_freq_slider", ImVec2(ImGui::GetContentRegionAvail().x + style.CellPadding.x,0.f))) { // short press on button + curr_ch_data->slider_base = (curr_ch_data->slider_base + 1) % n_bases; // toggle frequency base + curr_ch_data->freq = std::min(curr_ch_data->freq, freq_slider_maxima[curr_ch_data->slider_base]); + } + + amp_or_min_slider_and_button("##sg_amp_slider", "Amp.", &curr_ch_data->amp, &curr_ch_data->amp_delayed, &curr_ch_data->min_val, &curr_ch_data->min_val_delayed); + amp_or_min_slider_and_button("##sg_min_slider", "Min.", &curr_ch_data->min_val, &curr_ch_data->min_val_delayed, &curr_ch_data->amp, &curr_ch_data->amp_delayed); + + ImGui::EndDisabled(); // ch_sel==2 && ch2_disabled + + ImGui::EndTable(); + } + ImGui::EndGroup(); + if(need_usb_send) { + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + if(std::chrono::duration_cast(now - last_usb_send) > between_usb_sends_min) { + usb_send_data(ch_sel); + last_usb_send = now; + need_usb_send = false; + } + } +} + +void sigGenUI::usb_send_data(int ch) +{ + librador_send_wave(both_ch_data[ch-1].wf, ch, both_ch_data[ch-1].freq, both_ch_data[ch-1].amp, both_ch_data[ch-1].min_val); +} + +int sigGenUI::get_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + int calc_height = 2 * style.ItemSpacing.y + ImGui::GetFontSize() + \ + CHECKBOX_SIZE + 2 * style.CellPadding.y + \ + 4 * (ImGui::GetFontSize() + 2 * style.FramePadding.y + 2 * style.CellPadding.y); + return calc_height; +} diff --git a/Android_App/app/src/main/cpp/sig_gen_ui.h b/Android_App/app/src/main/cpp/sig_gen_ui.h new file mode 100644 index 000000000..8700b2762 --- /dev/null +++ b/Android_App/app/src/main/cpp/sig_gen_ui.h @@ -0,0 +1,39 @@ +#ifndef SIGGENUI_H +#define SIGGENUI_H + +#include +#include "ui_tile.h" + +class sigGenUI : public UI_tile +{ + const static int n_bases = 5; + const int freq_slider_bases[n_bases] = {1,1,1,1000,1000}; + const float freq_slider_maxima[n_bases] = {10.f,100.f,1000.f,10000.f,64000.f}; + const char* freq_slider_formats[n_bases] = {"%.1f Hz", "%.0f Hz", "%.0f Hz", "%.1f kHz", "%.1f kHz"}; + const char* freq_slider_suffixs[n_bases] = {"Hz", "Hz", "Hz", "kHz", "kHz"}; + const char* wf_names[4] = { "Sin", "Square", "Triangle", "Sawtooth" }; + const std::chrono::milliseconds between_usb_sends_min{100}; + + void amp_or_min_slider_and_button(const char* slider_label, const char* button_label, float *amp_or_min, float *amp_or_min_delayed, float *min_or_amp, float *min_or_amp_delayed); + std::chrono::steady_clock::time_point last_usb_send; + struct ch_data { + int wf = 0; + int slider_base = 2; + float freq = 500.f; + float amp = 0.f; + float min_val = 0.f; + float amp_delayed = 0.f; + float min_val_delayed = 0.f; + }; + ch_data both_ch_data[2]; + ch_data * curr_ch_data = both_ch_data; // helper + bool need_usb_send; + int ch_sel = 1; +public: + sigGenUI() : UI_tile("Signal Generator", "Signal Generator", UI_tile::Width::duplex, 6) {}; + void draw(float width, inputsUI* inputs_ui = nullptr) override; + void usb_send_data(int ch); + int get_height() override; +}; + +#endif // SIGGENUI_H diff --git a/Android_App/app/src/main/cpp/trigger_ui.cpp b/Android_App/app/src/main/cpp/trigger_ui.cpp new file mode 100644 index 000000000..47e06bfd1 --- /dev/null +++ b/Android_App/app/src/main/cpp/trigger_ui.cpp @@ -0,0 +1,218 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "librador.h" +#include "custom_imgui.h" +#include +#include "imgui_internal.h" +#include "trigger_ui.h" + + +void triggerUI::draw(float width_pixels, inputsUI* inputs_ui) +{ + bool enable_helper[2] = {inputs_ui->scope_enable[0] || inputs_ui->mm, inputs_ui->scope_enable[1]}; + for (int ch:{1,2}) + { + if(!enable_helper[ch-1]) { + both_ch_trigger_settings[ch-1] = o1buffer::trigger_settings(); + } + } + ImGuiStyle& style = ImGui::GetStyle(); + ImGui::BeginGroup(); + standard_header(width_pixels); + if(!is_expanded) + { + ImGui::EndGroup(); + return; + } + ImGui::BeginGroup(); // for bounding rect + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 0.f)); + if(ImGui::BeginTable("trigger_helper1",1, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_NoHostExtendX, ImVec2(width_pixels, 0.))) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2(0.f, style.FramePadding.y - style.ItemSpacing.y)); +#define ALIGN_Y ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(0.f, style.FramePadding.y - style.ItemSpacing.y)); + ImGui::Text("CH: "); + ImGui::SameLine(); + ALIGN_Y + ImGui::RadioButton("A ", &ch_sel, 1); + ImGui::SameLine(); + ALIGN_Y + ImGui::RadioButton("B", &ch_sel, 2); + ImGui::EndTable(); + } + curr_ch_trigger_settings = &both_ch_trigger_settings[ch_sel - 1]; + ImGui::BeginDisabled(!enable_helper[ch_sel-1]); + if(ImGui::BeginTable("trigger_helper2",2, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_NoHostExtendX, ImVec2(width_pixels, 0.))) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.5f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.5f); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2((ImGui::GetContentRegionAvail().x - CHECKBOX_SIZE - style.ItemInnerSpacing.x - ImGui::CalcTextSize("Rising").x)/2.,0.f)); + ImGui::custom_RadioButton("Rising", (int *) &curr_ch_trigger_settings->trigger_type, 1); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2((ImGui::GetContentRegionAvail().x - CHECKBOX_SIZE - style.ItemInnerSpacing.x - ImGui::CalcTextSize("Falling").x)/2.,0.f)); + ImGui::custom_RadioButton("Falling", (int *) &curr_ch_trigger_settings->trigger_type, 2); + ImGui::EndTable(); + } + if(ImGui::BeginTable("trigger_helper3",2, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_NoHostExtendX, ImVec2(width_pixels, 0.))) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.75f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.25f); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushItemWidth(-1); + ImGui::custom_SliderFloat("##trigger level", "V", &curr_ch_trigger_settings->trigger_level, -20.f, 20.f, "%.1f V", ImGuiSliderFlags_ClampOnInput); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(style.CellPadding.x,0.f)); + ButtonForSlider("Level", "##trigger level", ImVec2(ImGui::GetContentRegionAvail().x + style.CellPadding.x,0.f)); + ImGui::EndTable(); + } + if(ImGui::BeginTable("trigger_helper4",1, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_NoHostExtendX, ImVec2(width_pixels, 0.))) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2((ImGui::GetContentRegionAvail().x - CHECKBOX_SIZE - style.ItemInnerSpacing.x - ImGui::CalcTextSize("Single shot").x)/2.,0.f)); + ImGui::Checkbox("Single shot", &curr_ch_trigger_settings->is_single_shot); + ImGui::EndTable(); + } + ImGui::EndDisabled(); + + ImGui::PopStyleVar(); //itemspacing + ImGui::EndGroup(); + ImVec2 p0 = ImGui::GetItemRectMin(); + ImVec2 p1 = ImGui::GetItemRectMax(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255)); + ImGui::EndGroup(); + + if(curr_ch_trigger_settings->trigger_type != o1buffer::TriggerType::Disabled) + { + both_ch_trigger_settings[ch_sel%2].trigger_type = o1buffer::TriggerType::Disabled; + librador_set_trigger_settings(ch_sel%2+1, both_ch_trigger_settings[ch_sel%2]); + } + + librador_set_trigger_settings(ch_sel, both_ch_trigger_settings[ch_sel-1]); + +} + +int triggerUI::get_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + int calc_height = 2 * style.ItemSpacing.y + ImGui::GetFontSize() + \ + 3 * (CHECKBOX_SIZE + 2 * style.CellPadding.y) + \ + (ImGui::GetFontSize() + 2 * style.FramePadding.y + 2 * style.CellPadding.y); + return calc_height; +} + +// singlet-width version that could become useful in the future +// void triggerUI::draw(float width_pixels, inputsUI* inputs_ui) +// { +// bool enable_helper[2] = {inputs_ui->scope_enable[0] || inputs_ui->mm, inputs_ui->scope_enable[1]}; +// for (int ch:{1,2}) +// { +// if(!enable_helper[ch-1]) { +// both_ch_trigger_settings[ch-1] = o1buffer::trigger_settings(); +// } +// } +// ImGuiStyle& style = ImGui::GetStyle(); +// ImGui::BeginGroup(); +// standard_header(width_pixels); +// if(!is_expanded) +// { +// ImGui::EndGroup(); +// return; +// } +// ImGui::BeginGroup(); // for bounding rect +// // get_height() line 1 end +// +// ImGui::BeginGroup(); // for bounding rect +// int free_space = width_pixels - ImGui::CalcTextSize("ChAChB").x - 2 * CHECKBOX_SIZE - 2 * style.ItemInnerSpacing.x - style.FramePadding.x * 2; +// ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + style.FramePadding); +// ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(free_space,0.f)); +// ImGui::RadioButton("ChA", &ch_sel, 1); ImGui::SameLine(); +// ImGui::RadioButton("ChB", &ch_sel, 2); +// ImGui::PopStyleVar(); +// ImGui::EndGroup(); +// curr_ch_trigger_settings = &both_ch_trigger_settings[ch_sel - 1]; +// ImVec2 p0 = ImGui::GetItemRectMin(); +// ImVec2 p1 = ImGui::GetItemRectMax() + style.FramePadding; +// ImGui::SetCursorScreenPos(ImVec2(ImGui::GetCursorScreenPos().x, p1.y)); // replacing ItemSpacing with FramePadding +// ImVec2 slider_top_right = p1; +// ImDrawList* draw_list = ImGui::GetWindowDrawList(); +// draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255)); +// // get_height() line 2 end +// +// float slider_left1 = (p0 + (p1-p0) * .75).x; +// ImGui::BeginDisabled(!enable_helper[ch_sel-1]); +// ImGui::BeginGroup(); +// ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + style.FramePadding); +// ImGui::custom_RadioButton("Rising", (int *) &curr_ch_trigger_settings->trigger_type, 1); +// ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2(style.FramePadding.x,0.f)); +// ImGui::custom_RadioButton("Falling", (int *) &curr_ch_trigger_settings->trigger_type, 2); +// p1 = ImGui::GetItemRectMax() + style.FramePadding; +// float slider_left2 = p1.x; +// float slider_left = fmax(slider_left1, slider_left2); +// p0 = ImVec2(ImGui::GetItemRectMin().x - style.FramePadding.x, p1.y); +// ImVec2 saved_pos = p0; +// // get_height() line 3 end +// draw_list = ImGui::GetWindowDrawList(); +// draw_list->AddLine(p0, p1, IM_COL32(90, 90, 120, 255)); +// float ss_text_height = ImGui::CalcTextSize("Single\n shot").y + 2 * style.ItemSpacing.y + 2; // +2 is a fudge factor that makes this correct +// ImGui::SetCursorScreenPos(ImVec2(ImGui::GetItemRectMin().x, p0.y + (ss_text_height - CHECKBOX_SIZE)/2.)); +// ImGui::Checkbox("##ss", &curr_ch_trigger_settings->is_single_shot); +// ImGui::SameLine(); +// ImGui::SetCursorScreenPos(ImVec2(ImGui::GetCursorScreenPos().x, saved_pos.y)); +// ImGui::Text("Single\n shot"); +// ImGui::EndGroup(); +// // height relative to init_pos; +// p0 = ImGui::GetItemRectMin(); +// p1 = ImGui::GetItemRectMax() + style.FramePadding; +// draw_list = ImGui::GetWindowDrawList(); +// draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255)); +// +// ImVec2 value_text_size = ImGui::CalcTextSize("-20.0 V", NULL); +// ImVec2 value_text_button_size = value_text_size + style.FramePadding + style.FramePadding; +// ImVec2 value_text_button_pos = p1 + ImVec2(-value_text_button_size.x, 0.f); +// ImGui::SetCursorScreenPos(value_text_button_pos); +// // get_height() line 4 end +// ButtonForSlider("##trigger_button", "##trigger_slider", value_text_button_size); +// ImVec2 saved_pos2 = ImGui::GetCursorScreenPos(); +// float slider_bottom = saved_pos2.y - style.ItemSpacing.y; +// +// // get_height() line 5 end +// +// ImGui::SetCursorScreenPos(ImVec2(slider_left, slider_top_right.y)); +// +// ImGui::custom_VSliderFloat("##trigger_slider", "V", +// ImVec2(slider_top_right.x - slider_left , slider_bottom - slider_top_right.y), +// &curr_ch_trigger_settings->trigger_level, -20.f, 20.f, "%.1f V", ImGuiSliderFlags_ClampOnInput, value_text_button_pos + style.FramePadding, value_text_size); +// ImGui::EndDisabled(); +// ImGui::SetCursorScreenPos({ImGui::GetCursorScreenPos().x, slider_bottom}); +// ImGui::Dummy({0.f,0.f}); // prevents issue with this draw() command affecting the vertical alignment of whatever ui element comes after it +// ImGui::EndGroup(); +// p0 = ImGui::GetItemRectMin(); +// p1 = ImGui::GetItemRectMax(); +// draw_list = ImGui::GetWindowDrawList(); +// draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255)); +// +// if(curr_ch_trigger_settings->trigger_type != o1buffer::TriggerType::Disabled) +// { +// both_ch_trigger_settings[ch_sel%2].trigger_type = o1buffer::TriggerType::Disabled; +// librador_set_trigger_settings(ch_sel%2+1, both_ch_trigger_settings[ch_sel%2]); +// } +// +// librador_set_trigger_settings(ch_sel, both_ch_trigger_settings[ch_sel-1]); +// ImGui::EndGroup(); +// } + +// for the singlet-width version of this widget +// int triggerUI::get_height() +// { +// ImGuiStyle& style = ImGui::GetStyle(); +// int calc_height = 2 * style.ItemSpacing.y + ImGui::GetFontSize() + \ +// CHECKBOX_SIZE + 2 * style.FramePadding.y + \ +// 2 * CHECKBOX_SIZE + 2 * style.FramePadding.y + style.ItemSpacing.y + \ +// ImGui::CalcTextSize("Single\n shot").y + style.FramePadding.y + style.ItemSpacing.y + 2 + \ +// ImGui::GetFontSize() + 2 * style.FramePadding.y; +// return calc_height; +// } + diff --git a/Android_App/app/src/main/cpp/trigger_ui.h b/Android_App/app/src/main/cpp/trigger_ui.h new file mode 100644 index 000000000..25d360a10 --- /dev/null +++ b/Android_App/app/src/main/cpp/trigger_ui.h @@ -0,0 +1,17 @@ +#ifndef TRIGGERUI_H +#define TRIGGERUI_H + +#include "o1buffer.h" +#include "ui_tile.h" +#include "inputs_ui.h" +class triggerUI : public UI_tile +{ + int ch_sel = 1; + o1buffer::trigger_settings both_ch_trigger_settings[2]; + o1buffer::trigger_settings* curr_ch_trigger_settings = &both_ch_trigger_settings[ch_sel-1]; +public: + triggerUI() : UI_tile("Trigger","Trigger",UI_tile::Width::duplex, 5) {}; + void draw(float width, inputsUI* inputs_ui = nullptr) override; + int get_height() override; +}; +#endif diff --git a/Android_App/app/src/main/cpp/ui_tile.cpp b/Android_App/app/src/main/cpp/ui_tile.cpp new file mode 100644 index 000000000..cdec80f2d --- /dev/null +++ b/Android_App/app/src/main/cpp/ui_tile.cpp @@ -0,0 +1,52 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "imgui_internal.h" +#include "ui_tile.h" +void UI_tile::standard_header(float width_pixels) +{ + is_expanded = next_is_expanded; + ImGuiStyle& style = ImGui::GetStyle(); + + float close_button_width = ImGui::GetFontSize() + style.FramePadding.x; + ImVec2 start_pos = ImGui::GetCursorScreenPos(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2(0.f,style.ItemSpacing.y)); // combined with lines in settings_panel.cpp, effectively folds ItemSpacing.y into the individual ui_tile groups + ImGui::Text("%s",short_name); + ImGui::SetCursorScreenPos(start_pos); + ImGui::PushID(short_name); +// TODO : make button larger, remove Dummy at the end + float invisible_button_width; + ImVec2 close_button_pos = start_pos + ImVec2(width_pixels - close_button_width,style.ItemSpacing.y); + if(is_expanded) { + invisible_button_width = width_pixels; + } else { + invisible_button_width = width_pixels - close_button_width; + } + float itemspacingy = style.ItemSpacing.y; + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,{style.ItemSpacing.x,0.f}); // fold ItemSpacing.y into the invisible button below + if(ImGui::InvisibleButton("toggle is_expanded", {invisible_button_width, ImGui::GetFontSize() + 2 * itemspacingy})) + { + next_is_expanded = !next_is_expanded; + } + ImGui::PopID(); + + if(!is_expanded) + { + char buf[64]; + sprintf(buf, "%s_close", short_name); + if(ImGui::CloseButton(ImGui::GetID(buf), close_button_pos)) + { + is_visible = false; + } + ImGui::SameLine(); + // mimic the spacing/cursor advancement that a standard Button(...) would generate + ImGui::SetCursorScreenPos(close_button_pos); + ImGui::Dummy({close_button_width,0.f}); + } + ImGui::PopStyleVar(); +} + +int UI_tile::get_collapsed_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + return ImGui::GetFontSize() + 2 * style.ItemSpacing.y; +} diff --git a/Android_App/app/src/main/cpp/ui_tile.h b/Android_App/app/src/main/cpp/ui_tile.h new file mode 100644 index 000000000..c23c3eda3 --- /dev/null +++ b/Android_App/app/src/main/cpp/ui_tile.h @@ -0,0 +1,23 @@ +#ifndef UITILE_H +#define UITILE_H +class inputsUI; + +class UI_tile +{ + public: + virtual ~UI_tile() {}; + enum Width {singlet, duplex}; + UI_tile(const char* name, const char* short_name, Width width, int n_lines) : name(name), short_name(short_name), width(width), n_lines(n_lines) {}; + virtual int get_height() = 0; + int get_collapsed_height(); + virtual void draw(float width_pixels, inputsUI* inputs_ui = nullptr) = 0; + const Width width; + int n_lines; + const char* name; + const char* short_name; + void standard_header(float width_pixels); + bool is_expanded = true; + bool next_is_expanded = true; // to prevent expansion/contraction of tiles mid-frame + bool is_visible = true; +}; +#endif diff --git a/Android_App/app/src/main/cpp/virtual_transform_ui.cpp b/Android_App/app/src/main/cpp/virtual_transform_ui.cpp new file mode 100644 index 000000000..6e96f9aa0 --- /dev/null +++ b/Android_App/app/src/main/cpp/virtual_transform_ui.cpp @@ -0,0 +1,96 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "imgui.h" +#include "librador.h" +#include "custom_imgui.h" +#include +#include "imgui_internal.h" +#include "virtual_transform_ui.h" + + +void virtualTransformUI::draw(float width_pixels, inputsUI* inputs_ui) +{ + ImGuiStyle& style = ImGui::GetStyle(); + + for (int ch : {1,2}) { + both_ch_settings[ch-1].is_paused = librador_get_paused(ch); // could have been set to true by a singleshot trigger + } +// if(xy && j==2) // sync ch1 and ch2 pause states in xy mode +// *(checkbox_bool[j] + (i+1)%2) = *(checkbox_bool[j] + i); + + ImGui::BeginGroup(); + standard_header(width_pixels); + if(!is_expanded) { + ImGui::EndGroup(); + return; + } + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 0.f)); + ImGui::BeginGroup(); // for bounding rect + if(ImGui::BeginTable("helper1",2, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_NoHostExtendX, ImVec2(width_pixels, 0.))) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.6f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.4f); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2(0.f, style.FramePadding.y - style.ItemSpacing.y)); +#define ALIGN_Y ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(0.f, style.FramePadding.y - style.ItemSpacing.y)); + ImGui::Text("CH: "); + ImGui::SameLine(); + ALIGN_Y + ImGui::RadioButton("A ", &ch_sel, 1); + ImGui::SameLine(); + ALIGN_Y + ImGui::RadioButton("B", &ch_sel, 2); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2((ImGui::GetContentRegionAvail().x - CHECKBOX_SIZE - ImGui::CalcTextSize("||").x - style.ItemInnerSpacing.x)/2.,0.f)); + ImGui::Checkbox("||", &curr_ch_settings->is_paused); + ImGui::EndTable(); + } + + const float offset_button_width = style.FramePadding.x*2 + ImGui::CalcTextSize("Offset").x; + if(ImGui::BeginTable("helper2",2, ImGuiTableFlags_SizingStretchProp|ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg , ImVec2(width_pixels, 0.))) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.7f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.3f); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::PushItemWidth(-1); + ImGui::custom_SliderFloat("##offset", "V", &curr_ch_settings->offset, -20.f, 20.f, "%.1f V", ImGuiSliderFlags_ClampOnInput); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() - ImVec2(style.CellPadding.x,0.f)); + ButtonForSlider("Offset", "##offset", ImVec2(ImGui::GetContentRegionAvail().x + style.CellPadding.x,0.f)); + ImGui::EndTable(); + } + if(ImGui::BeginTable("helper3", 2, ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH, ImVec2(width_pixels, 0.f))) { + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.6f); + ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.4f); + ImGui::TableNextRow(); + ImGui::TableNextColumn(); +// ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {style.FramePadding.x/4.f,style.FramePadding.y}); + ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - style.FramePadding.x - ImGui::CalcTextSize("Gain").x); + ImGui::Combo("Gain", &curr_ch_settings->gain_sel, gain_labels, IM_COUNTOF(gain_labels)); +// ImGui::PopStyleVar(); + ImGui::TableNextColumn(); + ImGui::SetCursorScreenPos(ImGui::GetCursorScreenPos() + ImVec2((ImGui::GetContentRegionAvail().x - CHECKBOX_SIZE - ImGui::CalcTextSize("AC").x - style.ItemInnerSpacing.x)/2.,0.f)); + ImGui::Checkbox("AC", &curr_ch_settings->is_ac); + ImGui::EndTable(); + } + ImGui::PopStyleVar(); //iteminnerspacing + ImGui::EndGroup(); + + curr_ch_settings = &both_ch_settings[ch_sel-1]; + ImVec2 p0 = ImGui::GetItemRectMin(); + ImVec2 p1 = ImGui::GetItemRectMax(); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRect(p0, p1, IM_COL32(90, 90, 120, 255),0,0,2); + ImGui::EndGroup(); + librador_set_virtual_transform_settings(ch_sel, + (o1buffer::virtual_transform_settings) + {.offset=curr_ch_settings->offset, .gain=gains[curr_ch_settings->gain_sel], .is_ac=curr_ch_settings->is_ac, .is_paused=curr_ch_settings->is_paused}); +} + +int virtualTransformUI::get_height() +{ + ImGuiStyle& style = ImGui::GetStyle(); + int calc_height = 2 * style.ItemSpacing.y + ImGui::GetFontSize() + \ + CHECKBOX_SIZE + 2 * style.CellPadding.y + \ + 2 * (ImGui::GetFontSize() + 2 * style.FramePadding.y + 2 * style.CellPadding.y); + return calc_height; +} diff --git a/Android_App/app/src/main/cpp/virtual_transform_ui.h b/Android_App/app/src/main/cpp/virtual_transform_ui.h new file mode 100644 index 000000000..33decc06c --- /dev/null +++ b/Android_App/app/src/main/cpp/virtual_transform_ui.h @@ -0,0 +1,25 @@ +#ifndef VIRTUALTRANSFORMUI_H +#define VIRTUALTRANSFORMUI_H + +#include "ui_tile.h" +class virtualTransformUI : public UI_tile +{ + static const int num_gain_options = 3; + const int gains[num_gain_options] = {1, 5, 10}; + const char* gain_labels[num_gain_options] = {"1x", "5x", "10x"}; + struct ch_settings { + float offset = 0.f; + int gain_sel = 0; + bool is_ac = false; + bool is_paused = false; + }; + + int ch_sel = 1; + ch_settings both_ch_settings[2]; + ch_settings* curr_ch_settings = both_ch_settings; +public: + virtualTransformUI() : UI_tile("Virtual Transforms", "Virtual Transforms", UI_tile::Width::duplex, 4) {}; + void draw(float width, inputsUI* inputs_ui = nullptr) override; + int get_height() override; +}; +#endif // VIRTUALTRANSFORMUI_H diff --git a/Android_App/app/src/main/java/com/EspoTek/Labrador/MainActivity.java b/Android_App/app/src/main/java/com/EspoTek/Labrador/MainActivity.java new file mode 100644 index 000000000..0bff0e553 --- /dev/null +++ b/Android_App/app/src/main/java/com/EspoTek/Labrador/MainActivity.java @@ -0,0 +1,309 @@ +package com.EspoTek.Labrador; + +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; +import android.hardware.usb.UsbDeviceConnection; +import android.content.Context; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.BroadcastReceiver; + +import android.content.res.AssetManager; +import android.os.Bundle; +import android.util.Log; + +import android.os.Build; +import android.content.res.Configuration; + +import org.libsdl.app.SDLActivity; + +import android.content.DialogInterface; +import android.app.AlertDialog; + +import java.io.BufferedOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import java.util.HashMap; +import java.util.Iterator; +import java.lang.String; + +import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.ViewCompat; +import android.content.pm.ActivityInfo; +// import android.graphics.Insets; + +// TODO: handle edge cases related to user unplugging board in non-bootloader state, replugging it back in in bootloader state +public class MainActivity extends SDLActivity { + private static final String ACTION_USB_PERMISSION = "com.EspoTek.Labrador.USB_PERMISSION"; + private static final String usbStateChangeAction = "android.hardware.usb.action.USB_STATE"; + private static final String TAG = "com.EspoTek.Labrador"; + public AssetManager mgr; + private boolean usb_permission_request_allowed = true; + + private UsbDeviceConnection connection = null; + public boolean bootloader_mode_allowed = false; // modified by usbcallhandler + private native void nativeRespondToStartupOrUsbStateChange(boolean is_plugged_in, int file_descriptor, boolean bootloader_mode); // fn in librador.cpp. **this fn initiates librador** + private native void nativeInitiateFirmwareFlash(); + + @Override + protected String[] getLibraries() { + return new String[]{"SDL3", "labrador-imgui-android"}; + } + + @Override + protected String getMainFunction() { + return "main"; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); +// https://stackoverflow.com/questions/10941802/cant-access-aassetmanager-in-native-code-passed-from-java-in-wallpaperservice/11617834#11617834 + mgr = getResources().getAssets(); + } + +// https://stackoverflow.com/questions/6981736/android-3-1-usb-host-broadcastreceiver-does-not-receive-usb-device-attached/9814826#9814826 +// https://stackoverflow.com/questions/8619883/onnewintent-lifecycle-and-registered-listeners +// called when the Labrador board is plugged in or restarted when the app is already running + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + Log.d(TAG, "on new intent"); + setIntent(intent); // set intent for subsequent call to onResume() + } + +// called on startup and on usb stage changes + @Override + protected void onResume() { + super.onResume(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); + // don't need to add the ACTION_USB_DEVICE_ATTACHED intent because it is already declared in the manifest and accordingly gets forwarded to this app's onNewIntent() by android software. + registerReceiver(myUsbDetachBroadcastReceiver, filter); + + Intent intent = getIntent(); + Log.d(TAG, "new intent: " + intent.getAction()); + UsbDevice device; + HashMap device_info = new HashMap(); + // look for the device + UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); //Handle to system USB service? + HashMap deviceList = manager.getDeviceList(); + Iterator deviceIterator = deviceList.values().iterator(); + if(!deviceIterator.hasNext()){ + Log.d(TAG, "no device found"); + } + while(device_info.isEmpty() && deviceIterator.hasNext()) { + Log.d(TAG, "device list has device"); + device = deviceIterator.next(); + device_info = processUsbDevice(device); + } + if(device_info.isEmpty()) { + nativeRespondToStartupOrUsbStateChange(false, -1, false); + } else { + int file_descriptor = device_info.get("file_descriptor"); + boolean bootloader_mode = device_info.get("bootloader_mode") == 1 ? true : false; + if(!bootloader_mode_allowed && bootloader_mode) { + AlertDialog alert = new AlertDialog.Builder(MainActivity.this) + .setMessage("Board found in bootloader mode, which is intended for firmware updates. Please unplug the board, disconnect Digital Out 1 from GND, plug the board back in, and then unplug and replug the board a second time. If a firmware update is needed, it will be performed automatically.") + .setPositiveButton("OK", new DialogInterface.OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int id) + { + } + } + ) + .setCancelable(false) + .create(); + alert.show(); + nativeRespondToStartupOrUsbStateChange(false, file_descriptor, bootloader_mode); + return; + } + nativeRespondToStartupOrUsbStateChange(true, file_descriptor, bootloader_mode); + } + } + + @Override + protected void onPause() { + super.onPause(); + unregisterReceiver(myUsbDetachBroadcastReceiver); + } + + @Override + protected void onStop() { + super.onStop(); + disconnectIfConnected(); + } + + private HashMap processUsbDevice(UsbDevice device) { + HashMap device_info = new HashMap(); + PendingIntent mPermissionIntent; + Intent intent = new Intent(MainActivity.ACTION_USB_PERMISSION); + intent.setPackage(MainActivity.getContext().getPackageName()); + + mPermissionIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE); + + UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE); //Handle to system USB service? + + // handle edge case: Labrador board is connected -> user puts phone to sleep -> user unplugs Labrador board -> user wakes phone back up (at which point onResume() gets called with intent= the most recent intent received by the app, i.e., the original intent signaling that the board was connected) + HashMap dl = manager.getDeviceList(); + if (!manager.getDeviceList().containsValue(device)) { + return device_info; + } + + int DeviceID = device.getDeviceId(); + int VID = device.getVendorId(); + int PID = device.getProductId(); + + // Block below: for the rare case that the app finds the board and android software hasn't handled the usb permissions, so they need to be handled by the app. E.g., if the user connects the board for the first time when their phone is asleep + if(!manager.hasPermission(device)) { + // block below: open a dialog window that prompts the user for usb connection permission. meanwhile, this function returns an empty device_info, which gets handled cleanly. After the user responds to the dialog window, onResume() gets called, which leads back to this fn. In the case of rejection by the user, the usb_permission_request_allowed boolean prevents the request from being repeated. This bool gets reset to true if the user disconnects the board. + if(usb_permission_request_allowed) { + manager.requestPermission(device, mPermissionIntent); + usb_permission_request_allowed = false; + } + return device_info; + } + + connection = manager.openDevice(device); + int file_descriptor; + if(connection==null) { + Log.d(TAG, "device connection fail"); + return device_info; + } else { + file_descriptor = connection.getFileDescriptor(); + } + Log.d(TAG, "fd = " + file_descriptor); + int bootloader_mode; + if((VID==0x03eb) && (PID==0x2fe4)) { + bootloader_mode = 1; + } else { + bootloader_mode = 0; + } + device_info.put("file_descriptor", file_descriptor); + device_info.put("bootloader_mode", bootloader_mode); + + Log.d(TAG, "Returning..."); + return device_info; + } + +// doesn't work ideally at the moment because iso_polling_thread in +// usbcallhandler.cpp encounters LIBUSB_ERROR_NO_DEVICE before the broadcast +// receiver below shuts down the thread. Then, usbcallhandler.cpp flushes out +// all remaining iso transfers that it had previously submitted. After that +// finishes, this broadcast receiver fires and does some more cleanup of the +// iso thread and also deletes the libusb handle on the Labrador board. + BroadcastReceiver myUsbDetachBroadcastReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + Log.d(TAG,"detach detector reached"); + String action = intent.getAction(); + if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { + UsbDevice device; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE, UsbDevice.class); + } else { + device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + } + int VID = device.getVendorId(); + int PID = device.getProductId(); + if((VID==0x03eb) && (PID==0xba94)){ + disconnectIfConnected(); + } + if(connection != null) { + connection.close(); + } + } + } + }; + + // for APIs 35 and higher, the status bar is included in the main display, so it's necessary to account for it and avoid it. Otherwise, return 0; + public int getStatusBarHeight() + { + int statusBarHeight; + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(getWindow().getDecorView()); + statusBarHeight = insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars()).top; + } else { + statusBarHeight = 0; + } + return statusBarHeight; + } + // for APIs 35 and higher, the navigation bar is included in the main display, so it's necessary to account for it and avoid it. Otherwise, return 0; + public int getNavigationBarHeight() + { + int navigationBarHeight; + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(getWindow().getDecorView()); + navigationBarHeight = insets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.systemBars()).bottom; + } else { + navigationBarHeight = 0; + } + return navigationBarHeight; + } + + public int getScreenWidth() + { + return getResources().getSystem().getDisplayMetrics().widthPixels; + } + + public int getScreenHeight() + { + return getResources().getSystem().getDisplayMetrics().heightPixels; + } + + public float getDpi() + { + return getResources().getSystem().getDisplayMetrics().xdpi; + } + + + // called by usbcallhandler.cpp + public void requestFirmwareFlash() + { + AlertDialog alert = new AlertDialog.Builder(MainActivity.this) + .setMessage("A firmware update is required. This process will produce several USB permission requests. Please accept them all.") + .setPositiveButton("OK", new DialogInterface.OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int id) + { + nativeInitiateFirmwareFlash(); + } + } + ) + .setCancelable(false) + .create(); + alert.show(); + } + + // called by usbcallhandler.cpp + public void confirmFirmwareFlash() + { + AlertDialog alert = new AlertDialog.Builder(MainActivity.this) + .setMessage("New firmware has been successfully uploaded to the Labrador board.") + .setPositiveButton("OK", new DialogInterface.OnClickListener() + { + @Override + public void onClick(DialogInterface dialog, int id) + { + } + } + ) + .setCancelable(false) + .create(); + alert.show(); + } + + public void disconnectIfConnected() + { + nativeRespondToStartupOrUsbStateChange(false, -1, false); + if(connection != null) { + connection.close(); + } + usb_permission_request_allowed = true; + } +} diff --git a/Android_App/app/src/main/res/drawable/ic_launcher_background.xml b/Android_App/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 000000000..07d5da9cb --- /dev/null +++ b/Android_App/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml b/Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 000000000..2b068d114 --- /dev/null +++ b/Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/layout/activity_main.xml b/Android_App/app/src/main/res/layout/activity_main.xml new file mode 100644 index 000000000..0fdf98529 --- /dev/null +++ b/Android_App/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..6f3b755bf --- /dev/null +++ b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..6f3b755bf --- /dev/null +++ b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..c209e78ecd372343283f4157dcfd918ec5165bb3 GIT binary patch literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9 GIT binary patch literal 2898 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 literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Android_App/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..4f0f1d64e58ba64d180ce43ee13bf9a17835fbca GIT binary patch literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!TQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

FJ$wK}0tWNB{uH;AM~i literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..948a3070fe34c611c42c0d3ad3013a0dce358be0 GIT binary patch literal 1900 zcmV-y2b1_xNk&Fw2LJ$9MM6+kP&il$0000G0001A003VA06|PpNH75a00DqwTbm-~ zullQTcXxO9ki!OCRx^i?oR|n!<8G0=kI^!JSjFi-LL*`V;ET0H2IXfU0*i>o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f GIT binary patch literal 3918 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�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp zwO~NVXwXCl;jE<}>%@xz|=8fIJAB?>+E{7)|4l${4ngA3G|=r z2Dyv;VVWSgZx9Wj>qUjleGl3Ei9K4>h!(lPS%8VOG>Xu0%6VDz^O=bjJmuP7>DeUv zrbI}MlHB^^d?{zv6d=@_ZD2lg1&G7UjnVN{1}9WkaM3H~btX0GtSzB+tZ^qRgWo4m z!GmimlG$=wgXCnr6j@m<1gAL46#T~5Bnm=2{^@>|t&`9mkEPddj zAvG~@Tv~TAm2i%VW}R-g(Z0)z-Y|szHr@rk>4MAyG*Ma*7Yh#H7(!-5>DZ@8r;_dx z{prSe<>~099F8vsYd2xff7uAS%7{S)f(|@me3t2$iy&NEc7OUEchp@9A|X;;IA>8!oX+y(BKJ$EzV* znR$z;!L$s7uy@{OT~nG#B!NRraT8(X##Ho!0r_o@gg0CA-9H^;-uE&?$2$nHv_00o z%cbuUc-tCx$Uh&EZ4Nf4Zgqv)Y6>usG3>GeQnxx_Z6+PcbX-+ysbt1hQ`K1LDpOE? zrAhIZhSN9yVIAOa22gn577tbc&i3|3V8NWy&!tw##`}9*x}gtI^h1DzZRA>UuaJG) zaZ7j)dq!O}{?#8Y7~7i6fHh4{`pL?>-18|p!S75Y#^DM>-S3)vuZG+Q7l@ek zQP~#cBpWgg#mApc_sPYjpw8odQuRokmTkzcNl`^CcKB7e&;zViV;{Y{o^Y$%7i0m# z62%#1Lq!RC?}lK>%mp}T!3Xv;L*0v*>USLm``N%>w>@fwC+#T&Tx2bN4w(20JB}oU zuSa6v^kXi0xPs?pbaOHnyiqq6By1EZY9OZ^^QA>{q-Hsd&m`pbQ%8121aWG-F5xf zlZ%;B{;C>X19|`^_?dVyCq>n+41w7|!tUS!{9rHlbhX=SZO5CQ^;!Du_E7*`GiR^Q w)2!4MKjfSAeNo!9>IaV6aUZ*?W>} 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/values-night/themes.xml b/Android_App/app/src/main/res/values-night/themes.xml new file mode 100644 index 000000000..54202f550 --- /dev/null +++ b/Android_App/app/src/main/res/values-night/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/values/colors.xml b/Android_App/app/src/main/res/values/colors.xml new file mode 100644 index 000000000..f8c6127d3 --- /dev/null +++ b/Android_App/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/Android_App/app/src/main/res/values/strings.xml b/Android_App/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..70f8fa474 --- /dev/null +++ b/Android_App/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Labrador + diff --git a/Android_App/app/src/main/res/values/themes.xml b/Android_App/app/src/main/res/values/themes.xml new file mode 100644 index 000000000..503477bfe --- /dev/null +++ b/Android_App/app/src/main/res/values/themes.xml @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/xml/backup_rules.xml b/Android_App/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 000000000..4df925582 --- /dev/null +++ b/Android_App/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/xml/data_extraction_rules.xml b/Android_App/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 000000000..9ee9997b0 --- /dev/null +++ b/Android_App/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/xml/device_filter.xml b/Android_App/app/src/main/res/xml/device_filter.xml new file mode 100644 index 000000000..85724f81f --- /dev/null +++ b/Android_App/app/src/main/res/xml/device_filter.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/Android_App/build.gradle.kts b/Android_App/build.gradle.kts new file mode 100644 index 000000000..327342f6c --- /dev/null +++ b/Android_App/build.gradle.kts @@ -0,0 +1,4 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false +} diff --git a/Android_App/gradle.properties b/Android_App/gradle.properties new file mode 100644 index 000000000..534063aa9 --- /dev/null +++ b/Android_App/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. For more details, visit +# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true diff --git a/Android_App/gradle/libs.versions.toml b/Android_App/gradle/libs.versions.toml new file mode 100644 index 000000000..485e997bc --- /dev/null +++ b/Android_App/gradle/libs.versions.toml @@ -0,0 +1,20 @@ +[versions] +agp = "9.0.0" +junit = "4.13.2" +junitVersion = "1.3.0" +espressoCore = "3.7.0" +appcompat = "1.7.1" +material = "1.13.0" +constraintlayout = "2.2.1" + +[libraries] +junit = { group = "junit", name = "junit", version.ref = "junit" } +ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } +constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" } + +[plugins] +android-application = { id = "com.android.application", version.ref = "agp" } + diff --git a/Android_App/gradle/wrapper/gradle-wrapper.jar b/Android_App/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..8bdaf60c75ab801e22807dde59e12a8735a34077 GIT binary patch literal 45457 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 c82=K%QXLKFx%@O{wJjEi6Y56o#$)Bpeg literal 0 HcmV?d00001 diff --git a/Android_App/gradle/wrapper/gradle-wrapper.properties b/Android_App/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..1e9b251d5 --- /dev/null +++ b/Android_App/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,9 @@ +#Tue Feb 03 14:11:51 PST 2026 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806 +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/Android_App/gradlew b/Android_App/gradlew new file mode 100755 index 000000000..ef07e0162 --- /dev/null +++ b/Android_App/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/Android_App/settings.gradle.kts b/Android_App/settings.gradle.kts new file mode 100644 index 000000000..0d0bb93aa --- /dev/null +++ b/Android_App/settings.gradle.kts @@ -0,0 +1,23 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "Labrador" +include(":app") From 97988beedcc4d3709926c24450a4666b0294550d Mon Sep 17 00:00:00 2001 From: brentfpage Date: Thu, 16 Apr 2026 23:25:58 -0700 Subject: [PATCH 02/21] CMakeLists for libdfuprog for imgui-android build --- libdfuprog/CMakeLists.txt | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 libdfuprog/CMakeLists.txt diff --git a/libdfuprog/CMakeLists.txt b/libdfuprog/CMakeLists.txt new file mode 100644 index 000000000..920d970d8 --- /dev/null +++ b/libdfuprog/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.16) +project(libdfuprog VERSION 1.0 LANGUAGES C CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_library(libdfuprog STATIC + config.h + dfu-programmer/src/arguments.c dfu-programmer/src/arguments.h + dfu-programmer/src/atmel.c dfu-programmer/src/atmel.h + dfu-programmer/src/commands.c dfu-programmer/src/commands.h + dfu-programmer/src/dfu.c dfu-programmer/src/dfu.h + dfu-programmer/src/dfu-bool.h + dfu-programmer/src/dfu-device.h + dfu-programmer/src/intel_hex.c dfu-programmer/src/intel_hex.h + dfu-programmer/src/stm32.c dfu-programmer/src/stm32.h + dfu-programmer/src/util.c dfu-programmer/src/util.h + libdfuprog.c libdfuprog.h +) + +target_include_directories(libdfuprog PRIVATE + dfu-programmer/src + ../Android_App/app/src/main/cpp/deps/librador/librador_deps/libusb +) + +target_compile_definitions(libdfuprog PRIVATE + HAVE_CONFIG_H + PLATFORM_ANDROID +) + +install(TARGETS libdfuprog + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) From c9519f596180601652f27f314fbe5532a73d2afd Mon Sep 17 00:00:00 2001 From: brentfpage Date: Thu, 16 Apr 2026 23:38:21 -0700 Subject: [PATCH 03/21] added submodules --- .gitmodules | 12 ++++++++++++ Android_App/app/src/main/cpp/deps/SDL | 1 + Android_App/app/src/main/cpp/deps/imgui | 1 + Android_App/app/src/main/cpp/deps/implot | 1 + 4 files changed, 15 insertions(+) create mode 160000 Android_App/app/src/main/cpp/deps/SDL create mode 160000 Android_App/app/src/main/cpp/deps/imgui create mode 160000 Android_App/app/src/main/cpp/deps/implot diff --git a/.gitmodules b/.gitmodules index 75de64e96..9807e5983 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,15 @@ [submodule "libdfuprog/dfu-programmer"] path = libdfuprog/dfu-programmer url = https://github.com/dfu-programmer/dfu-programmer +[submodule "Android_App/app/src/main/cpp/deps/implot"] + path = Android_App/app/src/main/cpp/deps/implot + url = https://github.com/brentfpage/implot.git + branch = for_labrador_android_app +[submodule "Android_App/app/src/main/cpp/deps/imgui"] + path = Android_App/app/src/main/cpp/deps/imgui + url = https://github.com/brentfpage/imgui.git + branch = for_labrador_android_app +[submodule "Android_App/app/src/main/cpp/deps/SDL"] + path = Android_App/app/src/main/cpp/deps/SDL + url = https://github.com/brentfpage/SDL.git + branch = for_labrador_app diff --git a/Android_App/app/src/main/cpp/deps/SDL b/Android_App/app/src/main/cpp/deps/SDL new file mode 160000 index 000000000..1726b34de --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/SDL @@ -0,0 +1 @@ +Subproject commit 1726b34deaa73d2952cf74801f23337ac9da7317 diff --git a/Android_App/app/src/main/cpp/deps/imgui b/Android_App/app/src/main/cpp/deps/imgui new file mode 160000 index 000000000..f1a3d6826 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/imgui @@ -0,0 +1 @@ +Subproject commit f1a3d68266807d597cc35a17a628a7952d7ac579 diff --git a/Android_App/app/src/main/cpp/deps/implot b/Android_App/app/src/main/cpp/deps/implot new file mode 160000 index 000000000..c506551c5 --- /dev/null +++ b/Android_App/app/src/main/cpp/deps/implot @@ -0,0 +1 @@ +Subproject commit c506551c58cfabf4c7d593c4c980575be8f89deb From ad7a009e1e2f9024e7be5ac3b032de3f3b6f94b8 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Thu, 16 Apr 2026 23:54:02 -0700 Subject: [PATCH 04/21] added PLATFORM_ANDROID guards to librador - usbcallhandler.cpp --- .../src/main/cpp/deps/librador/usbcallhandler.cpp | 13 ++++++++++--- .../app/src/main/cpp/deps/librador/usbcallhandler.h | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp index 4e1a07a4c..8094d1ed2 100644 --- a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp @@ -4,13 +4,14 @@ #include #include "logging_internal.h" #include "uartstyledecoder.h" +#include +#include +#ifdef PLATFORM_ANDROID #include #include - -#include -#include #include "SDL_android.h" +#endif void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){ //Thread mutex?? @@ -173,6 +174,7 @@ usbCallHandler::~usbCallHandler(){ LIBRADOR_LOG(LOG_DEBUG, "librador USB call handler deleted\n"); } +#ifdef PLATFORM_ANDROID void usbCallHandler::set_bootloader_mode_allowed(bool allowed) { JNIEnv *env = (JNIEnv *) SDL_GetAndroidJNIEnv(); jobject MainActivityObject = (jobject) SDL_GetAndroidActivity(); @@ -194,6 +196,7 @@ void usbCallHandler::initiateFirmwareFlash() ctx = nullptr; handle= nullptr; } +#endif //Initialise libusb int usbCallHandler::init_libusb(){ @@ -753,6 +756,7 @@ bool usbCallHandler::isoThreadIsActive(){ return tempReturn; } +#ifdef PLATFORM_ANDROID int usbCallHandler::flashFirmware(int file_descriptor){ libusb_device *device_ptr; @@ -830,6 +834,7 @@ int usbCallHandler::flashFirmware(int file_descriptor){ starting_after_flash = true; return 0; } +#endif void usbCallHandler::dfu_launch() { LOGI("\n\n\nDFU LAUNCH.\n\n\n"); @@ -846,6 +851,7 @@ void usbCallHandler::dfu_launch() { handle= nullptr; } +#ifdef PLATFORM_ANDROID void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int file_descriptor, bool bootloader_mode){ if(is_plugged_in) { if(bootloader_mode) { @@ -933,3 +939,4 @@ void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int fi } } } +#endif diff --git a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.h b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.h index 3c2f4d9a2..9f0583d41 100644 --- a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.h +++ b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.h @@ -11,9 +11,12 @@ extern "C" #include "i2cdecoder.h" #include #include -#include #include +#ifdef PLATFORM_ANDROID +#include +#endif + #define NUM_ISO_ENDPOINTS (1) #define NUM_FUTURE_CTX (4) #define ISO_PACKET_SIZE (750) From c40295243acf522cc423d18a71613400846f2b40 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Thu, 16 Apr 2026 23:55:28 -0700 Subject: [PATCH 05/21] rename --- Android_App/app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Android_App/app/build.gradle.kts b/Android_App/app/build.gradle.kts index 324964038..be964e94c 100644 --- a/Android_App/app/build.gradle.kts +++ b/Android_App/app/build.gradle.kts @@ -3,13 +3,13 @@ plugins { } android { - namespace = "org.labrador.imgui.android" + namespace = "com.EspoTek.Labrador" compileSdk { version = release(36) } defaultConfig { - applicationId = "org.labrador.imgui.android" + applicationId = "com.EspoTek.Labrador" minSdk = 25 targetSdk = 36 versionCode = 1 From 4a90698ae716f69a6cb599070db382a5465ffc51 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 00:52:49 -0700 Subject: [PATCH 06/21] name updates --- Android_App/app/src/main/cpp/CMakeLists.txt | 4 +++- Android_App/app/src/main/cpp/deps/librador/librador.cpp | 4 ++-- Android_App/app/src/main/cpp/deps/librador/librador.h | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Android_App/app/src/main/cpp/CMakeLists.txt b/Android_App/app/src/main/cpp/CMakeLists.txt index 752225719..d51a73a17 100644 --- a/Android_App/app/src/main/cpp/CMakeLists.txt +++ b/Android_App/app/src/main/cpp/CMakeLists.txt @@ -52,7 +52,9 @@ target_include_directories(labrador-imgui-android PRIVATE deps/SDL/include/build_config ) -target_compile_definitions(labrador-imgui-android PRIVATE IMGUI_IMPL_OPENGL_ES3 PLATFORM_ANDROID) +target_compile_definitions(labrador-imgui-android PRIVATE + IMGUI_IMPL_OPENGL_ES3 + PLATFORM_ANDROID) add_library(libusb SHARED IMPORTED) set_target_properties(libusb PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_LIST_DIR}/deps/librador/librador_deps/libusb/android/${ANDROID_ABI}/libusb1.0.so) diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.cpp b/Android_App/app/src/main/cpp/deps/librador/librador.cpp index 1964dc57e..7d0ed5723 100644 --- a/Android_App/app/src/main/cpp/deps/librador/librador.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/librador.cpp @@ -9,7 +9,7 @@ #include #include -JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *env, jobject thisobject, jboolean is_plugged_in, jint file_descriptor, jboolean bootloader_mode) +JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *env, jobject thisobject, jboolean is_plugged_in, jint file_descriptor, jboolean bootloader_mode) { if(!internal_librador_object) { @@ -19,7 +19,7 @@ JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeRespon return; } -JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeInitiateFirmwareFlash(JNIEnv *env, jobject thisobject) +JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeInitiateFirmwareFlash(JNIEnv *env, jobject thisobject) { internal_librador_object->usb_driver->initiateFirmwareFlash(); return; diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.h b/Android_App/app/src/main/cpp/deps/librador/librador.h index d5cf7ca0f..fccde3845 100644 --- a/Android_App/app/src/main/cpp/deps/librador/librador.h +++ b/Android_App/app/src/main/cpp/deps/librador/librador.h @@ -13,8 +13,8 @@ #ifdef __cplusplus extern "C" { #endif -JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *, jobject, jboolean, jint, jboolean); -JNIEXPORT void JNICALL Java_org_labrador_imgui_android_MainActivity_nativeInitiateFirmwareFlash(JNIEnv *, jobject); +JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *, jobject, jboolean, jint, jboolean); +JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeInitiateFirmwareFlash(JNIEnv *, jobject); #ifdef __cplusplus } #endif From be621f8e59273b1bd5288f941b967319757b25af Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 10:20:48 -0700 Subject: [PATCH 07/21] make all logging macros LIBRADOR_LOG --- .../src/main/cpp/deps/librador/i2cdecoder.cpp | 14 +-- .../app/src/main/cpp/deps/librador/logging.h | 12 +++ .../main/cpp/deps/librador/logging_internal.h | 10 ++- .../src/main/cpp/deps/librador/o1buffer.cpp | 4 +- .../cpp/deps/librador/uartstyledecoder.cpp | 4 +- .../main/cpp/deps/librador/usbcallhandler.cpp | 90 +++++++++---------- Android_App/app/src/main/cpp/main.cpp | 10 +-- 7 files changed, 81 insertions(+), 63 deletions(-) diff --git a/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp b/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp index d9f362699..0d9dac433 100644 --- a/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/i2cdecoder.cpp @@ -11,7 +11,7 @@ i2cDecoder::i2cDecoder(o1buffer* sda_in, o1buffer* scl_in) : void i2cDecoder::reset() { - LOGI("Resetting I2C"); + LIBRADOR_LOG(LOG_DEBUG, "Resetting I2C"); if (sda->mostRecentAddress != scl->mostRecentAddress) { @@ -76,9 +76,9 @@ void i2cDecoder::runStateMachine() if ((sdaEdge == edge::rising) && (sclEdge == edge::falling)) // INVALID STATE TRANSITION { state = transmissionState::unknown; - LOGW("Dumping I2C state and aborting..."); + LIBRADOR_LOG(LOG_WARNING, "Dumping I2C state and aborting..."); for (int i=31; i>=0; i--) - LOGI("%02x\t%02x", sda->get(serialPtr_bit/8 - i) & 0xFF, scl->get(serialPtr_bit/8 - i) & 0xFF); + LIBRADOR_LOG(LOG_DEBUG, "%02x\t%02x", sda->get(serialPtr_bit/8 - i) & 0xFF, scl->get(serialPtr_bit/8 - i) & 0xFF); throw std::runtime_error("unknown i2c transmission state"); return; } @@ -134,7 +134,7 @@ void i2cDecoder::decodeAddress(edge sdaEdge, edge sclEdge) if (currentBitIndex == addressBitStreamLength) { - LOGI("Finished Address Decode"); + LIBRADOR_LOG(LOG_DEBUG, "Finished Address Decode"); if (currentBitStream & 0b0000000000000010) m_serialBuffer.insert("READ: "); else @@ -167,7 +167,7 @@ void i2cDecoder::decodeData(edge sdaEdge, edge sclEdge) if (currentBitIndex == dataBitStreamLength) { - LOGI("Finished Data byte Decode"); + LIBRADOR_LOG(LOG_DEBUG, "Finished Data byte Decode"); m_serialBuffer.insert_hex((uint8_t)((currentBitStream & 0b0000000111111110) >> 1)); m_serialBuffer.insert(' '); @@ -188,14 +188,14 @@ void i2cDecoder::startCondition() currentBitIndex = 0; currentBitStream = 0x0000; state = transmissionState::address; - LOGI("I2C START"); + LIBRADOR_LOG(LOG_DEBUG, "I2C START"); } void i2cDecoder::stopCondition() { state = transmissionState::idle; m_serialBuffer.insert('\n'); - LOGI("I2C STOP"); + LIBRADOR_LOG(LOG_DEBUG, "I2C STOP"); } char * i2cDecoder::getString() diff --git a/Android_App/app/src/main/cpp/deps/librador/logging.h b/Android_App/app/src/main/cpp/deps/librador/logging.h index 972cfc170..b028bb0e6 100644 --- a/Android_App/app/src/main/cpp/deps/librador/logging.h +++ b/Android_App/app/src/main/cpp/deps/librador/logging.h @@ -1,11 +1,23 @@ #ifndef LOGGING_H #define LOGGING_H +#ifdef PLATFORM_ANDROID +// sync to android_LogPriority +enum { + LOG_NONE = 0, + LOG_ERROR = 6, + LOG_WARNING = 5, + LOG_DEBUG = 3, +}; +#else enum { LOG_NONE = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, }; +#endif //PLATFORM_ANDROID + + #endif // LOGGING_H diff --git a/Android_App/app/src/main/cpp/deps/librador/logging_internal.h b/Android_App/app/src/main/cpp/deps/librador/logging_internal.h index 3e757b709..bd7426199 100644 --- a/Android_App/app/src/main/cpp/deps/librador/logging_internal.h +++ b/Android_App/app/src/main/cpp/deps/librador/logging_internal.h @@ -2,10 +2,14 @@ #define LOGGING_INTERNAL_H #include "logging.h" +//TODO : maybe handle the logger switch for android by setting _librador_global_logger in librador.cpp instead? +#ifdef PLATFORM_ANDROID + #include #define LOG_TAG "librador" -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) +#define LIBRADOR_LOG(level, ...) __android_log_print(level, LOG_TAG, __VA_ARGS__) + +#else #ifdef LIBRADOR_ENABLE_LOGGING #define LIBRADOR_LOG(level, ...) \ @@ -21,6 +25,8 @@ } while (0) #endif // LIBRADOR_DISABLE_LOGGING +#endif // PLATFORM_ANDROID + void librador_global_logger(const int level, const char* format, ...); #endif // LOGGING_INTERNAL_H diff --git a/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp b/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp index ffa99aa5d..7f0c188b5 100644 --- a/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/o1buffer.cpp @@ -342,8 +342,8 @@ void o1buffer::resetTrigger(double scope_gain, bool twelve_bit_multimeter) m_triggerSensitivity = static_cast((1 + abs(actual_trigger_level * kTriggerSensitivityMultiplier )) * TOP / 128.); buffer_related_settings_mutex.unlock(); - LOGI("Trigger Level: %d", m_triggerLevelADC); - LOGI("Trigger sensitivity: %d", m_triggerSensitivity); + LIBRADOR_LOG(LOG_DEBUG, "Trigger Level: %d", m_triggerLevelADC); + LIBRADOR_LOG(LOG_DEBUG, "Trigger sensitivity: %d", m_triggerSensitivity); } diff --git a/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp b/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp index 3a304507c..959e083c9 100644 --- a/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/uartstyledecoder.cpp @@ -53,7 +53,7 @@ void uartStyleDecoder::UartDecode() //Not a single stop bit, or idle bit, in the whole stream. Wire must be disconnected. if (allZeroes) { - LOGW("Wire Disconnect detected!"); + LIBRADOR_LOG(LOG_WARNING, "Wire Disconnect detected!"); } } @@ -160,7 +160,7 @@ bool uartStyleDecoder::jitterCompensationProcedure(bool current_bit) //Can't be bothered dealing with the corner case where the serial pointer is at the very start of the buffer. //Just return and try again next time. int left_coord = serialPtr_bit - (8*m_parent->m_samples_per_second)/ m_settings.baudRate; - LOGI("left_coord = %d", left_coord); + LIBRADOR_LOG(LOG_DEBUG, "left_coord = %d", left_coord); if (left_coord < 0) return true; //Don't want to read out of bounds!! diff --git a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp index 8094d1ed2..e297e2775 100644 --- a/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/usbcallhandler.cpp @@ -57,14 +57,14 @@ void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){ if(!usb_driver->is_iso_thread_shutdown_requested()){ int error = libusb_submit_transfer(transfer); if(error){ - LOGW("Error re-arming the endpoint!\n"); + LIBRADOR_LOG(LOG_WARNING, "Error re-arming the endpoint!\n"); usb_driver->begin_iso_thread_shutdown(); usb_driver->decrement_remaining_transfers(); - LOGW("Transfer not being rearmed! %d armed transfers remaining\n", usb_driver->iso_thread_shutdown_remaining_transfers); + LIBRADOR_LOG(LOG_WARNING, "Transfer not being rearmed! %d armed transfers remaining\n", usb_driver->iso_thread_shutdown_remaining_transfers); } } else { usb_driver->decrement_remaining_transfers(); - LOGW("Transfer not being rearmed! %d armed transfers remaining\n", usb_driver->iso_thread_shutdown_remaining_transfers); + LIBRADOR_LOG(LOG_WARNING, "Transfer not being rearmed! %d armed transfers remaining\n", usb_driver->iso_thread_shutdown_remaining_transfers); } return; } @@ -102,7 +102,7 @@ bool usbCallHandler::safe_to_exit_thread(){ // it makes sense to call this iso_polling_function because we only use libusb's asynchronous API for isochronous transfers void usbCallHandler::iso_polling_function(libusb_context *ctx){ - LOGI("iso_polling_function thread spawned\n"); + LIBRADOR_LOG(LOG_DEBUG, "iso_polling_function thread spawned\n"); struct timeval tv; tv.tv_sec = 1; tv.tv_usec = 0;//ISO_PACKETS_PER_CTX*4000; @@ -115,7 +115,7 @@ void usbCallHandler::iso_polling_function(libusb_context *ctx){ get_set_iso_thread_active_mutex.lock(); iso_thread_active = false; get_set_iso_thread_active_mutex.unlock(); - LOGI("iso_polling_function thread finished\n"); + LIBRADOR_LOG(LOG_DEBUG, "iso_polling_function thread finished\n"); } usbCallHandler::usbCallHandler(unsigned short VID_in, unsigned short PID_in) @@ -181,7 +181,7 @@ void usbCallHandler::set_bootloader_mode_allowed(bool allowed) { jclass MainActivity(env->GetObjectClass(MainActivityObject)); jfieldID bootloader_mode_allowedID = env->GetFieldID(MainActivity, "bootloader_mode_allowed", "Z"); env->SetBooleanField(MainActivityObject, bootloader_mode_allowedID, allowed); - LOGI("bootloader_mode_allowed set"); + LIBRADOR_LOG(LOG_DEBUG, "bootloader_mode_allowed set"); } // call sequence: usbcallhandler.cpp(requestFirmwareFlash) -> MainActivity.java -> librador -> here, all just to get a dialog window before reset_device (below) triggers a usb permission request @@ -201,38 +201,38 @@ void usbCallHandler::initiateFirmwareFlash() //Initialise libusb int usbCallHandler::init_libusb(){ if(ctx){ - LOGI("There is already a libusb context!\n"); + LIBRADOR_LOG(LOG_DEBUG, "There is already a libusb context!\n"); return 1; - } else LOGI("libusb context is null\n"); + } else LIBRADOR_LOG(LOG_DEBUG, "libusb context is null\n"); struct libusb_init_option libusb_options[2] = { {.option = LIBUSB_OPTION_NO_DEVICE_DISCOVERY}, {.option = LIBUSB_OPTION_LOG_LEVEL, .value = {.ival = 3}} }; int error = libusb_init_context(&ctx, libusb_options, 2); if(error){ - LOGW("libusb_init FAILED\n"); + LIBRADOR_LOG(LOG_WARNING, "libusb_init FAILED\n"); return -1; } else { - LOGI("Libusb context initialised\n"); + LIBRADOR_LOG(LOG_DEBUG, "Libusb context initialised\n"); return 0; } } int usbCallHandler::setup_usb_control(int file_descriptor){ - LOGI("usbCallHandler::setup_usb_control()\n"); + LIBRADOR_LOG(LOG_DEBUG, "usbCallHandler::setup_usb_control()\n"); //Get a handle on the Labrador device libusb_wrap_sys_device(ctx, file_descriptor, &handle); if(!handle){ - LOGI("DEVICE NOT FOUND\n"); + LIBRADOR_LOG(LOG_DEBUG, "DEVICE NOT FOUND\n"); return -2; } - LOGI("Device found!!\n"); + LIBRADOR_LOG(LOG_DEBUG, "Device found!!\n"); if(libusb_kernel_driver_active(handle, 0)) { - LOGI("KERNEL DRIVER ACTIVE"); + LIBRADOR_LOG(LOG_DEBUG, "KERNEL DRIVER ACTIVE"); } else { - LOGI("KERNEL DRIVER INACTIVE"); + LIBRADOR_LOG(LOG_DEBUG, "KERNEL DRIVER INACTIVE"); } if(libusb_kernel_driver_active(handle, 0)){ libusb_detach_kernel_driver(handle, 0); @@ -241,29 +241,29 @@ int usbCallHandler::setup_usb_control(int file_descriptor){ //Claim the interface int error = libusb_claim_interface(handle, 0); if(error){ - LOGW("libusb_claim_interface FAILED\n"); + LIBRADOR_LOG(LOG_WARNING, "libusb_claim_interface FAILED\n"); libusb_close(handle); handle = nullptr; return -3; - } else LOGI("Interface claimed!\n"); + } else LIBRADOR_LOG(LOG_DEBUG, "Interface claimed!\n"); return 0; } // should only be called if iso_polling_thread is not active. This means either the thread has never been set up OR it was previously set up but has exited iso_polling_function. int usbCallHandler::setup_usb_iso(){ - LOGI("usbCallHandler::setup_usb_iso()\n"); + LIBRADOR_LOG(LOG_DEBUG, "usbCallHandler::setup_usb_iso()\n"); if(iso_polling_thread) { - LOGI("iso polling thead already exists"); + LIBRADOR_LOG(LOG_DEBUG, "iso polling thead already exists"); return -1; } else { - LOGI("creating iso polling thread"); + LIBRADOR_LOG(LOG_DEBUG, "creating iso polling thread"); alloc_iso_transfers(); int error = submit_iso_transfers(); if(error) { return error; - LOGW("setup_usb_iso failed\n"); + LIBRADOR_LOG(LOG_WARNING, "setup_usb_iso failed\n"); } iso_polling_thread = new std::thread(&usbCallHandler::iso_polling_function, this, ctx); iso_thread_active = true; @@ -298,7 +298,7 @@ int usbCallHandler::send_control_transfer(uint8_t RequestType, uint8_t Request, unsigned char *controlBuffer; if(!connected){ - LOGI("Control packet requested before device has connected!\n"); + LIBRADOR_LOG(LOG_DEBUG, "Control packet requested before device has connected!\n"); return -1; } @@ -309,7 +309,7 @@ int usbCallHandler::send_control_transfer(uint8_t RequestType, uint8_t Request, int error = libusb_control_transfer(handle, RequestType, Request, Value, Index, controlBuffer, Length, 4000); if(error<0){ - LOGW("send_control_transfer FAILED with error %s", libusb_error_name(error)); + LIBRADOR_LOG(LOG_WARNING, "send_control_transfer FAILED with error %s", libusb_error_name(error)); connected = false; return error - 100; } @@ -442,7 +442,7 @@ std::vector * usbCallHandler::getMany_singleBit(int channel, int numToGe } catch(...) { - LOGI("Resetting I2C"); + LIBRADOR_LOG(LOG_DEBUG, "Resetting I2C"); m_i2c_decoder->reset(); } break; @@ -644,7 +644,7 @@ int usbCallHandler::set_digital_state(uint8_t digState){ } int usbCallHandler::reset_device(bool goToBootloader){ - LOGI("resetting device: unimportant error LIBUSB_ERROR_NO_DEVICE for send_control_transfer expected"); // only if goToBootloader? + LIBRADOR_LOG(LOG_DEBUG, "resetting device: unimportant error LIBUSB_ERROR_NO_DEVICE for send_control_transfer expected"); // only if goToBootloader? send_control_transfer_with_error_checks(0x40, 0xa7, (goToBootloader ? 1 : 0), 0, 0, nullptr); return 0; } @@ -782,7 +782,7 @@ int usbCallHandler::flashFirmware(int file_descriptor){ strcpy(firmware_copy_filepath, external_filepath); strcat(firmware_copy_filepath, "/"); strcat(firmware_copy_filepath, firmware_filename); - LOGI("firmware copy path: %s", firmware_copy_filepath); + LIBRADOR_LOG(LOG_DEBUG, "firmware copy path: %s", firmware_copy_filepath); AAsset* asset = AAssetManager_open(mgr, apk_firmware_filepath, AASSET_MODE_STREAMING); char buf[2048]; @@ -793,20 +793,20 @@ int usbCallHandler::flashFirmware(int file_descriptor){ fclose(out); AAsset_close(asset); - LOGI("FLASHING %s", firmware_copy_filepath); + LIBRADOR_LOG(LOG_DEBUG, "FLASHING %s", firmware_copy_filepath); //Set up interface to dfuprog int exit_code; char command[256]; //Run stage 1 - LOGI("\n\nFlashing Firmware, stage 1.\n\n"); + LIBRADOR_LOG(LOG_DEBUG, "\n\nFlashing Firmware, stage 1.\n\n"); snprintf(command, sizeof command, "dfu-programmer atxmega32a4u erase --force --debug 300"); exit_code = dfuprog_virtual_cmd(command, device_ptr, handle, ctx, 0); if (exit_code) { - LOGW("ERROR ERASING FIRMWARE."); + LIBRADOR_LOG(LOG_WARNING, "ERROR ERASING FIRMWARE."); } else { - LOGI("ERASED FIRMWARE."); + LIBRADOR_LOG(LOG_DEBUG, "ERASED FIRMWARE."); } ctx = nullptr; handle= nullptr; @@ -815,11 +815,11 @@ int usbCallHandler::flashFirmware(int file_descriptor){ error = setup_usb_control(file_descriptor); //Run stage 2 - LOGI("\n\nFlashing Firmware, stage 2.\n\n"); + LIBRADOR_LOG(LOG_DEBUG, "\n\nFlashing Firmware, stage 2.\n\n"); snprintf(command, sizeof command, "dfu-programmer atxmega32a4u flash %s --debug 300", firmware_copy_filepath); exit_code = dfuprog_virtual_cmd(command, device_ptr, handle, ctx, 0); if (exit_code) { - LOGW("\n\n\nERROR WRITING NEW FIRMWARE TO DEVICE.\n\n\n"); + LIBRADOR_LOG(LOG_WARNING, "\n\n\nERROR WRITING NEW FIRMWARE TO DEVICE.\n\n\n"); //return exit_code+200; } ctx = nullptr; @@ -829,7 +829,7 @@ int usbCallHandler::flashFirmware(int file_descriptor){ error = setup_usb_control(file_descriptor); //Run stage 3 - LOGI("\n\nFlashing Firmware, stage 3.\n\n"); + LIBRADOR_LOG(LOG_DEBUG, "\n\nFlashing Firmware, stage 3.\n\n"); dfu_launch(); starting_after_flash = true; return 0; @@ -837,14 +837,14 @@ int usbCallHandler::flashFirmware(int file_descriptor){ #endif void usbCallHandler::dfu_launch() { - LOGI("\n\n\nDFU LAUNCH.\n\n\n"); + LIBRADOR_LOG(LOG_DEBUG, "\n\n\nDFU LAUNCH.\n\n\n"); int exit_code; char command[256]; libusb_device *device_ptr; snprintf(command, sizeof command, "dfu-programmer atxmega32a4u launch"); exit_code = dfuprog_virtual_cmd(command, device_ptr, handle, ctx, 0); if (exit_code) { - LOGW("\n\n\n DFU LAUNCH ERROR\n\n\n"); + LIBRADOR_LOG(LOG_WARNING, "\n\n\n DFU LAUNCH ERROR\n\n\n"); //return exit_code+300; } ctx = nullptr; @@ -855,9 +855,9 @@ void usbCallHandler::dfu_launch() { void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int file_descriptor, bool bootloader_mode){ if(is_plugged_in) { if(bootloader_mode) { - LOGI("found in bootloader mode"); + LIBRADOR_LOG(LOG_DEBUG, "found in bootloader mode"); if(starting_after_flash) { - LOGI("startup after flash"); + LIBRADOR_LOG(LOG_DEBUG, "startup after flash"); starting_after_flash = false; init_libusb(); int error = setup_usb_control(file_descriptor); @@ -871,7 +871,7 @@ void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int fi env->CallVoidMethod(MainActivityObject,confirmFirmwareFlashID); } else { int flashRet = flashFirmware(file_descriptor); - LOGI("flashRet: %d", flashRet); + LIBRADOR_LOG(LOG_DEBUG, "flashRet: %d", flashRet); } } else { if(connected) { @@ -882,15 +882,15 @@ void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int fi if(control_setup_success==0) { connected = true; uint16_t firmver = get_firmware_version(); - LOGI("BOARD IS RUNNING FIRMWARE VERSION 0x%04hx", firmver); - LOGI("EXPECTING FIRMWARE VERSION 0x%04hx", EXPECTED_FIRMWARE_VERSION); + LIBRADOR_LOG(LOG_DEBUG, "BOARD IS RUNNING FIRMWARE VERSION 0x%04hx", firmver); + LIBRADOR_LOG(LOG_DEBUG, "EXPECTING FIRMWARE VERSION 0x%04hx", EXPECTED_FIRMWARE_VERSION); uint8_t variant = get_firmware_variant(); - LOGI("FIRMWARE VARIANT = 0x%02hx", variant); - LOGI("EXPECTED VARIANT = 0x%02hx", DEFINED_EXPECTED_VARIANT); + LIBRADOR_LOG(LOG_DEBUG, "FIRMWARE VARIANT = 0x%02hx", variant); + LIBRADOR_LOG(LOG_DEBUG, "EXPECTED VARIANT = 0x%02hx", DEFINED_EXPECTED_VARIANT); if((firmver != EXPECTED_FIRMWARE_VERSION) || (variant != DEFINED_EXPECTED_VARIANT)){ - LOGI("Unexpected Firmware!!"); + LIBRADOR_LOG(LOG_DEBUG, "Unexpected Firmware!!"); JNIEnv *env = (JNIEnv *) SDL_GetAndroidJNIEnv(); jobject MainActivityObject = (jobject) SDL_GetAndroidActivity(); @@ -932,10 +932,10 @@ void usbCallHandler::respondToStartupOrUsbStateChange(bool is_plugged_in, int fi } if(handle){ libusb_release_interface(handle, 0); - LOGI("Interface released\n"); + LIBRADOR_LOG(LOG_DEBUG, "Interface released\n"); libusb_close(handle); handle = nullptr; - LOGI("Device Closed\n"); + LIBRADOR_LOG(LOG_DEBUG, "Device Closed\n"); } } } diff --git a/Android_App/app/src/main/cpp/main.cpp b/Android_App/app/src/main/cpp/main.cpp index b749d9179..b86621f82 100644 --- a/Android_App/app/src/main/cpp/main.cpp +++ b/Android_App/app/src/main/cpp/main.cpp @@ -98,7 +98,7 @@ int main(int, char**) jclass MainActivity(env->GetObjectClass(MainActivityObject)); jmethodID getDpiID = env->GetMethodID(MainActivity, "getDpi", "()F"); float dpi = (float) env->CallFloatMethod(MainActivityObject,getDpiID); - LOGI("dpi: %.2f", dpi); + LIBRADOR_LOG(LOG_DEBUG, "dpi: %.2f", dpi); SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY; SDL_Window* window = SDL_CreateWindow("main window", (int)bounds.w, (int)bounds.h, window_flags); if (window == nullptr) @@ -201,10 +201,10 @@ int main(int, char**) int sh = (int) env->CallIntMethod(MainActivityObject,getScreenHeight); int sbh = (int) env->CallIntMethod(MainActivityObject,getStatusBarHeightID); int nbh = (int) env->CallIntMethod(MainActivityObject,getNavigationBarHeightID); - LOGI("screen width: %d", sw); - LOGI("screen height: %d", sh); - LOGI("status bar beight: %d", sbh); - LOGI("navigation bar beight: %d", nbh); + LIBRADOR_LOG(LOG_DEBUG, "screen width: %d", sw); + LIBRADOR_LOG(LOG_DEBUG, "screen height: %d", sh); + LIBRADOR_LOG(LOG_DEBUG, "status bar beight: %d", sbh); + LIBRADOR_LOG(LOG_DEBUG, "navigation bar beight: %d", nbh); // Our state bool show_mainwindow = true; From e8d81f5e7fc4e3c9e95bc703c0b27c386b42c00f Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 10:24:12 -0700 Subject: [PATCH 08/21] more #ifdef PLATFORM_ANDROID wrapping --- Android_App/app/src/main/cpp/deps/librador/librador.cpp | 2 ++ Android_App/app/src/main/cpp/deps/librador/librador.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.cpp b/Android_App/app/src/main/cpp/deps/librador/librador.cpp index 7d0ed5723..4d511eed0 100644 --- a/Android_App/app/src/main/cpp/deps/librador/librador.cpp +++ b/Android_App/app/src/main/cpp/deps/librador/librador.cpp @@ -9,6 +9,7 @@ #include #include +#ifdef PLATFORM_ANDROID JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeRespondToStartupOrUsbStateChange(JNIEnv *env, jobject thisobject, jboolean is_plugged_in, jint file_descriptor, jboolean bootloader_mode) { if(!internal_librador_object) @@ -24,6 +25,7 @@ JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeInitiateFirm internal_librador_object->usb_driver->initiateFirmwareFlash(); return; } +#endif Librador::Librador() { diff --git a/Android_App/app/src/main/cpp/deps/librador/librador.h b/Android_App/app/src/main/cpp/deps/librador/librador.h index fccde3845..27d8558d5 100644 --- a/Android_App/app/src/main/cpp/deps/librador/librador.h +++ b/Android_App/app/src/main/cpp/deps/librador/librador.h @@ -10,6 +10,7 @@ #include #include +#ifdef PLATFORM_ANDROID #ifdef __cplusplus extern "C" { #endif @@ -18,6 +19,7 @@ JNIEXPORT void JNICALL Java_com_EspoTek_Labrador_MainActivity_nativeInitiateFirm #ifdef __cplusplus } #endif +#endif // PLATFORM_ANDROID LIBRADORSHARED_EXPORT int librador_init(); LIBRADORSHARED_EXPORT int librador_exit(); From 5fbf12d9fffd3a71ae9b64ddadc703be30105970 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 11:04:26 -0700 Subject: [PATCH 09/21] revised android.yml so that it builds the imgui app --- .github/workflows/android.yml | 40 ++++++++++------------------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 8232f2875..d68044d99 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -33,17 +33,14 @@ jobs: with: submodules: 'recursive' - - name: Install Qt - uses: jurplel/install-qt-action@v4 - with: - aqtversion: '==3.3.*' - version: '5.14.2' - host: 'linux' - target: 'android' - arch: 'android' + - name: Install Java + uses: actions/setup-java@v5 + with: + distribution: 'jetbrains' + java-version: '25' - name: Install SDK - run: ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install 'platforms;android-31' 'build-tools;31.0.0' 'ndk;21.3.6528147' + run: ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install 'platforms;android-36' 'build-tools;36.1.0' 'ndk;28.2.13676358' # Secrets should be the base64 portion of the PEM format # (i.e. the stuff between the BEGIN/END lines): @@ -71,24 +68,16 @@ jobs: # be signed with debug keys. - name: Build Android package - working-directory: Desktop_Interface + working-directory: Android_App run: | - export ANDROID_NDK_ROOT="${ANDROID_SDK_ROOT}/ndk/21.3.6528147" APK_BASENAME="Labrador-$(git rev-parse --short HEAD)" if [ -e cert.cer ] && [ -e cert.p8 ]; then - qmake -config release - make -j$(nproc) - make INSTALL_ROOT=android-build install - JAVA_HOME=${JAVA_HOME_8_X64} androiddeployqt --input android-Labrador-deployment-settings.json --output android-build --aab --android-platform android-31 --verbose --gradle --release - ${ANDROID_SDK_ROOT}/build-tools/31.0.0/apksigner sign --in android-build/build/outputs/apk/release/android-build-release-unsigned.apk --out ${APK_BASENAME}-release-signed.apk --key cert.p8 --cert cert.cer --verbose + ./gradlew assembleRelease + ${ANDROID_SDK_ROOT}/build-tools/36.1.0/apksigner sign --in app/build/outputs/apk/release/app-release-unsigned.apk --out ${APK_BASENAME}-release-signed.apk --key cert.p8 --cert cert.cer --verbose else - qmake -config debug - make -j$(nproc) - make INSTALL_ROOT=android-build install - JAVA_HOME=${JAVA_HOME_8_X64} androiddeployqt --input android-Labrador-deployment-settings.json --output android-build --aab --android-platform android-31 --verbose --gradle - cp android-build/build/outputs/apk/debug/android-build-debug.apk ${APK_BASENAME}-debug.apk + ./gradlew assembleDebug + cp app/build/outputs/apk/debug/app-debug.apk ${APK_BASENAME}-debug.apk fi - cp android-build/build/outputs/bundle/release/android-build-release.aab ${APK_BASENAME}-release-unsigned.aab - name: Upload apk artifacts uses: actions/upload-artifact@v4 @@ -97,10 +86,3 @@ jobs: path: Desktop_Interface/Labrador*.apk compression-level: 0 if-no-files-found: error - - name: Upload aab artifacts - uses: actions/upload-artifact@v4 - with: - name: asset-aab - path: Desktop_Interface/Labrador*.aab - compression-level: 0 - if-no-files-found: error From cce37f31ad98aad4b9f04d7c9a9d74846a246832 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 11:18:49 -0700 Subject: [PATCH 10/21] android.yml indentation edit --- .github/workflows/android.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index d68044d99..574f0bc8c 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -33,11 +33,11 @@ jobs: with: submodules: 'recursive' - - name: Install Java - uses: actions/setup-java@v5 - with: - distribution: 'jetbrains' - java-version: '25' + - name: Install Java + uses: actions/setup-java@v5 + with: + distribution: 'jetbrains' + java-version: '25' - name: Install SDK run: ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install 'platforms;android-36' 'build-tools;36.1.0' 'ndk;28.2.13676358' From 31646f3e5e8e4bec9abe40dd6b6b4f7a0c0d74ff Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 11:25:22 -0700 Subject: [PATCH 11/21] android.yml apk directory fix? --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 574f0bc8c..98aa82426 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -83,6 +83,6 @@ jobs: uses: actions/upload-artifact@v4 with: name: asset-apk - path: Desktop_Interface/Labrador*.apk + path: Android_App/Labrador*.apk compression-level: 0 if-no-files-found: error From 38bed7c16e8e1efadd5fbce5a25e752fbb7212bf Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 16:50:41 -0700 Subject: [PATCH 12/21] new icon files --- .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 ++--- .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 ++--- .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 1890 bytes .../mipmap-hdpi/ic_launcher_background.webp | Bin 0 -> 172 bytes .../mipmap-hdpi/ic_launcher_foreground.webp | Bin 0 -> 2866 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 4082 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 1642 bytes .../mipmap-mdpi/ic_launcher_background.webp | Bin 0 -> 168 bytes .../mipmap-mdpi/ic_launcher_foreground.webp | Bin 0 -> 1422 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 2514 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 2712 bytes .../mipmap-xhdpi/ic_launcher_background.webp | Bin 0 -> 224 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 0 -> 4130 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 5702 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 4316 bytes .../mipmap-xxhdpi/ic_launcher_background.webp | Bin 0 -> 254 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 0 -> 6930 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 9268 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 5750 bytes .../ic_launcher_background.webp | Bin 0 -> 284 bytes .../ic_launcher_foreground.webp | Bin 0 -> 9452 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 12358 bytes 22 files changed, 4 insertions(+), 6 deletions(-) create mode 100644 Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_background.webp create mode 100644 Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp create mode 100644 Android_App/app/src/main/res/mipmap-mdpi/ic_launcher_background.webp create mode 100644 Android_App/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp create mode 100644 Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp create mode 100644 Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.webp create mode 100644 Android_App/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp diff --git a/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 6f3b755bf..4ae7d1237 100644 --- a/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 6f3b755bf..4ae7d1237 100644 --- a/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/Android_App/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -1,6 +1,5 @@ - - - + + \ No newline at end of file diff --git a/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher.webp index c209e78ecd372343283f4157dcfd918ec5165bb3..5174551460f30a2300fcd9c8162222598c5f253b 100644 GIT binary patch literal 1890 zcmV-o2c7s*Nk&Fm2LJ$9MM6+kP&iCY2LJ#sN5ByfO)zL1$&r$|^8dph@iz(){hxsF zJnTbNQcz8c58viM$4#eBSD67 z&wZV$XgP^LC4I@%uHdj zeXK7a$&p+dQm$=VwXO8I*7 zwB#TL8($g{Xrm%G|6Oov+g7d2^Kf^Xa6*Up4Yhw~Wl82|~BWy$;;AaU>0d z%eFahFHe8~|GS$K&%XXt)d*8RegB7C&-CrCfYi`hLs1VTaP!-r70am5B$jMMIyeAe z=05AW6*@lD?HUe19n%z$Zr*h3d9bRx89+(dubWYWX;(}CJXwVF$W0MMBOn3m!5Y~# zM+wr3*+OBNG5ddG`lf)SM2Kf^s=$>mZnGN_)lEnvU76)fKKAA|2cCVcDwt=QD7Q%f z8WBUuLZ->-n*c!|Y}QI?MxY>QwLsJyHdRDJ0s*iVb)D)g8qqy%YR{tNs(8|91xVc} z6hHxh01ynxCc1|wCGj)?g+QU`Kmh=>!{`NJ^`0Cy(LG4W;fqNv06>ZzD4-v%JiP2O zBm>NZACf;xnS((ljR*jRK-uwd&YM*%N{K@mJEO8g0MKNqe6;!Fz~D zaZEe|g+KrRfd0(6oqaPI0u1mxy#7=`8l-p^OM(Up0PS$d9PjjJ1RiGSE_9q#Q^6#Z zLI4aL+sKQbJ0CbHFQLM2#Y5G074=O zJBIGy(x2&HGgG9Y0G*76!;^i*h5#k<0suhL2s-6pFQz!i&=vs)LZzr3a zB#MPIALX)3jy^bmod5tRnuL?-@QwL=m>(9BrTg()SxE>4*KKu02|kZA$Y6(`?nnRt z01_sW$N~VMQ2+|XIk7AGqVw{ZH^Slt14Gbl%udHq6L(RHn*ss;O&iF%&s~ZJS z5z~MwNOAb(#migp`NwY}#MJHXAM(R*zMek*`Q83bjbyz_Iw2__UgwZODpmjd`yL+s z^zAO>hd%pOhJbu8;OnWi{J`1D?l#zkBq^nANhiPa^B*3c{&7q2K1I}g%6NvlZ|Q{I z2fsX(gTK_*{ZD;$Npgfc(gI@uEDS6RfOP=|94rhrvDgd(41hHTwzvT-3@RAQRFQYz zKmY#!`Khme9Kg$$)YOfBjyOQW&$L1d)TaNI1sQ(fb?=9--=(5H%+0UVRPSn9d8E1; cMRKx~hW1uwKmYoGziq{V03iJj`2W-Z0C~1aDF6Tf literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG diff --git a/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_background.webp b/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_background.webp new file mode 100644 index 0000000000000000000000000000000000000000..f66bbd7d6e53b3d6d497ce6db71fbe9badb54e9e GIT binary patch literal 172 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 literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Android_App/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..5e70bfe3a19e71557163e95a141e5fb9f66fb820 100644 GIT binary patch literal 4082 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 literal 2898 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 diff --git a/Android_App/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Android_App/app/src/main/res/mipmap-mdpi/ic_launcher.webp index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..57a54099a378b48f3963a17d615f9ef2f3385208 100644 GIT binary patch literal 1642 zcmV-w29^0zNk&Fu1^@t8MM6+kP&iCg1^@srFTe{B6^DYf4Vc!y?HvmdF#&W1{i57z z+ZHXFa_|-$il7Mh%$))tvr*1`GCu`S+YG}eNd6r2)U8C}Mv^4OnXl^`XDV)|yJyAB%#tS`EqI0N z+O|z6wrv|#B)_k{umhv2_g=KmXRya{;5L#XIm>u_e~_f@pCL*2zf4ACmesax+qOG0 zvZ~Hd+n$*durWp}w`0a`tk!yz%f{HY^9FT{#+Xa)jGV3YK#(NawDtDChl4ruY}>YN z+xq^;fh0+$_3nR*#q2(Q+qP}nHu~?tZ5v0DpzVG4?h&G~RN2n%>O#fCT{BslnX64O z#{AgYgn-^kSEXtVXI44;-z-EMVXP_^ArF0Fk){Xf$(P5|^ZIoQFp;=e5N)+#VP%nO z0m_->u1*+GwOQLrX3jSE)r1<|j0LwZAnAi8q6qSYB<|RONkZv^LDh1;XD>!Y;kwvE zQQYly5%Io&BFMiC73?%3kb2pT#6!27?YxJ{myLUb$e~1A?By~ha3AUQb!O&1uWzlbG9{NQIRjL!Q^Q-ewDml)+p>4rWym1V zGiS~~iuVl(6f9$FV7ZXGnnm|o>6=B)X;=0Ct5yh=f8WH(@HG^01`5`3h0pYK>$mL@ z?KN?r$C;$dSd4dMtbFJuV0^ z5s;)ZUMssEv0Z02L^NyVKW~=G|DTQ14g_4V=@cl8O)1o(jl=314tT^PZjqpK(C6TF z+q)f30k2mo9^Gr_-;P!Ck1a0ye(6jG1WK+nM$%hMvBO@;$74^m{4d_K;$Wrx_Y;n} zmxDs1T(|&0QgPFpjamD3KQV3mxDNpUz(<=-f(fJKHcngiVPj6jGajWFLENCh(wg+4 z^-9^#o0wzK^J+l=fGjp9%|_??iCILnYJd@n(~kh?!JiD|DsgT|tsL2|ht|psW^mBP zYNiP4x_=)y_){kkbvsO`Xk@?nRtK;9pc!QD*SrWgxequ64!+YwFyIBj!Rx{(`M8HQ zDwhu$VKyL0v@|vXcfyoZ1Hk}&cz(Gw`(;%8eFIB*UZs}YW8s(U`f*&sL6M@kvC(1z zgpH&OP6$HlWkSe`=x*~X%`jvHP%J~{;B^OAib?Zv#qWod|9ob!(4T@R(7k3A}_D)w2fN;VAu3+r=|cR7@PJ+qD* zjb4KcU&rk0I!rQmtLDnzuReOD!EaDr}lmkO>;o;vjBMu%{zgsw1{Be(HH)Y6K>R$$OLfO~z-2Q&wOzPP* zNuoG8`j=)H0g-oU4Z14%_seG-ydIxSvH@Gl@;|EAu2Kl;+hxMIAJ(iwMy5$mo|wr= zgCt`Ao{&?T)6hmGq*`JC*eN_wRB4pBVJ~$#RcaN;3EQ;sznVKp5d8hjvBrAl3>2_w zVpn71$BzK${l>-x(~z`aj7pp)u}vHQtR)8t242s0V4Zn$8#xgOxNzYkz6zZcZ2V(!z27B$)-40$?&jDiVR8x0~M5%Mtg5udV!y(K`!L^ oH2nYn`Pd!eAHT1ePcjQjW-;zIo@o=L>{qa)Sa`WRDH=%v0CylXp8x;= literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!T$4l69WLyhfIs3O{+*WFnuj=7b+WjNDTL@Bm1?7ME;&*J}<1U@cJs#;#l2$(`&#%Hd3aN W=qj;)1j#^~ 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 literal 1772 zcmVQj4N+cqN`nQhxvX7dAV-`K|Ub$-q+H-5I?Tx0g9jWxd@A|?POE8`3b8fO$T))xP* z(X?&brZw({`)WU&rdAs1iTa0x6F@PIxJ&&L|dpySV!ID|iUhjCcKz(@mE z!x@~W#3H<)4Ae(4eQJRk`Iz3<1)6^m)0b_4_TRZ+cz#eD3f8V;2r-1fE!F}W zEi0MEkTTx}8i1{`l_6vo0(Vuh0HD$I4SjZ=?^?k82R51bC)2D_{y8mi_?X^=U?2|F{Vr7s!k(AZC$O#ZMyavHhlQ7 zUR~QXuH~#o#>(b$u4?s~HLF*3IcF7023AlwAYudn0FV~|odGH^05AYPEfR)8p`i{n zwg3zPVp{+wOsxKc>)(pMupKF!Y2HoUqQ3|Yu|8lwR=?5zZuhG6J?H`bSNk_wPoM{u zSL{c@pY7+c2kck>`^q1^^gR0QB7Y?KUD{vz-uVX~;V-rW)PDcI)$_UjgVV?S?=oLR zf4}zz{#*R_{LkiJ#0RdQLNC^2Vp%JPEUvG9ra2BVZ92(p9h7Ka@!yf9(lj#}>+|u* z;^_?KWdzkM`6gqPo9;;r6&JEa)}R3X{(CWv?NvgLeOTq$cZXqf7|sPImi-7cS8DCN zGf;DVt3Am`>hH3{4-WzH43Ftx)SofNe^-#|0HdCo<+8Qs!}TZP{HH8~z5n`ExcHuT zDL1m&|DVpIy=xsLO>8k92HcmfSKhflQ0H~9=^-{#!I1g(;+44xw~=* zxvNz35vfsQE)@)Zsp*6_GjYD};Squ83<_?^SbALb{a`j<0Gn%6JY!zhp=Fg}Ga2|8 z52e1WU%^L1}15Ex0fF$e@eCT(()_P zvV?CA%#Sy08_U6VPt4EtmVQraWJX` zh=N|WQ>LgrvF~R&qOfB$!%D3cGv?;Xh_z$z7k&s4N)$WYf*k=|*jCEkO19{h_(%W4 zPuOqbCw`SeAX*R}UUsbVsgtuG?xs(#Ikx9`JZoQFz0n*7ZG@Fv@kZk`gzO$HoA9kN z8U5{-yY zvV{`&WKU2$mZeoBmiJrEdzUZAv1sRxpePdg1)F*X^Y)zp^Y*R;;z~vOv-z&)&G)JQ{m!C9cmziu1^nHA z`#`0c>@PnQ9CJKgC5NjJD8HM3|KC(g5nnCq$n0Gsu_DXk36@ql%npEye|?%RmG)

FJ$wK}0tWNB{uH;AM~i diff --git a/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher.webp index 948a3070fe34c611c42c0d3ad3013a0dce358be0..ea2f74954e5f0fb2740127caba0cbeb059936d02 100644 GIT binary patch literal 2712 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 literal 1900 zcmV-y2b1_xNk&Fw2LJ$9MM6+kP&il$0000G0001A003VA06|PpNH75a00DqwTbm-~ zullQTcXxO9ki!OCRx^i?oR|n!<8G0=kI^!JSjFi-LL*`V;ET0H2IXfU0*i>o6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? diff --git a/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp b/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_background.webp new file mode 100644 index 0000000000000000000000000000000000000000..c2d0ca13693430fc8044a5aaca0ed4af7b59cf23 GIT binary patch literal 224 zcmV<603ZKSNk&H400012MM6+kP&iD?0000l*T6LZ83k?IFzVwEx;qpi`ab~xAmyS# zr4gTvLbeg0BAh?)gD?=${|TUXNUp$5BuS2x{NWtIvHr~yqt-y$Hc@&1M!phc+w_?C z2U#d#+sH|E3m^LZ_`2iXC4|2U00=E{Fqe%U%Ou?lX=rF0 ahV{@OIF@Pc{dfmq>s3%+VkckH>lySux) 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 literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Android_App/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp index 1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f..1951e1b37514b45f20cf5c1db0a60f8310888cb7 100644 GIT binary patch literal 5702 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

RAMi#?BV%&3{l4g)}9nzrNWg`zzX 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 literal 3918 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 K<&5Y*lZpU$B;UsX literal 2884 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 E0G8K#J^%m! literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/Android_App/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..53086e4389832fa5ec1ba18d99791f866fd86b4c GIT binary patch literal 6930 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

l{ z2bKf0xR1;!J9R#?UU{c0??Gxc+$Vr6vJ*09x6PZ+2F_0HHQ)f6p`ddlRwWn z`ZiPrB(fWZ(%pV6#Zph9<$XyCS`vY48Ulso}+cW4z4IrZlD@$gaQD)YUEU4eyg zF&JXFB+16f1suaw2j<*2=Ul2U?A7)CQBF^`yib%-PpNnMhWh5-8qr~*P#+Tl4ahP zjd=p-@dz;F)Tw!}>qzRIUlf|itSeQS-urA&q_8Q;IC*+hQzD&GO-;e^^t$0SI=|}V zJlNgI$|FGU#`Yz1GPotPM4Hb-0BXr(ie6veA2G6O`|m}>(_4JmhAF+s-!|X8xSc$C z`c`!2SXeBzWu%qXKYM=nbR?Bc`*~^TYe+PS0OX`jw=qwPu-nUII-G4reLKB8Dd$q- z--X9B8%tJ}C%`x+Q~OdOB5|!oTN~9`2*OcGwyBUHaQ3yawjtMblCA%a7Q1Fmxx8M<=@5!>w$jdy~c__WD zdq$NjzgBoWy|E<65>QI-{gYFBk2kmr(R^%gmA;i`bpjzeg2IE;#ykqO*9O17d#{&y zu*;0HJ=qGjkoFAp98PQa;%IZ_cZ-Z9H<##I z0!Y;kFvg)A1IjUekN0?kE4YFyV6u>LYdkgq=gIR35W_JvtMdw{egs7Z{^rrFmEIk8 zYw%+4uI^51D@C^KAGPi~FwCs$3S^}$NV|oD^)i_bc>ox3n$gYmdkkRVw;XwfMiPTV~mB%zU<2uA_f6bIKBUFmehX>kitX%_c5T1#m9g$7BXZw zwo@;~GI;YG1;sK;^T^lc53ALGwy&qxr+Wa{c1BK4GdtKVq&3XE6Ivu?!A>$iBmz*q zF$AF9BS3$4kIQH{#f&@vjCbwhXTO2$9$z-xcK@Z^inUq!ri)(`5lOD~?mJ3SCf}AO zfRqkKfGESI)3k$Q3ykPJ{TQmZ^x@iy4E(kEq;g;6R;0e_Jz3 zv4ZS#p7_QPfa-^YR7hcvENPN-cQ73UpkvP2ot(%a4*)y#=;h;x0qq}OI;8&ggClHo zewK5w{;yHx%P;4hDSViJD))84@yul5k<_vxqN$Zdh5gk<1^(*SC?b+vR!A&8nSV0> zRlcd*hoj1tUw+4X8gg&zfdTCvU+TQK06YH0j8Zr`WuNnRP3I2MO(d0K=$9bQI***mm~hqF;7W$ENR*t4s{(E;6h`#QM0&+mu6_V4}s zpJed>u-(o51y!5v3bN1hwE7IO8|Ii(!?LT0FXFp~a6($t@4m=Xb~MF1LF zMgUr_e&XM?kdI%%3g$fL6|CUn7xG;bzxpk-++Nz0hM$)@DLgagkkE6r*F^yG;$}|r zd4~IvE@i?TX-VZsm@?hI7=B)o%yHA`+Pmt(GGjhNWT~rtGToh|Ns|;%nlwAnO=j;( W*22fe+)ByiDCv>1q~z!*=~@}Qz1GeE literal 5914 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�(p-{x$&=IACIfoAR!za)F-^da-t3#0Dycnp zwO~NVXwXCl;jE<}>%@xz|=8fIJAB?>+E{7)|4l${4ngA3G|=r z2Dyv;VVWSgZx9Wj>qUjleGl3Ei9K4>h!(lPS%8VOG>Xu0%6VDz^O=bjJmuP7>DeUv zrbI}MlHB^^d?{zv6d=@_ZD2lg1&G7UjnVN{1}9WkaM3H~btX0GtSzB+tZ^qRgWo4m z!GmimlG$=wgXCnr6j@m<1gAL46#T~5Bnm=2{^@>|t&`9mkEPddj zAvG~@Tv~TAm2i%VW}R-g(Z0)z-Y|szHr@rk>4MAyG*Ma*7Yh#H7(!-5>DZ@8r;_dx z{prSe<>~099F8vsYd2xff7uAS%7{S)f(|@me3t2$iy&NEc7OUEchp@9A|X;;IA>8!oX+y(BKJ$EzV* znR$z;!L$s7uy@{OT~nG#B!NRraT8(X##Ho!0r_o@gg0CA-9H^;-uE&?$2$nHv_00o z%cbuUc-tCx$Uh&EZ4Nf4Zgqv)Y6>usG3>GeQnxx_Z6+PcbX-+ysbt1hQ`K1LDpOE? zrAhIZhSN9yVIAOa22gn577tbc&i3|3V8NWy&!tw##`}9*x}gtI^h1DzZRA>UuaJG) zaZ7j)dq!O}{?#8Y7~7i6fHh4{`pL?>-18|p!S75Y#^DM>-S3)vuZG+Q7l@ek zQP~#cBpWgg#mApc_sPYjpw8odQuRokmTkzcNl`^CcKB7e&;zViV;{Y{o^Y$%7i0m# z62%#1Lq!RC?}lK>%mp}T!3Xv;L*0v*>USLm``N%>w>@fwC+#T&Tx2bN4w(20JB}oU zuSa6v^kXi0xPs?pbaOHnyiqq6By1EZY9OZ^^QA>{q-Hsd&m`pbQ%8121aWG-F5xf zlZ%;B{;C>X19|`^_?dVyCq>n+41w7|!tUS!{9rHlbhX=SZO5CQ^;!Du_E7*`GiR^Q w)2!4MKjfSAeN5Yhh$ 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 literal 0 HcmV?d00001 diff --git a/Android_App/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/Android_App/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..50af534bc82ef27904d42bb48ebe6de401d85e87 GIT binary patch literal 9452 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

UmY2RIYtNPVDpE$%vda+HD#3m z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0 z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s From 3f5decf38060b374b68575caafc974d4e90e25ed Mon Sep 17 00:00:00 2001 From: brentfpage Date: Fri, 17 Apr 2026 17:04:40 -0700 Subject: [PATCH 13/21] remove more default Android icons --- .../res/drawable/ic_launcher_background.xml | 170 ------------------ .../res/drawable/ic_launcher_foreground.xml | 30 ---- 2 files changed, 200 deletions(-) delete mode 100644 Android_App/app/src/main/res/drawable/ic_launcher_background.xml delete mode 100644 Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/Android_App/app/src/main/res/drawable/ic_launcher_background.xml b/Android_App/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9cb..000000000 --- a/Android_App/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml b/Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d114..000000000 --- a/Android_App/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file From 03b967011fe577b840a52038648783357ab25a7b Mon Sep 17 00:00:00 2001 From: brentfpage Date: Sat, 18 Apr 2026 00:25:35 -0700 Subject: [PATCH 14/21] backup icon files --- .../.unpackaged_assets/labrador_icon.png | Bin 0 -> 118637 bytes .../labrador_icon_background.png | Bin 0 -> 50454 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Android_App/.unpackaged_assets/labrador_icon.png create mode 100644 Android_App/.unpackaged_assets/labrador_icon_background.png diff --git a/Android_App/.unpackaged_assets/labrador_icon.png b/Android_App/.unpackaged_assets/labrador_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..56ccd5cacff7eb68e629f8252897631e75fdc168 GIT binary patch literal 118637 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 Qw*fyong(ZbPhSf89~;o9UH||9 literal 0 HcmV?d00001 diff --git a/Android_App/.unpackaged_assets/labrador_icon_background.png b/Android_App/.unpackaged_assets/labrador_icon_background.png new file mode 100644 index 0000000000000000000000000000000000000000..33a37933c26b7a5d4ccc83aef5237e97eb285c9c GIT binary patch literal 50454 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 literal 0 HcmV?d00001 From b38593e92b52b45df9102cba0990f9e0f602d7ac Mon Sep 17 00:00:00 2001 From: brentfpage Date: Sat, 18 Apr 2026 00:44:57 -0700 Subject: [PATCH 15/21] now backed up the correct icon.png --- .../.unpackaged_assets/labrador_icon.png | Bin 118637 -> 131801 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Android_App/.unpackaged_assets/labrador_icon.png b/Android_App/.unpackaged_assets/labrador_icon.png index 56ccd5cacff7eb68e629f8252897631e75fdc168..7b788e3b7f8a42ab5eb242e3bdcff1f345553f52 100644 GIT binary patch literal 131801 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�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 literal 118637 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 Qw*fyong(ZbPhSf89~;o9UH||9 From 712350fe30e72e01b0563798146ca63104cb8064 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Mon, 20 Apr 2026 18:20:14 -0700 Subject: [PATCH 16/21] appropriate precision for the reference line legend; also a new greek delta --- .../app/src/main/assets/font/greek_delta.ttf | Bin 1168 -> 1168 bytes Android_App/app/src/main/cpp/main.cpp | 3 +- Android_App/app/src/main/cpp/plot_ui.cpp | 57 ++++++++++++++++-- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/Android_App/app/src/main/assets/font/greek_delta.ttf b/Android_App/app/src/main/assets/font/greek_delta.ttf index afac6271541625038a829cca4078ba7c6e13acc3..0dbb66ae88e977ce64a577baaa9c117f38657831 100644 GIT binary patch delta 204 zcmbQhIe}AzfsuiMft#U$ftkU;KUm+0?;`8Fi6S~Cp21&dF)%Pz0A({WQWH~j`+h73 z@*e>CW*`B!NES8*1||t0UnL{Aq=KvA|G$YPUQEmm6Ayd~`Tq|n7sbK=G!>|dnbDY0 zotu$~QBROjw*2HxMt7zSe*?4_-~AH;8VNK3i1$D6e;v0RWV4UfCK|jl`x|*qdGU^ z14ab_MuEZu7Z@d&CjHIRV7&QH9cUy_DG)!4-H{v5Z}XLb8>kBip8lv3L8h4%CUY@K X0SyBgJXwoL4rCz%NbTkTCI=<}g7qd- diff --git a/Android_App/app/src/main/cpp/main.cpp b/Android_App/app/src/main/cpp/main.cpp index b86621f82..c9211eebf 100644 --- a/Android_App/app/src/main/cpp/main.cpp +++ b/Android_App/app/src/main/cpp/main.cpp @@ -180,6 +180,7 @@ int main(int, char**) // https://stackoverflow.com/a/13317651/3474552 float glyph_y_offsets[2] = {3.f, 4.5f}; + float fontsizes[2] = {13.f, 12.f}; char buf[2][2048]; int fi = 0; for (const char* filename: {"font/waveform-glyphs3.ttf","font/greek_delta.ttf"}) { @@ -187,7 +188,7 @@ int main(int, char**) AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING); int nb_read = 0; nb_read = AAsset_read(asset, buf[fi], 2048); - ImFont* new_font = io.Fonts->AddFontFromMemoryTTF(buf[fi], nb_read, 13.f, &config); + ImFont* new_font = io.Fonts->AddFontFromMemoryTTF(buf[fi], nb_read, fontsizes[fi], &config); AAsset_close(asset); fi++; } diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp index cf909a274..faa6366a5 100644 --- a/Android_App/app/src/main/cpp/plot_ui.cpp +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -36,6 +36,38 @@ void plotUI::recompute_x_bounds(bool mode_changed, inputsUI::Mode mode) } } +void get_ref_line_label(char * label, int size, char X_or_Y, ImPlotAxis ax, double ref_a, double ref_b) { + + double ref_1 = ImMin(ref_a, ref_b); + double ref_2 = ImMax(ref_a, ref_b); + int n_prec = 3; + int n_sig_figs_needed = ref_1 != ref_2 ? ImMax(ImLog10(ImMax(ImAbs(ref_1),ImAbs(ref_2)) / ImAbs(ref_2-ref_1)),0.) + n_prec : 0; + int n_sig_figs_needed_1 = (int) (floor(ImLog10(ImAbs(ref_1))) - floor(ImLog10(ax.Range.Max - ax.Range.Min))) + n_prec; + int n_sig_figs_needed_2 = (int) (floor(ImLog10(ImAbs(ref_2))) - floor(ImLog10(ax.Range.Max - ax.Range.Min))) + n_prec; + + n_sig_figs_needed_1 = ImMax(n_sig_figs_needed, n_sig_figs_needed_1); + n_sig_figs_needed_2 = ImMax(n_sig_figs_needed, n_sig_figs_needed_2); + n_sig_figs_needed_1 = ImMin(n_sig_figs_needed_1, 8); + n_sig_figs_needed_2 = ImMin(n_sig_figs_needed_2, 8); + + // write the ref 1, 2 values and their difference to the same number of decimal places + int ref_1_prec = n_sig_figs_needed_1 - floor(ImLog10(ImAbs(ref_1))); + int ref_2_prec = n_sig_figs_needed_2 - floor(ImLog10(ImAbs(ref_2))); + ref_1_prec = ImMax(ref_1_prec, ref_2_prec); + ref_2_prec = ImMax(ref_1_prec, ref_2_prec); + n_sig_figs_needed_1 = ref_1_prec + floor(ImLog10(ImAbs(ref_1))); + n_sig_figs_needed_2 = ref_2_prec + floor(ImLog10(ImAbs(ref_2))); + double difference = ref_2 - ref_1; + int n_sig_figs_needed_diff = ImMax(ref_1_prec, ref_2_prec) + floor(ImLog10(difference)); + n_sig_figs_needed_diff = ImMin(n_sig_figs_needed_diff, 8); + + int buf_size = 64; + char str_to_format[buf_size]; + ImFormatString(str_to_format, buf_size, "%%c1: %%.%dg\n%%c2: %%.%dg\n\xee\xa4\x84%%c: %%.%dg", n_sig_figs_needed_1, n_sig_figs_needed_2, n_sig_figs_needed_diff); + + ImFormatString(label, size, str_to_format, X_or_Y, ref_1, X_or_Y, ref_2, X_or_Y, difference); +} + void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, bool chB_enabled, double data_width, double plot_height) { std::vector *from_librador_chA; @@ -191,14 +223,29 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, ImPlot::SetNextAxisLimits(ImAxis_X1, xmin, xmax, ImPlotCond_Always); ImPlot::SetNextAxisLimits(ImAxis_Y1, ymin, ymax, ImPlotCond_Always); + int buffer_size = 64; + char x_ref_line_label[buffer_size]; + char y_ref_line_label[buffer_size]; + if(enable_x_ref_lines) { + get_ref_line_label(x_ref_line_label, buffer_size, 'X', mainplot->XAxis(0), x_ref_1, x_ref_2); + } else { + x_ref_line_label[0] = '\0'; + } + if(enable_y_ref_lines) { + get_ref_line_label(y_ref_line_label, buffer_size, 'Y', mainplot->YAxis(0), y_ref_1, y_ref_2); + } else { + y_ref_line_label[0] = '\0'; + } + + if(enable_x_ref_lines || enable_y_ref_lines) { - ImGui::SetNextWindowBgAlpha(0.25f); ImGuiStyle& style = ImGui::GetStyle(); ImPlotContext& gp = *GImPlot; ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, {2 * style.ItemSpacing.x, style.ItemSpacing.y}); - float ref_legend_width = (enable_x_ref_lines + enable_y_ref_lines) * ImGui::CalcTextSize("X1: -0.000").x + (enable_x_ref_lines && enable_y_ref_lines) * style.ItemSpacing.x + 2 * style.FramePadding.x; - float ref_legend_height = 3 * ImGui::GetFontSize() + 2 * style.FramePadding.y; + float ref_legend_width = ImGui::CalcTextSize(x_ref_line_label).x + ImGui::CalcTextSize(y_ref_line_label).x + (enable_x_ref_lines && enable_y_ref_lines) * style.ItemSpacing.x + 2 * style.FramePadding.x; + float ref_legend_height = ImMax(ImGui::CalcTextSize(x_ref_line_label).y, ImGui::CalcTextSize(y_ref_line_label).y) + 2 * style.FramePadding.y; + ImGui::SetCursorScreenPos(mainplot->PlotRect.Max - ImVec2(ref_legend_width, ref_legend_height) - gp.Style.LegendPadding ); ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->AddRectFilled(ImGui::GetCursorScreenPos(), ImGui::GetCursorScreenPos() + ImVec2(ref_legend_width, ref_legend_height), ImGui::GetColorU32(ImGuiCol_WindowBg,.75)); @@ -206,13 +253,13 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, ImGui::BeginGroup(); if(enable_x_ref_lines) { - ImGui::Text("X1: %.3f\nX2: %.3f\n\xee\xa4\x84X: %.3f", fmin(x_ref_1,x_ref_2), fmax(x_ref_1,x_ref_2), fabs(x_ref_2 - x_ref_1)); + ImGui::Text("%s", x_ref_line_label); } if(enable_x_ref_lines && enable_y_ref_lines) { ImGui::SameLine(); } if(enable_y_ref_lines) { - ImGui::Text("Y1: %.3f\nY2: %.3f\n\xee\xa4\x84Y: %.3f", fmin(y_ref_1,y_ref_2), fmax(y_ref_1,y_ref_2), fabs(y_ref_2 - y_ref_1)); + ImGui::Text("%s", y_ref_line_label); } ImGui::EndGroup(); ImGui::PopStyleVar(); From 002a526bec73ca98446f2399c596894982519936 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Tue, 21 Apr 2026 11:21:14 -0700 Subject: [PATCH 17/21] android: clamping and appropriate precision for the axis limit selector pop-ups --- Android_App/app/src/main/cpp/plot_ui.cpp | 69 ++++++++++++++++++++---- Android_App/app/src/main/cpp/plot_ui.h | 12 +++-- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp index faa6366a5..a0d858b2e 100644 --- a/Android_App/app/src/main/cpp/plot_ui.cpp +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -187,14 +187,47 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, if(ImGui::BeginPopup("select x lims")) { ImGuiStyle& style = ImGui::GetStyle(); ImGui::Text("X-axis limits:"); - ImGui::PushItemWidth(ImGui::CalcTextSize("-10.00 s").x + 2 * style.FramePadding.x); - ImGui::InputFloat("Min", &xmin, 0.f, 0.f, "%.2f s"); - float new_window = xmax - xmin; + ImGui::PushItemWidth(ImGui::CalcTextSize("-00000000. s").x + 2 * style.FramePadding.x); + float xminf = xmin; + float window = xmax - xmin; + int n_prec = 3; + int n_sig_figs_needed = xmax != xmin ? ImMax(ImLog10(ImMax(ImAbs(xmax),ImAbs(xmin)) / ImAbs(window)),0.) + n_prec : 0; + n_sig_figs_needed = ImMin(n_sig_figs_needed, 8); + + char label_template[32]; + ImFormatString(label_template, 32, "%%.%dg s", n_sig_figs_needed); + if(ImGui::InputFloat("Min", &xminf, 0.f, 0.f, label_template)) { + if(xminf < 0) { + xminf = ImMax((float) x_constraint_min, xminf); + xminf = ImMin((float) x_constraint_max, xminf); + xmin = xminf; + } + } + float new_window = xmax - xmin; float new_delay = fabs(-xmax); // fabs to prevent signed 0 - ImGui::InputFloat("Window", &new_window, 0.f, 0.f, "%.2f s"); - ImGui::InputFloat("Delay", &new_delay, 0.f, 0.f, "%.2f s"); - xmin = -new_delay - new_window; - xmax = -new_delay; + char window_label_template[32]; + ImFormatString(window_label_template, 32, "%%.%dg s", n_prec); + if(ImGui::InputFloat("Window", &new_window, 0.f, 0.f, window_label_template)) { + if(new_window < 0) { + new_window = xmax - xmin; + } + new_window = ImMax((double) new_window, min_window_size); + } + if(ImGui::InputFloat("Delay", &new_delay, 0.f, 0.f, label_template)) { + if(new_delay < 0) { + new_delay = fabs(-xmax); + } + } + double new_xmin = -new_delay - new_window; + double new_xmax = -new_delay; + new_xmin = ImMax(x_constraint_min, new_xmin); + new_xmin = ImMin(x_constraint_max - min_window_size, new_xmin); + new_xmax = ImMax(new_xmin + min_window_size, new_xmax); + new_xmax = ImMin(x_constraint_max, new_xmax); + if(new_xmin!=new_xmax) { + xmin = new_xmin; + xmax = new_xmax; + } ImGui::EndPopup(); } else { xmin = axes_limits.X.Min; @@ -208,9 +241,25 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, if(ImGui::BeginPopup("select y lims")) { ImGuiStyle& style = ImGui::GetStyle(); ImGui::Text("Y-axis limits:"); - ImGui::PushItemWidth(ImGui::CalcTextSize("-20.00 V").x + 2 * style.FramePadding.x); - ImGui::InputFloat("Max", &ymax, 0.f, 0.f, "%.2f V"); - ImGui::InputFloat("Min", &ymin, 0.f, 0.f, "%.2f V"); + ImGui::PushItemWidth(ImGui::CalcTextSize("-00000000. V").x + 2 * style.FramePadding.x); + int n_sig_figs_needed = ymin != ymax ? ImMax(ImLog10(ImMax(ImAbs(ymin),ImAbs(ymax)) / ImAbs(ymin-ymax)),0.) + 3 : 0; + n_sig_figs_needed = ImMin(n_sig_figs_needed, 8); + char label_template[32]; + ImFormatString(label_template, 32, "%%.%dg V", n_sig_figs_needed); + float ymaxf = ymax; + if(ImGui::InputFloat("Max", &ymaxf, 0.f, 0.f, label_template)) { + ymaxf = ImMin(max_voltage, ymaxf); + if(ymaxf > ymin) { + ymax = ymaxf; + } + } + float yminf = ymin; + if(ImGui::InputFloat("Min", &yminf, 0.f, 0.f, label_template)) { + yminf = ImMax(-max_voltage, yminf); + if(yminf < ymax) { + ymin = yminf; + } + } ImGui::EndPopup(); } else { ymin = axes_limits.Y.Min; diff --git a/Android_App/app/src/main/cpp/plot_ui.h b/Android_App/app/src/main/cpp/plot_ui.h index 61ae79839..ccc532c9e 100644 --- a/Android_App/app/src/main/cpp/plot_ui.h +++ b/Android_App/app/src/main/cpp/plot_ui.h @@ -7,14 +7,16 @@ #define GRAPH_SAMPLES 512 class plotUI { - float xmin = -.5; - float xmax = 0.; - float ymin = -2.; - float ymax = 2.; + double xmin = -.5; + double xmax = 0.; + double ymin = -2.; + double ymax = 2.; const double max_time_window_375khz = 10; - const double max_voltage = 20; + const float max_voltage = 20; double x_constraint_min = -max_time_window_375khz; double x_constraint_max = 0.; + const double min_window_size = 1.e-6; + const double min_voltage_diff = 1.e-3; double x_ref_1; double x_ref_2; From 0030db9c823ded6b05ee67f5545233727ee92d7c Mon Sep 17 00:00:00 2001 From: brentfpage Date: Tue, 21 Apr 2026 12:52:52 -0700 Subject: [PATCH 18/21] android: streamline 712350f --- Android_App/app/src/main/cpp/plot_ui.cpp | 33 +++++++++--------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp index a0d858b2e..8a5676bab 100644 --- a/Android_App/app/src/main/cpp/plot_ui.cpp +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -40,32 +40,23 @@ void get_ref_line_label(char * label, int size, char X_or_Y, ImPlotAxis ax, doub double ref_1 = ImMin(ref_a, ref_b); double ref_2 = ImMax(ref_a, ref_b); - int n_prec = 3; - int n_sig_figs_needed = ref_1 != ref_2 ? ImMax(ImLog10(ImMax(ImAbs(ref_1),ImAbs(ref_2)) / ImAbs(ref_2-ref_1)),0.) + n_prec : 0; - int n_sig_figs_needed_1 = (int) (floor(ImLog10(ImAbs(ref_1))) - floor(ImLog10(ax.Range.Max - ax.Range.Min))) + n_prec; - int n_sig_figs_needed_2 = (int) (floor(ImLog10(ImAbs(ref_2))) - floor(ImLog10(ax.Range.Max - ax.Range.Min))) + n_prec; + double difference = ref_2 - ref_1; + // write the ref 1, 2 values and their difference to the same number of decimal places + int max_prec = 3 - floor(ImLog10(ImMin(ax.Range.Max - ax.Range.Min, ImAbs(ref_2 - ref_1)))); - n_sig_figs_needed_1 = ImMax(n_sig_figs_needed, n_sig_figs_needed_1); - n_sig_figs_needed_2 = ImMax(n_sig_figs_needed, n_sig_figs_needed_2); - n_sig_figs_needed_1 = ImMin(n_sig_figs_needed_1, 8); - n_sig_figs_needed_2 = ImMin(n_sig_figs_needed_2, 8); + int n_sig_figs_needed_1 = max_prec + floor(ImLog10(ImAbs(ref_1))); + int n_sig_figs_needed_2 = max_prec + floor(ImLog10(ImAbs(ref_2))); + int n_sig_figs_needed_diff = max_prec + floor(ImLog10(difference)); - // write the ref 1, 2 values and their difference to the same number of decimal places - int ref_1_prec = n_sig_figs_needed_1 - floor(ImLog10(ImAbs(ref_1))); - int ref_2_prec = n_sig_figs_needed_2 - floor(ImLog10(ImAbs(ref_2))); - ref_1_prec = ImMax(ref_1_prec, ref_2_prec); - ref_2_prec = ImMax(ref_1_prec, ref_2_prec); - n_sig_figs_needed_1 = ref_1_prec + floor(ImLog10(ImAbs(ref_1))); - n_sig_figs_needed_2 = ref_2_prec + floor(ImLog10(ImAbs(ref_2))); - double difference = ref_2 - ref_1; - int n_sig_figs_needed_diff = ImMax(ref_1_prec, ref_2_prec) + floor(ImLog10(difference)); - n_sig_figs_needed_diff = ImMin(n_sig_figs_needed_diff, 8); + n_sig_figs_needed_1 = ImMax(ImMin(n_sig_figs_needed_1, 8),0); + n_sig_figs_needed_2 = ImMax(ImMin(n_sig_figs_needed_2, 8),0); + n_sig_figs_needed_diff = ImMax(ImMin(n_sig_figs_needed_diff, 8),0); int buf_size = 64; - char str_to_format[buf_size]; - ImFormatString(str_to_format, buf_size, "%%c1: %%.%dg\n%%c2: %%.%dg\n\xee\xa4\x84%%c: %%.%dg", n_sig_figs_needed_1, n_sig_figs_needed_2, n_sig_figs_needed_diff); + char label_template[buf_size]; + ImFormatString(label_template, buf_size, "%%c1: %%.%dg\n%%c2: %%.%dg\n\xee\xa4\x84%%c: %%.%dg", n_sig_figs_needed_1, n_sig_figs_needed_2, n_sig_figs_needed_diff); - ImFormatString(label, size, str_to_format, X_or_Y, ref_1, X_or_Y, ref_2, X_or_Y, difference); + ImFormatString(label, size, label_template, X_or_Y, ref_1, X_or_Y, ref_2, X_or_Y, difference); } void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, bool chB_enabled, double data_width, double plot_height) From 51ad7acd23c6e2793ca26dce0410ea48dcf51145 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Tue, 21 Apr 2026 15:39:33 -0700 Subject: [PATCH 19/21] android: tweaks to 002a526 --- Android_App/app/src/main/cpp/plot_ui.cpp | 64 ++++++++++++++---------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp index 8a5676bab..0c179372e 100644 --- a/Android_App/app/src/main/cpp/plot_ui.cpp +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -41,7 +41,6 @@ void get_ref_line_label(char * label, int size, char X_or_Y, ImPlotAxis ax, doub double ref_1 = ImMin(ref_a, ref_b); double ref_2 = ImMax(ref_a, ref_b); double difference = ref_2 - ref_1; - // write the ref 1, 2 values and their difference to the same number of decimal places int max_prec = 3 - floor(ImLog10(ImMin(ax.Range.Max - ax.Range.Min, ImAbs(ref_2 - ref_1)))); int n_sig_figs_needed_1 = max_prec + floor(ImLog10(ImAbs(ref_1))); @@ -178,46 +177,59 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, if(ImGui::BeginPopup("select x lims")) { ImGuiStyle& style = ImGui::GetStyle(); ImGui::Text("X-axis limits:"); - ImGui::PushItemWidth(ImGui::CalcTextSize("-00000000. s").x + 2 * style.FramePadding.x); + ImGui::PushItemWidth(ImGui::CalcTextSize("-000000000. s").x + 2 * style.FramePadding.x); float xminf = xmin; float window = xmax - xmin; + float delay = ImAbs(-xmax); // fabs to prevent signed 0 int n_prec = 3; - int n_sig_figs_needed = xmax != xmin ? ImMax(ImLog10(ImMax(ImAbs(xmax),ImAbs(xmin)) / ImAbs(window)),0.) + n_prec : 0; - n_sig_figs_needed = ImMin(n_sig_figs_needed, 8); + int max_prec = n_prec - floor(ImLog10(ImAbs(window))); // - char label_template[32]; - ImFormatString(label_template, 32, "%%.%dg s", n_sig_figs_needed); - if(ImGui::InputFloat("Min", &xminf, 0.f, 0.f, label_template)) { + char min_label_template[32]; + int n_sig_figs_needed_min = max_prec + floor(ImLog10(ImAbs(xminf))); + n_sig_figs_needed_min = ImMax(ImMin(n_sig_figs_needed_min, 8),0); + ImFormatString(min_label_template, 32, "%%.%dg s", n_sig_figs_needed_min); + if(ImGui::InputFloat("Min", &xminf, 0.f, 0.f, min_label_template)) { if(xminf < 0) { xminf = ImMax((float) x_constraint_min, xminf); xminf = ImMin((float) x_constraint_max, xminf); xmin = xminf; } } - float new_window = xmax - xmin; - float new_delay = fabs(-xmax); // fabs to prevent signed 0 + + bool modified = false; char window_label_template[32]; ImFormatString(window_label_template, 32, "%%.%dg s", n_prec); - if(ImGui::InputFloat("Window", &new_window, 0.f, 0.f, window_label_template)) { - if(new_window < 0) { - new_window = xmax - xmin; + if(ImGui::InputFloat("Window", &window, 0.f, 0.f, window_label_template)) { + if(window <= 0) { + window = xmax - xmin; + } else { + window = ImMax((double) window, min_window_size); + modified = true; } - new_window = ImMax((double) new_window, min_window_size); } - if(ImGui::InputFloat("Delay", &new_delay, 0.f, 0.f, label_template)) { - if(new_delay < 0) { - new_delay = fabs(-xmax); + + char delay_label_template[32]; + int n_sig_figs_needed_delay = max_prec + (delay != 0 ? floor(ImLog10(ImAbs(delay))) : 0); + n_sig_figs_needed_delay = ImMax(ImMin(n_sig_figs_needed_delay, 8),0); + ImFormatString(delay_label_template, 32, "%%.%dg s", n_sig_figs_needed_delay); + if(ImGui::InputFloat("Delay", &delay, 0.f, 0.f, delay_label_template)) { + if(delay < 0) { + delay = fabs(-xmax); + } else { + modified = true; } } - double new_xmin = -new_delay - new_window; - double new_xmax = -new_delay; - new_xmin = ImMax(x_constraint_min, new_xmin); - new_xmin = ImMin(x_constraint_max - min_window_size, new_xmin); - new_xmax = ImMax(new_xmin + min_window_size, new_xmax); - new_xmax = ImMin(x_constraint_max, new_xmax); - if(new_xmin!=new_xmax) { - xmin = new_xmin; - xmax = new_xmax; + if(modified) { + double new_xmin = -delay - window; + double new_xmax = -delay; + new_xmin = ImMax(x_constraint_min, new_xmin); + new_xmin = ImMin(x_constraint_max - min_window_size, new_xmin); + new_xmax = ImMax(new_xmin + min_window_size, new_xmax); + new_xmax = ImMin(x_constraint_max, new_xmax); + if(new_xmin!=new_xmax) { + xmin = new_xmin; + xmax = new_xmax; + } } ImGui::EndPopup(); } else { @@ -232,7 +244,7 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, if(ImGui::BeginPopup("select y lims")) { ImGuiStyle& style = ImGui::GetStyle(); ImGui::Text("Y-axis limits:"); - ImGui::PushItemWidth(ImGui::CalcTextSize("-00000000. V").x + 2 * style.FramePadding.x); + ImGui::PushItemWidth(ImGui::CalcTextSize("-000000000. V").x + 2 * style.FramePadding.x); int n_sig_figs_needed = ymin != ymax ? ImMax(ImLog10(ImMax(ImAbs(ymin),ImAbs(ymax)) / ImAbs(ymin-ymax)),0.) + 3 : 0; n_sig_figs_needed = ImMin(n_sig_figs_needed, 8); char label_template[32]; From e1f563038ef9363b24d075417b982c4ec85cdbab Mon Sep 17 00:00:00 2001 From: brentfpage Date: Tue, 21 Apr 2026 15:55:27 -0700 Subject: [PATCH 20/21] android: float->double for axis limits --- Android_App/app/src/main/cpp/plot_ui.cpp | 43 ++++++++++++------------ Android_App/app/src/main/cpp/plot_ui.h | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp index 0c179372e..41778a601 100644 --- a/Android_App/app/src/main/cpp/plot_ui.cpp +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -178,28 +178,29 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, ImGuiStyle& style = ImGui::GetStyle(); ImGui::Text("X-axis limits:"); ImGui::PushItemWidth(ImGui::CalcTextSize("-000000000. s").x + 2 * style.FramePadding.x); - float xminf = xmin; - float window = xmax - xmin; - float delay = ImAbs(-xmax); // fabs to prevent signed 0 + double window = xmax - xmin; + double delay = ImAbs(-xmax); // fabs to prevent signed 0 int n_prec = 3; int max_prec = n_prec - floor(ImLog10(ImAbs(window))); // char min_label_template[32]; - int n_sig_figs_needed_min = max_prec + floor(ImLog10(ImAbs(xminf))); + int n_sig_figs_needed_min = max_prec + floor(ImLog10(ImAbs(xmin))); n_sig_figs_needed_min = ImMax(ImMin(n_sig_figs_needed_min, 8),0); ImFormatString(min_label_template, 32, "%%.%dg s", n_sig_figs_needed_min); - if(ImGui::InputFloat("Min", &xminf, 0.f, 0.f, min_label_template)) { - if(xminf < 0) { - xminf = ImMax((float) x_constraint_min, xminf); - xminf = ImMin((float) x_constraint_max, xminf); - xmin = xminf; + double xmin_saved = xmin; + if(ImGui::InputDouble("Min", &xmin, 0.f, 0.f, min_label_template)) { + if(xmin < 0) { + xmin = ImMax(x_constraint_min, xmin); + xmin = ImMin(x_constraint_max, xmin); + } else { + xmin = xmin_saved; } } bool modified = false; char window_label_template[32]; ImFormatString(window_label_template, 32, "%%.%dg s", n_prec); - if(ImGui::InputFloat("Window", &window, 0.f, 0.f, window_label_template)) { + if(ImGui::InputDouble("Window", &window, 0.f, 0.f, window_label_template)) { if(window <= 0) { window = xmax - xmin; } else { @@ -212,7 +213,7 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, int n_sig_figs_needed_delay = max_prec + (delay != 0 ? floor(ImLog10(ImAbs(delay))) : 0); n_sig_figs_needed_delay = ImMax(ImMin(n_sig_figs_needed_delay, 8),0); ImFormatString(delay_label_template, 32, "%%.%dg s", n_sig_figs_needed_delay); - if(ImGui::InputFloat("Delay", &delay, 0.f, 0.f, delay_label_template)) { + if(ImGui::InputDouble("Delay", &delay, 0.f, 0.f, delay_label_template)) { if(delay < 0) { delay = fabs(-xmax); } else { @@ -249,18 +250,18 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, n_sig_figs_needed = ImMin(n_sig_figs_needed, 8); char label_template[32]; ImFormatString(label_template, 32, "%%.%dg V", n_sig_figs_needed); - float ymaxf = ymax; - if(ImGui::InputFloat("Max", &ymaxf, 0.f, 0.f, label_template)) { - ymaxf = ImMin(max_voltage, ymaxf); - if(ymaxf > ymin) { - ymax = ymaxf; + double ymax_saved = ymax; + if(ImGui::InputDouble("Max", &ymax, 0.f, 0.f, label_template)) { + ymax = ImMin(max_voltage, ymax); + if(ymax <= ymin) { + ymax = ymax_saved; } } - float yminf = ymin; - if(ImGui::InputFloat("Min", &yminf, 0.f, 0.f, label_template)) { - yminf = ImMax(-max_voltage, yminf); - if(yminf < ymax) { - ymin = yminf; + double ymin_saved = ymin; + if(ImGui::InputDouble("Min", &ymin, 0.f, 0.f, label_template)) { + ymin = ImMax(-max_voltage, ymin); + if(ymin >= ymax) { + ymin = ymin_saved; } } ImGui::EndPopup(); diff --git a/Android_App/app/src/main/cpp/plot_ui.h b/Android_App/app/src/main/cpp/plot_ui.h index ccc532c9e..00a663ecc 100644 --- a/Android_App/app/src/main/cpp/plot_ui.h +++ b/Android_App/app/src/main/cpp/plot_ui.h @@ -12,7 +12,7 @@ class plotUI double ymin = -2.; double ymax = 2.; const double max_time_window_375khz = 10; - const float max_voltage = 20; + const double max_voltage = 20; double x_constraint_min = -max_time_window_375khz; double x_constraint_max = 0.; const double min_window_size = 1.e-6; From 6ec957362e8798811e4bf87bb89801d8e41ea422 Mon Sep 17 00:00:00 2001 From: brentfpage Date: Tue, 21 Apr 2026 16:53:53 -0700 Subject: [PATCH 21/21] float->double for reference line values --- Android_App/app/src/main/cpp/deps/implot | 2 +- Android_App/app/src/main/cpp/plot_ui.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Android_App/app/src/main/cpp/deps/implot b/Android_App/app/src/main/cpp/deps/implot index c506551c5..9c620603f 160000 --- a/Android_App/app/src/main/cpp/deps/implot +++ b/Android_App/app/src/main/cpp/deps/implot @@ -1 +1 @@ -Subproject commit c506551c58cfabf4c7d593c4c980575be8f89deb +Subproject commit 9c620603fd5610c0ee8fc8a71b13ce7268947e79 diff --git a/Android_App/app/src/main/cpp/plot_ui.cpp b/Android_App/app/src/main/cpp/plot_ui.cpp index 41778a601..2884481cf 100644 --- a/Android_App/app/src/main/cpp/plot_ui.cpp +++ b/Android_App/app/src/main/cpp/plot_ui.cpp @@ -122,8 +122,8 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, ImGuiContext& g = *GImGui; if(ImPlot::IsAxisActivated(ImAxis_X1)) { - float mouse_down_clicked_val = ImPlot::getMouseDownClickedVal(ImAxis_X1); - cursor_drag_tool_toggle = fabs(x_ref_1 - mouse_down_clicked_val) > fabs(x_ref_2 - mouse_down_clicked_val); + double mouse_down_clicked_val = ImPlot::getMouseDownClickedVal(ImAxis_X1); + cursor_drag_tool_toggle = ImAbs(x_ref_1 - mouse_down_clicked_val) > ImAbs(x_ref_2 - mouse_down_clicked_val); } ImPlotDragToolFlags x1_drag_tool_flags = cursor_drag_tool_toggle ? ImPlotDragToolFlags_NoAxisInputs : 0; @@ -146,8 +146,8 @@ void plotUI::draw(bool iso_thread_active, inputsUI::Mode mode, bool chA_enabled, } if(ImPlot::IsAxisActivated(ImAxis_Y1)) { - float mouse_down_clicked_val = ImPlot::getMouseDownClickedVal(ImAxis_Y1); - cursor_drag_tool_toggle = fabs(y_ref_1 - mouse_down_clicked_val) > fabs(y_ref_2 - mouse_down_clicked_val); + double mouse_down_clicked_val = ImPlot::getMouseDownClickedVal(ImAxis_Y1); + cursor_drag_tool_toggle = ImAbs(y_ref_1 - mouse_down_clicked_val) > ImAbs(y_ref_2 - mouse_down_clicked_val); } ImPlotDragToolFlags y1_drag_tool_flags = cursor_drag_tool_toggle ? ImPlotDragToolFlags_NoAxisInputs : 0;