From e17d0a03ace1ac00f07c9884cadb488e0b9f6206 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 27 Feb 2024 12:28:00 +0400 Subject: [PATCH 01/67] refactor(OpenGloves): decouple from Arduino SDK --- .../mode_configs/opengloves/opengloves.cpp | 2 +- .../senseshift/opengloves/autoconfig.hpp | 95 +++++++++++++--- .../senseshift/opengloves/opengloves.hpp | 102 +++++++++--------- .../opengloves/opengloves_component.hpp} | 12 +-- 4 files changed, 137 insertions(+), 74 deletions(-) rename lib/{opengloves_freertos/senseshift/opengloves/opengloves_task.hpp => opengloves/senseshift/opengloves/opengloves_component.hpp} (94%) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index 382ad083..aa8a0ee5 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include using namespace SenseShift::OpenGloves; diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index de6eeaf2..b3e763e2 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -144,14 +144,53 @@ #pragma region Buttons -#define BUTTON_A_ENABLED (defined(PIN_BUTTON_A) && (PIN_BUTTON_A != -1)) -#define BUTTON_B_ENABLED (defined(PIN_BUTTON_B) && (PIN_BUTTON_B != -1)) -#define BUTTON_MENU_ENABLED (defined(PIN_BUTTON_MENU) && (PIN_BUTTON_MENU != -1)) -#define BUTTON_JOYSTICK_ENABLED (JOYSTICK_ENABLED && defined(PIN_BUTTON_JOYSTICK) && (PIN_BUTTON_JOYSTICK != -1)) -#define BUTTON_CALIBRATE_ENABLED (defined(PIN_BUTTON_CALIBRATE) && (PIN_BUTTON_CALIBRATE != -1)) -#define BUTTON_TRIGGER_ENABLED (!GESTURE_TRIGGER_ENABLED && defined(PIN_BUTTON_TRIGGER) && (PIN_BUTTON_TRIGGER != -1)) -#define BUTTON_GRAB_ENABLED (!GESTURE_GRAB_ENABLED && defined(PIN_BUTTON_GRAB) && (PIN_BUTTON_GRAB != -1)) -#define BUTTON_PINCH_ENABLED (!GESTURE_PINCH_ENABLED && defined(PIN_BUTTON_PINCH) && (PIN_BUTTON_PINCH != -1)) +#ifdef PIN_BUTTON_A +#define BUTTON_A_ENABLED (PIN_BUTTON_A != -1) +#else +#define BUTTON_A_ENABLED false +#endif + +#ifdef PIN_BUTTON_B +#define BUTTON_B_ENABLED (PIN_BUTTON_B != -1) +#else +#define BUTTON_B_ENABLED false +#endif + +#ifdef PIN_BUTTON_MENU +#define BUTTON_MENU_ENABLED (PIN_BUTTON_MENU != -1) +#else +#define BUTTON_MENU_ENABLED false +#endif + +#ifdef PIN_BUTTON_JOYSTICK +#define BUTTON_JOYSTICK_ENABLED (PIN_BUTTON_JOYSTICK != -1) +#else +#define BUTTON_JOYSTICK_ENABLED false +#endif + +#ifdef PIN_BUTTON_CALIBRATE +#define BUTTON_CALIBRATE_ENABLED (PIN_BUTTON_CALIBRATE != -1) +#else +#define BUTTON_CALIBRATE_ENABLED false +#endif + +#ifdef PIN_BUTTON_TRIGGER +#define BUTTON_TRIGGER_ENABLED (PIN_BUTTON_TRIGGER != -1) +#else +#define BUTTON_TRIGGER_ENABLED false +#endif + +#ifdef PIN_BUTTON_GRAB +#define BUTTON_GRAB_ENABLED (PIN_BUTTON_GRAB != -1) +#else +#define BUTTON_GRAB_ENABLED false +#endif + +#ifdef PIN_BUTTON_PINCH +#define BUTTON_PINCH_ENABLED (PIN_BUTTON_PINCH != -1) +#else +#define BUTTON_PINCH_ENABLED false +#endif #define BUTTON_CLASS(PIN, INVERT) \ ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::DigitalSimpleSensor(PIN)); @@ -174,11 +213,35 @@ #pragma endregion -#define FFB_THUMB_ENABLED (defined(PIN_FFB_THUMB) && (PIN_FFB_THUMB != -1)) -#define FFB_INDEX_ENABLED (defined(PIN_FFB_INDEX) && (PIN_FFB_INDEX != -1)) -#define FFB_MIDDLE_ENABLED (defined(PIN_FFB_MIDDLE) && (PIN_FFB_MIDDLE != -1)) -#define FFB_RING_ENABLED (defined(PIN_FFB_RING) && (PIN_FFB_RING != -1)) -#define FFB_PINKY_ENABLED (defined(PIN_FFB_PINKY) && (PIN_FFB_PINKY != -1)) +#ifdef PIN_FFB_THUMB +#define FFB_THUMB_ENABLED (PIN_FFB_THUMB != -1) +#else +#define FFB_THUMB_ENABLED false +#endif + +#ifdef PIN_FFB_INDEX +#define FFB_INDEX_ENABLED (PIN_FFB_INDEX != -1) +#else +#define FFB_INDEX_ENABLED false +#endif + +#ifdef PIN_FFB_MIDDLE +#define FFB_MIDDLE_ENABLED (PIN_FFB_MIDDLE != -1) +#else +#define FFB_MIDDLE_ENABLED false +#endif + +#ifdef PIN_FFB_RING +#define FFB_RING_ENABLED (PIN_FFB_RING != -1) +#else +#define FFB_RING_ENABLED false +#endif + +#ifdef PIN_FFB_PINKY +#define FFB_PINKY_ENABLED (PIN_FFB_PINKY != -1) +#else +#define FFB_PINKY_ENABLED false +#endif #define FFB_ENABLED \ (FFB_THUMB_ENABLED || FFB_INDEX_ENABLED || FFB_MIDDLE_ENABLED || FFB_RING_ENABLED || FFB_PINKY_ENABLED) @@ -284,17 +347,21 @@ namespace SenseShift::OpenGloves::AutoConfig { auto* button_a = new BUTTON_CLASS(PIN_BUTTON_A, BUTTON_A_INVERT); input_sensors.button_a.press = button_a; #endif + #if BUTTON_B_ENABLED auto* button_b = new BUTTON_CLASS(PIN_BUTTON_B, BUTTON_B_INVERT); input_sensors.button_b.press = button_b; #endif + #if BUTTON_JOYSTICK_ENABLED auto* button_joystick = new BUTTON_CLASS(PIN_BUTTON_JOYSTICK, BUTTON_JOYSTICK_INVERT); input_sensors.joystick.press = button_joystick; #endif + #if BUTTON_MENU_ENABLED auto* button_menu = new BUTTON_CLASS(PIN_BUTTON_MENU, BUTTON_MENU_INVERT); #endif + #if BUTTON_CALIBRATE_ENABLED auto* button_calibrate = new BUTTON_CLASS(PIN_BUTTON_CALIBRATE, BUTTON_CALIBRATE_INVERT); input_sensors.button_calibrate.press = button_calibrate; @@ -375,7 +442,7 @@ namespace SenseShift::OpenGloves::AutoConfig { pSerial->begin(SERIAL_BAUDRATE); return new StreamTransport(pSerial); #elif (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BTSERIAL) \ - || (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth Serial + || (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth std::string name; #ifdef BTSERIAL_NAME name = BTSERIAL_NAME; diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index cd4cbd0e..8062ec29 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -11,6 +11,56 @@ #include #include +#define SS_OG_COLLECT_DATA(FN) \ + og::InputPeripheralData data{}; \ + \ + const auto& curls = this->curl.fingers; \ + const auto& splays = this->splay.fingers; \ + for (auto i = 0; i < curls.size(); i++) { \ + const auto& finger_curl = curls[i].curl; \ + for (auto j = 0; j < finger_curl.size(); j++) { \ + auto* joint_sensor = finger_curl[j]; \ + if (joint_sensor != nullptr) { \ + data.curl.fingers[i].curl[j] = joint_sensor->FN(); \ + } \ + } \ + \ + auto* finger_splay = splays[i]; \ + if (finger_splay != nullptr) { \ + data.splay.fingers[i] = finger_splay->FN(); \ + } \ + } \ + \ + if (this->joystick.x != nullptr) { \ + data.joystick.x = this->joystick.x->FN(); \ + } \ + if (this->joystick.y != nullptr) { \ + data.joystick.y = this->joystick.y->FN(); \ + } \ + if (this->joystick.press != nullptr) { \ + data.joystick.press = this->joystick.press->FN(); \ + } \ + \ + for (auto i = 0; i < this->buttons.size(); i++) { \ + auto* button = this->buttons[i].press; \ + if (button != nullptr) { \ + data.buttons[i].press = button->FN(); \ + } \ + } \ + \ + for (auto i = 0; i < this->analog_buttons.size(); i++) { \ + auto* button = this->analog_buttons[i].press; \ + if (button != nullptr) { \ + data.analog_buttons[i].press = button->FN(); \ + } \ + auto* value = this->analog_buttons[i].value; \ + if (value != nullptr) { \ + data.analog_buttons[i].value = value->FN(); \ + } \ + } \ + \ + return data; + namespace SenseShift::OpenGloves { class ITransport : public IInitializable { public: @@ -85,57 +135,9 @@ namespace SenseShift::OpenGloves { } } - auto collectData() -> og::InputPeripheralData - { - og::InputPeripheralData data{}; - - const auto& curls = this->curl.fingers; - const auto& splays = this->splay.fingers; - for (auto i = 0; i < curls.size(); i++) { - const auto& finger_curl = curls[i].curl; - for (auto j = 0; j < finger_curl.size(); j++) { - auto* joint_sensor = finger_curl[j]; - if (joint_sensor != nullptr) { - data.curl.fingers[i].curl[j] = joint_sensor->getValue(); - } - } + [[nodiscard]] auto collectData() -> og::InputPeripheralData { SS_OG_COLLECT_DATA(getValue); } - auto* finger_splay = splays[i]; - if (finger_splay != nullptr) { - data.splay.fingers[i] = finger_splay->getValue(); - } - } - - if (this->joystick.x != nullptr) { - data.joystick.x = this->joystick.x->getValue(); - } - if (this->joystick.y != nullptr) { - data.joystick.y = this->joystick.y->getValue(); - } - if (this->joystick.press != nullptr) { - data.joystick.press = this->joystick.press->getValue(); - } - - for (auto i = 0; i < this->buttons.size(); i++) { - auto* button = this->buttons[i].press; - if (button != nullptr) { - data.buttons[i].press = button->getValue(); - } - } - - for (auto i = 0; i < this->analog_buttons.size(); i++) { - auto* button = this->analog_buttons[i].press; - if (button != nullptr) { - data.analog_buttons[i].press = button->getValue(); - } - auto* value = this->analog_buttons[i].value; - if (value != nullptr) { - data.analog_buttons[i].value = value->getValue(); - } - } - - return data; - } + [[nodiscard]] auto collectRawData() -> og::InputPeripheralData { SS_OG_COLLECT_DATA(getRawValue); } void reselCalibration() override { diff --git a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp similarity index 94% rename from lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp rename to lib/opengloves/senseshift/opengloves/opengloves_component.hpp index f8509f3d..9ad39cd4 100644 --- a/lib/opengloves_freertos/senseshift/opengloves/opengloves_task.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -5,17 +5,11 @@ #include #include #include +#include -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/input/sensor/digital.hpp" -#include "senseshift/core/component.hpp" -#include "senseshift/freertos/task.hpp" -#include "senseshift/input/sensor.hpp" +#include "opengloves/opengloves.hpp" #include "senseshift/opengloves/opengloves.hpp" -#include "senseshift/utility.hpp" -#include -#include -#include +#include namespace SenseShift::OpenGloves { class OpenGlovesTrackingComponent : public SenseShift::Component { From b246d003fc979db92a3f5454cad91e26150d468b Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 27 Feb 2024 14:19:46 +0400 Subject: [PATCH 02/67] feat(OpenGloves): add Serial Plotter for data --- .../opengloves/opengloves_component.hpp | 9 +++++ .../opengloves/opengloves_plotter.hpp | 37 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index 9ad39cd4..55c8ce45 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -9,10 +9,15 @@ #include "opengloves/opengloves.hpp" #include "senseshift/opengloves/opengloves.hpp" +#include + #include namespace SenseShift::OpenGloves { class OpenGlovesTrackingComponent : public SenseShift::Component { + // Plotter raw_plotter_ = Plotter(&Serial, "Raw"); + // Plotter calibrated_plotter_ = Plotter(&Serial, "Cal"); + public: class Config { friend class OpenGlovesTrackingComponent; @@ -61,6 +66,10 @@ namespace SenseShift::OpenGloves { const auto data = this->input_sensors_.collectData(); // const auto collectTime = micros() - now; + // const auto raw_data = this->input_sensors_.collectRawData(); + // this->raw_plotter_.plot(raw_data); + // this->calibrated_plotter_.plot(data); + bool const calibrate_pressed = data.button_calibrate.press; if (calibrate_pressed && this->calibration_start_time_ == 0) { this->startCalibration(); diff --git a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp new file mode 100644 index 00000000..803a7d94 --- /dev/null +++ b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "Arduino.h" + +#include "opengloves/opengloves.hpp" + +namespace SenseShift::OpenGloves { + class Plotter { + public: + Plotter(Print* output, char* prefix) : output_(output), prefix_(prefix){}; + + void plot(const og::InputPeripheralData data) + { + this->output_->printf("%sThumbCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.thumb.curl_total * 4095); + this->output_->printf(", %sIndexCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.index.curl_total * 4095); + this->output_->printf(", %sMiddleCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.middle.curl_total * 4095); + this->output_->printf(", %sRingCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.ring.curl_total * 4095); + this->output_->printf(", %sPinkyCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.pinky.curl_total * 4095); + + this->output_->printf(", %sJoyX: ", this->prefix_); + this->output_->printf("%4.0f", data.joystick.x * 4095); + this->output_->printf(", %sJoyY: ", this->prefix_); + this->output_->printf("%4.0f", data.joystick.y * 4095); + + this->output_->println(); + } + + private: + Print* output_; + char* prefix_; + }; +} // namespace SenseShift::OpenGloves \ No newline at end of file From 204022615b869ac8f223b39552a8b3633dd2aad8 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 27 Feb 2024 14:21:53 +0400 Subject: [PATCH 03/67] chore(OpenGloves): tweak default sensitivity --- ini/opengloves.ini | 2 +- lib/io/senseshift/input/filter.hpp | 4 +- .../senseshift/opengloves/autoconfig.hpp | 8 +-- .../opengloves/opengloves_plotter.hpp | 4 +- test/test_io_sensor/main.cpp | 66 +++++++++++++++++++ 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/ini/opengloves.ini b/ini/opengloves.ini index ab5c8333..763fa00f 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -36,7 +36,7 @@ build_flags = -D JOYSTICK_X_INVERT=false -D JOYSTICK_Y_INVERT=false - -D JOYSTICK_DEADZONE=0.1 + -D JOYSTICK_DEADZONE=0.03 -D BUTTON_JOYSTICK_INVERT=false -D BUTTON_A_INVERT=false diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index fe534ee4..4fa3bb15 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -267,9 +267,9 @@ namespace SenseShift::Input::Filter { public: explicit CenterDeadzoneFilter(float deadzone, float center = 0.5F) : deadzone_(deadzone), center_(center){}; - auto filter(ISimpleSensor* /*sensor*/, float value) -> float override + inline auto filter(ISimpleSensor* /*sensor*/, float value) -> float override { - float const deviation = std::abs(value - this->center_); + const auto deviation = std::abs(value - this->center_); return deviation < deadzone_ ? this->center_ : value; } diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index b3e763e2..98ba482d 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -137,7 +137,7 @@ auto NAME##_sensor = \ new ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::AnalogSimpleSensor(PIN) \ ); \ - NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter(0.8F), \ + NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter(0.7F), \ new ::SenseShift::Input::Filter::CenterDeadzoneFilter(DEADZONE) }); #pragma endregion @@ -367,14 +367,14 @@ namespace SenseShift::OpenGloves::AutoConfig { input_sensors.button_calibrate.press = button_calibrate; #endif -#if GESTURE_TRIGGER_ENABLED +#if GESTURE_TRIGGER_ENABLED && FINGER_INDEX_ENABLED auto* trigger = new Body::Hands::Input::TriggerGesture(index_curl_sensor, GESTURE_TRIGGER_THRESHOLD); input_sensors.trigger.press = trigger; #elif BUTTON_TRIGGER_ENABLED auto trigger = new BUTTON_CLASS(PIN_BUTTON_TRIGGER, BUTTON_TRIGGER_INVERT); #endif -#if GESTURE_GRAB_ENABLED +#if GESTURE_GRAB_ENABLED && FINGER_INDEX_ENABLED && FINGER_MIDDLE_ENABLED && FINGER_RING_ENABLED && FINGER_PINKY_ENABLED auto* grab = new Body::Hands::Input::GrabGesture( Body::Hands::Input::GrabGesture::Fingers{ .index = index_curl_sensor, .middle = middle_curl_sensor, @@ -387,7 +387,7 @@ namespace SenseShift::OpenGloves::AutoConfig { auto* grab = new BUTTON_CLASS(PIN_BUTTON_GRAB, BUTTON_GRAB_INVERT); #endif -#if GESTURE_PINCH_ENABLED +#if GESTURE_PINCH_ENABLED && FINGER_THUMB_ENABLED && FINGER_INDEX_ENABLED auto* pinch = new Body::Hands::Input::PinchGesture( Body::Hands::Input::PinchGesture::Fingers{ .thumb = thumb_curl_sensor, .index = index_curl_sensor }, GESTURE_PINCH_THRESHOLD diff --git a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp index 803a7d94..0b9fa262 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp @@ -31,7 +31,7 @@ namespace SenseShift::OpenGloves { } private: - Print* output_; - char* prefix_; + Print* const output_; + char* const prefix_; }; } // namespace SenseShift::OpenGloves \ No newline at end of file diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index 188cbeaf..5977f81d 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -24,6 +24,16 @@ class TestAnalogSensor : public ISimpleSensor { auto getValue() -> int override { return this->value; }; }; +class TestFloatSensor : public ISimpleSensor { + public: + float value = 0.0f; + int setupCounter = 0; + + void init() override { this->setupCounter++; }; + + auto getValue() -> float override { return this->value; }; +}; + void test_memoized_sensor(void) { auto inner = new TestAnalogCountingSensor(); @@ -106,6 +116,60 @@ void test_sensor_filter_multiply(void) TEST_ASSERT_EQUAL_INT(32, sensor->getValue()); } +void test_sensor_filter_center_deadzone(void) +{ + auto inner = new TestFloatSensor(); + auto sensor = new SimpleSensorDecorator(inner); + sensor->addFilters({ new ::SenseShift::Input::Filter::CenterDeadzoneFilter(0.1, 0.5) }); + + TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); + sensor->init(); + TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); + + inner->value = 0; + sensor->tick(); + TEST_ASSERT_EQUAL_FLOAT(0.0f, sensor->getValue()); + + inner->value = 0.2; + sensor->tick(); + TEST_ASSERT_EQUAL_FLOAT(0.2f, sensor->getValue()); + + inner->value = 0.45; + sensor->tick(); + TEST_ASSERT_EQUAL_FLOAT(0.5f, sensor->getValue()); + + inner->value = 0.55; + sensor->tick(); + TEST_ASSERT_EQUAL_FLOAT(0.5f, sensor->getValue()); + + inner->value = 0.8; + sensor->tick(); + TEST_ASSERT_EQUAL_FLOAT(0.8f, sensor->getValue()); +} + +void test_sensor_multiple_filters(void) +{ + auto inner = new TestAnalogSensor(); + auto sensor = new SimpleSensorDecorator(inner); + + // Test MultiplyFilter separately + sensor->addFilter(new ::SenseShift::Input::Filter::MultiplyFilter(2)); + // Test AddFilter separately + sensor->addFilter(new ::SenseShift::Input::Filter::AddFilter(1)); + + TEST_ASSERT_EQUAL_INT(0, inner->setupCounter); + sensor->init(); + TEST_ASSERT_EQUAL_INT(1, inner->setupCounter); + + inner->value = 1; + sensor->tick(); + TEST_ASSERT_EQUAL_INT(3, sensor->getValue()); + + inner->value = 16; + sensor->tick(); + TEST_ASSERT_EQUAL_INT(33, sensor->getValue()); +} + void test_sensor_analog_threshold(void) { auto inner = new TestAnalogSensor(); @@ -144,6 +208,8 @@ int process(void) RUN_TEST(test_memoized_sensor); RUN_TEST(test_calibrated_sensor); RUN_TEST(test_sensor_filter_multiply); + RUN_TEST(test_sensor_filter_center_deadzone); + RUN_TEST(test_sensor_multiple_filters); RUN_TEST(test_sensor_analog_threshold); return UNITY_END(); From 41ae1ec35eb4cf03a5d31784b9f31cea5fff2943 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 27 Feb 2024 14:50:42 +0400 Subject: [PATCH 04/67] chore(CodiumAI): config PR agent (#101) --- .pr_agent.toml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .pr_agent.toml diff --git a/.pr_agent.toml b/.pr_agent.toml new file mode 100644 index 00000000..befe39c6 --- /dev/null +++ b/.pr_agent.toml @@ -0,0 +1,4 @@ +[github_app] +ignore_pr_title = ["^Sweep", "^Auto"] + +handle_push_trigger = true From 38a24bd56568b22516794a6502628fbc47cb336a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 28 Feb 2024 01:33:31 +0400 Subject: [PATCH 05/67] feat: add CD74HC4057 input --- .../arduino/input/sensor/analog.hpp | 4 +- .../arduino/input/sensor/cd74hc4067.hpp | 118 ++++++++++++++++++ .../senseshift/opengloves/autoconfig.hpp | 7 +- 3 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index dbef7c39..784a50d4 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -20,9 +20,11 @@ namespace SenseShift::Arduino::Input { template class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { - std::uint8_t pin_; + const std::uint8_t pin_; public: + static constexpr float MAX_VALUE = ANALOG_MAX; + explicit AnalogSimpleSensor(const std::uint8_t pin) : pin_(pin) {} void init() override { pinMode(this->pin_, INPUT); }; diff --git a/lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp b/lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp new file mode 100644 index 00000000..8e32ea57 --- /dev/null +++ b/lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp @@ -0,0 +1,118 @@ +#pragma once + +#include +#include +#include + +#include + +#include "senseshift/arduino/input/sensor/analog.hpp" + +#include + +namespace SenseShift::Arduino::Input { + class CD74HC4057Component : public IInitializable { + public: + /// \param pin_s0 The S0 pin. + /// \param pin_s1 The S1 pin. + /// \param pin_s2 The S2 pin. + /// \param pin_s3 The S3 pin. + /// \param switch_delay_us The delay in microseconds to wait after switching the channel. + CD74HC4057Component( + const std::uint8_t pin_s0, + const std::uint8_t pin_s1, + const std::uint8_t pin_s2, + const std::uint8_t pin_s3, + const size_t switch_delay_us = 2 + ) : + pin_s0_(pin_s0), pin_s1_(pin_s1), pin_s2_(pin_s2), pin_s3_(pin_s3), switch_delay_us_(switch_delay_us) + { + } + + void init() override + { + pinMode(this->pin_s0_, OUTPUT); + pinMode(this->pin_s1_, OUTPUT); + pinMode(this->pin_s2_, OUTPUT); + pinMode(this->pin_s3_, OUTPUT); + } + + /// Select the channel. + /// \param channel The channel to select. + /// + /// \note + /// Here is a table of the channel to select: + /// | Channel | S0 | S1 | S2 | S3 | + /// |---------|----|----|----|----| + /// | 0 | 0 | 0 | 0 | 0 | + /// | 1 | 1 | 0 | 0 | 0 | + /// | 2 | 0 | 1 | 0 | 0 | + /// | 3 | 1 | 1 | 0 | 0 | + /// | 4 | 0 | 0 | 1 | 0 | + /// | 5 | 1 | 0 | 1 | 0 | + /// | 6 | 0 | 1 | 1 | 0 | + /// | 7 | 1 | 1 | 1 | 0 | + /// | 8 | 0 | 0 | 0 | 1 | + /// | 9 | 1 | 0 | 0 | 1 | + /// | 10 | 0 | 1 | 0 | 1 | + /// | 11 | 1 | 1 | 0 | 1 | + /// | 12 | 0 | 0 | 1 | 1 | + /// | 13 | 1 | 0 | 1 | 1 | + /// | 14 | 0 | 1 | 1 | 1 | + /// | 15 | 1 | 1 | 1 | 1 | + void selectChannel(const std::uint8_t channel) + { + if (this->active_channel_ == channel) { + return; + } + + digitalWrite(this->pin_s0_, channel & 0b00001); + digitalWrite(this->pin_s1_, channel & 0b00010); + digitalWrite(this->pin_s2_, channel & 0b00100); + digitalWrite(this->pin_s3_, channel & 0b01000); + + delayMicroseconds(this->switch_delay_us_); + + this->active_channel_ = channel; + } + + private: + const std::uint8_t pin_s0_; + const std::uint8_t pin_s1_; + const std::uint8_t pin_s2_; + const std::uint8_t pin_s3_; + + size_t active_channel_ = 0; + + const size_t switch_delay_us_; + }; + + template + class CD74HC4057Sensor : public AnalogSimpleSensor { + CD74HC4057Component* component_; + const std::uint8_t channel_; + + public: + /// \param component The CD74HC4057 Component to use. + /// \param pin The SIG pin of the sensor. + /// \param channel The channel to read from. + CD74HC4057Sensor(CD74HC4057Component* component, const std::uint8_t pin, const std::uint8_t channel) : + component_(component), AnalogSimpleSensor(pin), channel_(channel) + { + assert(channel < 16 && "Channel must be between 0 and 15"); + } + + void init() override + { + this->component_->init(); + AnalogSimpleSensor::init(); + } + + [[nodiscard]] auto getValue() -> float override + { + this->component_->selectChannel(this->channel_); + + return AnalogSimpleSensor::getValue(); + } + }; +} // namespace SenseShift::Arduino::Input diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 98ba482d..3b12e89a 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -1,8 +1,5 @@ #pragma once -#include -#include -#include #include #include #include @@ -12,6 +9,10 @@ #include #ifdef ARDUINO +#include +#include +#include +#include #include #endif From 2fb4da4c64ed3f44ad3a388e090680c07bddaa4b Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 28 Feb 2024 18:38:58 +0400 Subject: [PATCH 06/67] refactor(Arduino): use Filter to invert analog sensors --- .../arduino/input/sensor/analog.hpp | 21 ++++----------- lib/io/senseshift/input/filter.hpp | 6 +++++ .../senseshift/opengloves/autoconfig.hpp | 27 ++++++++++--------- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 784a50d4..71a9af01 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -18,7 +18,6 @@ #endif namespace SenseShift::Arduino::Input { - template class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { const std::uint8_t pin_; @@ -29,20 +28,10 @@ namespace SenseShift::Arduino::Input { void init() override { pinMode(this->pin_, INPUT); }; - [[nodiscard]] auto getValue() -> float override; + [[nodiscard]] inline auto getValue() -> float override + { + const std::uint16_t raw = analogRead(this->pin_); + return static_cast(raw) / ANALOG_MAX; + } }; - - template<> - [[nodiscard]] inline auto AnalogSimpleSensor::getValue() -> float - { - const std::uint16_t raw = analogRead(this->pin_); - return static_cast(raw) / ANALOG_MAX; - } - - template<> - [[nodiscard]] inline auto AnalogSimpleSensor::getValue() -> float - { - const std::uint16_t raw = ANALOG_MAX - analogRead(this->pin_); - return static_cast(raw) / ANALOG_MAX; - } } // namespace SenseShift::Arduino::Input diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 4fa3bb15..01a4f495 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -300,4 +300,10 @@ namespace SenseShift::Input::Filter { private: Container const& lookup_table_; }; + + /// Specialized filter for analog sensors (between 0.0 and 1.0). + class AnalogInvertFilter : public IFilter { + public: + auto filter(ISimpleSensor* /*sensor*/, float value) -> float override { return 1.0F - value; } + }; } // namespace SenseShift::Input::Filter diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 3b12e89a..d3154522 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -83,11 +83,13 @@ #define FINGER_PINKY_ENABLED false #endif -#define DEFINE_FINGER(NAME, CURL_PIN, CURL_INVERT, CURL_CALIB) \ - auto* NAME##_sensor = new ::SenseShift::Input::SimpleSensorDecorator( \ - new ::SenseShift::Arduino::Input::AnalogSimpleSensor(CURL_PIN) \ - ); \ - NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter(0.8F) }); \ +#define DEFINE_FINGER(NAME, CURL_PIN, CURL_INVERT, CURL_CALIB) \ + auto* NAME##_sensor = \ + new ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::AnalogSimpleSensor(CURL_PIN)); \ + NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter(0.8F) }); \ + if (CURL_INVERT) { \ + NAME##_sensor->addFilter({ new ::SenseShift::Input::Filter::AnalogInvertFilter() }); \ + } \ NAME##_sensor->setCalibrator((CURL_CALIB)); #ifdef PIN_FINGER_THUMB_SPLAY @@ -134,13 +136,14 @@ #define JOYSTICK_ENABLED false #endif -#define DEFINE_JOYSTICK_AXIS(NAME, PIN, INVERT, DEADZONE) \ - auto NAME##_sensor = \ - new ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::AnalogSimpleSensor(PIN) \ - ); \ - NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter(0.7F), \ - new ::SenseShift::Input::Filter::CenterDeadzoneFilter(DEADZONE) }); - +#define DEFINE_JOYSTICK_AXIS(NAME, PIN, INVERT, DEADZONE) \ + auto NAME##_sensor = \ + new ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::AnalogSimpleSensor(PIN)); \ + NAME##_sensor->addFilters({ new ::SenseShift::Input::Filter::ExponentialMovingAverageFilter(0.7F), \ + new ::SenseShift::Input::Filter::CenterDeadzoneFilter(DEADZONE) }); \ + if (INVERT) { \ + NAME##_sensor->addFilter({ new ::SenseShift::Input::Filter::AnalogInvertFilter() }); \ + } #pragma endregion #pragma region Buttons From e2277d804d248d1ceb9e8d3845a48397a123edb6 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 28 Feb 2024 18:39:57 +0400 Subject: [PATCH 07/67] refactor: make multiplexers universal with templates --- .../arduino/input/sensor/cd74hc4067.hpp | 118 ------------------ .../arduino/input/sensor/multiplexer.hpp | 87 +++++++++++++ .../senseshift/opengloves/autoconfig.hpp | 2 +- 3 files changed, 88 insertions(+), 119 deletions(-) delete mode 100644 lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp create mode 100644 lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp diff --git a/lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp b/lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp deleted file mode 100644 index 8e32ea57..00000000 --- a/lib/arduino/senseshift/arduino/input/sensor/cd74hc4067.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include "senseshift/arduino/input/sensor/analog.hpp" - -#include - -namespace SenseShift::Arduino::Input { - class CD74HC4057Component : public IInitializable { - public: - /// \param pin_s0 The S0 pin. - /// \param pin_s1 The S1 pin. - /// \param pin_s2 The S2 pin. - /// \param pin_s3 The S3 pin. - /// \param switch_delay_us The delay in microseconds to wait after switching the channel. - CD74HC4057Component( - const std::uint8_t pin_s0, - const std::uint8_t pin_s1, - const std::uint8_t pin_s2, - const std::uint8_t pin_s3, - const size_t switch_delay_us = 2 - ) : - pin_s0_(pin_s0), pin_s1_(pin_s1), pin_s2_(pin_s2), pin_s3_(pin_s3), switch_delay_us_(switch_delay_us) - { - } - - void init() override - { - pinMode(this->pin_s0_, OUTPUT); - pinMode(this->pin_s1_, OUTPUT); - pinMode(this->pin_s2_, OUTPUT); - pinMode(this->pin_s3_, OUTPUT); - } - - /// Select the channel. - /// \param channel The channel to select. - /// - /// \note - /// Here is a table of the channel to select: - /// | Channel | S0 | S1 | S2 | S3 | - /// |---------|----|----|----|----| - /// | 0 | 0 | 0 | 0 | 0 | - /// | 1 | 1 | 0 | 0 | 0 | - /// | 2 | 0 | 1 | 0 | 0 | - /// | 3 | 1 | 1 | 0 | 0 | - /// | 4 | 0 | 0 | 1 | 0 | - /// | 5 | 1 | 0 | 1 | 0 | - /// | 6 | 0 | 1 | 1 | 0 | - /// | 7 | 1 | 1 | 1 | 0 | - /// | 8 | 0 | 0 | 0 | 1 | - /// | 9 | 1 | 0 | 0 | 1 | - /// | 10 | 0 | 1 | 0 | 1 | - /// | 11 | 1 | 1 | 0 | 1 | - /// | 12 | 0 | 0 | 1 | 1 | - /// | 13 | 1 | 0 | 1 | 1 | - /// | 14 | 0 | 1 | 1 | 1 | - /// | 15 | 1 | 1 | 1 | 1 | - void selectChannel(const std::uint8_t channel) - { - if (this->active_channel_ == channel) { - return; - } - - digitalWrite(this->pin_s0_, channel & 0b00001); - digitalWrite(this->pin_s1_, channel & 0b00010); - digitalWrite(this->pin_s2_, channel & 0b00100); - digitalWrite(this->pin_s3_, channel & 0b01000); - - delayMicroseconds(this->switch_delay_us_); - - this->active_channel_ = channel; - } - - private: - const std::uint8_t pin_s0_; - const std::uint8_t pin_s1_; - const std::uint8_t pin_s2_; - const std::uint8_t pin_s3_; - - size_t active_channel_ = 0; - - const size_t switch_delay_us_; - }; - - template - class CD74HC4057Sensor : public AnalogSimpleSensor { - CD74HC4057Component* component_; - const std::uint8_t channel_; - - public: - /// \param component The CD74HC4057 Component to use. - /// \param pin The SIG pin of the sensor. - /// \param channel The channel to read from. - CD74HC4057Sensor(CD74HC4057Component* component, const std::uint8_t pin, const std::uint8_t channel) : - component_(component), AnalogSimpleSensor(pin), channel_(channel) - { - assert(channel < 16 && "Channel must be between 0 and 15"); - } - - void init() override - { - this->component_->init(); - AnalogSimpleSensor::init(); - } - - [[nodiscard]] auto getValue() -> float override - { - this->component_->selectChannel(this->channel_); - - return AnalogSimpleSensor::getValue(); - } - }; -} // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp new file mode 100644 index 00000000..d6b1bb9c --- /dev/null +++ b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp @@ -0,0 +1,87 @@ +#pragma once + +#include +#include +#include +#include + +#include + +#include "senseshift/arduino/input/sensor/analog.hpp" + +#include +#include + +namespace SenseShift::Arduino::Input { + template + class Multiplexer : public IInitializable { + public: + /// \param pins The pins to use for the multiplexer. + explicit Multiplexer(const std::array& pins, const size_t switch_delay_us = 2) : + pins_(pins), switch_delay_us_(switch_delay_us) + { + } + + void init() override + { + for (const auto pin : this->pins_) { + pinMode(pin, OUTPUT); + } + } + + /// Select the channel. + /// \param channel The channel to select. + void selectChannel(const std::uint8_t channel) + { + if (channel >= (1 << N) || this->active_channel_ == channel) { + return; + } + + for (size_t i = 0; i < N; ++i) { + digitalWrite(this->pins_[i], (channel >> i) & 0b0001); + } + + delayMicroseconds(this->switch_delay_us_); + + this->active_channel_ = channel; + } + + private: + const std::array pins_; + std::uint8_t active_channel_ = 0; + const size_t switch_delay_us_; + }; + + using MUX_CD74HC4057Component = Multiplexer<4>; + using MUX_74HC4051Component = Multiplexer<3>; + + template + class MultiplexedSensor : public AnalogSimpleSensor { + public: + /// \param component The CD74HC4057 Component to use. + /// \param pin The SIG pin of the sensor. + /// \param channel The channel to read from. + MultiplexedSensor(Multiplexer* component, const std::uint8_t pin_sig, const std::uint8_t channel) : + component_(component), AnalogSimpleSensor(pin_sig), channel_(channel) + { + assert(channel < (1 << N) && "Channel out of range"); + } + + void init() override + { + this->component_->init(); + AnalogSimpleSensor::init(); + } + + [[nodiscard]] auto getValue() -> float override + { + this->component_->selectChannel(this->channel_); + + return AnalogSimpleSensor::getValue(); + } + + private: + Multiplexer* component_; + const std::uint8_t channel_; + }; +} // namespace SenseShift::Arduino::Input diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index d3154522..53229993 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -10,8 +10,8 @@ #ifdef ARDUINO #include -#include #include +#include #include #include #endif From b6c0b833a4515f94bcb11a6e60649f9144267f4a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 28 Feb 2024 21:43:59 +0400 Subject: [PATCH 08/67] refactor(Sensor): change core sensor dir structure --- .../senseshift/arduino/input/sensor/analog.hpp | 2 +- .../senseshift/arduino/input/sensor/digital.hpp | 2 +- .../senseshift/arduino/input/sensor/ina219.hpp | 2 +- .../arduino/input/sensor/multiplexer.hpp | 2 +- .../senseshift/battery/input/battery_sensor.hpp | 4 ++-- lib/bhaptics_ble/library.json | 16 ++++++++-------- lib/ble_serial/library.json | 14 +++++++------- .../senseshift/body/hands/input/gesture.hpp | 4 ++-- .../senseshift/body/hands/input/total_curl.hpp | 2 +- .../input/{ => sensor}/analog_threshold.hpp | 2 +- lib/io/senseshift/input/{ => sensor}/sensor.hpp | 0 .../senseshift/opengloves/autoconfig.hpp | 2 +- .../senseshift/opengloves/opengloves.hpp | 2 +- test/test_battery/main.cpp | 2 +- test/test_body_gestures/main.cpp | 2 +- test/test_io_filter/main.cpp | 2 +- test/test_io_sensor/main.cpp | 4 ++-- 17 files changed, 32 insertions(+), 32 deletions(-) rename lib/io/senseshift/input/{ => sensor}/analog_threshold.hpp (98%) rename lib/io/senseshift/input/{ => sensor}/sensor.hpp (100%) diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 71a9af01..1f50c26c 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index cc3e7573..55ab7158 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp index a2f4e6eb..970b7ecf 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include diff --git a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp index d6b1bb9c..52f10d28 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp @@ -10,7 +10,7 @@ #include "senseshift/arduino/input/sensor/analog.hpp" #include -#include +#include namespace SenseShift::Arduino::Input { template diff --git a/lib/battery/senseshift/battery/input/battery_sensor.hpp b/lib/battery/senseshift/battery/input/battery_sensor.hpp index 0ac6a840..e0b42e0e 100644 --- a/lib/battery/senseshift/battery/input/battery_sensor.hpp +++ b/lib/battery/senseshift/battery/input/battery_sensor.hpp @@ -4,8 +4,8 @@ #include "senseshift/battery/battery.hpp" -#include "senseshift/core/helpers.hpp" -#include "senseshift/input/sensor.hpp" +#include +#include namespace SenseShift::Battery::Input { /// Abstract battery sensor diff --git a/lib/bhaptics_ble/library.json b/lib/bhaptics_ble/library.json index 7ab73cce..8d0b1f4d 100644 --- a/lib/bhaptics_ble/library.json +++ b/lib/bhaptics_ble/library.json @@ -1,10 +1,10 @@ { - "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", - "frameworks": "arduino", - "platforms": [ - "espressif32" - ], - "dependencies": { - "h2zero/NimBLE-Arduino": "^1.4.0" - } + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "frameworks": "arduino", + "platforms": [ + "espressif32" + ], + "dependencies": { + "h2zero/NimBLE-Arduino": "^1.4.0" + } } diff --git a/lib/ble_serial/library.json b/lib/ble_serial/library.json index 7c2d9618..f4605a77 100644 --- a/lib/ble_serial/library.json +++ b/lib/ble_serial/library.json @@ -1,9 +1,9 @@ { - "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", - "name": "BLE Serial", - "description": "Arduino BLE Serial Stream library", - "frameworks": "arduino", - "platforms": [ - "espressif32" - ] + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "name": "BLE Serial", + "description": "Arduino BLE Serial Stream library", + "frameworks": "arduino", + "platforms": [ + "espressif32" + ] } diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp index eccb911f..aa4cb6ce 100644 --- a/lib/hands_input/senseshift/body/hands/input/gesture.hpp +++ b/lib/hands_input/senseshift/body/hands/input/gesture.hpp @@ -1,8 +1,8 @@ #pragma once #include -#include -#include +#include +#include namespace SenseShift::Body::Hands::Input { using Gesture = ::SenseShift::Input::BinarySensor; diff --git a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp index e086b894..1f52dbec 100644 --- a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace SenseShift::Body::Hands::Input { class TotalCurl : public ::SenseShift::Input::FloatSensor { diff --git a/lib/io/senseshift/input/analog_threshold.hpp b/lib/io/senseshift/input/sensor/analog_threshold.hpp similarity index 98% rename from lib/io/senseshift/input/analog_threshold.hpp rename to lib/io/senseshift/input/sensor/analog_threshold.hpp index 48397ef4..98b3cb30 100644 --- a/lib/io/senseshift/input/analog_threshold.hpp +++ b/lib/io/senseshift/input/sensor/analog_threshold.hpp @@ -1,6 +1,6 @@ #pragma once -#include "senseshift/input/sensor.hpp" +#include "senseshift/input/sensor/sensor.hpp" #include namespace SenseShift::Input { diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor/sensor.hpp similarity index 100% rename from lib/io/senseshift/input/sensor.hpp rename to lib/io/senseshift/input/sensor/sensor.hpp diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 53229993..fc081636 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 8062ec29..9ed26aad 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #define SS_OG_COLLECT_DATA(FN) \ diff --git a/test/test_battery/main.cpp b/test/test_battery/main.cpp index c563d37c..0274bb36 100644 --- a/test/test_battery/main.cpp +++ b/test/test_battery/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include using namespace SenseShift::Input; diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index e63fb03f..0cd7e5a6 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include using namespace SenseShift::Input; diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp index dc3e77f2..7e7a995f 100644 --- a/test/test_io_filter/main.cpp +++ b/test/test_io_filter/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index 5977f81d..42fd0937 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include using namespace SenseShift::Input; From bbd9c89694ebb838de977217e3bcf60441ae8d20 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 28 Feb 2024 22:37:31 +0400 Subject: [PATCH 09/67] refactor(Arduino): add pin_mode option to DigitalSensor --- .../arduino/input/sensor/digital.hpp | 33 ++++++++----------- .../senseshift/opengloves/autoconfig.hpp | 22 +++++++------ 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index 55ab7158..eede7f38 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -1,31 +1,26 @@ #pragma once -#include +#include #include +#include + namespace SenseShift::Arduino::Input { - template class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { - uint8_t pin_; - public: - DigitalSimpleSensor(const uint8_t pin) : pin_(pin) {} + explicit DigitalSimpleSensor( + const std::uint8_t pin, const std::uint8_t mode = INPUT_PULLUP, const std::uint8_t inverted = LOW + ) : + pin_(pin), mode_(mode), inverted_(inverted){}; - void init() override { pinMode(this->pin_, INPUT_PULLUP); }; + void init() override { pinMode(this->pin_, this->mode_); }; - [[nodiscard]] auto getValue() -> bool override; - }; - - template<> - [[nodiscard]] inline auto DigitalSimpleSensor::getValue() -> bool - { - return digitalRead(this->pin_) == LOW; - } + [[nodiscard]] auto getValue() -> bool override { return digitalRead(this->pin_) == this->inverted_; } - template<> - [[nodiscard]] inline auto DigitalSimpleSensor::getValue() -> bool - { - return digitalRead(this->pin_) == HIGH; - } + private: + std::uint8_t pin_; + std::uint8_t mode_ = INPUT_PULLUP; + std::uint8_t inverted_ = LOW; + }; } // namespace SenseShift::Arduino::Input diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index fc081636..972c65a8 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -196,8 +196,10 @@ #define BUTTON_PINCH_ENABLED false #endif -#define BUTTON_CLASS(PIN, INVERT) \ - ::SenseShift::Input::SimpleSensorDecorator(new ::SenseShift::Arduino::Input::DigitalSimpleSensor(PIN)); +#define BUTTON_CLASS(PIN, MODE, INVERT) \ + ::SenseShift::Input::SimpleSensorDecorator( \ + new ::SenseShift::Arduino::Input::DigitalSimpleSensor(PIN, MODE, (INVERT ? HIGH : LOW)) \ + ); #pragma endregion @@ -348,26 +350,26 @@ namespace SenseShift::OpenGloves::AutoConfig { #endif #if BUTTON_A_ENABLED - auto* button_a = new BUTTON_CLASS(PIN_BUTTON_A, BUTTON_A_INVERT); + auto* button_a = new BUTTON_CLASS(PIN_BUTTON_A, INPUT_PULLUP, BUTTON_A_INVERT); input_sensors.button_a.press = button_a; #endif #if BUTTON_B_ENABLED - auto* button_b = new BUTTON_CLASS(PIN_BUTTON_B, BUTTON_B_INVERT); + auto* button_b = new BUTTON_CLASS(PIN_BUTTON_B, INPUT_PULLUP, BUTTON_B_INVERT); input_sensors.button_b.press = button_b; #endif #if BUTTON_JOYSTICK_ENABLED - auto* button_joystick = new BUTTON_CLASS(PIN_BUTTON_JOYSTICK, BUTTON_JOYSTICK_INVERT); + auto* button_joystick = new BUTTON_CLASS(PIN_BUTTON_JOYSTICK, INPUT_PULLUP, BUTTON_JOYSTICK_INVERT); input_sensors.joystick.press = button_joystick; #endif #if BUTTON_MENU_ENABLED - auto* button_menu = new BUTTON_CLASS(PIN_BUTTON_MENU, BUTTON_MENU_INVERT); + auto* button_menu = new BUTTON_CLASS(PIN_BUTTON_MENU, INPUT_PULLUP, BUTTON_MENU_INVERT); #endif #if BUTTON_CALIBRATE_ENABLED - auto* button_calibrate = new BUTTON_CLASS(PIN_BUTTON_CALIBRATE, BUTTON_CALIBRATE_INVERT); + auto* button_calibrate = new BUTTON_CLASS(PIN_BUTTON_CALIBRATE, INPUT_PULLUP, BUTTON_CALIBRATE_INVERT); input_sensors.button_calibrate.press = button_calibrate; #endif @@ -375,7 +377,7 @@ namespace SenseShift::OpenGloves::AutoConfig { auto* trigger = new Body::Hands::Input::TriggerGesture(index_curl_sensor, GESTURE_TRIGGER_THRESHOLD); input_sensors.trigger.press = trigger; #elif BUTTON_TRIGGER_ENABLED - auto trigger = new BUTTON_CLASS(PIN_BUTTON_TRIGGER, BUTTON_TRIGGER_INVERT); + auto trigger = new BUTTON_CLASS(PIN_BUTTON_TRIGGER, INPUT_PULLUP, BUTTON_TRIGGER_INVERT); #endif #if GESTURE_GRAB_ENABLED && FINGER_INDEX_ENABLED && FINGER_MIDDLE_ENABLED && FINGER_RING_ENABLED && FINGER_PINKY_ENABLED @@ -388,7 +390,7 @@ namespace SenseShift::OpenGloves::AutoConfig { ); input_sensors.grab.press = grab; #elif BUTTON_GRAB_ENABLED - auto* grab = new BUTTON_CLASS(PIN_BUTTON_GRAB, BUTTON_GRAB_INVERT); + auto* grab = new BUTTON_CLASS(PIN_BUTTON_GRAB, INPUT_PULLUP, BUTTON_GRAB_INVERT); #endif #if GESTURE_PINCH_ENABLED && FINGER_THUMB_ENABLED && FINGER_INDEX_ENABLED @@ -398,7 +400,7 @@ namespace SenseShift::OpenGloves::AutoConfig { ); input_sensors.pinch.press = pinch; #elif BUTTON_PINCH_ENABLED - auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, BUTTON_PINCH_INVERT); + auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, INPUT_PULLUP, BUTTON_PINCH_INVERT); #endif return input_sensors; From 1733316f5ee6e72fb7dd35f0d75c695e7d6d29fa Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 28 Feb 2024 22:45:31 +0400 Subject: [PATCH 10/67] feat(Arduino): add digital MUX sensor --- .../arduino/input/sensor/multiplexer.hpp | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp index 52f10d28..53bf8318 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp @@ -8,6 +8,7 @@ #include #include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/input/sensor/digital.hpp" #include #include @@ -56,12 +57,12 @@ namespace SenseShift::Arduino::Input { using MUX_74HC4051Component = Multiplexer<3>; template - class MultiplexedSensor : public AnalogSimpleSensor { + class MultiplexedAnalogSensor : public AnalogSimpleSensor { public: /// \param component The CD74HC4057 Component to use. /// \param pin The SIG pin of the sensor. /// \param channel The channel to read from. - MultiplexedSensor(Multiplexer* component, const std::uint8_t pin_sig, const std::uint8_t channel) : + MultiplexedAnalogSensor(Multiplexer* component, const std::uint8_t pin_sig, const std::uint8_t channel) : component_(component), AnalogSimpleSensor(pin_sig), channel_(channel) { assert(channel < (1 << N) && "Channel out of range"); @@ -84,4 +85,36 @@ namespace SenseShift::Arduino::Input { Multiplexer* component_; const std::uint8_t channel_; }; + + class MultiplexedDigitalSensor : public DigitalSimpleSensor { + public: + /// \param component The CD74HC4057 Component to use. + /// \param pin The SIG pin of the sensor. + /// \param channel The channel to read from. + MultiplexedDigitalSensor( + MUX_CD74HC4057Component* component, const std::uint8_t pin_sig, const std::uint8_t channel + ) : + component_(component), DigitalSimpleSensor(pin_sig), channel_(channel) + { + assert(channel < 16 && "Channel out of range"); + } + + void init() override + { + this->component_->init(); + DigitalSimpleSensor::init(); + } + + [[nodiscard]] auto getValue() -> bool override + { + this->component_->selectChannel(this->channel_); + + return DigitalSimpleSensor::getValue(); + } + + private: + MUX_CD74HC4057Component* component_; + const std::uint8_t channel_; + }; + } // namespace SenseShift::Arduino::Input From 18c5217e78e4f1b4d9fec49d97a7aaf084c4da7d Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 2 Jul 2024 21:03:07 +0400 Subject: [PATCH 11/67] ci(GitHub): upload only cleaned coverage --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6ed30e2..41be53a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -412,6 +412,9 @@ jobs: find ./build/lcov -name 'lcov.info.*' -exec echo -a {} \; | xargs lcov -o ./build/lcov/lcov.info lcov --remove ./build/lcov/lcov.info '/usr/include/*' '*.platformio/*' '*/.pio/*' '*/tool-unity/*' '*/test/*' '*/MockArduino/*' '*/lib/frozen/*' -o ./build/lcov/lcov.info.cleaned + + # delete all except the cleaned file + find ./build/lcov -type f -not -name 'lcov.info.cleaned' -delete - name: Generate HTML report run: genhtml -p $PWD -o ./build/coverage/ --demangle-cpp ./build/lcov/lcov.info.cleaned From 7072ca513cce37adba8d5166b63ce8dce0c3488a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 14 Jul 2024 16:55:50 +0400 Subject: [PATCH 12/67] build(PlatformIO): use arduino-esp32 3.0.0 (#120) * build(PlatformIO): use arduino-esp32 3.0.2 * refactor(Output): use 3.0.0 ledc api * chore(deps): update ESP32Servo to 3.0.0 * refactor(BLE): use Arduino-styled String * ci(GitHub): use new partitions path * ci(Wokwi): hold calibration button longer * feat(Arduino): detach analog output * feat(Arduino): enable WiFi support CC https://github.com/espressif/arduino-esp32/issues/9782#issuecomment-2150947910 * ci(GitHub): cancel previous runs --- .github/workflows/ci.yml | 8 ++++++-- .github/workflows/codeql-analysis.yml | 4 ++++ .github/workflows/lint.yml | 4 ++++ .github/workflows/release.yml | 4 ++++ .wokwi/lucidgloves-prototype4+serial/test.yaml | 5 +++-- ini/bhaptics.ini | 5 +++-- ini/opengloves.ini | 5 +++-- lib/arduino/library.json | 2 +- .../senseshift/arduino/output/ledc.hpp | 16 +++++----------- .../senseshift/bh/ble/connection.cpp | 5 +++-- .../senseshift/bh/ble/connection.hpp | 4 ++++ lib/ble_serial/BLESerial.hpp | 2 +- platformio.ini | 1 + 13 files changed, 42 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41be53a8..86711f05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,10 @@ on: paths-ignore: - "**/*.md" +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build-bhaptics: name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} -D ${{ matrix.nimble_flag }} @@ -131,7 +135,7 @@ jobs: - name: Change memory segments if: matrix.coverage run: | - sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/memory.ld + sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32-libs/esp32/ld/memory.ld sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini - name: Build @@ -271,7 +275,7 @@ jobs: - name: Change memory segments if: matrix.coverage run: | - sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/ld/memory.ld + sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32-libs/esp32/ld/memory.ld sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini - name: Build diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 93b31adf..9263ccb3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,6 +13,10 @@ on: schedule: - cron: '0 16 * * 6' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: analyze: name: Analyze diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 18755c7f..c2ef1716 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -14,6 +14,10 @@ on: paths-ignore: - '**/*.md' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: clang-format: name: clang-format - `${{ matrix.path }}` diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 12fe53c4..8515cd38 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,10 @@ on: paths: - '.github/workflows/release.yml' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: build-bhaptics: runs-on: ubuntu-latest diff --git a/.wokwi/lucidgloves-prototype4+serial/test.yaml b/.wokwi/lucidgloves-prototype4+serial/test.yaml index d3a1f656..ed6807fb 100644 --- a/.wokwi/lucidgloves-prototype4+serial/test.yaml +++ b/.wokwi/lucidgloves-prototype4+serial/test.yaml @@ -3,7 +3,7 @@ version: 1 author: Leonid Meleshin steps: - - delay: 2000ms + - delay: 3000ms # Press calibration button - set-control: @@ -11,8 +11,9 @@ steps: control: pressed value: 1 - - delay: 250ms + - delay: 500ms + # Release calibration button - set-control: part-id: btn3 control: pressed diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index a9dc121b..7bcd9daf 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -1,7 +1,8 @@ [bhaptics] -platform = platformio/espressif32@^6.1.0 +platform = platformio/espressif32@^6.7.0 platform_packages = - platformio/framework-arduinoespressif32@^3.20014.231204 + framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 + framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip framework = arduino board = esp32doit-devkit-v1 upload_speed = 921600 diff --git a/ini/opengloves.ini b/ini/opengloves.ini index 763fa00f..bd89da7e 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -1,7 +1,8 @@ [opengloves] -platform = platformio/espressif32@^6.1.0 +platform = platformio/espressif32@^6.7.0 platform_packages = - platformio/framework-arduinoespressif32@^3.20014.231204 + framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 + framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip framework = arduino board = esp32doit-devkit-v1 upload_speed = 921600 diff --git a/lib/arduino/library.json b/lib/arduino/library.json index b906817b..844417f9 100644 --- a/lib/arduino/library.json +++ b/lib/arduino/library.json @@ -8,6 +8,6 @@ "adafruit/Adafruit PWM Servo Driver Library": "^2.4.0", "adafruit/Adafruit INA219": "^1.2.1", "sparkfun/SparkFun MAX1704x Fuel Gauge Arduino Library": "^1.0.4", - "madhephaestus/ESP32Servo": "^1.1.2" + "madhephaestus/ESP32Servo": "^3.0.0" } } diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp index 6c29efed..064890ba 100644 --- a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -20,13 +20,14 @@ namespace SenseShift::Arduino::Output { { } + ~LedcOutput() override { ledcDetach(this->pin_); } + void init() override { pinMode(this->pin_, OUTPUT); - this->channel_ = findChannel(this->pin_); LOG_D(TAG, "GPIO %d - Setting up Channel %d", this->pin_, this->channel_); - if (ledcSetup(this->channel_, this->analog_frequency_, this->analog_resolution_) == 0) { + if (!ledcAttach(this->pin_, this->analog_frequency_, this->analog_resolution_)) { LOG_E( TAG, "setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency", @@ -35,26 +36,19 @@ namespace SenseShift::Arduino::Output { ); return; } - ledcAttachPin(this->pin_, this->channel_); } - [[nodiscard]] auto getMaxValue() const -> std::uint32_t { return (1 << analog_resolution_) - 1; } + [[nodiscard]] inline auto getMaxValue() const -> std::uint32_t { return (1 << this->analog_resolution_) - 1; } void writeState(const float value) override { const auto duty = static_cast(value * this->getMaxValue()); LOG_V(TAG, "GPIO %d - Writing %d to Channel %d", this->pin_, duty, this->channel_); - ledcWrite(this->channel_, duty); + ledcWrite(this->pin_, duty); }; - protected: - static auto findChannel(std::uint8_t /*pin*/) -> std::int8_t { return CHANNELS++; } - private: - static inline std::uint8_t CHANNELS = 0; - std::uint8_t pin_; - std::int8_t channel_ = -1; std::uint8_t analog_resolution_; std::uint32_t analog_frequency_; }; diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 0fd40054..f926a314 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -103,9 +103,10 @@ namespace SenseShift::BH::BLE { void onWrite(BLECharacteristic* pCharacteristic) override { - std::string value = pCharacteristic->getValue(); + auto value = pCharacteristic->getValue(); + std::string valueStr(value.begin(), value.end()); - this->motorTransformer(value); + this->motorTransformer(valueStr); }; }; diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index c35810b4..ebba352b 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -20,7 +20,11 @@ namespace SenseShift::BH::BLE { struct ConnectionConfig { static constexpr size_t SN_LENGTH = 10; +#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true std::string deviceName; +#else + String deviceName; +#endif uint16_t appearance; uint8_t serialNumber[SN_LENGTH]; }; diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp index 090ecb75..de7c1d7b 100644 --- a/lib/ble_serial/BLESerial.hpp +++ b/lib/ble_serial/BLESerial.hpp @@ -237,7 +237,7 @@ class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks { return; } - std::string rxValue = pCharacteristic->getValue(); + auto rxValue = pCharacteristic->getValue(); for (int i = 0; i < rxValue.length(); i++) { bleSerial->m_receiveBuffer.push(rxValue[i]); } diff --git a/platformio.ini b/platformio.ini index fb8423bb..cd54ac00 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,6 +30,7 @@ build_flags = ; -D DEBUG_ESP_PORT=Serial ; -D SS_BATTERY_ENABLED=true ; -D SS_BLE_USE_NIMBLE=true + -D SOC_WIFI_SUPPORTED=1 build_src_filter = +<*> From df8bbc4b2d97c90504cb117eecb694c2dbaa62fe Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 19 Jul 2024 01:02:10 +0400 Subject: [PATCH 13/67] refactor(BLE): use library for BLE Serial --- lib/ble_serial/BLESerial.hpp | 287 ------------------ .../senseshift/opengloves/autoconfig.hpp | 2 +- .../library.json | 9 +- .../opengloves/transport/stream.hpp | 9 +- platformio.ini | 1 + 5 files changed, 10 insertions(+), 298 deletions(-) delete mode 100644 lib/ble_serial/BLESerial.hpp rename lib/{ble_serial => opengloves_arduino}/library.json (56%) diff --git a/lib/ble_serial/BLESerial.hpp b/lib/ble_serial/BLESerial.hpp deleted file mode 100644 index de7c1d7b..00000000 --- a/lib/ble_serial/BLESerial.hpp +++ /dev/null @@ -1,287 +0,0 @@ -#pragma once -#ifndef BLESERIAL_H -#define BLESERIAL_H - -#include -#include -#include -#include -#include - -#include - -#include - -#define BLESERIAL_ATTRIBUTE_MAX_VALUE_LENGTH 20 -#define BLESERIAL_RECEIVE_BUFFER_SIZE 256 - -class BLESerialCharacteristicCallbacks; -class BLESerialServerCallbacks; - -class BLESerial : public Stream { - friend class BLESerialCharacteristicCallbacks; - friend class BLESerialServerCallbacks; - - public: - inline static const char* SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"; - inline static const char* RX_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"; - inline static const char* TX_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"; - - BLESerial() : m_receiveBuffer() {} - - virtual int available() override { return m_receiveBuffer.getLength(); } - - virtual int peek() override { return m_receiveBuffer.get(0); } - - virtual int read() override { return m_receiveBuffer.pop(); } - - virtual size_t write(const uint8_t* buffer, size_t bufferSize) override - { - if (this->m_pTxCharacteristic == nullptr || !this->connected()) { - return 0; - } - - this->m_pTxCharacteristic->setValue(const_cast(buffer), bufferSize); - // this->flush(); - - return bufferSize; - } - - virtual size_t write(uint8_t byte) override - { - if (this->m_pTxCharacteristic == nullptr || !this->connected()) { - return 0; - } - - this->m_pTxCharacteristic->setValue(&byte, 1); - // this->flush(); - - return 1; - } - - virtual void flush(void) override { this->m_pTxCharacteristic->notify(true); } - - /** - * Begin BLE serial. This will create and start BLE server, service and characteristics. - * - * @note This will manage the BLE server, service and characteristics. If you want to manage them yourself, use the - * other begin(). - * - * @param deviceName Name of the BLE device - * @param serviceUuid UUID of the BLE service - * @param rxUuid UUID of the BLE characteristic for receiving data - * @param txUuid UUID of the BLE characteristic for transmitting data - */ - void begin( - const char* deviceName, - const char* serviceUuid = SERVICE_UUID, - const char* rxUuid = RX_UUID, - const char* txUuid = TX_UUID - ); - - /** - * Begin BLE serial. This will create and start BLE service and characteristics. - * - * @note This will manage the BLE service and characteristics. If you want to manage them yourself, use the other - * begin(). - * - * @param pServer BLE server instance - * @param serviceUuid UUID of the BLE service - * @param rxUuid UUID of the BLE characteristic for receiving data - * @param txUuid UUID of the BLE characteristic for transmitting data - */ - void begin( - BLEServer* pServer, - const char* serviceUuid = SERVICE_UUID, - const char* rxUuid = RX_UUID, - const char* txUuid = TX_UUID - ) - { - BLEService* pService = pServer->getServiceByUUID(serviceUuid); - if (pService == nullptr) { - log_d("Creating BLE service with UUID '%s'", serviceUuid); - pService = pServer->createService(serviceUuid); - } else { - log_w("BLE service with UUID '%s' already exists", serviceUuid); - } - - // Store the service so we know if we're managing it - this->m_pService = pService; - - this->begin(pService, rxUuid, txUuid); - - pService->start(); - log_d("Started BLE service"); - } - - /** - * Begin BLE serial. This will create and start BLE characteristics. - * - * @note If you want to create characteristics yourself, use the other begin(). - * - * @param pService BLE service instance - * @param rxUuid UUID of the BLE characteristic for receiving data - * @param txUuid UUID of the BLE characteristic for transmitting data - */ - void begin(BLEService* pService, const char* rxUuid = RX_UUID, const char* txUuid = TX_UUID) - { - auto pRxCharacteristic = pService->getCharacteristic(rxUuid); - if (pRxCharacteristic == nullptr) { - log_d("Creating BLE characteristic with UUIDs '%s' (RX)", rxUuid); - pRxCharacteristic = pService->createCharacteristic(rxUuid, BLECharacteristic::PROPERTY_WRITE_NR); - } else { - log_w("BLE characteristic with UUID '%s' (RX) already exists", rxUuid); - } - - auto pTxCharacteristic = pService->getCharacteristic(txUuid); - if (pTxCharacteristic == nullptr) { - log_d("Creating BLE characteristic with UUIDs '%s' (TX)", txUuid); - pTxCharacteristic = pService->createCharacteristic( - txUuid, - BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY - ); - } else { - log_w("BLE characteristic with UUID '%s' (TX) already exists", txUuid); - } - - this->begin(pRxCharacteristic, pTxCharacteristic); - } - - /** - * Begin BLE serial. This will setup the BLE characteristics. - * - * @param pServer BLE server instance - * @param pRxCharacteristic BLE characteristic instance for receiving data - * @param pTxCharacteristic BLE characteristic instance for transmitting data - */ - void begin(BLECharacteristic* pRxCharacteristic, BLECharacteristic* pTxCharacteristic); - - void end() - { - if (this->m_pService != nullptr) { - this->m_pService->stop(); - } - - if (this->m_pServer != nullptr) { - this->m_pServer->getAdvertising()->stop(); - } - - this->m_pServer = nullptr; - } - - bool connected() { return m_pServer != nullptr && m_pServer->getConnectedCount() > 0; } - - BLECharacteristic* getRxCharacteristic() { return m_pRxCharacteristic; } - - BLECharacteristic* getTxCharacteristic() { return m_pTxCharacteristic; } - - private: - BLESerial(BLESerial const& other) = delete; // disable copy constructor - void operator=(BLESerial const& other) = delete; // disable assign constructor - - SenseShift::RingBuffer m_receiveBuffer; - - /** - * BLE server instance - * @note This is only used if the BLESerial instance is managing the BLE server - */ - BLEServer* m_pServer = nullptr; - - /** - * BLE service instance - * @note This is only used if the BLESerial instance is managing the BLE service - */ - BLEService* m_pService = nullptr; - - /** - * BLE characteristic instance for receiving data - */ - BLECharacteristic* m_pRxCharacteristic = nullptr; - - /** - * BLE characteristic instance for transmitting data - */ - BLECharacteristic* m_pTxCharacteristic = nullptr; -}; - -class BLESerialServerCallbacks : public BLEServerCallbacks { - public: - BLESerialServerCallbacks(BLESerial* bleSerial) : bleSerial(bleSerial) {} - - void onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t* param) override - { - uint16_t conn_id = param->connect.conn_id; - pServer->updatePeerMTU(conn_id, BLESERIAL_ATTRIBUTE_MAX_VALUE_LENGTH); - } - - void onDisconnect(BLEServer* pServer, esp_ble_gatts_cb_param_t* param) override - { - auto* pAdvertising = pServer->getAdvertising(); - if (pAdvertising == nullptr) { - return; - } - pAdvertising->start(); - } - - private: - BLESerial* bleSerial; -}; - -class BLESerialCharacteristicCallbacks : public BLECharacteristicCallbacks { - public: - BLESerialCharacteristicCallbacks(BLESerial* bleSerial) : bleSerial(bleSerial) {} - - void onWrite(BLECharacteristic* pCharacteristic) - { - if (pCharacteristic != bleSerial->m_pRxCharacteristic) { - return; - } - - auto rxValue = pCharacteristic->getValue(); - for (int i = 0; i < rxValue.length(); i++) { - bleSerial->m_receiveBuffer.push(rxValue[i]); - } - } - - private: - BLESerial* bleSerial; -}; - -void BLESerial::begin(const char* deviceName, const char* serviceUuid, const char* rxUuid, const char* txUuid) -{ - // Create the BLE Device - log_d("Initializing BLE device with name '%s'", deviceName); - BLEDevice::init(deviceName); - - log_d("Creating BLE server"); - BLEServer* pServer = BLEDevice::createServer(); - pServer->setCallbacks(new BLESerialServerCallbacks(this)); - - // Store the server so we know if we're managing it - this->m_pServer = pServer; - - this->begin(pServer, serviceUuid, rxUuid, txUuid); - - BLEAdvertising* pAdvertising = pServer->getAdvertising(); - pAdvertising->start(); - log_d("Started BLE advertising"); -} - -void BLESerial::begin(BLECharacteristic* pRxCharacteristic, BLECharacteristic* pTxCharacteristic) -{ - // Store the characteristics so we know if we're managing them - this->m_pRxCharacteristic = pRxCharacteristic; - this->m_pTxCharacteristic = pTxCharacteristic; - - // this->m_pRxCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENCRYPTED); - this->m_pRxCharacteristic->addDescriptor(new BLE2902()); - this->m_pRxCharacteristic->setCallbacks(new BLESerialCharacteristicCallbacks(this)); - this->m_pRxCharacteristic->setWriteProperty(true); - - // this->m_pTxCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED); - this->m_pTxCharacteristic->addDescriptor(new BLE2902()); - this->m_pTxCharacteristic->setReadProperty(true); - this->m_pTxCharacteristic->setNotifyProperty(true); -} - -#endif // BLESERIAL_H diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 972c65a8..77a63dd2 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -465,7 +465,7 @@ namespace SenseShift::OpenGloves::AutoConfig { pBtSerial->begin(name.c_str()); return new BluetoothSerialTransport(*pBtSerial); #elif OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL // Bluetooth Low Energy - BLESerial* pBleSerial = new BLESerial(); + BLESerial<>* pBleSerial = new BLESerial<>(); pBleSerial->begin(name.c_str()); return new BLESerialTransport(*pBleSerial); #endif diff --git a/lib/ble_serial/library.json b/lib/opengloves_arduino/library.json similarity index 56% rename from lib/ble_serial/library.json rename to lib/opengloves_arduino/library.json index f4605a77..0fd9f21b 100644 --- a/lib/ble_serial/library.json +++ b/lib/opengloves_arduino/library.json @@ -1,9 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", - "name": "BLE Serial", - "description": "Arduino BLE Serial Stream library", "frameworks": "arduino", - "platforms": [ - "espressif32" - ] + "dependencies": { + "Serial_BLE": "^0.1.0", + "BLE": "*" + } } diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index 12d413e2..31c30c7d 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -2,9 +2,7 @@ #include -#include - -#include +#include #include #include #include @@ -89,15 +87,16 @@ namespace SenseShift::OpenGloves { } }; + template> class BLESerialTransport : public IStreamTransport { public: - explicit BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; + explicit BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; void init() override {} auto isReady() -> bool override { - auto* serial = static_cast(this->channel); + auto* serial = static_cast*>(this->channel); return serial->connected(); } }; diff --git a/platformio.ini b/platformio.ini index cd54ac00..fa73afc7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -38,6 +38,7 @@ build_src_filter = lib_deps = https://github.com/senseshift/frozen.git#feature/platformio + https://github.com/senseshift/arduino-ble-serial.git#v1.1.1 [env] build_flags = ${common.build_flags} From dc6d36ae1cb8598c05d93d63a22a186d695f0708 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 19 Jul 2024 01:07:54 +0400 Subject: [PATCH 14/67] chore: change NimBLE flag name --- .github/scripts/get_firmware_name.sh | 2 +- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 2 +- include/config/bluetooth.h | 4 ++-- lib/bhaptics_ble/senseshift/bh/ble/connection.cpp | 10 +++++----- lib/bhaptics_ble/senseshift/bh/ble/connection.hpp | 4 ++-- platformio.ini | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh index b759981f..97e654e0 100755 --- a/.github/scripts/get_firmware_name.sh +++ b/.github/scripts/get_firmware_name.sh @@ -8,7 +8,7 @@ getBhapticsName() { echo "::debug::Getting bHaptics name for $target" echo "::debug::Flags are $flags" - if [[ $flags =~ SS_BLE_USE_NIMBLE=true ]]; then + if [[ $flags =~ SS_USE_NIMBLE=true ]]; then echo "::debug::Nimble is enabled, appending +nimble to the target" target="$target+nimble" fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 86711f05..e7aae899 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: - bhaptics_tactvisor - bhaptics_tactglove_right battery_flag: [ SS_BATTERY_ENABLED=true ] - nimble_flag: [ SS_BLE_USE_NIMBLE=false ] + nimble_flag: [ SS_USE_NIMBLE=false ] coverage: [ false ] include: @@ -48,17 +48,17 @@ jobs: os: ubuntu-latest coverage: true battery_flag: SS_BATTERY_ENABLED=true - nimble_flag: SS_BLE_USE_NIMBLE=true + nimble_flag: SS_USE_NIMBLE=true # - target: bhaptics_tactsuit_x40 # os: ubuntu-latest # coverage: true # battery_flag: SS_BATTERY_ENABLED=true - # nimble_flag: SS_BLE_USE_NIMBLE=false + # nimble_flag: SS_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false battery_flag: SS_BATTERY_ENABLED=true - nimble_flag: SS_BLE_USE_NIMBLE=true + nimble_flag: SS_USE_NIMBLE=true steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8515cd38..eed4aaa9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -39,7 +39,7 @@ jobs: battery_flag: - SS_BATTERY_ENABLED=true nimble_flag: - - SS_BLE_USE_NIMBLE=true + - SS_USE_NIMBLE=true steps: - uses: actions/checkout@v4 diff --git a/include/config/bluetooth.h b/include/config/bluetooth.h index 79ac1c95..714548bc 100644 --- a/include/config/bluetooth.h +++ b/include/config/bluetooth.h @@ -11,6 +11,6 @@ } #endif -#ifndef SS_BLE_USE_NIMBLE -#define SS_BLE_USE_NIMBLE false +#ifndef SS_USE_NIMBLE +#define SS_USE_NIMBLE false #endif diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index f926a314..7de8c70a 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -6,7 +6,7 @@ #include -#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true +#if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true // BLE2902 not needed: https://github.com/h2zero/NimBLE-Arduino/blob/release/1.4/docs/Migration_guide.md#descriptors #define PROPERTY_READ NIMBLE_PROPERTY::READ @@ -77,7 +77,7 @@ namespace SenseShift::BH::BLE { ); }; -#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true +#if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override #else void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) override @@ -143,7 +143,7 @@ namespace SenseShift::BH::BLE { this->bleServer->getAdvertising()->setScanResponseData(*scanResponseData); // Each characteristic needs 2 handles and descriptor 1 handle. -#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true +#if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID); #else this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID, 30, 0); @@ -195,7 +195,7 @@ namespace SenseShift::BH::BLE { | PROPERTY_NOTIFY // for whatever reason, it have to be writable, otherwise Desktop app crashes ); -#if !defined(SS_BLE_USE_NIMBLE) || SS_BLE_USE_NIMBLE != true +#if !defined(SS_USE_NIMBLE) || SS_USE_NIMBLE != true batteryChar->addDescriptor(new BLE2902()); #endif @@ -222,7 +222,7 @@ namespace SenseShift::BH::BLE { ); monitorChar->setCallbacks(new LogOutputCharCallbacks()); -#if !defined(SS_BLE_USE_NIMBLE) || SS_BLE_USE_NIMBLE != true +#if !defined(SS_USE_NIMBLE) || SS_USE_NIMBLE != true monitorChar->addDescriptor(new BLE2902()); #endif diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index ebba352b..a572f63b 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -10,7 +10,7 @@ #include #include -#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true +#if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true #include #else #include @@ -20,7 +20,7 @@ namespace SenseShift::BH::BLE { struct ConnectionConfig { static constexpr size_t SN_LENGTH = 10; -#if defined(SS_BLE_USE_NIMBLE) && SS_BLE_USE_NIMBLE == true +#if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true std::string deviceName; #else String deviceName; diff --git a/platformio.ini b/platformio.ini index fa73afc7..bdcc8457 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ build_flags = ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial ; -D SS_BATTERY_ENABLED=true -; -D SS_BLE_USE_NIMBLE=true +; -D SS_USE_NIMBLE=true -D SOC_WIFI_SUPPORTED=1 build_src_filter = From 1616eb2e435642eb087e58d798c9a71200303111 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 19 Jul 2024 01:24:28 +0400 Subject: [PATCH 15/67] chore(OpenGloves): don't use deprecated API --- .../senseshift/opengloves/transport/stream.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index 31c30c7d..f25ada40 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -115,7 +115,7 @@ namespace SenseShift::OpenGloves { } this->m_server.begin(); - this->channel = new WiFiClient(this->m_server.available()); + this->channel = new WiFiClient(this->m_server.accept()); } auto isReady() -> bool override From 07e1295e58cec0e2757a29ed2c8557bcf042b990 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 19 Jul 2024 01:37:27 +0400 Subject: [PATCH 16/67] ci(GitHub): use correct flag for OpenGloves transport --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7aae899..ffcdcac1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -174,8 +174,8 @@ jobs: - indexer-cs - indexer-csf comm_flag: - - COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_SERIAL - - COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BTSERIAL + - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL + - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL coverage: [ false ] include: @@ -193,11 +193,11 @@ jobs: coverage: true - os: ubuntu-latest target: indexer-csf - comm_flag: COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BTSERIAL + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL coverage: true - os: ubuntu-latest target: indexer-csf - comm_flag: COMMUNICATION_PROTOCOL=OPENGLOVES_COMM_BLESERIAL + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL coverage: true steps: From 92b062ec56074353e5620c93755486e6b95886da Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 27 Jul 2024 03:36:54 +0400 Subject: [PATCH 17/67] refactor(OpenGloves): use `opengloves-lib` for encoding --- .../mode_configs/opengloves/opengloves.cpp | 3 +- lib/opengloves/library.json | 7 + lib/opengloves/opengloves/opengloves.cpp | 242 --------- lib/opengloves/opengloves/opengloves.hpp | 462 ------------------ .../senseshift/opengloves/opengloves.hpp | 4 +- .../opengloves/opengloves_component.hpp | 20 +- .../opengloves/opengloves_plotter.hpp | 4 +- platformio.ini | 5 +- test/test_opengloves_alpha_encoding/main.cpp | 224 --------- 9 files changed, 30 insertions(+), 941 deletions(-) create mode 100644 lib/opengloves/library.json delete mode 100644 lib/opengloves/opengloves/opengloves.cpp delete mode 100644 lib/opengloves/opengloves/opengloves.hpp delete mode 100644 test/test_opengloves_alpha_encoding/main.cpp diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index aa8a0ee5..cb285676 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -3,11 +3,12 @@ #include using namespace SenseShift::OpenGloves; +namespace og = ::opengloves; void setupMode() { auto* communication = AutoConfig::createTransport(); - auto* encoding = new og::AlphaEncoder(); + auto* encoding = new og::AlphaEncoding(); auto input_sensors = AutoConfig::createInput(); diff --git a/lib/opengloves/library.json b/lib/opengloves/library.json new file mode 100644 index 00000000..3fb3970b --- /dev/null +++ b/lib/opengloves/library.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "frameworks": "arduino", + "dependencies": { + "opengloves-lib": "*" + } +} diff --git a/lib/opengloves/opengloves/opengloves.cpp b/lib/opengloves/opengloves/opengloves.cpp deleted file mode 100644 index 010c0204..00000000 --- a/lib/opengloves/opengloves/opengloves.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include "opengloves/opengloves.hpp" - -#include -#include -#include -#include -#include -#include - -namespace og { - - inline auto ifloor(float x) -> int - { - return static_cast(x); - } - - auto AlphaEncoder::encode_input(const InputData& input, char* buffer, size_t length) const -> size_t - { - if (std::holds_alternative(input)) { - const auto& info = std::get(input); - - const auto& keyFirmwareVersion = AlphaEncoder::INFO_FIRMWARE_VERSION_KEY; - const auto& keyDeviceType = AlphaEncoder::INFO_DEVICE_TYPE_KEY; - const auto& keyHand = AlphaEncoder::INFO_HAND_KEY; - - return snprintf( - buffer, - length, - "%s%u%s%u%s%u\n", - keyFirmwareVersion, - info.firmware_version, - keyDeviceType, - info.device_type, - keyHand, - info.hand - ); - } - - if (std::holds_alternative(input)) { - const auto peripheral = std::get(input); - auto written = 0; - - const auto& curls = peripheral.curl.fingers; - const auto& splays = peripheral.splay.fingers; -#ifdef OG_ENCODE_FAST - for (auto i = 0; i < curls.size(); i++) { - const auto& finger = curls[i]; - const auto& finger_curl = finger.curl_total; - - written += - snprintf(buffer + written, length - written, "%c%u", 'A' + i, ifloor(finger_curl * MAX_ANALOG_VALUE)); - } -#else - for (auto i = 0; i < curls.size(); i++) { - const auto& finger_curl = curls[i]; - const auto& finger_splay = splays[i]; - const auto finger_alpha_key = 'A' + i; - - written += snprintf( - buffer + written, - length - written, - "%c%u", - finger_alpha_key, - ifloor(finger_curl.curl_total * MAX_ANALOG_VALUE) - ); - - if (finger_splay > 0.0F) { - written += snprintf( - buffer + written, - length - written, - "(%cB)%u", - finger_alpha_key, - ifloor(finger_splay * MAX_ANALOG_VALUE) - ); - } - - const auto& joints = finger_curl.curl; - for (auto j = 1; j < joints.size(); j++) { - const auto& joint = joints[j]; - const auto joint_alpha_key = 'A' + j; - - if (joint == 0.0F) { - continue; - } - - written += snprintf( - buffer + written, - length - written, - "(%cA%c)%u", - finger_alpha_key, - joint_alpha_key, - ifloor(joint * MAX_ANALOG_VALUE) - ); - } - } -#endif - if (peripheral.joystick.x != 0.0F) { - written += - snprintf(buffer + written, length - written, "F%u", ifloor(peripheral.joystick.x * MAX_ANALOG_VALUE)); - } - if (peripheral.joystick.y != 0.0F) { - written += - snprintf(buffer + written, length - written, "G%u", ifloor(peripheral.joystick.y * MAX_ANALOG_VALUE)); - } - if (peripheral.joystick.press) { - written += snprintf(buffer + written, length - written, "H"); - } - - const auto& buttons = peripheral.buttons; - for (auto i = 0; i < buttons.size(); i++) { - const auto& button = buttons[i]; - if (button.press) { - const auto& buttonKey = AlphaEncoder::BUTTON_ALPHA_KEY[i]; - written += snprintf(buffer + written, length - written, "%c", buttonKey); - } - } - - const auto& analog_buttons = peripheral.analog_buttons; - for (auto i = 0; i < analog_buttons.size(); i++) { - const auto& button = analog_buttons[i]; - if (button.press) { - const auto& buttonKey = AlphaEncoder::ANALOG_BUTTON_ALPHA_KEY[i]; - written += snprintf(buffer + written, length - written, "%c", buttonKey); - } - } - - // Add newline and null terminator - written += snprintf(buffer + written, length - written, "\n"); - - return written; - } - - return 0; - } - - auto AlphaEncoder::decode_output(const char* data, size_t length) const -> OutputData - { - if (length == 0) { - return OutputInvalid{}; - } - - const auto commands = split_to_map(data, length); - if (commands.empty()) { - return OutputInvalid{}; - } - - // We assume all commands are for ffb, if there is any ffb command - const auto& thumb_curl = commands.find("A"); - const auto& index_curl = commands.find("B"); - const auto& middle_curl = commands.find("C"); - const auto& ring_curl = commands.find("D"); - const auto& pinky_curl = commands.find("E"); - - if (thumb_curl != commands.end() || index_curl != commands.end() || middle_curl != commands.end() || - ring_curl != commands.end() || pinky_curl != commands.end() - ) { - OutputForceFeedbackData ffb{}; - - if (thumb_curl != commands.end()) { - ffb.thumb = std::stof(thumb_curl->second) / MAX_ANALOG_VALUE; - } - - if (index_curl != commands.end()) { - ffb.index = std::stof(index_curl->second) / MAX_ANALOG_VALUE; - } - - if (middle_curl != commands.end()) { - ffb.middle = std::stof(middle_curl->second) / MAX_ANALOG_VALUE; - } - - if (ring_curl != commands.end()) { - ffb.ring = std::stof(ring_curl->second) / MAX_ANALOG_VALUE; - } - - if (pinky_curl != commands.end()) { - ffb.pinky = std::stof(pinky_curl->second) / MAX_ANALOG_VALUE; - } - - return ffb; - } - - // const auto& haptics_frequency = commands.find("F"); - // if (haptics_frequency != commands.end()) { - // OutputHaptics haptics{}; - // return haptics; - // } - - return OutputInvalid{}; - } - - /// Splits the input data into a map of commands and their respective values. - /// - /// Example: `A100(AB)200B300(BB)400C500\n` -> `{"A": "100", "(AB)": "200", "B": "300", "(BB)": "400", "C": "500"}` - auto AlphaEncoder::split_to_map(const char* data, size_t length) const -> std::map - { - std::map result{}; - - // Start at the beginning of the data - size_t command_start = 0; - for (size_t i = 0; i < length; i++) { - const auto& current_char = data[i]; - - // Start a new command if the character is non-numeric or an opening parenthesis - // and previous character is a numeric character - const bool is_command_start = ((isdigit(current_char)) == 0) || current_char == '('; - const bool prev_is_digit = isdigit(data[i - 1]) != 0; - if (is_command_start && i > 0 && prev_is_digit) { - split_command(data, command_start, i, result); - command_start = i; - } - } - - // Add the last command - split_command(data, command_start, length, result); - - return result; - } - - void AlphaEncoder::split_command( - const char* data, size_t start, size_t length, std::map& commands - ) const - { - const std::string current_command = std::string(data + start, length - start); - - if (current_command.empty()) { - return; - } - - const size_t split_index = current_command.find_first_of("0123456789"); - - // If there is no numeric value, the command is empty (likely a binary command) - if (split_index == std::string::npos) { - commands[current_command] = ""; - return; - } - - const std::string command = current_command.substr(0, split_index); - const std::string value = current_command.substr(split_index, current_command.length() - split_index); - - commands[command] = value; - } -} // namespace og \ No newline at end of file diff --git a/lib/opengloves/opengloves/opengloves.hpp b/lib/opengloves/opengloves/opengloves.hpp deleted file mode 100644 index e6d708c7..00000000 --- a/lib/opengloves/opengloves/opengloves.hpp +++ /dev/null @@ -1,462 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef ARDUINO -#include -#endif // ARDUINO - -#ifdef OG_USE_FROZEN -#include -#include -#endif - -#ifndef OG_BUFFER_SIZE -#define OG_BUFFER_SIZE 256 -#endif // OG_BUFFER_SIZE - -namespace og { - using HandIndex = std::uint8_t; - enum Hand : HandIndex { - Hand_Left, - Hand_Right, - }; - - using DeviceTypeIndex = std::uint8_t; - enum DeviceType : DeviceTypeIndex { - DeviceType_LucidGloves, - }; - - template - union InputFingerCurl { - /// Access the curl as an array. - std::array curl; // NOLINT(*-magic-numbers): I'm sure our finger aren't changing anytime soon - - union { - /// The total curl of the finger. - /// Only use it if you do not use per-joint tracking. - Tf curl_total; - - /// Access the individual curl joints. - struct { - Tf curl_joint0; - Tf curl_joint1; - Tf curl_joint2; - Tf curl_joint3; - }; - }; - - auto operator==(const InputFingerCurl& other) const -> bool - { - return this->curl_joint0 == other.curl_joint0 && this->curl_joint1 == other.curl_joint1 - && this->curl_joint2 == other.curl_joint2 && this->curl_joint3 == other.curl_joint3; - } - }; - using InputFingerCurlData = InputFingerCurl; - - template - union InputFinger { - std::array fingers; // NOLINT(*-magic-numbers): We aren't going to grow any new fingers soon tbh - struct { - Tp thumb; - Tp index; - Tp middle; - Tp ring; - - union { - Tp pinky; - Tp little; - }; - }; - - auto operator==(const InputFinger& other) const -> bool - { - return this->thumb == other.thumb && this->index == other.index && this->middle == other.middle - && this->ring == other.ring && this->pinky == other.pinky; - } - }; - using InputFingerData = InputFinger; - - template - struct InputJoystick { - Tf x, y; - Tb press; - }; - using InputJoystickData = InputJoystick; - - template - struct InputButton { - Tb press; - // bool touch; - }; - using InputButtonData = InputButton; - - template - struct InputAnalogButton : public InputButton { - Tf value; - }; - using InputAnalogButtonData = InputAnalogButton; - - /// Input data structure. - /// - /// I know, it is not the prettiest one, but we need this type of punning to efficiently encode/decode the data - template - struct InputPeripheral { - template< - typename U = Tf, - typename V = Tb, - std::enable_if_t && std::is_same_v, bool> = true> - InputPeripheral() - { - this->curl.fingers = { { - { 0.0F, 0.0F, 0.0F, 0.0F }, - { 0.0F, 0.0F, 0.0F, 0.0F }, - { 0.0F, 0.0F, 0.0F, 0.0F }, - { 0.0F, 0.0F, 0.0F, 0.0F }, - { 0.0F, 0.0F, 0.0F, 0.0F }, - } }; - this->splay.fingers = { 0.0F, 0.0F, 0.0F, 0.0F, 0.0F }; - this->joystick = { 0.0F, 0.0F, false }; - this->buttons = { { false, false, false, false, false } }; - this->analog_buttons = { { { false, 0.0F }, { false, 0.0F } } }; - } - - template< - typename U = Tf, - typename V = Tb, - std::enable_if_t && std::is_pointer_v, bool> = true> - InputPeripheral() - { - this->curl.fingers = { { - { nullptr, nullptr, nullptr, nullptr }, - { nullptr, nullptr, nullptr, nullptr }, - { nullptr, nullptr, nullptr, nullptr }, - { nullptr, nullptr, nullptr, nullptr }, - { nullptr, nullptr, nullptr, nullptr }, - } }; - this->splay.fingers = { nullptr, nullptr, nullptr, nullptr, nullptr }; - this->joystick = { nullptr, nullptr, nullptr }; - this->buttons = { { nullptr, nullptr, nullptr, nullptr, nullptr } }; - this->analog_buttons = { { { nullptr, nullptr }, { nullptr, nullptr } } }; - } - - InputFinger> curl; - InputFinger splay; - - InputJoystick joystick; - - union { - /// Buttons as array. - /// MUST be the same length as the struct below - std::array, 5> buttons; // NOLINT(*-magic-numbers) We keep it here for clarity - - struct { - InputButton button_a; - InputButton button_b; - InputButton button_menu; - InputButton button_calibrate; - InputButton pinch; - }; - }; - - union { - std::array, 2> analog_buttons; - struct { - InputAnalogButton trigger; - InputAnalogButton grab; - }; - }; - }; - using InputPeripheralData = InputPeripheral; - - struct InputInfoData { - Hand hand; - DeviceType device_type; - - unsigned int firmware_version; - }; - - using InputData = std::variant; - - template - using OutputForceFeedback = InputFinger; - using OutputForceFeedbackData = OutputForceFeedback; - - template - struct OutputHaptics { - Tf frequency; - Tf duration; - Tf amplitude; - - auto operator==(const OutputHaptics& other) const -> bool - { - return frequency == other.frequency && duration == other.duration && amplitude == other.amplitude; - } - }; - using OutputHapticsData = OutputHaptics; - - class OutputInvalid { - auto operator==(const OutputInvalid& /*unused*/) const -> bool { return true; } - }; - using OutputData = std::variant; - - class IEncoder { - public: - [[nodiscard]] virtual auto encode_input(const InputData& input, char* buffer, size_t length) const - -> size_t = 0; - - [[nodiscard]] auto encode_input(const InputData& input) const -> std::string - { - std::string buffer; - buffer.resize(OG_BUFFER_SIZE); - - const auto length = this->encode_input(input, buffer.data(), buffer.length()); - buffer.resize(length); - - return buffer; - } - - [[nodiscard]] virtual auto decode_output(const char* data, size_t length) const -> OutputData = 0; - - [[nodiscard]] inline auto decode_output(const std::vector& data) const -> OutputData - { - return this->decode_output(data.data(), data.size()); - } - - [[nodiscard]] inline auto decode_output(const std::string& data) const -> OutputData - { - return this->decode_output(data.data(), data.length()); - } - -#ifdef ARDUINO - [[nodiscard]] inline auto decode_output(const String& data) const -> OutputData - { - return this->decode_output(data.c_str(), data.length()); - } -#endif // ARDUINO - }; - - class AlphaEncoder : public IEncoder { - public: - using CommandIndex = std::uint8_t; - enum Command : CommandIndex { - FingerThumb_CurlTotal, - FingerThumb_Splay, - FingerThumb_CurlJoint0, - FingerThumb_CurlJoint1, - FingerThumb_CurlJoint2, - FingerThumb_CurlJoint3 [[maybe_unused]], - - FingerIndex_CurlTotal, - FingerIndex_Splay, - FingerIndex_CurlJoint0, - FingerIndex_CurlJoint1, - FingerIndex_CurlJoint2, - FingerIndex_CurlJoint3, - - FingerMiddle_CurlTotal, - FingerMiddle_Splay, - FingerMiddle_CurlJoint0, - FingerMiddle_CurlJoint1, - FingerMiddle_CurlJoint2, - FingerMiddle_CurlJoint3, - - FingerRing_CurlTotal, - FingerRing_Splay, - FingerRing_CurlJoint0, - FingerRing_CurlJoint1, - FingerRing_CurlJoint2, - FingerRing_CurlJoint3, - - FingerPinky_CurlTotal, - FingerPinky_Splay, - FingerPinky_CurlJoint0, - FingerPinky_CurlJoint1, - FingerPinky_CurlJoint2, - FingerPinky_CurlJoint3, - - MainJoystick_X, - MainJoystick_Y, - MainJoystick_Click, - - ButtonA_Click, - ButtonB_Click, - ButtonMenu_Click, - ButtonCalibrate_Click, - - GestureTrigger_Value, - GestureTrigger_Click, - - GestureGrab_Click, - - GesturePinch_Click, - - Info, - Info_StartStreaming, - Info_StopStreaming, - Info_FirmwareVersion, - Info_DeviceType, - Info_Hand, - - Haptics_Frequency, - Haptics_Duration, - Haptics_Amplitude, - }; - - inline static constexpr const char* INFO_FIRMWARE_VERSION_KEY = "(ZV)"; - inline static constexpr const char* INFO_DEVICE_TYPE_KEY = "(ZG)"; - inline static constexpr const char* INFO_HAND_KEY = "(ZH)"; - - inline static constexpr const uint16_t MAX_ANALOG_VALUE = 4095; - -#ifdef OG_USE_FROZEN - inline static constexpr const auto ALPHA_KEYS_TO_COMMAND = frozen::make_map -#else - inline static const auto ALPHA_KEYS_TO_COMMAND = std::map -#endif - - ({ - { "A", Command::FingerThumb_CurlTotal }, // Thumb finger force feedback - { "B", Command::FingerIndex_CurlTotal }, // Index finger force feedback - { "C", Command::FingerMiddle_CurlTotal }, // Middle finger force feedback - { "D", Command::FingerRing_CurlTotal }, // Ring finger force feedback - { "E", Command::FingerPinky_CurlTotal }, // Pinky finger force feedback - - { "F", Command::Haptics_Frequency }, // - { "G", Command::Haptics_Duration }, // - { "H", Command::Haptics_Amplitude }, // - - { "Z", Command::Info }, - }); - -#ifdef OG_USE_FROZEN - inline static constexpr const auto COMMAND_TO_ALPHA_KEY = frozen::make_map -#else - inline static const auto COMMAND_TO_ALPHA_KEY = std::map -#endif - ({ - { Command::FingerThumb_CurlTotal, "A" }, // Whole thumb curl - { Command::FingerThumb_Splay, "(AB)" }, // Whole thumb splay - { Command::FingerThumb_CurlJoint0, "(AAA)" }, // - { Command::FingerThumb_CurlJoint1, "(AAB)" }, // - { Command::FingerThumb_CurlJoint2, "(AAC)" }, // - // { Command::FingerThumb_CurlJoint3, "(AAD)" }, // not used - - { Command::FingerIndex_CurlTotal, "B" }, // - { Command::FingerIndex_Splay, "(BB)" }, // - { Command::FingerIndex_CurlJoint0, "(BAA)" }, // - { Command::FingerIndex_CurlJoint1, "(BAB)" }, // - { Command::FingerIndex_CurlJoint2, "(BAC)" }, // - { Command::FingerIndex_CurlJoint3, "(BAD)" }, // - - { Command::FingerMiddle_CurlTotal, "C" }, // - { Command::FingerMiddle_Splay, "(CB)" }, // - { Command::FingerMiddle_CurlJoint0, "(CAA)" }, // - { Command::FingerMiddle_CurlJoint1, "(CAB)" }, // - { Command::FingerMiddle_CurlJoint2, "(CAC)" }, // - { Command::FingerMiddle_CurlJoint3, "(CAD)" }, // - - { Command::FingerRing_CurlTotal, "D" }, // - { Command::FingerRing_Splay, "(DB)" }, // - { Command::FingerRing_CurlJoint0, "(DAA)" }, // - { Command::FingerRing_CurlJoint1, "(DAB)" }, // - { Command::FingerRing_CurlJoint2, "(DAC)" }, // - { Command::FingerRing_CurlJoint3, "(DAD)" }, // - - { Command::FingerPinky_CurlTotal, "E" }, // - { Command::FingerPinky_Splay, "(EB)" }, // - { Command::FingerPinky_CurlJoint0, "(EAA)" }, // - { Command::FingerPinky_CurlJoint1, "(EAB)" }, // - { Command::FingerPinky_CurlJoint2, "(EAC)" }, // - { Command::FingerPinky_CurlJoint3, "(EAD)" }, // - - { Command::MainJoystick_X, "F" }, // - { Command::MainJoystick_Y, "G" }, // - { Command::MainJoystick_Click, "H" }, // - - { Command::GestureTrigger_Click, "I" }, // Binary trigger button/gesture - - { Command::ButtonA_Click, "J" }, // - { Command::ButtonB_Click, "K" }, // - - { Command::GestureGrab_Click, "L" }, // - { Command::GesturePinch_Click, "M" }, // - - { Command::ButtonMenu_Click, "N" }, // - { Command::ButtonCalibrate_Click, "O" }, // - - { Command::GestureTrigger_Value, "P" }, // Analog trigger button/gesture - - { Command::Info, "Z" }, -#ifdef OG_USE_FROZEN - { Command::Info_FirmwareVersion, frozen::string(INFO_FIRMWARE_VERSION_KEY) }, - { Command::Info_DeviceType, frozen::string(INFO_DEVICE_TYPE_KEY) }, - { Command::Info_Hand, frozen::string(INFO_HAND_KEY) }, -#else - { Command::Info_FirmwareVersion, INFO_FIRMWARE_VERSION_KEY }, - { Command::Info_DeviceType, INFO_DEVICE_TYPE_KEY }, - { Command::Info_Hand, INFO_HAND_KEY }, -#endif - }); - - /// Alpha keys for fingers. - /// MUST be in the same order as the `InputFingerData` struct. - inline static constexpr const std::array FINGER_ALPHA_KEY = { { - 'A', // Thumb - 'B', // Index - 'C', // Middle - 'D', // Ring - 'E', // Pinky - } }; - - /// Alpha keys for finger curl joints. Top level is the finger, second level is the joint. - /// The top level MUST be in the same order as the `InputFingerData` struct. - /// Second level array MUST be in the same order as the `InputFingerCurlData` struct. -#ifdef OG_USE_FROZEN - inline static constexpr const std::array, 5> FINGER_CURL_JOINT_ALPHA_KEY = -#else - inline static const std::array, 5> FINGER_CURL_JOINT_ALPHA_KEY = -#endif - { { - { "A", "(AAB)", "(AAC)", "(AAD)" }, // Thumb (total, joint1, joint2, joint3) - { "B", "(BAB)", "(BAC)", "(BAD)" }, // Index (total, joint1, joint2, joint3) - { "C", "(CAB)", "(CAC)", "(CAD)" }, // Middle (total, joint1, joint2, joint3) - { "D", "(DAB)", "(DAC)", "(DAD)" }, // Ring (total, joint1, joint2, joint3) - { "E", "(EAB)", "(EAC)", "(EAD)" }, // Pinky (total, joint1, joint2, joint3) - } }; - - /// Alpha keys for buttons. - /// MUST be in the same order as the `InputPeripheralData` struct. - inline static constexpr const std::array BUTTON_ALPHA_KEY = { { - 'J', // Button A - 'K', // Button B - 'N', // Button Menu - 'O', // Button Calibrate - 'M', // Button Pinch - } }; - - /// Alpha keys for analog buttons. - /// MUST be in the same order as the `InputPeripheralData` struct. - inline static constexpr const std::array ANALOG_BUTTON_ALPHA_KEY = { { - 'I', // Trigger - 'L', // Grab - } }; - - [[nodiscard]] auto encode_input(const InputData& input, char* buffer, size_t length) const -> size_t override; - - [[nodiscard]] auto decode_output(const char* data, size_t length) const -> OutputData override; - - protected: - [[nodiscard]] auto split_to_map(const char* data, size_t length) const -> std::map; - void split_command(const char* data, size_t start, size_t length, std::map& commands) - const; - }; -} // namespace og diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 9ed26aad..8e6cab5a 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include #include @@ -62,6 +62,8 @@ return data; namespace SenseShift::OpenGloves { + namespace og = ::opengloves; + class ITransport : public IInitializable { public: virtual auto send(const char* buffer, size_t length) -> size_t = 0; diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index 55c8ce45..69d761d3 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -7,13 +7,17 @@ #include #include -#include "opengloves/opengloves.hpp" +#include +#include + #include "senseshift/opengloves/opengloves.hpp" #include #include namespace SenseShift::OpenGloves { + namespace og = ::opengloves; + class OpenGlovesTrackingComponent : public SenseShift::Component { // Plotter raw_plotter_ = Plotter(&Serial, "Raw"); // Plotter calibrated_plotter_ = Plotter(&Serial, "Cal"); @@ -37,7 +41,7 @@ namespace SenseShift::OpenGloves { Config& config, InputSensors& input_sensors, ITransport* communication, - og::IEncoder* encoder = new og::AlphaEncoder() + og::AlphaEncoding* encoder = new og::AlphaEncoding() ) : config_(config), input_sensors_(std::move(input_sensors)), communication_(communication), encoder_(encoder) { @@ -76,7 +80,8 @@ namespace SenseShift::OpenGloves { } // now = micros(); - const auto length = this->encoder_->encode_input(data, buffer.data(), buffer.size()); + const auto length = + og::AlphaEncoding::encodeInput(data, reinterpret_cast(buffer.data()), buffer.size()); // const auto encodeTime = micros() - now; // now = micros(); @@ -128,7 +133,7 @@ namespace SenseShift::OpenGloves { Config& config_; InputSensors input_sensors_; ITransport* communication_; - og::IEncoder* encoder_; + og::AlphaEncoding* encoder_; }; class OpenGlovesForceFeedbackComponent : public SenseShift::Component { @@ -136,7 +141,7 @@ namespace SenseShift::OpenGloves { OpenGlovesForceFeedbackComponent( OutputWriters& output_writers, ::SenseShift::OpenGloves::ITransport* communication, - og::IEncoder* encoder = new og::AlphaEncoder() + og::AlphaEncoding* encoder = new og::AlphaEncoding() ) : output_writers_(output_writers), communication_(communication), encoder_(encoder){}; @@ -151,7 +156,8 @@ namespace SenseShift::OpenGloves { { if (this->communication_->hasData()) { const auto length = this->communication_->read(this->buffer.data(), this->buffer.size()); - const auto output = this->encoder_->decode_output(this->buffer.data(), length); + const auto output = + og::AlphaEncoding::decodeOutput(reinterpret_cast(this->buffer.data()), length); this->output_writers_.apply(output); } } @@ -161,6 +167,6 @@ namespace SenseShift::OpenGloves { OutputWriters output_writers_; ::SenseShift::OpenGloves::ITransport* communication_; - og::IEncoder* encoder_; + og::AlphaEncoding* encoder_; }; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp index 0b9fa262..13009cda 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp @@ -2,7 +2,7 @@ #include "Arduino.h" -#include "opengloves/opengloves.hpp" +#include "opengloves.hpp" namespace SenseShift::OpenGloves { class Plotter { @@ -34,4 +34,4 @@ namespace SenseShift::OpenGloves { Print* const output_; char* const prefix_; }; -} // namespace SenseShift::OpenGloves \ No newline at end of file +} // namespace SenseShift::OpenGloves diff --git a/platformio.ini b/platformio.ini index bdcc8457..928b7714 100644 --- a/platformio.ini +++ b/platformio.ini @@ -37,8 +37,9 @@ build_src_filter = - lib_deps = - https://github.com/senseshift/frozen.git#feature/platformio - https://github.com/senseshift/arduino-ble-serial.git#v1.1.1 + https://github.com/senseshift/frozen.git#feature/platformio + https://github.com/senseshift/arduino-ble-serial.git#v1.1.2 + https://github.com/senseshift/opengloves-lib.git#master [env] build_flags = ${common.build_flags} diff --git a/test/test_opengloves_alpha_encoding/main.cpp b/test/test_opengloves_alpha_encoding/main.cpp deleted file mode 100644 index 7fd164d0..00000000 --- a/test/test_opengloves_alpha_encoding/main.cpp +++ /dev/null @@ -1,224 +0,0 @@ -#include -#include - -using namespace og; - -void test_encode_input_peripherals(void) -{ - const IEncoder* encoder = new AlphaEncoder(); - - const auto defaultEmpty = InputPeripheralData(); - - auto halfCurl = InputPeripheralData(); - halfCurl.curl = { - .thumb = { .curl_total = 0.5 }, - .index = { .curl_total = 0.5 }, - .middle = { .curl_total = 0.5 }, - .ring = { .curl_total = 0.5 }, - .pinky = { .curl_total = 0.5 }, - }; - - auto zeroCurl = InputPeripheralData(); - zeroCurl.curl = { - .thumb = { .curl_total = 0.0 }, - .index = { .curl_total = 0.0 }, - .middle = { .curl_total = 0.0 }, - .ring = { .curl_total = 0.0 }, - .pinky = { .curl_total = 0.0 }, - }; - - auto fullCurl = InputPeripheralData(); - fullCurl.curl = { - .thumb = { .curl_total = 1.0 }, - .index = { .curl_total = 1.0 }, - .middle = { .curl_total = 1.0 }, - .ring = { .curl_total = 1.0 }, - .pinky = { .curl_total = 1.0 }, - }; - - auto halfSplay = InputPeripheralData(); - halfSplay.splay = { - .thumb = 0.5, - .index = 0.5, - .middle = 0.5, - .ring = 0.5, - .pinky = 0.5, - }; - - auto increasingJoints = InputPeripheralData(); - increasingJoints.curl = { - .thumb = { .curl = { 0.25f, 0.5f, 0.75f, 1.0f } }, - .index = { .curl = { 0.25f, 0.5f, 0.75f, 1.0f } }, - .middle = { .curl = { 0.25f, 0.5f, 0.75f, 1.0f } }, - .ring = { .curl = { 0.25f, 0.5f, 0.75f, 1.0f } }, - .pinky = { .curl = { 0.25f, 0.5f, 0.75f, 1.0f } }, - }; - - auto joystick = InputPeripheralData(); - joystick.joystick = { - .x = 0.5, - .y = 0.5, - .press = true, - }; - - auto buttons = InputPeripheralData(); - buttons.button_a = { .press = true }; - buttons.button_calibrate = { .press = true }; - - auto gesture = InputPeripheralData(); - gesture.pinch = { true }; - gesture.grab = { true }; - - auto halfCurlSplay = InputPeripheralData(halfCurl); - halfCurlSplay.curl = { - .thumb = { .curl_total = 0.5 }, - .index = { .curl_total = 0.5 }, - .middle = { .curl_total = 0.5 }, - .ring = { .curl_total = 0.5 }, - .pinky = { .curl_total = 0.5 }, - }; - halfCurlSplay.splay = { - .thumb = 0.5, - .index = 0.5, - .middle = 0.5, - .ring = 0.5, - .pinky = 0.5, - }; - - const std::vector> cases = { - { - defaultEmpty, - "A0B0C0D0E0\n", - }, - { - halfCurl, - "A2047B2047C2047D2047E2047\n", - }, - { - zeroCurl, - "A0B0C0D0E0\n", - }, - { - fullCurl, - "A4095B4095C4095D4095E4095\n", - }, - { - halfSplay, - "A0(AB)2047B0(BB)2047C0(CB)2047D0(DB)2047E0(EB)2047\n", - }, - { - increasingJoints, - "A1023(AAB)2047(AAC)3071(AAD)4095B1023(BAB)2047(BAC)3071(BAD)4095C1023(CAB)2047(CAC)3071(CAD)4095D1023(DAB)2047(DAC)3071(DAD)4095E1023(EAB)2047(EAC)3071(EAD)4095\n", - }, - { - joystick, - "A0B0C0D0E0F2047G2047H\n", - }, - { - buttons, - "A0B0C0D0E0JO\n", - }, - { - gesture, - "A0B0C0D0E0ML\n", - }, - { - halfCurlSplay, - "A2047(AB)2047B2047(BB)2047C2047(CB)2047D2047(DB)2047E2047(EB)2047\n", - } - }; - - for (auto i = 0; i < cases.size(); i++) { - const auto [data, expected] = cases[i]; - const auto encoded = encoder->encode_input(data); - TEST_ASSERT_EQUAL_STRING_MESSAGE( - expected.c_str(), - encoded.c_str(), - ("Failed case " + std::to_string(i)).c_str() - ); - } -} - -void test_decode_output_ffb(void) -{ - const IEncoder* encoder = new AlphaEncoder(); - - std::map cases = { - { - "A0B0C0D0E0\n", - OutputForceFeedbackData{ - .thumb = 0.0f, - .index = 0.0f, - .middle = 0.0f, - .ring = 0.0f, - .pinky = 0.0f, - }, - }, - { - "A0\n", - OutputForceFeedbackData{ - .thumb = 0.0f, - .index = 0.0f, - .middle = 0.0f, - .ring = 0.0f, - .pinky = 0.0f, - }, - }, - { - "A819B1638C2457D3276E4095\n", - OutputForceFeedbackData{ - .thumb = 0.2f, - .index = 0.4f, - .middle = 0.6f, - .ring = 0.8f, - .pinky = 1.0f, - }, - }, - { - "A4095B4095C4095D4095E4095\n", - OutputForceFeedbackData{ - .thumb = 1.0f, - .index = 1.0f, - .middle = 1.0f, - .ring = 1.0f, - .pinky = 1.0f, - }, - }, - }; - - for (const auto& [data, expected] : cases) { - const auto decoded = encoder->decode_output(data.c_str(), data.size()); - TEST_ASSERT_TRUE(std::holds_alternative(decoded)); - TEST_ASSERT_TRUE(std::get(decoded) == expected); - } -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_encode_input_peripherals); - RUN_TEST(test_decode_output_ffb); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include - -void setup(void) -{ - process(); -} - -void loop(void) {} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif From 6569b288e437164cf834e4448321bf29c05fe7d9 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 27 Jul 2024 17:42:08 +0400 Subject: [PATCH 18/67] refactor(OpenGloves): use template parameter for encoding --- .../mode_configs/opengloves/opengloves.cpp | 53 +++++++++++-------- .../opengloves/opengloves_component.hpp | 28 +++------- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/firmware/mode_configs/opengloves/opengloves.cpp index cb285676..3a3cb0b8 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/firmware/mode_configs/opengloves/opengloves.cpp @@ -2,44 +2,51 @@ #include #include +#include + using namespace SenseShift::OpenGloves; namespace og = ::opengloves; void setupMode() { auto* communication = AutoConfig::createTransport(); - auto* encoding = new og::AlphaEncoding(); auto input_sensors = AutoConfig::createInput(); - OpenGlovesTrackingComponent::Config tracking_config(CALIBRATION_DURATION, CALIBRATION_ALWAYS_CALIBRATE); - auto* og_tracking = new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication, encoding); - - auto* og_tracking_task = new SenseShift::FreeRTOS::ComponentUpdateTask( - og_tracking, - 1000 / UPDATE_RATE, - { - .name = "OG_TRACKING", - .stackDepth = 8192, - .priority = 1, - } + OpenGlovesTrackingComponent::Config tracking_config( + CALIBRATION_DURATION, + CALIBRATION_ALWAYS_CALIBRATE ); + auto* og_tracking = + new OpenGlovesTrackingComponent(tracking_config, input_sensors, communication); + + auto* og_tracking_task = + new SenseShift::FreeRTOS::ComponentUpdateTask>( + og_tracking, + 1000 / UPDATE_RATE, + { + .name = "OG_TRACKING", + .stackDepth = 8192, + .priority = 1, + } + ); og_tracking_task->begin(); #if FFB_ENABLED auto output_writers = AutoConfig::createFfbOutputs(); - auto* og_ffb = new OpenGlovesForceFeedbackComponent(output_writers, communication, encoding); - - auto* og_ffb_task = new ::SenseShift::FreeRTOS::ComponentUpdateTask( - og_ffb, - 1000 / UPDATE_RATE, - { - .name = "OG_FFB", - .stackDepth = 8192, - .priority = 1, - } - ); + auto* og_ffb = new OpenGlovesForceFeedbackComponent(output_writers, communication); + + auto* og_ffb_task = + new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + og_ffb, + 1000 / UPDATE_RATE, + { + .name = "OG_FFB", + .stackDepth = 8192, + .priority = 1, + } + ); og_ffb_task->begin(); #endif } diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index 69d761d3..735dd6d0 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -8,7 +8,6 @@ #include #include -#include #include "senseshift/opengloves/opengloves.hpp" #include @@ -16,8 +15,7 @@ #include namespace SenseShift::OpenGloves { - namespace og = ::opengloves; - + template class OpenGlovesTrackingComponent : public SenseShift::Component { // Plotter raw_plotter_ = Plotter(&Serial, "Raw"); // Plotter calibrated_plotter_ = Plotter(&Serial, "Cal"); @@ -37,13 +35,8 @@ namespace SenseShift::OpenGloves { } }; - OpenGlovesTrackingComponent( - Config& config, - InputSensors& input_sensors, - ITransport* communication, - og::AlphaEncoding* encoder = new og::AlphaEncoding() - ) : - config_(config), input_sensors_(std::move(input_sensors)), communication_(communication), encoder_(encoder) + OpenGlovesTrackingComponent(Config& config, InputSensors& input_sensors, ITransport* communication) : + config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) { } @@ -80,8 +73,7 @@ namespace SenseShift::OpenGloves { } // now = micros(); - const auto length = - og::AlphaEncoding::encodeInput(data, reinterpret_cast(buffer.data()), buffer.size()); + const auto length = T::encodeInput(data, reinterpret_cast(buffer.data()), buffer.size()); // const auto encodeTime = micros() - now; // now = micros(); @@ -133,17 +125,15 @@ namespace SenseShift::OpenGloves { Config& config_; InputSensors input_sensors_; ITransport* communication_; - og::AlphaEncoding* encoder_; }; + template class OpenGlovesForceFeedbackComponent : public SenseShift::Component { public: OpenGlovesForceFeedbackComponent( - OutputWriters& output_writers, - ::SenseShift::OpenGloves::ITransport* communication, - og::AlphaEncoding* encoder = new og::AlphaEncoding() + OutputWriters& output_writers, ::SenseShift::OpenGloves::ITransport* communication ) : - output_writers_(output_writers), communication_(communication), encoder_(encoder){}; + output_writers_(output_writers), communication_(communication){}; void init() override { @@ -156,8 +146,7 @@ namespace SenseShift::OpenGloves { { if (this->communication_->hasData()) { const auto length = this->communication_->read(this->buffer.data(), this->buffer.size()); - const auto output = - og::AlphaEncoding::decodeOutput(reinterpret_cast(this->buffer.data()), length); + const auto output = T::decodeOutput(reinterpret_cast(this->buffer.data()), length); this->output_writers_.apply(output); } } @@ -167,6 +156,5 @@ namespace SenseShift::OpenGloves { OutputWriters output_writers_; ::SenseShift::OpenGloves::ITransport* communication_; - og::AlphaEncoding* encoder_; }; } // namespace SenseShift::OpenGloves From 2f858d03a73b509b43b81a76565554589868846c Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 27 Jul 2024 18:02:11 +0400 Subject: [PATCH 19/67] style: update clang-format --- .clang-format | 15 +- examples/bhaptics-ble-bt-serial.cpp | 5 +- firmware/senseshift.cpp | 34 +- include/senseshift.h | 25 +- .../arduino/input/sensor/analog.hpp | 29 +- .../arduino/input/sensor/digital.hpp | 32 +- .../arduino/input/sensor/ina219.hpp | 29 +- .../arduino/input/sensor/multiplexer.hpp | 194 +++---- .../senseshift/arduino/output/analog.hpp | 41 +- .../senseshift/arduino/output/pca9685.hpp | 39 +- .../senseshift/arduino/output/servo.hpp | 31 +- .../senseshift/arduino/output/ledc.hpp | 90 ++-- lib/battery/senseshift/battery/battery.hpp | 47 +- .../battery/input/battery_sensor.hpp | 96 ++-- lib/bhaptics/senseshift/bh/devices.hpp | 94 ++-- lib/bhaptics/senseshift/bh/encoding.hpp | 352 ++++++------ .../senseshift/bh/ble/connection.cpp | 417 +++++++------- .../senseshift/bh/ble/connection.hpp | 103 ++-- lib/core/senseshift/core/component.hpp | 58 +- lib/core/senseshift/core/helpers.hpp | 228 ++++---- lib/core/senseshift/events.hpp | 30 +- lib/freertos/senseshift/freertos/task.hpp | 233 ++++---- .../senseshift/body/hands/hands_interface.hpp | 30 +- .../senseshift/body/hands/input/gesture.hpp | 170 +++--- .../body/hands/input/total_curl.hpp | 76 +-- lib/haptics/senseshift/body/haptics/body.cpp | 24 +- lib/haptics/senseshift/body/haptics/body.hpp | 78 +-- .../senseshift/body/haptics/interface.hpp | 144 ++--- lib/haptics/senseshift/body/haptics/plane.cpp | 113 ++-- lib/haptics/senseshift/body/haptics/plane.hpp | 216 ++++---- lib/io/senseshift/input/calibration.hpp | 430 ++++++++------- lib/io/senseshift/input/filter.hpp | 508 +++++++++--------- .../input/sensor/analog_threshold.hpp | 102 ++-- lib/io/senseshift/input/sensor/sensor.hpp | 358 ++++++------ lib/io/senseshift/output/output.hpp | 18 +- lib/math/senseshift/math/point2.hpp | 78 +-- .../senseshift/opengloves/autoconfig.hpp | 256 ++++----- .../senseshift/opengloves/opengloves.hpp | 212 ++++---- .../opengloves/opengloves_component.hpp | 240 ++++----- .../opengloves/opengloves_plotter.hpp | 50 +- .../opengloves/transport/stream.hpp | 222 ++++---- lib/util/senseshift/buffer.hpp | 299 ++++++----- lib/util/senseshift/container.hpp | 60 +-- test/test_battery/main.cpp | 6 +- test/test_bhaptics_encoding/main.cpp | 18 +- test/test_body_gestures/main.cpp | 4 +- test/test_core_helpers/main.cpp | 4 +- test/test_haptics_body/main.cpp | 18 +- test/test_haptics_plane/main.cpp | 18 +- test/test_io_calibration/main.cpp | 4 +- test/test_io_filter/main.cpp | 4 +- test/test_io_sensor/main.cpp | 44 +- test/test_math_point2/main.cpp | 4 +- test/test_util_buffer/main.cpp | 4 +- test/test_util_container/main.cpp | 6 +- 55 files changed, 3141 insertions(+), 2899 deletions(-) diff --git a/.clang-format b/.clang-format index f1213235..8c19bc74 100644 --- a/.clang-format +++ b/.clang-format @@ -5,12 +5,15 @@ AlignEscapedNewlines: Left AllowAllArgumentsOnNextLine: 'false' AllowAllConstructorInitializersOnNextLine: 'true' AllowAllParametersOfDeclarationOnNextLine: 'true' -AllowShortBlocksOnASingleLine: 'false' -AllowShortCaseLabelsOnASingleLine: 'false' -AllowShortFunctionsOnASingleLine: Inline + +# Always break after if to get accurate coverage +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: Empty -AllowShortLoopsOnASingleLine: 'false' +AllowShortLambdasOnASingleLine: None +AllowShortLoopsOnASingleLine: false + AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: 'true' AlwaysBreakTemplateDeclarations: 'Yes' @@ -39,7 +42,7 @@ IndentWrappedFunctionNames: 'true' KeepEmptyLinesAtTheStartOfBlocks: 'false' Language: Cpp MaxEmptyLinesToKeep: '1' -NamespaceIndentation: All +NamespaceIndentation: None PointerAlignment: Left ReflowComments: 'true' SortIncludes: 'true' diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index 9f1f9820..808b6821 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -26,7 +26,10 @@ static const ::SenseShift::Body::Haptics::Position* bhLayout[bhLayoutSize] = BH_ class BLECallbacks : public BHBLEConnectionCallbacks { public: - void postInit() { btSerial->begin("SenseShift Serial"); } + void postInit() + { + btSerial->begin("SenseShift Serial"); + } }; void setupMode() diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index a4f7ab8b..3599b0fc 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -9,26 +9,26 @@ #include namespace SenseShift { - static const char* const TAG = "application"; +static const char* const TAG = "application"; - Application::Application() - { - this->vibro_body_ = new Body::Haptics::FloatBody(); - } - - void Application::postEvent(const IEvent* event) - { - LOG_I(TAG, "Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); +Application::Application() +{ + this->vibro_body_ = new Body::Haptics::FloatBody(); +} - for (const auto* listener : this->event_listeners_) { - listener->handleEvent(event); - } +void Application::postEvent(const IEvent* event) +{ + LOG_I(TAG, "Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); - delete event; + for (const auto* listener : this->event_listeners_) { + listener->handleEvent(event); } - void Application::addEventListener(const IEventListener* listener) - { - this->event_listeners_.push_back(listener); - } + delete event; +} + +void Application::addEventListener(const IEventListener* listener) +{ + this->event_listeners_.push_back(listener); +} } // namespace SenseShift diff --git a/include/senseshift.h b/include/senseshift.h index d3d8629d..1b792373 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -9,18 +9,21 @@ #include namespace SenseShift { - class Application final : public IEventDispatcher { - public: - Application(); +class Application final : public IEventDispatcher { + public: + Application(); - [[nodiscard]] auto getVibroBody() const -> Body::Haptics::FloatBody* { return this->vibro_body_; }; + [[nodiscard]] auto getVibroBody() const -> Body::Haptics::FloatBody* + { + return this->vibro_body_; + }; - void postEvent(const IEvent* event) override; - void addEventListener(const IEventListener* listener) override; + void postEvent(const IEvent* event) override; + void addEventListener(const IEventListener* listener) override; - private: - std::vector event_listeners_{}; - Body::Haptics::FloatBody* vibro_body_; - Battery::Input::IBatterySensor* battery_ = nullptr; - }; + private: + std::vector event_listeners_{}; + Body::Haptics::FloatBody* vibro_body_; + Battery::Input::IBatterySensor* battery_ = nullptr; +}; } // namespace SenseShift diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 1f50c26c..9e5c8903 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -18,20 +18,25 @@ #endif namespace SenseShift::Arduino::Input { - class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { - const std::uint8_t pin_; +class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { + const std::uint8_t pin_; - public: - static constexpr float MAX_VALUE = ANALOG_MAX; + public: + static constexpr float MAX_VALUE = ANALOG_MAX; - explicit AnalogSimpleSensor(const std::uint8_t pin) : pin_(pin) {} + explicit AnalogSimpleSensor(const std::uint8_t pin) : pin_(pin) + { + } - void init() override { pinMode(this->pin_, INPUT); }; - - [[nodiscard]] inline auto getValue() -> float override - { - const std::uint16_t raw = analogRead(this->pin_); - return static_cast(raw) / ANALOG_MAX; - } + void init() override + { + pinMode(this->pin_, INPUT); }; + + [[nodiscard]] inline auto getValue() -> float override + { + const std::uint16_t raw = analogRead(this->pin_); + return static_cast(raw) / ANALOG_MAX; + } +}; } // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index eede7f38..c9d8e992 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -7,20 +7,26 @@ #include namespace SenseShift::Arduino::Input { - class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { - public: - explicit DigitalSimpleSensor( - const std::uint8_t pin, const std::uint8_t mode = INPUT_PULLUP, const std::uint8_t inverted = LOW - ) : - pin_(pin), mode_(mode), inverted_(inverted){}; +class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { + public: + explicit DigitalSimpleSensor( + const std::uint8_t pin, const std::uint8_t mode = INPUT_PULLUP, const std::uint8_t inverted = LOW + ) : + pin_(pin), mode_(mode), inverted_(inverted){}; - void init() override { pinMode(this->pin_, this->mode_); }; + void init() override + { + pinMode(this->pin_, this->mode_); + }; - [[nodiscard]] auto getValue() -> bool override { return digitalRead(this->pin_) == this->inverted_; } + [[nodiscard]] auto getValue() -> bool override + { + return digitalRead(this->pin_) == this->inverted_; + } - private: - std::uint8_t pin_; - std::uint8_t mode_ = INPUT_PULLUP; - std::uint8_t inverted_ = LOW; - }; + private: + std::uint8_t pin_; + std::uint8_t mode_ = INPUT_PULLUP; + std::uint8_t inverted_ = LOW; +}; } // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp index 970b7ecf..4efa7570 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp @@ -7,19 +7,22 @@ #include namespace SenseShift::Arduino::Input { - /// INA219 Current sensor - /// TODO: refactor to component, that updates the value in multiple sensors (ESPHome style) - class INA219CurrentSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { - Adafruit_INA219 ina219_; +/// INA219 Current sensor +/// TODO: refactor to component, that updates the value in multiple sensors (ESPHome style) +class INA219CurrentSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { + Adafruit_INA219 ina219_; - public: - void init() override - { - if (!ina219_.success()) { - log_e("Failed to find INA219 sensor"); - } + public: + void init() override + { + if (!ina219_.success()) { + log_e("Failed to find INA219 sensor"); } + } - [[nodiscard]] inline auto getValue() -> float override { return ina219_.getCurrent_mA(); } - }; -} // namespace SenseShift::Arduino::Input \ No newline at end of file + [[nodiscard]] inline auto getValue() -> float override + { + return ina219_.getCurrent_mA(); + } +}; +} // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp index 53bf8318..a0de2b34 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp @@ -14,107 +14,107 @@ #include namespace SenseShift::Arduino::Input { - template - class Multiplexer : public IInitializable { - public: - /// \param pins The pins to use for the multiplexer. - explicit Multiplexer(const std::array& pins, const size_t switch_delay_us = 2) : - pins_(pins), switch_delay_us_(switch_delay_us) - { +template +class Multiplexer : public IInitializable { + public: + /// \param pins The pins to use for the multiplexer. + explicit Multiplexer(const std::array& pins, const size_t switch_delay_us = 2) : + pins_(pins), switch_delay_us_(switch_delay_us) + { + } + + void init() override + { + for (const auto pin : this->pins_) { + pinMode(pin, OUTPUT); } - - void init() override - { - for (const auto pin : this->pins_) { - pinMode(pin, OUTPUT); - } - } - - /// Select the channel. - /// \param channel The channel to select. - void selectChannel(const std::uint8_t channel) - { - if (channel >= (1 << N) || this->active_channel_ == channel) { - return; - } - - for (size_t i = 0; i < N; ++i) { - digitalWrite(this->pins_[i], (channel >> i) & 0b0001); - } - - delayMicroseconds(this->switch_delay_us_); - - this->active_channel_ = channel; - } - - private: - const std::array pins_; - std::uint8_t active_channel_ = 0; - const size_t switch_delay_us_; - }; - - using MUX_CD74HC4057Component = Multiplexer<4>; - using MUX_74HC4051Component = Multiplexer<3>; - - template - class MultiplexedAnalogSensor : public AnalogSimpleSensor { - public: - /// \param component The CD74HC4057 Component to use. - /// \param pin The SIG pin of the sensor. - /// \param channel The channel to read from. - MultiplexedAnalogSensor(Multiplexer* component, const std::uint8_t pin_sig, const std::uint8_t channel) : - component_(component), AnalogSimpleSensor(pin_sig), channel_(channel) - { - assert(channel < (1 << N) && "Channel out of range"); - } - - void init() override - { - this->component_->init(); - AnalogSimpleSensor::init(); + } + + /// Select the channel. + /// \param channel The channel to select. + void selectChannel(const std::uint8_t channel) + { + if (channel >= (1 << N) || this->active_channel_ == channel) { + return; } - [[nodiscard]] auto getValue() -> float override - { - this->component_->selectChannel(this->channel_); - - return AnalogSimpleSensor::getValue(); - } - - private: - Multiplexer* component_; - const std::uint8_t channel_; - }; - - class MultiplexedDigitalSensor : public DigitalSimpleSensor { - public: - /// \param component The CD74HC4057 Component to use. - /// \param pin The SIG pin of the sensor. - /// \param channel The channel to read from. - MultiplexedDigitalSensor( - MUX_CD74HC4057Component* component, const std::uint8_t pin_sig, const std::uint8_t channel - ) : - component_(component), DigitalSimpleSensor(pin_sig), channel_(channel) - { - assert(channel < 16 && "Channel out of range"); - } - - void init() override - { - this->component_->init(); - DigitalSimpleSensor::init(); - } - - [[nodiscard]] auto getValue() -> bool override - { - this->component_->selectChannel(this->channel_); - - return DigitalSimpleSensor::getValue(); + for (size_t i = 0; i < N; ++i) { + digitalWrite(this->pins_[i], (channel >> i) & 0b0001); } - private: - MUX_CD74HC4057Component* component_; - const std::uint8_t channel_; - }; + delayMicroseconds(this->switch_delay_us_); + + this->active_channel_ = channel; + } + + private: + const std::array pins_; + std::uint8_t active_channel_ = 0; + const size_t switch_delay_us_; +}; + +using MUX_CD74HC4057Component = Multiplexer<4>; +using MUX_74HC4051Component = Multiplexer<3>; + +template +class MultiplexedAnalogSensor : public AnalogSimpleSensor { + public: + /// \param component The CD74HC4057 Component to use. + /// \param pin The SIG pin of the sensor. + /// \param channel The channel to read from. + MultiplexedAnalogSensor(Multiplexer* component, const std::uint8_t pin_sig, const std::uint8_t channel) : + component_(component), AnalogSimpleSensor(pin_sig), channel_(channel) + { + assert(channel < (1 << N) && "Channel out of range"); + } + + void init() override + { + this->component_->init(); + AnalogSimpleSensor::init(); + } + + [[nodiscard]] auto getValue() -> float override + { + this->component_->selectChannel(this->channel_); + + return AnalogSimpleSensor::getValue(); + } + + private: + Multiplexer* component_; + const std::uint8_t channel_; +}; + +class MultiplexedDigitalSensor : public DigitalSimpleSensor { + public: + /// \param component The CD74HC4057 Component to use. + /// \param pin The SIG pin of the sensor. + /// \param channel The channel to read from. + MultiplexedDigitalSensor( + MUX_CD74HC4057Component* component, const std::uint8_t pin_sig, const std::uint8_t channel + ) : + component_(component), DigitalSimpleSensor(pin_sig), channel_(channel) + { + assert(channel < 16 && "Channel out of range"); + } + + void init() override + { + this->component_->init(); + DigitalSimpleSensor::init(); + } + + [[nodiscard]] auto getValue() -> bool override + { + this->component_->selectChannel(this->channel_); + + return DigitalSimpleSensor::getValue(); + } + + private: + MUX_CD74HC4057Component* component_; + const std::uint8_t channel_; +}; } // namespace SenseShift::Arduino::Input diff --git a/lib/arduino/senseshift/arduino/output/analog.hpp b/lib/arduino/senseshift/arduino/output/analog.hpp index 28358ac3..0f68cb67 100644 --- a/lib/arduino/senseshift/arduino/output/analog.hpp +++ b/lib/arduino/senseshift/arduino/output/analog.hpp @@ -7,22 +7,27 @@ #include namespace SenseShift::Arduino::Output { - /// Arduino analog output - class AnalogOutput : public ::SenseShift::Output::IFloatOutput { - public: - static inline constexpr std::uint16_t MAX_INTENSITY = 255; - - explicit AnalogOutput(const std::uint8_t pin) : pin_(pin) {} - - void init() override { pinMode(this->pin_, OUTPUT); } - - void writeState(const float value) override - { - const auto duty = static_cast(value * MAX_INTENSITY); - analogWrite(this->pin_, duty); - } - - private: - uint8_t pin_; - }; +/// Arduino analog output +class AnalogOutput : public ::SenseShift::Output::IFloatOutput { + public: + static inline constexpr std::uint16_t MAX_INTENSITY = 255; + + explicit AnalogOutput(const std::uint8_t pin) : pin_(pin) + { + } + + void init() override + { + pinMode(this->pin_, OUTPUT); + } + + void writeState(const float value) override + { + const auto duty = static_cast(value * MAX_INTENSITY); + analogWrite(this->pin_, duty); + } + + private: + uint8_t pin_; +}; } // namespace SenseShift::Arduino::Output diff --git a/lib/arduino/senseshift/arduino/output/pca9685.hpp b/lib/arduino/senseshift/arduino/output/pca9685.hpp index 1bbffd38..730c4698 100644 --- a/lib/arduino/senseshift/arduino/output/pca9685.hpp +++ b/lib/arduino/senseshift/arduino/output/pca9685.hpp @@ -10,22 +10,25 @@ #include namespace SenseShift::Arduino::Output { - class PCA9685Output : public ::SenseShift::Output::IFloatOutput { - public: - static inline constexpr std::uint16_t MAX_INTENSITY = 4095; - - PCA9685Output(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver_(driver), channel_(num){}; - - void init() override { this->driver_->begin(); } - - void writeState(const ValueType value) override - { - const auto duty = static_cast(value * MAX_INTENSITY); - this->driver_->setPin(this->channel_, duty); - } - - private: - Adafruit_PWMServoDriver* driver_; - std::uint8_t channel_; - }; +class PCA9685Output : public ::SenseShift::Output::IFloatOutput { + public: + static inline constexpr std::uint16_t MAX_INTENSITY = 4095; + + PCA9685Output(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver_(driver), channel_(num){}; + + void init() override + { + this->driver_->begin(); + } + + void writeState(const ValueType value) override + { + const auto duty = static_cast(value * MAX_INTENSITY); + this->driver_->setPin(this->channel_, duty); + } + + private: + Adafruit_PWMServoDriver* driver_; + std::uint8_t channel_; +}; } // namespace SenseShift::Arduino::Output diff --git a/lib/arduino/senseshift/arduino/output/servo.hpp b/lib/arduino/senseshift/arduino/output/servo.hpp index 81f238eb..1fa4b554 100644 --- a/lib/arduino/senseshift/arduino/output/servo.hpp +++ b/lib/arduino/senseshift/arduino/output/servo.hpp @@ -12,20 +12,23 @@ #include namespace SenseShift::Arduino::Output { - class ServoOutput : public ::SenseShift::Output::IFloatOutput { - public: - ServoOutput(size_t pin) : pin_(pin){}; +class ServoOutput : public ::SenseShift::Output::IFloatOutput { + public: + ServoOutput(size_t pin) : pin_(pin){}; - void init() override { this->servo_.attach(this->pin_); } + void init() override + { + this->servo_.attach(this->pin_); + } - void writeState(const ValueType value) override - { - const auto duty = static_cast(value * 180); - this->servo_.write(duty); - } + void writeState(const ValueType value) override + { + const auto duty = static_cast(value * 180); + this->servo_.write(duty); + } - private: - Servo servo_; - size_t pin_; - }; -} // namespace SenseShift::Arduino::Output \ No newline at end of file + private: + Servo servo_; + size_t pin_; +}; +} // namespace SenseShift::Arduino::Output diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp index 064890ba..e74b84c1 100644 --- a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -8,48 +8,54 @@ #include namespace SenseShift::Arduino::Output { - static const char* const TAG = "output.ledc"; - - /// Arduino analog output - class LedcOutput : public ::SenseShift::Output::IFloatOutput { - public: - explicit LedcOutput( - const std::uint8_t pin, const std::uint8_t analog_resolution = 12, const std::uint32_t analog_frequency = 60 - ) : - pin_(pin), analog_resolution_(analog_resolution), analog_frequency_(analog_frequency) - { +static const char* const TAG = "output.ledc"; + +/// Arduino analog output +class LedcOutput : public ::SenseShift::Output::IFloatOutput { + public: + explicit LedcOutput( + const std::uint8_t pin, const std::uint8_t analog_resolution = 12, const std::uint32_t analog_frequency = 60 + ) : + pin_(pin), analog_resolution_(analog_resolution), analog_frequency_(analog_frequency) + { + } + + ~LedcOutput() override + { + ledcDetach(this->pin_); + } + + void init() override + { + pinMode(this->pin_, OUTPUT); + + LOG_D(TAG, "GPIO %d - Setting up Channel %d", this->pin_, this->channel_); + if (!ledcAttach(this->pin_, this->analog_frequency_, this->analog_resolution_)) { + LOG_E( + TAG, + "setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency", + this->analog_frequency_, + this->analog_resolution_ + ); + return; } - - ~LedcOutput() override { ledcDetach(this->pin_); } - - void init() override - { - pinMode(this->pin_, OUTPUT); - - LOG_D(TAG, "GPIO %d - Setting up Channel %d", this->pin_, this->channel_); - if (!ledcAttach(this->pin_, this->analog_frequency_, this->analog_resolution_)) { - LOG_E( - TAG, - "setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency", - this->analog_frequency_, - this->analog_resolution_ - ); - return; - } - } - - [[nodiscard]] inline auto getMaxValue() const -> std::uint32_t { return (1 << this->analog_resolution_) - 1; } - - void writeState(const float value) override - { - const auto duty = static_cast(value * this->getMaxValue()); - LOG_V(TAG, "GPIO %d - Writing %d to Channel %d", this->pin_, duty, this->channel_); - ledcWrite(this->pin_, duty); - }; - - private: - std::uint8_t pin_; - std::uint8_t analog_resolution_; - std::uint32_t analog_frequency_; + } + + [[nodiscard]] inline auto getMaxValue() const -> std::uint32_t + { + return (1 << this->analog_resolution_) - 1; + } + + void writeState(const float value) override + { + const auto duty = static_cast(value * this->getMaxValue()); + LOG_V(TAG, "GPIO %d - Writing %d to Channel %d", this->pin_, duty, this->channel_); + ledcWrite(this->pin_, duty); }; + + private: + std::uint8_t pin_; + std::uint8_t analog_resolution_; + std::uint32_t analog_frequency_; +}; } // namespace SenseShift::Arduino::Output diff --git a/lib/battery/senseshift/battery/battery.hpp b/lib/battery/senseshift/battery/battery.hpp index 0f4e587c..a697f8c4 100644 --- a/lib/battery/senseshift/battery/battery.hpp +++ b/lib/battery/senseshift/battery/battery.hpp @@ -9,28 +9,27 @@ namespace SenseShift::Battery { - namespace VoltageMap { - /// Lookup table for LiPO 1S 4.2V batteries - /// \see Source - [[maybe_unused]] inline static const auto LiPO_1S_42 = frozen::make_map({ - { 4.2, 1.0 }, { 4.15, 0.95 }, { 4.11, 0.9 }, { 4.08, 0.85 }, { 4.02, 0.8 }, { 3.98, 0.75 }, - { 3.95, 0.7 }, { 3.91, 0.65 }, { 3.87, 0.6 }, { 3.85, 0.55 }, { 3.84, 0.5 }, { 3.82, 0.45 }, - { 3.8, 0.4 }, { 3.79, 0.35 }, { 3.77, 0.3 }, { 3.75, 0.25 }, { 3.73, 0.2 }, { 3.71, 0.15 }, - { 3.69, 0.1 }, { 3.61, 0.05 }, { 3.27, 0.0 }, - }); - } // namespace VoltageMap - - struct BatteryState { - using VoltageType = float; - using LevelType = std::uint8_t; - - static constexpr LevelType MAX_LEVEL = std::numeric_limits::max(); - LevelType level; - }; - - class BatteryLevelEvent : public IEvent { - public: - const BatteryState& state; - BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; - }; +namespace VoltageMap { +/// Lookup table for LiPO 1S 4.2V batteries +/// \see Source +[[maybe_unused]] inline static const auto LiPO_1S_42 = frozen::make_map({ + { 4.2, 1.0 }, { 4.15, 0.95 }, { 4.11, 0.9 }, { 4.08, 0.85 }, { 4.02, 0.8 }, { 3.98, 0.75 }, { 3.95, 0.7 }, + { 3.91, 0.65 }, { 3.87, 0.6 }, { 3.85, 0.55 }, { 3.84, 0.5 }, { 3.82, 0.45 }, { 3.8, 0.4 }, { 3.79, 0.35 }, + { 3.77, 0.3 }, { 3.75, 0.25 }, { 3.73, 0.2 }, { 3.71, 0.15 }, { 3.69, 0.1 }, { 3.61, 0.05 }, { 3.27, 0.0 }, +}); +} // namespace VoltageMap + +struct BatteryState { + using VoltageType = float; + using LevelType = std::uint8_t; + + static constexpr LevelType MAX_LEVEL = std::numeric_limits::max(); + LevelType level; +}; + +class BatteryLevelEvent : public IEvent { + public: + const BatteryState& state; + BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; +}; } // namespace SenseShift::Battery diff --git a/lib/battery/senseshift/battery/input/battery_sensor.hpp b/lib/battery/senseshift/battery/input/battery_sensor.hpp index e0b42e0e..ac71d513 100644 --- a/lib/battery/senseshift/battery/input/battery_sensor.hpp +++ b/lib/battery/senseshift/battery/input/battery_sensor.hpp @@ -8,52 +8,52 @@ #include namespace SenseShift::Battery::Input { - /// Abstract battery sensor - using IBatterySensor = ::SenseShift::Input::Sensor; - - /// Interpolate voltage according to a lookup table. - template - class LookupTableInterpolateBatterySensor : public IBatterySensor { - static_assert(std::is_same_v); - static_assert(std::is_same_v); - - public: - using VoltageType = typename BatteryState::VoltageType; - using VoltageSource = ::SenseShift::Input::Sensor; - - LookupTableInterpolateBatterySensor(VoltageSource* voltage_source, Container* lookup_table) : - IBatterySensor(), voltage_source_(voltage_source), lookup_table_(lookup_table) - { - } - - void init() override - { - this->voltage_source_->init(); - this->voltage_source_->addValueCallback([this](VoltageType voltage) { - // Current level in % (0.0 - 1.0) - auto level = this->lookupInterpolateLevel(voltage); - - LOG_D("battery.sensor", "voltage=%f, level=%f", voltage, level); - - const BatteryState value = { - .level = static_cast(level * BatteryState::MAX_LEVEL), - }; - - this->publishState(value); - }); - } - - protected: - [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float - { - return ::SenseShift::lookup_table_interpolate_linear( - *this->lookup_table_, - voltage - ); - } - - private: - VoltageSource* voltage_source_; - Container* lookup_table_; - }; +/// Abstract battery sensor +using IBatterySensor = ::SenseShift::Input::Sensor; + +/// Interpolate voltage according to a lookup table. +template +class LookupTableInterpolateBatterySensor : public IBatterySensor { + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + public: + using VoltageType = typename BatteryState::VoltageType; + using VoltageSource = ::SenseShift::Input::Sensor; + + LookupTableInterpolateBatterySensor(VoltageSource* voltage_source, Container* lookup_table) : + IBatterySensor(), voltage_source_(voltage_source), lookup_table_(lookup_table) + { + } + + void init() override + { + this->voltage_source_->init(); + this->voltage_source_->addValueCallback([this](VoltageType voltage) { + // Current level in % (0.0 - 1.0) + auto level = this->lookupInterpolateLevel(voltage); + + LOG_D("battery.sensor", "voltage=%f, level=%f", voltage, level); + + const BatteryState value = { + .level = static_cast(level * BatteryState::MAX_LEVEL), + }; + + this->publishState(value); + }); + } + + protected: + [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float + { + return ::SenseShift::lookup_table_interpolate_linear( + *this->lookup_table_, + voltage + ); + } + + private: + VoltageSource* voltage_source_; + Container* lookup_table_; +}; } // namespace SenseShift::Battery::Input diff --git a/lib/bhaptics/senseshift/bh/devices.hpp b/lib/bhaptics/senseshift/bh/devices.hpp index 5cd2b438..28ae43f0 100644 --- a/lib/bhaptics/senseshift/bh/devices.hpp +++ b/lib/bhaptics/senseshift/bh/devices.hpp @@ -290,57 +290,57 @@ #pragma endregion BH_DEVIDE_TACTGLOVE namespace SenseShift::BH { - using namespace ::SenseShift::Body::Hands::Haptics; - using namespace ::SenseShift::Body::Haptics; - - using HandSide = ::SenseShift::Body::Hands::HandSide; - - using OutputLayout = std::tuple<::SenseShift::Body::Haptics::Target, SenseShift::Body::Haptics::Position>; - - // TactGlove Wrist motor position - static constexpr const Position WRIST_MOTOR_POSITION(127, 191); - static constexpr const std::array TactGloveLeftLayout = { - BH_LAYOUT_TACTGLOVE_LEFT - }; - static constexpr const std::array TactGloveRightLayout = { - BH_LAYOUT_TACTGLOVE_RIGHT - }; - - inline void addTactGloveActuators( - FloatBody* hapticBody, - const HandSide side, - FloatBody::Plane::Actuator* const thumb, - FloatBody::Plane::Actuator* const index, - FloatBody::Plane::Actuator* const middle, - FloatBody::Plane::Actuator* const ring, - FloatBody::Plane::Actuator* const little, - FloatBody::Plane::Actuator* const wrist - ) - { - const auto& layout = (side == HandSide::Left) ? TactGloveLeftLayout : TactGloveRightLayout; - - if (thumb != nullptr) { - hapticBody->addTarget(std::get<0>(layout[0]), new FloatPlane({ { std::get<1>(layout[0]), thumb } })); - } +using namespace ::SenseShift::Body::Hands::Haptics; +using namespace ::SenseShift::Body::Haptics; + +using HandSide = ::SenseShift::Body::Hands::HandSide; + +using OutputLayout = std::tuple<::SenseShift::Body::Haptics::Target, SenseShift::Body::Haptics::Position>; + +// TactGlove Wrist motor position +static constexpr const Position WRIST_MOTOR_POSITION(127, 191); +static constexpr const std::array TactGloveLeftLayout = { + BH_LAYOUT_TACTGLOVE_LEFT +}; +static constexpr const std::array TactGloveRightLayout = { + BH_LAYOUT_TACTGLOVE_RIGHT +}; + +inline void addTactGloveActuators( + FloatBody* hapticBody, + const HandSide side, + FloatBody::Plane::Actuator* const thumb, + FloatBody::Plane::Actuator* const index, + FloatBody::Plane::Actuator* const middle, + FloatBody::Plane::Actuator* const ring, + FloatBody::Plane::Actuator* const little, + FloatBody::Plane::Actuator* const wrist +) +{ + const auto& layout = (side == HandSide::Left) ? TactGloveLeftLayout : TactGloveRightLayout; + + if (thumb != nullptr) { + hapticBody->addTarget(std::get<0>(layout[0]), new FloatPlane({ { std::get<1>(layout[0]), thumb } })); + } - if (index != nullptr) { - hapticBody->addTarget(std::get<0>(layout[1]), new FloatPlane({ { std::get<1>(layout[1]), index } })); - } + if (index != nullptr) { + hapticBody->addTarget(std::get<0>(layout[1]), new FloatPlane({ { std::get<1>(layout[1]), index } })); + } - if (middle != nullptr) { - hapticBody->addTarget(std::get<0>(layout[2]), new FloatPlane({ { std::get<1>(layout[2]), middle } })); - } + if (middle != nullptr) { + hapticBody->addTarget(std::get<0>(layout[2]), new FloatPlane({ { std::get<1>(layout[2]), middle } })); + } - if (ring != nullptr) { - hapticBody->addTarget(std::get<0>(layout[3]), new FloatPlane({ { std::get<1>(layout[3]), ring } })); - } + if (ring != nullptr) { + hapticBody->addTarget(std::get<0>(layout[3]), new FloatPlane({ { std::get<1>(layout[3]), ring } })); + } - if (little != nullptr) { - hapticBody->addTarget(std::get<0>(layout[4]), new FloatPlane({ { std::get<1>(layout[4]), little } })); - } + if (little != nullptr) { + hapticBody->addTarget(std::get<0>(layout[4]), new FloatPlane({ { std::get<1>(layout[4]), little } })); + } - if (wrist != nullptr) { - hapticBody->addTarget(std::get<0>(layout[5]), new FloatPlane({ { std::get<1>(layout[5]), wrist } })); - } + if (wrist != nullptr) { + hapticBody->addTarget(std::get<0>(layout[5]), new FloatPlane({ { std::get<1>(layout[5]), wrist } })); } +} } // namespace SenseShift::BH diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index e23a55f3..9623fbc0 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -11,195 +11,193 @@ #include namespace SenseShift::BH { - class Decoder { - public: - using VibroEffectData = ::SenseShift::Body::Haptics::VibroEffectData; - - using Effect = ::SenseShift::Body::Haptics::Effect; - using Target = ::SenseShift::Body::Haptics::Target; - using Position = ::SenseShift::Body::Haptics::Position; - - using OutputLayout = std::tuple; - - static constexpr size_t VEST_LAYOUT_SIZE = 40; - static constexpr size_t VEST_PAYLOAD_SIZE = 20; - - template - static void applyPlain( - FloatBody* output, - const std::array& value, - const std::array& layout, - const Effect effect - ) - { - for (size_t i = 0; i < N; i++) { - const auto [target, position] = layout[i]; - const std::uint8_t byte = value[i]; - - output->effect(target, position, static_cast(effectDataFromByte(byte))); - } +class Decoder { + public: + using VibroEffectData = ::SenseShift::Body::Haptics::VibroEffectData; + + using Effect = ::SenseShift::Body::Haptics::Effect; + using Target = ::SenseShift::Body::Haptics::Target; + using Position = ::SenseShift::Body::Haptics::Position; + + using OutputLayout = std::tuple; + + static constexpr size_t VEST_LAYOUT_SIZE = 40; + static constexpr size_t VEST_PAYLOAD_SIZE = 20; + + template + static void applyPlain( + FloatBody* output, + const std::array& value, + const std::array& layout, + const Effect effect + ) + { + for (size_t i = 0; i < N; i++) { + const auto [target, position] = layout[i]; + const std::uint8_t byte = value[i]; + + output->effect(target, position, static_cast(effectDataFromByte(byte))); } - - template - static void applyPlain( - FloatBody* output, std::string& value, const std::array& layout, const Effect effect - ) - { - std::array buf{}; - std::size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf.data(), value.c_str(), copyLength); - - applyPlain(output, buf, layout, effect); + } + + template + static void + applyPlain(FloatBody* output, std::string& value, const std::array& layout, const Effect effect) + { + std::array buf{}; + std::size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf.data(), value.c_str(), copyLength); + + applyPlain(output, buf, layout, effect); + } + + /** + * Apply plain-encoded data to the output. + */ + template + static void applyPlain( + FloatBody* output, + const std::array& value, + const std::array& layout, + const Effect effect, + const Target target + ) + { + for (size_t i = 0; i < N; i++) { + const auto position = layout[i]; + const uint8_t byte = value[i]; + + output->effect(target, position, static_cast(effectDataFromByte(byte))); } - - /** - * Apply plain-encoded data to the output. - */ - template - static void applyPlain( - FloatBody* output, - const std::array& value, - const std::array& layout, - const Effect effect, - const Target target - ) - { - for (size_t i = 0; i < N; i++) { - const auto position = layout[i]; - const uint8_t byte = value[i]; - - output->effect(target, position, static_cast(effectDataFromByte(byte))); - } + } + + template + static void applyPlain( + FloatBody* output, + std::string& value, + const std::array& layout, + const Effect effect, + const Target target + ) + { + std::array buf{}; + std::size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf.data(), value.c_str(), copyLength); + + applyPlain(output, buf, layout, effect, target); + } + + /** + * Apply vest-encoded data to the output. + */ + static void applyVest( + FloatBody* output, + const std::array& value, + const std::array& layout + ) + { + for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { + const std::uint8_t byte = value[i]; + const size_t actIndex = i * 2; + + output->effect( + std::get<0>(layout[actIndex]), + std::get<1>(layout[actIndex]), + static_cast(effectDataFromByte(((byte >> 4) & 0xf), 15)) + ); + output->effect( + std::get<0>(layout[actIndex + 1]), + std::get<1>(layout[actIndex + 1]), + static_cast(effectDataFromByte((byte & 0xf), 15).getIntensity()) + ); } - - template - static void applyPlain( - FloatBody* output, - std::string& value, - const std::array& layout, - const Effect effect, - const Target target - ) - { - std::array buf{}; - std::size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf.data(), value.c_str(), copyLength); - - applyPlain(output, buf, layout, effect, target); + } + + static void + applyVest(FloatBody* output, std::string& value, const std::array& layout) + { + std::array buf{}; + const size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf.data(), value.c_str(), copyLength); + + applyVest(output, buf, layout); + } + + /** + * Apply grouped vest-encoded data to the output. + */ + template + static void applyVestGrouped( + FloatBody* output, + const std::array& value, + const std::array& layout, + const std::array& layoutGroups + ) + { + std::array result{}; + + // Unpack values + for (auto i = 0; i < VEST_PAYLOAD_SIZE; i++) { + const std::uint8_t byte = value[i]; + const size_t actIndex = i * 2; + + result[actIndex] = (byte >> 4) & 0xf; + result[actIndex + 1] = (byte & 0xf); } - /** - * Apply vest-encoded data to the output. - */ - static void applyVest( - FloatBody* output, - const std::array& value, - const std::array& layout - ) - { - for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { - const std::uint8_t byte = value[i]; - const size_t actIndex = i * 2; - - output->effect( - std::get<0>(layout[actIndex]), - std::get<1>(layout[actIndex]), - static_cast(effectDataFromByte(((byte >> 4) & 0xf), 15)) - ); - output->effect( - std::get<0>(layout[actIndex + 1]), - std::get<1>(layout[actIndex + 1]), - static_cast(effectDataFromByte((byte & 0xf), 15).getIntensity()) - ); - } - } + // Assign max value into each group + for (auto i = 0; i < N; i++) { + auto groupIndex = layoutGroups[i]; - static void - applyVest(FloatBody* output, std::string& value, const std::array& layout) - { - std::array buf{}; - const size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf.data(), value.c_str(), copyLength); + if (groupIndex % 10 >= 4) { + // Top 3 rows of x40 + auto maxValue = std::max({ result[groupIndex], result[groupIndex + 2], result[groupIndex + 4] }); - applyVest(output, buf, layout); - } + result[groupIndex] = maxValue; + result[groupIndex + 2] = maxValue; + result[groupIndex + 4] = maxValue; + } else { + // Bottom 2 rows of x40 + auto maxValue = std::max({ result[groupIndex], result[groupIndex + 2] }); - /** - * Apply grouped vest-encoded data to the output. - */ - template - static void applyVestGrouped( - FloatBody* output, - const std::array& value, - const std::array& layout, - const std::array& layoutGroups - ) - { - std::array result{}; - - // Unpack values - for (auto i = 0; i < VEST_PAYLOAD_SIZE; i++) { - const std::uint8_t byte = value[i]; - const size_t actIndex = i * 2; - - result[actIndex] = (byte >> 4) & 0xf; - result[actIndex + 1] = (byte & 0xf); + result[groupIndex] = maxValue; + result[groupIndex + 2] = maxValue; } + } - // Assign max value into each group - for (auto i = 0; i < N; i++) { - auto groupIndex = layoutGroups[i]; - - if (groupIndex % 10 >= 4) { - // Top 3 rows of x40 - auto maxValue = std::max({ result[groupIndex], result[groupIndex + 2], result[groupIndex + 4] }); - - result[groupIndex] = maxValue; - result[groupIndex + 2] = maxValue; - result[groupIndex + 4] = maxValue; - } else { - // Bottom 2 rows of x40 - auto maxValue = std::max({ result[groupIndex], result[groupIndex + 2] }); - - result[groupIndex] = maxValue; - result[groupIndex + 2] = maxValue; - } - } - - for (uint8_t i = 0; i < VEST_LAYOUT_SIZE; i++) { - // take only meaningful values - if (std::find(layoutGroups.begin(), layoutGroups.end(), i) == layoutGroups.end()) { - continue; - } - - const auto target = std::get<0>(layout[i]); - const auto position = std::get<1>(layout[i]); - - output - ->effect(target, position, static_cast(effectDataFromByte(result[i], 15))); + for (uint8_t i = 0; i < VEST_LAYOUT_SIZE; i++) { + // take only meaningful values + if (std::find(layoutGroups.begin(), layoutGroups.end(), i) == layoutGroups.end()) { + continue; } - } - template - static void applyVestGrouped( - FloatBody* output, - std::string& value, - const std::array& layout, - const std::array& layoutGroups - ) - { - std::array buf{}; - const size_t copyLength = std::min(value.size(), sizeof(buf)); - std::memcpy(buf.data(), value.c_str(), copyLength); - - applyVestGrouped(output, buf, layout, layoutGroups); - } + const auto target = std::get<0>(layout[i]); + const auto position = std::get<1>(layout[i]); - private: - static auto effectDataFromByte(const uint8_t byte, const uint8_t maxValue = 100) -> VibroEffectData - { - const auto value = static_cast(byte) / static_cast(maxValue); - return VibroEffectData(value); + output->effect(target, position, static_cast(effectDataFromByte(result[i], 15))); } - }; + } + + template + static void applyVestGrouped( + FloatBody* output, + std::string& value, + const std::array& layout, + const std::array& layoutGroups + ) + { + std::array buf{}; + const size_t copyLength = std::min(value.size(), sizeof(buf)); + std::memcpy(buf.data(), value.c_str(), copyLength); + + applyVestGrouped(output, buf, layout, layoutGroups); + } + + private: + static auto effectDataFromByte(const uint8_t byte, const uint8_t maxValue = 100) -> VibroEffectData + { + const auto value = static_cast(byte) / static_cast(maxValue); + return VibroEffectData(value); + } +}; } // namespace SenseShift::BH diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index 7de8c70a..cf765d43 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -27,265 +27,268 @@ #endif namespace SenseShift::BH::BLE { - class BHServerCallbacks final : public BLEServerCallbacks { - private: - ::SenseShift::IEventDispatcher* dispatcher; +class BHServerCallbacks final : public BLEServerCallbacks { + private: + ::SenseShift::IEventDispatcher* dispatcher; - public: - BHServerCallbacks(::SenseShift::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) {} + public: + BHServerCallbacks(::SenseShift::IEventDispatcher* eventDispatcher) : dispatcher(eventDispatcher) + { + } - void onConnect(BLEServer* pServer) - { - this->dispatcher->postEvent(new ::SenseShift::IEvent(OH_EVENT_CONNECTED)); - } + void onConnect(BLEServer* pServer) + { + this->dispatcher->postEvent(new ::SenseShift::IEvent(OH_EVENT_CONNECTED)); + } - void onDisconnect(BLEServer* pServer) - { - this->dispatcher->postEvent(new ::SenseShift::IEvent(OH_EVENT_DISCONNECTED)); - pServer->startAdvertising(); - } - }; + void onDisconnect(BLEServer* pServer) + { + this->dispatcher->postEvent(new ::SenseShift::IEvent(OH_EVENT_DISCONNECTED)); + pServer->startAdvertising(); + } +}; - class LogOutputCharCallbacks : public BLECharacteristicCallbacks { - void onWrite(BLECharacteristic* pCharacteristic) override - { - log_d( - ">>\tonWrite (UUID: %s)\n\tvalue: `%s`, len: %u", - pCharacteristic->getUUID().toString().c_str(), - pCharacteristic->getValue().c_str(), - pCharacteristic->getValue().length() - ); - }; +class LogOutputCharCallbacks : public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic* pCharacteristic) override + { + log_d( + ">>\tonWrite (UUID: %s)\n\tvalue: `%s`, len: %u", + pCharacteristic->getUUID().toString().c_str(), + pCharacteristic->getValue().c_str(), + pCharacteristic->getValue().length() + ); + }; - void onRead(BLECharacteristic* pCharacteristic) override - { - log_d( - ">>\tonRead (UUID: %s)\n\tvalue: `%s`, len: %u", - pCharacteristic->getUUID().toString().c_str(), - pCharacteristic->getValue().c_str(), - pCharacteristic->getValue().length() - ); - }; + void onRead(BLECharacteristic* pCharacteristic) override + { + log_d( + ">>\tonRead (UUID: %s)\n\tvalue: `%s`, len: %u", + pCharacteristic->getUUID().toString().c_str(), + pCharacteristic->getValue().c_str(), + pCharacteristic->getValue().length() + ); + }; - void onNotify(BLECharacteristic* pCharacteristic) override - { - log_d( - ">>\tonNotify (UUID: %s)\n\tvalue: `%s`, len: %u", - pCharacteristic->getUUID().toString().c_str(), - pCharacteristic->getValue().c_str(), - pCharacteristic->getValue().length() - ); - }; + void onNotify(BLECharacteristic* pCharacteristic) override + { + log_d( + ">>\tonNotify (UUID: %s)\n\tvalue: `%s`, len: %u", + pCharacteristic->getUUID().toString().c_str(), + pCharacteristic->getValue().c_str(), + pCharacteristic->getValue().length() + ); + }; #if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true - void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override + void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override #else - void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) override + void onStatus(BLECharacteristic* pCharacteristic, Status s, uint32_t code) override #endif - { - log_d( - ">>\tonNotify (UUID: %s)\n\tstatus: %d, code: %u \n\tvalue: `%s`, len: %u", - pCharacteristic->getUUID().toString().c_str(), - s, - code, - pCharacteristic->getValue().c_str(), - pCharacteristic->getValue().length() - ); - }; + { + log_d( + ">>\tonNotify (UUID: %s)\n\tstatus: %d, code: %u \n\tvalue: `%s`, len: %u", + pCharacteristic->getUUID().toString().c_str(), + s, + code, + pCharacteristic->getValue().c_str(), + pCharacteristic->getValue().length() + ); }; +}; - class MotorCharCallbacks : public BLECharacteristicCallbacks { - private: - Connection::MotorHandler motorTransformer; +class MotorCharCallbacks : public BLECharacteristicCallbacks { + private: + Connection::MotorHandler motorTransformer; - public: - MotorCharCallbacks(Connection::MotorHandler motorTransformer) : motorTransformer(motorTransformer) {} + public: + MotorCharCallbacks(Connection::MotorHandler motorTransformer) : motorTransformer(motorTransformer) + { + } - void onWrite(BLECharacteristic* pCharacteristic) override - { - auto value = pCharacteristic->getValue(); - std::string valueStr(value.begin(), value.end()); + void onWrite(BLECharacteristic* pCharacteristic) override + { + auto value = pCharacteristic->getValue(); + std::string valueStr(value.begin(), value.end()); - this->motorTransformer(valueStr); - }; + this->motorTransformer(valueStr); }; +}; - class ConfigCharCallbacks : public BLECharacteristicCallbacks { - void onWrite(BLECharacteristic* pCharacteristic) override - { - auto value = pCharacteristic->getValue(); +class ConfigCharCallbacks : public BLECharacteristicCallbacks { + void onWrite(BLECharacteristic* pCharacteristic) override + { + auto value = pCharacteristic->getValue(); - if (value.length() != 3) { - return; - } + if (value.length() != 3) { + return; + } - auto byte_0 = value[0], byte_1 = value[1], byte_2 = value[2]; + auto byte_0 = value[0], byte_1 = value[1], byte_2 = value[2]; - log_d(">>\tonWrite (Config Char): %3hhu %2hhu %2hhu", byte_0, byte_1, byte_2); - }; + log_d(">>\tonWrite (Config Char): %3hhu %2hhu %2hhu", byte_0, byte_1, byte_2); }; +}; - void Connection::begin() - { - BLEDevice::init(this->config.deviceName); +void Connection::begin() +{ + BLEDevice::init(this->config.deviceName); - this->callbacks->postInit(); + this->callbacks->postInit(); - this->bleServer = BLEDevice::createServer(); + this->bleServer = BLEDevice::createServer(); - this->bleServer->setCallbacks(new BHServerCallbacks(this->eventDispatcher)); + this->bleServer->setCallbacks(new BHServerCallbacks(this->eventDispatcher)); - auto scanResponseData = new BLEAdvertisementData(); - scanResponseData->setAppearance(this->config.appearance); - scanResponseData->setName(this->config.deviceName); + auto scanResponseData = new BLEAdvertisementData(); + scanResponseData->setAppearance(this->config.appearance); + scanResponseData->setName(this->config.deviceName); - this->bleServer->getAdvertising()->setAppearance(this->config.appearance); - this->bleServer->getAdvertising()->setScanResponseData(*scanResponseData); + this->bleServer->getAdvertising()->setAppearance(this->config.appearance); + this->bleServer->getAdvertising()->setScanResponseData(*scanResponseData); // Each characteristic needs 2 handles and descriptor 1 handle. #if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true - this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID); + this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID); #else - this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID, 30, 0); + this->motorService = this->bleServer->createService(BH_BLE_SERVICE_MOTOR_UUID, 30, 0); #endif - { - MotorCharCallbacks* motorCallbacks = new MotorCharCallbacks(this->motorHandler); + { + MotorCharCallbacks* motorCallbacks = new MotorCharCallbacks(this->motorHandler); - auto* motorChar = - this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_UUID, PROPERTY_WRITE_NR); - motorChar->setCallbacks(motorCallbacks); + auto* motorChar = + this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_UUID, PROPERTY_WRITE_NR); + motorChar->setCallbacks(motorCallbacks); - auto* motorCharStable = - this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_STABLE_UUID, PROPERTY_WRITE); - motorCharStable->setCallbacks(motorCallbacks); - } + auto* motorCharStable = + this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_MOTOR_STABLE_UUID, PROPERTY_WRITE); + motorCharStable->setCallbacks(motorCallbacks); + } - { - auto* configChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_CONFIG_UUID, - PROPERTY_READ | PROPERTY_WRITE - ); - configChar->setCallbacks(new ConfigCharCallbacks()); - - uint8_t config[3] = { - 0, // byte 0 - ? - 0, // byte 1 - ? - 0, // byte 2 - color, - // but for tactosy it is switching left/right position - }; - configChar->setValue(config, 3); - } + { + auto* configChar = this->motorService->createCharacteristic( + BH_BLE_SERVICE_MOTOR_CHAR_CONFIG_UUID, + PROPERTY_READ | PROPERTY_WRITE + ); + configChar->setCallbacks(new ConfigCharCallbacks()); + + uint8_t config[3] = { + 0, // byte 0 - ? + 0, // byte 1 - ? + 0, // byte 2 - color, + // but for tactosy it is switching left/right position + }; + configChar->setValue(config, 3); + } - { - auto* serialNumberChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, - PROPERTY_READ | PROPERTY_WRITE - ); - uint8_t serialNumber[ConnectionConfig::SN_LENGTH]; - memcpy(serialNumber, this->config.serialNumber, ConnectionConfig::SN_LENGTH); - serialNumberChar->setValue(serialNumber, ConnectionConfig::SN_LENGTH); - serialNumberChar->setCallbacks(new LogOutputCharCallbacks()); - } + { + auto* serialNumberChar = this->motorService->createCharacteristic( + BH_BLE_SERVICE_MOTOR_CHAR_SERIAL_KEY_UUID, + PROPERTY_READ | PROPERTY_WRITE + ); + uint8_t serialNumber[ConnectionConfig::SN_LENGTH]; + memcpy(serialNumber, this->config.serialNumber, ConnectionConfig::SN_LENGTH); + serialNumberChar->setValue(serialNumber, ConnectionConfig::SN_LENGTH); + serialNumberChar->setCallbacks(new LogOutputCharCallbacks()); + } - { - this->batteryChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_BATTERY_UUID, - PROPERTY_READ | PROPERTY_WRITE_NR - | PROPERTY_NOTIFY // for whatever reason, it have to be writable, otherwise Desktop app crashes - ); + { + this->batteryChar = this->motorService->createCharacteristic( + BH_BLE_SERVICE_MOTOR_CHAR_BATTERY_UUID, + PROPERTY_READ | PROPERTY_WRITE_NR + | PROPERTY_NOTIFY // for whatever reason, it have to be writable, otherwise Desktop app crashes + ); #if !defined(SS_USE_NIMBLE) || SS_USE_NIMBLE != true - batteryChar->addDescriptor(new BLE2902()); + batteryChar->addDescriptor(new BLE2902()); #endif - // original bHaptics Player requires a non-null value for battery level; otherwise, it crashes - uint16_t defaultLevel = 100; + // original bHaptics Player requires a non-null value for battery level; otherwise, it crashes + uint16_t defaultLevel = 100; - this->batteryChar->setValue(defaultLevel); - // this->batteryChar->notify(); - } + this->batteryChar->setValue(defaultLevel); + // this->batteryChar->notify(); + } - { - auto* versionChar = - this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_VERSION_UUID, PROPERTY_READ); - versionChar->setCallbacks(new LogOutputCharCallbacks()); - uint16_t firmwareVersion = BH_FIRMWARE_VERSION; - versionChar->setValue(firmwareVersion); - } + { + auto* versionChar = + this->motorService->createCharacteristic(BH_BLE_SERVICE_MOTOR_CHAR_VERSION_UUID, PROPERTY_READ); + versionChar->setCallbacks(new LogOutputCharCallbacks()); + uint16_t firmwareVersion = BH_FIRMWARE_VERSION; + versionChar->setValue(firmwareVersion); + } - { - auto* monitorChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_TACTSUIT_MONITOR_UUID, - PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE - | PROPERTY_WRITE_NR - ); - monitorChar->setCallbacks(new LogOutputCharCallbacks()); + { + auto* monitorChar = this->motorService->createCharacteristic( + BH_BLE_SERVICE_MOTOR_CHAR_TACTSUIT_MONITOR_UUID, + PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | PROPERTY_WRITE_NR + ); + monitorChar->setCallbacks(new LogOutputCharCallbacks()); #if !defined(SS_USE_NIMBLE) || SS_USE_NIMBLE != true - monitorChar->addDescriptor(new BLE2902()); + monitorChar->addDescriptor(new BLE2902()); #endif - // bit 7 - audio jack (0: off, 1: on) - uint8_t status = 0b00000000; + // bit 7 - audio jack (0: off, 1: on) + uint8_t status = 0b00000000; - uint8_t value[1] = { status }; - monitorChar->setValue(value, 1); - } + uint8_t value[1] = { status }; + monitorChar->setValue(value, 1); + } - { - auto* athGlobalChar = this->motorService->createCharacteristic( - BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID, - PROPERTY_READ | PROPERTY_WRITE - ); - athGlobalChar->setCallbacks(new LogOutputCharCallbacks()); - - uint8_t athGlobalConfig[20] = { - 0, // byte 0 - ? - 0, // byte 1 - VSM - 0, // byte 2 - AthConfigIndex - 0, // byte 3 - AthConfigIndex - 0, // byte 4 - SignaturePatternOnOff (0: off, 1: on) - 0, // byte 5 - WaitMinutes - 0, // byte 6 - DisableEmbedAth (0: off, 1: on) - 0, // byte 7 - ButtonLock (0: off, 1: on) - 0, // byte 8 - LedInfo - }; - - athGlobalChar->setValue(athGlobalConfig, 20); - } + { + auto* athGlobalChar = this->motorService->createCharacteristic( + BH_BLE_SERVICE_MOTOR_CHAR_ATH_GLOBAL_CONF_UUID, + PROPERTY_READ | PROPERTY_WRITE + ); + athGlobalChar->setCallbacks(new LogOutputCharCallbacks()); + + uint8_t athGlobalConfig[20] = { + 0, // byte 0 - ? + 0, // byte 1 - VSM + 0, // byte 2 - AthConfigIndex + 0, // byte 3 - AthConfigIndex + 0, // byte 4 - SignaturePatternOnOff (0: off, 1: on) + 0, // byte 5 - WaitMinutes + 0, // byte 6 - DisableEmbedAth (0: off, 1: on) + 0, // byte 7 - ButtonLock (0: off, 1: on) + 0, // byte 8 - LedInfo + }; - // auto* athThemeChar = this->motorService->createCharacteristic( - // BH_BLE_SERVICE_MOTOR_CHAR_ATH_THEME_UUID, - // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | - // PROPERTY_WRITE_NR - // ); - // athThemeChar->setCallbacks(new LogOutputCharCallbacks()); - - // auto* motorMappingChar = this->motorService->createCharacteristic( - // BH_BLE_SERVICE_MOTOR_CHAR_MOTTOR_MAPPING_UUID, - // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | - // PROPERTY_WRITE_NR - // ); - // motorMappingChar->setCallbacks(new LogOutputCharCallbacks()); - - // auto* signatureMappingChar = this->motorService->createCharacteristic( - // BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_UUID, - // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | - // PROPERTY_WRITE_NR - // ); - // signatureMappingChar->setCallbacks(new LogOutputCharCallbacks()); - - this->motorService->start(); - - { - auto dfuService = this->bleServer->createService(BH_BLE_SERVICE_DFU_UUID); - - auto* dfuControlChar = - dfuService->createCharacteristic(BH_BLE_SERVICE_DFU_CHAR_CONTROL_UUID, PROPERTY_READ | PROPERTY_WRITE); - dfuService->start(); - } + athGlobalChar->setValue(athGlobalConfig, 20); + } + + // auto* athThemeChar = this->motorService->createCharacteristic( + // BH_BLE_SERVICE_MOTOR_CHAR_ATH_THEME_UUID, + // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | + // PROPERTY_WRITE_NR + // ); + // athThemeChar->setCallbacks(new LogOutputCharCallbacks()); + + // auto* motorMappingChar = this->motorService->createCharacteristic( + // BH_BLE_SERVICE_MOTOR_CHAR_MOTTOR_MAPPING_UUID, + // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | + // PROPERTY_WRITE_NR + // ); + // motorMappingChar->setCallbacks(new LogOutputCharCallbacks()); + + // auto* signatureMappingChar = this->motorService->createCharacteristic( + // BH_BLE_SERVICE_MOTOR_CHAR_SIGNATURE_PATTERN_UUID, + // PROPERTY_READ | PROPERTY_WRITE | PROPERTY_NOTIFY | PROPERTY_BROADCAST | PROPERTY_INDICATE | + // PROPERTY_WRITE_NR + // ); + // signatureMappingChar->setCallbacks(new LogOutputCharCallbacks()); + + this->motorService->start(); - this->bleServer->getAdvertising()->start(); + { + auto dfuService = this->bleServer->createService(BH_BLE_SERVICE_DFU_UUID); + + auto* dfuControlChar = + dfuService->createCharacteristic(BH_BLE_SERVICE_DFU_CHAR_CONTROL_UUID, PROPERTY_READ | PROPERTY_WRITE); + dfuService->start(); } + + this->bleServer->getAdvertising()->start(); +} } // namespace SenseShift::BH::BLE diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index a572f63b..f6d1999b 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -17,69 +17,72 @@ #endif namespace SenseShift::BH::BLE { - struct ConnectionConfig { - static constexpr size_t SN_LENGTH = 10; +struct ConnectionConfig { + static constexpr size_t SN_LENGTH = 10; #if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true - std::string deviceName; + std::string deviceName; #else - String deviceName; + String deviceName; #endif - uint16_t appearance; - uint8_t serialNumber[SN_LENGTH]; - }; + uint16_t appearance; + uint8_t serialNumber[SN_LENGTH]; +}; - class ConnectionCallbacks { - public: - virtual void postInit() { log_v("Default postInit"); }; +class ConnectionCallbacks { + public: + virtual void postInit() + { + log_v("Default postInit"); }; - static ConnectionCallbacks defaultCallback; +}; +static ConnectionCallbacks defaultCallback; - class Connection final : public IEventListener { - public: - using MotorHandler = std::function; +class Connection final : public IEventListener { + public: + using MotorHandler = std::function; - Connection(const ConnectionConfig& config, MotorHandler motorHandler, IEventDispatcher* eventDispatcher) : - config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) - { - this->eventDispatcher->addEventListener(this); - }; + Connection(const ConnectionConfig& config, MotorHandler motorHandler, IEventDispatcher* eventDispatcher) : + config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) + { + this->eventDispatcher->addEventListener(this); + }; - void begin(void); - void handleEvent(const IEvent* event) const override - { - if (event->eventName == OH_EVENT_BATTERY_LEVEL) { - uint16_t level = remap_simple( - static_cast(event)->state.level, - ::SenseShift::Battery::BatteryState::MAX_LEVEL, - 100 - ); + void begin(void); + void handleEvent(const IEvent* event) const override + { + if (event->eventName == OH_EVENT_BATTERY_LEVEL) { + uint16_t level = remap_simple( + static_cast(event)->state.level, + ::SenseShift::Battery::BatteryState::MAX_LEVEL, + 100 + ); - this->batteryChar->setValue(level); - this->batteryChar->notify(); + this->batteryChar->setValue(level); + this->batteryChar->notify(); - return; - } - }; + return; + } + }; - void setCallbacks(ConnectionCallbacks* pCallbacks) - { - if (pCallbacks != nullptr) { - this->callbacks = pCallbacks; - } else { - this->callbacks = &defaultCallback; - } - }; + void setCallbacks(ConnectionCallbacks* pCallbacks) + { + if (pCallbacks != nullptr) { + this->callbacks = pCallbacks; + } else { + this->callbacks = &defaultCallback; + } + }; - private: - const ConnectionConfig& config; - MotorHandler motorHandler; - ::SenseShift::IEventDispatcher* eventDispatcher; + private: + const ConnectionConfig& config; + MotorHandler motorHandler; + ::SenseShift::IEventDispatcher* eventDispatcher; - BLEServer* bleServer = nullptr; - BLEService* motorService = nullptr; - BLECharacteristic* batteryChar = nullptr; + BLEServer* bleServer = nullptr; + BLEService* motorService = nullptr; + BLECharacteristic* batteryChar = nullptr; - ConnectionCallbacks* callbacks = &defaultCallback; - }; + ConnectionCallbacks* callbacks = &defaultCallback; +}; } // namespace SenseShift::BH::BLE diff --git a/lib/core/senseshift/core/component.hpp b/lib/core/senseshift/core/component.hpp index 8ead9f04..fdd495c3 100644 --- a/lib/core/senseshift/core/component.hpp +++ b/lib/core/senseshift/core/component.hpp @@ -10,36 +10,40 @@ } namespace SenseShift { - class IInitializable { - public: - virtual ~IInitializable() = default; +class IInitializable { + public: + virtual ~IInitializable() = default; - virtual void init() = 0; - }; + virtual void init() = 0; +}; - class ITickable { - public: - virtual ~ITickable() = default; +class ITickable { + public: + virtual ~ITickable() = default; - virtual void tick() = 0; - }; + virtual void tick() = 0; +}; - class Component : public virtual IInitializable, public virtual ITickable { - public: - /// @brief Initialize the component. - /// - /// Where the component's initialization should happen. - /// Analogous to Arduino's setup(). This method is guaranteed to only be called once. - /// - /// Defaults to doing nothing. - void init() override {} +class Component : public virtual IInitializable, public virtual ITickable { + public: + /// @brief Initialize the component. + /// + /// Where the component's initialization should happen. + /// Analogous to Arduino's setup(). This method is guaranteed to only be called once. + /// + /// Defaults to doing nothing. + void init() override + { + } - /// @brief Tick the component. - /// - /// This method will be called repeatedly. - /// Analogous to Arduino's loop(). init() is guaranteed to be called before this. - /// - /// Defaults to doing nothing. - void tick() override {} - }; + /// @brief Tick the component. + /// + /// This method will be called repeatedly. + /// Analogous to Arduino's loop(). init() is guaranteed to be called before this. + /// + /// Defaults to doing nothing. + void tick() override + { + } +}; } // namespace SenseShift diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index 2ce47264..83b62075 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -7,129 +7,135 @@ #include namespace SenseShift { - /// Linearly interpolate between \p start and \p end by \p completion (between 0 and 1). - template - constexpr auto lerp(const float completion, const Tp start, const Tp end) -> Tp - { - static_assert(std::is_arithmetic_v, "Type must be arithmetic"); - - return start + (end - start) * completion; +/// Linearly interpolate between \p start and \p end by \p completion (between 0 and 1). +template +constexpr auto lerp(const float completion, const Tp start, const Tp end) -> Tp +{ + static_assert(std::is_arithmetic_v, "Type must be arithmetic"); + + return start + (end - start) * completion; +} + +/// Remap \p value from the range (\p min, \p max) to (\p min_out, \p max_out). +/// +/// \tparam Tp The output type. +/// \tparam Up The input type. +/// +/// \param value The value to remap. +/// \param min The minimum value of the input range. +/// \param max The maximum value of the input range. +/// \param min_out The minimum value of the output range. +/// \param max_out The maximum value of the output range. +/// +/// \return The remapped value. +template +constexpr auto remap(Up value, Up min, Up max, Tp min_out, Tp max_out) -> Tp +{ + static_assert(std::is_arithmetic_v, "Type must be arithmetic"); + static_assert(std::is_arithmetic_v, "Type must be arithmetic"); + + if (max <= min) { + LOG_E("util.remap", "Invalid input range, min <= max"); + return (min_out + max_out) / 2; } - /// Remap \p value from the range (\p min, \p max) to (\p min_out, \p max_out). - /// - /// \tparam Tp The output type. - /// \tparam Up The input type. - /// - /// \param value The value to remap. - /// \param min The minimum value of the input range. - /// \param max The maximum value of the input range. - /// \param min_out The minimum value of the output range. - /// \param max_out The maximum value of the output range. - /// - /// \return The remapped value. - template - constexpr auto remap(Up value, Up min, Up max, Tp min_out, Tp max_out) -> Tp - { - static_assert(std::is_arithmetic_v, "Type must be arithmetic"); - static_assert(std::is_arithmetic_v, "Type must be arithmetic"); - - if (max <= min) { - LOG_E("util.remap", "Invalid input range, min <= max"); - return (min_out + max_out) / 2; - } - - return (value - min) * (max_out - min_out) / (max - min) + min_out; + return (value - min) * (max_out - min_out) / (max - min) + min_out; +} + +/// Remap \p value from the range (0, \p max) to (0, \p max_out). +/// +/// \tparam Tp The output type. +/// \tparam Up The input type. +/// +/// \param value The value to remap. +/// \param max The maximum value of the input range. +/// \param max_out The maximum value of the output range. +/// +/// \return The remapped value. +/// +/// \note This is a simplified version of remap() where the minimum values are 0. +template +constexpr auto remap_simple(Up value, Up max, Tp max_out) noexcept -> Tp +{ + static_assert(std::is_arithmetic_v, "Type must be arithmetic"); + static_assert(std::is_arithmetic_v, "Type must be arithmetic"); + + return value * max_out / max; +} + +/// Lookup a value in a table and interpolate between the two closest values. +/// +/// \tparam Container The type of the lookup table. +/// \tparam Tp The type of the lookup table keys. +/// \tparam To The type of the lookup table values. +/// +/// \param lookup_table Lookup table to use in the format of std::map in descending order. +/// \param value +/// +/// \return +template +[[nodiscard]] constexpr auto lookup_table_interpolate_linear(Container const& lookup_table, Tp value) -> To +{ + static_assert(std::is_same_v && std::is_same_v); + static_assert( + std::is_arithmetic_v && std::is_arithmetic_v, + "lookup_table_interpolate_linear only supports arithmetic types" + ); + + // If the value is outside the range of the lookup table, return the closest value + if (value <= lookup_table.begin()->first) { + return lookup_table.begin()->second; + } + if (value >= lookup_table.rbegin()->first) { + return lookup_table.rbegin()->second; } - /// Remap \p value from the range (0, \p max) to (0, \p max_out). - /// - /// \tparam Tp The output type. - /// \tparam Up The input type. - /// - /// \param value The value to remap. - /// \param max The maximum value of the input range. - /// \param max_out The maximum value of the output range. - /// - /// \return The remapped value. - /// - /// \note This is a simplified version of remap() where the minimum values are 0. - template - constexpr auto remap_simple(Up value, Up max, Tp max_out) noexcept -> Tp - { - static_assert(std::is_arithmetic_v, "Type must be arithmetic"); - static_assert(std::is_arithmetic_v, "Type must be arithmetic"); + // Find the two closest values in the lookup table + auto const upper = lookup_table.lower_bound(value); + auto const lower = std::prev(upper); - return value * max_out / max; - } + // Interpolate between the two closest values + float const completion = (value - lower->first) / (upper->first - lower->first); - /// Lookup a value in a table and interpolate between the two closest values. - /// - /// \tparam Container The type of the lookup table. - /// \tparam Tp The type of the lookup table keys. - /// \tparam To The type of the lookup table values. - /// - /// \param lookup_table Lookup table to use in the format of std::map in descending order. - /// \param value - /// - /// \return - template< - typename Container, - typename Tp = typename Container::key_type, - typename To = typename Container::mapped_type> - [[nodiscard]] constexpr auto lookup_table_interpolate_linear(Container const& lookup_table, Tp value) -> To - { - static_assert(std::is_same_v && std::is_same_v); - static_assert( - std::is_arithmetic_v && std::is_arithmetic_v, - "lookup_table_interpolate_linear only supports arithmetic types" - ); - - // If the value is outside the range of the lookup table, return the closest value - if (value <= lookup_table.begin()->first) { - return lookup_table.begin()->second; - } - if (value >= lookup_table.rbegin()->first) { - return lookup_table.rbegin()->second; - } + return lerp(completion, lower->second, upper->second); +} - // Find the two closest values in the lookup table - auto const upper = lookup_table.lower_bound(value); - auto const lower = std::prev(upper); +template +class CallbackManager; - // Interpolate between the two closest values - float const completion = (value - lower->first) / (upper->first - lower->first); +/// Helper class to allow having multiple subscribers to a callback. +/// +/// \tparam Ts The arguments for the callbacks, wrapped in void(). +template +class CallbackManager { + public: + using CallbackType = std::function; - return lerp(completion, lower->second, upper->second); + /// Add a callback to the list. + void add(CallbackType&& callback) + { + this->callbacks_.push_back(std::move(callback)); } - template - class CallbackManager; - - /// Helper class to allow having multiple subscribers to a callback. - /// - /// \tparam Ts The arguments for the callbacks, wrapped in void(). - template - class CallbackManager { - public: - using CallbackType = std::function; - - /// Add a callback to the list. - void add(CallbackType&& callback) { this->callbacks_.push_back(std::move(callback)); } - - /// Call all callbacks in this manager. - void call(Ts... args) - { - for (auto& callback : this->callbacks_) { - callback(args...); - } + /// Call all callbacks in this manager. + void call(Ts... args) + { + for (auto& callback : this->callbacks_) { + callback(args...); } - [[nodiscard]] auto size() const -> size_t { return this->callbacks_.size(); } + } + [[nodiscard]] auto size() const -> size_t + { + return this->callbacks_.size(); + } - /// Call all callbacks in this manager. - void operator()(Ts... args) { call(args...); } + /// Call all callbacks in this manager. + void operator()(Ts... args) + { + call(args...); + } - private: - std::vector callbacks_; - }; + private: + std::vector callbacks_; +}; } // namespace SenseShift diff --git a/lib/core/senseshift/events.hpp b/lib/core/senseshift/events.hpp index f9f404f2..20134a91 100644 --- a/lib/core/senseshift/events.hpp +++ b/lib/core/senseshift/events.hpp @@ -11,24 +11,24 @@ // https://www.etlcpp.com/messages.html namespace SenseShift { - enum Event { +enum Event { - }; +}; - struct IEvent { - const std::string eventName; +struct IEvent { + const std::string eventName; - IEvent(const std::string eventName) : eventName(eventName){}; - }; + IEvent(const std::string eventName) : eventName(eventName){}; +}; - class IEventListener { - public: - virtual void handleEvent(const IEvent* event) const = 0; - }; +class IEventListener { + public: + virtual void handleEvent(const IEvent* event) const = 0; +}; - class IEventDispatcher { - public: - virtual void postEvent(const IEvent* event) = 0; - virtual void addEventListener(const IEventListener* handler) = 0; - }; +class IEventDispatcher { + public: + virtual void postEvent(const IEvent* event) = 0; + virtual void addEventListener(const IEventListener* handler) = 0; +}; } // namespace SenseShift diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index ee4f3028..52179c4a 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -27,138 +27,141 @@ BaseType_t xTaskCreateUniversal( #endif namespace SenseShift::FreeRTOS { - struct TaskConfig { - const char* name; - uint32_t stackDepth; - UBaseType_t priority; - const BaseType_t coreId = tskNO_AFFINITY; +struct TaskConfig { + const char* name; + uint32_t stackDepth; + UBaseType_t priority; + const BaseType_t coreId = tskNO_AFFINITY; +}; + +// Static polymorphic abstract base class for a FreeRTOS task using CRTP +// pattern. Concrete implementations should implement a run() method. +// +// Inspired by https://fjrg76.wordpress.com/2018/05/23/objectifying-task-creation-in-freertos-ii/ +template +class Task { + template + friend class Task; + + public: + explicit Task(TaskConfig& config) : taskConfig(config) + { + log_i("creating ComponentUpdateTask: %s", taskConfig.name); + }; + virtual ~Task() + { + if (taskHandle) { + vTaskDelete(taskHandle); + } }; - // Static polymorphic abstract base class for a FreeRTOS task using CRTP - // pattern. Concrete implementations should implement a run() method. - // - // Inspired by https://fjrg76.wordpress.com/2018/05/23/objectifying-task-creation-in-freertos-ii/ - template - class Task { - template - friend class Task; - - public: - explicit Task(TaskConfig& config) : taskConfig(config) - { - log_i("creating ComponentUpdateTask: %s", taskConfig.name); - }; - virtual ~Task() - { - if (taskHandle) { - vTaskDelete(taskHandle); - } - }; - - TaskHandle_t getHandle() const { return taskHandle; }; - - virtual void begin() - { - BaseType_t result = xTaskCreateUniversal( - taskFunction, //< pvTaskCode - this->taskConfig.name, //< pcName - this->taskConfig.stackDepth, //< usStackDepth - this, //< pvParameters - this->taskConfig.priority, //< uxPriority - &taskHandle, //< pvCreatedTask - this->taskConfig.coreId //< xCoreID + TaskHandle_t getHandle() const + { + return taskHandle; + }; + + virtual void begin() + { + BaseType_t result = xTaskCreateUniversal( + taskFunction, //< pvTaskCode + this->taskConfig.name, //< pcName + this->taskConfig.stackDepth, //< usStackDepth + this, //< pvParameters + this->taskConfig.priority, //< uxPriority + &taskHandle, //< pvCreatedTask + this->taskConfig.coreId //< xCoreID + ); + + log_i("Created task %s, result %i", this->taskConfig.name, result); + assert("Failed to create task" && result == pdPASS); + if (!taskHandle) { + log_e("Failed to create task %s", this->taskConfig.name); + } + }; + + protected: + inline void monitorTask() + { + log_i("----------------------------------------\nFree Heap: %d\n", xPortGetFreeHeapSize()); + volatile UBaseType_t uxArraySize = uxTaskGetNumberOfTasks(); + TaskStatus_t* pxTaskStatusArray = (TaskStatus_t*) pvPortMalloc(uxArraySize * sizeof(TaskStatus_t)); + if (!pxTaskStatusArray) { + log_e("Failed to allocate memory for task status array!"); + return; + } + uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, NULL); + for (UBaseType_t i = 0; i < uxArraySize; i++) { + log_i( + "Task: %s\n\tStack High Watermark: %d\n\tState: %d\n", + pxTaskStatusArray[i].pcTaskName, + pxTaskStatusArray[i].usStackHighWaterMark, + pxTaskStatusArray[i].eCurrentState ); - log_i("Created task %s, result %i", this->taskConfig.name, result); - assert("Failed to create task" && result == pdPASS); - if (!taskHandle) { - log_e("Failed to create task %s", this->taskConfig.name); - } - }; - - protected: - inline void monitorTask() - { - log_i("----------------------------------------\nFree Heap: %d\n", xPortGetFreeHeapSize()); - volatile UBaseType_t uxArraySize = uxTaskGetNumberOfTasks(); - TaskStatus_t* pxTaskStatusArray = (TaskStatus_t*) pvPortMalloc(uxArraySize * sizeof(TaskStatus_t)); - if (!pxTaskStatusArray) { - log_e("Failed to allocate memory for task status array!"); - return; - } - uxArraySize = uxTaskGetSystemState(pxTaskStatusArray, uxArraySize, NULL); - for (UBaseType_t i = 0; i < uxArraySize; i++) { - log_i( - "Task: %s\n\tStack High Watermark: %d\n\tState: %d\n", + if (pxTaskStatusArray[i].usStackHighWaterMark < 20) { + log_w( + "Warning: Task %s has low stack space, only %dB awailable!", pxTaskStatusArray[i].pcTaskName, - pxTaskStatusArray[i].usStackHighWaterMark, - pxTaskStatusArray[i].eCurrentState + pxTaskStatusArray[i].usStackHighWaterMark * 4 ); - - if (pxTaskStatusArray[i].usStackHighWaterMark < 20) { - log_w( - "Warning: Task %s has low stack space, only %dB awailable!", - pxTaskStatusArray[i].pcTaskName, - pxTaskStatusArray[i].usStackHighWaterMark * 4 - ); - } } - vPortFree(pxTaskStatusArray); - } - - private: - const TaskConfig& taskConfig; - TaskHandle_t taskHandle = nullptr; - - static void taskFunction(void* params) - { - _Tp* task = static_cast<_Tp*>(params); - task->run(); } + vPortFree(pxTaskStatusArray); + } + + private: + const TaskConfig& taskConfig; + TaskHandle_t taskHandle = nullptr; + + static void taskFunction(void* params) + { + _Tp* task = static_cast<_Tp*>(params); + task->run(); + } +}; + +template +class ComponentUpdateTask : public Task> { + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + public: + ComponentUpdateTask(Tp* component, std::uint32_t updateDelay, TaskConfig taskConfig) : + Task(taskConfig), component_(component), updateDelay_(updateDelay) + { + log_i("creating ComponentUpdateTask: %s", taskConfig.name); }; - template - class ComponentUpdateTask : public Task> { - static_assert(std::is_same_v); - static_assert(std::is_same_v); - - public: - ComponentUpdateTask(Tp* component, std::uint32_t updateDelay, TaskConfig taskConfig) : - Task(taskConfig), component_(component), updateDelay_(updateDelay) - { - log_i("creating ComponentUpdateTask: %s", taskConfig.name); - }; - - void begin() override - { - this->component_->init(); - this->Task::begin(); - } + void begin() override + { + this->component_->init(); + this->Task::begin(); + } - protected: - [[noreturn]] void run() - { - auto now = millis(); - auto targetHz = 1000 / this->updateDelay_; + protected: + [[noreturn]] void run() + { + auto now = millis(); + auto targetHz = 1000 / this->updateDelay_; - while (true) { - now = millis(); + while (true) { + now = millis(); - this->component_->tick(); + this->component_->tick(); - const auto elapsed = millis() - now; + const auto elapsed = millis() - now; - log_d("T: %d, Fmax: %dHz, Ft: %dHz", elapsed, 1000 / elapsed, targetHz); - if (elapsed < this->updateDelay_) { - delay(this->updateDelay_ - elapsed); - } + log_d("T: %d, Fmax: %dHz, Ft: %dHz", elapsed, 1000 / elapsed, targetHz); + if (elapsed < this->updateDelay_) { + delay(this->updateDelay_ - elapsed); } } + } - private: - friend class Task; + private: + friend class Task; - Tp* component_; - std::uint32_t updateDelay_; - }; + Tp* component_; + std::uint32_t updateDelay_; +}; } // namespace SenseShift::FreeRTOS diff --git a/lib/hands/senseshift/body/hands/hands_interface.hpp b/lib/hands/senseshift/body/hands/hands_interface.hpp index cee4877e..a5d67bdc 100644 --- a/lib/hands/senseshift/body/hands/hands_interface.hpp +++ b/lib/hands/senseshift/body/hands/hands_interface.hpp @@ -5,20 +5,20 @@ #include namespace SenseShift::Body::Hands { - using HandLateralityIndex = std::uint8_t; - enum class HandSide : HandLateralityIndex { Left, Right }; - using FingerIndex = std::uint8_t; - enum class Finger : FingerIndex { - Thumb, - Index, - Middle, - Ring, - Little, - }; +using HandLateralityIndex = std::uint8_t; +enum class HandSide : HandLateralityIndex { Left, Right }; +using FingerIndex = std::uint8_t; +enum class Finger : FingerIndex { + Thumb, + Index, + Middle, + Ring, + Little, +}; - namespace Haptics { - /// @brief Helper with position of the haptic device on the fingertip. - /// Distal phalanx of the volar surface of the any finger. - static constexpr const ::SenseShift::Body::Haptics::Position FINGERTIP_POSITION(127, 16); - } // namespace Haptics +namespace Haptics { +/// @brief Helper with position of the haptic device on the fingertip. +/// Distal phalanx of the volar surface of the any finger. +static constexpr const ::SenseShift::Body::Haptics::Position FINGERTIP_POSITION(127, 16); +} // namespace Haptics } // namespace SenseShift::Body::Hands diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp index aa4cb6ce..a9454864 100644 --- a/lib/hands_input/senseshift/body/hands/input/gesture.hpp +++ b/lib/hands_input/senseshift/body/hands/input/gesture.hpp @@ -5,105 +5,103 @@ #include namespace SenseShift::Body::Hands::Input { - using Gesture = ::SenseShift::Input::BinarySensor; +using Gesture = ::SenseShift::Input::BinarySensor; - /// An alias for semantic consistency. - using TriggerGesture = ::SenseShift::Input::AnalogThresholdSensor; +/// An alias for semantic consistency. +using TriggerGesture = ::SenseShift::Input::AnalogThresholdSensor; - class GrabGesture : public Gesture { - public: - struct Fingers { - ::SenseShift::Input::FloatSensor* index; - ::SenseShift::Input::FloatSensor* middle; - ::SenseShift::Input::FloatSensor* ring; - ::SenseShift::Input::FloatSensor* pinky; - }; - - explicit GrabGesture(Fingers fingers, float threshold = 0.5F, bool attach_callbacks = false) : - fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) - { - } +class GrabGesture : public Gesture { + public: + struct Fingers { + ::SenseShift::Input::FloatSensor* index; + ::SenseShift::Input::FloatSensor* middle; + ::SenseShift::Input::FloatSensor* ring; + ::SenseShift::Input::FloatSensor* pinky; + }; - void init() override - { - SS_SUBSENSOR_INIT(this->fingers_.index, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - SS_SUBSENSOR_INIT(this->fingers_.middle, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - SS_SUBSENSOR_INIT(this->fingers_.ring, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - SS_SUBSENSOR_INIT(this->fingers_.pinky, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - } + explicit GrabGesture(Fingers fingers, float threshold = 0.5F, bool attach_callbacks = false) : + fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) + { + } - void tick() override - { - if (this->attach_callbacks_) { - LOG_E("gesture.grab", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); - } + void init() override + { + SS_SUBSENSOR_INIT(this->fingers_.index, this->attach_callbacks_, [this](float /*value*/) { this->recalculateState(); - } + }); + SS_SUBSENSOR_INIT(this->fingers_.middle, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); + SS_SUBSENSOR_INIT(this->fingers_.ring, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); + SS_SUBSENSOR_INIT(this->fingers_.pinky, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); + } - void recalculateState() - { - return this->publishState( - this->fingers_.index->getValue() > this->threshold_ - && this->fingers_.middle->getValue() > this->threshold_ - && this->fingers_.ring->getValue() > this->threshold_ - && this->fingers_.pinky->getValue() > this->threshold_ - ); + void tick() override + { + if (this->attach_callbacks_) { + LOG_E("gesture.grab", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); } + this->recalculateState(); + } - private: - Fingers fingers_; - float threshold_; - bool attach_callbacks_ = false; - }; + void recalculateState() + { + return this->publishState( + this->fingers_.index->getValue() > this->threshold_ && this->fingers_.middle->getValue() > this->threshold_ + && this->fingers_.ring->getValue() > this->threshold_ && this->fingers_.pinky->getValue() > this->threshold_ + ); + } - class PinchGesture : public Gesture { - public: - struct Fingers { - ::SenseShift::Input::FloatSensor* thumb; - ::SenseShift::Input::FloatSensor* index; - }; + private: + Fingers fingers_; + float threshold_; + bool attach_callbacks_ = false; +}; - explicit PinchGesture(Fingers fingers, float threshold = 0.5F, bool attach_callbacks = false) : - fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) - { - } +class PinchGesture : public Gesture { + public: + struct Fingers { + ::SenseShift::Input::FloatSensor* thumb; + ::SenseShift::Input::FloatSensor* index; + }; - void init() override - { - SS_SUBSENSOR_INIT(this->fingers_.thumb, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - SS_SUBSENSOR_INIT(this->fingers_.index, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - } + explicit PinchGesture(Fingers fingers, float threshold = 0.5F, bool attach_callbacks = false) : + fingers_(fingers), threshold_(threshold), attach_callbacks_(attach_callbacks) + { + } - void tick() override - { - if (this->attach_callbacks_) { - LOG_E("gesture.pinch", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); - } + void init() override + { + SS_SUBSENSOR_INIT(this->fingers_.thumb, this->attach_callbacks_, [this](float /*value*/) { this->recalculateState(); - } + }); + SS_SUBSENSOR_INIT(this->fingers_.index, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); + } - void recalculateState() - { - return this->publishState( - this->fingers_.thumb->getValue() > this->threshold_ && this->fingers_.index->getValue() > this->threshold_ - ); + void tick() override + { + if (this->attach_callbacks_) { + LOG_E("gesture.pinch", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); } + this->recalculateState(); + } - private: - Fingers fingers_; - float threshold_; - bool attach_callbacks_ = false; - }; -} // namespace SenseShift::Body::Hands::Input \ No newline at end of file + void recalculateState() + { + return this->publishState( + this->fingers_.thumb->getValue() > this->threshold_ && this->fingers_.index->getValue() > this->threshold_ + ); + } + + private: + Fingers fingers_; + float threshold_; + bool attach_callbacks_ = false; +}; +} // namespace SenseShift::Body::Hands::Input diff --git a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp index 1f52dbec..8e7e64eb 100644 --- a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -8,51 +8,51 @@ #include namespace SenseShift::Body::Hands::Input { - class TotalCurl : public ::SenseShift::Input::FloatSensor { - public: - /// \param joints The joints to calculate the total curl from. - /// \param attach_callbacks Whether to attach callbacks to the joints to update the total curl when they update. - /// If false, the total curl will only be recalculated when the tick() method is called. - /// Setting this to true is not recommended, as it will cause the total curl to - /// be recalculated multiple times per tick (the same as number of joints). - explicit TotalCurl(std::vector<::SenseShift::Input::FloatSensor> joints, bool attach_callbacks = false) : - joints_(std::move(joints)), attach_callbacks_(attach_callbacks) - { +class TotalCurl : public ::SenseShift::Input::FloatSensor { + public: + /// \param joints The joints to calculate the total curl from. + /// \param attach_callbacks Whether to attach callbacks to the joints to update the total curl when they update. + /// If false, the total curl will only be recalculated when the tick() method is called. + /// Setting this to true is not recommended, as it will cause the total curl to + /// be recalculated multiple times per tick (the same as number of joints). + explicit TotalCurl(std::vector<::SenseShift::Input::FloatSensor> joints, bool attach_callbacks = false) : + joints_(std::move(joints)), attach_callbacks_(attach_callbacks) + { + } + + void init() override + { + for (auto& joint : this->joints_) { + SS_SUBSENSOR_INIT(&joint, this->attach_callbacks_, [this](float /*value*/) { + this->recalculateState(); + }); } + } - void init() override - { - for (auto& joint : this->joints_) { - SS_SUBSENSOR_INIT(&joint, this->attach_callbacks_, [this](float /*value*/) { - this->recalculateState(); - }); - } + void tick() override + { + if (this->attach_callbacks_) { + LOG_E("total_curl", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); } + this->recalculateState(); + } - void tick() override - { - if (this->attach_callbacks_) { - LOG_E("total_curl", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); - } - this->recalculateState(); - } - - void recalculateState() - { - float total = 0.0F; + void recalculateState() + { + float total = 0.0F; - for (auto& joint : this->joints_) { - total += joint.getValue(); - } + for (auto& joint : this->joints_) { + total += joint.getValue(); + } - if (!this->joints_.empty()) { - this->publishState(total / static_cast(this->joints_.size())); - } + if (!this->joints_.empty()) { + this->publishState(total / static_cast(this->joints_.size())); } + } - private: - std::vector<::SenseShift::Input::FloatSensor> joints_; + private: + std::vector<::SenseShift::Input::FloatSensor> joints_; - bool attach_callbacks_ = false; - }; + bool attach_callbacks_ = false; +}; } // namespace SenseShift::Body::Hands::Input diff --git a/lib/haptics/senseshift/body/haptics/body.cpp b/lib/haptics/senseshift/body/haptics/body.cpp index eac297c1..fbdbfe5e 100644 --- a/lib/haptics/senseshift/body/haptics/body.cpp +++ b/lib/haptics/senseshift/body/haptics/body.cpp @@ -5,19 +5,19 @@ #include namespace SenseShift::Body::Haptics { - static const char* const TAG = "haptic.body"; +static const char* const TAG = "haptic.body"; - template - void OutputBody::effect(const Target& target, const Position& pos, const typename Plane::Value& val) - { - auto plane = this->getTarget(target); - if (!plane.has_value()) { - LOG_W(TAG, "No target found for effect: %d", target); - return; - } - - plane.value()->effect(pos, val); +template +void OutputBody::effect(const Target& target, const Position& pos, const typename Plane::Value& val) +{ + auto plane = this->getTarget(target); + if (!plane.has_value()) { + LOG_W(TAG, "No target found for effect: %d", target); + return; } - template class OutputBody; + plane.value()->effect(pos, val); +} + +template class OutputBody; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index d381348a..6c3cf002 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -9,46 +9,52 @@ #include namespace SenseShift::Body::Haptics { - /// IOutput body, contains all the output planes. - /// - /// \tparam Tc The type of the coordinate. - /// \tparam To The type of the output value. - template - class OutputBody { - public: - /// The type of the output plane for the given target. - using Plane = OutputPlane; - /// The type of the target to output plane map (e.g. Chest -> OutputPlane). - using TargetPlaneMap = std::map; - - OutputBody() = default; - - void setup() - { - for (auto& [target, plane] : this->targets_) { - plane->setup(); - } +/// IOutput body, contains all the output planes. +/// +/// \tparam Tc The type of the coordinate. +/// \tparam To The type of the output value. +template +class OutputBody { + public: + /// The type of the output plane for the given target. + using Plane = OutputPlane; + /// The type of the target to output plane map (e.g. Chest -> OutputPlane). + using TargetPlaneMap = std::map; + + OutputBody() = default; + + void setup() + { + for (auto& [target, plane] : this->targets_) { + plane->setup(); } - - void addTarget(Target target, Plane* plane) { this->targets_[target] = plane; } - - auto getTarget(Target target) -> std::optional - { - auto find = this->targets_.find(target); - if (find == this->targets_.end()) { - return std::nullopt; - } - - return find->second; + } + + void addTarget(Target target, Plane* plane) + { + this->targets_[target] = plane; + } + + auto getTarget(Target target) -> std::optional + { + auto find = this->targets_.find(target); + if (find == this->targets_.end()) { + return std::nullopt; } - void effect(const Target& target, const Position& pos, const typename Plane::Value& val); + return find->second; + } + + void effect(const Target& target, const Position& pos, const typename Plane::Value& val); - [[nodiscard]] auto getTargets() const -> const TargetPlaneMap* { return &targets_; } + [[nodiscard]] auto getTargets() const -> const TargetPlaneMap* + { + return &targets_; + } - private: - TargetPlaneMap targets_{}; - }; + private: + TargetPlaneMap targets_{}; +}; - using FloatBody = OutputBody; +using FloatBody = OutputBody; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/interface.hpp b/lib/haptics/senseshift/body/haptics/interface.hpp index f0952fd4..b6f50b52 100644 --- a/lib/haptics/senseshift/body/haptics/interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -6,77 +6,85 @@ #include namespace SenseShift::Body::Haptics { - using EffectIndex = std::uint8_t; - static constexpr EffectIndex EFFECT_INVALID = 0xFF; - enum class Effect : EffectIndex { - Invalid = EFFECT_INVALID, - Vibro = 0x00, - // TODO: thermal, etc. - // Thermal = 0x01, - }; - - using TargetIndex = std::uint8_t; - static constexpr TargetIndex TARGET_INVALID = 0xFF; - enum class Target : TargetIndex { - Invalid = TARGET_INVALID, - ChestFront = 0x00, - ChestBack = 0x01, - - // Legacy backward compatibility - Accessory [[deprecated]] = 0x02, - - FaceFront, - - HandLeftThumb, - HandLeftIndex, - HandLeftMiddle, - HandLeftRing, - HandLeftLittle, - HandLeftVolar, // Palm - HandLeftDorsal, // Back - - HandRightThumb, - HandRightIndex, - HandRightMiddle, - HandRightRing, - HandRightLittle, - HandRightVolar, // Palm - HandRightDorsal, // Back - - // TODO: arms, legs, etc. +using EffectIndex = std::uint8_t; +static constexpr EffectIndex EFFECT_INVALID = 0xFF; +enum class Effect : EffectIndex { + Invalid = EFFECT_INVALID, + Vibro = 0x00, + // TODO: thermal, etc. + // Thermal = 0x01, +}; + +using TargetIndex = std::uint8_t; +static constexpr TargetIndex TARGET_INVALID = 0xFF; +enum class Target : TargetIndex { + Invalid = TARGET_INVALID, + ChestFront = 0x00, + ChestBack = 0x01, + + // Legacy backward compatibility + Accessory [[deprecated]] = 0x02, + + FaceFront, + + HandLeftThumb, + HandLeftIndex, + HandLeftMiddle, + HandLeftRing, + HandLeftLittle, + HandLeftVolar, // Palm + HandLeftDorsal, // Back + + HandRightThumb, + HandRightIndex, + HandRightMiddle, + HandRightRing, + HandRightLittle, + HandRightVolar, // Palm + HandRightDorsal, // Back + + // TODO: arms, legs, etc. +}; + +using Coordinate = std::uint8_t; +using Position = Math::Point2; + +// Vibration intensity_. +class VibroEffectData { + public: + using Intensity = float; + + static constexpr Intensity INTENSITY_MIN = 0.0F; + static constexpr Intensity INTENSITY_MAX = 1.0F; + + constexpr VibroEffectData() = default; + constexpr explicit VibroEffectData(const Intensity intensity) : intensity_(intensity) + { + } + constexpr VibroEffectData(const VibroEffectData& other) = default; + + constexpr inline explicit operator float() const + { + return this->intensity_; + } + + [[nodiscard]] constexpr inline auto getIntensity() const -> Intensity + { + return intensity_; }; - using Coordinate = std::uint8_t; - using Position = Math::Point2; - - // Vibration intensity_. - class VibroEffectData { - public: - using Intensity = float; - - static constexpr Intensity INTENSITY_MIN = 0.0F; - static constexpr Intensity INTENSITY_MAX = 1.0F; - - constexpr VibroEffectData() = default; - constexpr explicit VibroEffectData(const Intensity intensity) : intensity_(intensity) {} - constexpr VibroEffectData(const VibroEffectData& other) = default; + private: + Intensity intensity_ = 0; +}; - constexpr inline explicit operator float() const { return this->intensity_; } +// TODO: thermal, etc. +using EffectData = std::variant; - [[nodiscard]] constexpr inline auto getIntensity() const -> Intensity { return intensity_; }; +struct EffectRequest { + Effect effect = Effect::Invalid; + Target target = Target::Invalid; + Position position = Position(0, 0); - private: - Intensity intensity_ = 0; - }; - - // TODO: thermal, etc. - using EffectData = std::variant; - - struct EffectRequest { - Effect effect = Effect::Invalid; - Target target = Target::Invalid; - Position position = Position(0, 0); - - EffectData data; - }; + EffectData data; +}; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/plane.cpp b/lib/haptics/senseshift/body/haptics/plane.cpp index 85fb184b..08af3b33 100644 --- a/lib/haptics/senseshift/body/haptics/plane.cpp +++ b/lib/haptics/senseshift/body/haptics/plane.cpp @@ -8,76 +8,75 @@ #include namespace SenseShift::Body::Haptics { - static const char* const TAG = "haptic.plane"; +static const char* const TAG = "haptic.plane"; - template - void OutputPlane::setActuators(const ActuatorMap& actuators) - { - this->actuators_.clear(); - for (const auto& [point, actuator] : actuators) { - this->actuators_[point] = actuator; - } - - this->points_.clear(); - for (const auto& [point, _] : actuators) { - this->points_.insert(point); - } - - this->states_.clear(); - for (const auto& [point, _] : actuators) { - this->states_[point] = static_cast(0); - } +template +void OutputPlane::setActuators(const ActuatorMap& actuators) +{ + this->actuators_.clear(); + for (const auto& [point, actuator] : actuators) { + this->actuators_[point] = actuator; } - template - void OutputPlane::setup() - { - for (const auto& [point, actuator] : this->actuators_) { - actuator->init(); - } + this->points_.clear(); + for (const auto& [point, _] : actuators) { + this->points_.insert(point); } - template - void OutputPlane::effect(const Position& pos, const Value& val) - { - auto find = this->actuators_.find(pos); - if (find == this->actuators_.end()) { - LOG_W(TAG, "No actuator for point (%u, %u)", pos.x, pos.y); - return; - } + this->states_.clear(); + for (const auto& [point, _] : actuators) { + this->states_[point] = static_cast(0); + } +} - find->second->writeState(val); - this->states_[pos] = val; +template +void OutputPlane::setup() +{ + for (const auto& [point, actuator] : this->actuators_) { + actuator->init(); } +} - template - void OutputPlane_Closest::effect(const Position& pos, const Value& val) - { - auto& closest = this->findClosestPoint(*this->getAvailablePoints(), pos); - OutputPlane::effect(closest, val); +template +void OutputPlane::effect(const Position& pos, const Value& val) +{ + auto find = this->actuators_.find(pos); + if (find == this->actuators_.end()) { + LOG_W(TAG, "No actuator for point (%u, %u)", pos.x, pos.y); + return; } - template - [[nodiscard]] auto OutputPlane_Closest::findClosestPoint(const PositionSet& pts, const Position& target) - -> const Position& - { - // check if exact point exists - const auto find = pts.find(target); - if (find != pts.end()) { - return *find; - } + find->second->writeState(val); + this->states_[pos] = val; +} - // find the closest point by square distance - std::multimap distance_map = {}; - for (const auto& point : pts) { - distance_map.insert({ (target - point), point }); - } +template +void OutputPlane_Closest::effect(const Position& pos, const Value& val) +{ + auto& closest = this->findClosestPoint(*this->getAvailablePoints(), pos); + OutputPlane::effect(closest, val); +} - const auto nearest = std::min_element(distance_map.begin(), distance_map.end()); +template +auto OutputPlane_Closest::findClosestPoint(const PositionSet& pts, const Position& target) -> const Position& +{ + // check if exact point exists + const auto find = pts.find(target); + if (find != pts.end()) { + return *find; + } - return nearest->second; + // find the closest point by square distance + std::multimap distance_map = {}; + for (const auto& point : pts) { + distance_map.insert({ (target - point), point }); } - template class OutputPlane; - template class OutputPlane_Closest; + const auto nearest = std::min_element(distance_map.begin(), distance_map.end()); + + return nearest->second; +} + +template class OutputPlane; +template class OutputPlane_Closest; } // namespace SenseShift::Body::Haptics diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index 5971ee32..54b7a653 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -12,111 +12,119 @@ #include namespace SenseShift::Body::Haptics { - /// Output "plane" (e.g. Chest, Palm, Finger, etc.). - /// - /// \tparam Tc The type of the coordinate. - /// \tparam To The type of the output value. - template - class OutputPlane { - public: - /// The type of the coordinate (e.g. std::uint8_t) for the plane. - using Coordinate = Tc; - /// The type of the position (e.g. Point2) for the plane. - using Position = Math::Point2; - using PositionSet = std::set; - - /// The type of the output value (e.g. float) for the plane. - using Value = To; - /// The type of the actuator for the plane. - using Actuator = Output::IOutput; - - using ActuatorMap = std::map; - using PositionStateMap = std::map; - - OutputPlane() = default; - - explicit OutputPlane(const ActuatorMap& actuators) { this->setActuators(actuators); } - - void setup(); - virtual void effect(const Position&, const Value&); - - [[nodiscard]] auto getAvailablePoints() const -> const PositionSet* { return &points_; } - [[nodiscard]] auto getActuatorStates() const -> const PositionStateMap* { return &states_; } - - protected: - void setActuators(const ActuatorMap& actuators); - - private: - PositionSet points_; - ActuatorMap actuators_{}; - PositionStateMap states_{}; - }; - - /// Output plane, finds the closest actuator for the given point. - /// \deprecated We should guarantee on the driver level, that the actuator is always exists. - /// - /// \tparam Tc The type of the coordinate. - /// \tparam To The type of the output value. - template - class OutputPlane_Closest : public OutputPlane { - public: - using Value = To; - using PositionSet = typename OutputPlane::PositionSet; - - explicit OutputPlane_Closest(const typename OutputPlane::ActuatorMap& actuators) : - OutputPlane(actuators) - { - } - - void effect(const Position&, const Value&) override; - - private: - [[nodiscard]] static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; - }; - - using FloatPlane = OutputPlane; - using FloatPlane_Closest = OutputPlane_Closest; - - // TODO: configurable margin - class PlaneMapper_Margin { - public: - /// Maps a 2D matrix into a 1D (coord, object) map. - template - [[nodiscard]] static constexpr auto mapMatrixCoordinates(std::vector> map2d) - -> std::map - { - std::map points{}; - - const size_t y_size = map2d.size(); - const size_t y_max = y_size - 1; - - for (size_t y = 0; y < y_size; ++y) { - auto row = map2d.at(y); - const size_t x_size = row.size(); - const size_t x_max = x_size - 1; - - for (size_t x = 0; x < x_size; ++x) { - auto* wr = row.at(x); - Position coord = mapPoint(x, y, x_max, y_max); - - points[coord] = wr; - } +/// Output "plane" (e.g. Chest, Palm, Finger, etc.). +/// +/// \tparam Tc The type of the coordinate. +/// \tparam To The type of the output value. +template +class OutputPlane { + public: + /// The type of the coordinate (e.g. std::uint8_t) for the plane. + using Coordinate = Tc; + /// The type of the position (e.g. Point2) for the plane. + using Position = Math::Point2; + using PositionSet = std::set; + + /// The type of the output value (e.g. float) for the plane. + using Value = To; + /// The type of the actuator for the plane. + using Actuator = Output::IOutput; + + using ActuatorMap = std::map; + using PositionStateMap = std::map; + + OutputPlane() = default; + + explicit OutputPlane(const ActuatorMap& actuators) + { + this->setActuators(actuators); + } + + void setup(); + virtual void effect(const Position&, const Value&); + + [[nodiscard]] auto getAvailablePoints() const -> const PositionSet* + { + return &points_; + } + [[nodiscard]] auto getActuatorStates() const -> const PositionStateMap* + { + return &states_; + } + + protected: + void setActuators(const ActuatorMap& actuators); + + private: + PositionSet points_; + ActuatorMap actuators_{}; + PositionStateMap states_{}; +}; + +/// Output plane, finds the closest actuator for the given point. +/// \deprecated We should guarantee on the driver level, that the actuator is always exists. +/// +/// \tparam Tc The type of the coordinate. +/// \tparam To The type of the output value. +template +class OutputPlane_Closest : public OutputPlane { + public: + using Value = To; + using PositionSet = typename OutputPlane::PositionSet; + + explicit OutputPlane_Closest(const typename OutputPlane::ActuatorMap& actuators) : + OutputPlane(actuators) + { + } + + void effect(const Position&, const Value&) override; + + private: + [[nodiscard]] static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; +}; + +using FloatPlane = OutputPlane; +using FloatPlane_Closest = OutputPlane_Closest; + +// TODO: configurable margin +class PlaneMapper_Margin { + public: + /// Maps a 2D matrix into a 1D (coord, object) map. + template + [[nodiscard]] static auto mapMatrixCoordinates(std::vector> map2d) -> std::map + { + std::map points{}; + + const size_t y_size = map2d.size(); + const size_t y_max = y_size - 1; + + for (size_t y = 0; y < y_size; ++y) { + auto row = map2d.at(y); + const size_t x_size = row.size(); + const size_t x_max = x_size - 1; + + for (size_t x = 0; x < x_size; ++x) { + auto* wr = row.at(x); + Position coord = mapPoint(x, y, x_max, y_max); + + points[coord] = wr; } - - return points; } - /// Re-maps a point index to output coordinate. - /// \tparam Tp The type of the point index. - template - [[nodiscard]] static constexpr auto mapPoint(Tp x, Tp y, Tp x_max, Tp y_max) -> Math::Point2 - { - using LocalPointType = Math::Point2; - - return LocalPointType( - ::SenseShift::remap(x + 1, 0, x_max + 2, LocalPointType::MIN, LocalPointType::MAX), - ::SenseShift::remap(y + 1, 0, y_max + 2, LocalPointType::MIN, LocalPointType::MAX) - ); - } - }; + return points; + } + + /// Re-maps a point index to output coordinate. + /// \tparam Tp The type of the point index. + template + [[nodiscard]] static constexpr auto mapPoint(Tp x, Tp y, Tp x_max, Tp y_max) -> Math::Point2 + { + using LocalPointType = Math::Point2; + + return LocalPointType( + ::SenseShift::remap(x + 1, 0, x_max + 2, LocalPointType::MIN, LocalPointType::MAX), + ::SenseShift::remap(y + 1, 0, y_max + 2, LocalPointType::MIN, LocalPointType::MAX) + ); + } +}; } // namespace SenseShift::Body::Haptics diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index fd6ec99e..c680d3df 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -8,231 +8,229 @@ #include namespace SenseShift::Input::Calibration { - struct ICalibrated { - virtual void startCalibration() = 0; - virtual void stopCalibration() = 0; - virtual void reselCalibration() = 0; - }; - - template - struct ICalibrator { - /// Reset the calibration. - virtual void reset() = 0; - - /// Update the calibration with a new input value. - virtual void update(Tp input) = 0; - - /// Calibrate the input value. - [[nodiscard]] virtual auto calibrate(Tp input) const -> Tp = 0; - }; - - template - class MinMaxCalibrator : public ICalibrator { - static_assert(std::is_arithmetic_v, "MinMaxCalibrator only can be used with arithmetic types"); - - public: - using ValueType = Tp; - - explicit MinMaxCalibrator(Tp output_min, Tp output_max) : - output_min_(output_min), output_max_(output_max), value_min_(output_max), value_max_(output_min) - { +struct ICalibrated { + virtual void startCalibration() = 0; + virtual void stopCalibration() = 0; + virtual void reselCalibration() = 0; +}; + +template +struct ICalibrator { + /// Reset the calibration. + virtual void reset() = 0; + + /// Update the calibration with a new input value. + virtual void update(Tp input) = 0; + + /// Calibrate the input value. + [[nodiscard]] virtual auto calibrate(Tp input) const -> Tp = 0; +}; + +template +class MinMaxCalibrator : public ICalibrator { + static_assert(std::is_arithmetic_v, "MinMaxCalibrator only can be used with arithmetic types"); + + public: + using ValueType = Tp; + + explicit MinMaxCalibrator(Tp output_min, Tp output_max) : + output_min_(output_min), output_max_(output_max), value_min_(output_max), value_max_(output_min) + { + } + + template, int> = 0> + explicit MinMaxCalibrator(Tp output_min = 0.0F, Tp output_max = 1.0F) : + output_min_(output_min), output_max_(output_max), value_min_(output_max), value_max_(output_min) + { + } + + void reset() override + { + value_min_ = output_max_; + value_max_ = output_min_; + } + + void update(ValueType input) override + { + // Update the min and the max. + if (input < value_min_) { + value_min_ = input; } - - template, int> = 0> - explicit MinMaxCalibrator(Tp output_min = 0.0F, Tp output_max = 1.0F) : - output_min_(output_min), output_max_(output_max), value_min_(output_max), value_max_(output_min) - { - } - - void reset() override - { - value_min_ = output_max_; - value_max_ = output_min_; - } - - void update(ValueType input) override - { - // Update the min and the max. - if (input < value_min_) { - value_min_ = input; - } - if (input > value_max_) { - value_max_ = input; - } - } - - auto calibrate(ValueType input) const -> ValueType override - { - // This means we haven't had any calibration data yet. - // Return a neutral value right in the middle of the output range. - if (value_min_ > value_max_) { - return (output_min_ + output_max_) / 2.0F; - } - - if (input <= value_min_) { - return output_min_; - } - - if (input >= value_max_) { - return output_max_; - } - - // Map the input range to the output range. - ValueType output = - ::SenseShift::remap(input, value_min_, value_max_, output_min_, output_max_); - - // Lock the range to the output. - return std::clamp(output, output_min_, output_max_); + if (input > value_max_) { + value_max_ = input; } - - private: - const ValueType output_min_; - const ValueType output_max_; - - ValueType value_min_; - ValueType value_max_; - }; - - template - class CenterPointDeviationCalibrator : public ICalibrator { - static_assert( - std::is_arithmetic_v, "CenterPointDeviationCalibrator only can be used with arithmetic types" - ); - - public: - using ValueType = Tp; - - CenterPointDeviationCalibrator(Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max) : - sensor_max_(sensor_max), - driver_max_deviation_(driver_max_deviation), - output_min_(output_min), - output_max_(output_max), - range_min_(sensor_max), - range_max_(0) - { + } + + auto calibrate(ValueType input) const -> ValueType override + { + // This means we haven't had any calibration data yet. + // Return a neutral value right in the middle of the output range. + if (value_min_ > value_max_) { + return (output_min_ + output_max_) / 2.0F; } - template, int> = 0> - CenterPointDeviationCalibrator( - Tp sensor_max, Tp driver_max_deviation, Tp output_min = 0.0F, Tp output_max = 1.0F - ) : - sensor_max_(sensor_max), - driver_max_deviation_(driver_max_deviation), - output_min_(output_min), - output_max_(output_max), - range_min_(sensor_max), - range_max_(0) - { + if (input <= value_min_) { + return output_min_; } - void reset() override - { - this->range_min_ = this->sensor_max_; - this->range_max_ = 0; + if (input >= value_max_) { + return output_max_; } - void update(Tp input) override - { - // Update the min and the max. - if (input < this->range_min_) { - this->range_min_ = - ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); - } - if (input > this->range_max_) { - this->range_max_ = - ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); - } + // Map the input range to the output range. + ValueType output = + ::SenseShift::remap(input, value_min_, value_max_, output_min_, output_max_); + + // Lock the range to the output. + return std::clamp(output, output_min_, output_max_); + } + + private: + const ValueType output_min_; + const ValueType output_max_; + + ValueType value_min_; + ValueType value_max_; +}; + +template +class CenterPointDeviationCalibrator : public ICalibrator { + static_assert(std::is_arithmetic_v, "CenterPointDeviationCalibrator only can be used with arithmetic types"); + + public: + using ValueType = Tp; + + CenterPointDeviationCalibrator(Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max) : + sensor_max_(sensor_max), + driver_max_deviation_(driver_max_deviation), + output_min_(output_min), + output_max_(output_max), + range_min_(sensor_max), + range_max_(0) + { + } + + template, int> = 0> + CenterPointDeviationCalibrator(Tp sensor_max, Tp driver_max_deviation, Tp output_min = 0.0F, Tp output_max = 1.0F) : + sensor_max_(sensor_max), + driver_max_deviation_(driver_max_deviation), + output_min_(output_min), + output_max_(output_max), + range_min_(sensor_max), + range_max_(0) + { + } + + void reset() override + { + this->range_min_ = this->sensor_max_; + this->range_max_ = 0; + } + + void update(Tp input) override + { + // Update the min and the max. + if (input < this->range_min_) { + this->range_min_ = + ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); } - - auto calibrate(ValueType input) const -> ValueType override - { - // Find the center point of the sensor, so we know how much we have deviated from it. - Tp center = (this->range_min_ + this->range_max_) / 2.0F; - - // Map the input to the sensor range of motion. - int output = ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); - - // Find the deviation from the center and clamp it to the maximum that the driver supports. - output = std::clamp(output - center, -(this->driver_max_deviation_), this->driver_max_deviation_); - - // Finally map the deviation from the center back to the output range. - return SenseShift::remap( - output, - -(this->driver_max_deviation_), - this->driver_max_deviation_, - this->output_min_, - this->output_max_ - ); + if (input > this->range_max_) { + this->range_max_ = + ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); } - - private: - const Tp sensor_max_; - const Tp driver_max_deviation_; - const Tp output_min_; - const Tp output_max_; - - Tp range_min_; - Tp range_max_; - }; - - template - class FixedCenterPointDeviationCalibrator : public ICalibrator { - static_assert( - std::is_arithmetic_v, "FixedCenterPointDeviationCalibrator only can be used with arithmetic types" + } + + auto calibrate(ValueType input) const -> ValueType override + { + // Find the center point of the sensor, so we know how much we have deviated from it. + Tp center = (this->range_min_ + this->range_max_) / 2.0F; + + // Map the input to the sensor range of motion. + int output = ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); + + // Find the deviation from the center and clamp it to the maximum that the driver supports. + output = std::clamp(output - center, -(this->driver_max_deviation_), this->driver_max_deviation_); + + // Finally map the deviation from the center back to the output range. + return SenseShift::remap( + output, + -(this->driver_max_deviation_), + this->driver_max_deviation_, + this->output_min_, + this->output_max_ ); - - public: - using ValueType = Tp; - - explicit FixedCenterPointDeviationCalibrator( - Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max - ) : - sensor_max_(sensor_max), - driver_max_deviation_(driver_max_deviation), - output_min_(output_min), - output_max_(output_max) - { - } - - template, int> = 0> - explicit FixedCenterPointDeviationCalibrator( - Tp sensor_max, Tp driver_max_deviation, Tp output_min = 0.0F, Tp output_max = 1.0F - ) : - sensor_max_(sensor_max), - driver_max_deviation_(driver_max_deviation), - output_min_(output_min), - output_max_(output_max) - { - } - - void reset() override {} - void update(ValueType input) override {} - - auto calibrate(ValueType input) const -> ValueType override - { - // Find the center point of the sensor, so we know how much we have deviated from it. - Tp center = this->sensor_max_ / 2.0F; - - // Map the input to the sensor range of motion. - int output = ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); - - // Find the deviation from the center and clamp it to the maximum that the driver supports. - output = std::clamp(output - center, -(this->driver_max_deviation_), this->driver_max_deviation_); - - // Finally map the deviation from the center back to the output range. - return SenseShift::remap( - output, - -(this->driver_max_deviation_), - this->driver_max_deviation_, - this->output_min_, - this->output_max_ - ); - } - - private: - const Tp sensor_max_; - const Tp driver_max_deviation_; - const Tp output_min_; - const Tp output_max_; - }; + } + + private: + const Tp sensor_max_; + const Tp driver_max_deviation_; + const Tp output_min_; + const Tp output_max_; + + Tp range_min_; + Tp range_max_; +}; + +template +class FixedCenterPointDeviationCalibrator : public ICalibrator { + static_assert( + std::is_arithmetic_v, "FixedCenterPointDeviationCalibrator only can be used with arithmetic types" + ); + + public: + using ValueType = Tp; + + explicit FixedCenterPointDeviationCalibrator(Tp sensor_max, Tp driver_max_deviation, Tp output_min, Tp output_max) : + sensor_max_(sensor_max), + driver_max_deviation_(driver_max_deviation), + output_min_(output_min), + output_max_(output_max) + { + } + + template, int> = 0> + explicit FixedCenterPointDeviationCalibrator( + Tp sensor_max, Tp driver_max_deviation, Tp output_min = 0.0F, Tp output_max = 1.0F + ) : + sensor_max_(sensor_max), + driver_max_deviation_(driver_max_deviation), + output_min_(output_min), + output_max_(output_max) + { + } + + void reset() override + { + } + void update(ValueType input) override + { + } + + auto calibrate(ValueType input) const -> ValueType override + { + // Find the center point of the sensor, so we know how much we have deviated from it. + Tp center = this->sensor_max_ / 2.0F; + + // Map the input to the sensor range of motion. + int output = ::SenseShift::remap(input, this->output_min_, this->output_max_, 0, this->sensor_max_); + + // Find the deviation from the center and clamp it to the maximum that the driver supports. + output = std::clamp(output - center, -(this->driver_max_deviation_), this->driver_max_deviation_); + + // Finally map the deviation from the center back to the output range. + return SenseShift::remap( + output, + -(this->driver_max_deviation_), + this->driver_max_deviation_, + this->output_min_, + this->output_max_ + ); + } + + private: + const Tp sensor_max_; + const Tp driver_max_deviation_; + const Tp output_min_; + const Tp output_max_; +}; } // namespace SenseShift::Input::Calibration diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 01a4f495..951f9b16 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -15,295 +15,309 @@ #include namespace SenseShift::Input::Filter { - template - class ISimpleSensor { - public: - using ValueType = Tp; +template +class ISimpleSensor { + public: + using ValueType = Tp; - virtual auto getValue() -> ValueType = 0; - }; + virtual auto getValue() -> ValueType = 0; +}; - template - class Sensor; +template +class Sensor; - template - class IFilter { - public: - using ValueType = Tp; +template +class IFilter { + public: + using ValueType = Tp; - virtual auto filter(ISimpleSensor* sensor, ValueType value) -> ValueType = 0; - }; + virtual auto filter(ISimpleSensor* sensor, ValueType value) -> ValueType = 0; +}; - template - class IFiltered { - public: - using ValueType = Tp; +template +class IFiltered { + public: + using ValueType = Tp; - virtual void addFilter(IFilter* filter) = 0; + virtual void addFilter(IFilter* filter) = 0; - virtual void addFilters(std::vector*> filters) = 0; + virtual void addFilters(std::vector*> filters) = 0; - virtual void setFilters(std::vector*> filters) = 0; + virtual void setFilters(std::vector*> filters) = 0; - void clearFilters() = 0; - }; + void clearFilters() = 0; +}; - template - class AddFilter : public IFilter { - public: - explicit AddFilter(Tp offset) : offset_(offset){}; +template +class AddFilter : public IFilter { + public: + explicit AddFilter(Tp offset) : offset_(offset){}; - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override { return value + this->offset_; } + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + return value + this->offset_; + } - private: - Tp offset_; - }; + private: + Tp offset_; +}; - template - class SubtractFilter : public IFilter { - public: - explicit SubtractFilter(Tp offset) : offset_(offset){}; +template +class SubtractFilter : public IFilter { + public: + explicit SubtractFilter(Tp offset) : offset_(offset){}; - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override { return value - this->offset_; } + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + return value - this->offset_; + } - private: - Tp offset_; - }; + private: + Tp offset_; +}; - template - class MultiplyFilter : public IFilter { - public: - explicit MultiplyFilter(Tp factor) : factor_(factor){}; +template +class MultiplyFilter : public IFilter { + public: + explicit MultiplyFilter(Tp factor) : factor_(factor){}; - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override { return value * this->factor_; } - - private: - Tp factor_; - }; - - class VoltageDividerFilter : public MultiplyFilter { - public: - /// Calculates the original voltage from the voltage divider. - /// - /// \param r1 The resistance in Ohms of the first resistor in the voltage divider. - /// Example: 27000.0F. - /// \param r2 The resistance in Ohms of the second resistor in the voltage divider. - /// Example: 100000.0F. - /// - /// \example - /// \code - /// new VoltageDividerFilter(27000.0F, 100000.0F); - /// \endcode - explicit VoltageDividerFilter(float r1, float r2) : MultiplyFilter((r1 + r2) / r2){}; - }; + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + return value * this->factor_; + } - template - class ClampFilter : public IFilter { - public: - ClampFilter(Tp min, Tp max) : min_(min), max_(max){}; + private: + Tp factor_; +}; - auto filter(ISimpleSensor* /*source*/, Tp value) -> Tp override - { - return std::clamp(value, this->min_, this->max_); +class VoltageDividerFilter : public MultiplyFilter { + public: + /// Calculates the original voltage from the voltage divider. + /// + /// \param r1 The resistance in Ohms of the first resistor in the voltage divider. + /// Example: 27000.0F. + /// \param r2 The resistance in Ohms of the second resistor in the voltage divider. + /// Example: 100000.0F. + /// + /// \example + /// \code + /// new VoltageDividerFilter(27000.0F, 100000.0F); + /// \endcode + explicit VoltageDividerFilter(float r1, float r2) : MultiplyFilter((r1 + r2) / r2){}; +}; + +template +class ClampFilter : public IFilter { + public: + ClampFilter(Tp min, Tp max) : min_(min), max_(max){}; + + auto filter(ISimpleSensor* /*source*/, Tp value) -> Tp override + { + return std::clamp(value, this->min_, this->max_); + } + + private: + Tp min_; + Tp max_; +}; + +/// An alias for ClampFilter. +template +using MinMaxFilter = ClampFilter; + +/// An alias for ClampFilter. +template +using RangeFilter = ClampFilter; + +template +class LambdaFilter : public IFilter { + public: + using Lambda = std::function; + + explicit LambdaFilter(Lambda filter) : filter_(std::move(filter)){}; + + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + return this->filter_(value); + } + + private: + Lambda filter_; +}; + +/// Average filter. Reads the value from the sensor and returns the average of the N values. +template +class SampleAverageFilter : public IFilter { + static_assert(std::is_arithmetic_v, "SampleAverageFilter only supports arithmetic types"); + static_assert(std::is_same_v, "Sensor type must match filter type"); + static_assert( + std::is_same_v, "Can only use sensors with readRawValue()" + ); + + public: + explicit SampleAverageFilter(std::size_t size) : size_(size){}; + + auto filter(ISimpleSensor* sensor, Tp value) -> Tp override + { + auto sum = value; + + // Read the acc_ from the sensor N-1 times and sum them up. + // We read it N-1 times because we already have the first acc_. + for (std::size_t i = 0; i < this->size_ - 1; i++) { + sum += sensor->readRawValue(); } - private: - Tp min_; - Tp max_; - }; - - /// An alias for ClampFilter. - template - using MinMaxFilter = ClampFilter; - - /// An alias for ClampFilter. - template - using RangeFilter = ClampFilter; - - template - class LambdaFilter : public IFilter { - public: - using Lambda = std::function; - - explicit LambdaFilter(Lambda filter) : filter_(std::move(filter)){}; - - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override { return this->filter_(value); } - - private: - Lambda filter_; + // Return the average of the values. + return sum / this->size_; + } + + private: + std::size_t size_; +}; + +template +class SampleMedianFilter : public IFilter { + static_assert(std::is_same_v, "Sensor type must match filter type"); + // static_assert(std::is_same_v, "Can only use sensors with + // readRawValue()"); + + public: + explicit SampleMedianFilter(std::size_t size_) : size_(size_) + { + // allocate the array + this->values = new Tp[size_]; }; - /// Average filter. Reads the value from the sensor and returns the average of the N values. - template - class SampleAverageFilter : public IFilter { - static_assert(std::is_arithmetic_v, "SampleAverageFilter only supports arithmetic types"); - static_assert(std::is_same_v, "Sensor type must match filter type"); - static_assert( - std::is_same_v, - "Can only use sensors with readRawValue()" - ); - - public: - explicit SampleAverageFilter(std::size_t size) : size_(size){}; - - auto filter(ISimpleSensor* sensor, Tp value) -> Tp override - { - auto sum = value; - - // Read the acc_ from the sensor N-1 times and sum them up. - // We read it N-1 times because we already have the first acc_. - for (std::size_t i = 0; i < this->size_ - 1; i++) { - sum += sensor->readRawValue(); - } - - // Return the average of the values. - return sum / this->size_; + auto filter(ISimpleSensor* sensor, Tp value) -> Tp override + { + if (sensor == nullptr) { + LOG_E("filter.sampling_median", "Source sensor is null"); + return value; } - private: - std::size_t size_; - }; + this->values[0] = value; - template - class SampleMedianFilter : public IFilter { - static_assert(std::is_same_v, "Sensor type must match filter type"); - // static_assert(std::is_same_v, "Can only use sensors with - // readRawValue()"); - - public: - explicit SampleMedianFilter(std::size_t size_) : size_(size_) - { - // allocate the array - this->values = new Tp[size_]; - }; - - auto filter(ISimpleSensor* sensor, Tp value) -> Tp override - { - if (sensor == nullptr) { - LOG_E("filter.sampling_median", "Source sensor is null"); - return value; - } - - this->values[0] = value; - - // Read the acc_ from the sensor N-1 times and put them in the array. - // We read it N-1 times because we already have the first acc_. - for (std::size_t i = 1; i <= this->size_ - 1; i++) { - this->values[i] = sensor->getValue(); - } - - // Sort the array. - std::sort(this->values, this->values + this->size_); - - // Return the median of the values. - return this->values[this->size_ / 2]; + // Read the acc_ from the sensor N-1 times and put them in the array. + // We read it N-1 times because we already have the first acc_. + for (std::size_t i = 1; i <= this->size_ - 1; i++) { + this->values[i] = sensor->getValue(); } - private: - std::size_t size_; - Tp* values; - }; + // Sort the array. + std::sort(this->values, this->values + this->size_); - template - class SlidingWindowMovingAverageFilter : public IFilter { - static_assert(std::is_arithmetic_v, "SlidingWindowAverageFilter only supports arithmetic types"); + // Return the median of the values. + return this->values[this->size_ / 2]; + } - public: - explicit SlidingWindowMovingAverageFilter(size_t window_size) : window_size_(window_size){}; + private: + std::size_t size_; + Tp* values; +}; - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override - { - while (this->queue_.size() >= this->window_size_) { - this->queue_.pop_front(); - } - this->queue_.push_back(value); +template +class SlidingWindowMovingAverageFilter : public IFilter { + static_assert(std::is_arithmetic_v, "SlidingWindowAverageFilter only supports arithmetic types"); - return this->getAverage(); - } + public: + explicit SlidingWindowMovingAverageFilter(size_t window_size) : window_size_(window_size){}; - private: - std::size_t window_size_; - std::deque queue_; - - [[nodiscard]] auto getAverage() const -> Tp - { - Tp sum = 0; - for (auto value : this->queue_) { - sum += value; - } - return sum / this->queue_.size(); + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + while (this->queue_.size() >= this->window_size_) { + this->queue_.pop_front(); } - }; - - template - class ExponentialMovingAverageFilter : public IFilter { - static_assert(std::is_arithmetic_v, "ExponentialMovingAverageFilter only supports arithmetic types"); + this->queue_.push_back(value); - public: - explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha){}; + return this->getAverage(); + } - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override - { - if (this->is_first_) { - this->is_first_ = false; + private: + std::size_t window_size_; + std::deque queue_; - this->acc_ = value; - return this->acc_; - } - - this->acc_ = (this->alpha_ * value) + ((1 - this->alpha_) * this->acc_); - return this->acc_; + [[nodiscard]] auto getAverage() const -> Tp + { + Tp sum = 0; + for (auto value : this->queue_) { + sum += value; } + return sum / this->queue_.size(); + } +}; - private: - bool is_first_ = true; - float alpha_; - Tp acc_; - }; +template +class ExponentialMovingAverageFilter : public IFilter { + static_assert(std::is_arithmetic_v, "ExponentialMovingAverageFilter only supports arithmetic types"); - /// Deadzone filter. Clamps acc_ to center if it is within the deadzone. - /// Usually used to filter out noise in the joystick. - class CenterDeadzoneFilter : public IFilter { - public: - explicit CenterDeadzoneFilter(float deadzone, float center = 0.5F) : deadzone_(deadzone), center_(center){}; + public: + explicit ExponentialMovingAverageFilter(float alpha) : alpha_(alpha){}; - inline auto filter(ISimpleSensor* /*sensor*/, float value) -> float override - { - const auto deviation = std::abs(value - this->center_); - return deviation < deadzone_ ? this->center_ : value; - } + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + if (this->is_first_) { + this->is_first_ = false; - private: - const float center_; - - float deadzone_; - }; - - /// Interpolates the value from the lookup table. - /// Can be used to determine battery level from the voltage. - /// - /// \tparam Tp Type of the lookup table values. - /// \tparam Container Type of the lookup table container. - template - class LookupTableInterpolationFilter : public IFilter { - static_assert(std::is_same_v); - static_assert(std::is_arithmetic_v, "LookupTableInterpolationFilter only supports arithmetic types"); - - public: - explicit LookupTableInterpolationFilter(Container const& lookup_table) : lookup_table_(lookup_table){}; - - auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override - { - return SenseShift::lookup_table_interpolate_linear(this->lookup_table_, value); + this->acc_ = value; + return this->acc_; } - private: - Container const& lookup_table_; - }; - - /// Specialized filter for analog sensors (between 0.0 and 1.0). - class AnalogInvertFilter : public IFilter { - public: - auto filter(ISimpleSensor* /*sensor*/, float value) -> float override { return 1.0F - value; } - }; + this->acc_ = (this->alpha_ * value) + ((1 - this->alpha_) * this->acc_); + return this->acc_; + } + + private: + bool is_first_ = true; + float alpha_; + Tp acc_; +}; + +/// Deadzone filter. Clamps acc_ to center if it is within the deadzone. +/// Usually used to filter out noise in the joystick. +class CenterDeadzoneFilter : public IFilter { + public: + explicit CenterDeadzoneFilter(float deadzone, float center = 0.5F) : deadzone_(deadzone), center_(center){}; + + inline auto filter(ISimpleSensor* /*sensor*/, float value) -> float override + { + const auto deviation = std::abs(value - this->center_); + return deviation < deadzone_ ? this->center_ : value; + } + + private: + const float center_; + + float deadzone_; +}; + +/// Interpolates the value from the lookup table. +/// Can be used to determine battery level from the voltage. +/// +/// \tparam Tp Type of the lookup table values. +/// \tparam Container Type of the lookup table container. +template +class LookupTableInterpolationFilter : public IFilter { + static_assert(std::is_same_v); + static_assert(std::is_arithmetic_v, "LookupTableInterpolationFilter only supports arithmetic types"); + + public: + explicit LookupTableInterpolationFilter(Container const& lookup_table) : lookup_table_(lookup_table){}; + + auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override + { + return SenseShift::lookup_table_interpolate_linear(this->lookup_table_, value); + } + + private: + Container const& lookup_table_; +}; + +/// Specialized filter for analog sensors (between 0.0 and 1.0). +class AnalogInvertFilter : public IFilter { + public: + auto filter(ISimpleSensor* /*sensor*/, float value) -> float override + { + return 1.0F - value; + } +}; } // namespace SenseShift::Input::Filter diff --git a/lib/io/senseshift/input/sensor/analog_threshold.hpp b/lib/io/senseshift/input/sensor/analog_threshold.hpp index 98b3cb30..11e4df6e 100644 --- a/lib/io/senseshift/input/sensor/analog_threshold.hpp +++ b/lib/io/senseshift/input/sensor/analog_threshold.hpp @@ -4,63 +4,63 @@ #include namespace SenseShift::Input { - template - class AnalogThresholdSensor : public BinarySensor { - public: - /// Analog threshold sensor with hysteresis. - /// - /// \param source The source sensor. - /// \param threshold_upper Upper threshold, that needs to be crossed to transition from `low` to `high` states. - /// \param threshold_lower Lower threshold, that needs to be crossed to transition from `high` to `low` states. - explicit AnalogThresholdSensor( - ::SenseShift::Input::Sensor* source, Tp threshold_upper, Tp threshold_lower, bool attach_callbacks = false - ) : - source_(source), - threshold_upper_(threshold_upper), - threshold_lower_(threshold_lower), - attach_callbacks_(attach_callbacks) - { - } - - /// \param source The source sensor. - /// \param threshold Threshold, that will be used for both upper and lower thresholds. - template, int> = 0> - explicit AnalogThresholdSensor( - ::SenseShift::Input::Sensor* source, float threshold = 0.5f, bool attach_callbacks = false - ) : - AnalogThresholdSensor(source, threshold, threshold, attach_callbacks) - { - } +template +class AnalogThresholdSensor : public BinarySensor { + public: + /// Analog threshold sensor with hysteresis. + /// + /// \param source The source sensor. + /// \param threshold_upper Upper threshold, that needs to be crossed to transition from `low` to `high` states. + /// \param threshold_lower Lower threshold, that needs to be crossed to transition from `high` to `low` states. + explicit AnalogThresholdSensor( + ::SenseShift::Input::Sensor* source, Tp threshold_upper, Tp threshold_lower, bool attach_callbacks = false + ) : + source_(source), + threshold_upper_(threshold_upper), + threshold_lower_(threshold_lower), + attach_callbacks_(attach_callbacks) + { + } - void init() override - { - SS_SUBSENSOR_INIT(this->source_, this->attach_callbacks_, [this](Tp /*value*/) { - this->recalculateState(); - }); - } + /// \param source The source sensor. + /// \param threshold Threshold, that will be used for both upper and lower thresholds. + template, int> = 0> + explicit AnalogThresholdSensor( + ::SenseShift::Input::Sensor* source, float threshold = 0.5f, bool attach_callbacks = false + ) : + AnalogThresholdSensor(source, threshold, threshold, attach_callbacks) + { + } - void tick() override - { - if (this->attach_callbacks_) { - LOG_E( - "sensor.analog_threshold", - "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!" - ); - } + void init() override + { + SS_SUBSENSOR_INIT(this->source_, this->attach_callbacks_, [this](Tp /*value*/) { this->recalculateState(); - } + }); + } - void recalculateState() - { - const auto sensor_value = this->source_->getValue(); - this->publishState(sensor_value >= (this->getValue() ? this->threshold_lower_ : this->threshold_upper_)); + void tick() override + { + if (this->attach_callbacks_) { + LOG_E( + "sensor.analog_threshold", + "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!" + ); } + this->recalculateState(); + } + + void recalculateState() + { + const auto sensor_value = this->source_->getValue(); + this->publishState(sensor_value >= (this->getValue() ? this->threshold_lower_ : this->threshold_upper_)); + } - private: - ::SenseShift::Input::Sensor* source_; + private: + ::SenseShift::Input::Sensor* source_; - Tp threshold_lower_, threshold_upper_; + Tp threshold_lower_, threshold_upper_; - bool attach_callbacks_ = false; - }; + bool attach_callbacks_ = false; +}; } // namespace SenseShift::Input diff --git a/lib/io/senseshift/input/sensor/sensor.hpp b/lib/io/senseshift/input/sensor/sensor.hpp index 3d6e1b1f..e03eb3b4 100644 --- a/lib/io/senseshift/input/sensor/sensor.hpp +++ b/lib/io/senseshift/input/sensor/sensor.hpp @@ -17,197 +17,243 @@ } namespace SenseShift::Input { - /// Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) - /// \tparam Tp Type of the sensor value - template - class ISimpleSensor : public virtual IInitializable { - public: - using ValueType = Tp; - - explicit ISimpleSensor() = default; - - /// Get the current sensor value. - [[nodiscard]] virtual auto getValue() -> ValueType = 0; - }; - - using IBinarySimpleSensor = ISimpleSensor; - using IFloatSimpleSensor = ISimpleSensor; - - template - class ISensor : public virtual ISimpleSensor, public Calibration::ICalibrated {}; - - template - class Sensor : public ISensor, public Component { - public: - using ValueType = Tp; - using CallbackManagerType = CallbackManager; - using CallbackType = typename CallbackManagerType::CallbackType; - - explicit Sensor() = default; - - template, int> = 0> - explicit Sensor(float value = 0.0f) : raw_value_(value) - { - this->value_ = this->applyFilters(value); - } - - /// Appends a filter to the sensor's filter chain. - /// - /// \param filter The filter to add. - /// - /// \see addFilters for adding multiple filters. - void addFilter(Filter::IFilter* filter) { this->filters_.push_back(filter); } - - /// Adds multiple filters to the sensor's filter chain. Appends to the end of the chain. - /// - /// \param filters The chain of filters to add. - /// - /// \example - /// \code - /// sensor->addFilters({ - /// new MinMaxFilter(0.1f, 0.9f), - /// new CenterDeadzoneFilter(0.1f), - /// }); - /// \endcode - void addFilters(std::vector*> filters) - { - this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); - } +/// Abstract hardware sensor (e.g. potentiometer, flex sensor, etc.) +/// \tparam Tp Type of the sensor value +template +class ISimpleSensor : public virtual IInitializable { + public: + using ValueType = Tp; + + explicit ISimpleSensor() = default; + + /// Get the current sensor value. + [[nodiscard]] virtual auto getValue() -> ValueType = 0; +}; + +using IBinarySimpleSensor = ISimpleSensor; +using IFloatSimpleSensor = ISimpleSensor; + +template +class ISensor : public virtual ISimpleSensor, public Calibration::ICalibrated {}; + +template +class Sensor : public ISensor, public Component { + public: + using ValueType = Tp; + using CallbackManagerType = CallbackManager; + using CallbackType = typename CallbackManagerType::CallbackType; + + explicit Sensor() = default; + + template, int> = 0> + explicit Sensor(float value = 0.0f) : raw_value_(value) + { + this->value_ = this->applyFilters(value); + } - /// Replaces the sensor's filter chain with the given filters. - /// - /// \param filters New filter chain. - /// - /// \example - /// \code - /// sensor->setFilters({ - /// new MinMaxFilter(0.1f, 0.9f), - /// new CenterDeadzoneFilter(0.1f), - /// }); - /// \endcode - void setFilters(std::vector*> filters) { this->filters_ = filters; } + /// Appends a filter to the sensor's filter chain. + /// + /// \param filter The filter to add. + /// + /// \see addFilters for adding multiple filters. + void addFilter(Filter::IFilter* filter) + { + this->filters_.push_back(filter); + } - /// Removes everything from the sensor's filter chain. - void clearFilters() { this->filters_.clear(); } + /// Adds multiple filters to the sensor's filter chain. Appends to the end of the chain. + /// + /// \param filters The chain of filters to add. + /// + /// \example + /// \code + /// sensor->addFilters({ + /// new MinMaxFilter(0.1f, 0.9f), + /// new CenterDeadzoneFilter(0.1f), + /// }); + /// \endcode + void addFilters(std::vector*> filters) + { + this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); + } - void setCalibrator(Calibration::ICalibrator* calibrator) { this->calibrator_ = calibrator; } + /// Replaces the sensor's filter chain with the given filters. + /// + /// \param filters New filter chain. + /// + /// \example + /// \code + /// sensor->setFilters({ + /// new MinMaxFilter(0.1f, 0.9f), + /// new CenterDeadzoneFilter(0.1f), + /// }); + /// \endcode + void setFilters(std::vector*> filters) + { + this->filters_ = filters; + } - void clearCalibrator() { this->calibrator_ = std::nullopt; } + /// Removes everything from the sensor's filter chain. + void clearFilters() + { + this->filters_.clear(); + } - void startCalibration() override { this->is_calibrating_ = true; } + void setCalibrator(Calibration::ICalibrator* calibrator) + { + this->calibrator_ = calibrator; + } - void stopCalibration() override { this->is_calibrating_ = false; } + void clearCalibrator() + { + this->calibrator_ = std::nullopt; + } - void reselCalibration() override - { - if (this->calibrator_.has_value()) { - this->calibrator_.value()->reset(); - } - } + void startCalibration() override + { + this->is_calibrating_ = true; + } - void addValueCallback(CallbackType&& callback) { this->callbacks_.add(std::move(callback)); } + void stopCalibration() override + { + this->is_calibrating_ = false; + } - void addRawValueCallback(CallbackType&& callback) { this->raw_callbacks_.add(std::move(callback)); } + void reselCalibration() override + { + if (this->calibrator_.has_value()) { + this->calibrator_.value()->reset(); + } + } - void init() override {} + void addValueCallback(CallbackType&& callback) + { + this->callbacks_.add(std::move(callback)); + } - /// Publish the given state to the sensor. - /// - /// Firstly, the given state will be assigned to the sensor's raw_value_. - /// Then, the raw_value_ will be passed through the sensor's filter chain. - /// Finally, the filtered value will be assigned to the sensor's .value_. - /// - /// \param rawValue The new .raw_value_. - void publishState(ValueType rawValue) - { - this->raw_value_ = rawValue; - this->raw_callbacks_.call(this->raw_value_); + void addRawValueCallback(CallbackType&& callback) + { + this->raw_callbacks_.add(std::move(callback)); + } - this->value_ = this->applyFilters(rawValue); - this->callbacks_.call(this->value_); - } + void init() override + { + } - /// Get the current sensor .value_. - [[nodiscard]] auto getValue() -> ValueType override { return this->value_; } + /// Publish the given state to the sensor. + /// + /// Firstly, the given state will be assigned to the sensor's raw_value_. + /// Then, the raw_value_ will be passed through the sensor's filter chain. + /// Finally, the filtered value will be assigned to the sensor's .value_. + /// + /// \param rawValue The new .raw_value_. + void publishState(ValueType rawValue) + { + this->raw_value_ = rawValue; + this->raw_callbacks_.call(this->raw_value_); + + this->value_ = this->applyFilters(rawValue); + this->callbacks_.call(this->value_); + } - /// Get the current raw sensor .raw_value_. - [[nodiscard]] auto getRawValue() -> ValueType { return this->raw_value_; } + /// Get the current sensor .value_. + [[nodiscard]] auto getValue() -> ValueType override + { + return this->value_; + } - protected: - /// Apply current filters to value. - [[nodiscard]] auto applyFilters(ValueType value) -> ValueType - { - /// Apply calibration - if (this->calibrator_.has_value()) { - if (this->is_calibrating_) { - this->calibrator_.value()->update(value); - } + /// Get the current raw sensor .raw_value_. + [[nodiscard]] auto getRawValue() -> ValueType + { + return this->raw_value_; + } - value = this->calibrator_.value()->calibrate(value); + protected: + /// Apply current filters to value. + [[nodiscard]] auto applyFilters(ValueType value) -> ValueType + { + /// Apply calibration + if (this->calibrator_.has_value()) { + if (this->is_calibrating_) { + this->calibrator_.value()->update(value); } - /// Apply filters - for (auto filter : this->filters_) { - value = filter->filter(nullptr, value); - } + value = this->calibrator_.value()->calibrate(value); + } - return value; + /// Apply filters + for (auto filter : this->filters_) { + value = filter->filter(nullptr, value); } - private: - friend class Filter::IFilter; - friend class Calibration::ICalibrator; + return value; + } + + private: + friend class Filter::IFilter; + friend class Calibration::ICalibrator; - /// The sensor's filter chain. - std::vector*> filters_ = std::vector*>(); + /// The sensor's filter chain. + std::vector*> filters_ = std::vector*>(); - bool is_calibrating_ = false; - std::optional*> calibrator_ = std::nullopt; + bool is_calibrating_ = false; + std::optional*> calibrator_ = std::nullopt; - ValueType raw_value_; - ValueType value_; + ValueType raw_value_; + ValueType value_; - /// Storage for raw state callbacks. - CallbackManagerType raw_callbacks_; - /// Storage for filtered state callbacks. - CallbackManagerType callbacks_; - }; + /// Storage for raw state callbacks. + CallbackManagerType raw_callbacks_; + /// Storage for filtered state callbacks. + CallbackManagerType callbacks_; +}; - using FloatSensor = Sensor; +using FloatSensor = Sensor; - // todo: support double/triple/N-times/long click and so on - using BinarySensor = Sensor; +// todo: support double/triple/N-times/long click and so on +using BinarySensor = Sensor; - template - class SimpleSensorDecorator : public Sensor { - public: - using ValueType = Tp; - using SourceType = ISimpleSensor; +template +class SimpleSensorDecorator : public Sensor { + public: + using ValueType = Tp; + using SourceType = ISimpleSensor; - explicit SimpleSensorDecorator(SourceType* source) : source_(source) {} + explicit SimpleSensorDecorator(SourceType* source) : source_(source) + { + } - void init() override { this->source_->init(); } + void init() override + { + this->source_->init(); + } - void tick() override { this->updateValue(); } + void tick() override + { + this->updateValue(); + } - auto updateValue() -> ValueType - { - auto const raw_value = this->readRawValue(); - this->publishState(raw_value); + auto updateValue() -> ValueType + { + auto const raw_value = this->readRawValue(); + this->publishState(raw_value); - LOG_D("decorator.simple", " raw_value=%f, value=%f", raw_value, this->getValue()); + LOG_D("decorator.simple", " raw_value=%f, value=%f", raw_value, this->getValue()); - return this->getValue(); - } + return this->getValue(); + } - [[nodiscard]] auto readRawValue() -> ValueType { return this->source_->getValue(); } + [[nodiscard]] auto readRawValue() -> ValueType + { + return this->source_->getValue(); + } - protected: - private: - SourceType* source_; - }; + protected: + private: + SourceType* source_; +}; - namespace _private { - class TheFloatSensor : public Sensor {}; - } // namespace _private +namespace _private { +class TheFloatSensor : public Sensor {}; +} // namespace _private } // namespace SenseShift::Input diff --git a/lib/io/senseshift/output/output.hpp b/lib/io/senseshift/output/output.hpp index 581770d7..3c317679 100644 --- a/lib/io/senseshift/output/output.hpp +++ b/lib/io/senseshift/output/output.hpp @@ -3,14 +3,14 @@ #include namespace SenseShift::Output { - template - class IOutput : public IInitializable { - public: - using ValueType = Tp; +template +class IOutput : public IInitializable { + public: + using ValueType = Tp; - virtual void writeState(ValueType value) = 0; - }; + virtual void writeState(ValueType value) = 0; +}; - using IBinaryOutput = IOutput; - using IFloatOutput = IOutput; -} // namespace SenseShift::Output \ No newline at end of file +using IBinaryOutput = IOutput; +using IFloatOutput = IOutput; +} // namespace SenseShift::Output diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index 57d3f1e2..967edc4b 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -6,40 +6,46 @@ #include namespace SenseShift::Math { - template - struct Point2 { - static_assert(std::is_arithmetic_v, "Point2 only can be used with arithmetic types"); - - using Value = Tp; - - static constexpr Tp MIN = std::numeric_limits::min(); - static constexpr Tp MAX = std::numeric_limits::max(); - - Tp x, y; - - constexpr Point2() : x(static_cast(0)), y(static_cast(0)){}; - constexpr Point2(Tp x, Tp y) : x(x), y(y){}; - constexpr Point2(const Point2& v) : x((Tp) v.x), y((Tp) v.y){}; - - constexpr inline auto operator==(const Point2& rhs) const -> bool { return x == rhs.x && y == rhs.y; } - - constexpr inline auto operator!=(const Point2& rhs) const -> bool { return !(*this == rhs); } - - constexpr auto operator<(const Point2& rhs) const -> bool - { - return std::tie(x, y) < std::tie(rhs.x, rhs.y); - } - - constexpr auto operator-(const Point2& rhs) const -> float - { - return std::sqrt(std::pow(x - rhs.x, 2) + std::pow(y - rhs.y, 2)); - } - }; - - using Point2b = Point2; - using Point2d = Point2; - using Point2f = Point2; - using Point2i = Point2; - using Point2s = Point2; - using Point2w = Point2; +template +struct Point2 { + static_assert(std::is_arithmetic_v, "Point2 only can be used with arithmetic types"); + + using Value = Tp; + + static constexpr Tp MIN = std::numeric_limits::min(); + static constexpr Tp MAX = std::numeric_limits::max(); + + Tp x, y; + + constexpr Point2() : x(static_cast(0)), y(static_cast(0)){}; + constexpr Point2(Tp x, Tp y) : x(x), y(y){}; + constexpr Point2(const Point2& v) : x((Tp) v.x), y((Tp) v.y){}; + + constexpr inline auto operator==(const Point2& rhs) const -> bool + { + return x == rhs.x && y == rhs.y; + } + + constexpr inline auto operator!=(const Point2& rhs) const -> bool + { + return !(*this == rhs); + } + + constexpr auto operator<(const Point2& rhs) const -> bool + { + return std::tie(x, y) < std::tie(rhs.x, rhs.y); + } + + constexpr auto operator-(const Point2& rhs) const -> float + { + return std::sqrt(std::pow(x - rhs.x, 2) + std::pow(y - rhs.y, 2)); + } +}; + +using Point2b = Point2; +using Point2d = Point2; +using Point2f = Point2; +using Point2i = Point2; +using Point2s = Point2; +using Point2w = Point2; }; // namespace SenseShift::Math diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 77a63dd2..6e46b720 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -262,216 +262,216 @@ namespace SenseShift::OpenGloves::AutoConfig { - [[nodiscard]] auto createInput() -> InputSensors - { - InputSensors input_sensors; +[[nodiscard]] auto createInput() -> InputSensors +{ + InputSensors input_sensors; #if FINGER_THUMB_SPLAY - DEFINE_FINGER_SPLAY( - thumb, - PIN_FINGER_THUMB, - FINGER_THUMB_INVERT, - CALIBRATION_CURL, - PIN_FINGER_THUMB_SPLAY, - FINGER_THUMB_SPLAY_INVERT, - CALIBRATION_SPLAY - ); + DEFINE_FINGER_SPLAY( + thumb, + PIN_FINGER_THUMB, + FINGER_THUMB_INVERT, + CALIBRATION_CURL, + PIN_FINGER_THUMB_SPLAY, + FINGER_THUMB_SPLAY_INVERT, + CALIBRATION_SPLAY + ); #elif FINGER_THUMB_ENABLED - DEFINE_FINGER(thumb_curl, PIN_FINGER_THUMB, FINGER_THUMB_INVERT, CALIBRATION_CURL); - input_sensors.curl.thumb.curl_total = thumb_curl_sensor; + DEFINE_FINGER(thumb_curl, PIN_FINGER_THUMB, FINGER_THUMB_INVERT, CALIBRATION_CURL); + input_sensors.curl.thumb.curl_total = thumb_curl_sensor; #endif #if FINGER_INDEX_SPLAY - DEFINE_FINGER_SPLAY( - index, - PIN_FINGER_INDEX, - FINGER_INDEX_INVERT, - CALIBRATION_CURL, - PIN_FINGER_INDEX_SPLAY, - FINGER_INDEX_SPLAY_INVERT, - CALIBRATION_SPLAY - ); + DEFINE_FINGER_SPLAY( + index, + PIN_FINGER_INDEX, + FINGER_INDEX_INVERT, + CALIBRATION_CURL, + PIN_FINGER_INDEX_SPLAY, + FINGER_INDEX_SPLAY_INVERT, + CALIBRATION_SPLAY + ); #elif FINGER_INDEX_ENABLED - DEFINE_FINGER(index_curl, PIN_FINGER_INDEX, FINGER_INDEX_INVERT, CALIBRATION_CURL); - input_sensors.curl.index.curl_total = index_curl_sensor; + DEFINE_FINGER(index_curl, PIN_FINGER_INDEX, FINGER_INDEX_INVERT, CALIBRATION_CURL); + input_sensors.curl.index.curl_total = index_curl_sensor; #endif #if FINGER_MIDDLE_SPLAY - DEFINE_FINGER_SPLAY( - middle, - PIN_FINGER_MIDDLE, - FINGER_MIDDLE_INVERT, - CALIBRATION_CURL, - PIN_FINGER_MIDDLE_SPLAY, - FINGER_MIDDLE_SPLAY_INVERT, - CALIBRATION_SPLAY - ); + DEFINE_FINGER_SPLAY( + middle, + PIN_FINGER_MIDDLE, + FINGER_MIDDLE_INVERT, + CALIBRATION_CURL, + PIN_FINGER_MIDDLE_SPLAY, + FINGER_MIDDLE_SPLAY_INVERT, + CALIBRATION_SPLAY + ); #elif FINGER_MIDDLE_ENABLED - DEFINE_FINGER(middle_curl, PIN_FINGER_MIDDLE, FINGER_MIDDLE_INVERT, CALIBRATION_CURL); - input_sensors.curl.middle.curl_total = middle_curl_sensor; + DEFINE_FINGER(middle_curl, PIN_FINGER_MIDDLE, FINGER_MIDDLE_INVERT, CALIBRATION_CURL); + input_sensors.curl.middle.curl_total = middle_curl_sensor; #endif #if FINGER_RING_SPLAY - DEFINE_FINGER_SPLAY( - ring, - PIN_FINGER_RING, - FINGER_RING_INVERT, - CALIBRATION_CURL, - PIN_FINGER_RING_SPLAY, - FINGER_RING_SPLAY_INVERT, - CALIBRATION_SPLAY - ); + DEFINE_FINGER_SPLAY( + ring, + PIN_FINGER_RING, + FINGER_RING_INVERT, + CALIBRATION_CURL, + PIN_FINGER_RING_SPLAY, + FINGER_RING_SPLAY_INVERT, + CALIBRATION_SPLAY + ); #elif FINGER_RING_ENABLED - DEFINE_FINGER(ring_curl, PIN_FINGER_RING, FINGER_RING_INVERT, CALIBRATION_CURL); - input_sensors.curl.ring.curl_total = ring_curl_sensor; + DEFINE_FINGER(ring_curl, PIN_FINGER_RING, FINGER_RING_INVERT, CALIBRATION_CURL); + input_sensors.curl.ring.curl_total = ring_curl_sensor; #endif #if FINGER_PINKY_SPLAY - DEFINE_FINGER_SPLAY( - pinky, - PIN_FINGER_PINKY, - FINGER_PINKY_INVERT, - CALIBRATION_CURL, - PIN_FINGER_PINKY_SPLAY, - FINGER_PINKY_SPLAY_INVERT, - CALIBRATION_SPLAY - ); + DEFINE_FINGER_SPLAY( + pinky, + PIN_FINGER_PINKY, + FINGER_PINKY_INVERT, + CALIBRATION_CURL, + PIN_FINGER_PINKY_SPLAY, + FINGER_PINKY_SPLAY_INVERT, + CALIBRATION_SPLAY + ); #elif FINGER_PINKY_ENABLED - DEFINE_FINGER(pinky_curl, PIN_FINGER_PINKY, FINGER_PINKY_INVERT, CALIBRATION_CURL); - input_sensors.curl.pinky.curl_total = pinky_curl_sensor; + DEFINE_FINGER(pinky_curl, PIN_FINGER_PINKY, FINGER_PINKY_INVERT, CALIBRATION_CURL); + input_sensors.curl.pinky.curl_total = pinky_curl_sensor; #endif #if JOYSTICK_ENABLED - DEFINE_JOYSTICK_AXIS(joystick_x, PIN_JOYSTICK_X, JOYSTICK_X_INVERT, JOYSTICK_DEADZONE); - DEFINE_JOYSTICK_AXIS(joystick_y, PIN_JOYSTICK_Y, JOYSTICK_Y_INVERT, JOYSTICK_DEADZONE); + DEFINE_JOYSTICK_AXIS(joystick_x, PIN_JOYSTICK_X, JOYSTICK_X_INVERT, JOYSTICK_DEADZONE); + DEFINE_JOYSTICK_AXIS(joystick_y, PIN_JOYSTICK_Y, JOYSTICK_Y_INVERT, JOYSTICK_DEADZONE); - input_sensors.joystick.x = joystick_x_sensor; - input_sensors.joystick.y = joystick_y_sensor; + input_sensors.joystick.x = joystick_x_sensor; + input_sensors.joystick.y = joystick_y_sensor; #endif #if BUTTON_A_ENABLED - auto* button_a = new BUTTON_CLASS(PIN_BUTTON_A, INPUT_PULLUP, BUTTON_A_INVERT); - input_sensors.button_a.press = button_a; + auto* button_a = new BUTTON_CLASS(PIN_BUTTON_A, INPUT_PULLUP, BUTTON_A_INVERT); + input_sensors.button_a.press = button_a; #endif #if BUTTON_B_ENABLED - auto* button_b = new BUTTON_CLASS(PIN_BUTTON_B, INPUT_PULLUP, BUTTON_B_INVERT); - input_sensors.button_b.press = button_b; + auto* button_b = new BUTTON_CLASS(PIN_BUTTON_B, INPUT_PULLUP, BUTTON_B_INVERT); + input_sensors.button_b.press = button_b; #endif #if BUTTON_JOYSTICK_ENABLED - auto* button_joystick = new BUTTON_CLASS(PIN_BUTTON_JOYSTICK, INPUT_PULLUP, BUTTON_JOYSTICK_INVERT); - input_sensors.joystick.press = button_joystick; + auto* button_joystick = new BUTTON_CLASS(PIN_BUTTON_JOYSTICK, INPUT_PULLUP, BUTTON_JOYSTICK_INVERT); + input_sensors.joystick.press = button_joystick; #endif #if BUTTON_MENU_ENABLED - auto* button_menu = new BUTTON_CLASS(PIN_BUTTON_MENU, INPUT_PULLUP, BUTTON_MENU_INVERT); + auto* button_menu = new BUTTON_CLASS(PIN_BUTTON_MENU, INPUT_PULLUP, BUTTON_MENU_INVERT); #endif #if BUTTON_CALIBRATE_ENABLED - auto* button_calibrate = new BUTTON_CLASS(PIN_BUTTON_CALIBRATE, INPUT_PULLUP, BUTTON_CALIBRATE_INVERT); - input_sensors.button_calibrate.press = button_calibrate; + auto* button_calibrate = new BUTTON_CLASS(PIN_BUTTON_CALIBRATE, INPUT_PULLUP, BUTTON_CALIBRATE_INVERT); + input_sensors.button_calibrate.press = button_calibrate; #endif #if GESTURE_TRIGGER_ENABLED && FINGER_INDEX_ENABLED - auto* trigger = new Body::Hands::Input::TriggerGesture(index_curl_sensor, GESTURE_TRIGGER_THRESHOLD); - input_sensors.trigger.press = trigger; + auto* trigger = new Body::Hands::Input::TriggerGesture(index_curl_sensor, GESTURE_TRIGGER_THRESHOLD); + input_sensors.trigger.press = trigger; #elif BUTTON_TRIGGER_ENABLED - auto trigger = new BUTTON_CLASS(PIN_BUTTON_TRIGGER, INPUT_PULLUP, BUTTON_TRIGGER_INVERT); + auto trigger = new BUTTON_CLASS(PIN_BUTTON_TRIGGER, INPUT_PULLUP, BUTTON_TRIGGER_INVERT); #endif #if GESTURE_GRAB_ENABLED && FINGER_INDEX_ENABLED && FINGER_MIDDLE_ENABLED && FINGER_RING_ENABLED && FINGER_PINKY_ENABLED - auto* grab = new Body::Hands::Input::GrabGesture( - Body::Hands::Input::GrabGesture::Fingers{ .index = index_curl_sensor, - .middle = middle_curl_sensor, - .ring = ring_curl_sensor, - .pinky = pinky_curl_sensor }, - GESTURE_GRAB_THRESHOLD - ); - input_sensors.grab.press = grab; + auto* grab = new Body::Hands::Input::GrabGesture( + Body::Hands::Input::GrabGesture::Fingers{ .index = index_curl_sensor, + .middle = middle_curl_sensor, + .ring = ring_curl_sensor, + .pinky = pinky_curl_sensor }, + GESTURE_GRAB_THRESHOLD + ); + input_sensors.grab.press = grab; #elif BUTTON_GRAB_ENABLED - auto* grab = new BUTTON_CLASS(PIN_BUTTON_GRAB, INPUT_PULLUP, BUTTON_GRAB_INVERT); + auto* grab = new BUTTON_CLASS(PIN_BUTTON_GRAB, INPUT_PULLUP, BUTTON_GRAB_INVERT); #endif #if GESTURE_PINCH_ENABLED && FINGER_THUMB_ENABLED && FINGER_INDEX_ENABLED - auto* pinch = new Body::Hands::Input::PinchGesture( - Body::Hands::Input::PinchGesture::Fingers{ .thumb = thumb_curl_sensor, .index = index_curl_sensor }, - GESTURE_PINCH_THRESHOLD - ); - input_sensors.pinch.press = pinch; + auto* pinch = new Body::Hands::Input::PinchGesture( + Body::Hands::Input::PinchGesture::Fingers{ .thumb = thumb_curl_sensor, .index = index_curl_sensor }, + GESTURE_PINCH_THRESHOLD + ); + input_sensors.pinch.press = pinch; #elif BUTTON_PINCH_ENABLED - auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, INPUT_PULLUP, BUTTON_PINCH_INVERT); + auto* pinch = new BUTTON_CLASS(PIN_BUTTON_PINCH, INPUT_PULLUP, BUTTON_PINCH_INVERT); #endif - return input_sensors; - } + return input_sensors; +} - [[nodiscard]] auto createFfbOutputs() -> OutputWriters - { - OutputWriters output_writers; +[[nodiscard]] auto createFfbOutputs() -> OutputWriters +{ + OutputWriters output_writers; #if FFB_THUMB_ENABLED - auto* thumb_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_THUMB); - output_writers.ffb.thumb = thumb_ffb_output; + auto* thumb_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_THUMB); + output_writers.ffb.thumb = thumb_ffb_output; #endif #if FFB_INDEX_ENABLED - auto* index_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_INDEX); - output_writers.ffb.index = index_ffb_output; + auto* index_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_INDEX); + output_writers.ffb.index = index_ffb_output; #endif #if FFB_MIDDLE_ENABLED - auto* middle_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_MIDDLE); - output_writers.ffb.middle = middle_ffb_output; + auto* middle_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_MIDDLE); + output_writers.ffb.middle = middle_ffb_output; #endif #if FFB_RING_ENABLED - auto* ring_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_RING); - output_writers.ffb.ring = ring_ffb_output; + auto* ring_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_RING); + output_writers.ffb.ring = ring_ffb_output; #endif #if FFB_PINKY_ENABLED - auto* pinky_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_PINKY); - output_writers.ffb.pinky = pinky_ffb_output; + auto* pinky_ffb_output = new ::SenseShift::Arduino::Output::ServoOutput(PIN_FFB_PINKY); + output_writers.ffb.pinky = pinky_ffb_output; #endif - return output_writers; - } + return output_writers; +} - /** - * Setup the transport for the OpenGloves interface. - */ - [[nodiscard]] auto createTransport() -> ITransport* - { +/** + * Setup the transport for the OpenGloves interface. + */ +[[nodiscard]] auto createTransport() -> ITransport* +{ #if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_SERIAL // Serial - auto* pSerial = &SERIAL_PORT; - pSerial->begin(SERIAL_BAUDRATE); - return new StreamTransport(pSerial); + auto* pSerial = &SERIAL_PORT; + pSerial->begin(SERIAL_BAUDRATE); + return new StreamTransport(pSerial); #elif (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BTSERIAL) \ || (OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL) // Bluetooth - std::string name; + std::string name; #ifdef BTSERIAL_NAME - name = BTSERIAL_NAME; + name = BTSERIAL_NAME; #else - char suffix[4]; - snprintf(suffix, 4, "%04X", (uint16_t) (ESP.getEfuseMac() >> 32)); - name = BTSERIAL_PREFIX + std::string(suffix); + char suffix[4]; + snprintf(suffix, 4, "%04X", (uint16_t) (ESP.getEfuseMac() >> 32)); + name = BTSERIAL_PREFIX + std::string(suffix); - log_i("Generated Bluetooth name: %s", name.c_str()); + log_i("Generated Bluetooth name: %s", name.c_str()); #endif #if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic - BluetoothSerial* pBtSerial = new BluetoothSerial(); - pBtSerial->begin(name.c_str()); - return new BluetoothSerialTransport(*pBtSerial); + BluetoothSerial* pBtSerial = new BluetoothSerial(); + pBtSerial->begin(name.c_str()); + return new BluetoothSerialTransport(*pBtSerial); #elif OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BLESERIAL // Bluetooth Low Energy - BLESerial<>* pBleSerial = new BLESerial<>(); - pBleSerial->begin(name.c_str()); - return new BLESerialTransport(*pBleSerial); + BLESerial<>* pBleSerial = new BLESerial<>(); + pBleSerial->begin(name.c_str()); + return new BLESerialTransport(*pBleSerial); #endif #else // Fallback #error "Unsupported communication type" - return nullptr; + return nullptr; #endif - } +} } // namespace SenseShift::OpenGloves::AutoConfig diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 8e6cab5a..2244f7c6 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -62,136 +62,142 @@ return data; namespace SenseShift::OpenGloves { - namespace og = ::opengloves; - - class ITransport : public IInitializable { - public: - virtual auto send(const char* buffer, size_t length) -> size_t = 0; - virtual auto hasData() -> bool = 0; - virtual auto read(char* buffer, size_t length) -> size_t = 0; - }; - - using FloatSensor = ::SenseShift::Input::FloatSensor; - using BinarySensor = ::SenseShift::Input::BinarySensor; - - class InputSensors : - public og::InputPeripheral, - public Component, - public ::SenseShift::Input::Calibration::ICalibrated { - public: - void init() override - { - for (auto& finger_curl : this->curl.fingers) { - for (auto& joint_sensor : finger_curl.curl) { - if (joint_sensor != nullptr) { - joint_sensor->init(); - this->calibrated_inputs_.insert(joint_sensor); - } +namespace og = ::opengloves; + +class ITransport : public IInitializable { + public: + virtual auto send(const char* buffer, size_t length) -> size_t = 0; + virtual auto hasData() -> bool = 0; + virtual auto read(char* buffer, size_t length) -> size_t = 0; +}; + +using FloatSensor = ::SenseShift::Input::FloatSensor; +using BinarySensor = ::SenseShift::Input::BinarySensor; + +class InputSensors : + public og::InputPeripheral, + public Component, + public ::SenseShift::Input::Calibration::ICalibrated { + public: + void init() override + { + for (auto& finger_curl : this->curl.fingers) { + for (auto& joint_sensor : finger_curl.curl) { + if (joint_sensor != nullptr) { + joint_sensor->init(); + this->calibrated_inputs_.insert(joint_sensor); } } + } - for (auto& finger_splay : this->splay.fingers) { - if (finger_splay != nullptr) { - finger_splay->init(); - this->calibrated_inputs_.insert(finger_splay); - } - } - - SS_INIT_NOT_NULL(this->joystick.x); - SS_INIT_NOT_NULL(this->joystick.y); - SS_INIT_NOT_NULL(this->joystick.press); - - for (auto& button : this->buttons) { - SS_INIT_NOT_NULL(button.press); - } - - for (auto& analog_button : this->analog_buttons) { - SS_INIT_NOT_NULL(analog_button.press); - SS_INIT_NOT_NULL(analog_button.value); + for (auto& finger_splay : this->splay.fingers) { + if (finger_splay != nullptr) { + finger_splay->init(); + this->calibrated_inputs_.insert(finger_splay); } } - void tick() override - { - for (auto& finger_curl : this->curl.fingers) { - for (auto& joint_sensor : finger_curl.curl) { - SS_TICK_NOT_NULL(joint_sensor); - } - } + SS_INIT_NOT_NULL(this->joystick.x); + SS_INIT_NOT_NULL(this->joystick.y); + SS_INIT_NOT_NULL(this->joystick.press); - for (auto& finger_splay : this->splay.fingers) { - SS_TICK_NOT_NULL(finger_splay); - } + for (auto& button : this->buttons) { + SS_INIT_NOT_NULL(button.press); + } - SS_TICK_NOT_NULL(this->joystick.x); - SS_TICK_NOT_NULL(this->joystick.y); - SS_TICK_NOT_NULL(this->joystick.press); + for (auto& analog_button : this->analog_buttons) { + SS_INIT_NOT_NULL(analog_button.press); + SS_INIT_NOT_NULL(analog_button.value); + } + } - for (auto& button : this->buttons) { - SS_TICK_NOT_NULL(button.press); + void tick() override + { + for (auto& finger_curl : this->curl.fingers) { + for (auto& joint_sensor : finger_curl.curl) { + SS_TICK_NOT_NULL(joint_sensor); } + } - for (auto& analog_button : this->analog_buttons) { - SS_TICK_NOT_NULL(analog_button.press); - SS_TICK_NOT_NULL(analog_button.value); - } + for (auto& finger_splay : this->splay.fingers) { + SS_TICK_NOT_NULL(finger_splay); } - [[nodiscard]] auto collectData() -> og::InputPeripheralData { SS_OG_COLLECT_DATA(getValue); } + SS_TICK_NOT_NULL(this->joystick.x); + SS_TICK_NOT_NULL(this->joystick.y); + SS_TICK_NOT_NULL(this->joystick.press); - [[nodiscard]] auto collectRawData() -> og::InputPeripheralData { SS_OG_COLLECT_DATA(getRawValue); } + for (auto& button : this->buttons) { + SS_TICK_NOT_NULL(button.press); + } - void reselCalibration() override - { - for (const auto& calibrated_input : this->calibrated_inputs_) { - calibrated_input->reselCalibration(); - } + for (auto& analog_button : this->analog_buttons) { + SS_TICK_NOT_NULL(analog_button.press); + SS_TICK_NOT_NULL(analog_button.value); + } + } + + [[nodiscard]] auto collectData() -> og::InputPeripheralData + { + SS_OG_COLLECT_DATA(getValue); + } + + [[nodiscard]] auto collectRawData() -> og::InputPeripheralData + { + SS_OG_COLLECT_DATA(getRawValue); + } + + void reselCalibration() override + { + for (const auto& calibrated_input : this->calibrated_inputs_) { + calibrated_input->reselCalibration(); } + } - void startCalibration() override - { - for (const auto& calibrated_input : this->calibrated_inputs_) { - calibrated_input->startCalibration(); - } + void startCalibration() override + { + for (const auto& calibrated_input : this->calibrated_inputs_) { + calibrated_input->startCalibration(); } + } - void stopCalibration() override - { - for (const auto& calibrated_input : this->calibrated_inputs_) { - calibrated_input->stopCalibration(); - } + void stopCalibration() override + { + for (const auto& calibrated_input : this->calibrated_inputs_) { + calibrated_input->stopCalibration(); } + } - private: - std::set calibrated_inputs_{}; - }; + private: + std::set calibrated_inputs_{}; +}; - using FloatOutput = ::SenseShift::Output::IFloatOutput; +using FloatOutput = ::SenseShift::Output::IFloatOutput; - class OutputWriters : public IInitializable { - public: - og::OutputForceFeedback ffb; +class OutputWriters : public IInitializable { + public: + og::OutputForceFeedback ffb; - void init() override - { - for (auto& finger : this->ffb.fingers) { - if (finger != nullptr) { - finger->init(); - } + void init() override + { + for (auto& finger : this->ffb.fingers) { + if (finger != nullptr) { + finger->init(); } } - - void apply(const og::OutputData& data) - { - if (std::holds_alternative(data)) { - const auto& ffb_data = std::get(data); - for (auto i = 0; i < this->ffb.fingers.size(); i++) { - auto* finger = this->ffb.fingers[i]; - if (finger != nullptr) { - finger->writeState(ffb_data.fingers[i]); - } + } + + void apply(const og::OutputData& data) + { + if (std::holds_alternative(data)) { + const auto& ffb_data = std::get(data); + for (auto i = 0; i < this->ffb.fingers.size(); i++) { + auto* finger = this->ffb.fingers[i]; + if (finger != nullptr) { + finger->writeState(ffb_data.fingers[i]); } } } - }; + } +}; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index 735dd6d0..bcb77e13 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -15,146 +15,146 @@ #include namespace SenseShift::OpenGloves { - template - class OpenGlovesTrackingComponent : public SenseShift::Component { - // Plotter raw_plotter_ = Plotter(&Serial, "Raw"); - // Plotter calibrated_plotter_ = Plotter(&Serial, "Cal"); +template +class OpenGlovesTrackingComponent : public SenseShift::Component { + // Plotter raw_plotter_ = Plotter(&Serial, "Raw"); + // Plotter calibrated_plotter_ = Plotter(&Serial, "Cal"); - public: - class Config { - friend class OpenGlovesTrackingComponent; - size_t calibration_duration_ms_; - bool always_calibrate_; - - public: - /// \param updateRate The rate at which the sensors should be updated in Hz. - /// \param calibrationDuration The duration in milliseconds that the calibration button should be held for. - Config(size_t calibration_duration_ms, bool always_calibrate) : - calibration_duration_ms_(calibration_duration_ms), always_calibrate_(always_calibrate) - { - } - }; - - OpenGlovesTrackingComponent(Config& config, InputSensors& input_sensors, ITransport* communication) : - config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) - { - } + public: + class Config { + friend class OpenGlovesTrackingComponent; + size_t calibration_duration_ms_; + bool always_calibrate_; - void init() override + public: + /// \param updateRate The rate at which the sensors should be updated in Hz. + /// \param calibrationDuration The duration in milliseconds that the calibration button should be held for. + Config(size_t calibration_duration_ms, bool always_calibrate) : + calibration_duration_ms_(calibration_duration_ms), always_calibrate_(always_calibrate) { - this->communication_->init(); - this->input_sensors_.init(); - - // If the calibration button is not present, start calibration immediately. - if (this->config_.always_calibrate_ || this->input_sensors_.button_calibrate.press == nullptr) { - this->startCalibration(); - } } + }; - void tick() override - { - // const auto start = micros(); - - // auto now = micros(); - this->input_sensors_.tick(); - // const auto tickTime = micros() - now; - - // now = micros(); - const auto data = this->input_sensors_.collectData(); - // const auto collectTime = micros() - now; - - // const auto raw_data = this->input_sensors_.collectRawData(); - // this->raw_plotter_.plot(raw_data); - // this->calibrated_plotter_.plot(data); - - bool const calibrate_pressed = data.button_calibrate.press; - if (calibrate_pressed && this->calibration_start_time_ == 0) { - this->startCalibration(); - } + OpenGlovesTrackingComponent(Config& config, InputSensors& input_sensors, ITransport* communication) : + config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) + { + } - // now = micros(); - const auto length = T::encodeInput(data, reinterpret_cast(buffer.data()), buffer.size()); - // const auto encodeTime = micros() - now; + void init() override + { + this->communication_->init(); + this->input_sensors_.init(); - // now = micros(); - this->communication_->send(buffer.data(), length); - // const auto sendTime = micros() - now; + // If the calibration button is not present, start calibration immediately. + if (this->config_.always_calibrate_ || this->input_sensors_.button_calibrate.press == nullptr) { + this->startCalibration(); + } + } - if (!this->config_.always_calibrate_ && this->calibration_start_time_ != 0) { - const auto calibration_elapsed = millis() - this->calibration_start_time_; - const bool calibration_done = calibration_elapsed >= this->config_.calibration_duration_ms_; + void tick() override + { + // const auto start = micros(); - if (calibration_done) { - this->stopCalibration(); - } - } + // auto now = micros(); + this->input_sensors_.tick(); + // const auto tickTime = micros() - now; - // const auto total = micros() - start; - // log_i( - // "total: %d, tick: %d, collect: %d, encode: %d, send: %d, c/s: %.2f", - // total, - // tickTime, - // collectTime, - // encodeTime, - // sendTime, - // 1000000.0 / total - // ); - } + // now = micros(); + const auto data = this->input_sensors_.collectData(); + // const auto collectTime = micros() - now; - protected: - void startCalibration() - { - log_i("Starting calibration"); - this->input_sensors_.reselCalibration(); - this->input_sensors_.startCalibration(); - this->calibration_start_time_ = millis(); - } + // const auto raw_data = this->input_sensors_.collectRawData(); + // this->raw_plotter_.plot(raw_data); + // this->calibrated_plotter_.plot(data); - void stopCalibration() - { - log_i("Stopping calibration"); - this->input_sensors_.stopCalibration(); - this->calibration_start_time_ = 0; + bool const calibrate_pressed = data.button_calibrate.press; + if (calibrate_pressed && this->calibration_start_time_ == 0) { + this->startCalibration(); } - private: - std::array buffer = {}; - - unsigned long long calibration_start_time_ = 0; + // now = micros(); + const auto length = T::encodeInput(data, reinterpret_cast(buffer.data()), buffer.size()); + // const auto encodeTime = micros() - now; - Config& config_; - InputSensors input_sensors_; - ITransport* communication_; - }; + // now = micros(); + this->communication_->send(buffer.data(), length); + // const auto sendTime = micros() - now; - template - class OpenGlovesForceFeedbackComponent : public SenseShift::Component { - public: - OpenGlovesForceFeedbackComponent( - OutputWriters& output_writers, ::SenseShift::OpenGloves::ITransport* communication - ) : - output_writers_(output_writers), communication_(communication){}; + if (!this->config_.always_calibrate_ && this->calibration_start_time_ != 0) { + const auto calibration_elapsed = millis() - this->calibration_start_time_; + const bool calibration_done = calibration_elapsed >= this->config_.calibration_duration_ms_; - void init() override - { - log_d("Setting up OpenGloves force feedback task: %p", this); - this->communication_->init(); - this->output_writers_.init(); + if (calibration_done) { + this->stopCalibration(); + } } - void tick() override - { - if (this->communication_->hasData()) { - const auto length = this->communication_->read(this->buffer.data(), this->buffer.size()); - const auto output = T::decodeOutput(reinterpret_cast(this->buffer.data()), length); - this->output_writers_.apply(output); - } + // const auto total = micros() - start; + // log_i( + // "total: %d, tick: %d, collect: %d, encode: %d, send: %d, c/s: %.2f", + // total, + // tickTime, + // collectTime, + // encodeTime, + // sendTime, + // 1000000.0 / total + // ); + } + + protected: + void startCalibration() + { + log_i("Starting calibration"); + this->input_sensors_.reselCalibration(); + this->input_sensors_.startCalibration(); + this->calibration_start_time_ = millis(); + } + + void stopCalibration() + { + log_i("Stopping calibration"); + this->input_sensors_.stopCalibration(); + this->calibration_start_time_ = 0; + } + + private: + std::array buffer = {}; + + unsigned long long calibration_start_time_ = 0; + + Config& config_; + InputSensors input_sensors_; + ITransport* communication_; +}; + +template +class OpenGlovesForceFeedbackComponent : public SenseShift::Component { + public: + OpenGlovesForceFeedbackComponent( + OutputWriters& output_writers, ::SenseShift::OpenGloves::ITransport* communication + ) : + output_writers_(output_writers), communication_(communication){}; + + void init() override + { + log_d("Setting up OpenGloves force feedback task: %p", this); + this->communication_->init(); + this->output_writers_.init(); + } + + void tick() override + { + if (this->communication_->hasData()) { + const auto length = this->communication_->read(this->buffer.data(), this->buffer.size()); + const auto output = T::decodeOutput(reinterpret_cast(this->buffer.data()), length); + this->output_writers_.apply(output); } + } - private: - std::array buffer = {}; + private: + std::array buffer = {}; - OutputWriters output_writers_; - ::SenseShift::OpenGloves::ITransport* communication_; - }; + OutputWriters output_writers_; + ::SenseShift::OpenGloves::ITransport* communication_; +}; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp index 13009cda..9c113f25 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp @@ -5,33 +5,33 @@ #include "opengloves.hpp" namespace SenseShift::OpenGloves { - class Plotter { - public: - Plotter(Print* output, char* prefix) : output_(output), prefix_(prefix){}; +class Plotter { + public: + Plotter(Print* output, char* prefix) : output_(output), prefix_(prefix){}; - void plot(const og::InputPeripheralData data) - { - this->output_->printf("%sThumbCurl: ", this->prefix_); - this->output_->printf("%4.0f", data.curl.thumb.curl_total * 4095); - this->output_->printf(", %sIndexCurl: ", this->prefix_); - this->output_->printf("%4.0f", data.curl.index.curl_total * 4095); - this->output_->printf(", %sMiddleCurl: ", this->prefix_); - this->output_->printf("%4.0f", data.curl.middle.curl_total * 4095); - this->output_->printf(", %sRingCurl: ", this->prefix_); - this->output_->printf("%4.0f", data.curl.ring.curl_total * 4095); - this->output_->printf(", %sPinkyCurl: ", this->prefix_); - this->output_->printf("%4.0f", data.curl.pinky.curl_total * 4095); + void plot(const og::InputPeripheralData data) + { + this->output_->printf("%sThumbCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.thumb.curl_total * 4095); + this->output_->printf(", %sIndexCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.index.curl_total * 4095); + this->output_->printf(", %sMiddleCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.middle.curl_total * 4095); + this->output_->printf(", %sRingCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.ring.curl_total * 4095); + this->output_->printf(", %sPinkyCurl: ", this->prefix_); + this->output_->printf("%4.0f", data.curl.pinky.curl_total * 4095); - this->output_->printf(", %sJoyX: ", this->prefix_); - this->output_->printf("%4.0f", data.joystick.x * 4095); - this->output_->printf(", %sJoyY: ", this->prefix_); - this->output_->printf("%4.0f", data.joystick.y * 4095); + this->output_->printf(", %sJoyX: ", this->prefix_); + this->output_->printf("%4.0f", data.joystick.x * 4095); + this->output_->printf(", %sJoyY: ", this->prefix_); + this->output_->printf("%4.0f", data.joystick.y * 4095); - this->output_->println(); - } + this->output_->println(); + } - private: - Print* const output_; - char* const prefix_; - }; + private: + Print* const output_; + char* const prefix_; +}; } // namespace SenseShift::OpenGloves diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index f25ada40..51f3ec61 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -11,124 +11,134 @@ #include namespace SenseShift::OpenGloves { - class IStreamTransport : public ITransport { - protected: - Stream* channel; - std::array buffer_{}; - - public: - IStreamTransport(Stream* channel) : channel(channel){}; - - auto send(const char* buffer, size_t length) -> size_t override - { - if (!this->isReady()) { - return 0; - } - - const auto written = this->channel->write(buffer, length); - this->channel->flush(); - - return written; - } - - virtual auto isReady() -> bool = 0; - - auto hasData() -> bool override - { - return this->isReady() && this->channel != nullptr && this->channel->available() > 0; +class IStreamTransport : public ITransport { + protected: + Stream* channel; + std::array buffer_{}; + + public: + IStreamTransport(Stream* channel) : channel(channel){}; + + auto send(const char* buffer, size_t length) -> size_t override + { + if (!this->isReady()) { + return 0; } - auto read(char* buffer, size_t length) -> size_t override - { - if (!this->hasData()) { - return 0U; - } - - size_t bytesRead = this->channel->readBytesUntil('\n', buffer, length); - buffer[bytesRead] = '\0'; - - return bytesRead; - } - }; - - class StreamTransport : public IStreamTransport { - public: - explicit StreamTransport(Stream& channel) : IStreamTransport(&channel){}; - explicit StreamTransport(Stream* channel) : IStreamTransport(channel){}; - - void init() override { this->mReady = true; } + const auto written = this->channel->write(buffer, length); + this->channel->flush(); - auto isReady() -> bool override { return this->channel != nullptr && this->mReady; } + return written; + } - private: - bool mReady = false; - }; + virtual auto isReady() -> bool = 0; - class BluetoothSerialTransport : public IStreamTransport { - public: - explicit BluetoothSerialTransport(BluetoothSerial& channel) : IStreamTransport(&channel){}; + auto hasData() -> bool override + { + return this->isReady() && this->channel != nullptr && this->channel->available() > 0; + } - auto isReady() -> bool override - { - auto* serial = static_cast(this->channel); - return serial->isReady() && serial->hasClient(); + auto read(char* buffer, size_t length) -> size_t override + { + if (!this->hasData()) { + return 0U; } - void init() override {} - - auto send(const char* buffer, size_t length) -> size_t override - { - auto written = this->channel->write(buffer, length); - - // TODO: This is a hack to ensure the data is sent - delay(2); - - return written; - } - }; - - template> - class BLESerialTransport : public IStreamTransport { - public: - explicit BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; - - void init() override {} - - auto isReady() -> bool override - { - auto* serial = static_cast*>(this->channel); - return serial->connected(); - } - }; - - class WiFiSerialTransport : public IStreamTransport { - public: - WiFiSerialTransport(WiFiServer& server) : IStreamTransport(nullptr), m_server(server){}; - - void init() override - { - auto* client = static_cast(this->channel); - if (client != nullptr) { - if (client->connected() != 0U) { - return; - } + size_t bytesRead = this->channel->readBytesUntil('\n', buffer, length); + buffer[bytesRead] = '\0'; + + return bytesRead; + } +}; + +class StreamTransport : public IStreamTransport { + public: + explicit StreamTransport(Stream& channel) : IStreamTransport(&channel){}; + explicit StreamTransport(Stream* channel) : IStreamTransport(channel){}; + + void init() override + { + this->mReady = true; + } + + auto isReady() -> bool override + { + return this->channel != nullptr && this->mReady; + } + + private: + bool mReady = false; +}; + +class BluetoothSerialTransport : public IStreamTransport { + public: + explicit BluetoothSerialTransport(BluetoothSerial& channel) : IStreamTransport(&channel){}; + + auto isReady() -> bool override + { + auto* serial = static_cast(this->channel); + return serial->isReady() && serial->hasClient(); + } + + void init() override + { + } + + auto send(const char* buffer, size_t length) -> size_t override + { + auto written = this->channel->write(buffer, length); + + // TODO: This is a hack to ensure the data is sent + delay(2); + + return written; + } +}; + +template> +class BLESerialTransport : public IStreamTransport { + public: + explicit BLESerialTransport(BLESerial& channel) : IStreamTransport(&channel){}; + + void init() override + { + } + + auto isReady() -> bool override + { + auto* serial = static_cast*>(this->channel); + return serial->connected(); + } +}; + +class WiFiSerialTransport : public IStreamTransport { + public: + WiFiSerialTransport(WiFiServer& server) : IStreamTransport(nullptr), m_server(server){}; + + void init() override + { + auto* client = static_cast(this->channel); + if (client != nullptr) { + if (client->connected() != 0U) { + return; } - - this->m_server.begin(); - this->channel = new WiFiClient(this->m_server.accept()); } - auto isReady() -> bool override - { - if (this->channel == nullptr) { - return false; - } + this->m_server.begin(); + this->channel = new WiFiClient(this->m_server.accept()); + } - auto* client = static_cast(this->channel); - return client->connected() != 0U; + auto isReady() -> bool override + { + if (this->channel == nullptr) { + return false; } - private: - WiFiServer& m_server; - }; + auto* client = static_cast(this->channel); + return client->connected() != 0U; + } + + private: + WiFiServer& m_server; +}; } // namespace SenseShift::OpenGloves diff --git a/lib/util/senseshift/buffer.hpp b/lib/util/senseshift/buffer.hpp index a6756cb8..37564136 100644 --- a/lib/util/senseshift/buffer.hpp +++ b/lib/util/senseshift/buffer.hpp @@ -5,160 +5,175 @@ #include namespace SenseShift { - template - struct IBuffer { - using ValueType = _Tp; - - IBuffer() = default; - virtual ~IBuffer() = default; - - virtual bool push(const ValueType value) = 0; - virtual bool push(const ValueType* values, size_t length) = 0; - virtual void clear() = 0; - virtual ValueType pop() = 0; - virtual ValueType get(size_t index) const = 0; - virtual size_t getLength() const = 0; - - virtual ValueType operator[](size_t index) const { return this->get(index); } - }; - - template - class RingBuffer : public IBuffer<_Tp> { - public: - using ValueType = _Tp; - - bool push(const ValueType value) override - { - this->mRingBuffer[this->mNewestIndex] = value; - this->mNewestIndex = (this->mNewestIndex + 1) % N; - this->mLength = std::min(this->mLength + 1, N); - - return true; +template +struct IBuffer { + using ValueType = _Tp; + + IBuffer() = default; + virtual ~IBuffer() = default; + + virtual bool push(const ValueType value) = 0; + virtual bool push(const ValueType* values, size_t length) = 0; + virtual void clear() = 0; + virtual ValueType pop() = 0; + virtual ValueType get(size_t index) const = 0; + virtual size_t getLength() const = 0; + + virtual ValueType operator[](size_t index) const + { + return this->get(index); + } +}; + +template +class RingBuffer : public IBuffer<_Tp> { + public: + using ValueType = _Tp; + + bool push(const ValueType value) override + { + this->mRingBuffer[this->mNewestIndex] = value; + this->mNewestIndex = (this->mNewestIndex + 1) % N; + this->mLength = std::min(this->mLength + 1, N); + + return true; + } + + bool push(const ValueType* values, size_t length) override + { + if (this->mLength + length > N) { + return false; } - bool push(const ValueType* values, size_t length) override - { - if (this->mLength + length > N) { - return false; - } - - for (size_t i = 0; i < length; i++) { - this->push(values[i]); - } - - return true; + for (size_t i = 0; i < length; i++) { + this->push(values[i]); } - void clear() override - { - this->mNewestIndex = 0; - this->mLength = 0; + return true; + } + + void clear() override + { + this->mNewestIndex = 0; + this->mLength = 0; + } + + /** + * @brief Remove the oldest value from the buffer and return it. + * If the buffer is empty, `-1` is returned. + */ + ValueType pop() override + { + if (this->mLength == 0) { + return -1; } - - /** - * @brief Remove the oldest value from the buffer and return it. - * If the buffer is empty, `-1` is returned. - */ - ValueType pop() override - { - if (this->mLength == 0) { - return -1; - } - ValueType result = this->mRingBuffer[(N + this->mNewestIndex - this->mLength) % N]; - this->mLength -= 1; - return result; + ValueType result = this->mRingBuffer[(N + this->mNewestIndex - this->mLength) % N]; + this->mLength -= 1; + return result; + } + + /** + * @brief Get the value at the given index. + * + * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value + */ + ValueType get(size_t index) const override + { + if (index < 0 || index >= this->mLength) { + return -1; } - - /** - * @brief Get the value at the given index. - * - * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value - */ - ValueType get(size_t index) const override - { - if (index < 0 || index >= this->mLength) { - return -1; - } - return this->mRingBuffer[(N + this->mNewestIndex - this->mLength + index) % N]; + return this->mRingBuffer[(N + this->mNewestIndex - this->mLength + index) % N]; + } + + size_t getLength() const override + { + return this->mLength; + } + + private: + ValueType mRingBuffer[N]; + size_t mNewestIndex = 0; + size_t mLength = 0; +}; + +template +class FixedSizeBuffer : public IBuffer<_Tp> { + public: + using ValueType = _Tp; + + FixedSizeBuffer() = default; + virtual ~FixedSizeBuffer() = default; + + bool push(const ValueType value) override + { + if (this->mLength == N) { + return false; } + this->mBuffer[this->mLength] = value; + this->mLength += 1; - size_t getLength() const override { return this->mLength; } - - private: - ValueType mRingBuffer[N]; - size_t mNewestIndex = 0; - size_t mLength = 0; - }; - - template - class FixedSizeBuffer : public IBuffer<_Tp> { - public: - using ValueType = _Tp; - - FixedSizeBuffer() = default; - virtual ~FixedSizeBuffer() = default; - - bool push(const ValueType value) override - { - if (this->mLength == N) { - return false; - } - this->mBuffer[this->mLength] = value; - this->mLength += 1; + return true; + } - return true; + bool push(const ValueType* values, size_t length) override + { + if (this->mLength + length > N) { + return false; } - bool push(const ValueType* values, size_t length) override - { - if (this->mLength + length > N) { - return false; - } - - memcpy(this->mBuffer.data() + this->mLength, values, length); - this->mLength += length; - - return true; + memcpy(this->mBuffer.data() + this->mLength, values, length); + this->mLength += length; + + return true; + } + + void clear() override + { + this->mLength = 0; + } + + /** + * @brief Remove the oldest value from the buffer and return it. + * If the buffer is empty, `-1` is returned. + */ + ValueType pop() override + { + if (this->mLength == 0) { + return -1; } - - void clear() override { this->mLength = 0; } - - /** - * @brief Remove the oldest value from the buffer and return it. - * If the buffer is empty, `-1` is returned. - */ - ValueType pop() override - { - if (this->mLength == 0) { - return -1; - } - ValueType result = this->mBuffer[0]; - for (size_t i = 1; i < this->mLength; i++) { - this->mBuffer[i - 1] = this->mBuffer[i]; - } - this->mLength -= 1; - return result; + ValueType result = this->mBuffer[0]; + for (size_t i = 1; i < this->mLength; i++) { + this->mBuffer[i - 1] = this->mBuffer[i]; } - - /** - * @brief Get the value at the given index. - * - * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value - */ - ValueType get(size_t index) const override - { - if (index < 0 || index >= this->mLength) { - return -1; - } - return this->mBuffer[index]; + this->mLength -= 1; + return result; + } + + /** + * @brief Get the value at the given index. + * + * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value + */ + ValueType get(size_t index) const override + { + if (index < 0 || index >= this->mLength) { + return -1; } - - ValueType* getData() { return this->mBuffer.data(); } - - size_t getLength() const override { return this->mLength; } - - private: - std::array mBuffer; - size_t mLength = 0; - }; + return this->mBuffer[index]; + } + + ValueType* getData() + { + return this->mBuffer.data(); + } + + size_t getLength() const override + { + return this->mLength; + } + + private: + std::array mBuffer; + size_t mLength = 0; +}; } // namespace SenseShift diff --git a/lib/util/senseshift/container.hpp b/lib/util/senseshift/container.hpp index 613b962b..afd42a2a 100644 --- a/lib/util/senseshift/container.hpp +++ b/lib/util/senseshift/container.hpp @@ -6,37 +6,37 @@ #include namespace SenseShift { - /** - * Checks if a container contains a value. - * - * @tparam _Cp The type of the container. - * @tparam _Tp The type of the value. - */ - template - inline auto contains(Cp&& c, Tp val) -> bool - { - return std::find(std::begin(c), std::end(c), val) != std::end(c); - }; +/** + * Checks if a container contains a value. + * + * @tparam _Cp The type of the container. + * @tparam _Tp The type of the value. + */ +template +inline auto contains(Cp&& c, Tp val) -> bool +{ + return std::find(std::begin(c), std::end(c), val) != std::end(c); +}; - template<> - inline auto contains(std::string& s, char val) -> bool - { - return s.find(val) != std::string::npos; - }; +template<> +inline auto contains(std::string& s, char val) -> bool +{ + return s.find(val) != std::string::npos; +}; - template - inline auto contains(Tp* begin, Tp* end, const Tp& val) -> bool - { - return std::find(begin, end, val) != end; - }; +template +inline auto contains(Tp* begin, Tp* end, const Tp& val) -> bool +{ + return std::find(begin, end, val) != end; +}; - template - constexpr inline auto contains(const Tp* arr, const std::size_t size, const Tp& val) -> bool - { - static_assert( - std::is_same_v::value_type>, - "Container and value must be of the same type" - ); - return std::find(arr, arr + size, val) != arr + size; - }; +template +constexpr inline auto contains(const Tp* arr, const std::size_t size, const Tp& val) -> bool +{ + static_assert( + std::is_same_v::value_type>, + "Container and value must be of the same type" + ); + return std::find(arr, arr + size, val) != arr + size; +}; } // namespace SenseShift diff --git a/test/test_battery/main.cpp b/test/test_battery/main.cpp index 0274bb36..5316c228 100644 --- a/test/test_battery/main.cpp +++ b/test/test_battery/main.cpp @@ -41,7 +41,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else @@ -50,4 +52,4 @@ int main(int argc, char** argv) return process(); } -#endif \ No newline at end of file +#endif diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 0d171a91..facbb6ca 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -11,9 +11,17 @@ class TestActuator : public IOutput { bool isSetup = false; float intensity = 0; - TestActuator() : IFloatOutput() {} - void init() override { this->isSetup = true; } - void writeState(float newIntensity) override { this->intensity = newIntensity; } + TestActuator() : IFloatOutput() + { + } + void init() override + { + this->isSetup = true; + } + void writeState(float newIntensity) override + { + this->intensity = newIntensity; + } }; #define ASSERT_EQUAL_FLOAT_ROUNDED(expected, actual, precision) \ @@ -268,7 +276,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index 0cd7e5a6..6bcb0335 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -95,7 +95,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_core_helpers/main.cpp b/test/test_core_helpers/main.cpp index e1bcdd29..24c5b771 100644 --- a/test/test_core_helpers/main.cpp +++ b/test/test_core_helpers/main.cpp @@ -117,7 +117,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 96b39736..364dbc72 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -9,9 +9,17 @@ class TestActuator : public IOutput { bool isSetup = false; float intensity = 0; - TestActuator() : IFloatOutput() {} - void init() override { this->isSetup = true; } - void writeState(float newIntensity) override { this->intensity = newIntensity; } + TestActuator() : IFloatOutput() + { + } + void init() override + { + this->isSetup = true; + } + void writeState(float newIntensity) override + { + this->intensity = newIntensity; + } }; void test_it_sets_up_planes(void) @@ -82,7 +90,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index a9c329a1..6e45a75f 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -9,9 +9,17 @@ class TestActuator : public IOutput { bool isSetup = false; float intensity = 0; - TestActuator() : IFloatOutput() {} - void init() override { this->isSetup = true; } - void writeState(float newIntensity) override { this->intensity = newIntensity; } + TestActuator() : IFloatOutput() + { + } + void init() override + { + this->isSetup = true; + } + void writeState(float newIntensity) override + { + this->intensity = newIntensity; + } }; void test_it_sets_up_actuators(void) @@ -213,7 +221,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_io_calibration/main.cpp b/test/test_io_calibration/main.cpp index f554fab5..a0dc6f6b 100644 --- a/test/test_io_calibration/main.cpp +++ b/test/test_io_calibration/main.cpp @@ -130,7 +130,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp index 7e7a995f..cf562048 100644 --- a/test/test_io_filter/main.cpp +++ b/test/test_io_filter/main.cpp @@ -190,7 +190,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index 42fd0937..a93a536f 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -9,9 +9,15 @@ class TestAnalogCountingSensor : public ISimpleSensor { int count = 0; int setupCounter = 0; - void init() override { this->setupCounter++; }; + void init() override + { + this->setupCounter++; + }; - auto getValue() -> int override { return ++this->count; }; + auto getValue() -> int override + { + return ++this->count; + }; }; class TestAnalogSensor : public ISimpleSensor { @@ -19,9 +25,15 @@ class TestAnalogSensor : public ISimpleSensor { int value = 0; int setupCounter = 0; - void init() override { this->setupCounter++; }; + void init() override + { + this->setupCounter++; + }; - auto getValue() -> int override { return this->value; }; + auto getValue() -> int override + { + return this->value; + }; }; class TestFloatSensor : public ISimpleSensor { @@ -29,9 +41,15 @@ class TestFloatSensor : public ISimpleSensor { float value = 0.0f; int setupCounter = 0; - void init() override { this->setupCounter++; }; + void init() override + { + this->setupCounter++; + }; - auto getValue() -> float override { return this->value; }; + auto getValue() -> float override + { + return this->value; + }; }; void test_memoized_sensor(void) @@ -62,8 +80,14 @@ class DummyCalibrator : public ::SenseShift::Input::Calibration::ICalibratorresetCounter++; this->calibrated = 0.0f; }; - void update(float input) override { this->calibrated = input; }; - float calibrate(float input) const override { return calibrated; }; + void update(float input) override + { + this->calibrated = input; + }; + float calibrate(float input) const override + { + return calibrated; + }; }; void test_calibrated_sensor(void) @@ -224,7 +248,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_math_point2/main.cpp b/test/test_math_point2/main.cpp index a4fa7baf..1ac4a254 100644 --- a/test/test_math_point2/main.cpp +++ b/test/test_math_point2/main.cpp @@ -63,7 +63,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_util_buffer/main.cpp b/test/test_util_buffer/main.cpp index 14eec519..f1e2bf8a 100644 --- a/test/test_util_buffer/main.cpp +++ b/test/test_util_buffer/main.cpp @@ -156,7 +156,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else diff --git a/test/test_util_container/main.cpp b/test/test_util_container/main.cpp index ed0279ca..98ac6005 100644 --- a/test/test_util_container/main.cpp +++ b/test/test_util_container/main.cpp @@ -65,7 +65,9 @@ void setup(void) process(); } -void loop(void) {} +void loop(void) +{ +} #else @@ -74,4 +76,4 @@ int main(int argc, char** argv) return process(); } -#endif \ No newline at end of file +#endif From 986486468eaf2fbfbc3394d25a8d6dfb30f6de4b Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 27 Jul 2024 19:16:57 +0400 Subject: [PATCH 20/67] refactor: use template params for auto-mapping --- .clang-tidy | 37 +++++++++++++++++- examples/bhaptics-ble-bt-serial.cpp | 2 +- firmware/mode_configs/bhaptics/tactal.cpp | 2 +- firmware/mode_configs/bhaptics/tactosy2.cpp | 2 +- firmware/mode_configs/bhaptics/tactosyf.cpp | 2 +- firmware/mode_configs/bhaptics/tactosyh.cpp | 2 +- .../mode_configs/bhaptics/tactsuit_x16.cpp | 4 +- .../bhaptics/tactsuit_x16_pca9685.cpp | 4 +- .../mode_configs/bhaptics/tactsuit_x40.cpp | 38 ++++++++++--------- firmware/mode_configs/bhaptics/tactvisor.cpp | 2 +- lib/haptics/senseshift/body/haptics/plane.hpp | 18 ++++++--- test/test_bhaptics_encoding/main.cpp | 10 ++--- 12 files changed, 84 insertions(+), 39 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index bc01716a..631a236a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1 +1,36 @@ -Checks: 'bugprone-*,clang-analyzer-*,google-*,hicpp-*,misc-*,modernize-*,performance-*,portability-*,readability-*' +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,modernize-*,-modernize-use-trailing-return-type' +WarningsAsErrors: true +HeaderFilterRegex: '' +AnalyzeTemporaryDtors: false +FormatStyle: google +CheckOptions: + - key: cert-dcl16-c.NewSuffixes + value: 'L;LL;LU;LLU' + - key: cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField + value: '0' + - key: cppcoreguidelines-explicit-virtual-functions.IgnoreDestructors + value: '1' + - key: cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic + value: '1' + - key: google-readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-readability-function-size.StatementThreshold + value: '800' + - key: google-readability-namespace-comments.ShortNamespaceLines + value: '10' + - key: google-readability-namespace-comments.SpacesBeforeComments + value: '2' + - key: modernize-loop-convert.MaxCopySize + value: '16' + - key: modernize-loop-convert.MinConfidence + value: reasonable + - key: modernize-loop-convert.NamingStyle + value: CamelCase + - key: modernize-pass-by-value.IncludeStyle + value: llvm + - key: modernize-replace-auto-ptr.IncludeStyle + value: llvm + - key: modernize-use-nullptr.NullMacros + value: 'NULL' +... diff --git a/examples/bhaptics-ble-bt-serial.cpp b/examples/bhaptics-ble-bt-serial.cpp index 808b6821..15c57e9c 100644 --- a/examples/bhaptics-ble-bt-serial.cpp +++ b/examples/bhaptics-ble-bt-serial.cpp @@ -35,7 +35,7 @@ class BLECallbacks : public BHBLEConnectionCallbacks { void setupMode() { // Configure PWM pins to their positions on the face - auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off {new ActuatorPWM(32), new ActuatorPWM(33), new ActuatorPWM(25), new ActuatorPWM(26), new ActuatorPWM(27), new ActuatorPWM(14)}, // clang-format on diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index cfdd4e9c..ae5f4970 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -32,7 +32,7 @@ static const std::array bhLayout = { BH_LAYOUT_ void setupMode() { // Configure PWM pins to their positions on the face - const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26), new LedcOutput(27), new LedcOutput(14) }, // clang-format on diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index ea6373b4..f4310b9b 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -32,7 +32,7 @@ static const std::array bhLayout = { BH_LAYOU void setupMode() { // Configure PWM pins to their positions on the forearm - auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25) }, { new LedcOutput(26), new LedcOutput(27), new LedcOutput(14) }, diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index 63860af4..c41334a0 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -32,7 +32,7 @@ static const std::array bhLayout = { BH_LAYOU void setupMode() { // Configure PWM pins to their positions on the feet - auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(32) }, { new LedcOutput(33) }, diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index be8bfd79..900b9a23 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -32,7 +32,7 @@ static const std::array bhLayout = { BH_LAYOU void setupMode() { // Configure PWM pins to their positions on the hands - auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(32) }, { new LedcOutput(33) }, diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index bdc9521b..3f8913b1 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -35,13 +35,13 @@ static const std::array layoutG void setupMode() { // Configure PWM pins to their positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) }, { new LedcOutput(27), new LedcOutput(14), new LedcOutput(12), new LedcOutput(13) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(19), new LedcOutput(18), new LedcOutput(5), new LedcOutput(17) }, { new LedcOutput(16), new LedcOutput(4), new LedcOutput(2), new LedcOutput(15) }, diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 2042b582..576a7501 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -40,13 +40,13 @@ void setupMode() pwm->setPWMFreq(PWM_FREQUENCY); // Assign the pins on the configured PCA9685 to positions on the vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new PCA9685Output(pwm, 0), new PCA9685Output(pwm, 1), new PCA9685Output(pwm, 2), new PCA9685Output(pwm, 3) }, { new PCA9685Output(pwm, 4), new PCA9685Output(pwm, 5), new PCA9685Output(pwm, 6), new PCA9685Output(pwm, 7) }, // clang-format on }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new PCA9685Output(pwm, 8), new PCA9685Output(pwm, 9), new PCA9685Output(pwm, 10), new PCA9685Output(pwm, 11) }, { new PCA9685Output(pwm, 12), new PCA9685Output(pwm, 13), new PCA9685Output(pwm, 14), new PCA9685Output(pwm, 15) }, diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 09e0dab1..a85a610a 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -43,24 +43,26 @@ void setupMode() // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ - // clang-format off - { new PCA9685Output(pwm0, 0), new PCA9685Output(pwm0, 1), new PCA9685Output(pwm0, 2), new PCA9685Output(pwm0, 3) }, - { new PCA9685Output(pwm0, 4), new PCA9685Output(pwm0, 5), new PCA9685Output(pwm0, 6), new PCA9685Output(pwm0, 7) }, - { new PCA9685Output(pwm0, 8), new PCA9685Output(pwm0, 9), new PCA9685Output(pwm0, 10), new PCA9685Output(pwm0, 11) }, - { new PCA9685Output(pwm0, 12), new PCA9685Output(pwm0, 13), new PCA9685Output(pwm0, 14), new PCA9685Output(pwm0, 15) }, - { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) }, - // clang-format on - }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ - // clang-format off - { new PCA9685Output(pwm1, 0), new PCA9685Output(pwm1, 1), new PCA9685Output(pwm1, 2), new PCA9685Output(pwm1, 3) }, - { new PCA9685Output(pwm1, 4), new PCA9685Output(pwm1, 5), new PCA9685Output(pwm1, 6), new PCA9685Output(pwm1, 7) }, - { new PCA9685Output(pwm1, 8), new PCA9685Output(pwm1, 9), new PCA9685Output(pwm1, 10), new PCA9685Output(pwm1, 11) }, - { new PCA9685Output(pwm1, 12), new PCA9685Output(pwm1, 13), new PCA9685Output(pwm1, 14), new PCA9685Output(pwm1, 15) }, - { new LedcOutput(27), new LedcOutput(14), new LedcOutput(12), new LedcOutput(13) }, - // clang-format on - }); + auto frontOutputs = PlaneMapper_Margin:: + mapMatrixCoordinates, 5>>({ { + // clang-format off + { new PCA9685Output(pwm0, 0), new PCA9685Output(pwm0, 1), new PCA9685Output(pwm0, 2), new PCA9685Output(pwm0, 3) }, + { new PCA9685Output(pwm0, 4), new PCA9685Output(pwm0, 5), new PCA9685Output(pwm0, 6), new PCA9685Output(pwm0, 7) }, + { new PCA9685Output(pwm0, 8), new PCA9685Output(pwm0, 9), new PCA9685Output(pwm0, 10), new PCA9685Output(pwm0, 11) }, + { new PCA9685Output(pwm0, 12), new PCA9685Output(pwm0, 13), new PCA9685Output(pwm0, 14), new PCA9685Output(pwm0, 15) }, + { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) }, + // clang-format on + } }); + auto backOutputs = PlaneMapper_Margin:: + mapMatrixCoordinates, 5>>({ { + // clang-format off + { new PCA9685Output(pwm1, 0), new PCA9685Output(pwm1, 1), new PCA9685Output(pwm1, 2), new PCA9685Output(pwm1, 3) }, + { new PCA9685Output(pwm1, 4), new PCA9685Output(pwm1, 5), new PCA9685Output(pwm1, 6), new PCA9685Output(pwm1, 7) }, + { new PCA9685Output(pwm1, 8), new PCA9685Output(pwm1, 9), new PCA9685Output(pwm1, 10), new PCA9685Output(pwm1, 11) }, + { new PCA9685Output(pwm1, 12), new PCA9685Output(pwm1, 13), new PCA9685Output(pwm1, 14), new PCA9685Output(pwm1, 15) }, + { new LedcOutput(27), new LedcOutput(14), new LedcOutput(12), new LedcOutput(13) }, + // clang-format on + } }); app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index b6c618bc..a6bf5ef7 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -32,7 +32,7 @@ static const std::array bhLayout = { BH_LAYO void setupMode() { // Configure PWM pins to their positions on the face - auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ // clang-format off { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) }, // clang-format on diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index 54b7a653..f446c758 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -89,11 +89,19 @@ using FloatPlane_Closest = OutputPlane_Closest - [[nodiscard]] static auto mapMatrixCoordinates(std::vector> map2d) -> std::map + /// Maps a 2D matrix into a (coord, object) map. + /// + /// \tparam Tp + /// \tparam I Input 2D matrix type. + /// \tparam O Output map type. + /// + /// \param map2d Input 2D matrix. + /// + /// \return Output map. + template>, typename O = std::map> + static auto mapMatrixCoordinates(I map2d) -> O { - std::map points{}; + O points{}; const size_t y_size = map2d.size(); const size_t y_max = y_size - 1; @@ -104,7 +112,7 @@ class PlaneMapper_Margin { const size_t x_max = x_size - 1; for (size_t x = 0; x < x_size; ++x) { - auto* wr = row.at(x); + Tp wr = row.at(x); Position coord = mapPoint(x, y, x_max, y_max); points[coord] = wr; diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index facbb6ca..70b34e79 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -55,11 +55,11 @@ void test_layout_tactsuitx16(void) TestActuator* actuator14 = new TestActuator(); TestActuator* actuator15 = new TestActuator(); - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ { actuator0, actuator1, actuator2, actuator3 }, { actuator4, actuator5, actuator6, actuator7 }, }); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ { actuator8, actuator9, actuator10, actuator11 }, { actuator12, actuator13, actuator14, actuator15 }, }); @@ -117,8 +117,8 @@ void test_layout_tactsuitx40(void) { new TestActuator(), new TestActuator(), new TestActuator(), new TestActuator() }, }; - auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates(frontMatrix); - auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates(backMatrix); + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates(frontMatrix); + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates(backMatrix); auto frontPlane = new FloatPlane(frontOutputs); auto backPlane = new FloatPlane(backOutputs); @@ -191,7 +191,7 @@ void test_layout_tactal(void) TestActuator* actuator4 = new TestActuator(); TestActuator* actuator5 = new TestActuator(); - auto outputs = PlaneMapper_Margin::mapMatrixCoordinates({ + auto outputs = PlaneMapper_Margin::mapMatrixCoordinates({ { actuator0, actuator1, actuator2, actuator3, actuator4, actuator5 }, }); auto plane = new FloatPlane(outputs); From a9817ea9cd2fda836203d2aa26a8e1ddd21e7932 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 01:15:37 +0400 Subject: [PATCH 21/67] refactor: remove unused buffer types --- lib/util/senseshift/buffer.hpp | 179 --------------------------------- test/test_util_buffer/main.cpp | 170 ------------------------------- 2 files changed, 349 deletions(-) delete mode 100644 lib/util/senseshift/buffer.hpp delete mode 100644 test/test_util_buffer/main.cpp diff --git a/lib/util/senseshift/buffer.hpp b/lib/util/senseshift/buffer.hpp deleted file mode 100644 index 37564136..00000000 --- a/lib/util/senseshift/buffer.hpp +++ /dev/null @@ -1,179 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace SenseShift { -template -struct IBuffer { - using ValueType = _Tp; - - IBuffer() = default; - virtual ~IBuffer() = default; - - virtual bool push(const ValueType value) = 0; - virtual bool push(const ValueType* values, size_t length) = 0; - virtual void clear() = 0; - virtual ValueType pop() = 0; - virtual ValueType get(size_t index) const = 0; - virtual size_t getLength() const = 0; - - virtual ValueType operator[](size_t index) const - { - return this->get(index); - } -}; - -template -class RingBuffer : public IBuffer<_Tp> { - public: - using ValueType = _Tp; - - bool push(const ValueType value) override - { - this->mRingBuffer[this->mNewestIndex] = value; - this->mNewestIndex = (this->mNewestIndex + 1) % N; - this->mLength = std::min(this->mLength + 1, N); - - return true; - } - - bool push(const ValueType* values, size_t length) override - { - if (this->mLength + length > N) { - return false; - } - - for (size_t i = 0; i < length; i++) { - this->push(values[i]); - } - - return true; - } - - void clear() override - { - this->mNewestIndex = 0; - this->mLength = 0; - } - - /** - * @brief Remove the oldest value from the buffer and return it. - * If the buffer is empty, `-1` is returned. - */ - ValueType pop() override - { - if (this->mLength == 0) { - return -1; - } - ValueType result = this->mRingBuffer[(N + this->mNewestIndex - this->mLength) % N]; - this->mLength -= 1; - return result; - } - - /** - * @brief Get the value at the given index. - * - * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value - */ - ValueType get(size_t index) const override - { - if (index < 0 || index >= this->mLength) { - return -1; - } - return this->mRingBuffer[(N + this->mNewestIndex - this->mLength + index) % N]; - } - - size_t getLength() const override - { - return this->mLength; - } - - private: - ValueType mRingBuffer[N]; - size_t mNewestIndex = 0; - size_t mLength = 0; -}; - -template -class FixedSizeBuffer : public IBuffer<_Tp> { - public: - using ValueType = _Tp; - - FixedSizeBuffer() = default; - virtual ~FixedSizeBuffer() = default; - - bool push(const ValueType value) override - { - if (this->mLength == N) { - return false; - } - this->mBuffer[this->mLength] = value; - this->mLength += 1; - - return true; - } - - bool push(const ValueType* values, size_t length) override - { - if (this->mLength + length > N) { - return false; - } - - memcpy(this->mBuffer.data() + this->mLength, values, length); - this->mLength += length; - - return true; - } - - void clear() override - { - this->mLength = 0; - } - - /** - * @brief Remove the oldest value from the buffer and return it. - * If the buffer is empty, `-1` is returned. - */ - ValueType pop() override - { - if (this->mLength == 0) { - return -1; - } - ValueType result = this->mBuffer[0]; - for (size_t i = 1; i < this->mLength; i++) { - this->mBuffer[i - 1] = this->mBuffer[i]; - } - this->mLength -= 1; - return result; - } - - /** - * @brief Get the value at the given index. - * - * @example `get(0)` is the oldest value, `get(this.getLength() - 1)` is the newest value - */ - ValueType get(size_t index) const override - { - if (index < 0 || index >= this->mLength) { - return -1; - } - return this->mBuffer[index]; - } - - ValueType* getData() - { - return this->mBuffer.data(); - } - - size_t getLength() const override - { - return this->mLength; - } - - private: - std::array mBuffer; - size_t mLength = 0; -}; -} // namespace SenseShift diff --git a/test/test_util_buffer/main.cpp b/test/test_util_buffer/main.cpp deleted file mode 100644 index f1e2bf8a..00000000 --- a/test/test_util_buffer/main.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include - -#include - -using namespace SenseShift; - -void test_ring_buffer(void) -{ - auto buffer = RingBuffer(); - - TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - - buffer.push('a'); // [] => [a] - TEST_ASSERT_EQUAL_UINT8(1, buffer.getLength()); - TEST_ASSERT_EQUAL_INT8('a', buffer.get(0)); - TEST_ASSERT_EQUAL_UINT8(-1, buffer.get(1)); - TEST_ASSERT_EQUAL_UINT8(-1, buffer.get(2)); - - // pop value and check length - TEST_ASSERT_EQUAL_INT8('a', buffer.pop()); // [a] => [] - TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - - // add 5 values and check length - buffer.push('a'); // [] => [a] - buffer.push('b'); // [a] => [a, b] - buffer.push('c'); // [a, b] => [a, b, c] - buffer.push('d'); // [a, b, c] => [a, b, c, d] - buffer.push('e'); // [a, b, c, d] => [a, b, c, d, e] - TEST_ASSERT_EQUAL_UINT8(5, buffer.getLength()); - - // check values - TEST_ASSERT_EQUAL_INT8('a', buffer.get(0)); - TEST_ASSERT_EQUAL_INT8('b', buffer.get(1)); - TEST_ASSERT_EQUAL_INT8('c', buffer.get(2)); - TEST_ASSERT_EQUAL_INT8('d', buffer.get(3)); - TEST_ASSERT_EQUAL_INT8('e', buffer.get(4)); - - // check values after pop - TEST_ASSERT_EQUAL_INT8('a', buffer.pop()); // [a, b, c, d, e] => [b, c, d, e] - TEST_ASSERT_EQUAL_INT8('b', buffer.pop()); // [b, c, d, e] => [c, d, e] - - TEST_ASSERT_EQUAL_INT8('c', buffer.get(0)); - TEST_ASSERT_EQUAL_INT8('d', buffer.get(1)); - TEST_ASSERT_EQUAL_INT8('e', buffer.get(2)); - - // check clear - buffer.clear(); - TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(0)); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(1)); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(2)); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(3)); - - // check overflow - buffer.push('c'); // [] => [c] - buffer.push('d'); // [c] => [c, d] - buffer.push('e'); // [c, d] => [c, d, e] - buffer.push('f'); // [c, d, e] => [c, d, e, f] - buffer.push('g'); // [c, d, e, f] => [c, d, e, f, g] - buffer.push('h'); // [c, d, e, f, g] => [d, e, f, g, h] - - // Buffer must shift values to the left when it is full - TEST_ASSERT_EQUAL_INT8('d', buffer.get(0)); - TEST_ASSERT_EQUAL_INT8('e', buffer.get(1)); - TEST_ASSERT_EQUAL_INT8('f', buffer.get(2)); - TEST_ASSERT_EQUAL_INT8('g', buffer.get(3)); - TEST_ASSERT_EQUAL_INT8('h', buffer.get(4)); - - // check underflow - TEST_ASSERT_EQUAL_INT8('d', buffer.pop()); // [d, e, f, g, h] => [e, f, g, h] - TEST_ASSERT_EQUAL_INT8('e', buffer.pop()); // [e, f, g, h] => [f, g, h] - TEST_ASSERT_EQUAL_INT8('f', buffer.pop()); // [f, g, h] => [g, h] - TEST_ASSERT_EQUAL_INT8('g', buffer.pop()); // [g, h] => [h] - TEST_ASSERT_EQUAL_INT8('h', buffer.pop()); // [h] => [] -} - -void test_flat_buffer(void) -{ - auto buffer = FixedSizeBuffer(); - - TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - - buffer.push('a'); // [] => [a] - TEST_ASSERT_EQUAL_UINT8(1, buffer.getLength()); - TEST_ASSERT_EQUAL_INT8('a', buffer.get(0)); - TEST_ASSERT_EQUAL_UINT8(-1, buffer.get(1)); - TEST_ASSERT_EQUAL_UINT8(-1, buffer.get(2)); - - // pop value and check length - TEST_ASSERT_EQUAL_INT8('a', buffer.pop()); // [a] => [] - TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - - // add 5 values and check length - buffer.push('a'); // [] => [a] - buffer.push('b'); // [a] => [a, b] - buffer.push('c'); // [a, b] => [a, b, c] - buffer.push('d'); // [a, b, c] => [a, b, c, d] - buffer.push('e'); // [a, b, c, d] => [a, b, c, d, e] - TEST_ASSERT_EQUAL_UINT8(5, buffer.getLength()); - - // check values - TEST_ASSERT_EQUAL_INT8('a', buffer.get(0)); - TEST_ASSERT_EQUAL_INT8('b', buffer.get(1)); - TEST_ASSERT_EQUAL_INT8('c', buffer.get(2)); - TEST_ASSERT_EQUAL_INT8('d', buffer.get(3)); - TEST_ASSERT_EQUAL_INT8('e', buffer.get(4)); - - // check values after pop - TEST_ASSERT_EQUAL_INT8('a', buffer.pop()); // [a, b, c, d, e] => [b, c, d, e] - TEST_ASSERT_EQUAL_INT8('b', buffer.pop()); // [b, c, d, e] => [c, d, e] - - TEST_ASSERT_EQUAL_INT8('c', buffer.get(0)); - TEST_ASSERT_EQUAL_INT8('d', buffer.get(1)); - TEST_ASSERT_EQUAL_INT8('e', buffer.get(2)); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(3)); - - // check clear - buffer.clear(); - TEST_ASSERT_EQUAL_UINT8(0, buffer.getLength()); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(0)); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(1)); - TEST_ASSERT_EQUAL_INT8(-1, buffer.get(2)); - - // check overflow - buffer.push('c'); // [] => [c] - buffer.push('d'); // [c] => [c, d] - buffer.push('e'); // [c, d] => [c, d, e] - buffer.push('f'); // [c, d, e] => [c, d, e, f] - buffer.push('g'); // [c, d, e, f] => [c, d, e, f, g] - buffer.push('h'); // [c, d, e, f, g] => [c, d, e, f, g] - - // Buffer must not change values when it is full - TEST_ASSERT_EQUAL_INT8('c', buffer.get(0)); - TEST_ASSERT_EQUAL_INT8('d', buffer.get(1)); - TEST_ASSERT_EQUAL_INT8('e', buffer.get(2)); - TEST_ASSERT_EQUAL_INT8('f', buffer.get(3)); - TEST_ASSERT_EQUAL_INT8('g', buffer.get(4)); -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_ring_buffer); - RUN_TEST(test_flat_buffer); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include - -void setup(void) -{ - process(); -} - -void loop(void) -{ -} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif From 1e673a024361604f763ecb274b97f00ac0cc2288 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 01:24:23 +0400 Subject: [PATCH 22/67] refactor: remove unused container helpers --- lib/util/senseshift/container.hpp | 42 ---------------- lib/util/senseshift/utility.hpp | 1 - test/test_util_container/main.cpp | 79 ------------------------------- 3 files changed, 122 deletions(-) delete mode 100644 lib/util/senseshift/container.hpp delete mode 100644 test/test_util_container/main.cpp diff --git a/lib/util/senseshift/container.hpp b/lib/util/senseshift/container.hpp deleted file mode 100644 index afd42a2a..00000000 --- a/lib/util/senseshift/container.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace SenseShift { -/** - * Checks if a container contains a value. - * - * @tparam _Cp The type of the container. - * @tparam _Tp The type of the value. - */ -template -inline auto contains(Cp&& c, Tp val) -> bool -{ - return std::find(std::begin(c), std::end(c), val) != std::end(c); -}; - -template<> -inline auto contains(std::string& s, char val) -> bool -{ - return s.find(val) != std::string::npos; -}; - -template -inline auto contains(Tp* begin, Tp* end, const Tp& val) -> bool -{ - return std::find(begin, end, val) != end; -}; - -template -constexpr inline auto contains(const Tp* arr, const std::size_t size, const Tp& val) -> bool -{ - static_assert( - std::is_same_v::value_type>, - "Container and value must be of the same type" - ); - return std::find(arr, arr + size, val) != arr + size; -}; -} // namespace SenseShift diff --git a/lib/util/senseshift/utility.hpp b/lib/util/senseshift/utility.hpp index 595944a9..53a68933 100644 --- a/lib/util/senseshift/utility.hpp +++ b/lib/util/senseshift/utility.hpp @@ -4,5 +4,4 @@ #include #include -#include "senseshift/container.hpp" #include "senseshift/core/helpers.hpp" diff --git a/test/test_util_container/main.cpp b/test/test_util_container/main.cpp deleted file mode 100644 index 98ac6005..00000000 --- a/test/test_util_container/main.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include - -using namespace SenseShift; - -void test_contains_container(void) -{ - std::vector v = { 1, 2, 3, 4, 5 }; - TEST_ASSERT_TRUE(contains(v, 1)); - TEST_ASSERT_TRUE(contains(v, 2)); - TEST_ASSERT_TRUE(contains(v, 3)); - TEST_ASSERT_TRUE(contains(v, 4)); - TEST_ASSERT_TRUE(contains(v, 5)); - TEST_ASSERT_FALSE(contains(v, 6)); -} - -void test_contains_iterator(void) -{ - int arr[] = { 1, 2, 3, 4, 5 }; - TEST_ASSERT_TRUE(contains(arr, arr + 5, 1)); - TEST_ASSERT_TRUE(contains(arr, arr + 5, 2)); - TEST_ASSERT_TRUE(contains(arr, arr + 5, 3)); - TEST_ASSERT_TRUE(contains(arr, arr + 5, 4)); - TEST_ASSERT_TRUE(contains(arr, arr + 5, 5)); - TEST_ASSERT_FALSE(contains(arr, arr + 5, 6)); -} - -void test_contains_string(void) -{ - std::string s = "Hello, World!"; - TEST_ASSERT_TRUE(contains(s, 'H')); - TEST_ASSERT_TRUE(contains(s, 'e')); - TEST_ASSERT_TRUE(contains(s, 'l')); - TEST_ASSERT_TRUE(contains(s, 'o')); - TEST_ASSERT_TRUE(contains(s, ',')); - TEST_ASSERT_TRUE(contains(s, ' ')); - TEST_ASSERT_TRUE(contains(s, 'W')); - TEST_ASSERT_TRUE(contains(s, 'r')); - TEST_ASSERT_TRUE(contains(s, 'd')); - TEST_ASSERT_TRUE(contains(s, '!')); - TEST_ASSERT_FALSE(contains(s, 'h')); - TEST_ASSERT_FALSE(contains(s, 'w')); - TEST_ASSERT_FALSE(contains(s, 'x')); - TEST_ASSERT_FALSE(contains(s, 'y')); - TEST_ASSERT_FALSE(contains(s, 'z')); -} - -int process(void) -{ - UNITY_BEGIN(); - - RUN_TEST(test_contains_container); - RUN_TEST(test_contains_iterator); - RUN_TEST(test_contains_string); - - return UNITY_END(); -} - -#ifdef ARDUINO - -#include - -void setup(void) -{ - process(); -} - -void loop(void) -{ -} - -#else - -int main(int argc, char** argv) -{ - return process(); -} - -#endif From efe64f0ce66a1e43b5ddb7c4146a8245ce74fcc2 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 01:30:03 +0400 Subject: [PATCH 23/67] chore: remove irrelevant example --- .editorconfig | 2 +- examples/float_benchmark/float_benchmark.ino | 129 ------------------- 2 files changed, 1 insertion(+), 130 deletions(-) delete mode 100644 examples/float_benchmark/float_benchmark.ino diff --git a/.editorconfig b/.editorconfig index 56f567d8..2eef2bc9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -18,7 +18,7 @@ indent_size = 4 max_line_length = 80 [*.{c++,cc,cpp,cxx,h,h++,hh,hpp,hxx,inl,ipp,tlh,tli}] -indent_size = 4 +indent_size = 2 cpp_indent_case_contents_when_block = true cpp_new_line_before_open_brace_namespace = same_line diff --git a/examples/float_benchmark/float_benchmark.ino b/examples/float_benchmark/float_benchmark.ino deleted file mode 100644 index 99a7da2e..00000000 --- a/examples/float_benchmark/float_benchmark.ino +++ /dev/null @@ -1,129 +0,0 @@ -#include - -#ifdef ESP32 -#include -#else -#include -#endif - -#include - -#define TIMES_TO_LOOP 1000000 - -/** by Vlad Kaipetsky -portable assuming FP24 set to nearest rounding mode -efficient on x86 platform -*/ -inline int toInt(float fval) -{ - static const float Snapper = 3 << 22; - - union UFloatInt { - int i; - float f; - }; - - assert(fabs(fval) <= 0x003fffff); // only 23 bit values handled - UFloatInt& fi = *(UFloatInt*) &fval; - fi.f += Snapper; - return ((fi.i) & 0x007fffff) - 0x00400000; -} - -inline auto ifloor_toInt(float x) -> int -{ - const auto casted = toInt(x); - return casted - (x < casted); -} - -inline int i_cast(float value) -{ - return static_cast(value); -} - -inline auto ifloor_cast(float x) -> int -{ - const auto casted = i_cast(x); - return casted - (x < casted); -} - -inline int ifloor_std_cast(float x) -{ - return static_cast(std::floor(x)); -} - -volatile int xi, yi, resulti; -volatile float xf, yf, resultf; - -uint32_t seed32() -{ - return random(0, 0xffffffff); -} - -float seedfloat() -{ - // float x, y; - - // x = seed32(); - // y = seed32(); - - // return x / y; - return 4094.8492342342932034F; -} - -void setup() -{ - Serial.begin(115200); - Serial.println("Preparing system..."); - - // Turn WiFi off for consistency - WiFi.mode(WIFI_OFF); - - delay(1000); - Serial.println("Starting benchmark"); - - uint32_t i; - uint64_t micros_start, micros_end; - - xf = seedfloat(); - yf = seedfloat(); - - micros_start = micros(); - for (i = 0; i < TIMES_TO_LOOP; i++) - resulti = i_cast(xf); - micros_end = micros(); - Serial.printf("i_cast(%f) => %i\t\tmicros: ", xf, resulti); - Serial.println(micros_end - micros_start); - - micros_start = micros(); - for (i = 0; i < TIMES_TO_LOOP; i++) - resulti = ifloor_cast(xf); - micros_end = micros(); - Serial.printf("ifloor_cast(%f) => %i\tmicros: ", xf, resulti); - Serial.println(micros_end - micros_start); - - micros_start = micros(); - for (i = 0; i < TIMES_TO_LOOP; i++) - resulti = ifloor_std_cast(xf); - micros_end = micros(); - Serial.printf("ifloor_std_cast(%f) => %i\tmicros: ", xf, resulti); - Serial.println(micros_end - micros_start); - - micros_start = micros(); - for (i = 0; i < TIMES_TO_LOOP; i++) - resulti = toInt(xf); - micros_end = micros(); - Serial.printf("toInt(%f) => %i\t\tmicros: ", xf, resulti); - Serial.println(micros_end - micros_start); - - micros_start = micros(); - for (i = 0; i < TIMES_TO_LOOP; i++) - resulti = ifloor_toInt(xf); - micros_end = micros(); - Serial.printf("ifloor_toInt(%f) => %i\tmicros: ", xf, resulti); - Serial.println(micros_end - micros_start); -} - -void loop() -{ - // put your main code here, to run repeatedly: -} From 291c428206df360b061eac099e87e141ddb574ab Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 01:43:25 +0400 Subject: [PATCH 24/67] chore: update `.editorconfig` --- .editorconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 2eef2bc9..556813a8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ end_of_line = lf insert_final_newline = true # Tab indentation (no size specified) -[Makefile] +[{Makefile,*.mk}] indent_style = tab [CMakeLists.txt] @@ -19,6 +19,7 @@ max_line_length = 80 [*.{c++,cc,cpp,cxx,h,h++,hh,hpp,hxx,inl,ipp,tlh,tli}] indent_size = 2 +indent_style = space cpp_indent_case_contents_when_block = true cpp_new_line_before_open_brace_namespace = same_line From 24a37807104539ce8b373cf1948778cb409a9afb Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 02:38:20 +0400 Subject: [PATCH 25/67] refactor: remove unused Adafruit dependencies --- lib/arduino/library.json | 5 ---- .../arduino/input/sensor/ina219.hpp | 28 ------------------- 2 files changed, 33 deletions(-) delete mode 100644 lib/arduino/senseshift/arduino/input/sensor/ina219.hpp diff --git a/lib/arduino/library.json b/lib/arduino/library.json index 844417f9..27ccde88 100644 --- a/lib/arduino/library.json +++ b/lib/arduino/library.json @@ -3,11 +3,6 @@ "frameworks": "arduino", "platforms": "*", "dependencies": { - "adafruit/Adafruit BusIO": "^1.14.1", - "adafruit/Adafruit Unified Sensor": "^1.1.4", - "adafruit/Adafruit PWM Servo Driver Library": "^2.4.0", - "adafruit/Adafruit INA219": "^1.2.1", - "sparkfun/SparkFun MAX1704x Fuel Gauge Arduino Library": "^1.0.4", "madhephaestus/ESP32Servo": "^3.0.0" } } diff --git a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp b/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp deleted file mode 100644 index 4efa7570..00000000 --- a/lib/arduino/senseshift/arduino/input/sensor/ina219.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include - -#include - -#include - -namespace SenseShift::Arduino::Input { -/// INA219 Current sensor -/// TODO: refactor to component, that updates the value in multiple sensors (ESPHome style) -class INA219CurrentSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { - Adafruit_INA219 ina219_; - - public: - void init() override - { - if (!ina219_.success()) { - log_e("Failed to find INA219 sensor"); - } - } - - [[nodiscard]] inline auto getValue() -> float override - { - return ina219_.getCurrent_mA(); - } -}; -} // namespace SenseShift::Arduino::Input From 62f7399c32b8b9b72f0dd5497359b901941699bc Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 02:48:53 +0400 Subject: [PATCH 26/67] refactor(PCA9685): use own I2CDevLibContrib --- .../bhaptics/tactsuit_x16_pca9685.cpp | 17 +++++---- .../mode_configs/bhaptics/tactsuit_x40.cpp | 20 +++++++---- .../senseshift/arduino/output/pca9685.hpp | 34 ------------------ lib/i2cdevlib-contrib-derive/library.json | 8 +++++ .../senseshift/output/i2cdevlib_pwm.hpp | 35 +++++++++++++++++++ platformio.ini | 1 + 6 files changed, 68 insertions(+), 47 deletions(-) delete mode 100644 lib/arduino/senseshift/arduino/output/pca9685.hpp create mode 100644 lib/i2cdevlib-contrib-derive/library.json create mode 100644 lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 576a7501..d6907776 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -4,20 +4,23 @@ #include #include +#include +#include + #include #include -#include #include #include #include #include #include +#include using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; -using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; @@ -34,10 +37,12 @@ static const std::array layoutG void setupMode() { - // Configure the PCA9685 - auto* pwm = new Adafruit_PWMServoDriver(0x40); - pwm->begin(); - pwm->setPWMFreq(PWM_FREQUENCY); + Wire.begin(); + + // Configure the PCA9685s + auto pwm = i2cdev::PCA9685(0x40, I2CDev); + pwm.setFrequency(PWM_FREQUENCY); + pwm.wakeup(); // Assign the pins on the configured PCA9685 to positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index a85a610a..71fc166b 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -4,21 +4,25 @@ #include #include +#include +#include + #include #include #include -#include #include #include #include #include #include +#include using namespace SenseShift; using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; using namespace SenseShift::Arduino::Output; +using namespace SenseShift::Output; using namespace SenseShift::Arduino::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; @@ -32,14 +36,16 @@ static const std::array bhLayout = { B void setupMode() { + Wire.begin(); + // Configure the PCA9685s - auto* pwm0 = new Adafruit_PWMServoDriver(0x40); - pwm0->begin(); - pwm0->setPWMFreq(PWM_FREQUENCY); + auto pwm0 = i2cdev::PCA9685(0x40, I2CDev); + pwm0.setFrequency(PWM_FREQUENCY); + pwm0.wakeup(); - auto* pwm1 = new Adafruit_PWMServoDriver(0x41); - pwm1->begin(); - pwm1->setPWMFreq(PWM_FREQUENCY); + auto pwm1 = i2cdev::PCA9685(0x41, I2CDev); + pwm1.setFrequency(PWM_FREQUENCY); + pwm1.wakeup(); // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest diff --git a/lib/arduino/senseshift/arduino/output/pca9685.hpp b/lib/arduino/senseshift/arduino/output/pca9685.hpp deleted file mode 100644 index 730c4698..00000000 --- a/lib/arduino/senseshift/arduino/output/pca9685.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include -#include -#include - -namespace SenseShift::Arduino::Output { -class PCA9685Output : public ::SenseShift::Output::IFloatOutput { - public: - static inline constexpr std::uint16_t MAX_INTENSITY = 4095; - - PCA9685Output(Adafruit_PWMServoDriver* driver, const std::uint8_t num) : driver_(driver), channel_(num){}; - - void init() override - { - this->driver_->begin(); - } - - void writeState(const ValueType value) override - { - const auto duty = static_cast(value * MAX_INTENSITY); - this->driver_->setPin(this->channel_, duty); - } - - private: - Adafruit_PWMServoDriver* driver_; - std::uint8_t channel_; -}; -} // namespace SenseShift::Arduino::Output diff --git a/lib/i2cdevlib-contrib-derive/library.json b/lib/i2cdevlib-contrib-derive/library.json new file mode 100644 index 00000000..98e1dc6b --- /dev/null +++ b/lib/i2cdevlib-contrib-derive/library.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/schema/library.json", + "frameworks": "arduino", + "platforms": "*", + "dependencies": { + "I2CDevLibContrib": "*" + } +} diff --git a/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp b/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp new file mode 100644 index 00000000..6ee6b9d3 --- /dev/null +++ b/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include +#include + +#include +#include + +namespace SenseShift::Output { + +template +class I2CDevLibContribPWMOutput : public ::SenseShift::Output::IFloatOutput { + public: + I2CDevLibContribPWMOutput(T& driver, const std::uint8_t num) : driver_(driver), channel_(num){}; + + void init() override + { + // + } + + void writeState(const ValueType value) override + { + const auto duty = static_cast(value * MAX_INTENSITY); + this->driver_.setChannel(this->channel_, duty); + } + + private: + T& driver_; + std::uint8_t channel_; +}; + +using PCA9685Output = I2CDevLibContribPWMOutput; +} // namespace SenseShift::Output diff --git a/platformio.ini b/platformio.ini index 928b7714..df040834 100644 --- a/platformio.ini +++ b/platformio.ini @@ -38,6 +38,7 @@ build_src_filter = lib_deps = https://github.com/senseshift/frozen.git#feature/platformio + https://github.com/senseshift/i2cdevlib-contrib.git#master https://github.com/senseshift/arduino-ble-serial.git#v1.1.2 https://github.com/senseshift/opengloves-lib.git#master From 69d280be530b799ca1ee6bb86a9bd13d14914257 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 03:01:47 +0400 Subject: [PATCH 27/67] chore(deps): pin I2CDevLibContrib to exact hash --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index df040834..34933d71 100644 --- a/platformio.ini +++ b/platformio.ini @@ -38,7 +38,7 @@ build_src_filter = lib_deps = https://github.com/senseshift/frozen.git#feature/platformio - https://github.com/senseshift/i2cdevlib-contrib.git#master + https://github.com/senseshift/i2cdevlib-contrib.git#3ac7669f544587c2db4847dbc7841b456fe66008 https://github.com/senseshift/arduino-ble-serial.git#v1.1.2 https://github.com/senseshift/opengloves-lib.git#master From 082fb6f97d647994ff90287299393ce3b9a42270 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 12:11:33 +0400 Subject: [PATCH 28/67] chore: log I2C errors --- .../bhaptics/tactsuit_x16_pca9685.cpp | 8 ++++++-- firmware/mode_configs/bhaptics/tactsuit_x40.cpp | 16 ++++++++++++---- .../senseshift/output/i2cdevlib_pwm.hpp | 4 +++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index d6907776..3c2656bb 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -41,8 +41,12 @@ void setupMode() // Configure the PCA9685s auto pwm = i2cdev::PCA9685(0x40, I2CDev); - pwm.setFrequency(PWM_FREQUENCY); - pwm.wakeup(); + if (pwm.setFrequency(PWM_FREQUENCY) != I2CDEV_RESULT_OK) { + LOG_E("pca9685", "Failed to set frequency"); + } + if (pwm.wakeup() != I2CDEV_RESULT_OK) { + LOG_E("pca9685", "Failed to wake up"); + } // Assign the pins on the configured PCA9685 to positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 71fc166b..e1ec207f 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -40,12 +40,20 @@ void setupMode() // Configure the PCA9685s auto pwm0 = i2cdev::PCA9685(0x40, I2CDev); - pwm0.setFrequency(PWM_FREQUENCY); - pwm0.wakeup(); + if (pwm0.setFrequency(PWM_FREQUENCY) != I2CDEV_RESULT_OK) { + LOG_E("pca9685", "Failed to set frequency"); + } + if (pwm0.wakeup() != I2CDEV_RESULT_OK) { + LOG_E("pca9685", "Failed to wake up"); + } auto pwm1 = i2cdev::PCA9685(0x41, I2CDev); - pwm1.setFrequency(PWM_FREQUENCY); - pwm1.wakeup(); + if (pwm1.setFrequency(PWM_FREQUENCY) != I2CDEV_RESULT_OK) { + LOG_E("pca9685", "Failed to set frequency"); + } + if (pwm1.wakeup() != I2CDEV_RESULT_OK) { + LOG_E("pca9685", "Failed to wake up"); + } // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest diff --git a/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp b/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp index 6ee6b9d3..70b11ce4 100644 --- a/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp +++ b/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp @@ -23,7 +23,9 @@ class I2CDevLibContribPWMOutput : public ::SenseShift::Output::IFloatOutput { void writeState(const ValueType value) override { const auto duty = static_cast(value * MAX_INTENSITY); - this->driver_.setChannel(this->channel_, duty); + if (this->driver_.setChannel(this->channel_, duty) != I2CDEV_RESULT_OK) { + LOG_E("i2cdev::pwm", "Failed to set channel %d to %d", this->channel_, duty); + } } private: From cc3bf179afd6a64ee6ab6b89abea23dd1eed455b Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 16:05:07 +0400 Subject: [PATCH 29/67] feat(Battery): add MAX170xx support --- .../mode_configs/bhaptics/tactsuit_x40.cpp | 14 ++++++++ .../senseshift/input/max170xx.hpp | 34 +++++++++++++++++++ platformio.ini | 2 +- 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 lib/i2cdevlib-contrib-derive/senseshift/input/max170xx.hpp diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index e1ec207f..5bb119ed 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -117,6 +117,20 @@ void setupMode() app->postEvent(new BatteryLevelEvent(value)); }); batterySensor->init(); + +// i2cdev::MAX17048 gauge = i2cdev::MAX17048(MAX1704X_I2CADDR_BASE, I2CDev); +// if (gauge.check() != I2CDEV_RESULT_OK) { +// LOG_E("MAX17048", "Failed to initialize"); +// } +// if (gauge.quickStart() != I2CDEV_RESULT_OK) { +// LOG_E("MAX17048", "Failed to quick start"); +// } +// +// IBatterySensor* batterySensor = new SimpleSensorDecorator(new MAX170XXBatterySensor(gauge)); +// batterySensor->addValueCallback([](BatteryState value) -> void { +// app->postEvent(new BatteryLevelEvent(value)); +// }); +// batterySensor->init(); #endif } diff --git a/lib/i2cdevlib-contrib-derive/senseshift/input/max170xx.hpp b/lib/i2cdevlib-contrib-derive/senseshift/input/max170xx.hpp new file mode 100644 index 00000000..d3ebd13f --- /dev/null +++ b/lib/i2cdevlib-contrib-derive/senseshift/input/max170xx.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include + +namespace SenseShift::Battery::Input { +/// MAX170xx battery sensor +template +class MAX170XXBatterySensor : public ::SenseShift::Input::ISimpleSensor { + public: + MAX170XXBatterySensor(MAX170XX& driver) : ISimpleSensor(), driver_(driver) + { + } + + void init() override + { + if (this->driver_.check() != I2CDEV_RESULT_OK) { + LOG_E("battery.sensor", "Failed to initialize MAX170xx"); + return; + } + } + + BatteryState getValue() override + { + return { + .level = static_cast(this->driver_.readSoc() * BatteryState::MAX_LEVEL), + }; + } + + private: + MAX170XX& driver_; +}; +} // namespace SenseShift::Battery::Input diff --git a/platformio.ini b/platformio.ini index 34933d71..5af316fe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -38,7 +38,7 @@ build_src_filter = lib_deps = https://github.com/senseshift/frozen.git#feature/platformio - https://github.com/senseshift/i2cdevlib-contrib.git#3ac7669f544587c2db4847dbc7841b456fe66008 + https://github.com/senseshift/i2cdevlib-contrib.git#8db7eab29dd01385928c6a99938ed0a953a5acf3 https://github.com/senseshift/arduino-ble-serial.git#v1.1.2 https://github.com/senseshift/opengloves-lib.git#master From 9849339d1b40fd754c3a2e012acc64d958b26150 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 28 Jul 2024 16:15:26 +0400 Subject: [PATCH 30/67] docs(Readme): mention I2CDevLibContrib --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index ea5db7b0..ace6d3eb 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,11 @@ Please note that documentation is still a work in progress. | TLC59108F | 🚧 | 8 | | LP50xx | 🚧 | 9 _or_ 12 | +> **Note** +> Most of supported PWM drivers are provided by +> the [I2CDevLibContrib](https://github.com/senseshift/i2cdevlib-contrib) +> library + ### Battery controllers | Board | Status | @@ -66,6 +71,11 @@ Please note that documentation is still a work in progress. | MCP3021 | 🚧 | | STUSB4500 | 🚧 | +> **Note** +> Most of supported battery controllers are provided by +> the [I2CDevLibContrib](https://github.com/senseshift/i2cdevlib-contrib) +> library + ## Supported Protocols | Protocol | Status | From d4b786d96d252915cd5d26b44b519d8dfd8735c7 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 30 Jul 2024 21:51:39 +0400 Subject: [PATCH 31/67] ci(GitHub): run Semgrep SAST --- .../{codeql-analysis.yml => sast.yml} | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) rename .github/workflows/{codeql-analysis.yml => sast.yml} (83%) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/sast.yml similarity index 83% rename from .github/workflows/codeql-analysis.yml rename to .github/workflows/sast.yml index 9263ccb3..d00b9573 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/sast.yml @@ -1,4 +1,4 @@ -name: "CodeQL" +name: "SAST" on: push: @@ -18,8 +18,8 @@ concurrency: cancel-in-progress: true jobs: - analyze: - name: Analyze + codeql-analyze: + name: CodeQL Analyze runs-on: ubuntu-latest permissions: actions: read @@ -119,3 +119,29 @@ jobs: uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" + + semgrep: + name: semgrep/ci + runs-on: ubuntu-latest + + container: + image: semgrep/semgrep + + # Skip any PR created by dependabot to avoid permission issues: + if: (github.actor != 'dependabot[bot]') + + steps: + - uses: actions/checkout@v4 + + - run: semgrep ci --sarif > semgrep.sarif + env: + # Connect to Semgrep AppSec Platform through your SEMGREP_APP_TOKEN. + # Generate a token from Semgrep AppSec Platform > Settings + # and add it to your GitHub secrets. + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + + - name: Upload SARIF file for GitHub Advanced Security Dashboard + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: semgrep.sarif + if: always() From 2715fed271e2779918b281287fbc6c1a24ed323e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 30 Jul 2024 22:52:09 +0400 Subject: [PATCH 32/67] style: remove extra semicolons --- include/senseshift.h | 2 +- .../senseshift/arduino/input/sensor/analog.hpp | 2 +- .../senseshift/arduino/input/sensor/digital.hpp | 6 ++++-- lib/arduino/senseshift/arduino/output/servo.hpp | 4 +++- lib/arduino_esp32/senseshift/arduino/output/ledc.hpp | 2 +- lib/battery/senseshift/battery/battery.hpp | 4 +++- lib/bhaptics_ble/senseshift/bh/ble/connection.cpp | 12 ++++++------ lib/bhaptics_ble/senseshift/bh/ble/connection.hpp | 8 ++++---- lib/freertos/senseshift/freertos/task.hpp | 10 +++++----- lib/haptics/senseshift/body/haptics/interface.hpp | 2 +- .../senseshift/output/i2cdevlib_pwm.hpp | 4 +++- lib/io/senseshift/input/filter.hpp | 8 ++++++-- lib/math/senseshift/math/point2.hpp | 12 +++++++++--- .../senseshift/opengloves/opengloves_component.hpp | 4 +++- .../senseshift/opengloves/opengloves_plotter.hpp | 4 +++- .../senseshift/opengloves/transport/stream.hpp | 12 +++++++++--- test/test_io_sensor/main.cpp | 10 +++++----- 17 files changed, 67 insertions(+), 39 deletions(-) diff --git a/include/senseshift.h b/include/senseshift.h index 1b792373..fda7b0fc 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -16,7 +16,7 @@ class Application final : public IEventDispatcher { [[nodiscard]] auto getVibroBody() const -> Body::Haptics::FloatBody* { return this->vibro_body_; - }; + } void postEvent(const IEvent* event) override; void addEventListener(const IEventListener* listener) override; diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 9e5c8903..0a6d681c 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -31,7 +31,7 @@ class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { void init() override { pinMode(this->pin_, INPUT); - }; + } [[nodiscard]] inline auto getValue() -> float override { diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index c9d8e992..d64f952c 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -12,12 +12,14 @@ class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { explicit DigitalSimpleSensor( const std::uint8_t pin, const std::uint8_t mode = INPUT_PULLUP, const std::uint8_t inverted = LOW ) : - pin_(pin), mode_(mode), inverted_(inverted){}; + pin_(pin), mode_(mode), inverted_(inverted) + { + } void init() override { pinMode(this->pin_, this->mode_); - }; + } [[nodiscard]] auto getValue() -> bool override { diff --git a/lib/arduino/senseshift/arduino/output/servo.hpp b/lib/arduino/senseshift/arduino/output/servo.hpp index 1fa4b554..da487ccd 100644 --- a/lib/arduino/senseshift/arduino/output/servo.hpp +++ b/lib/arduino/senseshift/arduino/output/servo.hpp @@ -14,7 +14,9 @@ namespace SenseShift::Arduino::Output { class ServoOutput : public ::SenseShift::Output::IFloatOutput { public: - ServoOutput(size_t pin) : pin_(pin){}; + ServoOutput(size_t pin) : pin_(pin) + { + } void init() override { diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp index e74b84c1..ecef37a8 100644 --- a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -51,7 +51,7 @@ class LedcOutput : public ::SenseShift::Output::IFloatOutput { const auto duty = static_cast(value * this->getMaxValue()); LOG_V(TAG, "GPIO %d - Writing %d to Channel %d", this->pin_, duty, this->channel_); ledcWrite(this->pin_, duty); - }; + } private: std::uint8_t pin_; diff --git a/lib/battery/senseshift/battery/battery.hpp b/lib/battery/senseshift/battery/battery.hpp index a697f8c4..07061f10 100644 --- a/lib/battery/senseshift/battery/battery.hpp +++ b/lib/battery/senseshift/battery/battery.hpp @@ -30,6 +30,8 @@ struct BatteryState { class BatteryLevelEvent : public IEvent { public: const BatteryState& state; - BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state){}; + BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state) + { + } }; } // namespace SenseShift::Battery diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp index cf765d43..c2b15476 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.cpp @@ -57,7 +57,7 @@ class LogOutputCharCallbacks : public BLECharacteristicCallbacks { pCharacteristic->getValue().c_str(), pCharacteristic->getValue().length() ); - }; + } void onRead(BLECharacteristic* pCharacteristic) override { @@ -67,7 +67,7 @@ class LogOutputCharCallbacks : public BLECharacteristicCallbacks { pCharacteristic->getValue().c_str(), pCharacteristic->getValue().length() ); - }; + } void onNotify(BLECharacteristic* pCharacteristic) override { @@ -77,7 +77,7 @@ class LogOutputCharCallbacks : public BLECharacteristicCallbacks { pCharacteristic->getValue().c_str(), pCharacteristic->getValue().length() ); - }; + } #if defined(SS_USE_NIMBLE) && SS_USE_NIMBLE == true void onStatus(BLECharacteristic* pCharacteristic, Status s, int code) override @@ -93,7 +93,7 @@ class LogOutputCharCallbacks : public BLECharacteristicCallbacks { pCharacteristic->getValue().c_str(), pCharacteristic->getValue().length() ); - }; + } }; class MotorCharCallbacks : public BLECharacteristicCallbacks { @@ -111,7 +111,7 @@ class MotorCharCallbacks : public BLECharacteristicCallbacks { std::string valueStr(value.begin(), value.end()); this->motorTransformer(valueStr); - }; + } }; class ConfigCharCallbacks : public BLECharacteristicCallbacks { @@ -126,7 +126,7 @@ class ConfigCharCallbacks : public BLECharacteristicCallbacks { auto byte_0 = value[0], byte_1 = value[1], byte_2 = value[2]; log_d(">>\tonWrite (Config Char): %3hhu %2hhu %2hhu", byte_0, byte_1, byte_2); - }; + } }; void Connection::begin() diff --git a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp index f6d1999b..e87422b3 100644 --- a/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp +++ b/lib/bhaptics_ble/senseshift/bh/ble/connection.hpp @@ -34,7 +34,7 @@ class ConnectionCallbacks { virtual void postInit() { log_v("Default postInit"); - }; + } }; static ConnectionCallbacks defaultCallback; @@ -46,7 +46,7 @@ class Connection final : public IEventListener { config(config), motorHandler(motorHandler), eventDispatcher(eventDispatcher) { this->eventDispatcher->addEventListener(this); - }; + } void begin(void); void handleEvent(const IEvent* event) const override @@ -63,7 +63,7 @@ class Connection final : public IEventListener { return; } - }; + } void setCallbacks(ConnectionCallbacks* pCallbacks) { @@ -72,7 +72,7 @@ class Connection final : public IEventListener { } else { this->callbacks = &defaultCallback; } - }; + } private: const ConnectionConfig& config; diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 52179c4a..904eff4c 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -47,18 +47,18 @@ class Task { explicit Task(TaskConfig& config) : taskConfig(config) { log_i("creating ComponentUpdateTask: %s", taskConfig.name); - }; + } virtual ~Task() { if (taskHandle) { vTaskDelete(taskHandle); } - }; + } TaskHandle_t getHandle() const { return taskHandle; - }; + } virtual void begin() { @@ -77,7 +77,7 @@ class Task { if (!taskHandle) { log_e("Failed to create task %s", this->taskConfig.name); } - }; + } protected: inline void monitorTask() @@ -130,7 +130,7 @@ class ComponentUpdateTask : public Task> { Task(taskConfig), component_(component), updateDelay_(updateDelay) { log_i("creating ComponentUpdateTask: %s", taskConfig.name); - }; + } void begin() override { diff --git a/lib/haptics/senseshift/body/haptics/interface.hpp b/lib/haptics/senseshift/body/haptics/interface.hpp index b6f50b52..11cff2d0 100644 --- a/lib/haptics/senseshift/body/haptics/interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -71,7 +71,7 @@ class VibroEffectData { [[nodiscard]] constexpr inline auto getIntensity() const -> Intensity { return intensity_; - }; + } private: Intensity intensity_ = 0; diff --git a/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp b/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp index 70b11ce4..51f89f8e 100644 --- a/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp +++ b/lib/i2cdevlib-contrib-derive/senseshift/output/i2cdevlib_pwm.hpp @@ -13,7 +13,9 @@ namespace SenseShift::Output { template class I2CDevLibContribPWMOutput : public ::SenseShift::Output::IFloatOutput { public: - I2CDevLibContribPWMOutput(T& driver, const std::uint8_t num) : driver_(driver), channel_(num){}; + I2CDevLibContribPWMOutput(T& driver, const std::uint8_t num) : driver_(driver), channel_(num) + { + } void init() override { diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 951f9b16..da0220c0 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -51,7 +51,9 @@ class IFiltered { template class AddFilter : public IFilter { public: - explicit AddFilter(Tp offset) : offset_(offset){}; + explicit AddFilter(Tp offset) : offset_(offset) + { + } auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override { @@ -65,7 +67,9 @@ class AddFilter : public IFilter { template class SubtractFilter : public IFilter { public: - explicit SubtractFilter(Tp offset) : offset_(offset){}; + explicit SubtractFilter(Tp offset) : offset_(offset) + { + } auto filter(ISimpleSensor* /*sensor*/, Tp value) -> Tp override { diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index 967edc4b..f714a6c0 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -17,9 +17,15 @@ struct Point2 { Tp x, y; - constexpr Point2() : x(static_cast(0)), y(static_cast(0)){}; - constexpr Point2(Tp x, Tp y) : x(x), y(y){}; - constexpr Point2(const Point2& v) : x((Tp) v.x), y((Tp) v.y){}; + constexpr Point2() : x(static_cast(0)), y(static_cast(0)) + { + } + constexpr Point2(Tp x, Tp y) : x(x), y(y) + { + } + constexpr Point2(const Point2& v) : x((Tp) v.x), y((Tp) v.y) + { + } constexpr inline auto operator==(const Point2& rhs) const -> bool { diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index bcb77e13..cf1e84cd 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -133,7 +133,9 @@ class OpenGlovesForceFeedbackComponent : public SenseShift::Component { OpenGlovesForceFeedbackComponent( OutputWriters& output_writers, ::SenseShift::OpenGloves::ITransport* communication ) : - output_writers_(output_writers), communication_(communication){}; + output_writers_(output_writers), communication_(communication) + { + } void init() override { diff --git a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp index 9c113f25..4d44f480 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/opengloves_plotter.hpp @@ -7,7 +7,9 @@ namespace SenseShift::OpenGloves { class Plotter { public: - Plotter(Print* output, char* prefix) : output_(output), prefix_(prefix){}; + Plotter(Print* output, char* prefix) : output_(output), prefix_(prefix) + { + } void plot(const og::InputPeripheralData data) { diff --git a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp index 51f3ec61..1ca45526 100644 --- a/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp +++ b/lib/opengloves_arduino/senseshift/opengloves/transport/stream.hpp @@ -17,7 +17,9 @@ class IStreamTransport : public ITransport { std::array buffer_{}; public: - IStreamTransport(Stream* channel) : channel(channel){}; + IStreamTransport(Stream* channel) : channel(channel) + { + } auto send(const char* buffer, size_t length) -> size_t override { @@ -53,8 +55,12 @@ class IStreamTransport : public ITransport { class StreamTransport : public IStreamTransport { public: - explicit StreamTransport(Stream& channel) : IStreamTransport(&channel){}; - explicit StreamTransport(Stream* channel) : IStreamTransport(channel){}; + explicit StreamTransport(Stream& channel) : IStreamTransport(&channel) + { + } + explicit StreamTransport(Stream* channel) : IStreamTransport(channel) + { + } void init() override { diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index a93a536f..a17a0b18 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -12,12 +12,12 @@ class TestAnalogCountingSensor : public ISimpleSensor { void init() override { this->setupCounter++; - }; + } auto getValue() -> int override { return ++this->count; - }; + } }; class TestAnalogSensor : public ISimpleSensor { @@ -79,15 +79,15 @@ class DummyCalibrator : public ::SenseShift::Input::Calibration::ICalibratorresetCounter++; this->calibrated = 0.0f; - }; + } void update(float input) override { this->calibrated = input; - }; + } float calibrate(float input) const override { return calibrated; - }; + } }; void test_calibrated_sensor(void) From 6d842d3edf89f9ac19a8eb6ec159094ea20dce41 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Tue, 30 Jul 2024 23:26:53 +0400 Subject: [PATCH 33/67] ci(GitHub): add flawfinder --- .github/workflows/sast.yml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index d00b9573..19d5ae34 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -121,7 +121,7 @@ jobs: category: "/language:${{matrix.language}}" semgrep: - name: semgrep/ci + name: Semgrep runs-on: ubuntu-latest container: @@ -145,3 +145,25 @@ jobs: with: sarif_file: semgrep.sarif if: always() + + flawfinder: + runs-on: ubuntu-latest + strategy: + matrix: + directory: + - 'firmware' + - 'include' + - 'lib' + steps: + - uses: actions/checkout@v4 + + - uses: david-a-wheeler/flawfinder@2.0.19 + with: + arguments: '--sarif ${{ matrix.directory }}' + output: 'flawfinder_results.sarif' + + - name: Upload SARIF file for GitHub Advanced Security Dashboard + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: flawfinder_results.sarif + if: always() From ccfde5752d5ee46c6d0b15e2d253717136a96928 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 23 Feb 2024 11:09:13 +0400 Subject: [PATCH 34/67] feat: upgrade xtensa-esp32 toolchain --- ini/bhaptics.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index 7bcd9daf..a5de6b7f 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -1,6 +1,7 @@ [bhaptics] platform = platformio/espressif32@^6.7.0 platform_packages = + toolchain-xtensa-esp32@12.2.0+20230208 framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip framework = arduino From 161e6f3fd8daa2d12a420dd01d08fe2f256dae13 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 23 Feb 2024 11:33:00 +0400 Subject: [PATCH 35/67] refactor(bHaptics): deduct battery templates --- firmware/mode_configs/bhaptics/tactal.cpp | 5 +---- firmware/mode_configs/bhaptics/tactglove.cpp | 5 +---- firmware/mode_configs/bhaptics/tactosy2.cpp | 5 +---- firmware/mode_configs/bhaptics/tactosyf.cpp | 5 +---- firmware/mode_configs/bhaptics/tactosyh.cpp | 5 +---- firmware/mode_configs/bhaptics/tactsuit_x16.cpp | 5 +---- firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp | 5 +---- firmware/mode_configs/bhaptics/tactsuit_x40.cpp | 5 +---- firmware/mode_configs/bhaptics/tactvisor.cpp | 5 +---- 9 files changed, 9 insertions(+), 36 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index ae5f4970..a300daaf 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -68,10 +68,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index d1397408..8d6da8c7 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -76,10 +76,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index f4310b9b..fab4aa0c 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -69,10 +69,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index c41334a0..da9f1433 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -70,10 +70,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 900b9a23..2449ffe6 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -70,10 +70,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 3f8913b1..71b46973 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -79,10 +79,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index 3c2656bb..b5c9faa3 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -93,10 +93,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 5bb119ed..ee537d42 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -109,10 +109,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index a6bf5ef7..c012d3e6 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -68,10 +68,7 @@ void setupMode() ); batteryTask->begin(); - auto* batterySensor = new LookupTableInterpolateBatterySensor>( - batteryVoltageSensor, - &VoltageMap::LiPO_1S_42 - ); + auto* batterySensor = new LookupTableInterpolateBatterySensor(batteryVoltageSensor, &VoltageMap::LiPO_1S_42); batterySensor->addValueCallback([](BatteryState value) -> void { app->postEvent(new BatteryLevelEvent(value)); }); From 227108e650fad4ea9e8fbdc770e26cbff0514d89 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 23 Feb 2024 11:40:57 +0400 Subject: [PATCH 36/67] feat(bHaptics): deduct update task template --- firmware/mode_configs/bhaptics/tactal.cpp | 2 +- firmware/mode_configs/bhaptics/tactglove.cpp | 2 +- firmware/mode_configs/bhaptics/tactosy2.cpp | 2 +- firmware/mode_configs/bhaptics/tactosyf.cpp | 2 +- firmware/mode_configs/bhaptics/tactosyh.cpp | 2 +- firmware/mode_configs/bhaptics/tactsuit_x16.cpp | 2 +- firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp | 2 +- firmware/mode_configs/bhaptics/tactsuit_x40.cpp | 2 +- firmware/mode_configs/bhaptics/tactvisor.cpp | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/firmware/mode_configs/bhaptics/tactal.cpp index a300daaf..affade5e 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/firmware/mode_configs/bhaptics/tactal.cpp @@ -61,7 +61,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/firmware/mode_configs/bhaptics/tactglove.cpp index 8d6da8c7..6f48863b 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/firmware/mode_configs/bhaptics/tactglove.cpp @@ -69,7 +69,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/firmware/mode_configs/bhaptics/tactosy2.cpp index fab4aa0c..90945d98 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/firmware/mode_configs/bhaptics/tactosy2.cpp @@ -62,7 +62,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/firmware/mode_configs/bhaptics/tactosyf.cpp index da9f1433..3e6eab0d 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/firmware/mode_configs/bhaptics/tactosyf.cpp @@ -63,7 +63,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/firmware/mode_configs/bhaptics/tactosyh.cpp index 2449ffe6..5919df49 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/firmware/mode_configs/bhaptics/tactosyh.cpp @@ -63,7 +63,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp index 71b46973..91b1e20b 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16.cpp @@ -72,7 +72,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp index b5c9faa3..601e4f27 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp @@ -86,7 +86,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index ee537d42..511de089 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -102,7 +102,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/firmware/mode_configs/bhaptics/tactvisor.cpp index c012d3e6..ac662907 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/firmware/mode_configs/bhaptics/tactvisor.cpp @@ -61,7 +61,7 @@ void setupMode() new MultiplyFilter(3.3F), // Convert to raw pin voltage new VoltageDividerFilter(27000.0F, 100000.0F), // Convert to voltage divider voltage }); - auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask>( + auto* batteryTask = new ::SenseShift::FreeRTOS::ComponentUpdateTask( batteryVoltageSensor, SS_BATTERY_SAMPLE_RATE, { "ADC Battery", 4096, SS_BATTERY_TASK_PRIORITY, tskNO_AFFINITY } From b8e0f3b7e0f2c5db985d15151b488efa52cdf8da Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 1 Aug 2024 16:08:07 +0400 Subject: [PATCH 37/67] chore: upgrade `framework-arduinoespressif32` Closes #134 --- ini/bhaptics.ini | 8 ++++---- ini/opengloves.ini | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini index a5de6b7f..dc2683a2 100644 --- a/ini/bhaptics.ini +++ b/ini/bhaptics.ini @@ -1,9 +1,9 @@ [bhaptics] -platform = platformio/espressif32@^6.7.0 +platform = platformio/espressif32@^6.8.1 platform_packages = - toolchain-xtensa-esp32@12.2.0+20230208 - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 - framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip + toolchain-xtensa-esp32@12.2.0+20230208 + framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 + framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip framework = arduino board = esp32doit-devkit-v1 upload_speed = 921600 diff --git a/ini/opengloves.ini b/ini/opengloves.ini index bd89da7e..7606d671 100644 --- a/ini/opengloves.ini +++ b/ini/opengloves.ini @@ -1,8 +1,9 @@ [opengloves] -platform = platformio/espressif32@^6.7.0 +platform = platformio/espressif32@^6.8.1 platform_packages = - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.2 - framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.2/esp32-arduino-libs-3.0.2.zip + toolchain-xtensa-esp32@12.2.0+20230208 + framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 + framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip framework = arduino board = esp32doit-devkit-v1 upload_speed = 921600 From 32cc34a996125e5719dc82b447689d4ac7108b29 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 1 Aug 2024 19:21:04 +0400 Subject: [PATCH 38/67] ci(GitHub): upload memory usage artifact --- .github/workflows/ci.yml | 161 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 150 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffcdcac1..28aba569 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -139,11 +139,53 @@ jobs: sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini - name: Build + shell: bash run: | echo "::group::platformio.ini" cat platformio.ini echo "::endgroup::" - pio run --environment ${{matrix.target}} + pio ${{ matrix.coverage && 'debug' || 'run' }} --environment ${{matrix.target}} | tee build.log + + - name: Collect memory usage + id: memory_usage + if: matrix.coverage == false + run: | + echo "USAGE_FILENAME=${{ env.USAGE_FILENAME }}" >> $GITHUB_ENV + + # RAM: [= ] 11.8% (used 38636 bytes from 327680 bytes) + # Flash: [========= ] 90.1% (used 1181501 bytes from 1310720 bytes) + + # Extract the line containing RAM usage + ram_line=$(grep 'RAM:' build.log) + # Extract the line containing Flash usage + flash_line=$(grep 'Flash:' build.log) + + # Parse the RAM usage details + ram_percentage=$(echo $ram_line | grep -oP '\d+\.\d+(?=%)') + ram_used=$(echo $ram_line | grep -oP '(?<=used )\d+') + ram_total=$(echo $ram_line | grep -oP '(?<=from )\d+') + + # Parse the Flash usage details + flash_percentage=$(echo $flash_line | grep -oP '\d+\.\d+(?=%)') + flash_used=$(echo $flash_line | grep -oP '(?<=used )\d+') + flash_total=$(echo $flash_line | grep -oP '(?<=from )\d+') + + # Store as JSON to file usage.json + echo "{\"ram\": {\"percentage\": $ram_percentage, \"used\": $ram_used, \"total\": $ram_total}, \"flash\": {\"percentage\": $flash_percentage, \"used\": $flash_used, \"total\": $flash_total}}" > ${{ env.USAGE_FILENAME }} + + # Print the content of usage.json + cat ${{ env.USAGE_FILENAME }} + env: + USAGE_FILENAME: ${{ steps.firmware_name.outputs.firmware }}-usage.json + + - name: Upload usage.json artifact + if: matrix.coverage == false + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.firmware_name.outputs.firmware }}-usage + path: ${{ env.USAGE_FILENAME }} + retention-days: 1 + if-no-files-found: error - name: Collect initial coverage if: matrix.coverage @@ -279,19 +321,53 @@ jobs: sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini - name: Build - if: matrix.coverage == false + shell: bash run: | echo "::group::platformio.ini" cat platformio.ini echo "::endgroup::" - pio run --environment ${{matrix.target}} - - name: Build (debug) - if: matrix.coverage + pio ${{ matrix.coverage && 'debug' || 'run' }} --environment ${{matrix.target}} | tee build.log + + - name: Collect memory usage + id: memory_usage + if: matrix.coverage == false run: | - echo "::group::platformio.ini" - cat platformio.ini - echo "::endgroup::" - pio debug --environment ${{matrix.target}} + echo "USAGE_FILENAME=${{ env.USAGE_FILENAME }}" >> $GITHUB_ENV + + # RAM: [= ] 11.8% (used 38636 bytes from 327680 bytes) + # Flash: [========= ] 90.1% (used 1181501 bytes from 1310720 bytes) + + # Extract the line containing RAM usage + ram_line=$(grep 'RAM:' build.log) + # Extract the line containing Flash usage + flash_line=$(grep 'Flash:' build.log) + + # Parse the RAM usage details + ram_percentage=$(echo $ram_line | grep -oP '\d+\.\d+(?=%)') + ram_used=$(echo $ram_line | grep -oP '(?<=used )\d+') + ram_total=$(echo $ram_line | grep -oP '(?<=from )\d+') + + # Parse the Flash usage details + flash_percentage=$(echo $flash_line | grep -oP '\d+\.\d+(?=%)') + flash_used=$(echo $flash_line | grep -oP '(?<=used )\d+') + flash_total=$(echo $flash_line | grep -oP '(?<=from )\d+') + + # Store as JSON to file usage.json + echo "{\"ram\": {\"percentage\": $ram_percentage, \"used\": $ram_used, \"total\": $ram_total}, \"flash\": {\"percentage\": $flash_percentage, \"used\": $flash_used, \"total\": $flash_total}}" > ${{ env.USAGE_FILENAME }} + + # Print the content of usage.json + cat ${{ env.USAGE_FILENAME }} + env: + USAGE_FILENAME: ${{ steps.firmware_name.outputs.firmware }}-usage.json + + - name: Upload usage.json artifact + if: matrix.coverage == false + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.firmware_name.outputs.firmware }}-usage + path: ${{ env.USAGE_FILENAME }} + retention-days: 1 + if-no-files-found: error - name: Upload firmware Artifact if: matrix.coverage == false @@ -387,7 +463,7 @@ jobs: path: ./build/lcov/lcov.info.${{matrix.target}}.test retention-days: 5 - coverage-report: + report-coverage: needs: - build-bhaptics - build-opengloves @@ -416,7 +492,7 @@ jobs: find ./build/lcov -name 'lcov.info.*' -exec echo -a {} \; | xargs lcov -o ./build/lcov/lcov.info lcov --remove ./build/lcov/lcov.info '/usr/include/*' '*.platformio/*' '*/.pio/*' '*/tool-unity/*' '*/test/*' '*/MockArduino/*' '*/lib/frozen/*' -o ./build/lcov/lcov.info.cleaned - + # delete all except the cleaned file find ./build/lcov -type f -not -name 'lcov.info.cleaned' -delete @@ -440,6 +516,69 @@ jobs: files: ./build/lcov/lcov.info.cleaned flags: unittests + report-memory-usage: + needs: + - build-bhaptics + - build-opengloves + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download all workflow run artifacts + id: download + uses: actions/download-artifact@v4 + with: + path: current-usage + pattern: '*-usage' + merge-multiple: true + + - run: ls -lahR current-usage + + - name: Merge usage files + shell: python + run: | + import os + import json + + # Directory containing the JSON files + directory = "current-usage" + + # Initialize an empty dictionary to store the merged content + merged_data = {} + + # Iterate over all files in the directory + for filename in os.listdir(directory): + if filename.endswith(".json"): + # Extract the filename without the extension + key = os.path.splitext(filename)[0] + + # Construct the full path to the file + filepath = os.path.join(directory, filename) + + # Read the content of the file + with open(filepath, 'r') as file: + content = json.load(file) + + # Add the content to the merged dictionary + merged_data[key] = content + + # Specify the output file + output_file = os.path.join(directory, "merged.json") + + # Write the merged content to the output file + with open(output_file, 'w') as file: + json.dump(merged_data, file, indent=4) + + print(f"Merged JSON file has been created at: {output_file}") + + + + - name: Upload merged usage.json artifact + uses: actions/upload-artifact@v4 + with: + name: merged-usage + path: current-usage/merged.json + wokwi: needs: - build-bhaptics From 8b0ae1314e1bd96028eb2fd92cc509dbe9d3ec16 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 1 Aug 2024 15:45:38 +0400 Subject: [PATCH 39/67] perf(Input): reduce vtable usage, lessen coupling --- lib/io/senseshift/input/calibration.hpp | 53 ++++++++++- lib/io/senseshift/input/filter.hpp | 61 +++++++++++- lib/io/senseshift/input/sensor/sensor.hpp | 95 ++----------------- .../senseshift/opengloves/opengloves.hpp | 13 +-- .../opengloves/opengloves_component.hpp | 2 +- 5 files changed, 117 insertions(+), 107 deletions(-) diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index c680d3df..e763a113 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -8,11 +8,6 @@ #include namespace SenseShift::Input::Calibration { -struct ICalibrated { - virtual void startCalibration() = 0; - virtual void stopCalibration() = 0; - virtual void reselCalibration() = 0; -}; template struct ICalibrator { @@ -26,6 +21,54 @@ struct ICalibrator { [[nodiscard]] virtual auto calibrate(Tp input) const -> Tp = 0; }; +template +class Calibrated { + public: + using ValueType = Tp; + using CalibratorType = ICalibrator; + + inline void setCalibrator(CalibratorType* calibrator) + { + this->calibrator_ = calibrator; + } + + inline auto getCalibrator() -> CalibratorType* + { + return this->calibrator_; + } + + inline void clearCalibrator() + { + this->calibrator_ = nullptr; + } + + inline void startCalibration() + { + this->is_calibrating_ = true; + } + + inline void stopCalibration() + { + this->is_calibrating_ = false; + } + + inline void resetCalibration() + { + if (this->calibrator_ != nullptr) { + this->calibrator_->reset(); + } + } + + inline bool isCalibrating() const + { + return this->is_calibrating_; + } + + private: + CalibratorType* calibrator_; + bool is_calibrating_ = false; +}; + template class MinMaxCalibrator : public ICalibrator { static_assert(std::is_arithmetic_v, "MinMaxCalibrator only can be used with arithmetic types"); diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index da0220c0..06823fc4 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -35,17 +35,68 @@ class IFilter { }; template -class IFiltered { +class Filtered { public: using ValueType = Tp; + using FilterType = IFilter*; - virtual void addFilter(IFilter* filter) = 0; + auto getFilters() -> std::vector& + { + return this->filters_; + } - virtual void addFilters(std::vector*> filters) = 0; + /// Appends a filter to the sensor's filter chain. + /// + /// \param filter The filter to add. + /// + /// \see addFilters for adding multiple filters. + void addFilter(FilterType filter) + { + this->filters_.push_back(filter); + } - virtual void setFilters(std::vector*> filters) = 0; + /// Adds multiple filters to the sensor's filter chain. Appends to the end of the chain. + /// + /// \param filters The chain of filters to add. + /// + /// \example + /// \code + /// sensor->addFilters({ + /// new MinMaxFilter(0.1f, 0.9f), + /// new CenterDeadzoneFilter(0.1f), + /// }); + /// \endcode + /// + /// todo(leon0399): use SFINAE + void addFilters(std::vector filters) + { + this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); + } + + /// Replaces the sensor's filter chain with the given filters. + /// + /// \param filters New filter chain. + /// + /// \example + /// \code + /// sensor->setFilters({ + /// new MinMaxFilter(0.1f, 0.9f), + /// new CenterDeadzoneFilter(0.1f), + /// }); + /// \endcode + void setFilters(std::vector filters) + { + this->filters_ = filters; + } + + /// Removes everything from the sensor's filter chain. + void clearFilters() + { + this->filters_.clear(); + } - void clearFilters() = 0; + protected: + std::vector filters_ = {}; }; template diff --git a/lib/io/senseshift/input/sensor/sensor.hpp b/lib/io/senseshift/input/sensor/sensor.hpp index e03eb3b4..3cf36ace 100644 --- a/lib/io/senseshift/input/sensor/sensor.hpp +++ b/lib/io/senseshift/input/sensor/sensor.hpp @@ -34,7 +34,7 @@ using IBinarySimpleSensor = ISimpleSensor; using IFloatSimpleSensor = ISimpleSensor; template -class ISensor : public virtual ISimpleSensor, public Calibration::ICalibrated {}; +class ISensor : public virtual ISimpleSensor, public Calibration::Calibrated, public Filter::Filtered {}; template class Sensor : public ISensor, public Component { @@ -51,81 +51,6 @@ class Sensor : public ISensor, public Component { this->value_ = this->applyFilters(value); } - /// Appends a filter to the sensor's filter chain. - /// - /// \param filter The filter to add. - /// - /// \see addFilters for adding multiple filters. - void addFilter(Filter::IFilter* filter) - { - this->filters_.push_back(filter); - } - - /// Adds multiple filters to the sensor's filter chain. Appends to the end of the chain. - /// - /// \param filters The chain of filters to add. - /// - /// \example - /// \code - /// sensor->addFilters({ - /// new MinMaxFilter(0.1f, 0.9f), - /// new CenterDeadzoneFilter(0.1f), - /// }); - /// \endcode - void addFilters(std::vector*> filters) - { - this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); - } - - /// Replaces the sensor's filter chain with the given filters. - /// - /// \param filters New filter chain. - /// - /// \example - /// \code - /// sensor->setFilters({ - /// new MinMaxFilter(0.1f, 0.9f), - /// new CenterDeadzoneFilter(0.1f), - /// }); - /// \endcode - void setFilters(std::vector*> filters) - { - this->filters_ = filters; - } - - /// Removes everything from the sensor's filter chain. - void clearFilters() - { - this->filters_.clear(); - } - - void setCalibrator(Calibration::ICalibrator* calibrator) - { - this->calibrator_ = calibrator; - } - - void clearCalibrator() - { - this->calibrator_ = std::nullopt; - } - - void startCalibration() override - { - this->is_calibrating_ = true; - } - - void stopCalibration() override - { - this->is_calibrating_ = false; - } - - void reselCalibration() override - { - if (this->calibrator_.has_value()) { - this->calibrator_.value()->reset(); - } - } - void addValueCallback(CallbackType&& callback) { this->callbacks_.add(std::move(callback)); @@ -173,16 +98,16 @@ class Sensor : public ISensor, public Component { [[nodiscard]] auto applyFilters(ValueType value) -> ValueType { /// Apply calibration - if (this->calibrator_.has_value()) { - if (this->is_calibrating_) { - this->calibrator_.value()->update(value); + if (this->getCalibrator() != nullptr) { + if (this->isCalibrating()) { + this->getCalibrator()->update(value); } - value = this->calibrator_.value()->calibrate(value); + value = this->getCalibrator()->calibrate(value); } /// Apply filters - for (auto filter : this->filters_) { + for (auto filter : this->getFilters()) { value = filter->filter(nullptr, value); } @@ -193,12 +118,6 @@ class Sensor : public ISensor, public Component { friend class Filter::IFilter; friend class Calibration::ICalibrator; - /// The sensor's filter chain. - std::vector*> filters_ = std::vector*>(); - - bool is_calibrating_ = false; - std::optional*> calibrator_ = std::nullopt; - ValueType raw_value_; ValueType value_; @@ -219,7 +138,7 @@ class SimpleSensorDecorator : public Sensor { using ValueType = Tp; using SourceType = ISimpleSensor; - explicit SimpleSensorDecorator(SourceType* source) : source_(source) + explicit SimpleSensorDecorator(SourceType* source) : source_(source), Sensor() { } diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 2244f7c6..b13754ed 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -74,10 +74,7 @@ class ITransport : public IInitializable { using FloatSensor = ::SenseShift::Input::FloatSensor; using BinarySensor = ::SenseShift::Input::BinarySensor; -class InputSensors : - public og::InputPeripheral, - public Component, - public ::SenseShift::Input::Calibration::ICalibrated { +class InputSensors : public og::InputPeripheral, public Component { public: void init() override { @@ -147,21 +144,21 @@ class InputSensors : SS_OG_COLLECT_DATA(getRawValue); } - void reselCalibration() override + void resetCalibration() { for (const auto& calibrated_input : this->calibrated_inputs_) { - calibrated_input->reselCalibration(); + calibrated_input->resetCalibration(); } } - void startCalibration() override + void startCalibration() { for (const auto& calibrated_input : this->calibrated_inputs_) { calibrated_input->startCalibration(); } } - void stopCalibration() override + void stopCalibration() { for (const auto& calibrated_input : this->calibrated_inputs_) { calibrated_input->stopCalibration(); diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index cf1e84cd..b18d01b1 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -105,7 +105,7 @@ class OpenGlovesTrackingComponent : public SenseShift::Component { void startCalibration() { log_i("Starting calibration"); - this->input_sensors_.reselCalibration(); + this->input_sensors_.resetCalibration(); this->input_sensors_.startCalibration(); this->calibration_start_time_ = millis(); } From a02db2d5861d7cab02b8f25c65522b5f5bf818f5 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 1 Aug 2024 17:16:51 +0400 Subject: [PATCH 40/67] fix(tests): add missing functions for some architectures --- test/test_battery/main.cpp | 10 ++++++++++ test/test_bhaptics_encoding/main.cpp | 10 ++++++++++ test/test_body_gestures/main.cpp | 10 ++++++++++ test/test_core_helpers/main.cpp | 10 ++++++++++ test/test_haptics_body/main.cpp | 10 ++++++++++ test/test_haptics_plane/main.cpp | 10 ++++++++++ test/test_io_calibration/main.cpp | 10 ++++++++++ test/test_io_filter/main.cpp | 10 ++++++++++ test/test_io_sensor/main.cpp | 10 ++++++++++ test/test_math_point2/main.cpp | 10 ++++++++++ 10 files changed, 100 insertions(+) diff --git a/test/test_battery/main.cpp b/test/test_battery/main.cpp index 5316c228..9c7bd7b5 100644 --- a/test/test_battery/main.cpp +++ b/test/test_battery/main.cpp @@ -6,6 +6,16 @@ using namespace SenseShift::Input; using namespace SenseShift::Battery; using namespace SenseShift::Battery::Input; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + void test_battery_sensor(void) { auto* source = new FloatSensor(); diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index 70b34e79..d3b4533d 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -6,6 +6,16 @@ using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; using namespace SenseShift::Output; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + class TestActuator : public IOutput { public: bool isSetup = false; diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index 6bcb0335..c25462c3 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -5,6 +5,16 @@ using namespace SenseShift::Input; using namespace SenseShift::Body::Hands::Input; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + void test_gesture_trigger(void) { float threshold = 0.5f; diff --git a/test/test_core_helpers/main.cpp b/test/test_core_helpers/main.cpp index 24c5b771..5d529448 100644 --- a/test/test_core_helpers/main.cpp +++ b/test/test_core_helpers/main.cpp @@ -6,6 +6,16 @@ using namespace SenseShift; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + void test_lerp_uint8(void) { TEST_ASSERT_EQUAL_UINT16(0, lerp(0.0f, 0, 255)); diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 364dbc72..5554db13 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -4,6 +4,16 @@ using namespace SenseShift::Body::Haptics; using namespace SenseShift::Output; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + class TestActuator : public IOutput { public: bool isSetup = false; diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index 6e45a75f..ab0af8ff 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -4,6 +4,16 @@ using namespace SenseShift::Body::Haptics; using namespace SenseShift::Output; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + class TestActuator : public IOutput { public: bool isSetup = false; diff --git a/test/test_io_calibration/main.cpp b/test/test_io_calibration/main.cpp index a0dc6f6b..9f8e1ba7 100644 --- a/test/test_io_calibration/main.cpp +++ b/test/test_io_calibration/main.cpp @@ -3,6 +3,16 @@ using namespace SenseShift::Input::Calibration; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + void test_minmax_calibrator(void) { const auto calibrator = new MinMaxCalibrator(); diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp index cf562048..493d8b19 100644 --- a/test/test_io_filter/main.cpp +++ b/test/test_io_filter/main.cpp @@ -13,6 +13,16 @@ using namespace SenseShift::Input; using namespace SenseShift::Input::Filter; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + void test_add_filter(void) { IFilter* filter = new AddFilter(5.0f); diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index a17a0b18..9f5b7122 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -4,6 +4,16 @@ using namespace SenseShift::Input; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + class TestAnalogCountingSensor : public ISimpleSensor { public: int count = 0; diff --git a/test/test_math_point2/main.cpp b/test/test_math_point2/main.cpp index 1ac4a254..f021530a 100644 --- a/test/test_math_point2/main.cpp +++ b/test/test_math_point2/main.cpp @@ -3,6 +3,16 @@ using namespace SenseShift::Math; +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // clean stuff up here +} + void test_operator_equal(void) { Point2 p1 = { 1, 2 }; From 22c634e124e6b11a0fdc3f8b9763fc7cf2d99b9c Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 2 Aug 2024 12:00:37 +0400 Subject: [PATCH 41/67] ci(GitHub): compare memory usage --- .github/scripts/compare-memory-usage.py | 87 +++++++++++++++++++++++++ .github/workflows/ci.yml | 74 +++++++++++++++++++-- .idea/misc.xml | 5 +- .idea/senseshift-firmware.iml | 8 ++- 4 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 .github/scripts/compare-memory-usage.py diff --git a/.github/scripts/compare-memory-usage.py b/.github/scripts/compare-memory-usage.py new file mode 100644 index 00000000..512f726d --- /dev/null +++ b/.github/scripts/compare-memory-usage.py @@ -0,0 +1,87 @@ +import json +import pandas as pd +import argparse + + +# Function to load JSON data from files +def load_json(filename): + with open(filename, 'r') as f: + return json.load(f) + + +# Function to compare values and create formatted strings +def compare_values(base, current, key): + if key not in base and key not in current: + return None + if key not in base: + return f"🆕 {current[key]}" + if key not in current: + return f"❌" + + base_value = base[key] + current_value = current[key] + + if base_value == current_value: + return f"🆗 {base_value}" + + change = current_value - base_value + sign = "+" if change > 0 else "-" + symbol = "⚠️" if change > 0 else "⬇️" + + # round to 2 decimal places + change = round(abs(change), 2) + return f"{symbol} {current_value} {sign}{change}" + + +# Function to generate Markdown table +def generate_markdown_table(base_data, current_data): + table_data = [] + + all_keys = set(base_data.keys()).union(set(current_data.keys())) + all_keys = sorted(all_keys) + + for key in all_keys: + base_ram = base_data.get(key, {}).get("ram", {}) + current_ram = current_data.get(key, {}).get("ram", {}) + + base_flash = base_data.get(key, {}).get("flash", {}) + current_flash = current_data.get(key, {}).get("flash", {}) + + row = [ + key.replace("-usage", ""), + compare_values(base_ram, current_ram, "percentage"), + compare_values(base_ram, current_ram, "used"), + compare_values(base_flash, current_flash, "percentage"), + compare_values(base_flash, current_flash, "used") + ] + table_data.append(row) + + df = pd.DataFrame(table_data, columns=["Variant", "RAM, %", "RAM, bytes", "Flash, %", "Flash, bytes"]) + + return df.to_markdown(index=False) + + +# Main function to handle CLI arguments and execute the script +def main(): + parser = argparse.ArgumentParser(description='Compare JSON files and generate a markdown table.') + parser.add_argument('base', type=str, help='Path to the base JSON file') + parser.add_argument('current', type=str, help='Path to the current JSON file') + parser.add_argument('--output', type=str, help='Path to the output markdown file') + args = parser.parse_args() + + base_data = load_json(args.base) + current_data = load_json(args.current) + + markdown_table = generate_markdown_table(base_data, current_data) + + if args.output: + with open(args.output, 'w') as f: + f.write(markdown_table) + print(f"Markdown table generated and saved to {args.output}") + else: + print(markdown_table) + + +# usage: python compare-memory-usage.py base.json current.json --output table.md +if __name__ == "__main__": + main() diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28aba569..8fdb0839 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,11 +49,11 @@ jobs: coverage: true battery_flag: SS_BATTERY_ENABLED=true nimble_flag: SS_USE_NIMBLE=true - # - target: bhaptics_tactsuit_x40 - # os: ubuntu-latest - # coverage: true - # battery_flag: SS_BATTERY_ENABLED=true - # nimble_flag: SS_USE_NIMBLE=false + - target: bhaptics_tactsuit_x40 + os: ubuntu-latest + coverage: true + battery_flag: SS_BATTERY_ENABLED=true + nimble_flag: SS_USE_NIMBLE=false - target: bhaptics_tactsuit_x40 os: ubuntu-latest coverage: false @@ -532,8 +532,6 @@ jobs: pattern: '*-usage' merge-multiple: true - - run: ls -lahR current-usage - - name: Merge usage files shell: python run: | @@ -579,6 +577,68 @@ jobs: name: merged-usage path: current-usage/merged.json + - name: Get base branch job ID + if: github.event_name == 'pull_request' + id: base_branch_workflow + uses: actions/github-script@v7 + with: + script: | + const { data: workflows } = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + branch: context.payload.pull_request.base.ref, + event: 'push', + workflow_id: 'ci.yml', + status: 'completed', + per_page: 1 + }); + + const baseBranchJobId = workflows.workflow_runs[0].id; + console.log(baseBranchJobId); + + return baseBranchJobId; + + + - name: Download base branch usage.json artifact + if: github.event_name == 'pull_request' + id: download-base-usage + uses: actions/download-artifact@v4 + with: + name: merged-usage + path: base-usage + github-token: ${{ secrets.GITHUB_TOKEN }} + repository: ${{ github.repository }} + run-id: ${{ steps.base_branch_workflow.outputs.result }} + + - uses: actions/setup-python@v2 + if: github.event_name == 'pull_request' + with: + python-version: '3.x' + + - name: Report memory usage table + if: github.event_name == 'pull_request' + shell: bash + run: | + python -m pip install --upgrade pip pandas tabulate + + cat ./base-usage/merged.json + cat ./current-usage/merged.json + + echo "## Memory Usage Comparison" > memory-usage-comparison.md + echo "" >> memory-usage-comparison.md + echo "
" >> memory-usage-comparison.md + echo " Click to expand" >> memory-usage-comparison.md + echo "" >> memory-usage-comparison.md + python ./.github/scripts/compare-memory-usage.py ./base-usage/merged.json ./current-usage/merged.json | tee -a memory-usage-comparison.md + echo "
" >> memory-usage-comparison.md + + cat ./memory-usage-comparison.md > $GITHUB_STEP_SUMMARY + + - uses: thollander/actions-comment-pull-request@v2 + if: github.event_name == 'pull_request' + with: + filePath: memory-usage-comparison.md + comment_tag: memory-usage-comparison wokwi: needs: - build-bhaptics diff --git a/.idea/misc.xml b/.idea/misc.xml index d858eb18..abbace02 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,5 +1,8 @@ + + - \ No newline at end of file + diff --git a/.idea/senseshift-firmware.iml b/.idea/senseshift-firmware.iml index d986c559..7b655970 100644 --- a/.idea/senseshift-firmware.iml +++ b/.idea/senseshift-firmware.iml @@ -1,2 +1,8 @@ - \ No newline at end of file + + + + + + + From 4851aea8247b84d4fcf30027034ad4f57374b6c4 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 2 Aug 2024 19:44:40 +0400 Subject: [PATCH 42/67] refactor(Input): change sensor.h dir --- lib/arduino/senseshift/arduino/input/sensor/analog.hpp | 2 +- lib/arduino/senseshift/arduino/input/sensor/digital.hpp | 2 +- lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp | 2 +- lib/battery/senseshift/battery/input/battery_sensor.hpp | 2 +- lib/hands_input/senseshift/body/hands/input/gesture.hpp | 2 +- lib/hands_input/senseshift/body/hands/input/total_curl.hpp | 2 +- lib/io/senseshift/input/{sensor => }/sensor.hpp | 4 ++-- lib/io/senseshift/input/sensor/analog_threshold.hpp | 2 +- lib/opengloves/senseshift/opengloves/autoconfig.hpp | 2 +- lib/opengloves/senseshift/opengloves/opengloves.hpp | 2 +- test/test_battery/main.cpp | 2 +- test/test_body_gestures/main.cpp | 2 +- test/test_io_filter/main.cpp | 2 +- test/test_io_sensor/main.cpp | 2 +- 14 files changed, 15 insertions(+), 15 deletions(-) rename lib/io/senseshift/input/{sensor => }/sensor.hpp (98%) diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 0a6d681c..5838df3d 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index d64f952c..dd8e75b2 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -4,7 +4,7 @@ #include -#include +#include namespace SenseShift::Arduino::Input { class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { diff --git a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp index a0de2b34..eb3c13b3 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp @@ -11,7 +11,7 @@ #include "senseshift/arduino/input/sensor/digital.hpp" #include -#include +#include namespace SenseShift::Arduino::Input { template diff --git a/lib/battery/senseshift/battery/input/battery_sensor.hpp b/lib/battery/senseshift/battery/input/battery_sensor.hpp index ac71d513..d1aa71a8 100644 --- a/lib/battery/senseshift/battery/input/battery_sensor.hpp +++ b/lib/battery/senseshift/battery/input/battery_sensor.hpp @@ -5,7 +5,7 @@ #include "senseshift/battery/battery.hpp" #include -#include +#include namespace SenseShift::Battery::Input { /// Abstract battery sensor diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp index a9454864..8ce198d4 100644 --- a/lib/hands_input/senseshift/body/hands/input/gesture.hpp +++ b/lib/hands_input/senseshift/body/hands/input/gesture.hpp @@ -1,8 +1,8 @@ #pragma once #include +#include #include -#include namespace SenseShift::Body::Hands::Input { using Gesture = ::SenseShift::Input::BinarySensor; diff --git a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp index 8e7e64eb..f1f9bce2 100644 --- a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -5,7 +5,7 @@ #include #include -#include +#include namespace SenseShift::Body::Hands::Input { class TotalCurl : public ::SenseShift::Input::FloatSensor { diff --git a/lib/io/senseshift/input/sensor/sensor.hpp b/lib/io/senseshift/input/sensor.hpp similarity index 98% rename from lib/io/senseshift/input/sensor/sensor.hpp rename to lib/io/senseshift/input/sensor.hpp index 3cf36ace..68455080 100644 --- a/lib/io/senseshift/input/sensor/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -7,8 +7,8 @@ #include "senseshift/input/calibration.hpp" #include "senseshift/input/filter.hpp" -#include -#include +#include "senseshift/core/component.hpp" +#include "senseshift/core/helpers.hpp" #define SS_SUBSENSOR_INIT(SENSOR, ATTACH_CALLBACK, CALLBACK) \ (SENSOR)->init(); \ diff --git a/lib/io/senseshift/input/sensor/analog_threshold.hpp b/lib/io/senseshift/input/sensor/analog_threshold.hpp index 11e4df6e..280f0a46 100644 --- a/lib/io/senseshift/input/sensor/analog_threshold.hpp +++ b/lib/io/senseshift/input/sensor/analog_threshold.hpp @@ -1,6 +1,6 @@ #pragma once -#include "senseshift/input/sensor/sensor.hpp" +#include "senseshift/input/sensor.hpp" #include namespace SenseShift::Input { diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 6e46b720..ddae8059 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index b13754ed..b5bc67a9 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #define SS_OG_COLLECT_DATA(FN) \ diff --git a/test/test_battery/main.cpp b/test/test_battery/main.cpp index 9c7bd7b5..f8950acf 100644 --- a/test/test_battery/main.cpp +++ b/test/test_battery/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include using namespace SenseShift::Input; diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index c25462c3..bbae8332 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include using namespace SenseShift::Input; diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp index 493d8b19..94ad4ce2 100644 --- a/test/test_io_filter/main.cpp +++ b/test/test_io_filter/main.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index 9f5b7122..910d8073 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -1,5 +1,5 @@ +#include #include -#include #include using namespace SenseShift::Input; From c4c3b59210a88d5c058a8a81d21f8527e50f1ffc Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 3 Aug 2024 00:34:13 +0400 Subject: [PATCH 43/67] refactor(bHaptics): use initializer list for map --- .../mode_configs/bhaptics/tactsuit_x40.cpp | 18 ++++----- lib/haptics/senseshift/body/haptics/plane.hpp | 38 +++++++++++++------ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp index 511de089..89aaff3b 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/firmware/mode_configs/bhaptics/tactsuit_x40.cpp @@ -57,26 +57,24 @@ void setupMode() // Assign the pins on the configured PCA9685s and PWM pins to locations on the // vest - auto frontOutputs = PlaneMapper_Margin:: - mapMatrixCoordinates, 5>>({ { - // clang-format off + auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + // clang-format off { new PCA9685Output(pwm0, 0), new PCA9685Output(pwm0, 1), new PCA9685Output(pwm0, 2), new PCA9685Output(pwm0, 3) }, { new PCA9685Output(pwm0, 4), new PCA9685Output(pwm0, 5), new PCA9685Output(pwm0, 6), new PCA9685Output(pwm0, 7) }, { new PCA9685Output(pwm0, 8), new PCA9685Output(pwm0, 9), new PCA9685Output(pwm0, 10), new PCA9685Output(pwm0, 11) }, { new PCA9685Output(pwm0, 12), new PCA9685Output(pwm0, 13), new PCA9685Output(pwm0, 14), new PCA9685Output(pwm0, 15) }, { new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) }, - // clang-format on - } }); - auto backOutputs = PlaneMapper_Margin:: - mapMatrixCoordinates, 5>>({ { - // clang-format off + // clang-format on + }); + auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ + // clang-format off { new PCA9685Output(pwm1, 0), new PCA9685Output(pwm1, 1), new PCA9685Output(pwm1, 2), new PCA9685Output(pwm1, 3) }, { new PCA9685Output(pwm1, 4), new PCA9685Output(pwm1, 5), new PCA9685Output(pwm1, 6), new PCA9685Output(pwm1, 7) }, { new PCA9685Output(pwm1, 8), new PCA9685Output(pwm1, 9), new PCA9685Output(pwm1, 10), new PCA9685Output(pwm1, 11) }, { new PCA9685Output(pwm1, 12), new PCA9685Output(pwm1, 13), new PCA9685Output(pwm1, 14), new PCA9685Output(pwm1, 15) }, { new LedcOutput(27), new LedcOutput(14), new LedcOutput(12), new LedcOutput(13) }, - // clang-format on - } }); + // clang-format on + }); app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index f446c758..1dd8a2c3 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -92,36 +92,52 @@ class PlaneMapper_Margin { /// Maps a 2D matrix into a (coord, object) map. /// /// \tparam Tp - /// \tparam I Input 2D matrix type. - /// \tparam O Output map type. + /// \tparam TContainer Input 2D matrix type. /// /// \param map2d Input 2D matrix. /// /// \return Output map. - template>, typename O = std::map> - static auto mapMatrixCoordinates(I map2d) -> O + template< + typename Tp, + typename TContainer, + typename = std::enable_if_t>> + static auto mapMatrixCoordinates(const TContainer& map2d) -> std::map { - O points{}; + std::map points{}; const size_t y_size = map2d.size(); const size_t y_max = y_size - 1; - for (size_t y = 0; y < y_size; ++y) { - auto row = map2d.at(y); + size_t y = 0; + for (const auto& row : map2d) { const size_t x_size = row.size(); const size_t x_max = x_size - 1; - for (size_t x = 0; x < x_size; ++x) { - Tp wr = row.at(x); + size_t x = 0; + for (const auto& elem : row) { Position coord = mapPoint(x, y, x_max, y_max); - - points[coord] = wr; + points[coord] = elem; + ++x; } + + ++y; } return points; } + template + inline static auto mapMatrixCoordinates(const std::array, Y>& map2d) + { + return mapMatrixCoordinates, Y>>(map2d); + } + + template + inline static auto mapMatrixCoordinates(const std::initializer_list>& map2d) + { + return mapMatrixCoordinates>>(map2d); + } + /// Re-maps a point index to output coordinate. /// \tparam Tp The type of the point index. template From fa1e331f0be2dbb52db7787d19fa6390a6a6f514 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 3 Aug 2024 01:21:42 +0400 Subject: [PATCH 44/67] perf(bHaptics): constexpr map outputs --- lib/haptics/senseshift/body/haptics/plane.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index 1dd8a2c3..40680a25 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -101,7 +101,7 @@ class PlaneMapper_Margin { typename Tp, typename TContainer, typename = std::enable_if_t>> - static auto mapMatrixCoordinates(const TContainer& map2d) -> std::map + static constexpr auto mapMatrixCoordinates(const TContainer& map2d) -> std::map { std::map points{}; @@ -127,13 +127,13 @@ class PlaneMapper_Margin { } template - inline static auto mapMatrixCoordinates(const std::array, Y>& map2d) + inline static constexpr auto mapMatrixCoordinates(const std::array, Y>& map2d) { return mapMatrixCoordinates, Y>>(map2d); } template - inline static auto mapMatrixCoordinates(const std::initializer_list>& map2d) + inline static constexpr auto mapMatrixCoordinates(const std::initializer_list>& map2d) { return mapMatrixCoordinates>>(map2d); } @@ -141,7 +141,7 @@ class PlaneMapper_Margin { /// Re-maps a point index to output coordinate. /// \tparam Tp The type of the point index. template - [[nodiscard]] static constexpr auto mapPoint(Tp x, Tp y, Tp x_max, Tp y_max) -> Math::Point2 + inline static constexpr auto mapPoint(Tp x, Tp y, Tp x_max, Tp y_max) -> Math::Point2 { using LocalPointType = Math::Point2; From e7f8a9a481591dd744633ddbde33ec4ad6fe9687 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sat, 3 Aug 2024 01:39:19 +0400 Subject: [PATCH 45/67] refactor: do not use virtual component --- lib/core/senseshift/core/component.hpp | 30 ------------------- lib/freertos/senseshift/freertos/task.hpp | 2 +- .../senseshift/body/hands/input/gesture.hpp | 4 +-- .../body/hands/input/total_curl.hpp | 2 +- lib/io/senseshift/input/sensor.hpp | 8 +++-- .../input/sensor/analog_threshold.hpp | 2 +- .../senseshift/opengloves/opengloves.hpp | 6 ++-- .../opengloves/opengloves_component.hpp | 12 ++++---- 8 files changed, 20 insertions(+), 46 deletions(-) diff --git a/lib/core/senseshift/core/component.hpp b/lib/core/senseshift/core/component.hpp index fdd495c3..602fce3d 100644 --- a/lib/core/senseshift/core/component.hpp +++ b/lib/core/senseshift/core/component.hpp @@ -16,34 +16,4 @@ class IInitializable { virtual void init() = 0; }; - -class ITickable { - public: - virtual ~ITickable() = default; - - virtual void tick() = 0; -}; - -class Component : public virtual IInitializable, public virtual ITickable { - public: - /// @brief Initialize the component. - /// - /// Where the component's initialization should happen. - /// Analogous to Arduino's setup(). This method is guaranteed to only be called once. - /// - /// Defaults to doing nothing. - void init() override - { - } - - /// @brief Tick the component. - /// - /// This method will be called repeatedly. - /// Analogous to Arduino's loop(). init() is guaranteed to be called before this. - /// - /// Defaults to doing nothing. - void tick() override - { - } -}; } // namespace SenseShift diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 904eff4c..4ee395b7 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -120,7 +120,7 @@ class Task { } }; -template +template class ComponentUpdateTask : public Task> { static_assert(std::is_same_v); static_assert(std::is_same_v); diff --git a/lib/hands_input/senseshift/body/hands/input/gesture.hpp b/lib/hands_input/senseshift/body/hands/input/gesture.hpp index 8ce198d4..e559b21a 100644 --- a/lib/hands_input/senseshift/body/hands/input/gesture.hpp +++ b/lib/hands_input/senseshift/body/hands/input/gesture.hpp @@ -40,7 +40,7 @@ class GrabGesture : public Gesture { }); } - void tick() override + void tick() { if (this->attach_callbacks_) { LOG_E("gesture.grab", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); @@ -84,7 +84,7 @@ class PinchGesture : public Gesture { }); } - void tick() override + void tick() { if (this->attach_callbacks_) { LOG_E("gesture.pinch", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); diff --git a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp index f1f9bce2..000bb4c4 100644 --- a/lib/hands_input/senseshift/body/hands/input/total_curl.hpp +++ b/lib/hands_input/senseshift/body/hands/input/total_curl.hpp @@ -29,7 +29,7 @@ class TotalCurl : public ::SenseShift::Input::FloatSensor { } } - void tick() override + void tick() { if (this->attach_callbacks_) { LOG_E("total_curl", "tick() called when attach_callbacks_ is true, infinite loop go wroom-wroom!"); diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 68455080..98655871 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -37,7 +37,7 @@ template class ISensor : public virtual ISimpleSensor, public Calibration::Calibrated, public Filter::Filtered {}; template -class Sensor : public ISensor, public Component { +class Sensor : public ISensor { public: using ValueType = Tp; using CallbackManagerType = CallbackManager; @@ -65,6 +65,10 @@ class Sensor : public ISensor, public Component { { } + virtual void tick() + { + } + /// Publish the given state to the sensor. /// /// Firstly, the given state will be assigned to the sensor's raw_value_. @@ -147,7 +151,7 @@ class SimpleSensorDecorator : public Sensor { this->source_->init(); } - void tick() override + virtual void tick() { this->updateValue(); } diff --git a/lib/io/senseshift/input/sensor/analog_threshold.hpp b/lib/io/senseshift/input/sensor/analog_threshold.hpp index 280f0a46..286da2cd 100644 --- a/lib/io/senseshift/input/sensor/analog_threshold.hpp +++ b/lib/io/senseshift/input/sensor/analog_threshold.hpp @@ -39,7 +39,7 @@ class AnalogThresholdSensor : public BinarySensor { }); } - void tick() override + void tick() { if (this->attach_callbacks_) { LOG_E( diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index b5bc67a9..38181134 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -74,9 +74,9 @@ class ITransport : public IInitializable { using FloatSensor = ::SenseShift::Input::FloatSensor; using BinarySensor = ::SenseShift::Input::BinarySensor; -class InputSensors : public og::InputPeripheral, public Component { +class InputSensors : public og::InputPeripheral { public: - void init() override + void init() { for (auto& finger_curl : this->curl.fingers) { for (auto& joint_sensor : finger_curl.curl) { @@ -108,7 +108,7 @@ class InputSensors : public og::InputPeripheral, pu } } - void tick() override + void tick() { for (auto& finger_curl : this->curl.fingers) { for (auto& joint_sensor : finger_curl.curl) { diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index b18d01b1..fc3be9b6 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -16,7 +16,7 @@ namespace SenseShift::OpenGloves { template -class OpenGlovesTrackingComponent : public SenseShift::Component { +class OpenGlovesTrackingComponent { // Plotter raw_plotter_ = Plotter(&Serial, "Raw"); // Plotter calibrated_plotter_ = Plotter(&Serial, "Cal"); @@ -40,7 +40,7 @@ class OpenGlovesTrackingComponent : public SenseShift::Component { { } - void init() override + void init() { this->communication_->init(); this->input_sensors_.init(); @@ -51,7 +51,7 @@ class OpenGlovesTrackingComponent : public SenseShift::Component { } } - void tick() override + void tick() { // const auto start = micros(); @@ -128,7 +128,7 @@ class OpenGlovesTrackingComponent : public SenseShift::Component { }; template -class OpenGlovesForceFeedbackComponent : public SenseShift::Component { +class OpenGlovesForceFeedbackComponent { public: OpenGlovesForceFeedbackComponent( OutputWriters& output_writers, ::SenseShift::OpenGloves::ITransport* communication @@ -137,14 +137,14 @@ class OpenGlovesForceFeedbackComponent : public SenseShift::Component { { } - void init() override + void init() { log_d("Setting up OpenGloves force feedback task: %p", this); this->communication_->init(); this->output_writers_.init(); } - void tick() override + void tick() { if (this->communication_->hasData()) { const auto length = this->communication_->read(this->buffer.data(), this->buffer.size()); From e76662cb98d5cee1c81aaa64958bfc8d5288b765 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 21:29:11 +0400 Subject: [PATCH 46/67] chore: remove unnecessary inheritance --- .../arduino/input/sensor/multiplexer.hpp | 17 +++-- lib/io/senseshift/input/filter.hpp | 70 ------------------- lib/io/senseshift/input/sensor.hpp | 2 +- .../input/sensor/analog_threshold.hpp | 8 +-- 4 files changed, 12 insertions(+), 85 deletions(-) diff --git a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp index eb3c13b3..7746a7c8 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp @@ -15,7 +15,7 @@ namespace SenseShift::Arduino::Input { template -class Multiplexer : public IInitializable { +class Multiplexer { public: /// \param pins The pins to use for the multiplexer. explicit Multiplexer(const std::array& pins, const size_t switch_delay_us = 2) : @@ -23,7 +23,7 @@ class Multiplexer : public IInitializable { { } - void init() override + void init() { for (const auto pin : this->pins_) { pinMode(pin, OUTPUT); @@ -74,7 +74,7 @@ class MultiplexedAnalogSensor : public AnalogSimpleSensor { AnalogSimpleSensor::init(); } - [[nodiscard]] auto getValue() -> float override + auto getValue() -> float override { this->component_->selectChannel(this->channel_); @@ -86,17 +86,16 @@ class MultiplexedAnalogSensor : public AnalogSimpleSensor { const std::uint8_t channel_; }; +template class MultiplexedDigitalSensor : public DigitalSimpleSensor { public: /// \param component The CD74HC4057 Component to use. /// \param pin The SIG pin of the sensor. /// \param channel The channel to read from. - MultiplexedDigitalSensor( - MUX_CD74HC4057Component* component, const std::uint8_t pin_sig, const std::uint8_t channel - ) : + MultiplexedDigitalSensor(Multiplexer* component, const std::uint8_t pin_sig, const std::uint8_t channel) : component_(component), DigitalSimpleSensor(pin_sig), channel_(channel) { - assert(channel < 16 && "Channel out of range"); + assert(channel < (1 << N) && "Channel out of range"); } void init() override @@ -105,7 +104,7 @@ class MultiplexedDigitalSensor : public DigitalSimpleSensor { DigitalSimpleSensor::init(); } - [[nodiscard]] auto getValue() -> bool override + auto getValue() -> bool override { this->component_->selectChannel(this->channel_); @@ -113,7 +112,7 @@ class MultiplexedDigitalSensor : public DigitalSimpleSensor { } private: - MUX_CD74HC4057Component* component_; + Multiplexer* component_; const std::uint8_t channel_; }; diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 06823fc4..d0a3fab8 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -200,76 +200,6 @@ class LambdaFilter : public IFilter { Lambda filter_; }; -/// Average filter. Reads the value from the sensor and returns the average of the N values. -template -class SampleAverageFilter : public IFilter { - static_assert(std::is_arithmetic_v, "SampleAverageFilter only supports arithmetic types"); - static_assert(std::is_same_v, "Sensor type must match filter type"); - static_assert( - std::is_same_v, "Can only use sensors with readRawValue()" - ); - - public: - explicit SampleAverageFilter(std::size_t size) : size_(size){}; - - auto filter(ISimpleSensor* sensor, Tp value) -> Tp override - { - auto sum = value; - - // Read the acc_ from the sensor N-1 times and sum them up. - // We read it N-1 times because we already have the first acc_. - for (std::size_t i = 0; i < this->size_ - 1; i++) { - sum += sensor->readRawValue(); - } - - // Return the average of the values. - return sum / this->size_; - } - - private: - std::size_t size_; -}; - -template -class SampleMedianFilter : public IFilter { - static_assert(std::is_same_v, "Sensor type must match filter type"); - // static_assert(std::is_same_v, "Can only use sensors with - // readRawValue()"); - - public: - explicit SampleMedianFilter(std::size_t size_) : size_(size_) - { - // allocate the array - this->values = new Tp[size_]; - }; - - auto filter(ISimpleSensor* sensor, Tp value) -> Tp override - { - if (sensor == nullptr) { - LOG_E("filter.sampling_median", "Source sensor is null"); - return value; - } - - this->values[0] = value; - - // Read the acc_ from the sensor N-1 times and put them in the array. - // We read it N-1 times because we already have the first acc_. - for (std::size_t i = 1; i <= this->size_ - 1; i++) { - this->values[i] = sensor->getValue(); - } - - // Sort the array. - std::sort(this->values, this->values + this->size_); - - // Return the median of the values. - return this->values[this->size_ / 2]; - } - - private: - std::size_t size_; - Tp* values; -}; - template class SlidingWindowMovingAverageFilter : public IFilter { static_assert(std::is_arithmetic_v, "SlidingWindowAverageFilter only supports arithmetic types"); diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 98655871..0ec38d29 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -34,7 +34,7 @@ using IBinarySimpleSensor = ISimpleSensor; using IFloatSimpleSensor = ISimpleSensor; template -class ISensor : public virtual ISimpleSensor, public Calibration::Calibrated, public Filter::Filtered {}; +class ISensor : public ISimpleSensor, public Calibration::Calibrated, public Filter::Filtered {}; template class Sensor : public ISensor { diff --git a/lib/io/senseshift/input/sensor/analog_threshold.hpp b/lib/io/senseshift/input/sensor/analog_threshold.hpp index 286da2cd..8a9af64f 100644 --- a/lib/io/senseshift/input/sensor/analog_threshold.hpp +++ b/lib/io/senseshift/input/sensor/analog_threshold.hpp @@ -13,7 +13,7 @@ class AnalogThresholdSensor : public BinarySensor { /// \param threshold_upper Upper threshold, that needs to be crossed to transition from `low` to `high` states. /// \param threshold_lower Lower threshold, that needs to be crossed to transition from `high` to `low` states. explicit AnalogThresholdSensor( - ::SenseShift::Input::Sensor* source, Tp threshold_upper, Tp threshold_lower, bool attach_callbacks = false + Sensor* source, Tp threshold_upper, Tp threshold_lower, bool attach_callbacks = false ) : source_(source), threshold_upper_(threshold_upper), @@ -25,9 +25,7 @@ class AnalogThresholdSensor : public BinarySensor { /// \param source The source sensor. /// \param threshold Threshold, that will be used for both upper and lower thresholds. template, int> = 0> - explicit AnalogThresholdSensor( - ::SenseShift::Input::Sensor* source, float threshold = 0.5f, bool attach_callbacks = false - ) : + explicit AnalogThresholdSensor(Sensor* source, float threshold = 0.5f, bool attach_callbacks = false) : AnalogThresholdSensor(source, threshold, threshold, attach_callbacks) { } @@ -57,7 +55,7 @@ class AnalogThresholdSensor : public BinarySensor { } private: - ::SenseShift::Input::Sensor* source_; + Sensor* source_; Tp threshold_lower_, threshold_upper_; From 3852b4d617320950fb46e9c214cd235ff7ecb631 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 21:29:42 +0400 Subject: [PATCH 47/67] chore: remove unnecessary `[[nodiscard]]` attributes --- include/senseshift.h | 2 +- lib/arduino/senseshift/arduino/input/sensor/analog.hpp | 2 +- lib/arduino/senseshift/arduino/input/sensor/digital.hpp | 2 +- lib/arduino_esp32/senseshift/arduino/output/ledc.hpp | 2 +- lib/battery/senseshift/battery/input/battery_sensor.hpp | 2 +- lib/core/senseshift/core/helpers.hpp | 5 +++-- lib/haptics/senseshift/body/haptics/body.hpp | 2 +- lib/haptics/senseshift/body/haptics/interface.hpp | 2 +- lib/haptics/senseshift/body/haptics/plane.hpp | 7 ++++--- lib/io/senseshift/input/sensor.hpp | 8 ++++---- lib/opengloves/senseshift/opengloves/autoconfig.hpp | 6 +++--- lib/opengloves/senseshift/opengloves/opengloves.hpp | 4 ++-- 12 files changed, 23 insertions(+), 21 deletions(-) diff --git a/include/senseshift.h b/include/senseshift.h index fda7b0fc..c1c8073e 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -13,7 +13,7 @@ class Application final : public IEventDispatcher { public: Application(); - [[nodiscard]] auto getVibroBody() const -> Body::Haptics::FloatBody* + auto getVibroBody() const -> Body::Haptics::FloatBody* { return this->vibro_body_; } diff --git a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp index 5838df3d..8beb1861 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/analog.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/analog.hpp @@ -33,7 +33,7 @@ class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor { pinMode(this->pin_, INPUT); } - [[nodiscard]] inline auto getValue() -> float override + inline auto getValue() -> float override { const std::uint16_t raw = analogRead(this->pin_); return static_cast(raw) / ANALOG_MAX; diff --git a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp index dd8e75b2..a5050a26 100644 --- a/lib/arduino/senseshift/arduino/input/sensor/digital.hpp +++ b/lib/arduino/senseshift/arduino/input/sensor/digital.hpp @@ -21,7 +21,7 @@ class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor { pinMode(this->pin_, this->mode_); } - [[nodiscard]] auto getValue() -> bool override + auto getValue() -> bool override { return digitalRead(this->pin_) == this->inverted_; } diff --git a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp index ecef37a8..887999f8 100644 --- a/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp +++ b/lib/arduino_esp32/senseshift/arduino/output/ledc.hpp @@ -41,7 +41,7 @@ class LedcOutput : public ::SenseShift::Output::IFloatOutput { } } - [[nodiscard]] inline auto getMaxValue() const -> std::uint32_t + inline auto getMaxValue() const -> std::uint32_t { return (1 << this->analog_resolution_) - 1; } diff --git a/lib/battery/senseshift/battery/input/battery_sensor.hpp b/lib/battery/senseshift/battery/input/battery_sensor.hpp index d1aa71a8..d95036c4 100644 --- a/lib/battery/senseshift/battery/input/battery_sensor.hpp +++ b/lib/battery/senseshift/battery/input/battery_sensor.hpp @@ -44,7 +44,7 @@ class LookupTableInterpolateBatterySensor : public IBatterySensor { } protected: - [[nodiscard]] auto lookupInterpolateLevel(VoltageType voltage) -> float + auto lookupInterpolateLevel(VoltageType voltage) -> float { return ::SenseShift::lookup_table_interpolate_linear( *this->lookup_table_, diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index 83b62075..f86df634 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -74,7 +74,7 @@ constexpr auto remap_simple(Up value, Up max, Tp max_out) noexcept -> Tp /// /// \return template -[[nodiscard]] constexpr auto lookup_table_interpolate_linear(Container const& lookup_table, Tp value) -> To +constexpr auto lookup_table_interpolate_linear(Container const& lookup_table, Tp value) -> To { static_assert(std::is_same_v && std::is_same_v); static_assert( @@ -124,7 +124,8 @@ class CallbackManager { callback(args...); } } - [[nodiscard]] auto size() const -> size_t + + auto size() const -> size_t { return this->callbacks_.size(); } diff --git a/lib/haptics/senseshift/body/haptics/body.hpp b/lib/haptics/senseshift/body/haptics/body.hpp index 6c3cf002..06a2b92e 100644 --- a/lib/haptics/senseshift/body/haptics/body.hpp +++ b/lib/haptics/senseshift/body/haptics/body.hpp @@ -47,7 +47,7 @@ class OutputBody { void effect(const Target& target, const Position& pos, const typename Plane::Value& val); - [[nodiscard]] auto getTargets() const -> const TargetPlaneMap* + auto getTargets() const -> const TargetPlaneMap* { return &targets_; } diff --git a/lib/haptics/senseshift/body/haptics/interface.hpp b/lib/haptics/senseshift/body/haptics/interface.hpp index 11cff2d0..f9453234 100644 --- a/lib/haptics/senseshift/body/haptics/interface.hpp +++ b/lib/haptics/senseshift/body/haptics/interface.hpp @@ -68,7 +68,7 @@ class VibroEffectData { return this->intensity_; } - [[nodiscard]] constexpr inline auto getIntensity() const -> Intensity + constexpr inline auto getIntensity() const -> Intensity { return intensity_; } diff --git a/lib/haptics/senseshift/body/haptics/plane.hpp b/lib/haptics/senseshift/body/haptics/plane.hpp index 40680a25..067ddb9b 100644 --- a/lib/haptics/senseshift/body/haptics/plane.hpp +++ b/lib/haptics/senseshift/body/haptics/plane.hpp @@ -43,11 +43,12 @@ class OutputPlane { void setup(); virtual void effect(const Position&, const Value&); - [[nodiscard]] auto getAvailablePoints() const -> const PositionSet* + auto getAvailablePoints() const -> const PositionSet* { return &points_; } - [[nodiscard]] auto getActuatorStates() const -> const PositionStateMap* + + auto getActuatorStates() const -> const PositionStateMap* { return &states_; } @@ -80,7 +81,7 @@ class OutputPlane_Closest : public OutputPlane { void effect(const Position&, const Value&) override; private: - [[nodiscard]] static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; + static auto findClosestPoint(const PositionSet&, const Position&) -> const Position&; }; using FloatPlane = OutputPlane; diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 0ec38d29..2883571e 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -27,7 +27,7 @@ class ISimpleSensor : public virtual IInitializable { explicit ISimpleSensor() = default; /// Get the current sensor value. - [[nodiscard]] virtual auto getValue() -> ValueType = 0; + virtual auto getValue() -> ValueType = 0; }; using IBinarySimpleSensor = ISimpleSensor; @@ -86,20 +86,20 @@ class Sensor : public ISensor { } /// Get the current sensor .value_. - [[nodiscard]] auto getValue() -> ValueType override + auto getValue() -> ValueType override { return this->value_; } /// Get the current raw sensor .raw_value_. - [[nodiscard]] auto getRawValue() -> ValueType + auto getRawValue() -> ValueType { return this->raw_value_; } protected: /// Apply current filters to value. - [[nodiscard]] auto applyFilters(ValueType value) -> ValueType + auto applyFilters(ValueType value) -> ValueType { /// Apply calibration if (this->getCalibrator() != nullptr) { diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index ddae8059..788a4fcc 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -262,7 +262,7 @@ namespace SenseShift::OpenGloves::AutoConfig { -[[nodiscard]] auto createInput() -> InputSensors +auto createInput() -> InputSensors { InputSensors input_sensors; @@ -406,7 +406,7 @@ namespace SenseShift::OpenGloves::AutoConfig { return input_sensors; } -[[nodiscard]] auto createFfbOutputs() -> OutputWriters +auto createFfbOutputs() -> OutputWriters { OutputWriters output_writers; @@ -441,7 +441,7 @@ namespace SenseShift::OpenGloves::AutoConfig { /** * Setup the transport for the OpenGloves interface. */ -[[nodiscard]] auto createTransport() -> ITransport* +auto createTransport() -> ITransport* { #if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_SERIAL // Serial auto* pSerial = &SERIAL_PORT; diff --git a/lib/opengloves/senseshift/opengloves/opengloves.hpp b/lib/opengloves/senseshift/opengloves/opengloves.hpp index 38181134..e1a6ef0a 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves.hpp @@ -134,12 +134,12 @@ class InputSensors : public og::InputPeripheral { } } - [[nodiscard]] auto collectData() -> og::InputPeripheralData + auto collectData() -> og::InputPeripheralData { SS_OG_COLLECT_DATA(getValue); } - [[nodiscard]] auto collectRawData() -> og::InputPeripheralData + auto collectRawData() -> og::InputPeripheralData { SS_OG_COLLECT_DATA(getRawValue); } From 392bb909d1f5782e9fe24d0fe0a7b8fa33442230 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 22:57:22 +0400 Subject: [PATCH 48/67] ci(GitHub): don't fail if can't get previous memory usage --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8fdb0839..22e7c146 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -598,11 +598,11 @@ jobs: return baseBranchJobId; - - name: Download base branch usage.json artifact if: github.event_name == 'pull_request' id: download-base-usage uses: actions/download-artifact@v4 + continue-on-error: true with: name: merged-usage path: base-usage @@ -611,12 +611,12 @@ jobs: run-id: ${{ steps.base_branch_workflow.outputs.result }} - uses: actions/setup-python@v2 - if: github.event_name == 'pull_request' + if: github.event_name == 'pull_request' && steps.download-base-usage.outputs.artifacts == 'null' with: python-version: '3.x' - name: Report memory usage table - if: github.event_name == 'pull_request' + if: github.event_name == 'pull_request' && steps.download-base-usage.outputs.artifacts == 'null' shell: bash run: | python -m pip install --upgrade pip pandas tabulate @@ -635,7 +635,7 @@ jobs: cat ./memory-usage-comparison.md > $GITHUB_STEP_SUMMARY - uses: thollander/actions-comment-pull-request@v2 - if: github.event_name == 'pull_request' + if: github.event_name == 'pull_request' && steps.download-base-usage.outputs.artifacts == 'null' with: filePath: memory-usage-comparison.md comment_tag: memory-usage-comparison From 8b848c591b9fcfb71c480badd31b7b4da8d71c8a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 21:54:04 +0400 Subject: [PATCH 49/67] ci(GitHub): use env build flags --- .github/workflows/ci.yml | 52 ++++++++++------------------------------ 1 file changed, 12 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22e7c146..a988fa3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,6 +59,11 @@ jobs: coverage: false battery_flag: SS_BATTERY_ENABLED=true nimble_flag: SS_USE_NIMBLE=true + env: + PLATFORMIO_BUILD_FLAGS: >- + ${{ matrix.coverage && '-lgcov --coverage' || '' }} + ${{ matrix.battery_flag && format('-D {0}', matrix.battery_flag) || '' }} + ${{ matrix.nimble_flag && format('-D {0}', matrix.nimble_flag) || '' }} steps: - uses: actions/checkout@v4 @@ -70,26 +75,6 @@ jobs: run: | ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.battery_flag }} ${{ matrix.nimble_flag }} - - name: Enable coverage (non-macOS) - if: runner.os != 'macOS' && matrix.coverage - run: | - sed -i '/__OH_FIRMWARE__/p; s/-D __OH_FIRMWARE__/-lgcov --coverage/' platformio.ini - - name: Enable coverage (macOS) - if: runner.os == 'macOS' && matrix.coverage - run: | - sed -i '' '/__OH_FIRMWARE__/p; s/-D __OH_FIRMWARE__/-lgcov --coverage/' platformio.ini - - - name: Update build flags (non-macOS) - if: runner.os != 'macOS' - run: | - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.battery_flag }}/' platformio.ini - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.nimble_flag }}/' platformio.ini - - name: Update build flags (macOS) - if: runner.os == 'macOS' - run: | - sed -i '' '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.battery_flag }}/' platformio.ini - sed -i '' '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.nimble_flag }}/' platformio.ini - - name: Speedup package installation if: matrix.coverage uses: abbbi/github-actions-tune@v1 @@ -242,6 +227,12 @@ jobs: comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL coverage: true + env: + PLATFORMIO_BUILD_FLAGS: >- + ${{ matrix.coverage && '-lgcov --coverage' || '' }} + ${{ matrix.comm_flag && format('-D {0}', matrix.comm_flag) || '' }} + ${{ matrix.curl_calibration_flag && format('-D {0}', matrix.curl_calibration_flag) || '' }} + steps: - uses: actions/checkout@v4 with: @@ -284,26 +275,6 @@ jobs: with: python-version: "3.9" - - name: Enable coverage (non-macOS) - if: runner.os != 'macOS' && matrix.coverage - run: | - sed -i '/__OH_FIRMWARE__/p; s/-D __OH_FIRMWARE__/-lgcov --coverage/' platformio.ini - - name: Enable coverage (macOS) - if: runner.os == 'macOS' && matrix.coverage - run: | - sed -i '' '/__OH_FIRMWARE__/p; s/-D __OH_FIRMWARE__/-lgcov --coverage/' platformio.ini - - - name: Update build flags (non-macOS) - if: runner.os != 'macOS' - run: | - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.curl_calibration_flag }}/' platformio.ini - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.comm_flag }}/' platformio.ini - - name: Update build flags (macOS) - if: runner.os == 'macOS' - run: | - sed -i '' '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.curl_calibration_flag }}/' platformio.ini - sed -i '' '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.comm_flag }}/' platformio.ini - - name: Install PlatformIO run: | python -m pip install --upgrade pip @@ -639,6 +610,7 @@ jobs: with: filePath: memory-usage-comparison.md comment_tag: memory-usage-comparison + wokwi: needs: - build-bhaptics From ed9cbb9f987d55089a1fe38b4aeddec4d28e2767 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 23:12:57 +0400 Subject: [PATCH 50/67] chore: enable NimBLE by default --- .github/workflows/ci.yml | 18 +++--------------- platformio.ini | 2 +- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a988fa3d..25544a73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ concurrency: jobs: build-bhaptics: - name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} -D ${{ matrix.nimble_flag }} + name: Build ${{ matrix.target }} ${{ matrix.coverage && 'with coverage' || 'without coverage' }}, -D ${{ matrix.battery_flag }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -39,7 +39,6 @@ jobs: - bhaptics_tactvisor - bhaptics_tactglove_right battery_flag: [ SS_BATTERY_ENABLED=true ] - nimble_flag: [ SS_USE_NIMBLE=false ] coverage: [ false ] include: @@ -48,22 +47,11 @@ jobs: os: ubuntu-latest coverage: true battery_flag: SS_BATTERY_ENABLED=true - nimble_flag: SS_USE_NIMBLE=true - - target: bhaptics_tactsuit_x40 - os: ubuntu-latest - coverage: true - battery_flag: SS_BATTERY_ENABLED=true - nimble_flag: SS_USE_NIMBLE=false - - target: bhaptics_tactsuit_x40 - os: ubuntu-latest - coverage: false - battery_flag: SS_BATTERY_ENABLED=true - nimble_flag: SS_USE_NIMBLE=true + env: PLATFORMIO_BUILD_FLAGS: >- ${{ matrix.coverage && '-lgcov --coverage' || '' }} ${{ matrix.battery_flag && format('-D {0}', matrix.battery_flag) || '' }} - ${{ matrix.nimble_flag && format('-D {0}', matrix.nimble_flag) || '' }} steps: - uses: actions/checkout@v4 @@ -73,7 +61,7 @@ jobs: - name: Get firmware name id: firmware_name run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.battery_flag }} ${{ matrix.nimble_flag }} + ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.battery_flag }} - name: Speedup package installation if: matrix.coverage diff --git a/platformio.ini b/platformio.ini index 5af316fe..49beda78 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ build_flags = ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial ; -D SS_BATTERY_ENABLED=true -; -D SS_USE_NIMBLE=true + -D SS_USE_NIMBLE=true -D SOC_WIFI_SUPPORTED=1 build_src_filter = From bb9e07b3eb24130d45f82fc85506a1f965a1765e Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 23:23:29 +0400 Subject: [PATCH 51/67] ci(GitHub): fix memory report checks --- .github/workflows/ci.yml | 25 +++++++++++++------------ .github/workflows/release.yml | 20 +++++++++----------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25544a73..34a3f5de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: - name: Get firmware name id: firmware_name run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.battery_flag }} + ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ env.PLATFORMIO_BUILD_FLAGS }} - name: Speedup package installation if: matrix.coverage @@ -117,7 +117,10 @@ jobs: echo "::group::platformio.ini" cat platformio.ini echo "::endgroup::" + + echo "::group::pio run" pio ${{ matrix.coverage && 'debug' || 'run' }} --environment ${{matrix.target}} | tee build.log + echo "::endgroup::" - name: Collect memory usage id: memory_usage @@ -229,7 +232,7 @@ jobs: - name: Get firmware name id: firmware_name run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.comm_flag }} ${{ matrix.curl_calibration_flag }} + ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ env.PLATFORMIO_BUILD_FLAGS }} - name: Speedup package installation if: matrix.coverage @@ -285,20 +288,20 @@ jobs: echo "::group::platformio.ini" cat platformio.ini echo "::endgroup::" + + echo "::group::pio run" pio ${{ matrix.coverage && 'debug' || 'run' }} --environment ${{matrix.target}} | tee build.log + echo "::endgroup::" - name: Collect memory usage id: memory_usage if: matrix.coverage == false + env: + USAGE_FILENAME: ${{ steps.firmware_name.outputs.firmware }}-usage.json run: | echo "USAGE_FILENAME=${{ env.USAGE_FILENAME }}" >> $GITHUB_ENV - # RAM: [= ] 11.8% (used 38636 bytes from 327680 bytes) - # Flash: [========= ] 90.1% (used 1181501 bytes from 1310720 bytes) - - # Extract the line containing RAM usage ram_line=$(grep 'RAM:' build.log) - # Extract the line containing Flash usage flash_line=$(grep 'Flash:' build.log) # Parse the RAM usage details @@ -316,8 +319,6 @@ jobs: # Print the content of usage.json cat ${{ env.USAGE_FILENAME }} - env: - USAGE_FILENAME: ${{ steps.firmware_name.outputs.firmware }}-usage.json - name: Upload usage.json artifact if: matrix.coverage == false @@ -570,12 +571,12 @@ jobs: run-id: ${{ steps.base_branch_workflow.outputs.result }} - uses: actions/setup-python@v2 - if: github.event_name == 'pull_request' && steps.download-base-usage.outputs.artifacts == 'null' + if: github.event_name == 'pull_request' && steps.download-base-usage.outcome == 'success' with: python-version: '3.x' - name: Report memory usage table - if: github.event_name == 'pull_request' && steps.download-base-usage.outputs.artifacts == 'null' + if: github.event_name == 'pull_request' && steps.download-base-usage.outcome == 'success' shell: bash run: | python -m pip install --upgrade pip pandas tabulate @@ -594,7 +595,7 @@ jobs: cat ./memory-usage-comparison.md > $GITHUB_STEP_SUMMARY - uses: thollander/actions-comment-pull-request@v2 - if: github.event_name == 'pull_request' && steps.download-base-usage.outputs.artifacts == 'null' + if: github.event_name == 'pull_request' && steps.download-base-usage.outcome == 'success' with: filePath: memory-usage-comparison.md comment_tag: memory-usage-comparison diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eed4aaa9..fcc857d4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,8 +38,10 @@ jobs: - bhaptics_tactglove_right battery_flag: - SS_BATTERY_ENABLED=true - nimble_flag: - - SS_USE_NIMBLE=true + + env: + PLATFORMIO_BUILD_FLAGS: >- + ${{ matrix.battery_flag && format('-D {0}', matrix.battery_flag) || '' }} steps: - uses: actions/checkout@v4 @@ -87,11 +89,6 @@ jobs: sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/scripts\/ci\/create-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - - name: Update build flags (non-macOS) - run: | - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.battery_flag }}/' platformio.ini - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.nimble_flag }}/' platformio.ini - - name: Build run: | mkdir build @@ -138,6 +135,11 @@ jobs: comm_flag: - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL + + env: + PLATFORMIO_BUILD_FLAGS: >- + ${{ matrix.comm_flag && format('-D {0}', matrix.comm_flag) || '' }} + steps: - uses: actions/checkout@v4 with: @@ -153,10 +155,6 @@ jobs: sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/scripts\/ci\/create-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - - name: Update build flags (non-macOS) - run: | - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.comm_flag }}/' platformio.ini - - name: Cache pip uses: actions/cache@v4 with: From 49d6f08587af8ef03f75faf15983948f42c3fe4d Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Sun, 4 Aug 2024 23:50:22 +0400 Subject: [PATCH 52/67] ci(GitHub): update firmware-name script --- .github/scripts/get-firmware-name.py | 135 +++++++++++++++++++++++++++ .github/scripts/get_firmware_name.sh | 93 ------------------ .github/workflows/ci.yml | 18 ++-- .github/workflows/release.yml | 6 +- 4 files changed, 143 insertions(+), 109 deletions(-) create mode 100644 .github/scripts/get-firmware-name.py delete mode 100755 .github/scripts/get_firmware_name.sh diff --git a/.github/scripts/get-firmware-name.py b/.github/scripts/get-firmware-name.py new file mode 100644 index 00000000..362a29de --- /dev/null +++ b/.github/scripts/get-firmware-name.py @@ -0,0 +1,135 @@ +import os +import sys +import re +import argparse + + +def github_debug(message): + """ + Print a debug message in GitHub Actions format. + + Args: + message (str): The debug message. + """ + print(f"::debug::{message}") + + +def strip_flags(flags): + return [flag[2:] if flag.startswith('-D') and flag != '-D' else flag for flag in flags if flag != '-D'] + + +def store_firmware_name(target): + print(f"firmware={target}") + if os.getenv('GITHUB_ACTIONS'): + with open(os.getenv('GITHUB_OUTPUT'), 'a') as github_output: + github_output.write(f"firmware={target}\n") + else: + print("::error::Not in GitHub Actions") + + +def get_bhaptics_name(target, flags): + """ + Get bHaptics name based on target and flags. + + Args: + target (str): The target name. + flags (list): List of flags. + """ + github_debug(f"Getting bHaptics name for {target}") + github_debug(f"Flags are {flags}") + + if "SS_USE_NIMBLE=true" in flags: + github_debug("Nimble is enabled, appending +nimble to the target") + target += "+nimble" + + if "SS_BATTERY_ENABLED=true" in flags: + github_debug("Battery is enabled, appending +battery to the target") + target += "+battery" + + store_firmware_name(target) + + +def handle_calibration_flag(target, flag, prefix): + """ + Handle calibration flags. + + Args: + target (str): The target name. + flag (str): The flag name. + prefix (str): The prefix for the calibration. + """ + if "MinMaxCalibrator" in flag: + target += f"+{prefix}_minmax" + elif "FixedCenterPointDeviationCalibrator" in flag: + target += f"+{prefix}_fcpd" + elif "CenterPointDeviationCalibrator" in flag: + target += f"+{prefix}_cpd" + + return target + + +def handle_opengloves_comm_flag(target, flag): + """ + Handle OpenGloves communication flags. + + Args: + target (str): The target name. + flag (str): The flag name. + """ + if "OPENGLOVES_COMM_SERIAL" in flag: + github_debug("Serial is enabled, appending +serial to the target") + target += "+serial" + elif "OPENGLOVES_COMM_BTSERIAL" in flag: + github_debug("Bluetooth Serial is enabled, appending +bluetooth to the target") + target += "+bluetooth" + elif "OPENGLOVES_COMM_BLESERIAL" in flag: + github_debug("BLE Serial is enabled, appending +ble to the target") + target += "+ble" + + return target + + +def get_opengloves_name(target, flags): + """ + Get OpenGloves name based on target and flags. + + Args: + target (str): The target name. + flags (list): List of flags. + """ + github_debug(f"Getting OpenGloves name for {target}") + github_debug(f"Flags are {flags}") + + for flag in flags: + if "OPENGLOVES_COMMUNICATION" in flag: + target = handle_opengloves_comm_flag(target, flag) + if "CALIBRATION_CURL" in flag: + target = handle_calibration_flag(target, flag, "curl_calib") + if "CALIBRATION_SPLAY" in flag: + target = handle_calibration_flag(target, flag, "splay_calib") + + store_firmware_name(target) + + +def main(): + parser = argparse.ArgumentParser(description='Get firmware name based on target and flags.') + parser.add_argument('target', type=str, help='The target name') + parser.add_argument('flags', type=str, help='List of flags', default='') + args = parser.parse_args() + + target = args.target + flags = strip_flags(args.flags.split(' ')) + + github_debug(f"Target is {target}") + + if re.match(r'^(bhaptics)', target): + get_bhaptics_name(target, flags) + elif re.match(r'^(opengloves|lucidgloves|indexer)', target): + get_opengloves_name(target, flags) + else: + print(f"::error::Unknown target {target}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/.github/scripts/get_firmware_name.sh b/.github/scripts/get_firmware_name.sh deleted file mode 100755 index 97e654e0..00000000 --- a/.github/scripts/get_firmware_name.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env bash - -getBhapticsName() { - target=$1 - # rest of params - flags=${@:2} - - echo "::debug::Getting bHaptics name for $target" - echo "::debug::Flags are $flags" - - if [[ $flags =~ SS_USE_NIMBLE=true ]]; then - echo "::debug::Nimble is enabled, appending +nimble to the target" - target="$target+nimble" - fi - - if [[ $flags =~ SS_BATTERY_ENABLED=true ]]; then - echo "::debug::Battery is enabled, appending +battery to the target" - target="$target+battery" - fi - - echo "firmware=$target" - if [[ -n "$GITHUB_ACTIONS" ]]; then - echo "firmware=$target" >> "$GITHUB_OUTPUT" - return - else - echo "::error::Not in GitHub Actions" - fi -} - -handleCalibrationFlag() { - local target=$1 - local flag=$2 - local prefix=$3 - - if [[ $flag =~ MinMaxCalibrator ]]; then - target="$target+${prefix}_minmax" - elif [[ $flag =~ FixedCenterPointDeviationCalibrator ]]; then - target="$target+${prefix}_fcpd" - elif [[ $flag =~ CenterPointDeviationCalibrator ]]; then - target="$target+${prefix}_cpd" - fi - - echo "$target" -} - -getOpenGlovesName() { - local target=$1 - # rest of params - local flags=${@:2} - - echo "::debug::Getting OpenGloves name for $target" - echo "::debug::Flags are $flags" - - if [[ $flags =~ OPENGLOVES_COMM_SERIAL ]]; then - echo "::debug::Serial is enabled, appending +serial to the target" - target="$target+serial" - elif [[ $flags =~ OPENGLOVES_COMM_BTSERIAL ]]; then - echo "::debug::Bluetooth Serial is enabled, appending +bluetooth to the target" - target="$target+bluetooth" - elif [[ $flags =~ OPENGLOVES_COMM_BLESERIAL ]]; then - echo "::debug::BLE Serial is enabled, appending +ble to the target" - target="$target+ble" - fi - - for flag in "${@:2}"; do - if [[ $flag =~ CALIBRATION_CURL ]]; then - target=$(handleCalibrationFlag "$target" "$flag" "curl_calib") - fi - - if [[ $flag =~ CALIBRATION_SPLAY ]]; then - target=$(handleCalibrationFlag "$target" "$flag" "splay_calib") - fi - done - - echo "firmware=$target" - if [[ -n "$GITHUB_ACTIONS" ]]; then - echo "firmware=$target" >> "$GITHUB_OUTPUT" - return - else - echo "::error::Not in GitHub Actions" - fi -} - -target=$1 -echo "::debug::Target is $target" -if [[ $target =~ ^(bhaptics) ]]; then - getBhapticsName "${@}" -elif [[ $target =~ ^(opengloves|lucidgloves|indexer) ]]; then - getOpenGlovesName "${@}" -else - echo "::error::Unknown target $target" - exit 1 -fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34a3f5de..b45a2138 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,8 +60,7 @@ jobs: - name: Get firmware name id: firmware_name - run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ env.PLATFORMIO_BUILD_FLAGS }} + run: python3 ./.github/scripts/get-firmware-name.py ${{ matrix.target }} '${{ env.PLATFORMIO_BUILD_FLAGS }}' - name: Speedup package installation if: matrix.coverage @@ -199,24 +198,20 @@ jobs: include: - os: ubuntu-latest target: lucidgloves-prototype4-ffb + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::MinMaxCalibrator()" coverage: true + - os: ubuntu-latest target: lucidgloves-prototype4-ffb + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::CenterPointDeviationCalibrator(0.66F, 0.005F)" coverage: true + - os: ubuntu-latest target: lucidgloves-prototype4-ffb curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::FixedCenterPointDeviationCalibrator(0.66F, 0.005F)" coverage: true - - os: ubuntu-latest - target: indexer-csf - comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL - coverage: true - - os: ubuntu-latest - target: indexer-csf - comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL - coverage: true env: PLATFORMIO_BUILD_FLAGS: >- @@ -231,8 +226,7 @@ jobs: - name: Get firmware name id: firmware_name - run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ env.PLATFORMIO_BUILD_FLAGS }} + run: python3 ./.github/scripts/get-firmware-name.py ${{ matrix.target }} '${{ env.PLATFORMIO_BUILD_FLAGS }}' - name: Speedup package installation if: matrix.coverage diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fcc857d4..2457c914 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,8 +50,7 @@ jobs: - name: Get firmware name id: firmware_name - run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} + run: python3 ./.github/scripts/get-firmware-name.py ${{ matrix.target }} "" - name: Cache pip uses: actions/cache@v4 @@ -147,8 +146,7 @@ jobs: - name: Get firmware name id: firmware_name - run: | - ./.github/scripts/get_firmware_name.sh ${{ matrix.target }} ${{ matrix.comm_flag }} + run: python3 ./.github/scripts/get-firmware-name.py ${{ matrix.target }} '${{ matrix.comm_flag }}' - name: Update build command (non-Windows) run: | From 5f54f91b7ef6413787c7dcd76641e1d89ce49d57 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Mon, 5 Aug 2024 15:01:37 +0400 Subject: [PATCH 53/67] ci(GitHub): lessen OpenGloves matrix --- .github/workflows/ci.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b45a2138..be339a99 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -186,30 +186,37 @@ jobs: target: - lucidgloves-prototype3 - lucidgloves-prototype4 + - lucidgloves-prototype4-ffb - indexer-c - indexer-cf - indexer-cs - indexer-csf - comm_flag: - - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL - - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL + comm_flag: [ OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL ] coverage: [ false ] include: - os: ubuntu-latest target: lucidgloves-prototype4-ffb comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL + - os: ubuntu-latest + target: lucidgloves-prototype4-ffb + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL + + - os: ubuntu-latest + target: lucidgloves-prototype4-ffb + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::MinMaxCalibrator()" coverage: true - os: ubuntu-latest target: lucidgloves-prototype4-ffb - comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::CenterPointDeviationCalibrator(0.66F, 0.005F)" coverage: true - os: ubuntu-latest target: lucidgloves-prototype4-ffb + comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::FixedCenterPointDeviationCalibrator(0.66F, 0.005F)" coverage: true From 1ca09b0421d8a1e663edca7fcb628cf888d9fac7 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Mon, 5 Aug 2024 16:35:10 +0400 Subject: [PATCH 54/67] ci(GitHub): reusable `setup-platfromio` action --- .github/actions/setup-platformio/action.yml | 67 ++++++++++ .../scripts/create-release-archive.py | 6 +- .github/workflows/ci.yml | 119 ++++++------------ .github/workflows/release.yml | 74 +++++------ .github/workflows/sast.yml | 81 ++---------- platformio.ini | 2 +- 6 files changed, 147 insertions(+), 202 deletions(-) create mode 100644 .github/actions/setup-platformio/action.yml rename scripts/ci/create-archive.py => .github/scripts/create-release-archive.py (86%) diff --git a/.github/actions/setup-platformio/action.yml b/.github/actions/setup-platformio/action.yml new file mode 100644 index 00000000..6294ae0d --- /dev/null +++ b/.github/actions/setup-platformio/action.yml @@ -0,0 +1,67 @@ +name: "Setup PlatformIO" +description: "Setup PlatformIO for building and checking firmware" + +inputs: + cache: + required: false + description: "Specify things to cache. Supported values are: 'pip', 'cache', 'packages', 'platforms', 'build_cache', 'build_dir'." + default: 'pip cache' + cache_dir: + description: https://docs.platformio.org/en/latest/projectconf/sections/platformio/options/directory/cache_dir.html + required: false + default: '~/.platformio/.cache' + packages_dir: + description: https://docs.platformio.org/en/latest/projectconf/sections/platformio/options/directory/packages_dir.html + required: false + default: '~/.platformio/packages' + platforms_dir: + description: https://docs.platformio.org/en/latest/projectconf/sections/platformio/options/directory/platforms_dir.html + required: false + default: '~/.platformio/platforms' + build_cache_dir: + description: https://docs.platformio.org/en/latest/projectconf/sections/platformio/options/directory/build_cache_dir.html + required: false + build_dir: + description: https://docs.platformio.org/en/latest/projectconf/sections/platformio/options/directory/build_dir.html + required: false + +runs: + using: composite + steps: + - name: Prepare + shell: bash + run: | + touch ./requirements.txt + + ${{ inputs.cache_dir && format('echo "PLATFORMIO_CACHE_DIR={0}" >> $GITHUB_ENV', inputs.cache_dir) || '' }} + ${{ inputs.packages_dir && format('echo "PLATFORMIO_PACKAGES_DIR={0}" >> $GITHUB_ENV', inputs.packages_dir) || '' }} + ${{ inputs.platforms_dir && format('echo "PLATFORMIO_PLATFORMS_DIR={0}" >> $GITHUB_ENV', inputs.platforms_dir) || '' }} + ${{ inputs.build_cache_dir && format('echo "PLATFORMIO_BUILD_CACHE_DIR={0}" >> $GITHUB_ENV', inputs.build_cache_dir) || '' }} + ${{ inputs.build_dir && format('echo "PLATFORMIO_BUILD_DIR={0}" >> $GITHUB_ENV', inputs.build_dir) || '' }} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + cache: ${{ contains(inputs.cache, 'pip') && 'pip' || '' }} + + - name: Cache PlatformIO + uses: actions/cache@v4 + with: + path: | + ${{ contains(inputs.cache, 'cache') && inputs.cache_dir || '' }} + ${{ contains(inputs.cache, 'packages') && inputs.packages_dir || '' }} + ${{ contains(inputs.cache, 'platforms') && inputs.platforms_dir || '' }} + ${{ contains(inputs.cache, 'build_cache') && inputs.build_cache_dir || '' }} + ${{ contains(inputs.cache, 'build_dir') && inputs.build_dir || '' }} + key: setup-platformio-${{ runner.os }}-pio-${{ hashFiles('**/*.ini') }} + restore-keys: | + setup-platformio-${{ runner.os }}-pio- + + - name: Install PlatformIO + shell: bash + run: | + python -m pip install --upgrade pip + pip install --upgrade platformio + pio upgrade --dev + pio pkg update --global diff --git a/scripts/ci/create-archive.py b/.github/scripts/create-release-archive.py similarity index 86% rename from scripts/ci/create-archive.py rename to .github/scripts/create-release-archive.py index 4490669a..7643e03e 100644 --- a/scripts/ci/create-archive.py +++ b/.github/scripts/create-release-archive.py @@ -8,9 +8,10 @@ n = 2 partitions_arg = sys.argv[1:] -partitions = final = [partitions_arg[i * n:(i + 1) * n] for i in range((len(partitions_arg) + n - 1) // n )] +partitions = final = [partitions_arg[i * n:(i + 1) * n] for i in range((len(partitions_arg) + n - 1) // n)] -with ZipFile('build/firmware.zip', 'w') as archive: +path = 'build/firmware.zip' +with ZipFile(path, 'w') as archive: print('Creating "' + archive.filename + '"', end='\n') parts = [] @@ -28,4 +29,3 @@ 'parts': parts, } archive.writestr('manifest.json', json.dumps(manifest)) - diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be339a99..802977c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,39 +70,28 @@ jobs: if: matrix.coverage uses: hrishikesh-kadam/setup-lcov@v1 - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Cache PlatformIO + - name: Cache PlatformIO target + if: matrix.coverage == false uses: actions/cache@v4 with: path: | - ~/.platformio/.cache - ./.pio - key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ hashFiles('**/*.ini') }} + ./.pio/build/${{ matrix.target }} + key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}-${{ hashFiles('**/*.ini') }} restore-keys: | + ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}- ${{ runner.os }}-pio-${{ matrix.target }}- ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v5 + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio with: - python-version: "3.9" - - - name: Install PlatformIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pio upgrade --dev - pio pkg update --global + build_cache_dir: ./.pio/build_cache + cache: 'pip cache build_cache' - name: Install libs - run: pio pkg install -e ${{matrix.target}} + shell: bash + run: | + pio pkg install -e ${{matrix.target}} - name: Change memory segments if: matrix.coverage @@ -113,13 +102,7 @@ jobs: - name: Build shell: bash run: | - echo "::group::platformio.ini" - cat platformio.ini - echo "::endgroup::" - - echo "::group::pio run" pio ${{ matrix.coverage && 'debug' || 'run' }} --environment ${{matrix.target}} | tee build.log - echo "::endgroup::" - name: Collect memory usage id: memory_usage @@ -243,39 +226,28 @@ jobs: if: matrix.coverage uses: hrishikesh-kadam/setup-lcov@v1 - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Cache PlatformIO + - name: Cache PlatformIO target + if: matrix.coverage == false uses: actions/cache@v4 with: path: | - ~/.platformio/.cache - ./.pio - key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ hashFiles('platformio.ini') }} + ./.pio/build/${{ matrix.target }} + key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}-${{ hashFiles('**/*.ini') }} restore-keys: | + ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}- ${{ runner.os }}-pio-${{ matrix.target }}- ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v5 + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio with: - python-version: "3.9" - - - name: Install PlatformIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pio upgrade --dev - pio pkg update --global + build_cache_dir: ./.pio/build_cache + cache: 'pip cache build_cache' - name: Install libs - run: pio pkg install -e ${{matrix.target}} + shell: bash + run: | + pio pkg install -e ${{matrix.target}} - name: Change memory segments if: matrix.coverage @@ -286,13 +258,7 @@ jobs: - name: Build shell: bash run: | - echo "::group::platformio.ini" - cat platformio.ini - echo "::endgroup::" - - echo "::group::pio run" pio ${{ matrix.coverage && 'debug' || 'run' }} --environment ${{matrix.target}} | tee build.log - echo "::endgroup::" - name: Collect memory usage id: memory_usage @@ -344,6 +310,9 @@ jobs: - name: Collect initial coverage if: matrix.coverage run: | + echo "::group::List files" + ls -lahR ./.pio/build/${{matrix.target}}/ + echo "::endgroup::" mkdir -p ./build/lcov lcov -i -d ./.pio/build/${{matrix.target}}/ -c -o ./build/lcov/lcov.info.${{ steps.firmware_name.outputs.firmware }} -gcov-tool ~/.platformio/packages/toolchain-xtensa-esp32/bin/xtensa-esp32-elf-gcov @@ -375,39 +344,23 @@ jobs: - name: Setup LCOV uses: hrishikesh-kadam/setup-lcov@v1 - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Cache PlatformIO + - name: Cache PlatformIO target uses: actions/cache@v4 with: path: | - ~/.platformio/.cache - ./.pio - key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ hashFiles('platformio.ini') }} + ./.pio/build/${{ matrix.target }} + key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ hashFiles('**/*.ini') }} restore-keys: | - ${{ runner.os }}-pio-${{ matrix.target }} + ${{ runner.os }}-pio-${{ matrix.target }}- ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.9" - - - name: Install PlatformIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pio upgrade --dev - pio pkg update --global + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio - name: Install libs - run: pio pkg install -e ${{matrix.target}} + shell: bash + run: | + pio pkg install -e ${{matrix.target}} - name: Run Unit Tests run: pio test -e ${{matrix.target}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2457c914..7b87191f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,41 +52,32 @@ jobs: id: firmware_name run: python3 ./.github/scripts/get-firmware-name.py ${{ matrix.target }} "" - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Cache PlatformIO + - name: Cache PlatformIO target uses: actions/cache@v4 with: path: | - ~/.platformio/.cache - ./.pio - key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ hashFiles('platformio.ini') }} + ./.pio/build/${{ matrix.target }} + key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}-${{ hashFiles('**/*.ini') }} restore-keys: | + ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}- ${{ runner.os }}-pio-${{ matrix.target }}- ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v5 + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio with: - python-version: '3.9' + build_cache_dir: ./.pio/build_cache + cache: 'pip cache build_cache' - - name: Install PlatformIO + - name: Install libs + shell: bash run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pio upgrade --dev - pio pkg update --global + pio pkg install -e ${{matrix.target}} - name: Update build command (non-Windows) run: | sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini - sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/scripts\/ci\/create-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini + sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/.github\/scripts\/create-release-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - name: Build run: | @@ -148,41 +139,32 @@ jobs: id: firmware_name run: python3 ./.github/scripts/get-firmware-name.py ${{ matrix.target }} '${{ matrix.comm_flag }}' - - name: Update build command (non-Windows) - run: | - sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini - sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/scripts\/ci\/create-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Cache PlatformIO + - name: Cache PlatformIO target uses: actions/cache@v4 with: path: | - ~/.platformio/.cache - ./.pio - key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ hashFiles('platformio.ini') }} + ./.pio/build/${{ matrix.target }} + key: ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}-${{ hashFiles('**/*.ini') }} restore-keys: | + ${{ runner.os }}-pio-${{ matrix.target }}-${{ steps.firmware_name.outputs.firmware }}- ${{ runner.os }}-pio-${{ matrix.target }}- ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v5 + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio with: - python-version: '3.9' + build_cache_dir: ./.pio/build_cache + cache: 'pip cache build_cache' - - name: Install PlatformIO + - name: Install libs + shell: bash run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pio upgrade --dev - pio pkg update --global + pio pkg install -e ${{matrix.target}} + + - name: Update build command (non-Windows) + run: | + sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini + sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/.github\/scripts\/create-release-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - name: Build run: | diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 19d5ae34..66aaa39d 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -29,96 +29,39 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'cpp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - # Enabling all flags to test build for every feature + target: + - bhaptics_tactsuit_x40 + - lucidgloves-prototype4-ffb battery_flag: - SS_BATTERY_ENABLED=true + env: + PLATFORMIO_BUILD_FLAGS: >- + ${{ matrix.battery_flag && format('-D {0}', matrix.battery_flag) || '' }} + steps: - name: Checkout repository uses: actions/checkout@v4 with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. fetch-depth: 2 submodules: 'recursive' - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - # - run: git checkout HEAD^2 - # if: ${{ github.event_name == 'pull_request' }} - - # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/codeql-config.yml - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - # - name: Autobuild - # uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Cache pip - uses: actions/cache@v4 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - name: Cache PlatformIO - uses: actions/cache@v4 - with: - path: ~/.platformio - key: ${{ runner.os }}-pio-${{ hashFiles('**/lockfiles') }} - restore-keys: | - ${{ runner.os }}-pio- - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.9' - - - name: Update build flags (non-macOS) - if: runner.os != 'macOS' - run: | - sed -i '/__OH_FIRMWARE__/p; s/__OH_FIRMWARE__/${{ matrix.battery_flag }}/' platformio.ini - - name: Install PlatformIO - run: | - python -m pip install --upgrade pip - pip install --upgrade platformio - pio upgrade --dev - pio pkg update --global + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio - - name: Build - run: | - pio run --environment bhaptics_tactsuit_x40 + - name: Build target + run: pio run ${{ matrix.target && format('-e {0}', matrix.target) || '' }} - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: - category: "/language:${{matrix.language}}" + category: "/language:cpp" semgrep: name: Semgrep diff --git a/platformio.ini b/platformio.ini index 49beda78..d3c4aa2c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,7 +39,7 @@ build_src_filter = lib_deps = https://github.com/senseshift/frozen.git#feature/platformio https://github.com/senseshift/i2cdevlib-contrib.git#8db7eab29dd01385928c6a99938ed0a953a5acf3 - https://github.com/senseshift/arduino-ble-serial.git#v1.1.2 + senseshift/Serial_BLE @ ^1.1.2 https://github.com/senseshift/opengloves-lib.git#master [env] From b2935a35ac821ecc750a37e6aec4d9bdb0b1bc74 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Mon, 5 Aug 2024 22:23:50 +0400 Subject: [PATCH 55/67] build: add custom `release-archive` target --- .github/scripts/create-release-archive.py | 31 --------------- .github/workflows/release.yml | 43 ++++---------------- platformio.ini | 5 ++- scripts/extra_scripts.py | 9 +++++ scripts/targets/create-release-archive.py | 48 +++++++++++++++++++++++ scripts/test-cover.sh | 13 ------ 6 files changed, 69 insertions(+), 80 deletions(-) delete mode 100644 .github/scripts/create-release-archive.py create mode 100644 scripts/extra_scripts.py create mode 100644 scripts/targets/create-release-archive.py delete mode 100755 scripts/test-cover.sh diff --git a/.github/scripts/create-release-archive.py b/.github/scripts/create-release-archive.py deleted file mode 100644 index 7643e03e..00000000 --- a/.github/scripts/create-release-archive.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -import sys -from os import getcwd -from ntpath import basename -from zipfile import ZipFile -import json - -n = 2 -partitions_arg = sys.argv[1:] -partitions = final = [partitions_arg[i * n:(i + 1) * n] for i in range((len(partitions_arg) + n - 1) // n)] - -path = 'build/firmware.zip' -with ZipFile(path, 'w') as archive: - print('Creating "' + archive.filename + '"', end='\n') - parts = [] - - for [offset, path] in partitions: - filename = basename(path) - archive.write(path, filename) - partition = { - 'path': filename, - 'offset': int(offset, 16), - } - parts.append(partition) - - manifest = { - 'chipFamily': 'ESP32', - 'parts': parts, - } - archive.writestr('manifest.json', json.dumps(manifest)) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7b87191f..99736c8e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,30 +74,17 @@ jobs: run: | pio pkg install -e ${{matrix.target}} - - name: Update build command (non-Windows) - run: | - sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini - sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/.github\/scripts\/create-release-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - - name: Build run: | - mkdir build - - echo "::group::platformio.ini" - cat platformio.ini - echo "::endgroup::" + pio run --environment ${{matrix.target}} --target release-archive - echo "::group::pio run" - pio run --environment ${{matrix.target}} --target upload - echo "::endgroup::" - - unzip -l ./build/firmware.zip + unzip -l ./.pio/build/${{ matrix.target }}/firmware.zip - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: firmware-${{matrix.target}} - path: ./build/firmware.zip + path: ./.pio/build/${{ matrix.target }}/firmware.zip retention-days: 5 - name: Upload binaries to release @@ -105,7 +92,7 @@ jobs: if: startsWith(github.ref, 'refs/tags/') && github.repository == 'senseshift/senseshift-firmware' with: asset_name: ${{matrix.target}}.zip - file: ./build/firmware.zip + file: ./.pio/build/${{ matrix.target }}/firmware.zip tag: ${{github.ref}} build-opengloves: @@ -161,30 +148,16 @@ jobs: run: | pio pkg install -e ${{matrix.target}} - - name: Update build command (non-Windows) - run: | - sed -i '/\[env\]/p; s/\[env\]/upload_protocol = custom/' platformio.ini - sed -i '/\[env\]/p; s/\[env\]/upload_command = \$PYTHONEXE .\/.github\/scripts\/create-release-archive.py \$FLASH_EXTRA_IMAGES \$ESP32_APP_OFFSET \$SOURCE/' platformio.ini - - name: Build run: | - mkdir build - - echo "::group::platformio.ini" - cat platformio.ini - echo "::endgroup::" - - echo "::group::pio run" - pio run --environment ${{matrix.target}} --target upload - echo "::endgroup::" - - unzip -l ./build/firmware.zip + pio run --environment ${{matrix.target}} --target release-archive + unzip -l ./.pio/build/${{ matrix.target }}/firmware.zip - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: firmware-${{ steps.firmware_name.outputs.firmware }} - path: ./build/firmware.zip + path: ./.pio/build/${{ matrix.target }}/firmware.zip retention-days: 5 - name: Upload binaries to release @@ -192,5 +165,5 @@ jobs: if: startsWith(github.ref, 'refs/tags/') && github.repository == 'senseshift/senseshift-firmware' with: asset_name: ${{ steps.firmware_name.outputs.firmware }}.zip - file: ./build/firmware.zip + file: ./.pio/build/${{ matrix.target }}/firmware.zip tag: ${{github.ref}} diff --git a/platformio.ini b/platformio.ini index d3c4aa2c..77dabb14 100644 --- a/platformio.ini +++ b/platformio.ini @@ -39,10 +39,13 @@ build_src_filter = lib_deps = https://github.com/senseshift/frozen.git#feature/platformio https://github.com/senseshift/i2cdevlib-contrib.git#8db7eab29dd01385928c6a99938ed0a953a5acf3 - senseshift/Serial_BLE @ ^1.1.2 https://github.com/senseshift/opengloves-lib.git#master + senseshift/Serial_BLE @ ^1.1.2 + etlcpp/Embedded Template Library@^20.38.11 [env] +extra_scripts = ./scripts/extra_scripts.py + build_flags = ${common.build_flags} build_unflags = ${common.build_unflags} build_src_filter = ${common.build_src_filter} diff --git a/scripts/extra_scripts.py b/scripts/extra_scripts.py new file mode 100644 index 00000000..9a633068 --- /dev/null +++ b/scripts/extra_scripts.py @@ -0,0 +1,9 @@ +Import("env") + +env.AddCustomTarget( + name="release-archive", + dependencies="$BUILD_DIR/${PROGNAME}.elf", + actions=[ + "$PYTHONEXE ./scripts/targets/create-release-archive.py $BUILD_DIR/${PROGNAME}.zip $FLASH_EXTRA_IMAGES $ESP32_APP_OFFSET $SOURCE", + ] +) diff --git a/scripts/targets/create-release-archive.py b/scripts/targets/create-release-archive.py new file mode 100644 index 00000000..1e0bf7e8 --- /dev/null +++ b/scripts/targets/create-release-archive.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +import argparse +from os import getcwd +from ntpath import basename +from zipfile import ZipFile +import json + + +def parse_args(): + parser = argparse.ArgumentParser(description='Create a firmware zip file with a manifest.') + parser.add_argument('target', type=str) + parser.add_argument('partitions', metavar='N', type=str, nargs='+', + help='List of partitions in the format ') + return parser.parse_args() + + +def main(): + args = parse_args() + + n = 2 + partitions_arg = args.partitions + partitions = [partitions_arg[i * n:(i + 1) * n] for i in range((len(partitions_arg) + n - 1) // n)] + + path = args.target + + with ZipFile(path, 'w') as archive: + print(f'Creating "{archive.filename}"', end='\n') + parts = [] + + for offset, path in partitions: + filename = basename(path) + archive.write(path, filename) + partition = { + 'path': filename, + 'offset': int(offset, 16), + } + parts.append(partition) + + manifest = { + 'chipFamily': 'ESP32', + 'parts': parts, + } + archive.writestr('manifest.json', json.dumps(manifest)) + + +if __name__ == '__main__': + main() diff --git a/scripts/test-cover.sh b/scripts/test-cover.sh deleted file mode 100755 index d15330f7..00000000 --- a/scripts/test-cover.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -euxo pipefail - -build_dir=$1 -env=$2 -shift 2 - -# Run tests -$@ - -lcov -d $build_dir/$env/ -c -o lcov.info -lcov --remove lcov.info '/usr/include/*' '*.platformio/*' '*.pio/*' '*/tool-unity/*' '*/test/*' '*/MockArduino/*' -o lcov.info.cleaned -genhtml -p $PWD -o build/coverage/ --demangle-cpp lcov.info.cleaned From 09cfc4896eb71590f9e4613318ee6209bbbfff28 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Wed, 7 Aug 2024 21:06:31 +0400 Subject: [PATCH 56/67] build: refactor PlatformIO bHaptics configuration --- arch/esp32/esp32.ini | 19 ++ firmware/firmware.cpp | 28 -- include/config/all.h | 2 +- include/config/bhaptics.h | 5 +- ini/bhaptics.ini | 297 ------------------ platformio.ini | 75 ++--- variants/bhaptics/bhaptics.ini | 28 ++ .../bhaptics/tactal}/tactal.cpp | 24 +- variants/bhaptics/tactal/tactal.ini | 12 + .../bhaptics/tactglove}/tactglove.cpp | 24 +- variants/bhaptics/tactglove/tactglove.ini | 27 ++ .../bhaptics/tactosy2}/tactosy2.cpp | 24 +- variants/bhaptics/tactosy2/tactosy2.ini | 25 ++ .../bhaptics/tactosyf}/tactosyf.cpp | 24 +- variants/bhaptics/tactosyf/tactosyf.ini | 25 ++ .../bhaptics/tactosyh}/tactosyh.cpp | 24 +- variants/bhaptics/tactosyh/tactosyh.ini | 25 ++ .../bhaptics/tactsuit_x16}/tactsuit_x16.cpp | 26 +- .../bhaptics/tactsuit_x16/tactsuit_x16.ini | 12 + .../tactsuit_x16_pca9685.cpp | 30 +- .../tactsuit_x16_pca9685.ini | 12 + .../bhaptics/tactsuit_x40}/tactsuit_x40.cpp | 32 +- .../bhaptics/tactsuit_x40/tactsuit_x40.ini | 12 + .../bhaptics/tactvisor}/tactvisor.cpp | 24 +- variants/bhaptics/tactvisor/tactvisor.ini | 12 + 25 files changed, 368 insertions(+), 480 deletions(-) create mode 100644 arch/esp32/esp32.ini delete mode 100644 firmware/firmware.cpp delete mode 100644 ini/bhaptics.ini create mode 100644 variants/bhaptics/bhaptics.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactal}/tactal.cpp (84%) create mode 100644 variants/bhaptics/tactal/tactal.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactglove}/tactglove.cpp (85%) create mode 100644 variants/bhaptics/tactglove/tactglove.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactosy2}/tactosy2.cpp (84%) create mode 100644 variants/bhaptics/tactosy2/tactosy2.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactosyf}/tactosyf.cpp (84%) create mode 100644 variants/bhaptics/tactosyf/tactosyf.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactosyh}/tactosyh.cpp (84%) create mode 100644 variants/bhaptics/tactosyh/tactosyh.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactsuit_x16}/tactsuit_x16.cpp (86%) create mode 100644 variants/bhaptics/tactsuit_x16/tactsuit_x16.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactsuit_x16_pca9685}/tactsuit_x16_pca9685.cpp (87%) create mode 100644 variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactsuit_x40}/tactsuit_x40.cpp (89%) create mode 100644 variants/bhaptics/tactsuit_x40/tactsuit_x40.ini rename {firmware/mode_configs/bhaptics => variants/bhaptics/tactvisor}/tactvisor.cpp (84%) create mode 100644 variants/bhaptics/tactvisor/tactvisor.ini diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini new file mode 100644 index 00000000..be9aecfa --- /dev/null +++ b/arch/esp32/esp32.ini @@ -0,0 +1,19 @@ +[arch:esp32] +platform = platformio/espressif32@^6.8.1 +platform_packages = + toolchain-xtensa-esp32@12.2.0+20230208 + framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 + framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip + +build_flags = + -D SS_USE_NIMBLE=true + -D SOC_WIFI_SUPPORTED=1 +; -D CORE_DEBUG_LEVEL=3 +; -D DEBUG_MODE=0 +; -D DEBUG_ESP_PORT=Serial +build_unflags = + +lib_deps = +lib_ignore = + segger_rtt + ESP32 BLE Arduino diff --git a/firmware/firmware.cpp b/firmware/firmware.cpp deleted file mode 100644 index 258921f2..00000000 --- a/firmware/firmware.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "senseshift.h" - -#if defined(ARDUINO) -#include -#endif // ARDUINO - -#ifndef PIO_UNIT_TESTING - -extern void setupMode(); -extern void loopMode(); - -#if defined(ARDUINO) - -SenseShift::Application App; - -void setup() -{ - setupMode(); -} - -void loop() -{ - loopMode(); -} - -#endif // ARDUINO - -#endif // PIO_UNIT_TESTING diff --git a/include/config/all.h b/include/config/all.h index 46c9d0b0..970c80d5 100644 --- a/include/config/all.h +++ b/include/config/all.h @@ -7,6 +7,6 @@ #include "config/bluetooth.h" -#ifdef BHAPTICS +#ifdef SS_BHAPTICS #include "config/bhaptics.h" #endif diff --git a/include/config/bhaptics.h b/include/config/bhaptics.h index 009dd457..5cd12d9b 100644 --- a/include/config/bhaptics.h +++ b/include/config/bhaptics.h @@ -1,6 +1,6 @@ #pragma once -#ifdef BHAPTICS +#ifdef SS_BHAPTICS #include "config/bluetooth.h" @@ -9,10 +9,11 @@ #endif #ifndef BH_SERIAL_NUMBER +// 76b5-e8e7-835d-8b71-381c #define BH_SERIAL_NUMBER \ { \ 0x76, 0xbd, 0xe8, 0xe7, 0x83, 0x5d, 0x8b, 0x71, 0x38, 0x1c \ - } // 76b5-e8e7-835d-8b71-381c + } #endif #endif diff --git a/ini/bhaptics.ini b/ini/bhaptics.ini deleted file mode 100644 index dc2683a2..00000000 --- a/ini/bhaptics.ini +++ /dev/null @@ -1,297 +0,0 @@ -[bhaptics] -platform = platformio/espressif32@^6.8.1 -platform_packages = - toolchain-xtensa-esp32@12.2.0+20230208 - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 - framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip -framework = arduino -board = esp32doit-devkit-v1 -upload_speed = 921600 -monitor_speed = 115200 - -build_flags = - ${common.build_flags} - -D BHAPTICS -build_unflags = ${common.build_unflags} -build_src_filter = ${common.build_src_filter} -lib_deps = ${common.lib_deps} - -[env:bhaptics_tactsuit_x16] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTSUITX16 - -D BH_BLE_APPEARANCE=510 - '-D BLUETOOTH_NAME="TactSuitX16"' - '-D BH_SERIAL_NUMBER={ 0x0d, 0x3a, 0xeb, 0x77, 0xbe, 0xf8, 0x7a, 0x1e, 0x3b, 0x2a }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactsuit_x16_pca9685] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTSUITX16 - -D BH_BLE_APPEARANCE=510 - '-D BLUETOOTH_NAME="TactSuitX16"' - '-D BH_SERIAL_NUMBER={ 0x0d, 0x3a, 0xeb, 0x77, 0xbe, 0xf8, 0x7a, 0x1e, 0x3b, 0x2a }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactsuit_x40] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTSUITX40 - -D BH_BLE_APPEARANCE=509 - '-D BLUETOOTH_NAME="TactSuitX40"' - '-D BH_SERIAL_NUMBER={ 0xcf, 0xcb, 0x0d, 0x95, 0x5f, 0xf6, 0xee, 0x2c, 0xbd, 0x73 }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -; [env:bhaptics_tactbelt] -; platform = ${bhaptics.platform} -; platform_packages = ${bhaptics.platform_packages} -; framework = ${bhaptics.framework} -; board = ${bhaptics.board} -; upload_speed = ${bhaptics.upload_speed} -; monitor_speed = ${bhaptics.monitor_speed} - -; build_flags = ${bhaptics.build_flags} -; -D BH_DEVICE_TACTOSY2 -; -D BH_BLE_APPEARANCE=508 -; '-D BLUETOOTH_NAME="TactBelt"' -; '-D BH_SERIAL_NUMBER={ 0x86, 0x4b, 0x19, 0xe9, 0x66, 0xab, 0x53, 0xb0, 0xc7, 0xd3 }' -; build_unflags = ${bhaptics.build_unflags} -; build_src_filter = ${bhaptics.build_src_filter} -; + -; lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactosy2_forearm_left] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTOSY2 - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="Tactosy2_L"' - '-D BH_SERIAL_NUMBER={ 0xa0, 0xba, 0x0a, 0xd1, 0xbf, 0x36, 0x11, 0x30, 0xa4, 0xff }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactosy2_forearm_right] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTOSY2 - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="Tactosy2_R"' - '-D BH_SERIAL_NUMBER={ 0xb0, 0x1c, 0xc1, 0xf8, 0xec, 0x12, 0x18, 0x4e, 0x09, 0x77 }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactosyh_hand_left] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTOSYH - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactosyH_L"' - '-D BH_SERIAL_NUMBER={ 0xc1, 0x36, 0xdc, 0x21, 0xc9, 0xd4, 0x17, 0x85, 0xbb, 0x90 }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactosyh_hand_right] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTOSYH - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactosyH_R"' - '-D BH_SERIAL_NUMBER={ 0xc7, 0x5f, 0x3b, 0x06, 0x38, 0xba, 0x34, 0xfa, 0x36, 0xc1 }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactosyf_foot_left] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTOSYF - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactosyF_L"' - '-D BH_SERIAL_NUMBER={ 0x1a, 0x45, 0x83, 0x44, 0x03, 0xc5, 0xf3, 0xc3, 0xf3, 0xb8 }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactosyf_foot_right] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTOSYF - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactosyF_R"' - '-D BH_SERIAL_NUMBER={ 0x14, 0xb9, 0x02, 0x62, 0x41, 0xe4, 0x04, 0xb2, 0xc5, 0x11 }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactal] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTAL - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="Tactal_"' - '-D BH_SERIAL_NUMBER={ 0xed, 0xcb, 0x55, 0x7c, 0xd7, 0xb9, 0x16, 0xc5, 0x18, 0x2a }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactvisor] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTAL - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactVisor_V____"' - '-D BH_SERIAL_NUMBER={ 0x5e, 0xa3, 0xdd, 0x12, 0x00, 0x01, 0x43, 0xc1, 0x26, 0x8a }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactglove_left] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTGLOVE - -D SS_HAND_SIDE=Left - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactGlove (L"' - '-D BH_SERIAL_NUMBER={ 0xcd, 0x0b, 0x81, 0x45, 0x85, 0xf9, 0x2b, 0x6c, 0xed, 0x5b }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} - -[env:bhaptics_tactglove_right] -platform = ${bhaptics.platform} -platform_packages = ${bhaptics.platform_packages} -framework = ${bhaptics.framework} -board = ${bhaptics.board} -upload_speed = ${bhaptics.upload_speed} -monitor_speed = ${bhaptics.monitor_speed} - -build_flags = - ${bhaptics.build_flags} - -D BH_DEVICE_TACTGLOVE - -D SS_HAND_SIDE=Right - -D BH_BLE_APPEARANCE=508 - '-D BLUETOOTH_NAME="TactGlove (R"' - '-D BH_SERIAL_NUMBER={ 0x12, 0x0b, 0xae, 0xbf, 0xbc, 0x90, 0x3b, 0x0d, 0x84, 0xdd }' -build_unflags = ${bhaptics.build_unflags} -build_src_filter = - ${bhaptics.build_src_filter} - + -lib_deps = ${bhaptics.lib_deps} diff --git a/platformio.ini b/platformio.ini index 77dabb14..f7141e12 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,68 +9,71 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -description = Open Source Haptic-feedback device firmware -lib_dir = ./lib -src_dir = ./firmware +default_envs = bhaptics_tactsuit_x40 + +description = Open Source Haptic-feedback device firmware + +lib_dir = ./lib +src_dir = ./firmware + extra_configs = - ini/bhaptics.ini - ini/opengloves.ini - ini/opengloves-lucidgloves.ini - ini/opengloves-indexer.ini -default_envs = bhaptics_tactsuit_x16, bhaptics_tactal, bhaptics_tactglove_left, lucidgloves-prototype3 + variants/**/*.ini + arch/**/*.ini + +[env] +extra_scripts = ./scripts/extra_scripts.py + +upload_speed = 921600 +monitor_speed = 115200 -[common] build_unflags = -std=gnu++11 -build_flags = +build_flags = -std=gnu++17 -D __OH_FIRMWARE__ - -D CORE_DEBUG_LEVEL=3 -; -D DEBUG_MODE=0 -; -D DEBUG_ESP_PORT=Serial -; -D SS_BATTERY_ENABLED=true - -D SS_USE_NIMBLE=true - -D SOC_WIFI_SUPPORTED=1 build_src_filter = +<*> - -lib_deps = +lib_ldf_mode = deep+ +lib_deps = https://github.com/senseshift/frozen.git#feature/platformio https://github.com/senseshift/i2cdevlib-contrib.git#8db7eab29dd01385928c6a99938ed0a953a5acf3 https://github.com/senseshift/opengloves-lib.git#master - senseshift/Serial_BLE @ ^1.1.2 etlcpp/Embedded Template Library@^20.38.11 -[env] -extra_scripts = ./scripts/extra_scripts.py - -build_flags = ${common.build_flags} -build_unflags = ${common.build_unflags} -build_src_filter = ${common.build_src_filter} -lib_deps = ${common.lib_deps} -lib_ldf_mode = deep+ - -check_tool = clangtidy +check_tool = clangtidy +check_skip_packages = yes check_flags = clangtidy: --config-file=./.clang-tidy --fix -debug_build_flags = -Os +[base:arduino] +framework = arduino + +build_unflags = +build_flags = + +lib_deps = + senseshift/Serial_BLE @ ^1.1.2 +lib_ignore = [env:native] platform = native -build_unflags = ${common.build_unflags} -build_flags = - ${common.build_flags} +build_unflags = + ${env.build_unflags} +build_flags = + ${env.build_flags} -lgcov --coverage + build_src_filter = - ${common.build_src_filter} + ${env.build_src_filter} + -lib_deps = - ${common.lib_deps} + +lib_deps = fabiobatsilva/ArduinoFake@^0.4 -test_ignore = test_embedded +test_ignore = + test_embedded diff --git a/variants/bhaptics/bhaptics.ini b/variants/bhaptics/bhaptics.ini new file mode 100644 index 00000000..c8796192 --- /dev/null +++ b/variants/bhaptics/bhaptics.ini @@ -0,0 +1,28 @@ +[base:bhaptics] +platform = ${arch:esp32.platform} +platform_packages = + ${arch:esp32.platform_packages} + +framework = ${base:arduino.framework} + +board = esp32dev + +build_unflags = + ${env.build_unflags} + ${arch:esp32.build_unflags} + ${base:arduino.build_unflags} +build_flags = + ${env.build_flags} + ${arch:esp32.build_flags} + ${base:arduino.build_flags} + -D SS_BHAPTICS=true +; -D SS_BATTERY_ENABLED=true + +lib_deps = + ${env.lib_deps} + ${arch:esp32.lib_deps} + ${base:arduino.lib_deps} +lib_ignore = + ${env.lib_ignore} + ${arch:esp32.lib_ignore} + ${base:arduino.lib_ignore} diff --git a/firmware/mode_configs/bhaptics/tactal.cpp b/variants/bhaptics/tactal/tactal.cpp similarity index 84% rename from firmware/mode_configs/bhaptics/tactal.cpp rename to variants/bhaptics/tactal/tactal.cpp index affade5e..fcd88e78 100644 --- a/firmware/mode_configs/bhaptics/tactal.cpp +++ b/variants/bhaptics/tactal/tactal.cpp @@ -4,15 +4,15 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -24,12 +24,12 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTAL }; -void setupMode() +void setup() { // Configure PWM pins to their positions on the face const auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ @@ -38,7 +38,7 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::FaceFront, new FloatPlane_Closest(faceOutputs)); + app->getVibroBody()->addTarget(Target::FaceFront, new FloatPlane(faceOutputs)); app->getVibroBody()->setup(); @@ -76,7 +76,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactal/tactal.ini b/variants/bhaptics/tactal/tactal.ini new file mode 100644 index 00000000..6d6e2877 --- /dev/null +++ b/variants/bhaptics/tactal/tactal.ini @@ -0,0 +1,12 @@ +[env:bhaptics_tactal] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="Tactal_"' + '-D BH_SERIAL_NUMBER={ 0xed, 0xcb, 0x55, 0x7c, 0xd7, 0xb9, 0x16, 0xc5, 0x18, 0x2a }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactal> diff --git a/firmware/mode_configs/bhaptics/tactglove.cpp b/variants/bhaptics/tactglove/tactglove.cpp similarity index 85% rename from firmware/mode_configs/bhaptics/tactglove.cpp rename to variants/bhaptics/tactglove/tactglove.cpp index 6f48863b..4ce21e57 100644 --- a/firmware/mode_configs/bhaptics/tactglove.cpp +++ b/variants/bhaptics/tactglove/tactglove.cpp @@ -4,16 +4,16 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" +#include "senseshift/utility.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -25,7 +25,7 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static constexpr Body::Hands::HandSide handSide = Body::Hands::HandSide::SS_HAND_SIDE; @@ -33,7 +33,7 @@ static constexpr Body::Hands::HandSide handSide = Body::Hands::HandSide::SS_HAND static const auto& bhLayout = handSide == Body::Hands::HandSide::Left ? BH::TactGloveLeftLayout : BH::TactGloveRightLayout; // clang-format on -void setupMode() +void setup() { // Configure PWM pins to their positions on the glove // Replace `new PWMOutputWriter(...)` with `nullptr` to disable a specific actuator @@ -84,7 +84,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactglove/tactglove.ini b/variants/bhaptics/tactglove/tactglove.ini new file mode 100644 index 00000000..81397cee --- /dev/null +++ b/variants/bhaptics/tactglove/tactglove.ini @@ -0,0 +1,27 @@ +[env:bhaptics_tactglove_left] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D SS_HAND_SIDE=Left + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="TactGlove (L"' + '-D BH_SERIAL_NUMBER={ 0xcd, 0x0b, 0x81, 0x45, 0x85, 0xf9, 0x2b, 0x6c, 0xed, 0x5b }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactal> + +[env:bhaptics_tactglove_right] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D SS_HAND_SIDE=Right + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="TactGlove (R"' + '-D BH_SERIAL_NUMBER={ 0x12, 0x0b, 0xae, 0xbf, 0xbc, 0x90, 0x3b, 0x0d, 0x84, 0xdd }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactglove> diff --git a/firmware/mode_configs/bhaptics/tactosy2.cpp b/variants/bhaptics/tactosy2/tactosy2.cpp similarity index 84% rename from firmware/mode_configs/bhaptics/tactosy2.cpp rename to variants/bhaptics/tactosy2/tactosy2.cpp index 90945d98..84c5b31e 100644 --- a/firmware/mode_configs/bhaptics/tactosy2.cpp +++ b/variants/bhaptics/tactosy2/tactosy2.cpp @@ -4,15 +4,15 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -24,12 +24,12 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTOSY2 }; -void setupMode() +void setup() { // Configure PWM pins to their positions on the forearm auto forearmOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ @@ -39,7 +39,7 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane_Closest(forearmOutputs)); + app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane(forearmOutputs)); app->getVibroBody()->setup(); @@ -77,7 +77,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactosy2/tactosy2.ini b/variants/bhaptics/tactosy2/tactosy2.ini new file mode 100644 index 00000000..8b33b8e3 --- /dev/null +++ b/variants/bhaptics/tactosy2/tactosy2.ini @@ -0,0 +1,25 @@ +[env:bhaptics_tactosy2_forearm_left] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="Tactosy2_L"' + '-D BH_SERIAL_NUMBER={ 0xa0, 0xba, 0x0a, 0xd1, 0xbf, 0x36, 0x11, 0x30, 0xa4, 0xff }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactosy2> + +[env:bhaptics_tactosy2_forearm_right] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="Tactosy2_R"' + '-D BH_SERIAL_NUMBER={ 0xb0, 0x1c, 0xc1, 0xf8, 0xec, 0x12, 0x18, 0x4e, 0x09, 0x77 }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactosy2> diff --git a/firmware/mode_configs/bhaptics/tactosyf.cpp b/variants/bhaptics/tactosyf/tactosyf.cpp similarity index 84% rename from firmware/mode_configs/bhaptics/tactosyf.cpp rename to variants/bhaptics/tactosyf/tactosyf.cpp index 3e6eab0d..2e5c28c1 100644 --- a/firmware/mode_configs/bhaptics/tactosyf.cpp +++ b/variants/bhaptics/tactosyf/tactosyf.cpp @@ -4,15 +4,15 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -24,12 +24,12 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTOSYF }; -void setupMode() +void setup() { // Configure PWM pins to their positions on the feet auto footOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ @@ -40,7 +40,7 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane_Closest(footOutputs)); + app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane(footOutputs)); app->getVibroBody()->setup(); @@ -78,7 +78,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactosyf/tactosyf.ini b/variants/bhaptics/tactosyf/tactosyf.ini new file mode 100644 index 00000000..ad34f29c --- /dev/null +++ b/variants/bhaptics/tactosyf/tactosyf.ini @@ -0,0 +1,25 @@ +[env:bhaptics_tactosyf_foot_left] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="TactosyF_L"' + '-D BH_SERIAL_NUMBER={ 0x1a, 0x45, 0x83, 0x44, 0x03, 0xc5, 0xf3, 0xc3, 0xf3, 0xb8 }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactosyf> + +[env:bhaptics_tactosyf_foot_right] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="TactosyF_R"' + '-D BH_SERIAL_NUMBER={ 0x14, 0xb9, 0x02, 0x62, 0x41, 0xe4, 0x04, 0xb2, 0xc5, 0x11 }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactosyf> diff --git a/firmware/mode_configs/bhaptics/tactosyh.cpp b/variants/bhaptics/tactosyh/tactosyh.cpp similarity index 84% rename from firmware/mode_configs/bhaptics/tactosyh.cpp rename to variants/bhaptics/tactosyh/tactosyh.cpp index 5919df49..511c10fc 100644 --- a/firmware/mode_configs/bhaptics/tactosyh.cpp +++ b/variants/bhaptics/tactosyh/tactosyh.cpp @@ -4,15 +4,15 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -24,12 +24,12 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTOSYH }; -void setupMode() +void setup() { // Configure PWM pins to their positions on the hands auto handOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ @@ -40,7 +40,7 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane_Closest(handOutputs)); + app->getVibroBody()->addTarget(Target::Accessory, new FloatPlane(handOutputs)); app->getVibroBody()->setup(); @@ -78,7 +78,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactosyh/tactosyh.ini b/variants/bhaptics/tactosyh/tactosyh.ini new file mode 100644 index 00000000..d835f82d --- /dev/null +++ b/variants/bhaptics/tactosyh/tactosyh.ini @@ -0,0 +1,25 @@ +[env:bhaptics_tactosyh_hand_left] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="TactosyH_L"' + '-D BH_SERIAL_NUMBER={ 0xc1, 0x36, 0xdc, 0x21, 0xc9, 0xd4, 0x17, 0x85, 0xbb, 0x90 }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactosyh> + +[env:bhaptics_tactosyh_hand_right] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="TactosyH_R"' + '-D BH_SERIAL_NUMBER={ 0xc7, 0x5f, 0x3b, 0x06, 0x38, 0xba, 0x34, 0xfa, 0x36, 0xc1 }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactosyh> diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp b/variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp similarity index 86% rename from firmware/mode_configs/bhaptics/tactsuit_x16.cpp rename to variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp index 91b1e20b..003a391f 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16.cpp +++ b/variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp @@ -4,15 +4,15 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -24,7 +24,7 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTSUITX16 }; @@ -32,7 +32,7 @@ static const std::array bhLayout = { B // Ouput indices, responsible for x40 => x16 grouping static const std::array layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; -void setupMode() +void setup() { // Configure PWM pins to their positions on the vest auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ @@ -48,8 +48,8 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); - app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); + app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane(frontOutputs)); + app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane(backOutputs)); app->getVibroBody()->setup(); @@ -87,7 +87,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactsuit_x16/tactsuit_x16.ini b/variants/bhaptics/tactsuit_x16/tactsuit_x16.ini new file mode 100644 index 00000000..d3c4c3b8 --- /dev/null +++ b/variants/bhaptics/tactsuit_x16/tactsuit_x16.ini @@ -0,0 +1,12 @@ +[env:bhaptics_tactsuit_x16] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=510 + '-D BLUETOOTH_NAME="TactSuitX16"' + '-D BH_SERIAL_NUMBER={ 0x0d, 0x3a, 0xeb, 0x77, 0xbe, 0xf8, 0x7a, 0x1e, 0x3b, 0x2a }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactsuit_x16> diff --git a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp b/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp similarity index 87% rename from firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp rename to variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp index 601e4f27..12d47bb0 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x16_pca9685.cpp +++ b/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp @@ -4,18 +4,18 @@ #include #include -#include -#include +#include "I2CDevLib.h" +#include "i2cdev/pca9685.hpp" -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" +#include "senseshift/output/i2cdevlib_pwm.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -27,7 +27,7 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTSUITX16 }; @@ -35,7 +35,7 @@ static const std::array bhLayout = { B // Ouput indices, responsible for x40 => x16 grouping static const std::array layoutGroups = BH_LAYOUT_TACTSUITX16_GROUPS; -void setupMode() +void setup() { Wire.begin(); @@ -62,8 +62,8 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); - app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); + app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane(frontOutputs)); + app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane(backOutputs)); app->getVibroBody()->setup(); @@ -101,7 +101,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.ini b/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.ini new file mode 100644 index 00000000..b1d09315 --- /dev/null +++ b/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.ini @@ -0,0 +1,12 @@ +[env:bhaptics_tactsuit_x16_pca9685] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=510 + '-D BLUETOOTH_NAME="TactSuitX16"' + '-D BH_SERIAL_NUMBER={ 0x0d, 0x3a, 0xeb, 0x77, 0xbe, 0xf8, 0x7a, 0x1e, 0x3b, 0x2a }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactsuit_x16_pca9685> diff --git a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp b/variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp similarity index 89% rename from firmware/mode_configs/bhaptics/tactsuit_x40.cpp rename to variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp index 89aaff3b..c2958512 100644 --- a/firmware/mode_configs/bhaptics/tactsuit_x40.cpp +++ b/variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp @@ -4,19 +4,19 @@ #include #include -#include -#include +#include "I2CDevLib.h" +#include "i2cdev/pca9685.hpp" -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" +#include "senseshift/output/i2cdevlib_pwm.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -29,12 +29,12 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTSUITX40 }; -void setupMode() +void setup() { Wire.begin(); @@ -76,8 +76,8 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs)); - app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs)); + app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane(frontOutputs)); + app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane(backOutputs)); app->getVibroBody()->setup(); @@ -129,7 +129,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactsuit_x40/tactsuit_x40.ini b/variants/bhaptics/tactsuit_x40/tactsuit_x40.ini new file mode 100644 index 00000000..0cec74f0 --- /dev/null +++ b/variants/bhaptics/tactsuit_x40/tactsuit_x40.ini @@ -0,0 +1,12 @@ +[env:bhaptics_tactsuit_x40] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=509 + '-D BLUETOOTH_NAME="TactSuitX40"' + '-D BH_SERIAL_NUMBER={ 0xcf, 0xcb, 0x0d, 0x95, 0x5f, 0xf6, 0xee, 0x2c, 0xbd, 0x73 }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactsuit_x40> diff --git a/firmware/mode_configs/bhaptics/tactvisor.cpp b/variants/bhaptics/tactvisor/tactvisor.cpp similarity index 84% rename from firmware/mode_configs/bhaptics/tactvisor.cpp rename to variants/bhaptics/tactvisor/tactvisor.cpp index ac662907..e5cb6e56 100644 --- a/firmware/mode_configs/bhaptics/tactvisor.cpp +++ b/variants/bhaptics/tactvisor/tactvisor.cpp @@ -4,15 +4,15 @@ #include #include -#include +#include "senseshift.h" -#include -#include -#include -#include -#include -#include -#include +#include "senseshift/arduino/input/sensor/analog.hpp" +#include "senseshift/arduino/output/ledc.hpp" +#include "senseshift/battery/input/battery_sensor.hpp" +#include "senseshift/bh/ble/connection.hpp" +#include "senseshift/bh/devices.hpp" +#include "senseshift/bh/encoding.hpp" +#include "senseshift/freertos/task.hpp" using namespace SenseShift; using namespace SenseShift::Input; @@ -24,12 +24,12 @@ using namespace SenseShift::Battery::Input; using namespace SenseShift::BH; using namespace SenseShift::Body::Haptics; -extern Application App; +Application App; Application* app = &App; static const std::array bhLayout = { BH_LAYOUT_TACTVISOR }; -void setupMode() +void setup() { // Configure PWM pins to their positions on the face auto faceOutputs = PlaneMapper_Margin::mapMatrixCoordinates({ @@ -38,7 +38,7 @@ void setupMode() // clang-format on }); - app->getVibroBody()->addTarget(Target::FaceFront, new FloatPlane_Closest(faceOutputs)); + app->getVibroBody()->addTarget(Target::FaceFront, new FloatPlane(faceOutputs)); app->getVibroBody()->setup(); @@ -76,7 +76,7 @@ void setupMode() #endif } -void loopMode() +void loop() { // Free up the Arduino loop task vTaskDelete(NULL); diff --git a/variants/bhaptics/tactvisor/tactvisor.ini b/variants/bhaptics/tactvisor/tactvisor.ini new file mode 100644 index 00000000..ce568fe8 --- /dev/null +++ b/variants/bhaptics/tactvisor/tactvisor.ini @@ -0,0 +1,12 @@ +[env:bhaptics_tactvisor] +extends = base:bhaptics + +build_flags = + ${base:bhaptics.build_flags} + -D BH_BLE_APPEARANCE=508 + '-D BLUETOOTH_NAME="Tactal_"' + '-D BH_SERIAL_NUMBER={ 0xed, 0xcb, 0x55, 0x7c, 0xd7, 0xb9, 0x16, 0xc5, 0x18, 0x2a }' + +build_src_filter = + ${env.build_src_filter} + +<../variants/bhaptics/tactvisor> From 558374ea84fc1b89cc4c9d298dff35f83cee10b6 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 11:42:52 +0400 Subject: [PATCH 57/67] build: refactor PlatformIO OpenGloves configuration --- .github/workflows/ci.yml | 28 +-- .github/workflows/lint.yml | 1 + .github/workflows/release.yml | 14 +- .github/workflows/sast.yml | 4 +- .../lucidgloves-prototype3+serial/wokwi.toml | 6 - .../lucidgloves-prototype4+serial/wokwi.toml | 6 - .../diagram.json | 0 .../test.yaml | 0 .../wokwi.toml | 6 + .../diagram.json | 0 .../test.yaml | 0 .../wokwi.toml | 6 + ini/opengloves-indexer.ini | 185 ------------------ ini/opengloves-lucidgloves.ini | 126 ------------ platformio.ini | 2 +- variants/opengloves/indexer.ini | 169 ++++++++++++++++ variants/opengloves/lucidgloves.ini | 124 ++++++++++++ .../opengloves/opengloves.cpp | 12 +- {ini => variants/opengloves}/opengloves.ini | 41 ++-- 19 files changed, 352 insertions(+), 378 deletions(-) delete mode 100644 .wokwi/lucidgloves-prototype3+serial/wokwi.toml delete mode 100644 .wokwi/lucidgloves-prototype4+serial/wokwi.toml rename .wokwi/{lucidgloves-prototype3+serial => opengloves_lucidgloves_proto3+serial}/diagram.json (100%) rename .wokwi/{lucidgloves-prototype3+serial => opengloves_lucidgloves_proto3+serial}/test.yaml (100%) create mode 100644 .wokwi/opengloves_lucidgloves_proto3+serial/wokwi.toml rename .wokwi/{lucidgloves-prototype4+serial => opengloves_lucidgloves_proto4+serial}/diagram.json (100%) rename .wokwi/{lucidgloves-prototype4+serial => opengloves_lucidgloves_proto4+serial}/test.yaml (100%) create mode 100644 .wokwi/opengloves_lucidgloves_proto4+serial/wokwi.toml delete mode 100644 ini/opengloves-indexer.ini delete mode 100644 ini/opengloves-lucidgloves.ini create mode 100644 variants/opengloves/indexer.ini create mode 100644 variants/opengloves/lucidgloves.ini rename {firmware/mode_configs => variants}/opengloves/opengloves.cpp (86%) rename {ini => variants/opengloves}/opengloves.ini (50%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 802977c8..7c3ea41e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -167,38 +167,38 @@ jobs: matrix: os: [ ubuntu-latest ] target: - - lucidgloves-prototype3 - - lucidgloves-prototype4 - - lucidgloves-prototype4-ffb - - indexer-c - - indexer-cf - - indexer-cs - - indexer-csf + - opengloves_lucidgloves_proto3 + - opengloves_lucidgloves_proto4 + - opengloves_lucidgloves_proto4_ffb + - opengloves_indexer_c + - opengloves_indexer_cf + - opengloves_indexer_cs + - opengloves_indexer_csf comm_flag: [ OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL ] coverage: [ false ] include: - os: ubuntu-latest - target: lucidgloves-prototype4-ffb + target: opengloves_lucidgloves_proto4_ffb comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL - os: ubuntu-latest - target: lucidgloves-prototype4-ffb + target: opengloves_lucidgloves_proto4_ffb comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL - os: ubuntu-latest - target: lucidgloves-prototype4-ffb + target: opengloves_lucidgloves_proto4_ffb comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::MinMaxCalibrator()" coverage: true - os: ubuntu-latest - target: lucidgloves-prototype4-ffb + target: opengloves_lucidgloves_proto4_ffb comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::CenterPointDeviationCalibrator(0.66F, 0.005F)" coverage: true - os: ubuntu-latest - target: lucidgloves-prototype4-ffb + target: opengloves_lucidgloves_proto4_ffb comm_flag: OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL curl_calibration_flag: CALIBRATION_CURL="new ::SenseShift::Input::Calibration::FixedCenterPointDeviationCalibrator(0.66F, 0.005F)" coverage: true @@ -564,8 +564,8 @@ jobs: strategy: matrix: variant: - - lucidgloves-prototype3+serial - - lucidgloves-prototype4+serial + - opengloves_lucidgloves_proto3+serial + - opengloves_lucidgloves_proto4+serial steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c2ef1716..b97595e4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,6 +30,7 @@ jobs: - 'firmware' - 'examples' - 'test' + - 'variants' fail-fast: false steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 99736c8e..70fad115 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,13 +102,13 @@ jobs: strategy: matrix: target: - - lucidgloves-prototype3 - - lucidgloves-prototype4 - - lucidgloves-prototype4-ffb - - indexer-c - - indexer-cf - - indexer-cs - - indexer-csf + - opengloves_lucidgloves_proto3 + - opengloves_lucidgloves_proto4 + - opengloves_lucidgloves_proto4_ffb + - opengloves_indexer_c + - opengloves_indexer_cf + - opengloves_indexer_cs + - opengloves_indexer_csf comm_flag: - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_SERIAL - OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BTSERIAL diff --git a/.github/workflows/sast.yml b/.github/workflows/sast.yml index 66aaa39d..091f4390 100644 --- a/.github/workflows/sast.yml +++ b/.github/workflows/sast.yml @@ -31,7 +31,7 @@ jobs: matrix: target: - bhaptics_tactsuit_x40 - - lucidgloves-prototype4-ffb + - opengloves_lucidgloves_proto4_ffb battery_flag: - SS_BATTERY_ENABLED=true @@ -94,9 +94,11 @@ jobs: strategy: matrix: directory: + - 'variants' - 'firmware' - 'include' - 'lib' + - 'examples' steps: - uses: actions/checkout@v4 diff --git a/.wokwi/lucidgloves-prototype3+serial/wokwi.toml b/.wokwi/lucidgloves-prototype3+serial/wokwi.toml deleted file mode 100644 index 5878bf60..00000000 --- a/.wokwi/lucidgloves-prototype3+serial/wokwi.toml +++ /dev/null @@ -1,6 +0,0 @@ -[wokwi] -version = 1 -firmware = "../../.pio/build/lucidgloves-prototype3/firmware.bin" -elf = "../../.pio/build/lucidgloves-prototype3/firmware.elf" - -gdbServerPort=3333 diff --git a/.wokwi/lucidgloves-prototype4+serial/wokwi.toml b/.wokwi/lucidgloves-prototype4+serial/wokwi.toml deleted file mode 100644 index 316b68c7..00000000 --- a/.wokwi/lucidgloves-prototype4+serial/wokwi.toml +++ /dev/null @@ -1,6 +0,0 @@ -[wokwi] -version = 1 -firmware = "../../.pio/build/lucidgloves-prototype4/firmware.bin" -elf = "../../.pio/build/lucidgloves-prototype4/firmware.elf" - -gdbServerPort=3333 diff --git a/.wokwi/lucidgloves-prototype3+serial/diagram.json b/.wokwi/opengloves_lucidgloves_proto3+serial/diagram.json similarity index 100% rename from .wokwi/lucidgloves-prototype3+serial/diagram.json rename to .wokwi/opengloves_lucidgloves_proto3+serial/diagram.json diff --git a/.wokwi/lucidgloves-prototype3+serial/test.yaml b/.wokwi/opengloves_lucidgloves_proto3+serial/test.yaml similarity index 100% rename from .wokwi/lucidgloves-prototype3+serial/test.yaml rename to .wokwi/opengloves_lucidgloves_proto3+serial/test.yaml diff --git a/.wokwi/opengloves_lucidgloves_proto3+serial/wokwi.toml b/.wokwi/opengloves_lucidgloves_proto3+serial/wokwi.toml new file mode 100644 index 00000000..3b7089e4 --- /dev/null +++ b/.wokwi/opengloves_lucidgloves_proto3+serial/wokwi.toml @@ -0,0 +1,6 @@ +[wokwi] +version = 1 +firmware = "../../.pio/build/opengloves_lucidgloves_proto3/firmware.bin" +elf = "../../.pio/build/opengloves_lucidgloves_proto3/firmware.elf" + +gdbServerPort = 3333 diff --git a/.wokwi/lucidgloves-prototype4+serial/diagram.json b/.wokwi/opengloves_lucidgloves_proto4+serial/diagram.json similarity index 100% rename from .wokwi/lucidgloves-prototype4+serial/diagram.json rename to .wokwi/opengloves_lucidgloves_proto4+serial/diagram.json diff --git a/.wokwi/lucidgloves-prototype4+serial/test.yaml b/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml similarity index 100% rename from .wokwi/lucidgloves-prototype4+serial/test.yaml rename to .wokwi/opengloves_lucidgloves_proto4+serial/test.yaml diff --git a/.wokwi/opengloves_lucidgloves_proto4+serial/wokwi.toml b/.wokwi/opengloves_lucidgloves_proto4+serial/wokwi.toml new file mode 100644 index 00000000..437d38f2 --- /dev/null +++ b/.wokwi/opengloves_lucidgloves_proto4+serial/wokwi.toml @@ -0,0 +1,6 @@ +[wokwi] +version = 1 +firmware = "../../.pio/build/opengloves_lucidgloves_proto4/firmware.bin" +elf = "../../.pio/build/opengloves_lucidgloves_proto4/firmware.elf" + +gdbServerPort = 3333 diff --git a/ini/opengloves-indexer.ini b/ini/opengloves-indexer.ini deleted file mode 100644 index 08048903..00000000 --- a/ini/opengloves-indexer.ini +++ /dev/null @@ -1,185 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Indexer C -; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:indexer-c] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = wemos_d1_mini32 -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - -D OG_ENCODE_FAST - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=25 - -D PIN_FINGER_INDEX=14 - -D PIN_FINGER_MIDDLE=33 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_JOYSTICK_X=12 - -D PIN_JOYSTICK_Y=4 - -D PIN_BUTTON_JOYSTICK=0 - - -D PIN_BUTTON_A=2 - -D PIN_BUTTON_B=11 - ; -D PIN_BUTTON_MENU=5 - -D PIN_BUTTON_CALIBRATE=27 - ; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true - ; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true - ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Indexer CF -; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:indexer-cf] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = wemos_d1_mini32 -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - -D OG_ENCODE_FAST - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=25 - -D PIN_FINGER_INDEX=14 - -D PIN_FINGER_MIDDLE=33 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_JOYSTICK_X=12 - -D PIN_JOYSTICK_Y=4 - -D PIN_BUTTON_JOYSTICK=0 - - -D PIN_BUTTON_A=2 - -D PIN_BUTTON_B=11 - ; -D PIN_BUTTON_MENU=5 - -D PIN_BUTTON_CALIBRATE=27 - ; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true - ; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true - ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true - - -D PIN_FFB_THUMB=16 - -D PIN_FFB_INDEX=17 - -D PIN_FFB_MIDDLE=21 - -D PIN_FFB_RING=22 - -D PIN_FFB_PINKY=1 - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Indexer CS -; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:indexer-cs] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = wemos_d1_mini32 -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=25 - -D PIN_FINGER_INDEX=14 - -D PIN_FINGER_MIDDLE=33 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_FINGER_THUMB_SPLAY=32 - -D PIN_FINGER_INDEX_SPLAY=13 - -D PIN_FINGER_MIDDLE_SPLAY=34 - -D PIN_FINGER_RING_SPLAY=35 - -D PIN_FINGER_PINKY_SPLAY=26 - - -D PIN_JOYSTICK_X=12 - -D PIN_JOYSTICK_Y=4 - -D PIN_BUTTON_JOYSTICK=0 - - -D PIN_BUTTON_A=2 - -D PIN_BUTTON_B=11 - ; -D PIN_BUTTON_MENU=5 - -D PIN_BUTTON_CALIBRATE=27 - ; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true - ; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true - ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Indexer CSF -; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:indexer-csf] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = wemos_d1_mini32 -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=25 - -D PIN_FINGER_INDEX=14 - -D PIN_FINGER_MIDDLE=33 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_FINGER_THUMB_SPLAY=32 - -D PIN_FINGER_INDEX_SPLAY=13 - -D PIN_FINGER_MIDDLE_SPLAY=34 - -D PIN_FINGER_RING_SPLAY=35 - -D PIN_FINGER_PINKY_SPLAY=26 - - -D PIN_JOYSTICK_X=12 - -D PIN_JOYSTICK_Y=4 - -D PIN_BUTTON_JOYSTICK=0 - - -D PIN_BUTTON_A=2 - -D PIN_BUTTON_B=11 - ; -D PIN_BUTTON_MENU=5 - -D PIN_BUTTON_CALIBRATE=27 - ; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true - ; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true - ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true - - -D PIN_FFB_THUMB=16 - -D PIN_FFB_INDEX=17 - -D PIN_FFB_MIDDLE=21 - -D PIN_FFB_RING=22 - -D PIN_FFB_PINKY=1 - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} diff --git a/ini/opengloves-lucidgloves.ini b/ini/opengloves-lucidgloves.ini deleted file mode 100644 index b777cee8..00000000 --- a/ini/opengloves-lucidgloves.ini +++ /dev/null @@ -1,126 +0,0 @@ -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; LucidGloves Prototype 3 -; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-3-Wiring-Diagram -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:lucidgloves-prototype3] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = ${opengloves.board} -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - -D OG_ENCODE_FAST - - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=32 - -D PIN_FINGER_INDEX=35 - -D PIN_FINGER_MIDDLE=34 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_JOYSTICK_X=33 - -D PIN_JOYSTICK_Y=25 - -D PIN_BUTTON_JOYSTICK=26 - - -D PIN_BUTTON_A=27 - -D PIN_BUTTON_B=14 - - -D CALIBRATION_ALWAYS_CALIBRATE=true - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; LucidGloves Prototype 4 -; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-4-Wiring-Diagram -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:lucidgloves-prototype4] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = ${opengloves.board} -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - -D OG_ENCODE_FAST - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=32 - -D PIN_FINGER_INDEX=35 - -D PIN_FINGER_MIDDLE=34 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_JOYSTICK_X=33 - -D PIN_JOYSTICK_Y=25 - -D PIN_BUTTON_JOYSTICK=26 - - -D PIN_BUTTON_A=27 - -D PIN_BUTTON_B=14 - ; -D PIN_BUTTON_MENU=27 - -D PIN_BUTTON_CALIBRATE=12 - ; -D PIN_BUTTON_TRIGGER=12 ; unused if GESTURE_TRIGGER is true - ; -D PIN_BUTTON_GRAB=13 ; unused if GESTURE_GRAB is true - ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; LucidGloves Prototype 4 + Force Feedback -; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-4-Wiring-Diagram -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[env:lucidgloves-prototype4-ffb] -platform = ${opengloves.platform} -platform_packages = ${opengloves.platform_packages} -framework = ${opengloves.framework} -board = ${opengloves.board} -upload_speed = ${opengloves.upload_speed} -monitor_speed = ${opengloves.monitor_speed} - -build_flags = - ${opengloves.build_flags} - -D OG_ENCODE_FAST - ;;;; Pins configuration - ;;;; Comment out to disable - -D PIN_FINGER_THUMB=32 - -D PIN_FINGER_INDEX=35 - -D PIN_FINGER_MIDDLE=34 - -D PIN_FINGER_RING=39 - -D PIN_FINGER_PINKY=36 - - -D PIN_JOYSTICK_X=33 - -D PIN_JOYSTICK_Y=25 - -D PIN_BUTTON_JOYSTICK=26 - - -D PIN_BUTTON_A=27 - -D PIN_BUTTON_B=14 - ; -D PIN_BUTTON_MENU=27 - -D PIN_BUTTON_CALIBRATE=12 - ; -D PIN_BUTTON_TRIGGER=12 ; unused if GESTURE_TRIGGER is true - ; -D PIN_BUTTON_GRAB=13 ; unused if GESTURE_GRAB is true - ; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true - - -D PIN_FFB_THUMB=17 - -D PIN_FFB_INDEX=21 - -D PIN_FFB_MIDDLE=19 - -D PIN_FFB_RING=18 - -D PIN_FFB_PINKY=5 - -build_unflags = ${opengloves.build_unflags} -build_src_filter = - ${opengloves.build_src_filter} - + -lib_deps = ${opengloves.lib_deps} diff --git a/platformio.ini b/platformio.ini index f7141e12..92dd6214 100644 --- a/platformio.ini +++ b/platformio.ini @@ -40,7 +40,6 @@ lib_ldf_mode = deep+ lib_deps = https://github.com/senseshift/frozen.git#feature/platformio https://github.com/senseshift/i2cdevlib-contrib.git#8db7eab29dd01385928c6a99938ed0a953a5acf3 - https://github.com/senseshift/opengloves-lib.git#master etlcpp/Embedded Template Library@^20.38.11 check_tool = clangtidy @@ -73,6 +72,7 @@ build_src_filter = + lib_deps = + ${env.lib_deps} fabiobatsilva/ArduinoFake@^0.4 test_ignore = diff --git a/variants/opengloves/indexer.ini b/variants/opengloves/indexer.ini new file mode 100644 index 00000000..4c11b4ab --- /dev/null +++ b/variants/opengloves/indexer.ini @@ -0,0 +1,169 @@ +[base:opengloves_indexer] +platform = ${arch:esp32.platform} +platform_packages = + ${arch:esp32.platform_packages} + +framework = ${base:arduino.framework} + +board = wemos_d1_mini32 + +build_unflags = + ${env.build_unflags} + ${arch:esp32.build_unflags} + ${base:arduino.build_unflags} + ${base:opengloves.build_unflags} +build_flags = + ${env.build_flags} + ${arch:esp32.build_flags} + ${base:arduino.build_flags} + ${base:opengloves.build_flags} + +build_src_filter = + ${env.build_src_filter} + +<../variants/opengloves> + +lib_deps = + ${env.lib_deps} + ${arch:esp32.lib_deps} + ${base:arduino.lib_deps} + ${base:opengloves.lib_deps} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Indexer C +; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_indexer_c] +extends = base:opengloves_indexer + +build_flags = + ${base:opengloves_indexer.build_flags} +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=25 + -D PIN_FINGER_INDEX=14 + -D PIN_FINGER_MIDDLE=33 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_JOYSTICK_X=12 + -D PIN_JOYSTICK_Y=4 + -D PIN_BUTTON_JOYSTICK=0 + + -D PIN_BUTTON_A=2 + -D PIN_BUTTON_B=11 +; -D PIN_BUTTON_MENU=5 + -D PIN_BUTTON_CALIBRATE=27 +; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true +; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true +; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Indexer CF +; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_indexer_cf] +extends = base:opengloves_indexer + +build_flags = + ${base:opengloves_indexer.build_flags} +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=25 + -D PIN_FINGER_INDEX=14 + -D PIN_FINGER_MIDDLE=33 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_JOYSTICK_X=12 + -D PIN_JOYSTICK_Y=4 + -D PIN_BUTTON_JOYSTICK=0 + + -D PIN_BUTTON_A=2 + -D PIN_BUTTON_B=11 +; -D PIN_BUTTON_MENU=5 + -D PIN_BUTTON_CALIBRATE=27 +; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true +; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true +; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true + + -D PIN_FFB_THUMB=16 + -D PIN_FFB_INDEX=17 + -D PIN_FFB_MIDDLE=21 + -D PIN_FFB_RING=22 + -D PIN_FFB_PINKY=1 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Indexer CS +; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_indexer_cs] +extends = base:opengloves_indexer + +build_flags = + ${base:opengloves_indexer.build_flags} +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=25 + -D PIN_FINGER_INDEX=14 + -D PIN_FINGER_MIDDLE=33 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_FINGER_THUMB_SPLAY=32 + -D PIN_FINGER_INDEX_SPLAY=13 + -D PIN_FINGER_MIDDLE_SPLAY=34 + -D PIN_FINGER_RING_SPLAY=35 + -D PIN_FINGER_PINKY_SPLAY=26 + + -D PIN_JOYSTICK_X=12 + -D PIN_JOYSTICK_Y=4 + -D PIN_BUTTON_JOYSTICK=0 + + -D PIN_BUTTON_A=2 + -D PIN_BUTTON_B=11 +; -D PIN_BUTTON_MENU=5 + -D PIN_BUTTON_CALIBRATE=27 +; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true +; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true +; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Indexer CSF +; Wiring Diagram: https://github.com/Valsvirtuals/Indexer/wiki/wiring-and-pinout +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_indexer_csf] +extends = base:opengloves_indexer + +build_flags = + ${base:opengloves_indexer.build_flags} +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=25 + -D PIN_FINGER_INDEX=14 + -D PIN_FINGER_MIDDLE=33 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_FINGER_THUMB_SPLAY=32 + -D PIN_FINGER_INDEX_SPLAY=13 + -D PIN_FINGER_MIDDLE_SPLAY=34 + -D PIN_FINGER_RING_SPLAY=35 + -D PIN_FINGER_PINKY_SPLAY=26 + + -D PIN_JOYSTICK_X=12 + -D PIN_JOYSTICK_Y=4 + -D PIN_BUTTON_JOYSTICK=0 + + -D PIN_BUTTON_A=2 + -D PIN_BUTTON_B=11 +; -D PIN_BUTTON_MENU=5 + -D PIN_BUTTON_CALIBRATE=27 +; -D PIN_BUTTON_TRIGGER=19 ; unused if GESTURE_TRIGGER is true +; -D PIN_BUTTON_GRAB=18 ; unused if GESTURE_GRAB is true +; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true + + -D PIN_FFB_THUMB=16 + -D PIN_FFB_INDEX=17 + -D PIN_FFB_MIDDLE=21 + -D PIN_FFB_RING=22 + -D PIN_FFB_PINKY=1 diff --git a/variants/opengloves/lucidgloves.ini b/variants/opengloves/lucidgloves.ini new file mode 100644 index 00000000..cffea539 --- /dev/null +++ b/variants/opengloves/lucidgloves.ini @@ -0,0 +1,124 @@ +[base:opengloves_lucidgloves] +framework = ${base:arduino.framework} + +[base:opengloves_lucidgloves_esp32] +platform = ${arch:esp32.platform} +platform_packages = + ${arch:esp32.platform_packages} + +framework = ${base:opengloves_lucidgloves.framework} + +board = esp32dev + +build_unflags = + ${env.build_unflags} + ${arch:esp32.build_unflags} + ${base:arduino.build_unflags} + ${base:opengloves.build_unflags} +build_flags = + ${env.build_flags} + ${arch:esp32.build_flags} + ${base:arduino.build_flags} + ${base:opengloves.build_flags} + +build_src_filter = + ${env.build_src_filter} + +<../variants/opengloves> + +lib_deps = + ${env.lib_deps} + ${arch:esp32.lib_deps} + ${base:arduino.lib_deps} + ${base:opengloves.lib_deps} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; LucidGloves Prototype 3 +; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-3-Wiring-Diagram +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_lucidgloves_proto3] +extends = base:opengloves_lucidgloves_esp32 + +build_flags = + ${base:opengloves_lucidgloves_esp32.build_flags} +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=32 + -D PIN_FINGER_INDEX=35 + -D PIN_FINGER_MIDDLE=34 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_JOYSTICK_X=33 + -D PIN_JOYSTICK_Y=25 + -D PIN_BUTTON_JOYSTICK=26 + + -D PIN_BUTTON_A=27 + -D PIN_BUTTON_B=14 + + -D CALIBRATION_ALWAYS_CALIBRATE=true + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; LucidGloves Prototype 4 +; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-4-Wiring-Diagram +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_lucidgloves_proto4] +extends = base:opengloves_lucidgloves_esp32 + +build_flags = + ${base:opengloves_lucidgloves_esp32.build_flags} + -D OG_ENCODE_FAST +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=32 + -D PIN_FINGER_INDEX=35 + -D PIN_FINGER_MIDDLE=34 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_JOYSTICK_X=33 + -D PIN_JOYSTICK_Y=25 + -D PIN_BUTTON_JOYSTICK=26 + + -D PIN_BUTTON_A=27 + -D PIN_BUTTON_B=14 +; -D PIN_BUTTON_MENU=27 + -D PIN_BUTTON_CALIBRATE=12 +; -D PIN_BUTTON_TRIGGER=12 ; unused if GESTURE_TRIGGER is true +; -D PIN_BUTTON_GRAB=13 ; unused if GESTURE_GRAB is true +; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; LucidGloves Prototype 4 + Force Feedback +; Wiring Diagram: https://github.com/LucidVR/lucidgloves/wiki/Prototype-4-Wiring-Diagram +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[env:opengloves_lucidgloves_proto4_ffb] +extends = base:opengloves_lucidgloves_esp32 + +build_flags = + ${base:opengloves_lucidgloves_esp32.build_flags} + -D OG_ENCODE_FAST +;;;; Pins configuration +;;;; Comment out to disable + -D PIN_FINGER_THUMB=32 + -D PIN_FINGER_INDEX=35 + -D PIN_FINGER_MIDDLE=34 + -D PIN_FINGER_RING=39 + -D PIN_FINGER_PINKY=36 + + -D PIN_JOYSTICK_X=33 + -D PIN_JOYSTICK_Y=25 + -D PIN_BUTTON_JOYSTICK=26 + + -D PIN_BUTTON_A=27 + -D PIN_BUTTON_B=14 +; -D PIN_BUTTON_MENU=27 + -D PIN_BUTTON_CALIBRATE=12 +; -D PIN_BUTTON_TRIGGER=12 ; unused if GESTURE_TRIGGER is true +; -D PIN_BUTTON_GRAB=13 ; unused if GESTURE_GRAB is true +; -D PIN_BUTTON_PINCH=23 ; unused if GESTURE_PINCH is true + + -D PIN_FFB_THUMB=17 + -D PIN_FFB_INDEX=21 + -D PIN_FFB_MIDDLE=19 + -D PIN_FFB_RING=18 + -D PIN_FFB_PINKY=5 diff --git a/firmware/mode_configs/opengloves/opengloves.cpp b/variants/opengloves/opengloves.cpp similarity index 86% rename from firmware/mode_configs/opengloves/opengloves.cpp rename to variants/opengloves/opengloves.cpp index 3a3cb0b8..fade899d 100644 --- a/firmware/mode_configs/opengloves/opengloves.cpp +++ b/variants/opengloves/opengloves.cpp @@ -1,13 +1,13 @@ -#include -#include -#include +#include "senseshift/freertos/task.hpp" +#include "senseshift/opengloves/autoconfig.hpp" +#include "senseshift/opengloves/opengloves_component.hpp" -#include +#include "opengloves/alpha.hpp" using namespace SenseShift::OpenGloves; namespace og = ::opengloves; -void setupMode() +void setup() { auto* communication = AutoConfig::createTransport(); @@ -51,7 +51,7 @@ void setupMode() #endif } -void loopMode() +void loop() { vTaskDelete(NULL); } diff --git a/ini/opengloves.ini b/variants/opengloves/opengloves.ini similarity index 50% rename from ini/opengloves.ini rename to variants/opengloves/opengloves.ini index 7606d671..daa7c518 100644 --- a/ini/opengloves.ini +++ b/variants/opengloves/opengloves.ini @@ -1,29 +1,19 @@ -[opengloves] -platform = platformio/espressif32@^6.8.1 -platform_packages = - toolchain-xtensa-esp32@12.2.0+20230208 - framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 - framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip -framework = arduino -board = esp32doit-devkit-v1 -upload_speed = 921600 -monitor_speed = 115200 - +[base:opengloves] +build_unflags = build_flags = - ${common.build_flags} - -D OPENGLOVES + -D SS_OPENGLOVES - ;;;; Communication - ; -D OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL - ;;;; Serial +;;;; Communication +; -D OPENGLOVES_COMMUNICATION=OPENGLOVES_COMM_BLESERIAL ; OPENGLOVES_COMM_SERIAL, OPENGLOVES_COMM_BTSERIAL, OPENGLOVES_COMM_BLESERIAL +;;;; Serial -D SERIAL_BAUDRATE=115200 - ; Options: Serial, Serial1, Serial2, Serial3 +; Options: Serial, Serial1, Serial2, Serial3 -D SERIAL_PORT=Serial - ;;;; BTSerial +;;;; BTSerial '-D BTSERIAL_PREFIX="SenseShift_OG"' - ; '-D BTSERIAL_NAME="SenseShift_OG_Left"' +; '-D BTSERIAL_NAME="SenseShift_OG_Left"' - ; Sensors +; Sensors -D FINGER_THUMB_INVERT=false -D FINGER_INDEX_INVERT=false -D FINGER_MIDDLE_INVERT=false @@ -53,12 +43,11 @@ build_flags = -D GESTURE_GRAB_ENABLED=true -D GESTURE_PINCH_ENABLED=true - ;;;; Calibration +;;;; Calibration -D CALIBRATION_ALWAYS_CALIBRATE=false -D CALIBRATION_DURATION=2000 ; in ms +; sensors update rate in Hz + -D UPDATE_RATE=90 - -D UPDATE_RATE=90 ; sensors update rate in Hz - -build_unflags = ${common.build_unflags} -build_src_filter = ${common.build_src_filter} -lib_deps = ${common.lib_deps} +lib_deps = + https://github.com/senseshift/opengloves-lib.git#master From 10b42c9a43df51d022668328a3098b8c00aa45e9 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 13:36:41 +0400 Subject: [PATCH 58/67] style: change back include brackets --- include/config/bhaptics.h | 12 ------------ variants/bhaptics/tactal/tactal.cpp | 14 +++++++------- variants/bhaptics/tactglove/tactglove.cpp | 15 +++++++-------- variants/bhaptics/tactosy2/tactosy2.cpp | 14 +++++++------- variants/bhaptics/tactosyf/tactosyf.cpp | 14 +++++++------- variants/bhaptics/tactosyh/tactosyh.cpp | 14 +++++++------- variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp | 14 +++++++------- .../tactsuit_x16_pca9685.cpp | 14 +++++++------- variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp | 16 ++++++++-------- variants/bhaptics/tactvisor/tactvisor.cpp | 14 +++++++------- variants/opengloves/opengloves.cpp | 6 +++--- 11 files changed, 67 insertions(+), 80 deletions(-) diff --git a/include/config/bhaptics.h b/include/config/bhaptics.h index 5cd12d9b..c8b869f5 100644 --- a/include/config/bhaptics.h +++ b/include/config/bhaptics.h @@ -4,16 +4,4 @@ #include "config/bluetooth.h" -#ifndef BH_BLE_APPEARANCE -#define BH_BLE_APPEARANCE 508 -#endif - -#ifndef BH_SERIAL_NUMBER -// 76b5-e8e7-835d-8b71-381c -#define BH_SERIAL_NUMBER \ - { \ - 0x76, 0xbd, 0xe8, 0xe7, 0x83, 0x5d, 0x8b, 0x71, 0x38, 0x1c \ - } -#endif - #endif diff --git a/variants/bhaptics/tactal/tactal.cpp b/variants/bhaptics/tactal/tactal.cpp index fcd88e78..90ccca74 100644 --- a/variants/bhaptics/tactal/tactal.cpp +++ b/variants/bhaptics/tactal/tactal.cpp @@ -6,13 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactglove/tactglove.cpp b/variants/bhaptics/tactglove/tactglove.cpp index 4ce21e57..308d59b3 100644 --- a/variants/bhaptics/tactglove/tactglove.cpp +++ b/variants/bhaptics/tactglove/tactglove.cpp @@ -6,14 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" -#include "senseshift/utility.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactosy2/tactosy2.cpp b/variants/bhaptics/tactosy2/tactosy2.cpp index 84c5b31e..2bcc1d73 100644 --- a/variants/bhaptics/tactosy2/tactosy2.cpp +++ b/variants/bhaptics/tactosy2/tactosy2.cpp @@ -6,13 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactosyf/tactosyf.cpp b/variants/bhaptics/tactosyf/tactosyf.cpp index 2e5c28c1..165cc0e3 100644 --- a/variants/bhaptics/tactosyf/tactosyf.cpp +++ b/variants/bhaptics/tactosyf/tactosyf.cpp @@ -6,13 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactosyh/tactosyh.cpp b/variants/bhaptics/tactosyh/tactosyh.cpp index 511c10fc..b52c7dfe 100644 --- a/variants/bhaptics/tactosyh/tactosyh.cpp +++ b/variants/bhaptics/tactosyh/tactosyh.cpp @@ -6,13 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp b/variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp index 003a391f..b32bd2a5 100644 --- a/variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp +++ b/variants/bhaptics/tactsuit_x16/tactsuit_x16.cpp @@ -6,13 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp b/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp index 12d47bb0..d73b76d2 100644 --- a/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp +++ b/variants/bhaptics/tactsuit_x16_pca9685/tactsuit_x16_pca9685.cpp @@ -9,13 +9,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" -#include "senseshift/output/i2cdevlib_pwm.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp b/variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp index c2958512..5e79caca 100644 --- a/variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp +++ b/variants/bhaptics/tactsuit_x40/tactsuit_x40.cpp @@ -9,14 +9,14 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" -#include "senseshift/output/i2cdevlib_pwm.hpp" +#include +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/bhaptics/tactvisor/tactvisor.cpp b/variants/bhaptics/tactvisor/tactvisor.cpp index e5cb6e56..47895849 100644 --- a/variants/bhaptics/tactvisor/tactvisor.cpp +++ b/variants/bhaptics/tactvisor/tactvisor.cpp @@ -6,13 +6,13 @@ #include "senseshift.h" -#include "senseshift/arduino/input/sensor/analog.hpp" -#include "senseshift/arduino/output/ledc.hpp" -#include "senseshift/battery/input/battery_sensor.hpp" -#include "senseshift/bh/ble/connection.hpp" -#include "senseshift/bh/devices.hpp" -#include "senseshift/bh/encoding.hpp" -#include "senseshift/freertos/task.hpp" +#include +#include +#include +#include +#include +#include +#include using namespace SenseShift; using namespace SenseShift::Input; diff --git a/variants/opengloves/opengloves.cpp b/variants/opengloves/opengloves.cpp index fade899d..18b1307a 100644 --- a/variants/opengloves/opengloves.cpp +++ b/variants/opengloves/opengloves.cpp @@ -1,6 +1,6 @@ -#include "senseshift/freertos/task.hpp" -#include "senseshift/opengloves/autoconfig.hpp" -#include "senseshift/opengloves/opengloves_component.hpp" +#include +#include +#include #include "opengloves/alpha.hpp" From 5b9fdcd8fb52fd648f617040fa627ada654c08b3 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 14:43:07 +0400 Subject: [PATCH 59/67] fix(ESP32): bring back info logging --- arch/esp32/esp32.ini | 3 ++- docs/DEVELOPMENT.md | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index be9aecfa..043629ea 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -2,13 +2,14 @@ platform = platformio/espressif32@^6.8.1 platform_packages = toolchain-xtensa-esp32@12.2.0+20230208 + espressif/tool-xtensa-esp-elf-gdb@12.1.0+20221002 framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.3 framework-arduinoespressif32-libs @ https://github.com/espressif/arduino-esp32/releases/download/3.0.3/esp32-arduino-libs-3.0.3.zip build_flags = -D SS_USE_NIMBLE=true -D SOC_WIFI_SUPPORTED=1 -; -D CORE_DEBUG_LEVEL=3 + -D CORE_DEBUG_LEVEL=3 ; -D DEBUG_MODE=0 ; -D DEBUG_ESP_PORT=Serial build_unflags = diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 1a6e5409..91b59d3f 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -26,7 +26,7 @@ Run and debug firmware in Wokwi Simulator 1. Run this command: ```shell - pio debug -e lucidgloves-prototype3 + pio debug -e opengloves_lucidgloves_proto3 ``` 2. `Ctrl+Shift+P` => `> Wokwi: Start Simulator and Wait for Debugger`, 3. Add launch option (this step is required until PlatformIO fixes this issue: [#3824](https://github.com/platformio/platformio-core/issues/3824)): @@ -34,14 +34,14 @@ Run and debug firmware in Wokwi Simulator ... { - "name": "Wokwi GDB - lucidgloves-prototype3", + "name": "Wokwi GDB - opengloves_lucidgloves_proto3", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/.pio/build/lucidgloves-prototype3/firmware.elf", + "program": "${workspaceFolder}/.pio/build/opengloves_lucidgloves_proto3/firmware.elf", "cwd": "${workspaceFolder}", "MIMode": "gdb", - "miDebuggerPath": "${userHome}/.platformio/packages/toolchain-xtensa-esp32/bin/xtensa-esp32-elf-gdb", + "miDebuggerPath": "${userHome}/.platformio/packages/tool-xtensa-esp-elf-gdb/bin/xtensa-esp32-elf-gdb.exe", "miDebuggerServerAddress": "localhost:3333", }, ... - ``` \ No newline at end of file + ``` From 3a04e15167cd708b541b631684843532173aa4d9 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 15:19:39 +0400 Subject: [PATCH 60/67] feat(FreeRTOS): pass config by reference --- lib/freertos/senseshift/freertos/task.hpp | 8 ++++---- variants/opengloves/opengloves.ini | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 4ee395b7..4d1ddceb 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -44,9 +44,9 @@ class Task { friend class Task; public: - explicit Task(TaskConfig& config) : taskConfig(config) + explicit Task(const TaskConfig& config) : taskConfig(config) { - log_i("creating ComponentUpdateTask: %s", taskConfig.name); + log_i("creating Task: %s", taskConfig.name); } virtual ~Task() { @@ -126,8 +126,8 @@ class ComponentUpdateTask : public Task> { static_assert(std::is_same_v); public: - ComponentUpdateTask(Tp* component, std::uint32_t updateDelay, TaskConfig taskConfig) : - Task(taskConfig), component_(component), updateDelay_(updateDelay) + ComponentUpdateTask(Tp* component, std::uint32_t updateDelay, const TaskConfig& taskConfig) : + Task>(taskConfig), component_(component), updateDelay_(updateDelay) { log_i("creating ComponentUpdateTask: %s", taskConfig.name); } diff --git a/variants/opengloves/opengloves.ini b/variants/opengloves/opengloves.ini index daa7c518..dfea493f 100644 --- a/variants/opengloves/opengloves.ini +++ b/variants/opengloves/opengloves.ini @@ -44,7 +44,7 @@ build_flags = -D GESTURE_PINCH_ENABLED=true ;;;; Calibration - -D CALIBRATION_ALWAYS_CALIBRATE=false +; -D CALIBRATION_ALWAYS_CALIBRATE=true -D CALIBRATION_DURATION=2000 ; in ms ; sensors update rate in Hz -D UPDATE_RATE=90 From c87d7891da78be2b29e0da5df5137ce98e16427a Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 15:40:40 +0400 Subject: [PATCH 61/67] ci(Wokwi): start calibration for lucidgloves proto4 --- .../test.yaml | 182 +++++++++--------- 1 file changed, 95 insertions(+), 87 deletions(-) diff --git a/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml b/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml index ed6807fb..ead709bf 100644 --- a/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml +++ b/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml @@ -3,90 +3,98 @@ version: 1 author: Leonid Meleshin steps: - - delay: 3000ms - - # Press calibration button - - set-control: - part-id: btn3 - control: pressed - value: 1 - - - delay: 500ms - - # Release calibration button - - set-control: - part-id: btn3 - control: pressed - value: 0 - - - wait-serial: "A0B0C0D0E0F2047G2047" - - # Press the 'A' button - - set-control: - part-id: btn1 - control: pressed - value: 1 - - wait-serial: "A0B0C0D0E0F2047G2047J" - - # Press the 'B' button - - set-control: - part-id: btn2 - control: pressed - value: 1 - - wait-serial: "A0B0C0D0E0F2047G2047JK" - - # Release the 'A' button - - set-control: - part-id: btn1 - control: pressed - value: 0 - - wait-serial: "A0B0C0D0E0F2047G2047K" - - # Release the 'B' button - - set-control: - part-id: btn2 - control: pressed - value: 0 - - wait-serial: "A0B0C0D0E0F2047G2047" - - # Curl Index finger - - set-control: - part-id: pot-index - control: position - value: 1 - - wait-serial: "A0B4095C0D0E0F2047G2047I" # I is for Trigger gesture - - # Curl Thumb finger - - set-control: - part-id: pot-thumb - control: position - value: 1 - - wait-serial: "A4095B4095C0D0E0F2047G2047MI" # M is for Pinch gesture - - # Curl Middle finger - - set-control: - part-id: pot-middle - control: position - value: 1 - - wait-serial: "A4095B4095C4095D0E0F2047G2047MI" - - # Curl Ring finger - - set-control: - part-id: pot-ring - control: position - value: 1 - - wait-serial: "A4095B4095C4095D4095E0F2047G2047MI" - - # Curl Pinky finger - - set-control: - part-id: pot-pinky - control: position - value: 1 - - wait-serial: "A4095B4095C4095D4095E4095F2047G2047MIL" # L is for the Grab gesture - - # Partially Release Thumb finger - - set-control: - part-id: pot-thumb - control: position - value: 0.25 - - wait-serial: "A1024B4095C4095D4095E4095F2047G2047IL" + - delay: 3000ms + + # Press calibration button + - set-control: + part-id: btn3 + control: pressed + value: 1 + + - delay: 500ms + + # Release calibration button + - set-control: + part-id: btn3 + control: pressed + value: 0 + + - wait-serial: "A0B0C0D0E0F2047G2047" + + # Press the 'A' button + - set-control: + part-id: btn1 + control: pressed + value: 1 + - wait-serial: "A0B0C0D0E0F2047G2047J" + + # Press the 'B' button + - set-control: + part-id: btn2 + control: pressed + value: 1 + - wait-serial: "A0B0C0D0E0F2047G2047JK" + + # Release the 'A' button + - set-control: + part-id: btn1 + control: pressed + value: 0 + - wait-serial: "A0B0C0D0E0F2047G2047K" + + # Release the 'B' button + - set-control: + part-id: btn2 + control: pressed + value: 0 + - wait-serial: "A0B0C0D0E0F2047G2047" + + # Press calibration button + - set-control: + part-id: btn3 + control: pressed + value: 1 + + - delay: 500ms + + # Curl Index finger + - set-control: + part-id: pot-index + control: position + value: 1 + - wait-serial: "A0B4095C0D0E0F2047G2047I" # I is for Trigger gesture + + # Curl Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 1 + - wait-serial: "A4095B4095C0D0E0F2047G2047MI" # M is for Pinch gesture + + # Curl Middle finger + - set-control: + part-id: pot-middle + control: position + value: 1 + - wait-serial: "A4095B4095C4095D0E0F2047G2047MI" + + # Curl Ring finger + - set-control: + part-id: pot-ring + control: position + value: 1 + - wait-serial: "A4095B4095C4095D4095E0F2047G2047MI" + + # Curl Pinky finger + - set-control: + part-id: pot-pinky + control: position + value: 1 + - wait-serial: "A4095B4095C4095D4095E4095F2047G2047MIL" # L is for the Grab gesture + + # Partially Release Thumb finger + - set-control: + part-id: pot-thumb + control: position + value: 0.25 + - wait-serial: "A1024B4095C4095D4095E4095F2047G2047IL" From 41e53cb043fbf23a904ccbaa0ef119619ee143d2 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 15:49:33 +0400 Subject: [PATCH 62/67] fix(OpenGloves): don't reset calibration while holding button --- .../test.yaml | 14 +++++++------- .../opengloves/opengloves_component.hpp | 16 +++++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml b/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml index ead709bf..34d19fe7 100644 --- a/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml +++ b/.wokwi/opengloves_lucidgloves_proto4+serial/test.yaml @@ -54,47 +54,47 @@ steps: part-id: btn3 control: pressed value: 1 - - delay: 500ms + - wait-serial: "A0B0C0D0E0F2047G2047O" # Curl Index finger - set-control: part-id: pot-index control: position value: 1 - - wait-serial: "A0B4095C0D0E0F2047G2047I" # I is for Trigger gesture + - wait-serial: "A0B4095C0D0E0F2047G2047OI" # I is for Trigger gesture # Curl Thumb finger - set-control: part-id: pot-thumb control: position value: 1 - - wait-serial: "A4095B4095C0D0E0F2047G2047MI" # M is for Pinch gesture + - wait-serial: "A4095B4095C0D0E0F2047G2047OMI" # M is for Pinch gesture # Curl Middle finger - set-control: part-id: pot-middle control: position value: 1 - - wait-serial: "A4095B4095C4095D0E0F2047G2047MI" + - wait-serial: "A4095B4095C4095D0E0F2047G2047OMI" # Curl Ring finger - set-control: part-id: pot-ring control: position value: 1 - - wait-serial: "A4095B4095C4095D4095E0F2047G2047MI" + - wait-serial: "A4095B4095C4095D4095E0F2047G2047OMI" # Curl Pinky finger - set-control: part-id: pot-pinky control: position value: 1 - - wait-serial: "A4095B4095C4095D4095E4095F2047G2047MIL" # L is for the Grab gesture + - wait-serial: "A4095B4095C4095D4095E4095F2047G2047OMIL" # L is for the Grab gesture # Partially Release Thumb finger - set-control: part-id: pot-thumb control: position value: 0.25 - - wait-serial: "A1024B4095C4095D4095E4095F2047G2047IL" + - wait-serial: "A1024B4095C4095D4095E4095F2047G2047OIL" diff --git a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp index fc3be9b6..c3758ab2 100644 --- a/lib/opengloves/senseshift/opengloves/opengloves_component.hpp +++ b/lib/opengloves/senseshift/opengloves/opengloves_component.hpp @@ -35,7 +35,7 @@ class OpenGlovesTrackingComponent { } }; - OpenGlovesTrackingComponent(Config& config, InputSensors& input_sensors, ITransport* communication) : + OpenGlovesTrackingComponent(const Config& config, InputSensors& input_sensors, ITransport* communication) : config_(config), input_sensors_(std::move(input_sensors)), communication_(communication) { } @@ -67,8 +67,7 @@ class OpenGlovesTrackingComponent { // this->raw_plotter_.plot(raw_data); // this->calibrated_plotter_.plot(data); - bool const calibrate_pressed = data.button_calibrate.press; - if (calibrate_pressed && this->calibration_start_time_ == 0) { + if (data.button_calibrate.press) { this->startCalibration(); } @@ -104,9 +103,12 @@ class OpenGlovesTrackingComponent { protected: void startCalibration() { - log_i("Starting calibration"); - this->input_sensors_.resetCalibration(); - this->input_sensors_.startCalibration(); + if (this->calibration_start_time_ == 0) { + log_i("Starting calibration"); + this->input_sensors_.resetCalibration(); + this->input_sensors_.startCalibration(); + } + this->calibration_start_time_ = millis(); } @@ -122,7 +124,7 @@ class OpenGlovesTrackingComponent { unsigned long long calibration_start_time_ = 0; - Config& config_; + Config config_; InputSensors input_sensors_; ITransport* communication_; }; From bbe02253c7bf02c5492ed394be69612797530204 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Thu, 8 Aug 2024 21:36:51 +0400 Subject: [PATCH 63/67] ci(GitHub): setup GCC problem matcher --- .github/workflows/ci.yml | 6 ++++++ platformio.ini | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7c3ea41e..2eaa0c75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,6 +99,8 @@ jobs: sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32-libs/esp32/ld/memory.ld sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini + - uses: ammaraskar/gcc-problem-matcher@0.3.0 + - name: Build shell: bash run: | @@ -255,6 +257,8 @@ jobs: sed -i "s/len\s=\s0x2c200\s-\s0xdb5c/len = 2898880/" ~/.platformio/packages/framework-arduinoespressif32-libs/esp32/ld/memory.ld sed -i "/\[env\]/p; s/\[env\]/board_build.partitions = huge_app.csv/" platformio.ini + - uses: ammaraskar/gcc-problem-matcher@0.3.0 + - name: Build shell: bash run: | @@ -362,6 +366,8 @@ jobs: run: | pio pkg install -e ${{matrix.target}} + - uses: ammaraskar/gcc-problem-matcher@0.3.0 + - name: Run Unit Tests run: pio test -e ${{matrix.target}} diff --git a/platformio.ini b/platformio.ini index 92dd6214..c324e0e8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,6 +30,10 @@ build_unflags = -std=gnu++11 build_flags = -std=gnu++17 + -Wall + -Wextra + -Werror + -Wno-unknown-pragmas -D __OH_FIRMWARE__ build_src_filter = From 3465d3553c15f1e869ad305cc6e20caa1f2aefdc Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 9 Aug 2024 12:44:50 +0400 Subject: [PATCH 64/67] feat(OpenGloves): upgrade lib --- variants/opengloves/opengloves.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/opengloves/opengloves.ini b/variants/opengloves/opengloves.ini index dfea493f..09486e21 100644 --- a/variants/opengloves/opengloves.ini +++ b/variants/opengloves/opengloves.ini @@ -50,4 +50,4 @@ build_flags = -D UPDATE_RATE=90 lib_deps = - https://github.com/senseshift/opengloves-lib.git#master + https://github.com/senseshift/opengloves-lib.git#d2e266045810b3e03ee6e5e0abb2aa3ff8fcca85 From 9cc1e427a785b063dd9b9342063bca30b69fe30f Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 9 Aug 2024 12:45:19 +0400 Subject: [PATCH 65/67] fix: resolve compiler warnings --- docs/DEVELOPMENT.md | 2 +- lib/bhaptics/senseshift/bh/encoding.hpp | 8 ++++---- lib/freertos/senseshift/freertos/task.hpp | 3 +-- lib/io/senseshift/input/calibration.hpp | 2 +- lib/io/senseshift/input/filter.hpp | 9 +++++---- lib/io/senseshift/input/sensor.hpp | 2 +- lib/io/senseshift/input/sensor/analog_threshold.hpp | 2 +- lib/math/senseshift/math/point2.hpp | 9 +++++++++ lib/opengloves/senseshift/opengloves/autoconfig.hpp | 13 ++++++++----- test/test_battery/main.cpp | 2 +- test/test_bhaptics_encoding/main.cpp | 2 +- test/test_body_gestures/main.cpp | 2 +- test/test_core_helpers/main.cpp | 2 +- test/test_haptics_body/main.cpp | 2 +- test/test_haptics_plane/main.cpp | 2 +- test/test_io_calibration/main.cpp | 2 +- test/test_io_filter/main.cpp | 2 +- test/test_io_sensor/main.cpp | 4 ++-- test/test_math_point2/main.cpp | 2 +- 19 files changed, 42 insertions(+), 30 deletions(-) diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 91b59d3f..64b3a8d7 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -15,7 +15,7 @@ Function argument: `snake_case` ### Fix `clang-format` ```shell -find lib include firmware test examples -type f -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' ! -regex '^lib/frozen\(/.*\)' -exec clang-format-16 -style=file -i {} \; +find lib include firmware test examples variants -type f -regex '.*\.\(cpp\|hpp\|cu\|c\|h\)' -exec clang-format-16 -style=file -i {} \; ``` # Debugging diff --git a/lib/bhaptics/senseshift/bh/encoding.hpp b/lib/bhaptics/senseshift/bh/encoding.hpp index 9623fbc0..7d626b3f 100644 --- a/lib/bhaptics/senseshift/bh/encoding.hpp +++ b/lib/bhaptics/senseshift/bh/encoding.hpp @@ -29,7 +29,7 @@ class Decoder { FloatBody* output, const std::array& value, const std::array& layout, - const Effect effect + const Effect ) { for (size_t i = 0; i < N; i++) { @@ -59,7 +59,7 @@ class Decoder { FloatBody* output, const std::array& value, const std::array& layout, - const Effect effect, + const Effect, const Target target ) { @@ -137,7 +137,7 @@ class Decoder { std::array result{}; // Unpack values - for (auto i = 0; i < VEST_PAYLOAD_SIZE; i++) { + for (size_t i = 0; i < VEST_PAYLOAD_SIZE; i++) { const std::uint8_t byte = value[i]; const size_t actIndex = i * 2; @@ -146,7 +146,7 @@ class Decoder { } // Assign max value into each group - for (auto i = 0; i < N; i++) { + for (size_t i = 0; i < N; i++) { auto groupIndex = layoutGroups[i]; if (groupIndex % 10 >= 4) { diff --git a/lib/freertos/senseshift/freertos/task.hpp b/lib/freertos/senseshift/freertos/task.hpp index 4d1ddceb..4ed9fba9 100644 --- a/lib/freertos/senseshift/freertos/task.hpp +++ b/lib/freertos/senseshift/freertos/task.hpp @@ -142,7 +142,6 @@ class ComponentUpdateTask : public Task> { [[noreturn]] void run() { auto now = millis(); - auto targetHz = 1000 / this->updateDelay_; while (true) { now = millis(); @@ -151,7 +150,7 @@ class ComponentUpdateTask : public Task> { const auto elapsed = millis() - now; - log_d("T: %d, Fmax: %dHz, Ft: %dHz", elapsed, 1000 / elapsed, targetHz); + log_d("T: %d, Fmax: %dHz, Ft: %dHz", elapsed, 1000 / elapsed, 1000 / this->updateDelay_); if (elapsed < this->updateDelay_) { delay(this->updateDelay_ - elapsed); } diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index e763a113..a2239c53 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -245,7 +245,7 @@ class FixedCenterPointDeviationCalibrator : public ICalibrator { void reset() override { } - void update(ValueType input) override + void update(ValueType) override { } diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index d0a3fab8..906c3524 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -259,9 +259,9 @@ class ExponentialMovingAverageFilter : public IFilter { /// Deadzone filter. Clamps acc_ to center if it is within the deadzone. /// Usually used to filter out noise in the joystick. -class CenterDeadzoneFilter : public IFilter { +class SinglePointDeadzoneFilter : public IFilter { public: - explicit CenterDeadzoneFilter(float deadzone, float center = 0.5F) : deadzone_(deadzone), center_(center){}; + explicit SinglePointDeadzoneFilter(float deadzone, float center = 0.5F) : deadzone_(deadzone), center_(center){}; inline auto filter(ISimpleSensor* /*sensor*/, float value) -> float override { @@ -270,11 +270,12 @@ class CenterDeadzoneFilter : public IFilter { } private: + const float deadzone_; const float center_; - - float deadzone_; }; +using CenterDeadzoneFilter = SinglePointDeadzoneFilter; + /// Interpolates the value from the lookup table. /// Can be used to determine battery level from the voltage. /// diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 2883571e..1731db82 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -142,7 +142,7 @@ class SimpleSensorDecorator : public Sensor { using ValueType = Tp; using SourceType = ISimpleSensor; - explicit SimpleSensorDecorator(SourceType* source) : source_(source), Sensor() + explicit SimpleSensorDecorator(SourceType* source) : Sensor(), source_(source) { } diff --git a/lib/io/senseshift/input/sensor/analog_threshold.hpp b/lib/io/senseshift/input/sensor/analog_threshold.hpp index 8a9af64f..d105e9db 100644 --- a/lib/io/senseshift/input/sensor/analog_threshold.hpp +++ b/lib/io/senseshift/input/sensor/analog_threshold.hpp @@ -16,8 +16,8 @@ class AnalogThresholdSensor : public BinarySensor { Sensor* source, Tp threshold_upper, Tp threshold_lower, bool attach_callbacks = false ) : source_(source), - threshold_upper_(threshold_upper), threshold_lower_(threshold_lower), + threshold_upper_(threshold_upper), attach_callbacks_(attach_callbacks) { } diff --git a/lib/math/senseshift/math/point2.hpp b/lib/math/senseshift/math/point2.hpp index f714a6c0..f992fc34 100644 --- a/lib/math/senseshift/math/point2.hpp +++ b/lib/math/senseshift/math/point2.hpp @@ -27,6 +27,15 @@ struct Point2 { { } + constexpr auto operator=(const Point2& v) -> Point2& + { + if (this != &v) { + x = v.x; + y = v.y; + } + return *this; + } + constexpr inline auto operator==(const Point2& rhs) const -> bool { return x == rhs.x && y == rhs.y; diff --git a/lib/opengloves/senseshift/opengloves/autoconfig.hpp b/lib/opengloves/senseshift/opengloves/autoconfig.hpp index 788a4fcc..7828bdb1 100644 --- a/lib/opengloves/senseshift/opengloves/autoconfig.hpp +++ b/lib/opengloves/senseshift/opengloves/autoconfig.hpp @@ -453,11 +453,14 @@ auto createTransport() -> ITransport* #ifdef BTSERIAL_NAME name = BTSERIAL_NAME; #else - char suffix[4]; - snprintf(suffix, 4, "%04X", (uint16_t) (ESP.getEfuseMac() >> 32)); - name = BTSERIAL_PREFIX + std::string(suffix); - - log_i("Generated Bluetooth name: %s", name.c_str()); + char suffix[5]; + int n = snprintf(suffix, sizeof(suffix), "%04X", (uint16_t) (ESP.getEfuseMac() >> 32)); + if (n < 0 || n >= sizeof(suffix)) { // also check for potential overflow + log_e("Failed to generate Bluetooth name"); + } else { + suffix[sizeof(suffix) - 1] = '\0'; // ensure null-termination + name = BTSERIAL_PREFIX + std::string(suffix, 4); + } #endif #if OPENGLOVES_COMMUNICATION == OPENGLOVES_COMM_BTSERIAL // Bluetooth Classic diff --git a/test/test_battery/main.cpp b/test/test_battery/main.cpp index f8950acf..1946738a 100644 --- a/test/test_battery/main.cpp +++ b/test/test_battery/main.cpp @@ -57,7 +57,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_bhaptics_encoding/main.cpp b/test/test_bhaptics_encoding/main.cpp index d3b4533d..60945ca5 100644 --- a/test/test_bhaptics_encoding/main.cpp +++ b/test/test_bhaptics_encoding/main.cpp @@ -292,7 +292,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_body_gestures/main.cpp b/test/test_body_gestures/main.cpp index bbae8332..6313f21b 100644 --- a/test/test_body_gestures/main.cpp +++ b/test/test_body_gestures/main.cpp @@ -111,7 +111,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_core_helpers/main.cpp b/test/test_core_helpers/main.cpp index 5d529448..ae5e7115 100644 --- a/test/test_core_helpers/main.cpp +++ b/test/test_core_helpers/main.cpp @@ -133,7 +133,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_haptics_body/main.cpp b/test/test_haptics_body/main.cpp index 5554db13..713cdd07 100644 --- a/test/test_haptics_body/main.cpp +++ b/test/test_haptics_body/main.cpp @@ -106,7 +106,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_haptics_plane/main.cpp b/test/test_haptics_plane/main.cpp index ab0af8ff..f049b8b1 100644 --- a/test/test_haptics_plane/main.cpp +++ b/test/test_haptics_plane/main.cpp @@ -237,7 +237,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_io_calibration/main.cpp b/test/test_io_calibration/main.cpp index 9f8e1ba7..011582d4 100644 --- a/test/test_io_calibration/main.cpp +++ b/test/test_io_calibration/main.cpp @@ -146,7 +146,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_io_filter/main.cpp b/test/test_io_filter/main.cpp index 94ad4ce2..5ef8cf10 100644 --- a/test/test_io_filter/main.cpp +++ b/test/test_io_filter/main.cpp @@ -206,7 +206,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_io_sensor/main.cpp b/test/test_io_sensor/main.cpp index 910d8073..1fd099d0 100644 --- a/test/test_io_sensor/main.cpp +++ b/test/test_io_sensor/main.cpp @@ -94,7 +94,7 @@ class DummyCalibrator : public ::SenseShift::Input::Calibration::ICalibratorcalibrated = input; } - float calibrate(float input) const override + float calibrate(float) const override { return calibrated; } @@ -264,7 +264,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } diff --git a/test/test_math_point2/main.cpp b/test/test_math_point2/main.cpp index f021530a..a3d9fa39 100644 --- a/test/test_math_point2/main.cpp +++ b/test/test_math_point2/main.cpp @@ -79,7 +79,7 @@ void loop(void) #else -int main(int argc, char** argv) +int main() { return process(); } From a76672d634875060bf26cfa3f29e2cb4f570dbc2 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 9 Aug 2024 14:29:32 +0400 Subject: [PATCH 66/67] ci(GitHub): run `pio check` --- .cppcheck-suppressions | 3 +++ .github/workflows/lint.yml | 14 ++++++++++++++ platformio.ini | 5 +++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 .cppcheck-suppressions diff --git a/.cppcheck-suppressions b/.cppcheck-suppressions new file mode 100644 index 00000000..b864e7cf --- /dev/null +++ b/.cppcheck-suppressions @@ -0,0 +1,3 @@ +*:.pio/* +*:*/libdeps/* +*:*/generated/* diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index b97595e4..626b9383 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -39,3 +39,17 @@ jobs: with: clang-format-version: '16' check-path: ${{ matrix.path }} + + pio-check-cppcheck: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup PlatformIO + uses: ./.github/actions/setup-platformio + + - name: PlatformIO check + shell: bash + run: | + pio check --skip-packages --fail-on-defect=medium --fail-on-defect=high diff --git a/platformio.ini b/platformio.ini index c324e0e8..7b4a9e9c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -default_envs = bhaptics_tactsuit_x40 +default_envs = bhaptics_tactsuit_x40, opengloves_lucidgloves_proto4 description = Open Source Haptic-feedback device firmware @@ -46,10 +46,11 @@ lib_deps = https://github.com/senseshift/i2cdevlib-contrib.git#8db7eab29dd01385928c6a99938ed0a953a5acf3 etlcpp/Embedded Template Library@^20.38.11 -check_tool = clangtidy +check_tool = cppcheck check_skip_packages = yes check_flags = clangtidy: --config-file=./.clang-tidy --fix + cppcheck: --enable=all --std=c++17 --suppressions-list=.cppcheck-suppressions --inline-suppr --suppress=missingIncludeSystem --inconclusive [base:arduino] framework = arduino From f5490353be410d86ff60bc665d61e35153680828 Mon Sep 17 00:00:00 2001 From: Leonid Meleshin Date: Fri, 9 Aug 2024 14:53:06 +0400 Subject: [PATCH 67/67] fix: resolve `cppcheck` warnings --- .cppcheck-suppressions | 4 ++ firmware/senseshift.cpp | 5 -- include/senseshift.h | 53 ++++++++++++++++++++-- lib/battery/senseshift/battery/battery.hpp | 3 +- lib/core/senseshift/core/helpers.hpp | 6 +-- lib/core/senseshift/events.hpp | 2 +- lib/io/senseshift/input/calibration.hpp | 2 +- lib/io/senseshift/input/filter.hpp | 9 ++-- lib/io/senseshift/input/sensor.hpp | 13 ++---- platformio.ini | 2 +- 10 files changed, 72 insertions(+), 27 deletions(-) diff --git a/.cppcheck-suppressions b/.cppcheck-suppressions index b864e7cf..49fdbb85 100644 --- a/.cppcheck-suppressions +++ b/.cppcheck-suppressions @@ -1,3 +1,7 @@ +// no real downside on these +unusedFunction +unusedPrivateFunction + *:.pio/* *:*/libdeps/* *:*/generated/* diff --git a/firmware/senseshift.cpp b/firmware/senseshift.cpp index 3599b0fc..45a144c7 100644 --- a/firmware/senseshift.cpp +++ b/firmware/senseshift.cpp @@ -11,11 +11,6 @@ namespace SenseShift { static const char* const TAG = "application"; -Application::Application() -{ - this->vibro_body_ = new Body::Haptics::FloatBody(); -} - void Application::postEvent(const IEvent* event) { LOG_I(TAG, "Event dispatched at %u: %s (%p)", millis(), event->eventName.c_str(), event); diff --git a/include/senseshift.h b/include/senseshift.h index c1c8073e..2660325f 100644 --- a/include/senseshift.h +++ b/include/senseshift.h @@ -11,7 +11,55 @@ namespace SenseShift { class Application final : public IEventDispatcher { public: - Application(); + Application() + { + this->vibro_body_ = new Body::Haptics::FloatBody(); + } + + ~Application() + { + delete this->vibro_body_; + } + + Application(const Application& other) + { + this->vibro_body_ = new Body::Haptics::FloatBody(*other.vibro_body_); + this->event_listeners_ = other.event_listeners_; + } + + Application(Application&& other) noexcept : + vibro_body_(other.vibro_body_), event_listeners_(std::move(other.event_listeners_)) + { + other.vibro_body_ = nullptr; + } + + Application& operator=(const Application& other) + { + if (this == &other) + return *this; // handle self-assignment + + delete this->vibro_body_; + + this->vibro_body_ = new Body::Haptics::FloatBody(*other.vibro_body_); + this->event_listeners_ = other.event_listeners_; + + return *this; + } + + Application& operator=(Application&& other) noexcept + { + if (this == &other) + return *this; // handle self-assignment + + delete this->vibro_body_; + + this->vibro_body_ = other.vibro_body_; + event_listeners_ = std::move(other.event_listeners_); + + other.vibro_body_ = nullptr; + + return *this; + } auto getVibroBody() const -> Body::Haptics::FloatBody* { @@ -22,8 +70,7 @@ class Application final : public IEventDispatcher { void addEventListener(const IEventListener* listener) override; private: - std::vector event_listeners_{}; Body::Haptics::FloatBody* vibro_body_; - Battery::Input::IBatterySensor* battery_ = nullptr; + std::vector event_listeners_{}; }; } // namespace SenseShift diff --git a/lib/battery/senseshift/battery/battery.hpp b/lib/battery/senseshift/battery/battery.hpp index 07061f10..4e96a45e 100644 --- a/lib/battery/senseshift/battery/battery.hpp +++ b/lib/battery/senseshift/battery/battery.hpp @@ -30,7 +30,8 @@ struct BatteryState { class BatteryLevelEvent : public IEvent { public: const BatteryState& state; - BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state) + + explicit BatteryLevelEvent(const BatteryState& state) : IEvent(OH_EVENT_BATTERY_LEVEL), state(state) { } }; diff --git a/lib/core/senseshift/core/helpers.hpp b/lib/core/senseshift/core/helpers.hpp index f86df634..1209d6f6 100644 --- a/lib/core/senseshift/core/helpers.hpp +++ b/lib/core/senseshift/core/helpers.hpp @@ -118,9 +118,9 @@ class CallbackManager { } /// Call all callbacks in this manager. - void call(Ts... args) + void call(Ts... args) const { - for (auto& callback : this->callbacks_) { + for (const auto& callback : this->callbacks_) { callback(args...); } } @@ -131,7 +131,7 @@ class CallbackManager { } /// Call all callbacks in this manager. - void operator()(Ts... args) + void operator()(Ts... args) const { call(args...); } diff --git a/lib/core/senseshift/events.hpp b/lib/core/senseshift/events.hpp index 20134a91..efc9705d 100644 --- a/lib/core/senseshift/events.hpp +++ b/lib/core/senseshift/events.hpp @@ -18,7 +18,7 @@ enum Event { struct IEvent { const std::string eventName; - IEvent(const std::string eventName) : eventName(eventName){}; + explicit IEvent(const std::string& eventName) : eventName(eventName){}; }; class IEventListener { diff --git a/lib/io/senseshift/input/calibration.hpp b/lib/io/senseshift/input/calibration.hpp index a2239c53..d2e1edf9 100644 --- a/lib/io/senseshift/input/calibration.hpp +++ b/lib/io/senseshift/input/calibration.hpp @@ -65,7 +65,7 @@ class Calibrated { } private: - CalibratorType* calibrator_; + CalibratorType* calibrator_ = nullptr; bool is_calibrating_ = false; }; diff --git a/lib/io/senseshift/input/filter.hpp b/lib/io/senseshift/input/filter.hpp index 906c3524..847d8506 100644 --- a/lib/io/senseshift/input/filter.hpp +++ b/lib/io/senseshift/input/filter.hpp @@ -50,7 +50,7 @@ class Filtered { /// \param filter The filter to add. /// /// \see addFilters for adding multiple filters. - void addFilter(FilterType filter) + void addFilter(const FilterType& filter) { this->filters_.push_back(filter); } @@ -68,7 +68,7 @@ class Filtered { /// \endcode /// /// todo(leon0399): use SFINAE - void addFilters(std::vector filters) + void addFilters(const std::vector& filters) { this->filters_.insert(this->filters_.end(), filters.begin(), filters.end()); } @@ -84,7 +84,7 @@ class Filtered { /// new CenterDeadzoneFilter(0.1f), /// }); /// \endcode - void setFilters(std::vector filters) + void setFilters(const std::vector& filters) { this->filters_ = filters; } @@ -223,8 +223,9 @@ class SlidingWindowMovingAverageFilter : public IFilter { [[nodiscard]] auto getAverage() const -> Tp { - Tp sum = 0; + Tp sum = Tp(); for (auto value : this->queue_) { + // cppcheck-suppress useStlAlgorithm; We may run in no-stl environment sum += value; } return sum / this->queue_.size(); diff --git a/lib/io/senseshift/input/sensor.hpp b/lib/io/senseshift/input/sensor.hpp index 1731db82..cf1080a4 100644 --- a/lib/io/senseshift/input/sensor.hpp +++ b/lib/io/senseshift/input/sensor.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -43,12 +44,8 @@ class Sensor : public ISensor { using CallbackManagerType = CallbackManager; using CallbackType = typename CallbackManagerType::CallbackType; - explicit Sensor() = default; - - template, int> = 0> - explicit Sensor(float value = 0.0f) : raw_value_(value) + explicit Sensor(Tp value = Tp()) : raw_value_(value), value_(this->applyFilters(value)) { - this->value_ = this->applyFilters(value); } void addValueCallback(CallbackType&& callback) @@ -92,7 +89,7 @@ class Sensor : public ISensor { } /// Get the current raw sensor .raw_value_. - auto getRawValue() -> ValueType + auto getRawValue() const -> ValueType { return this->raw_value_; } @@ -126,9 +123,9 @@ class Sensor : public ISensor { ValueType value_; /// Storage for raw state callbacks. - CallbackManagerType raw_callbacks_; + CallbackManagerType raw_callbacks_ = CallbackManagerType(); /// Storage for filtered state callbacks. - CallbackManagerType callbacks_; + CallbackManagerType callbacks_ = CallbackManagerType(); }; using FloatSensor = Sensor; diff --git a/platformio.ini b/platformio.ini index 7b4a9e9c..70cea51c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -50,7 +50,7 @@ check_tool = cppcheck check_skip_packages = yes check_flags = clangtidy: --config-file=./.clang-tidy --fix - cppcheck: --enable=all --std=c++17 --suppressions-list=.cppcheck-suppressions --inline-suppr --suppress=missingIncludeSystem --inconclusive + cppcheck: --enable=all --std=c++17 --suppress=missingIncludeSystem --suppress=unmatchedSuppression --suppressions-list=.cppcheck-suppressions --inline-suppr --inconclusive [base:arduino] framework = arduino